📄 siglib.c
字号:
* This routine waits until one of the signals specified in <pSet> is delivered* to the calling thread. It then stores the number of the signal received in* the the location pointed to by <pSig>.** The signals in <pSet> must not be ignored on entrance to sigwait().* If the delivered signal has a signal handler function attached, that* function is not called.** RETURNS: OK, or ERROR on failure.** SEE ALSO: sigtimedwait()*/ int sigwait ( const sigset_t *pSet, int *pSig ) { struct siginfo info; if (sigtimedwait(pSet, &info, (struct timespec *)NULL) == ERROR) return(ERROR); *pSig = info.si_signo; return(OK); }/********************************************************************************** sigvec - install a signal handler** This routine binds a signal handler routine referenced by <pVec> to a* specified signal <sig>. It can also be used to determine which handler,* if any, has been bound to a particular signal: sigvec() copies current* signal handler information for <sig> to <pOvec> and does not install a* signal handler if <pVec> is set to NULL (0).** Both <pVec> and <pOvec> are pointers to a structure of type \f3struct* sigvec\fP. The information passed includes not only the signal handler* routine, but also the signal mask and additional option bits. The* structure `sigvec' and the available options are defined in signal.h.** RETURNS: OK (0), or ERROR (-1) if the signal number is invalid or the* signal TCB cannot be allocated.** ERRNO: EINVAL, ENOMEM*/int sigvec ( int sig, /* signal to attach handler to */ const struct sigvec *pVec, /* new handler information */ struct sigvec *pOvec /* previous handler information */ ) { struct sigaction act, oact; int retVal; if (pVec != NULL) { act.sa_handler = pVec->sv_handler; act.sa_mask = pVec->sv_mask; act.sa_flags = pVec->sv_flags; retVal = sigaction(sig, &act, &oact); } else retVal = sigaction(sig, NULL, &oact); if (pOvec != NULL) { pOvec->sv_handler = oact.sa_handler; pOvec->sv_mask = oact.sa_mask; pOvec->sv_flags = oact.sa_flags; } return (retVal); }/********************************************************************************* sigreturn - early return from a signal handler** NOMANUAL**/void sigreturn ( struct sigcontext *pContext ) { (void) sigprocmask (SIG_SETMASK, &pContext->sc_mask, 0); _sigCtxLoad (&pContext->sc_regs); }/********************************************************************************* sigsetmask - set the signal mask** This routine sets the calling task's signal mask to a specified value.* A one (1) in the bit mask indicates that the specified signal is blocked* from delivery. Use the macro SIGMASK to construct the mask for a specified* signal number.** RETURNS: The previous value of the signal mask.** SEE ALSO: sigprocmask()*/ int sigsetmask ( int mask /* new signal mask */ ) { sigset_t in; sigset_t out; in = (sigset_t) mask; (void) sigprocmask (SIG_SETMASK, &in, &out); return ((int) out); }/********************************************************************************* sigblock - add to a set of blocked signals** This routine adds the signals in <mask> to the task's set of blocked signals.* A one (1) in the bit mask indicates that the specified signal is blocked* from delivery. Use the macro SIGMASK to construct the mask for a specified* signal number.** RETURNS: The previous value of the signal mask.** SEE ALSO: sigprocmask()*/ int sigblock ( int mask /* mask of additional signals to be blocked */ ) { sigset_t in; sigset_t out; in = (sigset_t) mask; (void) sigprocmask (SIG_BLOCK, &in, &out); return ((int) out); }/********************************************************************************* raise - send a signal to the caller's task** This routine sends the signal <signo> to the task invoking the call.** RETURNS: OK (0), or ERROR (-1) if the signal number or task ID is invalid.** ERRNO: EINVAL*/int raise ( int signo /* signal to send to caller's task */ ) { return (kill ((int) taskIdCurrent, signo)); }/********************************************************************************* kill - send a signal to a task (POSIX)** This routine sends a signal <signo> to the task specified by <tid>.** RETURNS: OK (0), or ERROR (-1) if the task ID or signal number is invalid.** ERRNO: EINVAL*/int kill ( int tid, /* task to send signal to */ int signo /* signal to send to task */ ) { if (!issig (signo)) { errnoSet (EINVAL); return (ERROR); }#ifdef WV_INSTRUMENTATION /* windview - level 1 event logging */ EVT_OBJ_SIG (EVENT_KILL , 2, signo, tid);#endif if (kernelState || (INT_CONTEXT () && (int) taskIdCurrent == tid)) { if (TASK_ID_VERIFY (tid) != OK) { errnoSet (EINVAL); return (ERROR); } excJobAdd ((VOIDFUNCPTR) kill, tid, signo, 0, 0, 0, 0); return (OK); } kernelState = TRUE; /* KERNEL ENTER */ if (TASK_ID_VERIFY (tid) != OK) /* verify task */ { windExit (); /* KERNEL EXIT */ errnoSet (EINVAL); return (ERROR); } sigWindKill ((WIND_TCB *) tid, signo); /* send signal */ windExit (); /* KERNEL EXIT */ return (OK); }/********************************************************************************* sigqueue - send a queued signal to a task* * The function sigqueue() sends the signal specified by <signo> with* the signal-parameter value specified by <value> to the process* specified by <tid>.** RETURNS: OK (0), or ERROR (-1) if the task ID or signal number is invalid,* or if there are no queued-signal buffers available.** ERRNO: EINVAL EAGAIN*/int sigqueue ( int tid, int signo, const union sigval value ) { struct sigpend pend; if (!issig (signo)) { errnoSet (EINVAL); return (ERROR); }#ifdef WV_INSTRUMENTATION /* windview - level 1 event logging */ EVT_OBJ_SIG (EVENT_KILL , 2, signo, tid);#endif if (kernelState || (INT_CONTEXT () && (int) taskIdCurrent == tid)) { if (TASK_ID_VERIFY (tid) != OK) { errnoSet (EINVAL); return (ERROR); } if (_pSigQueueFreeHead == NULL) { errnoSet (EAGAIN); return (ERROR); } excJobAdd ((VOIDFUNCPTR)sigqueue, tid, signo, value.sival_int, 0, 0, 0); return (OK); } kernelState = TRUE; /* KERNEL ENTER */ if (TASK_ID_VERIFY (tid) != OK) /* verify task */ { windExit (); /* KERNEL EXIT */ errnoSet (EINVAL); return (ERROR); } if (_pSigQueueFreeHead == NULL) { windExit (); /* KERNEL EXIT */ errnoSet (EAGAIN); return (ERROR); } sigPendInit (&pend); pend.sigp_info.si_signo = signo; pend.sigp_info.si_code = SI_QUEUE; pend.sigp_info.si_value = value; sigWindPendKill ((WIND_TCB *) tid, &pend); /* signal a task */ windExit (); /* KERNEL EXIT */ return (0); }/********************************************************************************* sigWrapper - trampoline code to get to users signal handler from kernel**/static void sigWrapper ( struct sigcontext *pContext ) { int signo = pContext->sc_info.si_signo; struct sigaction *pAction = &((taskIdCurrent->pSignalInfo))->sigt_vec[signo]; void (*handler)() = pAction->sa_handler;#ifdef WV_INSTRUMENTATION /* windview - level 1 event logging */ EVT_OBJ_SIG (EVENT_SIGWRAPPER, 2, signo, taskIdCurrent);#endif if (pAction->sa_flags & SA_RESETHAND) (void) signal (signo, SIG_DFL); if (handler != SIG_DFL && handler != SIG_IGN && handler != SIG_ERR) { if (pAction->sa_flags & SA_SIGINFO) (*handler) (signo, &pContext->sc_info, pContext); else (*handler) (signo, pContext->sc_info.si_value.sival_int, pContext); } sigreturn (pContext); }/********************************************************************************* sigTcbGet - get the pointer to the signal tcb** Get the pointer to the signal tcb. If there is no signal tcb, try and* allocate it.**/static struct sigtcb *sigTcbGet (void) { WIND_TCB *pTcb = taskIdCurrent; struct sigtcb *pSigTcb; int ix; if (INT_RESTRICT () != OK) return (NULL); /* errno was set */ if (pTcb->pSignalInfo != NULL) return (pTcb->pSignalInfo); pSigTcb = (struct sigtcb *) taskStackAllot((int) taskIdCurrent, sizeof (struct sigtcb)); if (pSigTcb == NULL) { errnoSet (ENOMEM); return (NULL); } pTcb->pSignalInfo = pSigTcb; bzero ((void *) pSigTcb, sizeof (struct sigtcb)); for (ix = 0; ix <= _NSIGS; ix++) pSigTcb->sigt_qhead[ix].sigq_next = pSigTcb->sigt_qhead[ix].sigq_prev = &pSigTcb->sigt_qhead[ix]; return (pSigTcb); }/********************************************************************************* sigPendRun - get a signal from the set of pending signals and run it** NOTE: YOU MUST BE IN THE KERNEL.*/static int sigPendRun ( struct sigtcb *pSigTcb ) { sigset_t set = ~pSigTcb->sigt_blocked; struct sigcontext sigCtx; int signo; if ((signo = sigPendGet (pSigTcb, &set, &sigCtx.sc_info)) > 0) { sigCtx.sc_onstack = 0; sigCtx.sc_restart = 0; sigCtx.sc_mask = pSigTcb->sigt_blocked; pSigTcb->sigt_blocked |= (pSigTcb->sigt_vec[signo].sa_mask | sigmask(signo));#if CPU_FAMILY == MC680X0 sigCtx.sc_fformat = 0;#endif windExit (); /* KERNEL EXIT */ if (_sigCtxSave (&sigCtx.sc_regs) == 0) { _sigCtxRtnValSet (&sigCtx.sc_regs, 1); sigWrapper (&sigCtx); } return (TRUE); } return (FALSE); }/********************************************************************************* sigPendGet - get a signal from the set of pending signals** NOTE: YOU MUST BE IN THE KERNEL.*/static int sigPendGet ( struct sigtcb *pSigTcb, const sigset_t *sigset, struct siginfo *info ) { long sig; long mask; struct sigpend *pSigpend; mask = *sigset & pSigTcb->sigt_pending; if (mask == 0) return (OK); mask &= -mask; /* find lowest bit set */ sig = ffsMsb (mask); if (mask & pSigTcb->sigt_kilsigs) { pSigTcb->sigt_kilsigs &= ~mask; info->si_signo = sig; info->si_code = SI_KILL; info->si_value.sival_int = 0; } else { pSigpend = structbase(struct sigpend, sigp_q, pSigTcb->sigt_qhead[sig].sigq_next); pSigpend->sigp_q.sigq_prev->sigq_next = pSigpend->sigp_q.sigq_next; pSigpend->sigp_q.sigq_next->sigq_prev = pSigpend->sigp_q.sigq_prev; pSigpend->sigp_q.sigq_next = NULL; pSigpend->sigp_q.sigq_prev = NULL; *info = pSigpend->sigp_info; pSigpend->sigp_overruns = pSigpend->sigp_active_overruns; pSigpend->sigp_active_overruns = 0; /* * free queued signal buffer */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -