home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gnat-2.06-src.tgz / tar.out / fsf / gnat / ada / threads / src / signal.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  59KB  |  2,341 lines

  1. /* Copyright (C) 1992, the Florida State University
  2.    Distributed by the Florida State University under the terms of the
  3.    GNU Library General Public License.
  4.  
  5. This file is part of Pthreads.
  6.  
  7. Pthreads is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU Library General Public
  9. License as published by the Free Software Foundation (version 2).
  10.  
  11. Pthreads is distributed "AS IS" in the hope that it will be
  12. useful, but WITHOUT ANY WARRANTY; without even the implied
  13. warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. See the GNU Library General Public License for more details.
  15.  
  16. You should have received a copy of the GNU Library General Public
  17. License along with Pthreads; see the file COPYING.  If not, write
  18. to the Free Software Foundation, 675 Mass Ave, Cambridge,
  19. MA 02139, USA.
  20.  
  21. Report problems and direct all questions to:
  22.  
  23.   pthreads-bugs@ada.cs.fsu.edu
  24.  
  25.   @(#)signal.c    2.5 4/12/95
  26.  
  27. */
  28.  
  29. /* 
  30.  * Functions for the handling of signals and timers.
  31.  */
  32.  
  33. /*
  34.  * The DEBUG flag causes a message to be printed out during signal handling.
  35.  * The IO flag handles I/O requests asynchronously such that a signal is
  36.  * delivered to the process upon completion of the operation.
  37.  * If both flags are set at the same time, the signal handler would issue
  38.  * an I/O request for each invocation which in turns causes another signal
  39.  * to be delivered to yet another instance of the signal handler.
  40.  * To avoid this, messages are only printed if DEBUG is defined but not IO.
  41.  */
  42.  
  43. #define PTHREAD_KERNEL
  44. #include "pthread_setjmp.h"
  45. #include "pthread_offsets.h"
  46. #include "signal_internals.h"
  47. #include "pthread_internals.h"
  48. #include <sys/syscall.h>
  49.  
  50. #if defined(SOLARIS) && defined(IO)
  51. #include <dlfcn.h>
  52. #endif SOLARIS && IO
  53.  
  54. #ifdef NOERR_CHECK
  55. #undef NOERR_CHECK
  56. #include "mutex.h"
  57. #define NOERR_CHECK
  58. #else !NOERR_CHECK
  59. #include "mutex.h"
  60. #endif NOERR_CHECK
  61.  
  62. #ifdef STAND_ALONE
  63. #include <sun4e/counter.h>
  64. extern char heap_start;
  65. #endif STAND_ALONE
  66.  
  67. #ifdef RAND_SWITCH 
  68. extern int pthread_n_ready;
  69. #endif
  70.  
  71. #ifdef TIMER_DEBUG
  72. static struct timeval last_alarm;
  73. #endif
  74.  
  75. #if defined(STACK_CHECK) && defined(SIGNAL_STACK)
  76. extern int pthread_page_size;
  77. extern KERNEL_STACK pthread_tempstack;
  78. #endif
  79.  
  80. #ifdef STAND_ALONE
  81. pthread_timer_q_t pthread_timer;              /* timer queue                 */
  82. #else
  83. pthread_timer_q pthread_timer;                /* timer queue                 */
  84. static struct itimerval it;                   /* timer structure             */
  85. #endif
  86. struct sigaction pthread_user_handler[NNSIG]; /* user signal handlers        */
  87. volatile int new_code[NNSIG];                 /* UNIX signal code (new sigs) */
  88. static int pending_code[NNSIG];               /* UNIX signal code (pending)  */
  89. static sigset_t synchronous;                  /* set of synchronous signals  */
  90. static sigset_t sig_handling;                 /* set of signals being handled*/
  91.  
  92. /*------------------------------------------------------------*/
  93. /*
  94.  * pthread_sigcpyset2set - add a signal set to another one
  95.  */
  96. void pthread_sigcpyset2set(dst, src)
  97. int *dst, *src;
  98. {
  99.   int i;
  100.  
  101.   for (i = 0; i < sizeof(sigset_t); i += sizeof(int))
  102.     *(dst++) = *(src++);
  103. }
  104.  
  105. /*------------------------------------------------------------*/
  106. /*
  107.  * pthread_sigaddset2set - add a signal set to another one
  108.  */
  109. void pthread_sigaddset2set(dst, src)
  110. int *dst, *src;
  111. {
  112.   int i;
  113.  
  114.   for (i = 0; i < sizeof(sigset_t); i += sizeof(int))
  115.     *(dst++) |= *(src++);
  116. }
  117.  
  118. /*------------------------------------------------------------*/
  119. /*
  120.  * pthread_sigdelset2set - delete a signal set from another one
  121.  */
  122. void pthread_sigdelset2set(dst, src)
  123. int *dst, *src;
  124. {
  125.   int i;
  126.  
  127.   for (i = 0; i < sizeof(sigset_t); i += sizeof(int))
  128.     *(dst++) &= ~(*(src++));
  129. }
  130.  
  131. /*------------------------------------------------------------*/
  132. /*
  133.  * pthread_sigismemberset2set - check if two sets overlap
  134.  */
  135. int pthread_sigismemberset2set(dst, src)
  136. int *dst, *src;
  137. {
  138.   int i;
  139.  
  140.   for (i = 0; i < sizeof(sigset_t); i += sizeof(int))
  141.     if (*(dst++) & *(src++))
  142.       return(TRUE);
  143.  
  144.   return(FALSE);
  145. }
  146.  
  147. /*------------------------------------------------------------*/
  148. /*
  149.  * pthread_signonemptyset - check if a set has any bits set
  150.  */
  151. int pthread_signonemptyset(set)
  152. int *set;
  153. {
  154.   int i;
  155.  
  156.   for (i = 0; i < sizeof(sigset_t); i += sizeof(int))
  157.     if (*(set++))
  158.       return(TRUE);
  159.  
  160.   return(FALSE);
  161. }
  162.  
  163. /*------------------------------------------------------------*/
  164. /*
  165.  * pthread_siggeset2set - check if dst set is >= src set, i.e.
  166.  * dst has at least the bits set which src has set
  167.  */
  168. int pthread_siggeset2set(dst, src)
  169. int *dst, *src;
  170. {
  171.   int i;
  172.  
  173.   for (i = 0; i < sizeof(sigset_t); i += sizeof(int))
  174.     if ((*(dst++) & *(src)) != *(src++))
  175.       return(FALSE);
  176.  
  177.   return(TRUE);
  178. }
  179.  
  180. /*------------------------------------------------------------*/
  181. /*
  182.  * pthread_sigeqset2set - check if dst set is == src set
  183.  */
  184. int pthread_sigeqset2set(dst, src)
  185. int *dst, *src;
  186. {
  187.   int i;
  188.  
  189.   for (i = 0; i < sizeof(sigset_t); i += sizeof(int))
  190.     if (*(dst++) != *(src++))
  191.       return(FALSE);
  192.  
  193.   return(TRUE);
  194. }
  195.  
  196. #ifndef STAND_ALONE
  197. /*------------------------------------------------------------*/
  198. /*
  199.  * pthread_clear_sighandler - get rid of universal signal handler for all
  200.  * signals except for those which cannot be masked;
  201.  * also invalidate the timer if still active
  202.  */
  203. void pthread_clear_sighandler()
  204. {
  205.   struct sigaction vec;
  206.   register int sig;
  207.   struct itimerval it;
  208.  
  209.   vec.sa_handler = SIG_DFL;
  210.   pthread_sigcpyset2set(&vec.sa_mask, &all_signals);
  211.   vec.sa_flags = 0;
  212.  
  213.   for (sig = 1; sig < NSIG; sig++)
  214.     if (sig != SIGKILL && sig != SIGSTOP)
  215.       if (SIGACTION(sig, &vec, (struct sigaction *) NULL))
  216. #ifdef DEBUG
  217.     fprintf(stderr,
  218.         "Pthreads: Could not install handler for signal %d\n", sig)
  219. #endif
  220.       ;
  221.  
  222.   if (!getitimer(ITIMER_REAL, &it) && timerisset(&it.it_value)) {
  223.     it.it_value.tv_sec = it.it_value.tv_usec = 0;
  224.     it.it_interval.tv_sec = it.it_interval.tv_usec = 0;
  225.     setitimer(ITIMER_REAL, &it, (struct itimerval *) NULL);
  226.   }
  227. }
  228. #endif !STAND_ALONE
  229.  
  230. /*------------------------------------------------------------*/
  231. /*
  232.  * default_action - take default action on process
  233.  * Notice: SIGSTOP and SIGKILL can never be received (unmaskable)
  234.  * but they are included anyway.
  235.  */
  236. static void default_action(sig)
  237.      int sig;
  238. {
  239.   switch (sig) {
  240.   case SIGURG:
  241.   case SIGCONT:
  242.   case SIGCHLD:
  243.   case SIGIO:
  244.   case SIGWINCH:
  245.     break; /* ignore or continue */
  246.  
  247.   case SIGSTOP:
  248.   case SIGTSTP:
  249.   case SIGTTIN:
  250.   case SIGTTOU:
  251. #ifdef STAND_ALONE
  252.     exit();
  253. #else
  254.     kill(getpid(), SIGSTOP);  /* stop process -> UNIX may generate SIGCHLD */
  255. #endif
  256.     break;
  257.  
  258.   default:
  259. #ifdef TIMER_DEBUG
  260.     fprintf(stderr, "last alarm is %d.%d\n",
  261.         last_alarm.tv_sec, last_alarm.tv_usec);
  262.     if (pthread_timer.head != NO_TIMER) {
  263.       fprintf(stderr, "wakeup  time is %d.%d\n", pthread_timer.head->tp.tv_sec,
  264.           pthread_timer.head->tp.tv_usec);
  265.       gettimeofday(&pthread_timer.head->tp, (struct timezone *) NULL);
  266.       fprintf(stderr, "current time is %d.%d\n", pthread_timer.head->tp.tv_sec,
  267.                                              pthread_timer.head->tp.tv_usec);
  268.     }
  269.  
  270. #endif
  271. #ifndef STAND_ALONE
  272.     pthread_clear_sighandler();
  273.     kill(getpid(), sig); /* reissue signal to terminate process: UNIX default */
  274.     {
  275.       sigset_t empty;
  276.  
  277.       sigemptyset(&empty);
  278.       SIGPROCMASK(SIG_SETMASK, &empty, (struct sigset_t *) NULL);
  279.     }
  280. #endif !STAND_ALONE
  281. #ifdef DEBUG
  282. #ifndef IO
  283.     fprintf(stderr, "RUNAWAY: should produce core dump now\n");
  284. #endif DEBUG
  285. #endif IO
  286. #ifdef STAND_ALONE
  287.     exit();
  288. #else !STAND_ALONE
  289.     pthread_process_exit(-1); /* abnormal termination, but no core dump */
  290. #endif STAND_ALONE
  291.   }
  292. }
  293.  
  294. /*------------------------------------------------------------*/
  295. /*
  296.  * handle_thread_signal - try to handle one signal on a thread and
  297.  * return TRUE if it was handled, otherwise return FALSE
  298.  */
  299. static int handle_thread_signal(p, sig, code)
  300. pthread_t p;
  301. int sig;
  302. int code;
  303. {
  304.   register struct context_t *scp;
  305. #ifdef C_CONTEXT_SWITCH
  306.   extern void pthread_fake_call_wrapper_wrapper();
  307. #endif C_CONTEXT_SWITCH
  308.  
  309. #ifndef STAND_ALONE
  310.   /*
  311.    * handle timer signals
  312.    */
  313.   if (sig == TIMER_SIG) {
  314. #ifdef TIMER_DEBUG
  315.     fprintf(stderr, "handle_thread_signal: timer signal\n");
  316. #endif
  317. #ifdef DEF_RR
  318. #ifdef REAL_TIME
  319.     if (pthread_timer.head->mode == DL_TIME)
  320.       pthread_cancel_timed_sigwait(p, TRUE, ANY_TIME, p->queue != &ready);
  321.     else {
  322. #endif REAL_TIME
  323.       if (pthread_timer.head->mode == RR_TIME && p->queue == &ready) {
  324.     pthread_cancel_timed_sigwait(p, TRUE, ANY_TIME, FALSE);
  325.     pthread_q_deq(&ready, p, PRIMARY_QUEUE);
  326.     pthread_q_primary_enq(&ready, p);
  327.       } else
  328. #endif DER_FF
  329.     pthread_cancel_timed_sigwait(p, TRUE, ANY_TIME, p->queue != &ready);
  330.       return(TRUE);
  331.     }
  332. #ifdef REAL_TIME
  333.   }
  334. #endif REAL_TIME
  335. #endif !STAND_ALONE
  336.   
  337.   /*
  338.    * handle signals for sigwait
  339.    */
  340.   if (p->state & T_SIGWAIT && sigismember(&p->sigwaitset, sig)) {
  341.     pthread_q_wakeup_thread(NO_QUEUE, p, NO_QUEUE_INDEX);
  342.     p->state &= ~T_SIGWAIT;
  343.     pthread_sigaddset2set(&p->mask, &p->sigwaitset);
  344.     pthread_sigdelset2set(&p->mask, &cantmask);
  345.     sigdelset(&p->sigwaitset, sig);
  346.     return(TRUE);
  347.   }
  348.   
  349.   /*
  350.    * handler set to ignore
  351.    */
  352.   if (pthread_user_handler[sig].sa_handler == SIG_IGN && sig != SIGCANCEL)
  353.     return(TRUE);
  354.     
  355.   /*
  356.    * handler set to default action
  357.    */
  358.   if (pthread_user_handler[sig].sa_handler == SIG_DFL && sig != SIGCANCEL) {
  359.     default_action(sig);
  360.     return(TRUE);
  361.   }
  362.  
  363.   /*
  364.    * handle signals for sigsuspend and user handlers
  365.    */
  366.   if (sigismember(&handlerset, sig)) {
  367.     if (p->state & T_BLOCKED)
  368.       p->errno = EINTR;
  369.       
  370.     if (!(p->state & T_RUNNING)) {
  371.       if (p->state & T_SYNCTIMER)
  372.     pthread_cancel_timed_sigwait(p, FALSE, SYNC_TIME, TRUE);
  373.       else {
  374.     pthread_q_wakeup_thread(p->queue, p, PRIMARY_QUEUE);
  375.     if (p->state & (T_SIGWAIT | T_SIGSUSPEND)) {
  376.       p->state &= ~(T_SIGWAIT | T_SIGSUSPEND);
  377.       sigemptyset(&p->sigwaitset);
  378.     }
  379.       }
  380.     }
  381.       
  382.     p->sig_info[sig].si_signo = sig;
  383.     p->sig_info[sig].si_code = code;
  384.  
  385. #ifdef C_CONTEXT_SWITCH
  386.     if (pthread_not_called_from_sighandler(p->context[JB_PC]))
  387.       p->nscp = (struct context_t *) DIRECTED_AT_THREAD;
  388.     p->sig = sig;
  389.     p->osp = p->context[JB_SP];
  390.     p->opc = p->context[JB_PC];
  391.     p->context[JB_PC] = (int) pthread_fake_call_wrapper_wrapper;
  392. #ifdef ASM_SETJMP
  393.     p->opc += RETURN_OFFSET;
  394.     p->context[JB_PC] -= RETURN_OFFSET;
  395. #endif ASM_SETJMP
  396. #else !C_CONTEXT_SWITCH
  397.     if (pthread_not_called_from_sighandler(p->context[JB_PC]))
  398.       scp = (struct context_t *) DIRECTED_AT_THREAD;
  399.     else
  400.       scp = p->nscp;
  401.     
  402.     pthread_push_fake_call(p, pthread_user_handler[sig].sa_handler, sig,
  403.                scp, &pthread_user_handler[sig].sa_mask);
  404. #endif !C_CONTEXT_SWITCH
  405.     return(TRUE);
  406.   }
  407.  
  408.   /*
  409.    * handle cancel signal
  410.    */
  411.   if (sig == SIGCANCEL) {
  412.     if (p->state & T_SYNCTIMER)
  413.       pthread_cancel_timed_sigwait(p, FALSE, ALL_TIME, TRUE);
  414.     else if (p->state & (T_SIGWAIT | T_SIGSUSPEND)) {
  415.       p->state &= ~(T_SIGWAIT | T_SIGSUSPEND);
  416.       sigemptyset(&p->sigwaitset);
  417.     }
  418.  
  419.     if (p->queue && !(p->state & T_RUNNING))
  420.       pthread_q_deq(p->queue, p, PRIMARY_QUEUE);
  421.     
  422.     pthread_q_deq(&all, p, ALL_QUEUE);
  423.     
  424.     /*
  425.      * no more signals for this thread, not even cancellation signal
  426.      */
  427.     pthread_sigcpyset2set(&p->mask, &all_signals);
  428.     sigaddset(&p->mask, SIGCANCEL);
  429. #ifdef C_CONTEXT_SWITCH
  430.     p->nscp = (struct context_t *) DIRECTED_AT_THREAD;
  431.     p->sig = -1;
  432.     p->context[JB_PC] = (int) pthread_fake_call_wrapper_wrapper;
  433. #ifdef ASM_SETJMP
  434.     p->context[JB_PC] -= RETURN_OFFSET;
  435. #endif ASM_SETJMP
  436. #else !C_CONTEXT_SWITCH
  437.     pthread_push_fake_call(p, pthread_exit, -1,
  438.                (struct context_t *) DIRECTED_AT_THREAD,
  439.                (struct sigset_t *) NULL);
  440. #endif !C_CONTEXT_SWITCH
  441.     if (!(p->state & T_RUNNING))
  442.       pthread_q_wakeup_thread(NO_QUEUE, p, NO_QUEUE_INDEX);
  443.     
  444.     return(TRUE);
  445.   }
  446.  
  447.   return (FALSE);
  448. }
  449.  
  450. /*------------------------------------------------------------*/
  451. /*
  452.  * handle_one_signal - handle one signal on the process level
  453.  * assumes SET_KERNEL_FLAG
  454.  */
  455. static void handle_one_signal(sig, code)
  456. int sig;
  457. int code;
  458. {
  459.   register pthread_t p = mac_pthread_self();
  460.   struct itimerval it;
  461.   struct timespec now;
  462.   extern pthread_t pthread_q_all_find_receiver();
  463.   static int aio_handle();
  464.  
  465.   /*
  466.    * Determine who needs to get the signal (in the following order):
  467.    * (1) signal directed at specific thread: take this thread
  468.    * (2) signal at process level:
  469.    * (2a) synchronous signal: direct at current thread
  470.    * (2b) SIGALRM, timer queue not empty, timer expired: take head off timer q
  471.    * (2c) SIGIO, asynchronous I/O requested: determine receiver and make ready
  472.    * (2c) handler defined: take first thread in all queue with signal unmasked
  473.    * (3) no handler defined: pend signal on process till thread unmasks signal
  474.    *      if signal already pending, it's lost
  475.    */
  476.   if (p != NO_PTHREAD &&
  477.       (p->nscp == DIRECTED_AT_THREAD ||
  478.        pthread_not_called_from_sighandler(p->context[JB_PC])) &&
  479.       (p = (pthread_t) code))
  480.     code = 0;
  481.   else if (p != NO_PTHREAD && sigismember(&synchronous, sig))
  482.     /* p = p */;
  483. #ifdef STAND_ALONE
  484.   else if (sig == SIGALRM) {
  485.     if ((p = pthread_timer) && 
  486.     !clock_gettime(CLOCK_REALTIME, &now) && GTEQ_NTIME(now, p->tp))
  487.       pthread_cancel_timed_sigwait(p, TRUE, ANY_TIME, p->queue != &ready);
  488.     return;
  489.   }
  490.   /* SIGIO is being used to invoke pthread_select_isr which takes care of 
  491.    * suspending and waking up threads waiting on I/O.
  492.    * The parameter 2 is used instead of UART_ISR
  493.    */
  494.      
  495.   else if (sig == SIGIO) {
  496.     pthread_select_isr(SIGIO);
  497.     return;
  498.   }
  499. #else !STAND_ALONE
  500.   else if (sig == SIGALRM &&
  501. #ifdef DEF_RR
  502.     pthread_timer.head != NO_TIMER && (p = pthread_timer.head->thread) &&
  503. #else !DEF_RR
  504.     (p = pthread_timer.head) &&
  505. #endif DEF_RR
  506.     !getitimer(ITIMER_REAL, &it) && !timerisset(&it.it_value))
  507.       sig = TIMER_SIG;
  508. #endif !STAND_ALONE
  509. #ifdef IO
  510.   else if (sig == SIGIO && aio_handle())
  511.     return;
  512. #endif
  513.   else if (!(p = pthread_q_all_find_receiver(&all, sig))) {
  514.     if (!sigismember(&pending_signals, sig)) {
  515.       sigaddset(&pending_signals, sig);
  516.       pending_code[sig] = code;
  517.     }
  518.     return;
  519.   }
  520.   
  521.   if (p->state & T_RETURNED)
  522.     return;
  523.   
  524.   /*
  525.    * Pend signal on thread if it's masked out OR
  526.    * if the signal is SIGCANCEL, the interrupt state CONTROLLED, and
  527.    * we are not at an interruption point.
  528.    */
  529.   if (sigismember(&p->mask, sig) ||
  530.       sig == SIGCANCEL &&
  531.       p->state & T_CONTROLLED && !(p->state & T_INTR_POINT)) {
  532.     sigaddset(&p->pending, sig);
  533.     p->sig_info[sig].si_code = code;
  534.     return;
  535.   }
  536.  
  537.   if (handle_thread_signal(p, sig, code))
  538.     return;
  539.   
  540.   default_action(sig);
  541. }
  542.   
  543. /*------------------------------------------------------------*/
  544. /*
  545.  * pthread_handle_many_process_signals - determine pending signal(s).
  546.  * if no thread ready, suspend process;
  547.  * returns the head of the ready queue.
  548.  * assumes SET_KERNEL_FLAG
  549.  */
  550. pthread_t pthread_handle_many_process_signals()
  551. {
  552.   register int sig;
  553.  
  554.   do {
  555.     while (pthread_signonemptyset(&new_signals)) {
  556.       /*
  557.        * start critical section
  558.        */
  559.       SIGPROCMASK(SIG_BLOCK, &all_signals, (struct sigset_t *) NULL);
  560.       
  561.       pthread_sigcpyset2set(&sig_handling, &new_signals);
  562.       pthread_sigdelset2set(&new_signals, &sig_handling);
  563.       
  564.       SIGPROCMASK(SIG_UNBLOCK, &all_signals, (struct sigset_t *) NULL);
  565.       /*
  566.        * end of critical section
  567.        */
  568.  
  569.       for (sig = 1; sig < NNSIG; sig++)
  570.     if (sigismember(&sig_handling, sig))
  571.       handle_one_signal(sig, new_code[sig]);
  572.     }
  573.  
  574.     /*
  575.      * No thread, no action: suspend waiting for signal at process level
  576.      */
  577.     if (ready.head == NO_PTHREAD) {
  578.       SIGPROCMASK(SIG_BLOCK, &all_signals, (struct sigset_t *) NULL);
  579.       if (!pthread_signonemptyset(&new_signals)) {
  580. #ifdef DEBUG
  581. #ifndef IO
  582.     fprintf(stderr, "suspending process waiting for signal\n");
  583. #endif
  584. #endif
  585. #ifdef STAND_ALONE
  586.     while(!pthread_signonemptyset(&new_signals))
  587. #endif
  588.       SIGSUSPEND(&no_signals);
  589.       }
  590.       SIGPROCMASK(SIG_UNBLOCK, &all_signals, (struct sigset_t *) NULL);
  591.     }
  592.  
  593.   } while (ready.head == NO_PTHREAD);
  594.  
  595.   return(ready.head);
  596. }
  597.  
  598. /*------------------------------------------------------------*/
  599. /*
  600.  * pthread_handle_one_process_signal - handle latest signal caught by 
  601.  * universal handler while not in kernel
  602.  * returns the head of the ready queue.
  603.  * assumes SET_KERNEL_FLAG
  604.  */
  605. pthread_t pthread_handle_one_process_signal(sig, code)
  606. int sig;
  607. int code;
  608. {
  609.   handle_one_signal(sig, code);
  610.  
  611.   if (pthread_signonemptyset(&new_signals) ||
  612.       ready.head == NO_PTHREAD)
  613.     pthread_handle_many_process_signals();
  614. }
  615.  
  616. /*------------------------------------------------------------*/
  617. /*
  618.  * pthread_handle_pending_signals - handle unmasked pending signals of 
  619.  * current thread assumes SET_KERNEL_FLAG
  620.  */
  621. void pthread_handle_pending_signals()
  622. {
  623.   pthread_t p = mac_pthread_self();
  624.   int sig;
  625.  
  626.   /*
  627.    * handle signals pending on threads if they are unmasked and
  628.    * SIGCANCEL only on an interruption point.
  629.    */
  630.   if (!pthread_siggeset2set(&p->mask, &p->pending))
  631.     for (sig = 1; sig < NNSIG; sig++)
  632.       if (sigismember(&p->pending, sig) && !sigismember(&p->mask, sig) && 
  633.       (sig != SIGCANCEL || p->state & T_INTR_POINT)) {
  634.     sigdelset(&p->pending, sig);
  635.     
  636.     handle_thread_signal(p, sig, p->sig_info[sig].si_code);
  637.       }
  638.  
  639.   /*
  640.    * handle signals pending on process
  641.    */
  642.   if (!pthread_siggeset2set(&p->mask, &pending_signals))
  643.     for (sig = 1; sig < NNSIG; sig++)
  644.       if (sigismember(&pending_signals, sig) && !sigismember(&p->mask, sig)) {
  645.     sigdelset(&pending_signals, sig);
  646.     
  647.     handle_thread_signal(p, sig, pending_code[sig]);
  648.       }
  649. }
  650.  
  651. #ifndef STAND_ALONE
  652. /*------------------------------------------------------------*/
  653. /*
  654.  * sighandler - wrapper for all signals, defers signals for later processing
  655.  * Notice: All maskable signals are caught and re-multiplexed by Pthreads.
  656.  */
  657. #ifdef SVR4
  658. static void sighandler(sig, sip, scp)
  659.      struct siginfo *sip;
  660. #else !SVR4
  661. static void sighandler(sig, code, scp, addr)
  662.      int code;
  663.      char *addr;
  664. #endif !SVR4
  665.      int sig;
  666.      struct context_t *scp;
  667. {
  668.   register pthread_t p = mac_pthread_self();
  669. #ifdef SVR4
  670.   sigset_t omask;
  671.   greg_t opc = scp->sc_pc;
  672.   greg_t osp = scp->sc_sp;
  673. #endif SVR4
  674. #if defined(STACK_CHECK) && defined(SIGNAL_STACK)
  675.   void pthread_io_end();
  676.   SIGSTACK_T ss;
  677.  
  678.   if (sig == SIGILL || sig == SIGBUS || sig == SIGSEGV) {
  679.     if (p != NO_PTHREAD && !(p->state & T_LOCKED))
  680.       default_action(sig);
  681.  
  682.   if (((sig == SIGILL && SCP_CODE == ILL_STACK) || 
  683. #ifdef SVR4
  684.        (sig == SIGSEGV &&
  685.     (FC_CODE(SCP_CODE) == FC_HWERR || FC_CODE(SCP_CODE) == FC_ALIGN)) ||
  686. #else
  687.        (sig == SIGSEGV && FC_CODE(SCP_CODE) == FC_PROT) ||
  688. #endif
  689.        (sig == SIGBUS && BUS_CODE(SCP_CODE) == BUS_OBJERR)) &&
  690.       p != NO_PTHREAD &&
  691.       ((scp->sc_sp < PA(p->stack_base+3*pthread_page_size))
  692. #ifdef IO
  693.        || (scp->sc_pc > (int)read && scp->sc_pc < (int)pthread_io_end)
  694. #endif
  695.        ))
  696.     pthread_unlock_stack(p);
  697.  
  698.     switch_stacks(scp->sc_sp);
  699.  
  700. #ifndef SVR4
  701.     /*
  702.      * Let UNIX know that we are not on signal stack anymore. Does not work
  703.      * for SVR4, does work for BSD.
  704.      */
  705.     if (SCP_ONSTACK)
  706.       scp->sc_onstack = FALSE;
  707.     else {
  708.       ss.ss_sp = (char *) SA((int) pthread_tempstack_top - STACK_OFFSET);
  709.       scp->sc_onstack = FALSE;
  710.       if (SIGSTACK(&ss, (SIGSTACK_T *) NULL))
  711. #ifdef DEBUG
  712.         fprintf(stderr,
  713.             "Pthreads: Could not specify signal stack, errno %d\n", errno)
  714. #endif DEBUG
  715.         ;
  716.     }
  717. #endif !SVR4
  718.   }
  719.  
  720. #endif STACK_CHECK && SIGNAL_STACK
  721.  
  722. #ifdef SVR4
  723.   pthread_sigcpyset2set(&omask, &scp->sc_mask);
  724. #endif SVR4
  725.  
  726.   /*
  727.    * add signal to queue of pending signals
  728.    */
  729. #ifdef DEBUG
  730. #ifndef IO
  731. #ifdef DEF_RR
  732.   if (sig != SIGALRM)
  733. #endif
  734.     fprintf(stderr, "signal %d caught\n", sig);
  735. #endif
  736. #endif
  737.  
  738.   if (!sigismember(&new_signals, sig))
  739.     if (!is_in_kernel && scp) {
  740.       SET_KERNEL_FLAG;
  741.       SIGPROCMASK(SIG_UNBLOCK, &all_signals, (struct sigset_t *) NULL);
  742.  
  743.       /*
  744.        * Associate UNIX context with current thread
  745.        */
  746.       p->scp = p->nscp;
  747.       p->nscp = scp;
  748.  
  749.       /*
  750.        * A signal is pending so that the signal dispatcher calls
  751.        * pthread_handle_one_process_signals()
  752.        * and then switches to highest priority thread. Thus, we act as if no
  753.        * context switch is initiated, i.e. as if we switched back to thread
  754.        * which was running when the signal came in.
  755.        */
  756. #ifndef C_CONTEXT_SWITCH
  757.       pthread_sched_wrapper(sig, SCP_CODE);
  758. #else
  759.       p->errno = errno;
  760.       pthread_sched_wrapper(sig, SCP_CODE, p);
  761.       errno = p->errno;
  762.       CLEAR_KERNEL_FLAG;
  763. #endif
  764.     }
  765.     else {
  766.       sigaddset(&new_signals, sig);
  767.       new_code[sig] = SCP_CODE;
  768.       state_change = TRUE;
  769.     }
  770. #ifdef SVR4
  771.   /*
  772.    * Solaris does not seem to have a _sigtramp() wrapper for signal handlers.
  773.    * In fact, it is not quite understood how the signal mask is reset after
  774.    * returning from the signal handler. This is fixed by explicitly setting
  775.    * the context.
  776.    */
  777.   setcontext((struct ucontext *) scp);
  778. #endif SVR4
  779. }
  780. #endif !STAND_ALONE
  781.  
  782. /*------------------------------------------------------------*/
  783. /*
  784.  * pthread_init_signals - initialize signal package
  785.  */
  786. void pthread_init_signals()
  787. {
  788.   int sig;
  789.   struct sigaction vec;
  790. #if defined(STACK_CHECK) && defined(SIGNAL_STACK)
  791.   SIGSTACK_T ss;
  792.  
  793.   ss.ss_sp = (char *) SA((int) pthread_tempstack_top - STACK_OFFSET);
  794.   CLR_SS_ONSTACK;
  795. #ifndef STAND_ALONE
  796.   if (SIGSTACK(&ss, (SIGSTACK_T *) NULL))
  797. #ifdef DEBUG
  798.     fprintf(stderr,
  799.         "Pthreads: Could not specify signal stack, errno %d\n", errno)
  800. #endif DEBUG
  801.     ;
  802. #endif !STAND_ALONE
  803. #endif
  804.  
  805.   /*
  806.    * initialize kernel structure
  807.    */
  808.   is_in_kernel = is_updating_timer = FALSE;
  809.  
  810.   sigemptyset(&synchronous);
  811.   sigaddset(&synchronous, SIGILL);
  812.   sigaddset(&synchronous, SIGABRT);
  813.   sigaddset(&synchronous, SIGEMT);
  814.   sigaddset(&synchronous, SIGFPE);
  815.   sigaddset(&synchronous, SIGBUS);
  816.   sigaddset(&synchronous, SIGSEGV);
  817.   
  818.   sigemptyset((sigset_t *) &new_signals);
  819.   sigemptyset(&pending_signals);
  820.   sigemptyset(&handlerset);
  821.   sigemptyset(&sig_handling);
  822.  
  823.   sigemptyset(&cantmask);
  824.   sigaddset(&cantmask, SIGKILL);
  825.   sigaddset(&cantmask, SIGSTOP);
  826.   sigaddset(&cantmask, SIGCANCEL);
  827.  
  828.   sigfillset(&all_signals);
  829.   sigdelset(&all_signals, SIGKILL);
  830.   sigdelset(&all_signals, SIGSTOP);
  831.  
  832.   pthread_queue_init(&ready);
  833.   pthread_queue_init(&all);
  834. #ifdef STAND_ALONE
  835.   pthread_timer_queue_init(pthread_timer);
  836. #else
  837.   pthread_timer_queue_init(&pthread_timer);
  838. #endif
  839.   set_warning = "CAUTION: entering kernel again\n";
  840.   clear_warning = "CAUTION: leaving kernel again\n";
  841.   prio_warning = "CAUTION: prio violation when leaving kernel\n";
  842. #ifdef RAND_SWITCH
  843.   srandom(1);
  844.   pthread_n_ready = 0;
  845. #endif
  846.  
  847. #ifdef STAND_ALONE
  848.   sigemptyset(&proc_mask);
  849.   cur_heap = (int)(&heap_start);
  850. #else !STAND_ALONE
  851.   /*
  852.    * no signal requests
  853.    */
  854.   for (sig = 0; sig < NNSIG; sig++) {
  855.     pthread_user_handler[sig].sa_handler = SIG_DFL;
  856.     sigemptyset(&pthread_user_handler[sig].sa_mask);
  857.     pthread_user_handler[sig].sa_flags = 0;
  858.     new_code[sig] = 0;
  859.   }
  860.  
  861.   /*
  862.    * install universal signal handler for all signals
  863.    * except for those which cannot be masked
  864.    */
  865.   vec.sa_handler = sighandler;
  866.   pthread_sigcpyset2set(&vec.sa_mask, &all_signals);
  867.   vec.sa_flags = SA_SIGINFO | SA_RESTART;
  868.     
  869.   for (sig = 1; sig < NSIG; sig++)
  870.     if (!sigismember(&cantmask, sig)) {
  871. #if defined(STACK_CHECK) && defined(SIGNAL_STACK)
  872.       if (sig == SIGBUS || sig == SIGILL || sig == SIGSEGV)
  873.         vec.sa_flags |= SA_ONSTACK;
  874. #endif
  875.       if (SIGACTION(sig, &vec, (struct sigaction *) NULL))
  876. #ifdef DEBUG
  877.         fprintf(stderr, "Pthreads (signal): \
  878.           Could not install handler for signal %d\n", sig)
  879. #endif
  880.       ;
  881. #if defined(STACK_CHECK) && defined(SIGNAL_STACK)
  882.       if (sig == SIGBUS || sig == SIGILL || sig == SIGSEGV)
  883.         vec.sa_flags &= ~SA_ONSTACK;
  884. #endif
  885.     }
  886. #endif STAND_ALONE
  887.  
  888. #ifdef IO
  889.   gwidth = 0;
  890.   FD_ZERO(&greadfds);
  891.   FD_ZERO(&gwritefds);
  892.   FD_ZERO(&gexceptfds);
  893. #endif IO
  894. }
  895.  
  896. /*------------------------------------------------------------*/
  897. /*
  898.  * sigwait - suspend thread until signal becomes pending
  899.  * Return: signal number if o.k., otherwise -1
  900.  * Notice: cannot mask SIGKILL, SIGSTOP, SIGCANCEL
  901.  */
  902. int sigwait(set)
  903. sigset_t *set;
  904. {
  905.   register int sig;
  906.   sigset_t new, more;
  907.   register pthread_t p = mac_pthread_self();
  908.  
  909.   pthread_sigcpyset2set(&new, set);
  910.   pthread_sigdelset2set(&new, &cantmask);
  911.   pthread_sigcpyset2set(&more, &new);
  912.   SET_KERNEL_FLAG;
  913.  
  914.   /*
  915.    * Are the signals in set blocked by the current thread?
  916.    */
  917.   if (!pthread_siggeset2set(&p->mask, &more)) {
  918.     set_errno(EINVAL);
  919.     CLEAR_KERNEL_FLAG;
  920.     return(-1);
  921.   }
  922.  
  923.   /*
  924.    * Any of the signals in set pending on thread?
  925.    */
  926.   if (pthread_sigismemberset2set(&p->pending, &more))
  927.     for (sig = 1; sig < NNSIG; sig++)
  928.       if (sigismember(&p->pending, sig) && sigismember(&more, sig)) {
  929.     sigdelset(&p->pending, sig);
  930.     CLEAR_KERNEL_FLAG;
  931.     return(sig);
  932.       }
  933.     
  934.   /*
  935.    * Any of the signals in set pending on process?
  936.    */
  937.   if (pthread_sigismemberset2set(&pending_signals, &more))
  938.     for (sig = 1; sig < NNSIG; sig++)
  939.       if (sigismember(&pending_signals, sig) && sigismember(&more, sig)) {
  940.     sigdelset(&pending_signals, sig);
  941.     CLEAR_KERNEL_FLAG;
  942.     return(sig);
  943.       }
  944.     
  945.   /*
  946.    * suspend thread and wait for any of the signals
  947.    */
  948.   pthread_sigaddset2set(&p->sigwaitset, &new);
  949.   pthread_sigdelset2set(&p->mask, &new);
  950.   p->state &= ~T_RUNNING;
  951.   p->state |= T_SIGWAIT | T_BLOCKED | T_INTR_POINT;
  952.   if (sigismember(&p->pending, SIGCANCEL) && !sigismember(&p->mask, SIGCANCEL))
  953.     SIG_CLEAR_KERNEL_FLAG(TRUE);
  954.   else {
  955.     pthread_q_deq_head(&ready, PRIMARY_QUEUE);
  956.     SIM_SYSCALL(TRUE);
  957.     CLEAR_KERNEL_FLAG;
  958.   }
  959.  
  960.   if (get_errno() == EINTR)
  961.     return(-1);
  962.  
  963.   /*
  964.    * determine the received signal
  965.    */
  966.   for (sig = 1; sig < NNSIG; sig++)
  967.     if (sigismember(&new, sig) && !sigismember(&p->sigwaitset, sig))
  968.       break;
  969.  
  970.   /*
  971.    * Clear signal mask
  972.    */
  973.   SET_KERNEL_FLAG;
  974.   sigemptyset(&p->sigwaitset);
  975.   CLEAR_KERNEL_FLAG;
  976.  
  977.   /*
  978.    * If no signal woke us up directly, a user handler (hence interrupt) must
  979.    * have been activated via a different signal.
  980.    */
  981.   if (sig < 0) {
  982.     set_errno(EINVAL);
  983.     return(-1);
  984.   }
  985.  
  986.   return(sig);
  987. }
  988.  
  989. /*------------------------------------------------------------*/
  990. /*
  991.  * sigprocmask - change or examine signal mask of thread
  992.  * return old mask or -1 if error
  993.  * cannot mask SIGKILL, SIGSTOP, SIGCANCEL
  994.  */
  995. int sigprocmask(how, set, oset)
  996. int how;
  997. const sigset_t *set;
  998. sigset_t *oset;
  999. {
  1000.   sigset_t new, old, pending;
  1001.   register pthread_t p = mac_pthread_self();
  1002.   register already_in_kernel = is_in_kernel;
  1003.  
  1004. #if defined(SOLARIS) && defined(IO)
  1005.   if (pthread_get_retaddr() < 0) /* call from dynamic library */
  1006.     return(pthread_p_sigprocmask(how, set, oset));
  1007. #endif SOLARIS && IO
  1008.  
  1009.   if (!already_in_kernel)
  1010.     SET_KERNEL_FLAG;
  1011.  
  1012.   pthread_sigcpyset2set(&old, &p->mask);
  1013.   if (oset)
  1014.     pthread_sigcpyset2set(oset, &old);
  1015.   if (!set) {
  1016.     if (!already_in_kernel)
  1017.       CLEAR_KERNEL_FLAG;
  1018.     return(0);
  1019.   }
  1020.  
  1021.   pthread_sigcpyset2set(&new, set);
  1022.   pthread_sigdelset2set(&new, &cantmask);
  1023.  
  1024.   switch (how) {
  1025.   case SIG_BLOCK:
  1026.     pthread_sigaddset2set(&p->mask, &new);
  1027.     break;
  1028.   case SIG_UNBLOCK:
  1029.     pthread_sigdelset2set(&p->mask, &new);
  1030.     break;
  1031.   case SIG_SETMASK:
  1032.     pthread_sigcpyset2set(&p->mask, &new);
  1033.     break;
  1034.   default:
  1035.     set_errno(EINVAL);
  1036.     if (!already_in_kernel)
  1037.       CLEAR_KERNEL_FLAG;
  1038.     return(-1);
  1039.   }
  1040.  
  1041.   pthread_sigcpyset2set(&pending, &p->pending);
  1042.   pthread_sigaddset2set(&pending, &pending_signals);
  1043.   pthread_sigdelset2set(&old, &p->mask);
  1044.   if (pthread_sigismemberset2set(&pending, &old))
  1045.     SIG_CLEAR_KERNEL_FLAG(TRUE);
  1046.   else {
  1047.     SIM_SYSCALL(TRUE);
  1048.     if (!already_in_kernel)
  1049.       CLEAR_KERNEL_FLAG;
  1050.   }
  1051.   return(0);
  1052. }
  1053.  
  1054. /*------------------------------------------------------------*/
  1055. /*
  1056.  * sigpending - inquire about pending signals which are blocked, i.e. applies
  1057.  * to only those signals which are explicitly pending on the current thread
  1058.  * return 0 if o.k., -1 otherwise
  1059.  */
  1060. int sigpending(set)
  1061. sigset_t *set;
  1062. {
  1063.   if (!set) {
  1064.     set_errno(EINVAL);
  1065.     return(-1);
  1066.   }
  1067.  
  1068.   SIM_SYSCALL(TRUE);
  1069.   pthread_sigcpyset2set(set, &mac_pthread_self()->pending);
  1070.   pthread_sigaddset2set(set, &pending_signals);
  1071.   pthread_sigdelset2set(set, &cantmask);
  1072.   return(0);
  1073. }
  1074.  
  1075. /*------------------------------------------------------------*/
  1076. /*
  1077.  * sigsuspend - suspend thread,
  1078.  * set replaces the masked signals for the thread temporarily,
  1079.  * suspends thread, and resumes execution when a user handler is invoked
  1080.  * Return: -1 and EINTR if interrupted or EINVAL if wrong parameters
  1081.  * Notice: cannot mask SIGKILL, SIGSTOP
  1082.  */
  1083. int sigsuspend(set)
  1084. SIGSUSPEND_CONST sigset_t *set;
  1085. {
  1086.   register int sig;
  1087.   sigset_t old, pending;
  1088.   register pthread_t p = mac_pthread_self();
  1089.  
  1090.   if (!set) {
  1091.     set_errno(EINVAL);
  1092.     return(-1);
  1093.   }
  1094.  
  1095.   SET_KERNEL_FLAG;
  1096.   pthread_sigcpyset2set(&old, &p->mask);
  1097.   pthread_sigcpyset2set(&p->mask, set);
  1098.   pthread_sigdelset2set(&p->mask, &cantmask);
  1099.   pthread_sigaddset2set(&p->sigwaitset, &p->mask);
  1100.  
  1101.   p->state &= ~T_RUNNING;
  1102.   p->state |= T_SIGSUSPEND | T_BLOCKED | T_INTR_POINT;
  1103.   if (sigismember(&p->pending, SIGCANCEL) && !sigismember(&p->mask, SIGCANCEL))
  1104.     SIG_CLEAR_KERNEL_FLAG(TRUE);
  1105.   else {
  1106.     pthread_q_deq_head(&ready, PRIMARY_QUEUE);
  1107.     SIM_SYSCALL(TRUE);
  1108.     CLEAR_KERNEL_FLAG;
  1109.   }
  1110.  
  1111.   /*
  1112.    * restore the initial signal mask
  1113.    */
  1114.   SET_KERNEL_FLAG;
  1115.   pthread_sigcpyset2set(&p->mask, &old);
  1116.  
  1117.   pthread_sigcpyset2set(&pending, &p->pending);
  1118.   pthread_sigaddset2set(&pending, &pending_signals);
  1119.   pthread_sigcpyset2set(&old, set);
  1120.   pthread_sigdelset2set(&old, &cantmask);
  1121.   pthread_sigdelset2set(&old, &p->mask);
  1122.   if (pthread_sigismemberset2set(&pending, &old))
  1123.     SIG_CLEAR_KERNEL_FLAG(TRUE);
  1124.   else
  1125.     CLEAR_KERNEL_FLAG;
  1126.  
  1127.   return(-1);
  1128. }
  1129.  
  1130. /*------------------------------------------------------------*/
  1131. /*
  1132.  * pause - suspend thread until any signal is caught,
  1133.  * same as sigsuspend except that the signal mask doesn't change
  1134.  */
  1135. int pause()
  1136. {
  1137.   register int sig;
  1138.   register pthread_t p = mac_pthread_self();
  1139.  
  1140.   SET_KERNEL_FLAG;
  1141.   pthread_sigcpyset2set(&p->sigwaitset, &p->mask);
  1142.   
  1143.   p->state &= ~T_RUNNING;
  1144.   p->state |= T_SIGSUSPEND | T_BLOCKED | T_INTR_POINT;
  1145.   if (sigismember(&p->pending, SIGCANCEL) && !sigismember(&p->mask, SIGCANCEL))
  1146.     SIG_CLEAR_KERNEL_FLAG(TRUE);
  1147.   else {
  1148.     pthread_q_deq_head(&ready, PRIMARY_QUEUE);
  1149.     SIM_SYSCALL(TRUE);
  1150.     CLEAR_KERNEL_FLAG;
  1151.   }
  1152.   
  1153.   return(-1);
  1154. }
  1155.  
  1156. #ifdef STAND_ALONE
  1157.  
  1158. /*------------------------------------------------------------*/
  1159. /*
  1160.  * pthread_timed_sigwait - suspend running thread until specified time
  1161.  * Return -1 if error, 0 otherwise
  1162.  * assumes SET_KERNEL_FLAG
  1163.  */
  1164. int pthread_timed_sigwait(p, timeout, mode, func, arg)
  1165.      pthread_t p;
  1166.      struct timespec *timeout;
  1167.      int mode;
  1168.      pthread_func_t func;
  1169.      any_t arg;
  1170. {
  1171.   struct timespec now;
  1172.   
  1173.   if (!timeout || timeout->tv_sec < 0 || 
  1174.       timeout->tv_nsec < 0 || timeout->tv_nsec >= 1000000000) {
  1175.     set_errno(EINVAL);
  1176.     return(-1);
  1177.   }
  1178.   clock_gettime(CLOCK_REALTIME, &now);
  1179.   
  1180.   if (mode == ABS_TIME) {
  1181.     if (GTEQ_NTIME(now, *timeout)) {
  1182.       set_errno(EAGAIN);
  1183.       return(-1);
  1184.     }
  1185.   }
  1186.   else if (mode == REL_TIME) {
  1187.     if (LE0_NTIME(*timeout)) {
  1188.       set_errno(EAGAIN);
  1189.       return(-1);
  1190.     }
  1191.     PLUS_NTIME(*timeout, now, *timeout);
  1192.   }
  1193.   else {
  1194.     set_errno(EINVAL);
  1195.     return(-1);
  1196.   }
  1197.   /*   
  1198.    * queue up current thread on the timer queue
  1199.    */
  1200.   p->timer_func = func;
  1201.   p->timer_arg = arg;
  1202.   p->tp.tv_sec = timeout->tv_sec;
  1203.   p->tp.tv_nsec = timeout->tv_nsec;
  1204.   pthread_q_timed_enq(&pthread_timer, p);
  1205.   return(0);
  1206. }
  1207.  
  1208. /*------------------------------------------------------------*/
  1209. /*
  1210.  * pthread_cancel_timed_sigwait - dequeue thread waiting on timer only
  1211.  * "signaled" indicates if the thread "p" received a SIGALRM
  1212.  * Notice: set error in both thread structure and global UNIX errno
  1213.  *         since this may be called from pthread_handle_many_process_signals
  1214.  * assumes SET_KERNEL_FLAG
  1215.  */
  1216. int pthread_cancel_timed_sigwait(first_p, signaled, mode, activate)
  1217.      pthread_t first_p;
  1218.      int signaled, mode, activate;
  1219. {
  1220.   pthread_t p = first_p;
  1221.   struct timespec now;
  1222.   int time_read = 0;
  1223.   
  1224.   if (pthread_timer == NO_PTHREAD) {
  1225.     is_updating_timer = FALSE;
  1226.     return(0);
  1227.   }
  1228.   
  1229.   do {
  1230. #ifdef TRASH
  1231.     if (!p->timer_func) {
  1232. #endif
  1233.       if (p->state & T_CONDTIMER) {
  1234.         p->state &= ~(T_CONDTIMER | T_SYNCTIMER);
  1235.         pthread_q_deq(p->queue, p, PRIMARY_QUEUE);
  1236.         pthread_q_timed_wakeup_thread(&pthread_timer, p,
  1237.                       (p == first_p ? activate : TRUE));
  1238.         if (p != first_p || signaled) {
  1239.       p->errno = EAGAIN;
  1240.       
  1241.           if (p == mac_pthread_self())
  1242.             set_errno(EAGAIN);
  1243.         }   
  1244.       }
  1245.       else {
  1246.         p->state &= ~T_SYNCTIMER;
  1247.         pthread_q_timed_wakeup_thread(&pthread_timer, p,
  1248.                       (p == first_p ? activate : TRUE));
  1249.       }
  1250. #ifdef TRASH
  1251.     }
  1252.     else
  1253.       (*p->timer_func)(p->timer_arg);
  1254. #endif
  1255.  
  1256.     p = pthread_timer;
  1257.     if (p != NO_PTHREAD && !time_read) {
  1258.       clock_gettime(CLOCK_REALTIME, &now);
  1259.       time_read++;
  1260.     }
  1261.   } while (p && GTEQ_NTIME(now, p->tp));
  1262.   
  1263.   is_updating_timer = FALSE;
  1264.  
  1265.   /*
  1266.    * timer signal received while cancelling => ignore it
  1267.    */
  1268.   if (!signaled && (sigismember(&new_signals, SIGALRM)))
  1269.     sigdelset(&new_signals, SIGALRM);
  1270.   
  1271.   return(0);
  1272. }
  1273.  
  1274. #else !STAND_ALONE
  1275.  
  1276. /*------------------------------------------------------------*/
  1277. /*
  1278.  * pthread_timed_sigwait - suspend running thread until specified time
  1279.  * Return -1 if error, 0 otherwise
  1280.  * assumes SET_KERNEL_FLAG
  1281.  */
  1282. int pthread_timed_sigwait(p, timeout, mode, func, arg)
  1283.      pthread_t p;
  1284.      struct timespec *timeout;
  1285.      int mode;
  1286.      pthread_func_t func;
  1287.      any_t arg;
  1288. {
  1289.   struct itimerval it;
  1290.   struct timeval now, in;
  1291.   register timer_ent_t phead;
  1292.  
  1293. #ifdef TIMER_DEBUG
  1294.     fprintf(stderr, "timed_sigwait: enter\n");
  1295. #endif
  1296.  
  1297. #ifdef DEF_RR
  1298.   if (p->num_timers >= TIMER_MAX) {
  1299.     set_errno(EAGAIN);
  1300.     return(-1);
  1301.   }
  1302.  
  1303.   if (mode != RR_TIME) {
  1304. #endif
  1305.     if (!timeout || timeout->tv_nsec < 0 || timeout->tv_nsec >= 1000000000 ||
  1306.     gettimeofday(&now, (struct timezone *) NULL)) {
  1307.       set_errno(EINVAL);
  1308.       return(-1);
  1309.     }
  1310.     P2U_TIME(in, (*timeout));
  1311. #ifdef DEF_RR
  1312.   }
  1313. #endif
  1314.  
  1315.   it.it_interval.tv_sec = it.it_interval.tv_usec = 0;
  1316.  
  1317.   if (mode == ABS_TIME) {
  1318.     /*
  1319.      * time has already passed
  1320.      */
  1321.     if (GTEQ_TIME(now, in)) {
  1322.       set_errno(EAGAIN);
  1323.       return(-1);
  1324.     }
  1325.  
  1326.     MINUS_TIME(it.it_value, in, now);
  1327.   }
  1328.   else if (mode == REL_TIME) {
  1329.     /*
  1330.      * time has already passed
  1331.      */
  1332.     if (LE0_TIME(in)) {
  1333.       set_errno(EAGAIN);
  1334.       return(-1);
  1335.     }
  1336.  
  1337.     it.it_value.tv_sec = in.tv_sec;
  1338.     it.it_value.tv_usec = in.tv_usec;
  1339.     PLUS_TIME(in, in, now);
  1340.   }
  1341. #ifdef DEF_RR
  1342.   else if (mode == RR_TIME) {
  1343.     p->state |= T_ASYNCTIMER;
  1344.     if ((p->interval.tv_sec == 0) && (p->interval.tv_usec == 0)) {
  1345.       in.tv_sec = it.it_value.tv_sec = 0;
  1346.       in.tv_usec = it.it_value.tv_usec = TIME_SLICE;
  1347.     }
  1348.     else {
  1349.       in.tv_sec = it.it_value.tv_sec = p->interval.tv_sec; 
  1350.       in.tv_usec = it.it_value.tv_usec = p->interval.tv_usec;
  1351.     }
  1352.   }
  1353. #endif
  1354.   else {
  1355.     set_errno(EINVAL);
  1356.     return(-1);
  1357.   }
  1358.  
  1359. #ifdef DEF_RR
  1360.   p->num_timers++;
  1361. #endif
  1362.  
  1363.   /*
  1364.    * if no timer set, set timer to current request; otherwise
  1365.    * overwrite timer if current request needs to be served next
  1366.    */
  1367.   if (!(phead = pthread_timer.head) || GT_TIME(phead->tp, in)) {
  1368.     if (setitimer(ITIMER_REAL, &it, (struct itimerval *) NULL)) {
  1369. #ifdef DEBUG
  1370.       fprintf(stderr, "ERROR: setitimer in timed_sigwait\n");
  1371. #endif
  1372.       set_errno(EINVAL);
  1373.       return(-1);
  1374.     }
  1375. #ifdef TIMER_DEBUG
  1376.     fprintf(stderr, "timed_sigwait: setitimer %d.%d sec.usec\n",
  1377.         it.it_value.tv_sec, it.it_value.tv_usec);
  1378. #endif
  1379.   }
  1380. #ifdef TIMER_DEBUG
  1381.   else
  1382.     fprintf(stderr, "timed_sigwait: timer not set up, pthread_timer.head=%x\n", phead);
  1383. #endif
  1384.     
  1385.   /*
  1386.    * queue up current thread on the timer queue
  1387.    */
  1388.   pthread_q_timed_enq(&pthread_timer,
  1389.               in,
  1390.               func == (pthread_func_t) pthread_exit ? DL_TIME : mode,
  1391.               p);
  1392.   return(0);
  1393. }
  1394.  
  1395. /*------------------------------------------------------------*/
  1396. /*
  1397.  * pthread_cancel_timed_sigwait - dequeue thread waiting for alarm only
  1398.  * "signaled" indicates if the thread "p" received a SIGALRM
  1399.  * Notice: set error in both thread structure and global UNIX errno
  1400.  *         since this may be called from pthread_handle_many_process_signals
  1401.  * assumes SET_KERNEL_FLAG
  1402.  */
  1403. int pthread_cancel_timed_sigwait(first_p, signaled, mode, activate)
  1404.      pthread_t first_p;
  1405.      int signaled, mode, activate;
  1406. {
  1407.   pthread_t p = first_p;
  1408.   timer_ent_t tmr;
  1409.   timer_ent_t old_tmr_head = pthread_timer.head;
  1410.   struct itimerval it;
  1411.   struct timeval now;
  1412.   int time_read = FALSE;
  1413.  
  1414.   /*
  1415.    * find the first instance of this thread in timer queue
  1416.    */
  1417. #ifdef DEF_RR
  1418.   for (tmr = pthread_timer.head; tmr; tmr = tmr->next[TIMER_QUEUE])
  1419.     if (tmr->thread == p && (tmr->mode & mode))
  1420.       break;
  1421. #else
  1422.   tmr = p;
  1423. #endif
  1424.  
  1425.   if (!tmr) {
  1426. #ifdef TIMER_DEBUG
  1427.     fprintf(stderr, "pthread_cancel_timed_sigwait: exit0\n");
  1428. #endif
  1429.     return(0);
  1430.   }
  1431.  
  1432.   /*
  1433.    * for each occurrence, remove the timer entry
  1434.    */
  1435.   do {
  1436.     if (p->state & T_CONDTIMER) {
  1437.       p->state &= ~(T_CONDTIMER | T_SYNCTIMER);
  1438.       pthread_q_deq(p->queue, p, PRIMARY_QUEUE);
  1439.       pthread_q_timed_wakeup_thread(&pthread_timer, p, 
  1440.                     (p == first_p ? activate : TRUE));
  1441.       if (p != first_p || signaled) {
  1442.     p->errno = EAGAIN;
  1443.  
  1444.     if (p == mac_pthread_self())
  1445.       set_errno(EAGAIN);
  1446.       }
  1447.     }  
  1448.     else {
  1449. #ifdef DEF_RR
  1450.       p->state &= ~((tmr->mode & RR_TIME) ? T_ASYNCTIMER : T_SYNCTIMER);
  1451. #else
  1452.       p->state &= ~T_SYNCTIMER;
  1453. #endif
  1454.       pthread_q_timed_wakeup_thread(&pthread_timer, p,
  1455.              (p == first_p ? activate : TRUE));
  1456.     }
  1457.  
  1458. #ifdef DEF_RR
  1459.     /*
  1460.      * find next instance of this thread in timer queue
  1461.      */
  1462.     if (mode == ALL_TIME) {
  1463.       tmr = pthread_timer.head;
  1464.       while (tmr && tmr->thread != p)
  1465.     tmr = tmr->next[TIMER_QUEUE];
  1466.     }
  1467.     else
  1468.       tmr = NO_TIMER;
  1469.  
  1470.     /*
  1471.      * check if head of timer queue can be woken up, i.e. now > tmr->tp
  1472.      */
  1473.     if (tmr == NO_TIMER && !time_read)
  1474. #else
  1475.     if (!time_read)
  1476. #endif
  1477.       if (gettimeofday(&now, (struct timezone *) NULL)) {
  1478. #ifdef TIMER_DEBUG
  1479.     fprintf(stderr, "pthread_cancel_timed_sigwait: exit1\n");
  1480. #endif
  1481.     set_errno(EINVAL);
  1482.     return(-1);
  1483.       }
  1484.       else
  1485.     time_read = TRUE;
  1486.  
  1487.     if (time_read) {
  1488.       tmr = pthread_timer.head;
  1489. #ifdef DEF_RR
  1490.       if (tmr)
  1491.     p = tmr->thread;
  1492. #else
  1493.       p = tmr;
  1494. #endif
  1495.     }
  1496.       
  1497.   } while (tmr && (!time_read || GTEQ_TIME(now, tmr->tp)));
  1498.  
  1499.   /*
  1500.    * if head of timer queue hasn't changed, no action
  1501.    */
  1502.   if (tmr == old_tmr_head) {
  1503. #ifdef TIMER_DEBUG
  1504.     fprintf(stderr, "pthread_cancel_timed_sigwait: exit2\n");
  1505. #endif
  1506.     return(0);
  1507.   }
  1508.  
  1509.   /*
  1510.    * overwrite timer if current request needs to be served next or invalidate
  1511.    */
  1512.   if (tmr != NO_TIMER)
  1513.     MINUS_TIME(it.it_value, tmr->tp, now);
  1514.   else
  1515.     it.it_value.tv_sec = it.it_value.tv_usec = 0;
  1516.  
  1517.   it.it_interval.tv_sec = it.it_interval.tv_usec = 0;
  1518.   if (setitimer(ITIMER_REAL, &it, (struct itimerval *) NULL)) {
  1519. #ifdef DEBUG
  1520.     fprintf(stderr, "ERROR: setitimer in pthread_cancel_timed_sigwait\n");
  1521. #endif
  1522.     set_errno(EINVAL);
  1523.     return(-1);
  1524.   }
  1525.  
  1526. #ifdef TIMER_DEBUG
  1527.   last_alarm.tv_sec = it.it_value.tv_sec;
  1528.   last_alarm.tv_usec = it.it_value.tv_usec;
  1529. #endif
  1530.  
  1531. #ifdef TIMER_DEBUG
  1532.   fprintf(stderr, "pthread_cancel_timed_sigwait: setitimer %d.%d sec.usec\n",
  1533.       it.it_value.tv_sec, it.it_value.tv_usec);
  1534. #endif
  1535.   
  1536.   return(0);
  1537. }
  1538.  
  1539. #endif STAND_ALONE
  1540.  
  1541. /*------------------------------------------------------------*/
  1542. /*
  1543.  * raise - send a signal to the current process;
  1544.  * NOT directed to any particular thread,
  1545.  * any thread waiting for the signal may pick it up.
  1546.  */
  1547. int raise(sig)
  1548. int sig;
  1549. {
  1550.   SET_KERNEL_FLAG;
  1551.   SIM_SYSCALL(TRUE);
  1552. #ifdef C_CONTEXT_SWITCH
  1553.   if (!SAVE_CONTEXT(mac_pthread_self()))
  1554. #endif
  1555.     pthread_signal_sched(sig, (int) NO_PTHREAD);
  1556.  
  1557. #ifdef C_CONTEXT_SWITCH
  1558.   CLEAR_KERNEL_FLAG;
  1559. #endif
  1560.  
  1561.   return(0);
  1562. }
  1563.  
  1564. /*------------------------------------------------------------*/
  1565. /*
  1566.  * pthread_kill - send signal to thread
  1567.  */
  1568. int pthread_kill(thread, sig)
  1569. pthread_t thread;
  1570. int sig;
  1571. {
  1572.   if (thread == NO_PTHREAD || thread->state & T_RETURNED ||
  1573.       sigismember(&cantmask, sig) || !sigismember(&all_signals, sig)) {
  1574.     set_errno(EINVAL);
  1575.     return(-1);
  1576.   }
  1577.  
  1578.   /*
  1579.    * queue up signal associated with thread
  1580.    */
  1581.   SET_KERNEL_FLAG;
  1582.   SIM_SYSCALL(TRUE);
  1583. #ifdef C_CONTEXT_SWITCH
  1584.   if (!SAVE_CONTEXT(mac_pthread_self()))
  1585. #endif
  1586.     pthread_signal_sched(sig, (int) thread);
  1587.  
  1588. #ifdef C_CONTEXT_SWITCH
  1589.   CLEAR_KERNEL_FLAG;
  1590. #endif
  1591.  
  1592.   return(0);
  1593. }
  1594.  
  1595. /*------------------------------------------------------------*/
  1596. /*
  1597.  * pthread_cancel - cancel thread
  1598.  * Open question: is this an interruption point if a thread cancels itself?
  1599.  * As of now, it isn't!
  1600.  */
  1601. int pthread_cancel(thread)
  1602. pthread_t thread;
  1603. {
  1604.   if (thread == NO_PTHREAD || thread->state & T_RETURNED) {
  1605.     set_errno(EINVAL);
  1606.     return(-1);
  1607.   }
  1608.  
  1609.   /*
  1610.    * queue up signal associated with thread
  1611.    */
  1612.   SET_KERNEL_FLAG;
  1613.   SIM_SYSCALL(TRUE);
  1614. #ifdef C_CONTEXT_SWITCH
  1615.   if (!SAVE_CONTEXT(mac_pthread_self()))
  1616. #endif
  1617.     pthread_signal_sched(SIGCANCEL, (int) thread);
  1618.  
  1619. #ifdef C_CONTEXT_SWITCH
  1620.   CLEAR_KERNEL_FLAG;
  1621. #endif
  1622.  
  1623.   return(0);
  1624. }
  1625.  
  1626. /*------------------------------------------------------------*/
  1627. /*
  1628.  * pthread_setintr - set interruptablility state for thread cancellation
  1629.  */
  1630. int pthread_setintr(state)
  1631.      int state;
  1632. {
  1633.   int old;
  1634.   sigset_t new;
  1635.  
  1636.   if (state != PTHREAD_INTR_ENABLE && state != PTHREAD_INTR_DISABLE) {
  1637.     set_errno(EINVAL);
  1638.     return(-1);
  1639.   }
  1640.   
  1641.   SIM_SYSCALL(TRUE);
  1642.   old = (sigismember(&mac_pthread_self()->mask, SIGCANCEL) ?
  1643.      PTHREAD_INTR_DISABLE : PTHREAD_INTR_ENABLE);
  1644.   sigemptyset(&new);
  1645.   sigaddset(&new, SIGCANCEL);
  1646.   if (sigprocmask(state, &new, (sigset_t *) NULL) == 0)
  1647.     return(old);
  1648.   else
  1649.     return(-1);
  1650. }
  1651.  
  1652. /*------------------------------------------------------------*/
  1653. /*
  1654.  * pthread_setintrtype - set interruptablility type for thread cancellation
  1655.  */
  1656. int pthread_setintrtype(type)
  1657.      int type;
  1658. {
  1659.   register pthread_t p = mac_pthread_self();
  1660.   int old;
  1661.   
  1662.   old = (p->state & T_CONTROLLED ?
  1663.      PTHREAD_INTR_CONTROLLED : PTHREAD_INTR_ASYNCHRONOUS);
  1664.   switch (type) {
  1665.   case PTHREAD_INTR_CONTROLLED:
  1666.     SET_KERNEL_FLAG;
  1667.     p->state |= T_CONTROLLED;
  1668.     SIM_SYSCALL(TRUE);
  1669.     CLEAR_KERNEL_FLAG;
  1670.     return(old);
  1671.   case PTHREAD_INTR_ASYNCHRONOUS:
  1672.     SET_KERNEL_FLAG;
  1673.     p->state &= ~T_CONTROLLED;
  1674.     if (sigismember(&p->pending, SIGCANCEL) &&
  1675.     !sigismember(&p->mask, SIGCANCEL)) {
  1676.       p->state |= T_INTR_POINT;
  1677.       SIG_CLEAR_KERNEL_FLAG(TRUE);
  1678.     }
  1679.     else {
  1680.       SIM_SYSCALL(TRUE);
  1681.       CLEAR_KERNEL_FLAG;
  1682.     }
  1683.     return(old);
  1684.   default:
  1685.     set_errno(EINVAL);
  1686.     return(-1);
  1687.   }
  1688. }
  1689.  
  1690. /*------------------------------------------------------------*/
  1691. /*
  1692.  * pthread_testintr - act upon pending cancellation (creates interruption point)
  1693.  */
  1694. void pthread_testintr()
  1695. {
  1696.   register pthread_t p = mac_pthread_self();
  1697.  
  1698.   SET_KERNEL_FLAG;
  1699.   if (sigismember(&p->pending, SIGCANCEL) &&
  1700.       !sigismember(&p->mask, SIGCANCEL)) {
  1701.     p->state |= T_INTR_POINT;
  1702.     SIG_CLEAR_KERNEL_FLAG(TRUE);
  1703.   }
  1704.   else {
  1705.     SIM_SYSCALL(TRUE);
  1706.     CLEAR_KERNEL_FLAG;
  1707.   }
  1708. }
  1709.  
  1710. /*------------------------------------------------------------*/
  1711. /*
  1712.  * sigaction - install interrupt handler for a thread on a signal
  1713.  * return 0 if o.k., -1 otherwise
  1714.  * Notice: cannot mask SIGKILL, SIGSTOP, SIGCANCEL
  1715.  */
  1716. int sigaction(sig, act, oact)
  1717. int sig;
  1718. const struct sigaction *act;
  1719. struct sigaction *oact;
  1720. {
  1721.   register pthread_t p = mac_pthread_self();
  1722.   struct sigaction vec;
  1723.  
  1724. #if defined(SOLARIS) && defined(IO)
  1725.   /*
  1726.    * Handling for asynchronous process level IO under Solaris.
  1727.    * Under certain conditions, call sigaction() in libaio.so.
  1728.    * The aio library seems to contain some bugs. When stdin and stdout
  1729.    * are pending, the stdin seems to lock stdout at some point, until
  1730.    * it gets more input. This may be a result of mutually exclusive file
  1731.    * access under Solaris through mutexes. As a result, the Pthreads library
  1732.    * can no longer guarantee that the process continues to execute while
  1733.    * there is a runnable thread. It tries to do its best until Solaris
  1734.    * gets the upper hand and blocks an otherwise runnable LWP performing IO.
  1735.    * This problem may not occur when the accessed devices are distict.
  1736.    * (Notice that stdin requires an echo, this accessing stdout. Thus, the
  1737.    * two devices are not necessarily distinct.)
  1738.    * This problem does not occur under SunOS 4.1.x.
  1739.    */
  1740.   void *handle;
  1741.   extern int pthread_started;
  1742.   int (*clib_sigaction)
  1743.     _C_PROTOTYPE((int __sig,
  1744.                   const struct sigaction *__act,
  1745.                   struct sigaction *__oact));
  1746.  
  1747.   if (!pthread_started && sig == SIGIO || /* called from pthread_init_signals */
  1748.       pthread_get_retaddr() < 0) {        /* call from dynamic library */
  1749.     handle = dlopen("libaio.so", RTLD_LAZY);
  1750.     clib_sigaction = (int (*) _C_PROTOTYPE((int __sig,
  1751.                         const struct sigaction *__act,
  1752.                         struct sigaction *__oact)))
  1753.       dlsym(handle, "sigaction");
  1754.     return((*clib_sigaction)(sig, act, oact));
  1755.   }
  1756. #endif SOLARIS && IO
  1757.  
  1758.   if (sigismember(&cantmask, sig) || !sigismember(&all_signals, sig)) {
  1759.     set_errno(EINVAL);
  1760.     return(-1);
  1761.   }
  1762.  
  1763.   if (!act) {
  1764.     if (oact)
  1765.       *oact = pthread_user_handler[sig];
  1766.     return(0);
  1767.   }
  1768.  
  1769.   if (pthread_sigismemberset2set(&act->sa_mask, &cantmask)) {
  1770.     set_errno(EINVAL);
  1771.     return(-1);
  1772.   }
  1773.  
  1774.   SET_KERNEL_FLAG;
  1775.   if (oact)
  1776.     *oact = pthread_user_handler[sig];
  1777.  
  1778.   pthread_user_handler[sig] = *act;
  1779.  
  1780.   /*
  1781.    * queue up mac_pthread_self() in the signal queue indicated
  1782.    */
  1783.   if (!sigismember(&handlerset, sig))
  1784.     sigaddset(&handlerset, sig);
  1785.  
  1786.   /*
  1787.    * dequeue pending signals on process and threads if to be ignored
  1788.    * or perform default action on process if default action chosen
  1789.    */
  1790.   if (act->sa_handler == SIG_IGN || act->sa_handler == SIG_DFL) {
  1791.     if (sigismember(&pending_signals, sig)) {
  1792.       sigdelset(&pending_signals, sig);
  1793.       if (act->sa_handler == SIG_DFL)
  1794.     default_action(sig);
  1795.     }
  1796.  
  1797.     for (p = all.head; p; p = p->next[ALL_QUEUE])
  1798.       if (sigismember(&p->pending, sig)) {
  1799.     sigdelset(&p->pending, sig);
  1800.     if (act->sa_handler == SIG_DFL)
  1801.       default_action(sig);
  1802.       }
  1803.   }
  1804.  
  1805. #ifndef STAND_ALONE
  1806.   /*
  1807.    * let UNIX know about sa_flags by reinstalling process handler
  1808.    * for signals that have a defined sa_flags bit
  1809.    */
  1810.   if (sig == SIGCHLD) {
  1811.     vec.sa_handler = act->sa_handler;
  1812.     vec.sa_mask = act->sa_mask;
  1813.     vec.sa_flags = 
  1814. #ifdef SA_NOCLDSTOP
  1815.       (act->sa_flags & SA_NOCLDSTOP ? SA_NOCLDSTOP : 0);
  1816. #else
  1817.       0;
  1818. #endif
  1819.     SIGACTION(sig, &vec, (struct sigaction *) NULL);
  1820.   }
  1821. #endif !STAND_ALONE
  1822.  
  1823.   SIM_SYSCALL(TRUE);
  1824.   CLEAR_KERNEL_FLAG;
  1825.  
  1826.   return(0);
  1827. }
  1828.  
  1829. /*------------------------------------------------------------*/
  1830. /*
  1831.  * pthread_absnanosleep - suspend until abs. time interval specified by "rqtp"
  1832.  */
  1833. int pthread_absnanosleep(rqtp)
  1834. const struct timespec *rqtp;
  1835. {
  1836.   register pthread_t p = mac_pthread_self();
  1837.   struct timespec rmtp;
  1838. #ifdef STAND_ALONE
  1839.   struct timespec now;
  1840. #else
  1841.   timer_ent_t tmr;
  1842.   struct timeval now;
  1843. #endif
  1844.  
  1845.   rmtp.tv_sec = rqtp->tv_sec;
  1846.   rmtp.tv_nsec = rqtp->tv_nsec;
  1847.  
  1848.   do {
  1849.     SET_KERNEL_FLAG;
  1850.     
  1851.     if (pthread_timed_sigwait(p, rmtp, ABS_TIME, NULL, NULL) == -1) {
  1852.       CLEAR_KERNEL_FLAG;
  1853.       return(-1);
  1854.     }
  1855.  
  1856.     /*
  1857.      * clear error number before suspending
  1858.      */
  1859.     set_errno(0);
  1860.     
  1861.     p->state &= ~T_RUNNING;
  1862.     p->state |= T_BLOCKED | T_SYNCTIMER | T_INTR_POINT;
  1863.     if (sigismember(&p->pending, SIGCANCEL) &&
  1864.     !sigismember(&p->mask, SIGCANCEL))
  1865.       SIG_CLEAR_KERNEL_FLAG(TRUE);
  1866.     else {
  1867.       pthread_q_deq_head(&ready, PRIMARY_QUEUE);
  1868.       SIM_SYSCALL(TRUE);
  1869.       CLEAR_KERNEL_FLAG;
  1870.     }
  1871.     
  1872.     /*
  1873.      * Check if condition was signaled or time-out was exceeded.
  1874.      */
  1875.     if (get_errno() == EINTR) {
  1876. #ifdef STAND_ALONE
  1877.       clock_gettime(CLOCK_REALTIME, &now);
  1878.       if (pthread_timer = p)
  1879.     if (GT_NTIME(p->tp, now))
  1880.       MINUS_NTIME(rmtp, p->tp, now);
  1881. #else !STAND_ALONE
  1882.       if (gettimeofday(&now, (struct timezone *) NULL)) {
  1883.     set_errno(EINVAL);
  1884.     return(-1);
  1885.       }
  1886.  
  1887. #ifdef DEF_RR
  1888.       if (tmr = pthread_timer.head) {
  1889.     while (tmr->thread != p)
  1890.       tmr = tmr->next[TIMER_QUEUE];
  1891. #else
  1892.       if (tmr = p) {
  1893. #endif
  1894.     
  1895.     if (GT_TIME(tmr->tp, now)) {
  1896.       MINUS_TIME(now, tmr->tp, now);
  1897.       U2P_TIME((rmtp), now);
  1898.     }
  1899.       }
  1900. #endif !STAND_ALONE
  1901.     }
  1902.     else
  1903.       NTIMERCLEAR(rmtp);
  1904.   } while (!LE0_NTIME(rmtp));
  1905.  
  1906.   return(0);
  1907. }
  1908.  
  1909. /*------------------------------------------------------------*/
  1910. /*
  1911.  * nanosleep - suspend until time interval specified by "rqtp" has passed
  1912.  * or a user handler is invoked or the thread is canceled
  1913.  */
  1914. int nanosleep(rqtp, rmtp)
  1915. const struct timespec *rqtp;
  1916. struct timespec *rmtp;
  1917. {
  1918.   register pthread_t p = mac_pthread_self();
  1919. #ifdef STAND_ALONE
  1920.   struct timespec now;
  1921. #else
  1922.   timer_ent_t tmr;
  1923.   struct timeval now;
  1924. #endif
  1925.  
  1926.   if (rmtp)
  1927.     rmtp->tv_sec = rmtp->tv_nsec = 0;
  1928.  
  1929.   SET_KERNEL_FLAG;
  1930.  
  1931.   if (pthread_timed_sigwait(p, rqtp, REL_TIME, NULL, NULL) == -1) {
  1932.     CLEAR_KERNEL_FLAG;
  1933.     return(-1);
  1934.   }
  1935.  
  1936.   /*
  1937.    * clear error number before suspending
  1938.    */
  1939.   set_errno(0);
  1940.  
  1941.   p->state &= ~T_RUNNING;
  1942.   p->state |= T_BLOCKED | T_SYNCTIMER | T_INTR_POINT;
  1943.   if (sigismember(&p->pending, SIGCANCEL) &&
  1944.       !sigismember(&p->mask, SIGCANCEL))
  1945.     SIG_CLEAR_KERNEL_FLAG(TRUE);
  1946.   else {
  1947.     pthread_q_deq_head(&ready, PRIMARY_QUEUE);
  1948.     SIM_SYSCALL(TRUE);
  1949.     CLEAR_KERNEL_FLAG;
  1950.   }
  1951.  
  1952.   /*
  1953.    * Check if condition was signaled or time-out was exceeded.
  1954.    */
  1955.   if (get_errno() == EINTR) {
  1956. #ifdef STAND_ALONE
  1957.     clock_gettime(CLOCK_REALTIME, &now);
  1958.     if (pthread_timer = p)
  1959.       if (GT_NTIME(p->tp, now)) {
  1960.         if (rmtp)
  1961.           MINUS_NTIME(*rmtp, p->tp, now);
  1962.         return(-1);
  1963.       }
  1964. #else !STAND_ALONE
  1965.     if (gettimeofday(&now, (struct timezone *) NULL)) {
  1966.       set_errno(EINVAL);
  1967.       return(-1);
  1968.     }
  1969.  
  1970. #ifdef DEF_RR
  1971.     if (tmr = pthread_timer.head) {
  1972.       while (tmr->thread != p)
  1973.     tmr = tmr->next[TIMER_QUEUE];
  1974. #else
  1975.     if (tmr = p) {
  1976. #endif
  1977.     
  1978.       if (GT_TIME(tmr->tp, now)) {
  1979.     if (rmtp) {
  1980.       MINUS_TIME(now, tmr->tp, now);
  1981.       U2P_TIME((*rmtp), now);
  1982.     }
  1983.     return(-1);
  1984.       }
  1985.     }
  1986. #endif STAND_ALONE
  1987.   }
  1988.  
  1989.   return(0);
  1990. }
  1991.  
  1992. /*------------------------------------------------------------*/
  1993. /*
  1994.  * sleep - suspend thread for time interval (in seconds)
  1995.  */
  1996. unsigned int sleep(seconds)
  1997. unsigned int seconds;
  1998. {
  1999.   struct timespec rqtp, rmtp;
  2000.  
  2001.   if (rqtp.tv_sec = seconds) {
  2002.     rqtp.tv_nsec = 0;
  2003.     nanosleep(&rqtp, &rmtp);
  2004.     if (get_errno() == EINTR)
  2005.       return(rmtp.tv_sec + (rmtp.tv_nsec ? 1 : 0)); /* pessimistic round-up */
  2006.   }
  2007.   return(0);
  2008. }
  2009.  
  2010. #ifdef STAND_ALONE
  2011.  
  2012. /*------------------------------------------------------------*/
  2013. /*
  2014.  * clock_gettime - reads the clock
  2015.  */
  2016. int clock_gettime(clock_id, tp)
  2017.      int clock_id;
  2018.      struct timespec *tp;
  2019. {
  2020.   time_t secs;
  2021.   unsigned int nsecs;
  2022.  
  2023.   if (clock_id != CLOCK_REALTIME || !tp) {
  2024.     set_errno(EINVAL);
  2025.     return(-1);
  2026.   }
  2027.   do {
  2028.     do {
  2029.       tp->tv_sec =  timeofday.tv_sec;
  2030.       tp->tv_nsec =  timeofday.tv_nsec;
  2031.       secs = timeofday.tv_sec;
  2032.     } while (tp->tv_sec != secs);
  2033.     nsecs = (COUNTER->counter14 & CTR_USEC_MASK) >> CTR_USEC_SHIFT;
  2034.   } while (tp->tv_nsec != timeofday.tv_nsec);
  2035.   tp->tv_nsec += nsecs * 1000;
  2036.   return(0);
  2037. }
  2038.  
  2039. #else !STAND_ALONE
  2040.  
  2041. /*------------------------------------------------------------*/
  2042. /*
  2043.  * clock_gettime - reads the clock
  2044.  */
  2045. int clock_gettime(clock_id, tp)
  2046. int clock_id;
  2047. struct timespec *tp;
  2048. {
  2049.   struct timeval now;
  2050.  
  2051.   if (clock_id != CLOCK_REALTIME || !tp ||
  2052.       gettimeofday(&now, (struct timezone *) NULL)) {
  2053.     set_errno(EINVAL);
  2054.     return(-1);
  2055.   }
  2056.  
  2057.   U2P_TIME((*tp), now);
  2058.   return(0);
  2059. }
  2060.  
  2061. #endif STAND_ALONE
  2062.  
  2063. #ifdef IO
  2064. /*-------------------------------------------------------------*/
  2065. /*
  2066.  * fds_update - update fields of file descriptors
  2067.  */
  2068. static int fds_update(lrfds, lwfds, lefds, grfds, gwfds, gefds, width)
  2069.      fd_set *lrfds, *lwfds, *lefds, *grfds, *gwfds, *gefds;
  2070.      int width;
  2071. {
  2072.   int i;
  2073.   int result = 0;
  2074.   fd_set crfds, cwfds, cefds, gfds;
  2075.  
  2076.   FD_ZERO(&crfds);
  2077.   FD_ZERO(&cwfds);
  2078.   FD_ZERO(&cefds);
  2079.  
  2080.   for (i=0; i < howmany(width, NFDBITS); i++){
  2081.     crfds.fds_bits [i] = (*lrfds).fds_bits [i] & (*grfds).fds_bits [i];
  2082.     cwfds.fds_bits [i] = (*lwfds).fds_bits [i] & (*gwfds).fds_bits [i];
  2083.     cefds.fds_bits [i] = (*lefds).fds_bits [i] & (*gefds).fds_bits [i];
  2084.     gfds.fds_bits [i]  = crfds.fds_bits [i] | cwfds.fds_bits [i] |
  2085.       cefds.fds_bits [i];
  2086.   }
  2087.  
  2088.   for (i=0; i < width; i++)
  2089.     if FD_ISSET (i, &gfds)
  2090.       result++;
  2091.  
  2092.   if (result > 0) {
  2093.     *lrfds = crfds;
  2094.     *lwfds = cwfds;
  2095.     *lefds = cefds;
  2096.   }
  2097.  
  2098.   return(result);
  2099. }
  2100.  
  2101. /*-------------------------------------------------------------*/
  2102. /*
  2103.  * fds_subtract - delete fields of file descriptors
  2104.  */
  2105. static void fds_subtract(l,r, width)
  2106.      struct fd_set *l,*r;
  2107.      int width;
  2108. {
  2109.   int i;
  2110.  
  2111.   for (i=0; i < howmany(width, NFDBITS); i++) 
  2112.     (*l).fds_bits[i] = (*l).fds_bits[i] & ~(*r).fds_bits[i];
  2113. }
  2114.  
  2115. /*-------------------------------------------------------------*/
  2116. /*
  2117.  * aio_handle - handler for asynchronous I/O on process level,
  2118.  * demultiplexes SIGIO for threads
  2119.  */
  2120. static int aio_handle()
  2121. {
  2122.   pthread_t p;
  2123.   int count = 0;
  2124.  
  2125. #ifndef SVR4
  2126.   static struct timeval mintimeout = {0, 0};
  2127.   fd_set creadfds, cwritefds, cexceptfds;
  2128.   int cwidth = gwidth;
  2129.   int flag;
  2130.  
  2131.   if (gwidth > 0) {
  2132.     pthread_fds_set(&creadfds, &greadfds);
  2133.     pthread_fds_set(&cwritefds, &gwritefds);
  2134.     pthread_fds_set(&cexceptfds, &gexceptfds);
  2135.     if (SELECT(gwidth, &creadfds, &cwritefds, &cexceptfds, &mintimeout) > 0) {
  2136.       fds_subtract(&greadfds, &creadfds, gwidth);
  2137.       fds_subtract(&gwritefds, &cwritefds, gwidth);
  2138.       fds_subtract(&gexceptfds, &cexceptfds, gwidth);
  2139.       while (gwidth != 0 && 
  2140.          !FD_ISSET(gwidth-1, &greadfds) &&
  2141.          !FD_ISSET(gwidth-1, &gwritefds) &&
  2142.          !FD_ISSET(gwidth-1, &gexceptfds))
  2143.     gwidth--;
  2144.     }
  2145.   }
  2146. #endif !SVR4
  2147.   
  2148.   for(p = all.head; p; p = p->next[ALL_QUEUE]) {
  2149.     if (p->state & T_IO_OVER) {
  2150.       p->state &= ~T_IO_OVER;
  2151.       count++;
  2152.       continue;
  2153.     }
  2154.     else if (sigismember(&p->sigwaitset, AIO_SIG))
  2155. #ifndef SVR4
  2156.       if (cwidth > 0 && p->wait_on_select) {
  2157.     p->how_many = fds_update(&p->readfds, &p->writefds, &p->exceptfds,
  2158.                  &creadfds, &cwritefds, &cexceptfds, p->width);
  2159.     if (p->how_many > 0) {
  2160. #ifdef DEBUG
  2161.       fprintf(stderr, "wake up select\n");
  2162. #endif
  2163.       count++;
  2164.       pthread_q_wakeup_thread(NO_QUEUE, p, NO_QUEUE_INDEX);
  2165.       sigdelset(&p->sigwaitset, AIO_SIG);
  2166.       if (p->state & T_SYNCTIMER)
  2167.         pthread_cancel_timed_sigwait(p, FALSE, SYNC_TIME, TRUE);
  2168.       p->wait_on_select = FALSE;
  2169.     }
  2170.       }
  2171.       else
  2172. #endif !SVR4
  2173.     if (p->resultp.aio_return != AIO_INPROGRESS) {
  2174.       count++;
  2175.       pthread_q_wakeup_thread(NO_QUEUE, p, NO_QUEUE_INDEX);
  2176.       sigdelset(&p->sigwaitset, AIO_SIG);
  2177.     }
  2178.   }
  2179.  
  2180.   if (count)
  2181.     return(TRUE);
  2182.   else
  2183.     return(FALSE);
  2184. }
  2185. #endif
  2186. /*-------------------------------------------------------------*/
  2187.  
  2188. #ifdef STAND_ALONE
  2189. /*------------------------------------------------------------*/
  2190. /*
  2191.  * alarm - Deliver SIGALARM after "seconds"
  2192.  */
  2193. unsigned int alarm(seconds)
  2194.      unsigned int seconds;
  2195. {
  2196.   set_errno(ENOSYS);
  2197.   return(-1);
  2198. }
  2199. #endif STAND_ALONE
  2200.  
  2201. /*------------------------------------------------------------*/
  2202. /*
  2203.  * pthread_setsigcontext_np - modify the signal context to return to a setjmp()
  2204.  * call location, i.e. simulate a longjmp() but leave the signal handler
  2205.  * properly.
  2206.  */
  2207. void pthread_setsigcontext_np(scp, env, val)
  2208.      struct context_t *scp;
  2209.      jmp_buf env;
  2210.      int val;
  2211. {
  2212.   scp->sc_pc = env[JB_PC];
  2213.   scp->sc_npc = env[JB_PC] + 4;
  2214. #if defined(ASM_SETJMP) || !defined(C_CONTEXT_SWITCH)
  2215.   scp->sc_pc += RETURN_OFFSET;
  2216.   scp->sc_npc += RETURN_OFFSET;
  2217. #endif defined(ASM_SETJMP) || !defined(C_CONTEXT_SWITCH)
  2218.   scp->sc_sp = env[JB_SP];
  2219.   if (env[JB_SVMASK])
  2220.     pthread_sigcpyset2set(&scp->sc_mask, &env[JB_MASK]); /* copy sigmasks */
  2221.   scp->sc_o0 = val; 
  2222. }
  2223.  
  2224. /*------------------------------------------------------------*/
  2225. /*
  2226.  * SIGPROCMASK - change or examine signal mask of process
  2227.  */
  2228. int SIGPROCMASK(how, set, oset)
  2229. int how;
  2230. const sigset_t *set;
  2231. sigset_t *oset;
  2232. {
  2233. #ifdef SVR4
  2234.   return(syscall(SYS_sigprocmask, how, set, oset));
  2235. #else !SVR4
  2236.   sigset_t old;
  2237.  
  2238. #ifndef STAND_ALONE
  2239.   proc_mask = sigblock(0);
  2240. #endif !STAND_ALONE
  2241.  
  2242.   if (oset)
  2243.     pthread_sigcpyset2set(oset, &proc_mask);
  2244.  
  2245.   if (!set)
  2246.     return(0);
  2247.  
  2248.   switch (how) {
  2249.   case SIG_BLOCK:
  2250.     pthread_sigaddset2set(&proc_mask, set);
  2251.     break;
  2252.   case SIG_UNBLOCK:
  2253.     pthread_sigdelset2set(&proc_mask, set);
  2254.     break;
  2255.   case SIG_SETMASK:
  2256.     pthread_sigcpyset2set(&proc_mask, set);
  2257.     break;
  2258.   default:
  2259.     set_errno(EINVAL);
  2260.     return(-1);
  2261.   }
  2262.  
  2263.   pthread_sigdelset2set(&proc_mask, &cantmask);
  2264. #ifndef STAND_ALONE
  2265.   sigsetmask(proc_mask);
  2266. #endif !STAND_ALONE
  2267.   
  2268.   return(0);
  2269. #endif !SVR4
  2270. }
  2271.  
  2272. /*------------------------------------------------------------*/
  2273. /*
  2274.  * SIGACTION - change or examine signal handlers of process
  2275.  */
  2276. int SIGACTION(sig, act, oact)
  2277. int sig;
  2278. const struct sigaction *act;
  2279. struct sigaction *oact;
  2280. {
  2281. #ifdef SVR4
  2282. #if defined(SOLARIS) && defined(IO)
  2283.   if (sig == SIGIO)
  2284.     sigaction(sig, act, oact);
  2285.   else
  2286. #endif SOLARIS && IO
  2287.     return(syscall(SYS_sigaction, sig, act, oact));
  2288. #else !SVR4
  2289. #ifndef STAND_ALONE
  2290.   return(sigvec(sig, act, oact)); /* cheating: structs distinct / same layout */
  2291. #else !STAND_ALONE
  2292.   set_errno(EINVAL);
  2293.   return(-1);
  2294. #endif !STAND_ALONE
  2295. #endif !SVR4
  2296. }
  2297.  
  2298. /*------------------------------------------------------------*/
  2299. /*
  2300.  * SIGSUSPEND - suspend process waiting for signals
  2301.  */
  2302. int SIGSUSPEND(set)
  2303. sigset_t *set;
  2304. {
  2305. #ifdef SVR4
  2306.   return(syscall(SYS_sigsuspend, set));
  2307. #else !SVR4
  2308. #ifndef STAND_ALONE
  2309.   return(sigpause(*set));
  2310. #else !STAND_ALONE
  2311.   /* busy wait */;
  2312. #endif !STAND_ALONE
  2313. #endif !SVR4
  2314. }
  2315.  
  2316. #if defined(IO) && !defined(SVR4)
  2317. /*------------------------------------------------------------*/
  2318. /*
  2319.  * ACCEPT - accept call
  2320.  */
  2321. int ACCEPT(s, addr, addrlen)
  2322.      int s;
  2323.      struct sockaddr *addr;
  2324.      int *addrlen;
  2325. {
  2326.   return(syscall(SYS_accept, s, addr, addrlen));
  2327. }
  2328.  
  2329. /*------------------------------------------------------------*/
  2330. /*
  2331.  * SELECT - select call
  2332.  */
  2333. int SELECT(width, readfds, writefds, exceptfds, timeout)
  2334.      int width;
  2335.      fd_set *readfds, *writefds, *exceptfds;
  2336.      struct timeval *timeout;
  2337. {
  2338.   return(syscall(SYS_select, width, readfds, writefds, exceptfds, timeout));
  2339. }
  2340. #endif IO && !SVR4
  2341.