#include #include #include #include "linuxsys.h" #include "linux.h" static struct { char *msg; /* just check prefix */ int num; } sigtab[] = { {"hangup", SIGHUP}, {"interrupt", SIGINT}, {"quit", SIGQUIT}, {"alarm", SIGALRM}, {"sys: trap: illegal instruction", SIGILL}, {"sys: trap: reserved instruction", SIGILL}, {"sys: trap: reserved", SIGILL}, {"sys: trap: arithmetic overflow", SIGFPE}, {"abort", SIGABRT}, {"sys: fp:", SIGFPE}, {"exit", SIGKILL}, {"die", SIGKILL}, {"kill", SIGKILL}, {"sys: trap: bus error", SIGSEGV}, {"sys: trap: address error", SIGSEGV}, {"sys: trap: TLB", SIGSEGV}, {"sys: write on closed pipe", SIGPIPE}, {"alarm", SIGALRM}, {"term", SIGTERM}, {"usr1", SIGUSR1}, {"usr2", SIGUSR2}, {"rt1", SIGRT1}, {"rt2", SIGRT2}, {"rt3", SIGRT3}, {"rt4", SIGRT4}, {"rt5", SIGRT5}, {"rt6", SIGRT6}, {"rt7", SIGRT7}, {"rt8", SIGRT8}, {"tstp", SIGTSTP}, {"ttin", SIGTTIN}, {"ttou", SIGTTOU}, {"stop", SIGSTOP}, {"start", SIGCONT}, }; #define NSIGTAB ((sizeof sigtab)/(sizeof (sigtab[0]))) int stringsig(char *msg) { int i; for(i=0; iaction[sig-1].handler; if((ulong)h > 2){ ss->blocked |= ss->action[sig-1].blocked; callsignal(sig, h); ss->blocked = rblocked; } } static int sigenqueue(Sigqueue *q, int sig, void *info) { int a, i; a = i = q->wp; i = (i + 1) & (SIGQUEUESIZE - 1); if(i == q->rp) return 0; assert(q->e[a].sig == 0); q->e[a].sig = sig; q->e[a].info = info; q->wp = i; return 1; } static int sigdequeue(Sigqueue *q, int *psig, void **pinfo, uvlong blocked) { int i, a; a = i = q->rp; for(;;){ if(i == q->wp) return 0; if(!((1LL << (q->e[i].sig-1)) & blocked)) break; i = (i + 1) & (SIGQUEUESIZE - 1); } if(psig) *psig = q->e[i].sig; if(pinfo) *pinfo = q->e[i].info; q->e[i].sig = 0; if(i == a) q->rp = (i + 1) & (SIGQUEUESIZE - 1); return 1; } static uvlong sigpeekqueue(Sigqueue *q) { int i; uvlong m; m = 0LL; for(i = q->rp; i != q->wp; i = (i + 1) & (SIGQUEUESIZE - 1)) m |= 1LL << (q->e[i].sig-1); return m; } void sigprocess(Sigstate *ss) { int sig; void *info; uvlong rblocked; if(ss->level) return; for(sig=1; sig<=32; sig++){ ulong m; m = 1 << (sig-1); if((m & ss->pending) == 0) continue; rblocked = ss->blocked; if(m & rblocked) continue; info = ss->info[sig-1]; ss->pending &= ~m; dosig(ss, sig, info, rblocked); } for(;;){ rblocked = ss->blocked; if(!sigdequeue(&ss->rtsq, &sig, &info, rblocked)) break; dosig(ss, sig, info, rblocked); } } uvlong sigpending(Sigstate *ss) { uvlong m; m = (uvlong)ss->pending; m |= sigpeekqueue(&ss->rtsq); return m; } void sigclearall(Sigstate *ss) { ss->pending = 0; ss->rtsq.rp = ss->rtsq.wp = 0; } void sigdisable(Sigstate *ss) { _xinc(&ss->level); } void sigenable(Sigstate *ss) { if(!_xdec(&ss->level)) sigprocess(ss); } int signote(Sigstate *ss, char *msg) { int sig; void *info; if((sig = stringsig(msg)) < 1) return 0; info = nil; if(sig <= 32){ ulong m; m = 1<<(sig-1); if(m & ss->pending){ fprint(2, "signal %d lost!\n", sig); return 1; } ss->info[sig-1] = info; ss->pending |= m; } else { if(!sigenqueue(&ss->rtsq, sig, info)) fprint(2, "rt signal %d lost!\n", sig); } return 1; }