Example #1
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);
}
Example #2
0
/*********************************************************************************************************
** 函数名称: sigmask
** 功能描述: 通过信号的值获取一个信号掩码
** 输 入  : iSigNo                  信号
** 输 出  : 信号掩码
** 全局变量: 
** 调用模块: 
                                           API 函数
*********************************************************************************************************/
LW_API  
INT  sigmask (INT  iSigNo)
{
    if (!__issig(iSigNo)) {
        _ErrorHandle(EINVAL);
        return  (0);
    }
    
    return  ((INT)__sigmask(iSigNo));
}
Example #3
0
/*********************************************************************************************************
** 函数名称: sigdelset
** 功能描述: 从一个信号集中删除一个信号
** 输 入  : psigset                 信号集
**           iSigNo                  信号
** 输 出  : ERROR_NONE , EINVAL
** 全局变量: 
** 调用模块: 
                                           API 函数
*********************************************************************************************************/
LW_API  
INT  sigdelset (sigset_t  *psigset, INT  iSigNo)
{
    if (__issig(iSigNo)) {
        *psigset &= ~__sigmask(iSigNo);
        return  (ERROR_NONE);
    }
    _ErrorHandle(EINVAL);
    return  (PX_ERROR);
}
Example #4
0
/*********************************************************************************************************
** 函数名称: sigignore
** 功能描述: 将指定的信号设置为 SIG_IGN
** 输 入  : iSigNo                   需要 SIG_IGN 的信号
** 输 出  : ERROR
** 全局变量: 
** 调用模块: 
                                           API 函数
*********************************************************************************************************/
LW_API 
INT  sigignore (INT  iSigNo)
{
    if (!__issig(iSigNo)) {
        _ErrorHandle(EINVAL);
        return  (PX_ERROR);
    }
    
    signal(iSigNo, SIG_IGN);

    return  (ERROR_NONE);
}
Example #5
0
/*********************************************************************************************************
** 函数名称: sigismember
** 功能描述: 检查一个信号是否属于一个信号集
** 输 入  : 
**           psigset                 信号集
**           iSigNo                  信号
** 输 出  : 0 or 1 or -1
** 全局变量: 
** 调用模块: 
                                           API 函数
*********************************************************************************************************/
LW_API  
INT  sigismember (const sigset_t  *psigset, INT  iSigNo)
{
    if (__issig(iSigNo)) {
        if (*psigset & __sigmask(iSigNo)) {
            return  (1);
        } else {
            return  (0);
        }
    }
    _ErrorHandle(EINVAL);
    return  (PX_ERROR);
}
Example #6
0
/*********************************************************************************************************
** 函数名称: sighold
** 功能描述: 将新的需要阻塞的信号添加到当前线程
** 输 入  : iSigNo                   需要阻塞的信号
** 输 出  : ERROR
** 全局变量: 
** 调用模块: 
                                           API 函数
*********************************************************************************************************/
LW_API  
INT  sighold (INT  iSigNo)
{
    sigset_t    sigset = 0;

    if (!__issig(iSigNo)) {
        _ErrorHandle(EINVAL);
        return  (PX_ERROR);
    }

    sigset = __sigmask(iSigNo);

    return  (sigprocmask(SIG_BLOCK, &sigset, LW_NULL));
}
Example #7
0
/*********************************************************************************************************
** 函数名称: sigqueue
** 功能描述: 发送队列类型信号, 如果是进程, 将发送给其主线程.
** 输 入  : ulId                    线程 id 或者 进程号
**           iSigNo                  信号
**           sigvalue                信号 value
** 输 出  : ERROR or OK
** 全局变量: 
** 调用模块: 
                                           API 函数
*********************************************************************************************************/
LW_API  
INT  sigqueue (LW_OBJECT_HANDLE  ulId, INT   iSigNo, const union sigval  sigvalue)
{
    REGISTER UINT16             usIndex;
    REGISTER PLW_CLASS_TCB      ptcb;
             LW_SEND_VAL        sendval;
             
#if LW_CFG_MODULELOADER_EN > 0
    if (ulId < LW_CFG_MAX_THREADS) {                                    /*  进程号                      */
        ulId = vprocMainThread((pid_t)ulId);
    }
#endif                                                                  /*  LW_CFG_MODULELOADER_EN > 0  */
    
    usIndex = _ObjectGetIndex(ulId);
    
    if (!_ObjectClassOK(ulId, _OBJECT_THREAD)) {                        /*  检查 ID 类型有效性          */
        _ErrorHandle(ESRCH);
        return  (PX_ERROR);
    }
    if (_Thread_Index_Invalid(usIndex)) {                               /*  检查线程有效性              */
        _ErrorHandle(ESRCH);
        return  (PX_ERROR);
    }
    
    if (!__issig(iSigNo)) {
        _ErrorHandle(EINVAL);
        return  (PX_ERROR);
    }
    
    if (LW_CPU_GET_CUR_NESTING() || (ulId == API_ThreadIdSelf())) {
        _excJobAdd((VOIDFUNCPTR)sigqueue, (PVOID)ulId, (PVOID)iSigNo, (PVOID)sigvalue.sival_ptr, 
                   0, 0, 0);
        return  (ERROR_NONE);
    }
    
#if LW_CFG_SMP_EN > 0
    if (LW_NCPUS > 1) {                                                 /*  正工作在 SMP 多核模式       */
        if (API_ThreadStop(ulId)) {
            return  (PX_ERROR);
        }
    }
#endif                                                                  /*  LW_CFG_SMP_EN               */

    __KERNEL_ENTER();                                                   /*  进入内核                    */
    if (_Thread_Invalid(usIndex)) {
        __KERNEL_EXIT();                                                /*  退出内核                    */
        _ErrorHandle(ESRCH);
        return  (PX_ERROR);
    }
    
    ptcb = __GET_TCB_FROM_INDEX(usIndex);
    if (ptcb->TCB_iDeleteProcStatus) {
        __KERNEL_EXIT();                                                /*  退出内核                    */
        _ErrorHandle(ERROR_THREAD_OTHER_DELETE);
        return  (PX_ERROR);
    }
    
    sendval = _doSigQueue(ptcb, iSigNo, sigvalue);

#if LW_CFG_SMP_EN > 0
    if (LW_NCPUS > 1) {                                                 /*  正工作在 SMP 多核模式       */
        _ThreadContinue(ptcb, LW_FALSE);                                /*  在内核状态下唤醒被停止线程  */
    }
#endif                                                                  /*  LW_CFG_SMP_EN               */
    __KERNEL_EXIT();                                                    /*  退出内核                    */
    
#if LW_CFG_SIGNALFD_EN > 0
    if (sendval == SEND_BLOCK) {
        _sigfdReadUnblock(ulId, iSigNo);
    }
#endif                                                                  /*  LW_CFG_SIGNALFD_EN > 0      */
    
    return  (ERROR_NONE);
}
Example #8
0
/*********************************************************************************************************
** 函数名称: sigaction
** 功能描述: 设置一个指定信号的服务向量, 同时可获取原始服务向量. 
**           (由于与 struct sigaction 重名, 所以这里直接使用 sigaction 函数名)
** 输 入  : iSigNo        信号
**           psigactionNew 新的处理结构
**           psigactionOld 先早的处理结构
** 输 出  : ERROR_NONE , EINVAL
** 全局变量: 
** 调用模块: 
                                           API 函数
*********************************************************************************************************/
LW_API  
INT   sigaction (INT                      iSigNo, 
                 const struct sigaction  *psigactionNew,
                 struct sigaction        *psigactionOld)
{
    struct sigaction               *psigaction;
    PLW_CLASS_SIGCONTEXT            psigctx;
    PLW_CLASS_TCB                   ptcbCur;
    REGISTER PLW_CLASS_SIGPEND      psigpend;
    REGISTER INT                    iSigIndex = __sigindex(iSigNo);     /*  TCB_sigaction 下标          */
    
    if (!__issig(iSigNo)) {
        _ErrorHandle(EINVAL);
        return  (PX_ERROR);
    }
    
    if ((iSigNo == SIGKILL) || (iSigNo == SIGSTOP)) {                   /*  不能捕获和忽略              */
        _ErrorHandle(EINVAL);
        return  (PX_ERROR);
    }
    
    LW_TCB_GET_CUR_SAFE(ptcbCur);
    
    psigctx    = _signalGetCtx(ptcbCur);
    psigaction = &psigctx->SIGCTX_sigaction[iSigIndex];
    
    if (psigactionOld) {
        *psigactionOld = *psigaction;                                   /*  保存先早信息                */
    }
    
    if (psigactionNew == LW_NULL) {
        return  (ERROR_NONE);
    }
    
    __KERNEL_ENTER();
    *psigaction = *psigactionNew;                                       /*  拷贝新的处理控制块          */
    psigaction->sa_mask &= ~__SIGNO_UNMASK;                             /*  有些信号不可屏蔽            */
    __KERNEL_EXIT();
    
    if (psigaction->sa_handler == SIG_IGN) {                            /*  设置为忽略该信号            */
        __KERNEL_ENTER();                                               /*  进入内核                    */
        
        psigctx->SIGCTX_sigsetPending &= ~__sigmask(iSigNo);            /*  没有等待 unmask 后执行的信号*/
        psigctx->SIGCTX_sigsetKill    &= ~__sigmask(iSigNo);            /*  没有在屏蔽状态 kill 这个信号*/
        
        {                                                               /*  删除队列中的相关信号节点    */
                     PLW_LIST_RING  pringHead = psigctx->SIGCTX_pringSigQ[iSigIndex];
            REGISTER PLW_LIST_RING  pringSigP = pringHead;
            
            if (pringHead) {                                            /*  唤醒队列中存在节点          */
                do {
                    psigpend  = _LIST_ENTRY(pringSigP, 
                                            LW_CLASS_SIGPEND, 
                                            SIGPEND_ringSigQ);          /*  获得 sigpend 控制块地址     */
                    
                    pringSigP = _list_ring_get_next(pringSigP);         /*  下一个节点                  */
                    
                    if ((psigpend->SIGPEND_siginfo.si_code != SI_KILL) &&
                        (psigpend->SIGPEND_iNotify         == SIGEV_SIGNAL)) {
                        _sigPendFree(psigpend);                         /*  需要交换空闲队列            */
                    }
                } while (pringSigP != pringHead);
            }
        }
        __KERNEL_EXIT();                                                /*  退出内核                    */
    }
    
