📄 siglib.c
字号:
if (pSigpend->sigp_info.si_code == SI_QUEUE) { *(struct sigpend **)pSigpend = _pSigQueueFreeHead; _pSigQueueFreeHead = pSigpend; } } if (pSigTcb->sigt_qhead[sig].sigq_next == &pSigTcb->sigt_qhead[sig]) pSigTcb->sigt_pending &= ~mask; return (sig); }/********************************************************************************* sigWindPendKill - add a signal to the set of pending signals** NOTE: YOU MUST BE IN THE KERNEL.*/static void sigWindPendKill ( WIND_TCB *pTcb, struct sigpend *pSigPend ) { int signo = pSigPend->sigp_info.si_signo; struct sigtcb *pSigTcb; void (*func)(); unsigned mask; /* * Check to see if the task has the signal structure. If it does * not, we pretend the task is ignoring them. */ if ((pSigTcb = pTcb->pSignalInfo) == NULL) return; /* * If task is waiting for signal, deliver it by waking up the task. */ if ((pSigTcb->sigt_wait != NULL) && (sigismember(&pSigTcb->sigt_wait->sigw_set, signo) == 1) && (Q_FIRST(&pSigTcb->sigt_wait->sigw_wait) != NULL)) { pSigTcb->sigt_wait->sigw_info = pSigPend->sigp_info;#ifdef WV_INSTRUMENTATION /* windview - level 2 event logging */ EVT_TASK_1 (EVENT_OBJ_SIGKILL, pTcb); /* log event */#endif windPendQGet (&pSigTcb->sigt_wait->sigw_wait); /* * Mark task as no longer waiting */ pSigTcb->sigt_wait = NULL; return; } /* * The default action for signals is to ignore them, in posix * it is to kill the process. */ func = pSigTcb->sigt_vec[signo].sa_handler; if (func == SIG_DFL) return; /* should maybe kill the task */ /* * Check to see if signal should be ignored. */ if (func == SIG_IGN) return; /* * Check to see if signal should be queued up because they are being * blocked. */ mask = sigmask(signo); if (pSigTcb->sigt_blocked & mask) { /* * kill signals just get a bit to say a signal has come */ if (pSigPend->sigp_info.si_code == SI_KILL) { pSigTcb->sigt_kilsigs |= mask; pSigTcb->sigt_pending |= mask; } /* * if the signal is all ready queued, mark it as overrun */ else if (pSigPend->sigp_q.sigq_next != NULL) pSigPend->sigp_active_overruns++; /* * must be a signal to queue */ else { struct sigq *head = &pSigTcb->sigt_qhead[signo]; /* * alloc buffer for sigqueue */ if (pSigPend->sigp_info.si_code == SI_QUEUE) { struct sigpend *pTmp = _pSigQueueFreeHead; _pSigQueueFreeHead = *(struct sigpend **)_pSigQueueFreeHead; *pTmp = *pSigPend; pSigPend = pTmp; } pSigPend->sigp_q.sigq_prev = head->sigq_prev; pSigPend->sigp_q.sigq_next = head; pSigPend->sigp_q.sigq_prev->sigq_next = &pSigPend->sigp_q; head->sigq_prev = &pSigPend->sigp_q; pSigTcb->sigt_pending |= mask; pSigPend->sigp_tcb = pSigTcb; } return; } /* * Force delivery of the signal. */ if (taskIdCurrent != pTcb) { int args[2]; struct sigcontext *pCtx;#if _STACK_DIR == _STACK_GROWS_DOWN pCtx = (struct sigcontext *) MEM_ROUND_DOWN (((struct sigcontext *)_sigCtxStackEnd (&pTcb->regs)) - 1);#else taskRegsStackToTcb (pTcb); pCtx = (struct sigcontext *) MEM_ROUND_UP(_sigCtxStackEnd (&pTcb->regs));#endif args[0] = 1; args[1] = (int)pCtx; /* * Mark task as no longer waiting */ pSigTcb->sigt_wait = NULL; pCtx->sc_onstack = 0; pCtx->sc_restart = sigWindRestart (pTcb); pCtx->sc_mask = pSigTcb->sigt_blocked; pSigTcb->sigt_blocked |= (pSigTcb->sigt_vec[signo].sa_mask | mask); pCtx->sc_info = pSigPend->sigp_info; pCtx->sc_regs = pTcb->regs;#if CPU_FAMILY == MC680X0 pCtx->sc_fformat = pTcb->foroff;#endif#if CPU == I960KB bcopy (pTcb->intResumptionRec, pCtx->sc_resumption, 16);#endif pCtx->sc_pregs = pSigPend->sigp_pregs;#if _STACK_DIR == _STACK_GROWS_DOWN _sigCtxSetup (&pTcb->regs, (void *)STACK_ROUND_DOWN(pCtx), sigWrapper, args);#else _sigCtxSetup (&pTcb->regs, (void *)STACK_ROUND_UP(pCtx + 1), sigWrapper, args);#endif } else { struct sigcontext Ctx; Ctx.sc_onstack = 0; Ctx.sc_restart = 0; Ctx.sc_mask = pSigTcb->sigt_blocked; pSigTcb->sigt_blocked |= (pSigTcb->sigt_vec[signo].sa_mask | mask); Ctx.sc_info = pSigPend->sigp_info;#if CPU_FAMILY == MC680X0 Ctx.sc_fformat = pTcb->foroff;#endif#if CPU == I960KB bcopy (pTcb->intResumptionRec, Ctx.sc_resumption, 16);#endif Ctx.sc_pregs = pSigPend->sigp_pregs; windExit (); /* KERNEL EXIT */ if (_sigCtxSave(&Ctx.sc_regs) == 0) { _sigCtxRtnValSet (&Ctx.sc_regs, 1); sigWrapper(&Ctx); } kernelState = TRUE; /* KERNEL ENTER */ } }/********************************************************************************* sigPendKill - send a queue signal** NOMANUAL** RETURNS: nothing*/int sigPendKill ( int tid, struct sigpend *pSigPend ) {#if 0 /* * for now, blindly assume it is valid. */ if (!issig (pSigPend)) { errnoSet (EINVAL); return (ERROR); }#endif if (kernelState || (INT_CONTEXT () && (int) taskIdCurrent == tid)) { if (TASK_ID_VERIFY (tid) != OK) { errnoSet (EINVAL); return (ERROR); } excJobAdd ((VOIDFUNCPTR) sigPendKill, tid, (int) pSigPend, 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); } sigWindPendKill ((WIND_TCB *) tid, pSigPend); /* signal a task */ windExit (); /* KERNEL EXIT */ return (OK); }/********************************************************************************* sigPendInit - init a queue signal** NOMANUAL** RETURNS: nothing*/void sigPendInit ( struct sigpend *pSigPend ) { pSigPend->sigp_q.sigq_prev = pSigPend->sigp_q.sigq_next = NULL; pSigPend->sigp_overruns = 0; pSigPend->sigp_pregs = NULL; }/********************************************************************************* sigPendDestroy - destory a queue signal** NOMANUAL** RETURNS: OK or ERROR*/int sigPendDestroy ( struct sigpend *pSigPend ) { if (INT_RESTRICT () != OK) return (ERROR); pSigPend->sigp_overruns = 0; kernelState = TRUE; /* KERNEL ENTER */ if (pSigPend->sigp_q.sigq_next != 0) { /* * Clear sigpending if last one on chain. (and there was no kilsigs) */ if (pSigPend->sigp_q.sigq_next == pSigPend->sigp_q.sigq_prev) pSigPend->sigp_tcb->sigt_pending &= (pSigPend->sigp_tcb->sigt_kilsigs | ~sigmask(pSigPend->sigp_info.si_signo)); pSigPend->sigp_q.sigq_next->sigq_prev = pSigPend->sigp_q.sigq_prev; pSigPend->sigp_q.sigq_prev->sigq_next = pSigPend->sigp_q.sigq_next; pSigPend->sigp_q.sigq_prev = pSigPend->sigp_q.sigq_next = NULL; } windExit (); /* KERNEL EXIT */ return (OK); }/********************************************************************************* sigWindKill - do the dirty work of sending a signal.** NOTE: YOU MUST BE IN THE KERNEL.*/static void sigWindKill ( WIND_TCB *pTcb, int signo ) { struct sigpend pend; pend.sigp_info.si_signo = signo; pend.sigp_info.si_code = SI_KILL; pend.sigp_info.si_value.sival_int = 0; sigWindPendKill(pTcb, &pend); }/********************************************************************************* sigWindRestart - test the state of a task** Test the state of a task you are sending a signal to. If it is* pended, tell it to restart itself after it has returned.** NOTE: YOU MUST BE IN THE KERNEL.*/static int sigWindRestart ( WIND_TCB *pTcb ) { int delay = WAIT_FOREVER; int status; /* Q_REMOVE return value */ if ((pTcb->status & (WIND_PEND | WIND_DELAY)) != 0) { taskRtnValueSet (pTcb, RESTART); if ((pTcb->status & WIND_DELAY) != 0) { pTcb->status &= ~WIND_DELAY; Q_REMOVE (&tickQHead, &pTcb->tickNode); /* remove from queue */ delay = Q_KEY (&tickQHead, &pTcb->tickNode, 1); } if ((pTcb->status & WIND_PEND) != 0) { pTcb->pPriMutex = NULL; /* clear pPriMutex */ pTcb->status &= ~WIND_PEND; /* turn off pend bit */ status = Q_REMOVE (pTcb->pPendQ, pTcb); /* out of pend queue */ /* * If task was pended on a shared semaphore its shared TCB * could have been remove by a semGive on another CPU. In that * case Q_REMOVE returns ALREADY_REMOVED, What we have to do * is set task return value to OK to avoid task to be restarted. * Q_REMOVE can also return ERROR if it was unable to take * the shared semaphore lock to remove the shared TCB. * In that case we set task return value to ERROR and * errorStatus to S_smObjLib_LOCK_TIMEOUT. */ switch (status) { case ALREADY_REMOVED : { taskRtnValueSet (pTcb, OK); break; } case ERROR : { taskRtnValueSet (pTcb, ERROR); pTcb->errorStatus = S_smObjLib_LOCK_TIMEOUT; break; } } } if (pTcb->status == WIND_READY) /* task is now ready */ Q_PUT (&readyQHead, pTcb, pTcb->priority); } return (delay); }/********************************************************************************* sigExcSend - signal a task that has an exception** RETURNS: nothing*/static void sigExcSend ( int signo, int code, REG_SET *pRegSet ) { struct sigpend pend; REG_SET *pTmpRegSet; pTmpRegSet = taskIdCurrent->pExcRegSet; taskIdCurrent->pExcRegSet = 0; sigPendInit (&pend); pend.sigp_info.si_signo = signo; pend.sigp_info.si_code = SI_SYNC; pend.sigp_info.si_value.sival_int = code; pend.sigp_pregs = pRegSet; sigPendKill ((int) taskIdCurrent, &pend); sigPendDestroy (&pend); taskIdCurrent->pExcRegSet = pTmpRegSet; }/********************************************************************************* sigExcKill - signal a task that has an exception** RETURNS: nothing*/static void sigExcKill ( int faultType, int code, REG_SET *pRegSet ) { extern struct sigfaulttable _sigfaulttable[]; struct sigfaulttable *pFTab; for (pFTab = &_sigfaulttable[0]; !((pFTab->sigf_fault == 0) && (pFTab->sigf_signo == 0)); pFTab++) { if (pFTab->sigf_fault == faultType) { sigExcSend (pFTab->sigf_signo, code, pRegSet); return; } } /* not found in the table */ if (pFTab->sigf_signo != 0) sigExcSend (pFTab->sigf_signo, code, pReg
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -