home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Source Code 1992 March
/
Source_Code_CD-ROM_Walnut_Creek_March_1992.iso
/
usenet
/
altsrcs
/
1
/
1621
/
sig.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-12-28
|
5KB
|
180 lines
/* 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. */
}