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 >
C/C++ Source or Header  |  1990-12-28  |  5KB  |  180 lines

  1. /* Copyright 1990, Daniel J. Bernstein. All rights reserved. */
  2.  
  3. #include "config.h"
  4. #include <sys/time.h>
  5. #include "sig.h"
  6.  
  7. /* This is a stripped-down signal library, with automatic critical */
  8. /* sections around every signal handler. As long as no signal handler */
  9. /* has to pause waiting for another signal, this works beautifully */
  10. /* and prevents all races. */
  11.  
  12. static int queued[SIGNUM];
  13. static int quo[SIGNUM];
  14. static sig_syshandler orig[SIGNUM];
  15. static sig_handler handler[SIGNUM];
  16.  
  17. static sig_syshandler signalv(s,h)
  18. register sig_num s;
  19. register sig_syshandler h;
  20. {
  21.  return signal(s,h);
  22. }
  23.  
  24. static int crit = 0;
  25.  
  26. static void handle(i)
  27. register sig_num i;
  28. {
  29.  if (crit)
  30.    queued[i] = 1;
  31.  else
  32.   {
  33.    register int q;
  34.    register sig_num j;
  35.  
  36.    crit = 1; (void) handler[i](i); queued[i] = 0; crit = 0;
  37.    do for (j = q = 0;j < SIGNUM;j++) if (queued[j])
  38.     {
  39.      crit = q = 1;
  40.      if (j != i) (void) handler[j](j);
  41.      queued[j] = 0; crit = 0;
  42.     }
  43.    while (q);
  44.   }
  45. }
  46.  
  47. /* To see why handle() works: First, crit can be considered a local
  48. variable, because handle() is the only routine that modifies it, and
  49. handle() always leaves crit the same. Second, crit is 1 while any
  50. handler is called, and then any simultaneous handle()s will simply
  51. queue. Hence handlers are mutually exclusive. Third, when handle() is
  52. called with crit == 0, it can only exit after going through an entire j
  53. loop with no queued[]s true. Fourth, if all queued[]s are false through
  54. that j loop, then crit is not set by handle() during that loop. Finally,
  55. if crit is 0, handle() will exit with no queued signals: this is true by
  56. induction from the previous observations. */
  57.  
  58.  
  59. /* There is unfortunately no guarantee that a signal handler as */
  60. /* passed to signal() will receive its signal number as its first */
  61. /* argument. We do make that guarantee. */
  62.  
  63. #define HAN(s,h) SIGRET_TYPE h() { handle(s); }
  64.  
  65. HAN(0,han0);   HAN(1,han1);   HAN(2,han2);   HAN(3,han3);
  66. HAN(4,han4);   HAN(5,han5);   HAN(6,han6);   HAN(7,han7);
  67. HAN(8,han8);   HAN(9,han9);   HAN(10,han10); HAN(11,han11);
  68. HAN(12,han12); HAN(13,han13); HAN(14,han14); HAN(15,han15);
  69. HAN(16,han16); HAN(17,han17); HAN(18,han18); HAN(19,han19);
  70. HAN(20,han20); HAN(21,han21); HAN(22,han22); HAN(23,han23);
  71. HAN(24,han24); HAN(25,han25); HAN(26,han26); HAN(27,han27);
  72. HAN(28,han28); HAN(29,han29); HAN(30,han30); HAN(31,han31);
  73.  
  74. static sig_syshandler han[32] =
  75.   { han0 ,han1 ,han2 ,han3 ,han4 ,han5 ,han6 ,han7 ,
  76.     han8 ,han9 ,han10,han11,han12,han13,han14,han15,
  77.     han16,han17,han18,han19,han20,han21,han22,han23,
  78.     han24,han25,han26,han27,han28,han29,han30,han31
  79.   } ;
  80.  
  81. #define QUE(s,h) SIGRET_TYPE h() { quo[s] = 1; }
  82.  
  83. QUE(0,que0);   QUE(1,que1);   QUE(2,que2);   QUE(3,que3);
  84. QUE(4,que4);   QUE(5,que5);   QUE(6,que6);   QUE(7,que7);
  85. QUE(8,que8);   QUE(9,que9);   QUE(10,que10); QUE(11,que11);
  86. QUE(12,que12); QUE(13,que13); QUE(14,que14); QUE(15,que15);
  87. QUE(16,que16); QUE(17,que17); QUE(18,que18); QUE(19,que19);
  88. QUE(20,que20); QUE(21,que21); QUE(22,que22); QUE(23,que23);
  89. QUE(24,que24); QUE(25,que25); QUE(26,que26); QUE(27,que27);
  90. QUE(28,que28); QUE(29,que29); QUE(30,que30); QUE(31,que31);
  91.  
  92. static sig_syshandler que[32] =
  93.   { que0 ,que1 ,que2 ,que3 ,que4 ,que5 ,que6 ,que7 ,
  94.     que8 ,que9 ,que10,que11,que12,que13,que14,que15,
  95.     que16,que17,que18,que19,que20,que21,que22,que23,
  96.     que24,que25,que26,que27,que28,que29,que30,que31
  97.   } ;
  98.  
  99.  
  100. void sig_init()
  101. {
  102.  sig_num i;
  103.  
  104.  for (i = 0;i < SIGNUM;i++)
  105.    quo[i] = 0;
  106.  for (i = 0;i < SIGNUM;i++)
  107.    orig[i] = signalv(i,que[i]);
  108. }
  109.  
  110. void sig_restore()
  111. {
  112.  sig_num i;
  113.  
  114.  for (i = 0;i < SIGNUM;i++)
  115.    (void) signalv(i,orig[i]);
  116. }
  117.  
  118. void sig_handle(s)
  119. sig_num s;
  120. {
  121.  if (quo[s])
  122.    han[s]();
  123.  (void) signalv(s,han[s]);
  124.  quo[s] = 0;
  125. }
  126.  
  127. void sig_ignore(s)
  128. sig_num s;
  129. {
  130.  (void) signalv(s,SIG_IGN);
  131. }
  132.  
  133. void sig_default(s)
  134. sig_num s;
  135. {
  136.  (void) signalv(s,SIG_DFL);
  137. }
  138.  
  139. void sig_sethandler(s,h)
  140. sig_num s;
  141. sig_handler h;
  142. {
  143.  handler[s] = h;
  144. }
  145.  
  146. #ifdef SIGINTERRUPT
  147. void sig_interrupt()
  148. {
  149.  register sig_num s;
  150.  
  151.  for (s = 0;s < SIGNUM;s++)
  152.    (void) siginterrupt(s,1);
  153. }
  154. #endif
  155.  
  156. void sig_startring()
  157. {
  158.  struct itimerval it;
  159.  
  160.  it.it_value.tv_sec = it.it_interval.tv_sec = 0;
  161.  it.it_value.tv_usec = it.it_interval.tv_usec = 10000;
  162.  (void) setitimer(ITIMER_REAL,&it,(struct itimerval *) 0);
  163. }
  164.  
  165. void sig_stopring()
  166. {
  167.  struct itimerval it;
  168.  
  169.  it.it_value.tv_sec = it.it_interval.tv_sec = 0;
  170.  it.it_value.tv_usec = it.it_interval.tv_usec = 0;
  171.  (void) setitimer(ITIMER_REAL,&it,(struct itimerval *) 0);
  172. }
  173.  
  174. /*ARGSUSED*/
  175. void nothing(i)
  176. sig_num i;
  177. {
  178.  ; /* that's right, absolutely nothing. */
  179. }
  180.