Пример #1
0
/*********************************************************************************************************
** 函数名称: API_TimeSleepEx
** 功能描述: 线程睡眠函数 (精度为 TICK HZ)
** 输 入  : ulTick            睡眠的时间
**           bSigRet           是否允许信号唤醒
** 输 出  : ERROR_NONE or EINTR
** 全局变量: 
** 调用模块: 
                                           API 函数
                                           
                                       (不得在中断中调用)
*********************************************************************************************************/
LW_API
ULONG  API_TimeSleepEx (ULONG  ulTick, BOOL  bSigRet)
{
             INTREG                iregInterLevel;
             
             PLW_CLASS_TCB         ptcbCur;
	REGISTER PLW_CLASS_PCB         ppcb;
	REGISTER ULONG                 ulKernelTime;
    
    if (LW_CPU_GET_CUR_NESTING()) {                                     /*  不能在中断中调用            */
        _ErrorHandle(ERROR_KERNEL_IN_ISR);
        return  (ERROR_KERNEL_IN_ISR);
    }
    
    LW_TCB_GET_CUR_SAFE(ptcbCur);                                       /*  当前任务控制块              */
    
    MONITOR_EVT_LONG2(MONITOR_EVENT_ID_THREAD, MONITOR_EVENT_THREAD_SLEEP, 
                      ptcbCur->TCB_ulId, ulTick, LW_NULL);
    
__wait_again:
    if (!ulTick) {                                                      /*  不进行延迟                  */
        return  (ERROR_NONE);
    }

    iregInterLevel = __KERNEL_ENTER_IRQ();                              /*  进入内核                    */

    ppcb = _GetPcb(ptcbCur);
    __DEL_FROM_READY_RING(ptcbCur, ppcb);                               /*  从就绪表中删除              */
    
    ptcbCur->TCB_ulDelay = ulTick;
    __ADD_TO_WAKEUP_LINE(ptcbCur);                                      /*  加入等待扫描链              */
    
    __KERNEL_TIME_GET_NO_SPINLOCK(ulKernelTime, ULONG);                 /*  记录系统时间                */
    
    if (__KERNEL_EXIT_IRQ(iregInterLevel)) {                            /*  被信号激活                  */
        if (bSigRet) {
            _ErrorHandle(EINTR);
            return  (EINTR);
        }
        ulTick = _sigTimeoutRecalc(ulKernelTime, ulTick);               /*  重新计算等待时间            */
        goto __wait_again;                                              /*  继续等待                    */
    }
    
    return  (ERROR_NONE);
}
Пример #2
0
/*********************************************************************************************************
** 函数名称: nanosleep 
** 功能描述: 使调用此函数的线程睡眠一个指定的时间, 睡眠过程中可能被信号唤醒. (POSIX)
** 输 入  : rqtp         睡眠的时间
**           rmtp         保存剩余时间的结构.
** 输 出  : ERROR_NONE  or  PX_ERROR

             error == EINTR    表示被信号激活.
** 全局变量: 
** 调用模块: 
                                           API 函数
                                           
                                       (不得在中断中调用)
*********************************************************************************************************/
LW_API  
INT  nanosleep (const struct timespec  *rqtp, struct timespec  *rmtp)
{
             INTREG             iregInterLevel;
             
             PLW_CLASS_TCB      ptcbCur;
    REGISTER PLW_CLASS_PCB      ppcb;
	REGISTER ULONG              ulKernelTime;
	REGISTER INT                iRetVal;
	         INT                iSchedRet;
	
	REGISTER ULONG              ulError;
             ULONG              ulTick;
             
             struct timespec    tvStart;
             struct timespec    tvTemp;
    
    if ((!rqtp)              ||
        (rqtp->tv_nsec <  0) ||
        (rqtp->tv_nsec >= __TIMEVAL_NSEC_MAX)) {                        /*  时间格式错误                */
        _ErrorHandle(EINVAL);
        return  (PX_ERROR);
    }
    
    ulTick = __timespecToTick((struct timespec *)rqtp);
    if (!ulTick) {                                                      /*  不到一个 tick               */
        __timePassSpec(rqtp);                                           /*  平静度过                    */
        if (rmtp) {
            rmtp->tv_sec  = 0;                                          /*  不存在时间差别              */
            rmtp->tv_nsec = 0;
        }
        return  (ERROR_NONE);
    }
    
    __timeGetHighResolution(&tvStart);                                  /*  记录开始的时间              */
    
    __THREAD_CANCEL_POINT();                                            /*  测试取消点                  */
    
    LW_TCB_GET_CUR_SAFE(ptcbCur);                                       /*  当前任务控制块              */
    
    MONITOR_EVT_LONG2(MONITOR_EVENT_ID_THREAD, MONITOR_EVENT_THREAD_SLEEP, 
                      ptcbCur->TCB_ulId, ulTick, LW_NULL);
    
__wait_again:
    iregInterLevel = __KERNEL_ENTER_IRQ();                              /*  进入内核                    */
    
    ppcb = _GetPcb(ptcbCur);
    __DEL_FROM_READY_RING(ptcbCur, ppcb);                               /*  从就绪表中删除              */
    
    ptcbCur->TCB_ulDelay = ulTick;
    __ADD_TO_WAKEUP_LINE(ptcbCur);                                      /*  加入等待扫描链              */
    
    __KERNEL_TIME_GET_NO_SPINLOCK(ulKernelTime, ULONG);                 /*  记录系统时间                */
    
    iSchedRet = __KERNEL_EXIT_IRQ(iregInterLevel);                      /*  调度器解锁                  */
    if (iSchedRet == LW_SIGNAL_EINTR) {
        iRetVal = PX_ERROR;                                             /*  被信号激活                  */
        ulError = EINTR;
    
    } else {
        if (iSchedRet == LW_SIGNAL_RESTART) {                           /*  信号要求重启等待            */
            ulTick = _sigTimeoutRecalc(ulKernelTime, ulTick);           /*  重新计算等待时间            */
            if (ulTick != 0ul) {
                goto    __wait_again;                                   /*  重新等待剩余的 tick         */
            }
        }
        iRetVal = ERROR_NONE;                                           /*  自然唤醒                    */
        ulError = ERROR_NONE;
    }
    
    if (ulError ==  ERROR_NONE) {                                       /*  tick 已经延迟结束           */
        __timeGetHighResolution(&tvTemp);
        __timespecSub(&tvTemp, &tvStart);                               /*  计算已经延迟的时间          */
        if (__timespecLeftTime(&tvTemp, rqtp)) {                        /*  还有剩余时间需要延迟        */
            struct timespec  tvNeed = *rqtp;
            __timespecSub(&tvNeed, &tvTemp);
            __timePassSpec(&tvNeed);                                    /*  平静度过                    */
        }
        if (rmtp) {
            rmtp->tv_sec  = 0;                                          /*  不存在时间差别              */
            rmtp->tv_nsec = 0;
        }
    } else {                                                            /*  信号唤醒                    */
        if (rmtp) {
            *rmtp = *rqtp;
            __timeGetHighResolution(&tvTemp);
            __timespecSub(&tvTemp, &tvStart);                           /*  计算已经延迟的时间          */
            if (__timespecLeftTime(&tvTemp, rmtp)) {                    /*  没有延迟够                  */
                __timespecSub(rmtp, &tvTemp);                           /*  计算没有延迟够的时间        */
            }
        }
    }
             
    _ErrorHandle(ulError);                                              /*  设置 errno 值               */
    return  (iRetVal);
}
Пример #3
0
/*********************************************************************************************************
** 函数名称: pthread_rwlock_timedrdlock
** 功能描述: 等待一个读写锁可读 (带有超时的阻塞).
** 输 入  : prwlock        句柄
**           abs_timeout    绝对超时时间
** 输 出  : ERROR CODE
** 全局变量: 
** 调用模块: 
                                           API 函数
*********************************************************************************************************/
LW_API 
int  pthread_rwlock_timedrdlock (pthread_rwlock_t *prwlock,
                                 const struct timespec *abs_timeout)
{
    ULONG               ulTimeout;
    ULONG               ulOrgKernelTime;
    ULONG               ulError = ERROR_NONE;
    struct timespec     tvNow;
    struct timespec     tvWait  = {0, 0};
    
    if (prwlock == LW_NULL) {
        errno = EINVAL;
        return  (EINVAL);
    }
    
    if ((abs_timeout == LW_NULL)    || 
        (abs_timeout->tv_nsec <  0) ||
        (abs_timeout->tv_nsec >= __TIMEVAL_NSEC_MAX)) {
        errno = EINVAL;
        return  (EINVAL);
    }
    
    __pthread_rwlock_init_invisible(prwlock);
    
    lib_clock_gettime(CLOCK_REALTIME, &tvNow);                          /*  获得当前系统时间            */
    if (__timespecLeftTime(&tvNow, abs_timeout)) {
        tvWait = *abs_timeout;
        __timespecSub(&tvWait, &tvNow);                                 /*  计算与当前等待的时间间隔    */
    }
    /*
     *  注意: 当 tvWait 超过ulong tick范围时, 将自然产生溢出, 导致超时时间不准确.
     */
    ulTimeout = __timespecToTick(&tvWait);                              /*  变换为 tick                 */
    
    __PX_RWLOCK_LOCK(prwlock);                                          /*  锁定读写锁                  */
    prwlock->PRWLOCK_uiRPendCounter++;                                  /*  等待读的数量++              */
    do {
        __KERNEL_TIME_GET(ulOrgKernelTime, ULONG);                      /*  记录系统时间                */
        
        if ((prwlock->PRWLOCK_uiStatus == __PX_RWLOCK_STATUS_READING) &&
            (prwlock->PRWLOCK_uiWPendCounter == 0)) {
            /*
             *  如果写入器未持有读锁, 并且没有任何写入器基于改锁阻塞. 则调用线程立即获取读锁.
             */
            prwlock->PRWLOCK_uiOpCounter++;                             /*  正在操作数量++              */
            prwlock->PRWLOCK_uiRPendCounter--;                          /*  退出等待模式                */
            break;                                                      /*  直接跳出                    */
        
        } else {
            /*
             *  如果写入器正在操作或者, 或者有多个写入器正在等待该锁, 将阻塞.
             */
            __PX_RWLOCK_UNLOCK(prwlock);                                /*  解锁读写锁                  */
            ulError = API_SemaphoreCPend(prwlock->PRWLOCK_ulRSemaphore,
                                         ulTimeout);                    /*  等待读写锁状态变换          */
            __PX_RWLOCK_LOCK(prwlock);                                  /*  锁定读写锁                  */
            if (ulError) {
                break;                                                  /*  直接跳出                    */
            }
        }
        
        ulTimeout = _sigTimeoutRecalc(ulOrgKernelTime, ulTimeout);      /*  重新计算等待时间            */
    } while (1);
    __PX_RWLOCK_UNLOCK(prwlock);                                        /*  解锁读写锁                  */
    
    if (ulError == ERROR_THREAD_WAIT_TIMEOUT) {
        ulError = ETIMEDOUT;
        errno   = ETIMEDOUT;
    }
    
    return  ((INT)ulError);
}
Пример #4
0
/*********************************************************************************************************
** 函数名称: pthread_rwlock_wrlock
** 功能描述: 等待一个读写锁可写 (带有超时的阻塞).
** 输 入  : prwlock        句柄
**           abs_timeout    绝对超时时间
** 输 出  : ERROR CODE
** 全局变量: 
** 调用模块: 
                                           API 函数
*********************************************************************************************************/
LW_API 
int  pthread_rwlock_timedwrlock (pthread_rwlock_t *prwlock,
                                 const struct timespec *abs_timeout)
{
    ULONG               ulTimeout;
    ULONG               ulOrgKernelTime;
    ULONG               ulError = ERROR_NONE;
    struct timespec     tvNow;
    struct timespec     tvWait  = {0, 0};
    
    if (prwlock == LW_NULL) {
        errno = EINVAL;
        return  (EINVAL);
    }
    
    if ((abs_timeout == LW_NULL)    || 
        (abs_timeout->tv_nsec <  0) ||
        (abs_timeout->tv_nsec >= __TIMEVAL_NSEC_MAX)) {
        errno = EINVAL;
        return  (EINVAL);
    }
    
    __pthread_rwlock_init_invisible(prwlock);
    
    lib_clock_gettime(CLOCK_REALTIME, &tvNow);                          /*  获得当前系统时间            */
    if (__timespecLeftTime(&tvNow, abs_timeout)) {
        tvWait = *abs_timeout;
        __timespecSub(&tvWait, &tvNow);                                 /*  计算与当前等待的时间间隔    */
    }
    /*
     *  注意: 当 tvWait 超过ulong tick范围时, 将自然产生溢出, 导致超时时间不准确.
     */
    ulTimeout = __timespecToTick(&tvWait);                              /*  变换为 tick                 */
    
    __PX_RWLOCK_LOCK(prwlock);                                          /*  锁定读写锁                  */
    prwlock->PRWLOCK_uiWPendCounter++;                                  /*  等待写的数量++              */
    do {
        __KERNEL_TIME_GET(ulOrgKernelTime, ULONG);                      /*  记录系统时间                */
        
        if (prwlock->PRWLOCK_uiOpCounter == 0) {
            /*
             *  没有正在操作的线程
             */
            prwlock->PRWLOCK_uiOpCounter++;                             /*  正在操作的线程++            */
            prwlock->PRWLOCK_uiWPendCounter--;                          /*  退出等待状态                */
            prwlock->PRWLOCK_uiStatus = __PX_RWLOCK_STATUS_WRITING;     /*  转换为写模式                */
            break;
            
        } else {
            /*
             *  如果有等待写入的线程或者存在正在读取的线程.
             */
            __PX_RWLOCK_UNLOCK(prwlock);                                /*  解锁读写锁                  */
            ulError = API_SemaphoreCPend(prwlock->PRWLOCK_ulWSemaphore,
                                         ulTimeout);                    /*  等待读写锁状态变换          */
            __PX_RWLOCK_LOCK(prwlock);                                  /*  锁定读写锁                  */
            if (ulError) {
                break;                                                  /*  直接跳出                    */
            }
        }
        
        ulTimeout = _sigTimeoutRecalc(ulOrgKernelTime, ulTimeout);      /*  重新计算等待时间            */
    } while (1);
    
    if (ulError == ERROR_NONE) {
        prwlock->PRWLOCK_ulOwner = API_ThreadIdSelf();                  /*  读写锁拥有者                */
    }
    __PX_RWLOCK_UNLOCK(prwlock);                                        /*  解锁读写锁                  */
    
    if (ulError == ERROR_THREAD_WAIT_TIMEOUT) {
        ulError = ETIMEDOUT;
        errno   = ETIMEDOUT;
    }
    
    return  ((INT)ulError);
}
Пример #5
0
LW_API
ULONG  API_MsgQueueReceive (LW_OBJECT_HANDLE    ulId,
                            PVOID               pvMsgBuffer,
                            size_t              stMaxByteSize,
                            size_t             *pstMsgLen,
                            ULONG               ulTimeout)

{
    INTREG                iregInterLevel;

    PLW_CLASS_TCB         ptcbCur;
    REGISTER UINT16                usIndex;
    REGISTER PLW_CLASS_EVENT       pevent;
    REGISTER PLW_CLASS_MSGQUEUE    pmsgqueue;
    REGISTER UINT8                 ucPriorityIndex;
    REGISTER PLW_LIST_RING        *ppringList;
    ULONG                 ulTimeSave;                          /*  系统事件记录                */
    INT                   iSchedRet;

    ULONG                 ulEventOption;                       /*  事件创建选项                */
    size_t                stMsgLenTemp;                        /*  临时记录变量                */

    usIndex = _ObjectGetIndex(ulId);

    if (LW_CPU_GET_CUR_NESTING()) {                                     /*  不能在中断中调用            */
        _DebugHandle(__ERRORMESSAGE_LEVEL, "called from ISR.\r\n");
        _ErrorHandle(ERROR_KERNEL_IN_ISR);
        return  (ERROR_KERNEL_IN_ISR);
    }

    LW_TCB_GET_CUR_SAFE(ptcbCur);                                       /*  当前任务控制块              */

    if (pstMsgLen == LW_NULL) {
        pstMsgLen =  &stMsgLenTemp;                                     /*  临时变量记录消息长短        */
    }

__wait_again:
#if LW_CFG_ARG_CHK_EN > 0
    if (!pvMsgBuffer || !stMaxByteSize) {
        _DebugHandle(__ERRORMESSAGE_LEVEL, "pvMsgBuffer invalidate.\r\n");
        _ErrorHandle(ERROR_MSGQUEUE_MSG_NULL);
        return  (ERROR_MSGQUEUE_MSG_NULL);
    }
    if (!_ObjectClassOK(ulId, _OBJECT_MSGQUEUE)) {
        _DebugHandle(__ERRORMESSAGE_LEVEL, "msgqueue handle invalidate.\r\n");
        _ErrorHandle(ERROR_KERNEL_HANDLE_NULL);
        return  (ERROR_KERNEL_HANDLE_NULL);
    }
    if (_Event_Index_Invalid(usIndex)) {
        _DebugHandle(__ERRORMESSAGE_LEVEL, "msgqueue handle invalidate.\r\n");
        _ErrorHandle(ERROR_KERNEL_HANDLE_NULL);
        return  (ERROR_KERNEL_HANDLE_NULL);
    }
#endif
    pevent = &_K_eventBuffer[usIndex];

    iregInterLevel = __KERNEL_ENTER_IRQ();                              /*  进入内核                    */
    if (_Event_Type_Invalid(usIndex, LW_TYPE_EVENT_MSGQUEUE)) {
        __KERNEL_EXIT_IRQ(iregInterLevel);                              /*  退出内核                    */
        _DebugHandle(__ERRORMESSAGE_LEVEL, "msgqueue handle invalidate.\r\n");
        _ErrorHandle(ERROR_MSGQUEUE_TYPE);
        return  (ERROR_MSGQUEUE_TYPE);
    }

    pmsgqueue = (PLW_CLASS_MSGQUEUE)pevent->EVENT_pvPtr;

    ptcbCur->TCB_ulRecvOption = LW_OPTION_NOERROR;                      /*  接收大消息自动截断          */

    if (pevent->EVENT_ulCounter) {                                      /*  事件有效                    */
        pevent->EVENT_ulCounter--;
        _MsgQueueGetMsg(pmsgqueue,
                        pvMsgBuffer,
                        stMaxByteSize,
                        pstMsgLen);                                     /*  获得消息                    */
        __KERNEL_EXIT_IRQ(iregInterLevel);                              /*  退出内核                    */
        return  (ERROR_NONE);
    }

    if (ulTimeout == LW_OPTION_NOT_WAIT) {                              /*  不等待                      */
        __KERNEL_EXIT_IRQ(iregInterLevel);                              /*  退出内核                    */
        _ErrorHandle(ERROR_THREAD_WAIT_TIMEOUT);                        /*  超时                        */
        return  (ERROR_THREAD_WAIT_TIMEOUT);
    }

    ptcbCur->TCB_pstMsgByteSize    = pstMsgLen;
    ptcbCur->TCB_stMaxByteSize     = stMaxByteSize;
    ptcbCur->TCB_pvMsgQueueMessage = pvMsgBuffer;                       /*  记录信息                    */

    ptcbCur->TCB_usStatus      |= LW_THREAD_STATUS_MSGQUEUE;            /*  写状态位,开始等待          */
    ptcbCur->TCB_ucWaitTimeout  = LW_WAIT_TIME_CLEAR;                   /*  清空等待时间                */

    if (ulTimeout == LW_OPTION_WAIT_INFINITE) {                         /*  是否是无穷等待              */
        ptcbCur->TCB_ulDelay = 0ul;
    } else {
        ptcbCur->TCB_ulDelay = ulTimeout;                               /*  设置超时时间                */
    }
    __KERNEL_TIME_GET_NO_SPINLOCK(ulTimeSave, ULONG);                   /*  记录系统时间                */

    if (pevent->EVENT_ulOption & LW_OPTION_WAIT_PRIORITY) {
        _EVENT_INDEX_Q_PRIORITY(ptcbCur->TCB_ucPriority, ucPriorityIndex);
        _EVENT_PRIORITY_Q_PTR(ppringList, ucPriorityIndex);
        ptcbCur->TCB_ppringPriorityQueue = ppringList;                  /*  记录等待队列位置            */
        _EventWaitPriority(pevent, ppringList);                         /*  加入优先级等待表            */

    } else {                                                            /*  按 FIFO 等待                */
        _EVENT_FIFO_Q_PTR(ppringList);                                  /*  确定 FIFO 队列的位置        */
        _EventWaitFifo(pevent, ppringList);                             /*  加入 FIFO 等待表            */
    }

    KN_INT_ENABLE(iregInterLevel);                                      /*  使能中断                    */

    ulEventOption = pevent->EVENT_ulOption;

    MONITOR_EVT_LONG2(MONITOR_EVENT_ID_MSGQ, MONITOR_EVENT_MSGQ_PEND,
                      ulId, ulTimeout, LW_NULL);

    iSchedRet = __KERNEL_EXIT();                                        /*  调度器解锁                  */
    if (iSchedRet == LW_SIGNAL_EINTR) {
        if (ulEventOption & LW_OPTION_SIGNAL_INTER) {
            _ErrorHandle(EINTR);
            return  (EINTR);
        }
        ulTimeout = _sigTimeoutRecalc(ulTimeSave, ulTimeout);           /*  重新计算超时时间            */
        goto    __wait_again;

    } else if (iSchedRet == LW_SIGNAL_RESTART) {
        ulTimeout = _sigTimeoutRecalc(ulTimeSave, ulTimeout);           /*  重新计算超时时间            */
        goto    __wait_again;
    }

    if (ptcbCur->TCB_ucWaitTimeout == LW_WAIT_TIME_OUT) {
        iregInterLevel = __KERNEL_ENTER_IRQ();                          /*  进入内核                    */
        if (ptcbCur->TCB_ucWaitTimeout == LW_WAIT_TIME_CLEAR) {         /*  是否在上面瞬间被激活        */
            __KERNEL_EXIT_IRQ(iregInterLevel);                          /*  退出内核                    */
            return  (ERROR_NONE);
        }

        if (pevent->EVENT_ulOption & LW_OPTION_WAIT_PRIORITY) {
            _EventTimeoutPriority(pevent, ppringList);                  /*  等待超时恢复                */
        } else {
            _EventTimeoutFifo(pevent, ppringList);                      /*  等待超时恢复                */
        }

        __KERNEL_EXIT_IRQ(iregInterLevel);                              /*  退出内核                    */
        _ErrorHandle(ERROR_THREAD_WAIT_TIMEOUT);                        /*  超时                        */
        return  (ERROR_THREAD_WAIT_TIMEOUT);

    } else {
        if (ptcbCur->TCB_ucIsEventDelete == LW_EVENT_EXIST) {           /*  事件是否存在                */
            return  (ERROR_NONE);

        } else {
            _ErrorHandle(ERROR_MSGQUEUE_WAS_DELETED);                   /*  已经被删除                  */
            return  (ERROR_MSGQUEUE_WAS_DELETED);
        }
    }
}