    return  (ERROR_NONE);
}
Example #9
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);
}
Example #10
0
/*********************************************************************************************************
** 函数名称: lio_listio
** 功能描述: 同时发起多个传输 mode 参数可以是 LIO_WAIT 或 LIO_NOWAIT。LIO_WAIT 会阻塞这个调用,
             直到所有的 I/O 都完成为止. 在操作进行排队之后,LIO_NOWAIT 就会返回. 
             sigevent 引用定义了在所有 I/O 操作都完成时产生信号的方法。
** 输 入  : mode              LIO_WAIT or LIO_NOWAIT。LIO_WAIT
**           list              aio 请求控制块数组 (如果其中有 NULL, 程序将忽略)
**           nent              数组元素个数
**           sig               所有 I/O 操作都完成时产生信号的方法
                               LIO_WAIT 将会忽略此参数!
** 输 出  : ERROR or OK
** 全局变量: 
** 调用模块: 
                                           API 函数
*********************************************************************************************************/
LW_API 
int  lio_listio (int mode, struct aiocb * const list[], int nent, struct sigevent *sig)
{
    AIO_WAIT_CHAIN     *paiowc;
    struct aiowait     *paiowait;
    
    int                 iWait = 0;                                      /*  paiowait 下标               */
    int                 iCnt;                                           /*  list 下标                   */
    int                 iRet = ERROR_NONE;
    
#ifdef __SYLIXOS_KERNEL
    if (__PROC_GET_PID_CUR() != 0) {                                    /*  需要使用外部库提供的 aio    */
        errno = ENOSYS;
        return  (PX_ERROR);
    }
#endif                                                                  /*  __SYLIXOS_KERNEL            */
    
    if ((mode != LIO_WAIT) && (mode != LIO_NOWAIT)) {
        errno = EINVAL;
        return  (PX_ERROR);
    }
    
    if ((nent <= 0) || (list == LW_NULL)) {
        errno = EINVAL;
        return  (PX_ERROR);
    }
    
    if (mode == LIO_WAIT) {
        paiowc = __aioCreateWaitChain(nent, LW_TRUE);                   /*  创建等待队列                */
    } else {
        paiowc = __aioCreateWaitChain(nent, LW_FALSE);
    }
    if (paiowc == LW_NULL) {
        errno = ENOMEM;                                                 /*  should be EAGAIN ?          */
        return  (PX_ERROR);
    }
    
    if (sig) {
        paiowc->aiowc_sigevent = *sig;
    } else {
        paiowc->aiowc_sigevent.sigev_signo = 0;                         /*  无效信号不投递              */
    }
    
    paiowait = paiowc->aiowc_paiowait;
    
    API_SemaphoreMPend(_G_aioqueue.aioq_mutex, LW_OPTION_WAIT_INFINITE);
    
    for (iCnt = 0; iCnt < nent; iCnt++) {
        if (list[iCnt]) {
            if ((list[iCnt]->aio_lio_opcode != LIO_NOP) &&
                (list[iCnt]->aio_req.aioreq_error != EINPROGRESS)) {
                
                list[iCnt]->aio_sigevent.sigev_notify = SIGEV_NONE;     /*  不使用 aiocb 的 sigevent    */
                list[iCnt]->aio_req.aioreq_thread     = API_ThreadIdSelf();
                
                if (mode == LIO_WAIT) {
                    paiowait[iWait].aiowt_pcond     = &paiowc->aiowc_cond;
                    paiowait[iWait].aiowt_pcnt      = LW_NULL;
                    paiowait[iWait].aiowt_psigevent = LW_NULL;
                    paiowait[iWait].aiowt_paiowc    = LW_NULL;          /*  不需要代理线程释放          */
                
                } else {
                    paiowait[iWait].aiowt_pcond     = LW_NULL;
                    paiowait[iWait].aiowt_pcnt      = LW_NULL;
                    paiowait[iWait].aiowt_psigevent = &paiowc->aiowc_sigevent;
                    paiowait[iWait].aiowt_paiowc    = (void *)paiowc;
                }
                
                __aioAttachWaitNoCheck(list[iCnt], &paiowait[iWait]);   /*  aiocb and aiowait attach    */
                
                if (__aioEnqueue(list[iCnt]) == ERROR_NONE) {
                
                    _List_Line_Add_Tail(&paiowait[iWait].aiowt_line, 
                                        &paiowc->aiowc_pline);          /*  加入 wait 链表              */
                    iWait++;
                
                } else {
                    __aioDetachWait(LW_NULL, &paiowait[iWait]);         /*  删除关联关系                */
                    
                    iRet = PX_ERROR;
                }
            }
        }
    }
    
    if (iWait == 0) {                                                   /*  没有一个节点加入队列        */
        __aioDeleteWaitChain(paiowc);
        API_SemaphoreMPost(_G_aioqueue.aioq_mutex);
        
        if (mode == LIO_NOWAIT) {
            if (sig && __issig(sig->sigev_signo)) {
                _doSigEvent(API_ThreadIdSelf(), sig, SI_ASYNCIO);
            }
        }
        return  (ERROR_NONE);
    
    } else if (mode == LIO_WAIT) {                                      /*  需要等待                    */
        
        __aioWaitChainSetCnt(paiowc, &iWait);                           /*  设置计数变量                */
        
        while (iWait > 0) {
            if (API_ThreadCondWait(&paiowc->aiowc_cond, 
                                   _G_aioqueue.aioq_mutex, 
                                   LW_OPTION_WAIT_INFINITE)) {          /*  等待所有请求执行完毕        */
                break;
            }
        }
        
        __aioDeleteWaitChain(paiowc);                                   /*  清除 wait 队列              */
        
    } else {                                                            /*  LIO_NOWAIT                  */
        paiowc->aiowc_icnt = iWait;                                     /*  必须使用全局变量            */
        
        __aioWaitChainSetCnt(paiowc, &paiowc->aiowc_icnt);              /*  设置计数变量                */
    }
    
    API_SemaphoreMPost(_G_aioqueue.aioq_mutex);
                
    return  (iRet);
}