Esempio n. 1
0
/*********************************************************************************************************
** 函数名称: _ThreadStatusChangeCur
** 功能描述: 改变当前线程状态 (内核状态且关闭中断状态被调用)
** 输 入  : ptcbCur       当前 CPU
** 输 出  : NONE
** 全局变量: 
** 调用模块: 
** 注  意  : 
*********************************************************************************************************/
VOID  _ThreadStatusChangeCur (PLW_CLASS_CPU    pcpuCur)
{
    PLW_CLASS_TCB  ptcbCur;
    PLW_CLASS_TCB  ptcb;
    PLW_CLASS_PCB  ppcb;

    ptcbCur = pcpuCur->CPU_ptcbTCBCur;                                  /*  当前线程                    */

    if (ptcbCur->TCB_plineStatusReqHeader) {                            /*  需要阻塞                    */
        if (__LW_THREAD_IS_READY(ptcbCur)) {
            ppcb = _GetPcb(ptcbCur);
            __DEL_FROM_READY_RING(ptcbCur, ppcb);                       /*  从就绪表中删除              */
        }
        
        do {
            ptcb = _LIST_ENTRY(ptcbCur->TCB_plineStatusReqHeader, LW_CLASS_TCB, TCB_lineStatusPend);
            
            switch (ptcb->TCB_uiStatusChangeReq) {
            
            case LW_TCB_REQ_SUSPEND:
                ptcbCur->TCB_ulSuspendNesting++;
                ptcbCur->TCB_usStatus |= LW_THREAD_STATUS_SUSPEND;
                break;
                
            case LW_TCB_REQ_STOP:
                ptcbCur->TCB_ulStopNesting++;
                ptcbCur->TCB_usStatus |= LW_THREAD_STATUS_STOP;
                break;
                
            case LW_TCB_REQ_WDEATH:
                ptcbCur->TCB_usStatus |= LW_THREAD_STATUS_WDEATH;
                break;
            }
            
            ptcb->TCB_ptcbWaitStatus    = LW_NULL;
            ptcb->TCB_uiStatusChangeReq = 0;                            /*  请求修改的状态成功          */
            
            _List_Line_Del(&ptcb->TCB_lineStatusPend, 
                           &ptcbCur->TCB_plineStatusReqHeader);
            
            if (!__LW_THREAD_IS_READY(ptcb)) {                          /*  如果没有就绪, 取消 WSTAT    */
                ptcb->TCB_usStatus &= ~LW_THREAD_STATUS_WSTAT;
                if (__LW_THREAD_IS_READY(ptcb)) {
                    ptcb->TCB_ucSchedActivate = LW_SCHED_ACT_INTERRUPT; /*  中断激活方式                */
                    ppcb = _GetPcb(ptcb);
                    __ADD_TO_READY_RING(ptcb, ppcb);
                }
            }
        } while (ptcbCur->TCB_plineStatusReqHeader);
    }
}
Esempio n. 2
0
/*********************************************************************************************************
** 函数名称: pause
** 功能描述: 等待一个信号的到来
** 输 入  : NONE
** 输 出  : ERROR
** 全局变量: 
** 调用模块: 
                                           API 函数
*********************************************************************************************************/
LW_API  
INT  pause (VOID)
{
             INTREG         iregInterLevel;
             PLW_CLASS_TCB  ptcbCur;
    REGISTER PLW_CLASS_PCB  ppcb;
    
    __THREAD_CANCEL_POINT();                                            /*  测试取消点                  */
    
    LW_TCB_GET_CUR_SAFE(ptcbCur);                                       /*  当前任务控制块              */

    MONITOR_EVT_LONG1(MONITOR_EVENT_ID_SIGNAL, MONITOR_EVENT_SIGNAL_PAUSE, 
                      ptcbCur->TCB_ulId, LW_NULL);
    
    iregInterLevel = __KERNEL_ENTER_IRQ();                              /*  进入内核                    */
    
    ptcbCur->TCB_usStatus |= LW_THREAD_STATUS_SIGNAL;                   /*  等待信号                    */
    ppcb = _GetPcb(ptcbCur);
    __DEL_FROM_READY_RING(ptcbCur, ppcb);                               /*  从就绪表中删除              */
    
    __KERNEL_EXIT_IRQ(iregInterLevel);                                  /*  退出内核                    */
    
    _ErrorHandle(EINTR);
    return  (PX_ERROR);
}
Esempio n. 3
0
/*********************************************************************************************************
** 函数名称: _ThreadUnwaitStatus
** 功能描述: 从等待目标线程状态设置链表中退出, 并激活其他任务等待我的状态改变.(进入内核并关中断状态被调用)
** 输 入  : ptcbCur       当前线程控制块
**           ptcbDest      目标线程控制块
**           uiStatusReq   请求改变的
** 输 出  : ERROR
** 全局变量: 
** 调用模块: 
** 注  意  : 这里只是退出链表, 并不操作就续表.
*********************************************************************************************************/
VOID  _ThreadUnwaitStatus (PLW_CLASS_TCB  ptcb)
{
    PLW_CLASS_TCB  ptcbDest = ptcb->TCB_ptcbWaitStatus;
    PLW_CLASS_TCB  ptcbWait;
    PLW_CLASS_PCB  ppcb;

    if (ptcbDest) {
        _List_Line_Del(&ptcb->TCB_lineStatusPend, 
                       &ptcbDest->TCB_plineStatusReqHeader);
                       
        ptcb->TCB_ptcbWaitStatus    = LW_NULL;
        ptcb->TCB_uiStatusChangeReq = 0;
    }
    
    while (ptcb->TCB_plineStatusReqHeader) {                            /*  有其他线程请求              */
        ptcbWait = _LIST_ENTRY(ptcb->TCB_plineStatusReqHeader, 
                               LW_CLASS_TCB, 
                               TCB_lineStatusPend);
        ptcbWait->TCB_ptcbWaitStatus = LW_NULL;
        
        _List_Line_Del(&ptcbWait->TCB_lineStatusPend, 
                       &ptcb->TCB_plineStatusReqHeader);
        
        if (!__LW_THREAD_IS_READY(ptcbWait)) {                          /*  如果没有就绪, 取消 WSTAT    */
            ptcbWait->TCB_usStatus &= ~LW_THREAD_STATUS_WSTAT;
            if (__LW_THREAD_IS_READY(ptcbWait)) {
                ptcbWait->TCB_ucSchedActivate = LW_SCHED_ACT_INTERRUPT; /*  中断激活方式                */
                ppcb = _GetPcb(ptcbWait);
                __ADD_TO_READY_RING(ptcbWait, ppcb);
            }
        }
    }
}
Esempio n. 4
0
/*********************************************************************************************************
** 函数名称: _EventSetThreadReady
** 功能描述: 激活等待事件集队列的线程 (进入内核并关中断后被调用)
** 输 入  : pesn              事件组控制块
**           ulEventsReady     新的事件标志
** 输 出  : 是否调度
** 全局变量: 
** 调用模块: 
*********************************************************************************************************/
BOOL  _EventSetThreadReady (PLW_CLASS_EVENTSETNODE    pesn,
                            ULONG                     ulEventsReady)
{
    REGISTER PLW_CLASS_TCB    ptcb;
    REGISTER PLW_CLASS_PCB    ppcb;
    REGISTER BOOL             bIsSched = LW_FALSE;
    
    ptcb = (PLW_CLASS_TCB)pesn->EVENTSETNODE_ptcbMe;
    if (ptcb->TCB_usStatus & LW_THREAD_STATUS_DELAY) {                  /*  存在于 wake up 表中         */
        __DEL_FROM_WAKEUP_LINE(ptcb);                                   /*  从等待链中删除              */
    
    } else {
        if (ptcb->TCB_ucWaitTimeout == LW_WAIT_TIME_OUT) {              /*  已经被超时扫描就绪了        */
            ptcb->TCB_ucWaitTimeout =  LW_WAIT_TIME_CLEAR;
            ptcb->TCB_ulEventSets   =  ulEventsReady;
            
            _EventSetUnlink(pesn);                                      /*  event set 解链              */
            return  (bIsSched);
        }
    }
    
    ptcb->TCB_ulDelay      = 0ul;
    ptcb->TCB_ulEventSets  = ulEventsReady;
    ptcb->TCB_usStatus    &= (~LW_THREAD_STATUS_EVENTSET);
    
    if (__LW_THREAD_IS_READY(ptcb)) {                                   /*  是否就绪                    */
        ptcb->TCB_ucSchedActivate = LW_SCHED_ACT_INTERRUPT;
        ppcb = _GetPcb(ptcb);
        __ADD_TO_READY_RING(ptcb, ppcb);                                /*  加入就绪表                  */
        bIsSched = LW_TRUE;
    }
    
    _EventSetUnlink(pesn);
    return  (bIsSched);
}
Esempio n. 5
0
/*********************************************************************************************************
** 函数名称: sigwaitinfo
** 功能描述: 等待 sigset 内信号的到来,以串行的方式从信号队列中取出信号进行处理, 信号将不再被执行.
** 输 入  : psigset       指定的信号集
**           psiginfo      获取的信号信息
** 输 出  : ERROR
** 全局变量: 
** 调用模块: 
                                           API 函数
*********************************************************************************************************/
LW_API  
INT  sigwaitinfo (const sigset_t *psigset, struct  siginfo  *psiginfo)
{
             INTREG             iregInterLevel;
             PLW_CLASS_TCB      ptcbCur;
    REGISTER PLW_CLASS_PCB      ppcb;
    
             INT                    iSigNo;
             PLW_CLASS_SIGCONTEXT   psigctx;
             struct siginfo         siginfo;
             LW_CLASS_SIGWAIT       sigwt;
    
    if (!psigset) {
        _ErrorHandle(EINVAL);
        return  (PX_ERROR);
    }
    
    __THREAD_CANCEL_POINT();                                            /*  测试取消点                  */
    
    LW_TCB_GET_CUR_SAFE(ptcbCur);                                       /*  当前任务控制块              */
    
    MONITOR_EVT_D2(MONITOR_EVENT_ID_SIGNAL, MONITOR_EVENT_SIGNAL_SIGWAIT, 
                   ptcbCur->TCB_ulId, *psigset, LW_NULL);
    
    __KERNEL_ENTER();                                                   /*  进入内核                    */
    psigctx = _signalGetCtx(ptcbCur);
    
    iSigNo = _sigPendGet(psigctx, psigset, &siginfo);                   /*  检查当前是否有等待的信号    */
    if (__issig(iSigNo)) {
        __KERNEL_EXIT();                                                /*  退出内核                    */
        if (psiginfo) {
            *psiginfo = siginfo;
        }
        return  (siginfo.si_signo);
    }
    
    iregInterLevel = KN_INT_DISABLE();                                  /*  关闭中断                    */
    ptcbCur->TCB_usStatus |= LW_THREAD_STATUS_SIGNAL;                   /*  等待信号                    */
    ppcb = _GetPcb(ptcbCur);
    __DEL_FROM_READY_RING(ptcbCur, ppcb);                               /*  从就绪表中删除              */
    KN_INT_ENABLE(iregInterLevel);                                      /*  打开中断                    */
    
    sigwt.SIGWT_sigset = *psigset;
    psigctx->SIGCTX_sigwait = &sigwt;                                   /*  保存等待信息                */
    
    if (__KERNEL_EXIT()) {                                              /*  是否其他信号激活            */
        psigctx->SIGCTX_sigwait = LW_NULL;
        _ErrorHandle(EINTR);                                            /*  SA_RESTART 也退出           */
        return  (PX_ERROR);
    }
    
    psigctx->SIGCTX_sigwait = LW_NULL;
    if (psiginfo) {
        *psiginfo = sigwt.SIGWT_siginfo;
    }
    
    return  (sigwt.SIGWT_siginfo.si_signo);
}
Esempio n. 6
0
/*********************************************************************************************************
** 函数名称: sigsuspend
** 功能描述: 使用指定的掩码等待一个有效信号的到来, 然后返回先前的信号掩码.
** 输 入  : psigsetMask        指定的信号掩码
** 输 出  : ERROR
** 全局变量: 
** 调用模块: 
                                           API 函数
*********************************************************************************************************/
LW_API  
INT  sigsuspend (const sigset_t  *psigsetMask)
{
             INTREG         iregInterLevel;
             PLW_CLASS_TCB  ptcbCur;
    REGISTER PLW_CLASS_PCB  ppcb;
             BOOL           bIsRun;
    
             PLW_CLASS_SIGCONTEXT   psigctx;
             sigset_t               sigsetOld;
             
    if (!psigsetMask) {
        _ErrorHandle(EINVAL);
        return  (PX_ERROR);
    }
    
    __THREAD_CANCEL_POINT();                                            /*  测试取消点                  */
    
    LW_TCB_GET_CUR_SAFE(ptcbCur);                                       /*  当前任务控制块              */
    
    MONITOR_EVT_D2(MONITOR_EVENT_ID_SIGNAL, MONITOR_EVENT_SIGNAL_SIGSUSPEND, 
                   ptcbCur->TCB_ulId, *psigsetMask, LW_NULL);
    
    __KERNEL_ENTER();                                                   /*  进入内核                    */
    psigctx = _signalGetCtx(ptcbCur);
    
    sigsetOld = psigctx->SIGCTX_sigsetSigBlockMask;                     /*  记录先前的掩码              */
    psigctx->SIGCTX_sigsetSigBlockMask = *psigsetMask & (~__SIGNO_UNMASK);
    
    bIsRun = _sigPendRun(ptcbCur);
    if (bIsRun) {
        __KERNEL_EXIT();                                                /*  退出内核                    */
        sigprocmask(SIG_SETMASK, &sigsetOld, LW_NULL);                  /*  设置为原先的 mask           */
        
        _ErrorHandle(EINTR);
        return  (PX_ERROR);
    }
    
    iregInterLevel = KN_INT_DISABLE();                                  /*  关闭中断                    */
    ptcbCur->TCB_usStatus |= LW_THREAD_STATUS_SIGNAL;                   /*  等待信号                    */
    ppcb = _GetPcb(ptcbCur);
    __DEL_FROM_READY_RING(ptcbCur, ppcb);                               /*  从就绪表中删除              */
    KN_INT_ENABLE(iregInterLevel);                                      /*  打开中断                    */
    
    __KERNEL_EXIT();                                                    /*  退出内核                    */
    
    sigprocmask(SIG_SETMASK, &sigsetOld, NULL);
    
    _ErrorHandle(EINTR);
    return  (PX_ERROR);
}
Esempio n. 7
0
static VOID  _ThreadWaitStatus (PLW_CLASS_TCB  ptcbCur, PLW_CLASS_TCB  ptcbDest, UINT  uiStatusReq)
{
    PLW_CLASS_PCB  ppcb;

    if (__LW_THREAD_IS_READY(ptcbCur)) {
        ppcb = _GetPcb(ptcbCur);
        __DEL_FROM_READY_RING(ptcbCur, ppcb);                           /*  从就绪表中删除              */
    }
    
    ptcbCur->TCB_ptcbWaitStatus     = ptcbDest;
    ptcbCur->TCB_uiStatusChangeReq  = uiStatusReq;                      /*  请求修改的状态              */
    ptcbCur->TCB_usStatus          |= LW_THREAD_STATUS_WSTAT;
    
    _List_Line_Add_Ahead(&ptcbCur->TCB_lineStatusPend,
                         &ptcbDest->TCB_plineStatusReqHeader);
}
Esempio n. 8
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);
}
Esempio n. 9
0
/*********************************************************************************************************
** 函数名称: _ThreadTick
** 功能描述: 扫描等待唤醒链表, tick 处理函数
** 输 入  : NONE
** 输 出  : NONE
** 全局变量: 
** 调用模块: 
*********************************************************************************************************/
VOID  _ThreadTick (VOID)
{
             INTREG                 iregInterLevel;
    REGISTER PLW_CLASS_TCB          ptcb;
    REGISTER PLW_CLASS_PCB          ppcb;
             PLW_CLASS_WAKEUP_NODE  pwun;
             ULONG                  ulCounter = 1;
    
    iregInterLevel = __KERNEL_ENTER_IRQ();                              /*  进入内核同时关闭中断        */
    
    __WAKEUP_PASS_FIRST(&_K_wuDelay, pwun, ulCounter);
    
    ptcb = _LIST_ENTRY(pwun, LW_CLASS_TCB, TCB_wunDelay);
    
    __DEL_FROM_WAKEUP_LINE(ptcb);                                       /*  从等待链中删除              */
    
    if (ptcb->TCB_usStatus & LW_THREAD_STATUS_PEND_ANY) {               /*  检查是否在等待事件          */
        ptcb->TCB_usStatus &= (~LW_THREAD_STATUS_PEND_ANY);             /*  等待超时清除事件等待位      */
        ptcb->TCB_ucWaitTimeout = LW_WAIT_TIME_OUT;                     /*  等待超时                    */
    
    } else {
        ptcb->TCB_ucWaitTimeout = LW_WAIT_TIME_CLEAR;                   /*  没有等待事件                */
    }
    
    if (__LW_THREAD_IS_READY(ptcb)) {                                   /*  检查是否就绪                */
        ptcb->TCB_ucSchedActivate = LW_SCHED_ACT_OTHER;
        ppcb = _GetPcb(ptcb);                                           /*  获得优先级控制块            */
        __ADD_TO_READY_RING(ptcb, ppcb);                                /*  加入就绪环                  */
    }
    
    __WAKEUP_PASS_SECOND();
    
    KN_INT_ENABLE(iregInterLevel);                                      /*  这里允许响应中断            */
    
    iregInterLevel = KN_INT_DISABLE();
    
    __WAKEUP_PASS_END();
    
    __KERNEL_EXIT_IRQ(iregInterLevel);                                  /*  退出内核同时打开中断        */
}
Esempio n. 10
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);
}
Esempio n. 11
0
/*********************************************************************************************************
** 函数名称: sigtimedwait
** 功能描述: 等待 sigset 内信号的到来,以串行的方式从信号队列中取出信号进行处理, 信号将不再被执行.
** 输 入  : psigset        指定的信号集
**           psiginfo      获取的信号信息
**           ptv           超时时间 (NULL 表示一直等待)
** 输 出  : ERROR
** 全局变量: 
** 调用模块: 
                                           API 函数
*********************************************************************************************************/
LW_API  
INT  sigtimedwait (const sigset_t *psigset, struct  siginfo  *psiginfo, const struct timespec *ptv)
{
             INTREG             iregInterLevel;
             PLW_CLASS_TCB      ptcbCur;
    REGISTER PLW_CLASS_PCB      ppcb;
    
             INT                    iSigNo;
             PLW_CLASS_SIGCONTEXT   psigctx;
             struct siginfo         siginfo;
             LW_CLASS_SIGWAIT       sigwt;
             
             ULONG                  ulTimeout;
    
    if (!psigset) {
        _ErrorHandle(EINVAL);
        return  (PX_ERROR);
    }
    
    if (ptv == LW_NULL) {                                               /*  永久等待                    */
        ulTimeout = LW_OPTION_WAIT_INFINITE;
    } else {
        ulTimeout = __timespecToTick(ptv);
    }
    
    __THREAD_CANCEL_POINT();                                            /*  测试取消点                  */
    
    LW_TCB_GET_CUR_SAFE(ptcbCur);                                       /*  当前任务控制块              */
    
    MONITOR_EVT_D2(MONITOR_EVENT_ID_SIGNAL, MONITOR_EVENT_SIGNAL_SIGWAIT, 
                   ptcbCur->TCB_ulId, *psigset, LW_NULL);
    
    __KERNEL_ENTER();                                                   /*  进入内核                    */
    psigctx = _signalGetCtx(ptcbCur);
    
    iSigNo = _sigPendGet(psigctx, psigset, &siginfo);                   /*  检查当前是否有等待的信号    */
    if (__issig(iSigNo)) {
        __KERNEL_EXIT();                                                /*  退出内核                    */
        if (psiginfo) {
            *psiginfo = siginfo;
        }
        return  (siginfo.si_signo);
    }
    
    if (ulTimeout == LW_OPTION_NOT_WAIT) {                              /*  不进行等待                  */
        __KERNEL_EXIT();                                                /*  退出内核                    */
        _ErrorHandle(EAGAIN);
        return  (PX_ERROR);
    }
    
    iregInterLevel = KN_INT_DISABLE();                                  /*  关闭中断                    */
    ptcbCur->TCB_usStatus |= LW_THREAD_STATUS_SIGNAL;                   /*  等待信号                    */
    ptcbCur->TCB_ucWaitTimeout = LW_WAIT_TIME_CLEAR;                    /*  清空等待时间                */
    
    ppcb = _GetPcb(ptcbCur);
    __DEL_FROM_READY_RING(ptcbCur, ppcb);                               /*  从就绪表中删除              */
    
    if (ulTimeout != LW_OPTION_WAIT_INFINITE) {
        ptcbCur->TCB_ulDelay = ulTimeout;                               /*  设置超时时间                */
        __ADD_TO_WAKEUP_LINE(ptcbCur);                                  /*  加入等待扫描链              */
    } else {
        ptcbCur->TCB_ulDelay = 0ul;
    }
    KN_INT_ENABLE(iregInterLevel);                                      /*  打开中断                    */
    
    sigwt.SIGWT_sigset = *psigset;
    psigctx->SIGCTX_sigwait = &sigwt;                                   /*  保存等待信息                */
    
    if (__KERNEL_EXIT()) {                                              /*  是否其他信号激活            */
        psigctx->SIGCTX_sigwait = LW_NULL;
        _ErrorHandle(EINTR);                                            /*  SA_RESTART 也退出           */
        return  (PX_ERROR);
    }
    
    __KERNEL_ENTER();                                                   /*  进入内核                    */
    if (ptcbCur->TCB_ucWaitTimeout == LW_WAIT_TIME_OUT) {               /*  等待超时                    */
        __KERNEL_EXIT();                                                /*  退出内核                    */
        _ErrorHandle(EAGAIN);
        return  (PX_ERROR);
    }
    __KERNEL_EXIT();                                                    /*  退出内核                    */
    
    psigctx->SIGCTX_sigwait = LW_NULL;
    if (psiginfo) {
        *psiginfo = sigwt.SIGWT_siginfo;
    }
    
    return  (sigwt.SIGWT_siginfo.si_signo);
}
Esempio n. 12
0
/*********************************************************************************************************
** 函数名称: _ThreadStatusChange
** 功能描述: 改变线程状态 (进入内核状态被调用)
** 输 入  : ptcb          线程控制块
**           uiStatusReq   状态 (LW_TCB_REQ_SUSPEND / LW_TCB_REQ_WDEATH / LW_TCB_REQ_STOP)
** 输 出  : ERROR
** 全局变量: 
** 调用模块: 
** 注  意  : 此函数已经预置的阻塞点, 最后一次退出内核时, 将阻塞等待目标线程状态改变完毕.
*********************************************************************************************************/
ULONG  _ThreadStatusChange (PLW_CLASS_TCB  ptcb, UINT  uiStatusReq)
{
    INTREG         iregInterLevel;
    PLW_CLASS_PCB  ppcb;
    PLW_CLASS_TCB  ptcbCur;
    
    iregInterLevel = KN_INT_DISABLE();                                  /*  关闭中断                    */
    
    LW_TCB_GET_CUR(ptcbCur);
    
#if LW_CFG_SMP_EN > 0
    if (ptcb == ptcbCur) {                                              /*  改变自己的状态              */
        goto    __change1;
    
    } else if (!__LW_THREAD_IS_READY(ptcb)) {                           /*  任务没有就绪                */
        goto    __change2;
    
    } else {                                                            /*  目标任务处于就绪状态        */
        if (LW_CPU_GET_CUR_NESTING()) {
            KN_INT_ENABLE(iregInterLevel);                              /*  打开中断                    */
            return  (ERROR_KERNEL_IN_ISR);                              /*  中断状态下无法完成此工作    */
        }
        
        if (!__LW_THREAD_IS_RUNNING(ptcb)) {                            /*  目标任务不是正在执行        */
            ppcb = _GetPcb(ptcb);
            __DEL_FROM_READY_RING(ptcb, ppcb);                          /*  从就绪表中删除              */
            goto    __change2;
        
        } else {                                                        /*  目标任务正在执行            */
            _SmpUpdateIpi(LW_CPU_GET(ptcb->TCB_ulCPUId));               /*  发送核间中断通知改变状态    */
            _ThreadWaitStatus(ptcbCur, ptcb, uiStatusReq);              /*  设置等待对方完成状态        */
        }
        
        KN_INT_ENABLE(iregInterLevel);                                  /*  打开中断                    */
        return  (ERROR_NONE);                                           /*  退出内核时开始等待          */
    }
    
__change1:
#endif                                                                  /*  LW_CFG_SMP_EN               */
    
    if (__LW_THREAD_IS_READY(ptcb)) {
        ppcb = _GetPcb(ptcb);
        __DEL_FROM_READY_RING(ptcb, ppcb);                              /*  从就绪表中删除              */
    }
    
#if LW_CFG_SMP_EN > 0
__change2:
#endif                                                                  /*  LW_CFG_SMP_EN               */
    
    ptcbCur->TCB_uiStatusChangeReq = 0;                                 /*  状态修改操作执行成功        */
    
    switch (uiStatusReq) {
    
    case LW_TCB_REQ_SUSPEND:
        ptcb->TCB_ulSuspendNesting++;
        ptcb->TCB_usStatus |= LW_THREAD_STATUS_SUSPEND;
        break;
        
    case LW_TCB_REQ_STOP:
        ptcb->TCB_ulStopNesting++;
        ptcb->TCB_usStatus |= LW_THREAD_STATUS_STOP;
        break;
        
    case LW_TCB_REQ_WDEATH:
        ptcb->TCB_usStatus |= LW_THREAD_STATUS_WDEATH;
        break;
    }
        
    KN_INT_ENABLE(iregInterLevel);
    return  (ERROR_NONE);
}
Esempio n. 13
0
ULONG  __threadDelete (PLW_CLASS_TCB  ptcbDel, BOOL  bIsInSafe, 
                       PVOID  pvRetVal, BOOL  bIsAlreadyWaitDeath)
{
             INTREG                iregInterLevel;
    REGISTER UINT16                usIndex;
    REGISTER PLW_CLASS_PCB         ppcbDel;
    REGISTER LW_OBJECT_HANDLE      ulId;
    REGISTER PVOID                 pvFreeLowAddr;                       /*  要释放的内存地址            */
             PVOID                 pvVProc;
             
#if (LW_CFG_EVENTSET_EN > 0) && (LW_CFG_MAX_EVENTSETS > 0)
    REGISTER PLW_EVENTSETNODE      pesnPtr;
#endif

    ulId    = ptcbDel->TCB_ulId;
    usIndex = _ObjectGetIndex(ulId);
    
    if (bIsAlreadyWaitDeath == LW_FALSE) {
        _ThreadDeleteWaitDeath(ptcbDel);                                /*  将要删除的线程进入僵死状态  */
    }
    
    __KERNEL_ENTER();                                                   /*  进入内核                    */
    
    ppcbDel = _GetPcb(ptcbDel);
    
    iregInterLevel = KN_INT_DISABLE();                                  /*  关闭中断                    */
    
    if (ptcbDel->TCB_ptcbDeleteWait) {                                  /*  目标线程正在等待其他任务删除*/
        ptcbDel->TCB_ptcbDeleteWait->TCB_ptcbDeleteMe = (PLW_CLASS_TCB)1;
        ptcbDel->TCB_ptcbDeleteWait = LW_NULL;
    }
    
#if (LW_CFG_EVENT_EN > 0) && (LW_CFG_MAX_EVENTS > 0)
    if (ptcbDel->TCB_peventPtr) {                                       /*  等待事件中                  */
        _EventUnlink(ptcbDel);                                          /*  解等待连                    */
    }
#endif

#if (LW_CFG_EVENTSET_EN > 0) && (LW_CFG_MAX_EVENTSETS > 0)
    pesnPtr = ptcbDel->TCB_pesnPtr;
    if (pesnPtr) {
        _EventSetUnlink(pesnPtr);                                       /*  解事件集                    */
    }
#endif

#if LW_CFG_SMP_EN > 0
    if (ptcbDel->TCB_ptcbWaitStatus ||
        ptcbDel->TCB_plineStatusReqHeader) {                            /*  正在请求其他线程改变状态    */
        _ThreadUnwaitStatus(ptcbDel);
    }
#endif                                                                  /*  LW_CFG_SMP_EN               */
    
    if (__LW_THREAD_IS_READY(ptcbDel)) {                                /*  是否就绪                    */
        __DEL_FROM_READY_RING(ptcbDel, ppcbDel);                        /*  从就绪队列中删除            */
        
    } else {
        if (ptcbDel->TCB_usStatus & LW_THREAD_STATUS_DELAY) {
            __DEL_FROM_WAKEUP_LINE(ptcbDel);                            /*  从等待链中删除              */
            ptcbDel->TCB_ulDelay = 0ul;
        }
        ptcbDel->TCB_usStatus = LW_THREAD_STATUS_RDY;                   /*  防止 Tick 中断激活          */
    }
    
#if LW_CFG_SOFTWARE_WATCHDOG_EN > 0
    if (ptcbDel->TCB_bWatchDogInQ) {
        __DEL_FROM_WATCHDOG_LINE(ptcbDel);                              /*  从 watch dog 中删除         */
        ptcbDel->TCB_ulWatchDog = 0ul;
    }
#endif
    KN_INT_ENABLE(iregInterLevel);
    
    pvFreeLowAddr = (PVOID)ptcbDel->TCB_pstkStackLowAddr;               /*  记录地址                    */
    
#if (LW_CFG_THREAD_PRIVATE_VARS_EN > 0) && (LW_CFG_MAX_THREAD_GLB_VARS > 0)
    _ThreadVarDelete(ptcbDel);                                          /*  删除并恢复私有化的全局变量  */
#endif
    
    iregInterLevel = KN_INT_DISABLE();                                  /*  关闭中断                    */ 
    
    _K_usThreadCounter--;
    _K_ptcbTCBIdTable[usIndex] = LW_NULL;                               /*  TCB 表清0                   */
    
    _List_Line_Del(&ptcbDel->TCB_lineManage, &_K_plineTCBHeader);       /*  从管理练表中删除            */
    
    KN_INT_ENABLE(iregInterLevel);                                      /*  打开中断                    */
    
    if (ptcbDel->TCB_ptcbJoin) {
        _ThreadDisjoin(ptcbDel->TCB_ptcbJoin, ptcbDel);                 /*  退出 join 状态, 不操作就绪表*/
    }
    
    _ThreadDisjoinWakeupAll(ptcbDel, pvRetVal);                         /*  DETACH                      */
    
    __KERNEL_EXIT();                                                    /*  退出内核                    */
    
#if LW_CFG_COROUTINE_EN > 0
    _CoroutineFreeAll(ptcbDel);                                         /*  删除协程内存空间            */
#endif                                                                  /*  LW_CFG_COROUTINE_EN > 0     */
    
    if (bIsInSafe) {
        _DebugFormat(__ERRORMESSAGE_LEVEL, 
                     "thread \"%s\" has been delete in SAFE mode.\r\n",
                     ptcbDel->TCB_cThreadName);
    } else {
        _DebugFormat(__LOGMESSAGE_LEVEL, 
                     "thread \"%s\" has been delete.\r\n",
                     ptcbDel->TCB_cThreadName);
    }
    
    pvVProc = ptcbDel->TCB_pvVProcessContext;                           /*  进程信息                    */
    
    if (ptcbDel->TCB_ucStackAutoAllocFlag) {                            /*  是否是内核堆开辟堆栈        */
#if LW_CFG_MODULELOADER_EN > 0
        vprocStackFree(ptcbDel, pvFreeLowAddr, LW_FALSE);
#else
        __KHEAP_FREE(pvFreeLowAddr);                                    /*  释放堆栈空间                */
#endif                                                                  /*  LW_CFG_MODULELOADER_EN > 0  */
    }
    
    _TCBDestroy(ptcbDel);                                               /*  销毁 TCB                    */
    
    __KERNEL_MODE_PROC(
        _Free_Tcb_Object(ptcbDel);                                      /*  释放 ID                     */
    );