📄 siglib.c
字号:
.pG "Basic OS"*/#include "vxWorks.h"#include "private/sigLibP.h"#include "private/windLibP.h"#include "private/taskLibP.h"#include "private/kernelLibP.h"#include "private/funcBindP.h"#include "taskHookLib.h"#include "errnoLib.h"#include "intLib.h"#include "qFifoGLib.h"#include "stddef.h"#include "stdlib.h"#include "string.h"#include "excLib.h"#include "smObjLib.h"#include "taskArchLib.h"#include "timers.h"#include "private/eventP.h"#include "sysLib.h"#define __PTHREAD_SRC#include "pthread.h"/* * Given a structure type, a member, and a pointer to that member, find the * pointer to the structure. */#define structbase(s,m,p) ((s *)((char *)(p) - offsetof(s,m)))#define issig(m) (1 <= (m) && (m) <= _NSIGS)struct sigwait { sigset_t sigw_set; struct siginfo sigw_info; Q_HEAD sigw_wait; };#if CPU_FAMILY != I960extern int ffsMsb (unsigned long); /* not in any header */#endif/* global variables */#ifdef WV_INSTRUMENTATIONVOIDFUNCPTR sigEvtRtn; /* windview - level 1 event logging */#endif/* static variables */struct sigpend *_pSigQueueFreeHead;/* forward static functions */static void sigWindPendKill (WIND_TCB *, struct sigpend *);static struct sigtcb *sigTcbGet (void);static void sigWindKill (WIND_TCB *pTcb, int signo);static int sigWindRestart (WIND_TCB *pTcb);static int sigTimeoutRecalc(int i);static void sigDeleteHook (WIND_TCB *pNewTcb);static void sigWrapper (struct sigcontext *pContext);static int sigPendRun (struct sigtcb *pSigTcb);static int sigPendGet (struct sigtcb *pSigTcb, const sigset_t *sigset, struct siginfo *info);static void sigExcKill (int faultType, int faultSubtype, REG_SET *pRegSet);/********************************************************************************* sigInit - initialize the signal facilities** This routine initializes the signal facilities. It is usually called from* the system start-up routine usrInit() in usrConfig, before interrupts are* enabled.** RETURNS: OK, or ERROR if the delete hooks cannot be installed.** ERRNO: S_taskLib_TASK_HOOK_TABLE_FULL*/int sigInit (void) { static BOOL sigInstalled = FALSE; if (!sigInstalled) { _func_sigTimeoutRecalc = sigTimeoutRecalc; _func_sigExcKill = sigExcKill; _func_sigprocmask = sigprocmask; if (taskDeleteHookAdd ((FUNCPTR) sigDeleteHook) == ERROR) return (ERROR);/* FIXME-PR I do not think sigEvtRtn should be initialized here * It is also initialize in wvLib.c and that should be enough */#if 0 #ifdef WV_INSTRUMENTATION /* windview instrumentation - level 1 */ if (WV_EVTCLASS_IS_SET(WV_CLASS_3)) /* connect event logging routine */ sigEvtRtn = _func_evtLogOIntLock; else sigEvtRtn = NULL; /* disconnect event logging */#endif#endif sigInstalled = TRUE; } return (OK); }/********************************************************************************* sigqueueInit - initialize the queued signal facilities** This routine initializes the queued signal facilities. It must* be called before any call to sigqueue(). It is usually* called from the system start-up routine usrInit() in usrConfig,* after sysInit() is called.** It allocates <nQueues> buffers to be used by sigqueue(). A buffer is* used by each call to sigqueue() and freed when the signal is delivered* (thus if a signal is block, the buffer is unavailable until the signal* is unblocked.)** RETURNS: OK, or ERROR if memory could not be allocated.*/int sigqueueInit ( int nQueues ) { static BOOL sigqueueInstalled = FALSE; struct sigpend *p; if (!sigqueueInstalled) { if (nQueues < 1) return (ERROR); if ((p = (struct sigpend *)malloc(nQueues * sizeof(struct sigpend))) == NULL) return (ERROR); while (nQueues-- > 0) { *(struct sigpend **)p= _pSigQueueFreeHead; _pSigQueueFreeHead = p; p++; } sigqueueInstalled = TRUE; } return (OK); }/********************************************************************************* sigDeleteHook - task delete hook for signal facility** Cleanup any signals a task has hanging on it before the task gets* deleted.** RETURNS: Nothing.*/static void sigDeleteHook ( WIND_TCB *pTcb /* pointer to old task's TCB */ ) { struct sigtcb *pSigTcb = pTcb->pSignalInfo; struct sigpend *pSigPend; struct sigq *pSigQ; int ix; /* * If I never got any signals, nothing to clean up */ if (pSigTcb == NULL) return; kernelState = TRUE; /* KERNEL ENTER */ for (ix = 0; ix <= _NSIGS; ix++) { pSigQ = pSigTcb->sigt_qhead[ix].sigq_next; while (pSigQ != &pSigTcb->sigt_qhead[ix]) { pSigPend = structbase(struct sigpend, sigp_q, pSigQ); pSigQ = pSigQ->sigq_next; pSigPend->sigp_q.sigq_next = pSigPend->sigp_q.sigq_prev = NULL; /* * free queued signal buffer */ if (pSigPend->sigp_info.si_code == SI_QUEUE) { *(struct sigpend **)pSigPend = _pSigQueueFreeHead; _pSigQueueFreeHead = pSigPend; } } } windExit (); /* KERNEL EXIT */ }/********************************************************************************* sigTimeoutRecalc - Compute the new timeout when a function restarts** Compute the new timeout when a function restarts. For example, a* task pends on a semTake() with a timeout, receives a signal, runs the signal* handler, and then goes back to waiting on the semTake(). What timeout* should it use when it blocks? In this example, it uses the original* timeout passed to semTake().** RETURNS: The new timeout value.*/static int sigTimeoutRecalc ( int timeout /* original timeout value */ ) { return (timeout); }/********************************************************************************* sigemptyset - initialize a signal set with no signals included (POSIX)** This routine initializes the signal set specified by <pSet>, * such that all signals are excluded.** RETURNS: OK (0), or ERROR (-1) if the signal set cannot be initialized.** ERRNO: No errors are detectable.*/int sigemptyset ( sigset_t *pSet /* signal set to initialize */ ) { *pSet = 0; return (OK); }/********************************************************************************* sigfillset - initialize a signal set with all signals included (POSIX)** This routine initializes the signal set specified by <pSet>, such that* all signals are included.** RETURNS: OK (0), or ERROR (-1) if the signal set cannot be initialized.** ERRNO: No errors are detectable.*/int sigfillset ( sigset_t *pSet /* signal set to initialize */ ) { *pSet = 0xffffffff; return (OK); }/********************************************************************************* sigaddset - add a signal to a signal set (POSIX)** This routine adds the signal specified by <signo> to the signal set * specified by <pSet>.** RETURNS: OK (0), or ERROR (-1) if the signal number is invalid.** ERRNO: EINVAL*/int sigaddset ( sigset_t *pSet, /* signal set to add signal to */ int signo /* signal to add */ ) { if (issig (signo)) { *pSet |= sigmask (signo); return (OK); } errnoSet (EINVAL); return (ERROR); }/********************************************************************************* sigdelset - delete a signal from a signal set (POSIX)** This routine deletes the signal specified by <signo> from the signal set* specified by <pSet>.** RETURNS: OK (0), or ERROR (-1) if the signal number is invalid.** ERRNO: EINVAL*/int sigdelset ( sigset_t *pSet, /* signal set to delete signal from */ int signo /* signal to delete */ ) { if (issig (signo)) { *pSet &= ~sigmask (signo); return (OK); } errnoSet (EINVAL); return (ERROR); }/********************************************************************************* sigismember - test to see if a signal is in a signal set (POSIX)** This routine tests whether the signal specified by <signo> is* a member of the set specified by <pSet>.** RETURNS: 1 if the specified signal is a member of the specified set, OK* (0) if it is not, or ERROR (-1) if the test fails.* * ERRNO: EINVAL*/int sigismember ( const sigset_t *pSet, /* signal set to test */ int signo /* signal to test for */ ) { if (issig (signo)) return ((*pSet & sigmask (signo)) != 0); errnoSet (EINVAL); return (ERROR); }/********************************************************************************* signal - specify the handler associated with a signal** This routine chooses one of three ways in which receipt of the signal* number <signo> is to be subsequently handled. If the value of <pHandler> is* SIG_DFL, default handling for that signal will occur. If the value of* <pHandler> is SIG_IGN, the signal will be ignored. Otherwise, <pHandler>* must point to a function to be called when that signal occurs.** RETURNS: The value of the previous signal handler, or SIG_ERR.*/void (*signal ( int signo, void (*pHandler) () )) () { struct sigaction in, out; in.sa_handler = pHandler; in.sa_flags = 0; (void) sigemptyset (&in.sa_mask); return ((sigaction (signo, &in, &out) == ERROR) ? SIG_ERR : out.sa_handler); }/********************************************************************************* sigaction - examine and/or specify the action associated with a signal (POSIX)** This routine allows the calling process to examine and/or specify* the action to be associated with a specific signal.** RETURNS: OK (0), or ERROR (-1) if the signal number is invalid.** ERRNO: EINVAL*/int sigaction ( int signo, /* signal of handler of interest */ const struct sigaction *pAct, /* location of new handler */ struct sigaction *pOact /* location to store old handler */ ) { struct sigtcb *pSigTcb; struct sigaction *pSigAction; struct sigpend *pSigPend; struct sigq *pSigQ; if (!issig (signo)) { errnoSet (EINVAL); return (ERROR); } if ((pSigTcb = sigTcbGet ()) == NULL) return (ERROR); /* errno was set */#ifdef WV_INSTRUMENTATION /* windview - level 1 event logging */ EVT_OBJ_SIG (EVENT_SIGNAL, 2, signo, ((int) pAct->sa_handler));#endif pSigAction = &pSigTcb->sigt_vec[signo]; if (pOact != NULL) *pOact = *pSigAction; if (pAct != NULL) { kernelState = TRUE; /* KERNEL ENTER */ *pSigAction = *pAct; /* * if the new action is to ignore, then any pending * signals must be removed. */ if (pSigAction->sa_handler == SIG_IGN) { sigdelset (&pSigTcb->sigt_pending, signo); sigdelset (&pSigTcb->sigt_kilsigs, signo); /* XXX need to destroy queued signals */ pSigQ = pSigTcb->sigt_qhead[signo].sigq_next; while (pSigQ != &pSigTcb->sigt_qhead[signo]) { pSigPend = structbase(struct sigpend, sigp_q, pSigQ); pSigQ = pSigQ->sigq_next; pSigPend->sigp_q.sigq_next = pSigPend->sigp_q.sigq_prev = NULL; /* * free queued signal buffer */ if (pSigPend->sigp_info.si_code == SI_QUEUE)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -