home *** CD-ROM | disk | FTP | other *** search
- /* Copyright 1990, Daniel J. Bernstein. All rights reserved. */
-
- #include "config.h"
- #include <sys/time.h>
- #include "sig.h"
-
- /* This is a stripped-down signal library, with automatic critical */
- /* sections around every signal handler. As long as no signal handler */
- /* has to pause waiting for another signal, this works beautifully */
- /* and prevents all races. */
-
- static int queued[SIGNUM];
- static int quo[SIGNUM];
- static sig_syshandler orig[SIGNUM];
- static sig_handler handler[SIGNUM];
-
- static sig_syshandler signalv(s,h)
- register sig_num s;
- register sig_syshandler h;
- {
- return signal(s,h);
- }
-
- static int crit = 0;
-
- static void handle(i)
- register sig_num i;
- {
- if (crit)
- queued[i] = 1;
- else
- {
- register int q;
- register sig_num j;
-
- crit = 1; (void) handler[i](i); queued[i] = 0; crit = 0;
- do for (j = q = 0;j < SIGNUM;j++) if (queued[j])
- {
- crit = q = 1;
- if (j != i) (void) handler[j](j);
- queued[j] = 0; crit = 0;
- }
- while (q);
- }
- }
-
- /* To see why handle() works: First, crit can be considered a local
- variable, because handle() is the only routine that modifies it, and
- handle() always leaves crit the same. Second, crit is 1 while any
- handler is called, and then any simultaneous handle()s will simply
- queue. Hence handlers are mutually exclusive. Third, when handle() is
- called with crit == 0, it can only exit after going through an entire j
- loop with no queued[]s true. Fourth, if all queued[]s are false through
- that j loop, then crit is not set by handle() during that loop. Finally,
- if crit is 0, handle() will exit with no queued signals: this is true by
- induction from the previous observations. */
-
-
- /* There is unfortunately no guarantee that a signal handler as */
- /* passed to signal() will receive its signal number as its first */
- /* argument. We do make that guarantee. */
-
- #define HAN(s,h) SIGRET_TYPE h() { handle(s); }
-
- HAN(0,han0); HAN(1,han1); HAN(2,han2); HAN(3,han3);
- HAN(4,han4); HAN(5,han5); HAN(6,han6); HAN(7,han7);
- HAN(8,han8); HAN(9,han9); HAN(10,han10); HAN(11,han11);
- HAN(12,han12); HAN(13,han13); HAN(14,han14); HAN(15,han15);
- HAN(16,han16); HAN(17,han17); HAN(18,han18); HAN(19,han19);
- HAN(20,han20); HAN(21,han21); HAN(22,han22); HAN(23,han23);
- HAN(24,han24); HAN(25,han25); HAN(26,han26); HAN(27,han27);
- HAN(28,han28); HAN(29,han29); HAN(30,han30); HAN(31,han31);
-
- static sig_syshandler han[32] =
- { han0 ,han1 ,han2 ,han3 ,han4 ,han5 ,han6 ,han7 ,
- han8 ,han9 ,han10,han11,han12,han13,han14,han15,
- han16,han17,han18,han19,han20,han21,han22,han23,
- han24,han25,han26,han27,han28,han29,han30,han31
- } ;
-
- #define QUE(s,h) SIGRET_TYPE h() { quo[s] = 1; }
-
- QUE(0,que0); QUE(1,que1); QUE(2,que2); QUE(3,que3);
- QUE(4,que4); QUE(5,que5); QUE(6,que6); QUE(7,que7);
- QUE(8,que8); QUE(9,que9); QUE(10,que10); QUE(11,que11);
- QUE(12,que12); QUE(13,que13); QUE(14,que14); QUE(15,que15);
- QUE(16,que16); QUE(17,que17); QUE(18,que18); QUE(19,que19);
- QUE(20,que20); QUE(21,que21); QUE(22,que22); QUE(23,que23);
- QUE(24,que24); QUE(25,que25); QUE(26,que26); QUE(27,que27);
- QUE(28,que28); QUE(29,que29); QUE(30,que30); QUE(31,que31);
-
- static sig_syshandler que[32] =
- { que0 ,que1 ,que2 ,que3 ,que4 ,que5 ,que6 ,que7 ,
- que8 ,que9 ,que10,que11,que12,que13,que14,que15,
- que16,que17,que18,que19,que20,que21,que22,que23,
- que24,que25,que26,que27,que28,que29,que30,que31
- } ;
-
-
- void sig_init()
- {
- sig_num i;
-
- for (i = 0;i < SIGNUM;i++)
- quo[i] = 0;
- for (i = 0;i < SIGNUM;i++)
- orig[i] = signalv(i,que[i]);
- }
-
- void sig_restore()
- {
- sig_num i;
-
- for (i = 0;i < SIGNUM;i++)
- (void) signalv(i,orig[i]);
- }
-
- void sig_handle(s)
- sig_num s;
- {
- if (quo[s])
- han[s]();
- (void) signalv(s,han[s]);
- quo[s] = 0;
- }
-
- void sig_ignore(s)
- sig_num s;
- {
- (void) signalv(s,SIG_IGN);
- }
-
- void sig_default(s)
- sig_num s;
- {
- (void) signalv(s,SIG_DFL);
- }
-
- void sig_sethandler(s,h)
- sig_num s;
- sig_handler h;
- {
- handler[s] = h;
- }
-
- #ifdef SIGINTERRUPT
- void sig_interrupt()
- {
- register sig_num s;
-
- for (s = 0;s < SIGNUM;s++)
- (void) siginterrupt(s,1);
- }
- #endif
-
- void sig_startring()
- {
- struct itimerval it;
-
- it.it_value.tv_sec = it.it_interval.tv_sec = 0;
- it.it_value.tv_usec = it.it_interval.tv_usec = 10000;
- (void) setitimer(ITIMER_REAL,&it,(struct itimerval *) 0);
- }
-
- void sig_stopring()
- {
- struct itimerval it;
-
- it.it_value.tv_sec = it.it_interval.tv_sec = 0;
- it.it_value.tv_usec = it.it_interval.tv_usec = 0;
- (void) setitimer(ITIMER_REAL,&it,(struct itimerval *) 0);
- }
-
- /*ARGSUSED*/
- void nothing(i)
- sig_num i;
- {
- ; /* that's right, absolutely nothing. */
- }
-