Initial import from FreeBSD RELENG_4:
[dragonfly.git] / lib / libc_r / uthread / uthread_sig.c
1 /*
2  * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by John Birrell.
16  * 4. Neither the name of the author nor the names of any co-contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * $FreeBSD: src/lib/libc_r/uthread/uthread_sig.c,v 1.25.2.13 2002/10/22 14:44:03 fjoe Exp $
33  */
34 #include <sys/param.h>
35 #include <sys/types.h>
36 #include <sys/signalvar.h>
37 #include <signal.h>
38 #include <fcntl.h>
39 #include <unistd.h>
40 #include <setjmp.h>
41 #include <errno.h>
42 #include <pthread.h>
43 #include "pthread_private.h"
44
45 /* Prototypes: */
46 static void     thread_sig_add(struct pthread *pthread, int sig, int has_args);
47 static void     thread_sig_check_state(struct pthread *pthread, int sig);
48 static struct pthread *thread_sig_find(int sig);
49 static void     thread_sig_handle_special(int sig);
50 static void     thread_sigframe_add(struct pthread *thread, int sig,
51                     int has_args);
52 static void     thread_sigframe_save(struct pthread *thread,
53                     struct pthread_signal_frame *psf);
54 static void     thread_sig_invoke_handler(int sig, siginfo_t *info,
55                     ucontext_t *ucp);
56
57 /*#define DEBUG_SIGNAL*/
58 #ifdef DEBUG_SIGNAL
59 #define DBG_MSG         stdout_debug
60 #else
61 #define DBG_MSG(x...)
62 #endif
63
64 #if defined(_PTHREADS_INVARIANTS)
65 #define SIG_SET_ACTIVE()        _sig_in_handler = 1
66 #define SIG_SET_INACTIVE()      _sig_in_handler = 0
67 #else
68 #define SIG_SET_ACTIVE()
69 #define SIG_SET_INACTIVE()
70 #endif
71
72 void
73 _thread_sig_handler(int sig, siginfo_t *info, ucontext_t *ucp)
74 {
75         struct pthread  *curthread = _get_curthread();
76         struct pthread  *pthread, *pthread_h;
77         int             in_sched = _thread_kern_in_sched;
78         char            c;
79
80         if (ucp == NULL)
81                 PANIC("Thread signal handler received null context");
82         DBG_MSG("Got signal %d, current thread %p\n", sig, curthread);
83
84         /* Check if an interval timer signal: */
85         if (sig == _SCHED_SIGNAL) {
86                 /* Update the scheduling clock: */
87                 gettimeofday((struct timeval *)&_sched_tod, NULL);
88                 _sched_ticks++;
89
90                 if (in_sched != 0) {
91                         /*
92                          * The scheduler is already running; ignore this
93                          * signal.
94                          */
95                 }
96                 /*
97                  * Check if the scheduler interrupt has come when
98                  * the currently running thread has deferred thread
99                  * signals.
100                  */
101                 else if (curthread->sig_defer_count > 0)
102                         curthread->yield_on_sig_undefer = 1;
103                 else {
104                         /* Schedule the next thread: */
105                         _thread_kern_sched(ucp);
106
107                         /*
108                          * This point should not be reached, so abort the
109                          * process:
110                          */
111                         PANIC("Returned to signal function from scheduler");
112                 }
113         }
114         /*
115          * Check if the kernel has been interrupted while the scheduler
116          * is accessing the scheduling queues or if there is a currently
117          * running thread that has deferred signals.
118          */
119         else if ((in_sched != 0) || (curthread->sig_defer_count > 0)) {
120                 /* Cast the signal number to a character variable: */
121                 c = sig;
122
123                 /*
124                  * Write the signal number to the kernel pipe so that it will
125                  * be ready to read when this signal handler returns.
126                  */
127                 if (_queue_signals != 0) {
128                         __sys_write(_thread_kern_pipe[1], &c, 1);
129                         DBG_MSG("Got signal %d, queueing to kernel pipe\n", sig);
130                 }
131                 if (_thread_sigq[sig - 1].blocked == 0) {
132                         DBG_MSG("Got signal %d, adding to _thread_sigq\n", sig);
133                         /*
134                          * Do not block this signal; it will be blocked
135                          * when the pending signals are run down.
136                          */
137                         /* _thread_sigq[sig - 1].blocked = 1; */
138
139                         /*
140                          * Queue the signal, saving siginfo and sigcontext
141                          * (ucontext).
142                          *
143                          * XXX - Do we need to copy siginfo and ucp?
144                          */
145                         _thread_sigq[sig - 1].signo = sig;
146                         if (info != NULL)
147                                 memcpy(&_thread_sigq[sig - 1].siginfo, info,
148                                     sizeof(*info));
149                         memcpy(&_thread_sigq[sig - 1].uc, ucp, sizeof(*ucp));
150
151                         /* Indicate that there are queued signals: */
152                         _thread_sigq[sig - 1].pending = 1;
153                         _sigq_check_reqd = 1;
154                 }
155                 /* These signals need special handling: */
156                 else if (sig == SIGCHLD || sig == SIGTSTP ||
157                     sig == SIGTTIN || sig == SIGTTOU) {
158                         _thread_sigq[sig - 1].pending = 1;
159                         _thread_sigq[sig - 1].signo = sig;
160                         _sigq_check_reqd = 1;
161                 }
162                 else
163                         DBG_MSG("Got signal %d, ignored.\n", sig);
164         }
165         /*
166          * The signal handlers should have been installed so that they
167          * cannot be interrupted by other signals.
168          */
169         else if (_thread_sigq[sig - 1].blocked == 0) {
170                 /*
171                  * The signal is not blocked; handle the signal.
172                  *
173                  * Ignore subsequent occurrences of this signal
174                  * until the current signal is handled:
175                  */
176                 _thread_sigq[sig - 1].blocked = 1;
177
178                 /* This signal will be handled; clear the pending flag: */
179                 _thread_sigq[sig - 1].pending = 0;
180
181                 /*
182                  * Save siginfo and sigcontext (ucontext).
183                  *
184                  * XXX - Do we need to copy siginfo and ucp?
185                  */
186                 _thread_sigq[sig - 1].signo = sig;
187
188                 if (info != NULL)
189                         memcpy(&_thread_sigq[sig - 1].siginfo, info,
190                             sizeof(*info));
191                 memcpy(&_thread_sigq[sig - 1].uc, ucp, sizeof(*ucp));
192                 SIG_SET_ACTIVE();
193
194                 /* Handle special signals: */
195                 thread_sig_handle_special(sig);
196
197                 pthread_h = NULL;
198                 if ((pthread = thread_sig_find(sig)) == NULL)
199                         DBG_MSG("No thread to handle signal %d\n", sig);
200                 else if (pthread == curthread) {
201                         /*
202                          * Unblock the signal and restore the process signal
203                          * mask in case we don't return from the handler:
204                          */
205                         _thread_sigq[sig - 1].blocked = 0;
206                         __sys_sigprocmask(SIG_SETMASK, &_process_sigmask, NULL);
207
208                         /* Call the signal handler for the current thread: */
209                         thread_sig_invoke_handler(sig, info, ucp);
210
211                         /*
212                          * Set the process signal mask in the context; it
213                          * could have changed by the handler.
214                          */
215                         ucp->uc_sigmask = _process_sigmask;
216  
217                         /* Resume the interrupted thread: */
218                         sigreturn(ucp);
219                 } else {
220                         DBG_MSG("Got signal %d, adding frame to thread %p\n",
221                             sig, pthread);
222
223                         /* Setup the target thread to receive the signal: */
224                         thread_sig_add(pthread, sig, /*has_args*/ 1);
225
226                         /* Take a peek at the next ready to run thread: */
227                         pthread_h = PTHREAD_PRIOQ_FIRST();
228                         DBG_MSG("Finished adding frame, head of prio list %p\n",
229                             pthread_h);
230                 }
231                 SIG_SET_INACTIVE();
232
233                 /*
234                  * Switch to a different context if the currently running
235                  * thread takes a signal, or if another thread takes a
236                  * signal and the currently running thread is not in a
237                  * signal handler.
238                  */
239                 if ((pthread_h != NULL) &&
240                     (pthread_h->active_priority > curthread->active_priority)) {
241                         /* Enter the kernel scheduler: */
242                         _thread_kern_sched(ucp);
243                 }
244         }
245         else {
246                 SIG_SET_ACTIVE();
247                 thread_sig_handle_special(sig);
248                 SIG_SET_INACTIVE();
249         }
250 }
251
252 static void
253 thread_sig_invoke_handler(int sig, siginfo_t *info, ucontext_t *ucp)
254  {
255         struct pthread  *curthread = _get_curthread();
256         void (*sigfunc)(int, siginfo_t *, void *);
257         int             saved_seqno;
258         sigset_t        saved_sigmask;
259
260         /* Invoke the signal handler without going through the scheduler:
261          */
262         DBG_MSG("Got signal %d, calling handler for current thread %p\n",
263             sig, curthread);
264
265         /* Save the threads signal mask: */
266         saved_sigmask = curthread->sigmask;
267         saved_seqno = curthread->sigmask_seqno;
268  
269         /* Setup the threads signal mask: */
270         SIGSETOR(curthread->sigmask, _thread_sigact[sig - 1].sa_mask);
271         sigaddset(&curthread->sigmask, sig);
272  
273         /*
274          * Check that a custom handler is installed and if
275          * the signal is not blocked:
276          */
277         sigfunc = _thread_sigact[sig - 1].sa_sigaction;
278         if (((__sighandler_t *)sigfunc != SIG_DFL) &&
279             ((__sighandler_t *)sigfunc != SIG_IGN)) {
280                 if (((_thread_sigact[sig - 1].sa_flags & SA_SIGINFO) != 0) ||
281                     (info == NULL))
282                         (*(sigfunc))(sig, info, ucp);
283                 else
284                         (*(sigfunc))(sig, (siginfo_t *)info->si_code, ucp);
285         }
286         /*
287          * Only restore the signal mask if it hasn't been changed by the
288          * application during invocation of the signal handler:
289          */
290         if (curthread->sigmask_seqno == saved_seqno)
291                 curthread->sigmask = saved_sigmask;
292 }
293
294 /*
295  * Find a thread that can handle the signal.
296  */
297 struct pthread *
298 thread_sig_find(int sig)
299 {
300         struct pthread  *curthread = _get_curthread();
301         int             handler_installed;
302         struct pthread  *pthread, *pthread_next;
303         struct pthread  *suspended_thread, *signaled_thread;
304
305         DBG_MSG("Looking for thread to handle signal %d\n", sig);
306         /* Check if the signal requires a dump of thread information: */
307         if (sig == SIGINFO) {
308                 /* Dump thread information to file: */
309                 _thread_dump_info();
310
311                 /* Unblock this signal to allow further dumps: */
312                 _thread_sigq[sig - 1].blocked = 0;
313         }
314         /* Check if an interval timer signal: */
315         else if (sig == _SCHED_SIGNAL) {
316                 /*
317                  * This shouldn't ever occur (should this panic?).
318                  */
319         } else {
320                 /*
321                  * Enter a loop to look for threads that have the signal
322                  * unmasked.  POSIX specifies that a thread in a sigwait
323                  * will get the signal over any other threads.  Second
324                  * preference will be threads in in a sigsuspend.  Third
325                  * preference will be the current thread.  If none of the
326                  * above, then the signal is delivered to the first thread
327                  * that is found.  Note that if a custom handler is not
328                  * installed, the signal only affects threads in sigwait.
329                  */
330                 suspended_thread = NULL;
331                 if ((curthread != &_thread_kern_thread) &&
332                     !sigismember(&curthread->sigmask, sig))
333                         signaled_thread = curthread;
334                 else
335                         signaled_thread = NULL;
336                 if ((_thread_sigact[sig - 1].sa_handler == SIG_IGN) ||
337                     (_thread_sigact[sig - 1].sa_handler == SIG_DFL))
338                         handler_installed = 0;
339                 else
340                         handler_installed = 1;
341
342                 for (pthread = TAILQ_FIRST(&_waitingq);
343                     pthread != NULL; pthread = pthread_next) {
344                         /*
345                          * Grab the next thread before possibly destroying
346                          * the link entry.
347                          */
348                         pthread_next = TAILQ_NEXT(pthread, pqe);
349
350                         if ((pthread->state == PS_SIGWAIT) &&
351                             sigismember(pthread->data.sigwait, sig)) {
352                                 /* Change the state of the thread to run: */
353                                 PTHREAD_NEW_STATE(pthread,PS_RUNNING);
354                                 /*
355                                  * A signal handler is not invoked for threads
356                                  * in sigwait.  Clear the blocked and pending
357                                  * flags.
358                                  */
359                                 _thread_sigq[sig - 1].blocked = 0;
360                                 _thread_sigq[sig - 1].pending = 0;
361
362                                 /* Return the signal number: */
363                                 pthread->signo = sig;
364
365                                 /*
366                                  * POSIX doesn't doesn't specify which thread
367                                  * will get the signal if there are multiple
368                                  * waiters, so we give it to the first thread
369                                  * we find.
370                                  *
371                                  * Do not attempt to deliver this signal
372                                  * to other threads and do not add the signal
373                                  * to the process pending set.
374                                  */
375                                 return (NULL);
376                         }
377                         else if ((handler_installed != 0) &&
378                             !sigismember(&pthread->sigmask, sig) &&
379                             ((pthread->flags & PTHREAD_FLAGS_SUSPENDED) == 0)) {
380                                 if (pthread->state == PS_SIGSUSPEND) {
381                                         if (suspended_thread == NULL)
382                                                 suspended_thread = pthread;
383                                 } else if (signaled_thread == NULL)
384                                         signaled_thread = pthread;
385                         }
386                 }
387
388                 /*
389                  * Only perform wakeups and signal delivery if there is a
390                  * custom handler installed:
391                  */
392                 if (handler_installed == 0) {
393                         /*
394                          * There is no handler installed.  Unblock the
395                          * signal so that if a handler _is_ installed, any
396                          * subsequent signals can be handled.
397                          */
398                         _thread_sigq[sig - 1].blocked = 0;
399                 } else {
400                         /*
401                          * If we didn't find a thread in the waiting queue,
402                          * check the all threads queue:
403                          */
404                         if (suspended_thread == NULL &&
405                             signaled_thread == NULL) {
406                                 /*
407                                  * Enter a loop to look for other threads
408                                  * capable of receiving the signal:
409                                  */
410                                 TAILQ_FOREACH(pthread, &_thread_list, tle) {
411                                         if (!sigismember(&pthread->sigmask,
412                                             sig)) {
413                                                 signaled_thread = pthread;
414                                                 break;
415                                         }
416                                 }
417                         }
418
419                         if (suspended_thread == NULL &&
420                             signaled_thread == NULL)
421                                 /*
422                                  * Add it to the set of signals pending
423                                  * on the process:
424                                  */
425                                 sigaddset(&_process_sigpending, sig);
426                         else {
427                                 /*
428                                  * We only deliver the signal to one thread;
429                                  * give preference to the suspended thread:
430                                  */
431                                 if (suspended_thread != NULL)
432                                         pthread = suspended_thread;
433                                 else
434                                         pthread = signaled_thread;
435                                 return (pthread);
436                         }
437                 }
438         }
439
440         /* Returns nothing. */
441         return (NULL);
442 }
443
444 void
445 _thread_sig_check_pending(struct pthread *pthread)
446 {
447         sigset_t        sigset;
448         int             i;
449
450         /*
451          * Check if there are pending signals for the running
452          * thread or process that aren't blocked:
453          */
454         sigset = pthread->sigpend;
455         SIGSETOR(sigset, _process_sigpending);
456         SIGSETNAND(sigset, pthread->sigmask);
457         if (SIGNOTEMPTY(sigset)) {
458                 for (i = 1; i < NSIG; i++) {
459                         if (sigismember(&sigset, i) != 0) {
460                                 if (sigismember(&pthread->sigpend, i) != 0)
461                                         thread_sig_add(pthread, i,
462                                             /*has_args*/ 0);
463                                 else {
464                                         thread_sig_add(pthread, i,
465                                             /*has_args*/ 1);
466                                         sigdelset(&_process_sigpending, i);
467                                 }
468                         }
469                 }
470         }
471 }
472
473 /*
474  * This can only be called from the kernel scheduler.  It assumes that
475  * all thread contexts are saved and that a signal frame can safely be
476  * added to any user thread.
477  */
478 void
479 _thread_sig_handle_pending(void)
480 {
481         struct pthread  *pthread;
482         int             i, sig;
483
484         PTHREAD_ASSERT(_thread_kern_in_sched != 0,
485             "_thread_sig_handle_pending called from outside kernel schedule");
486         /*
487          * Check the array of pending signals:
488          */
489         for (i = 0; i < NSIG; i++) {
490                 if (_thread_sigq[i].pending != 0) {
491                         /* This signal is no longer pending. */
492                         _thread_sigq[i].pending = 0;
493
494                         sig = _thread_sigq[i].signo;
495
496                         /* Some signals need special handling: */
497                         thread_sig_handle_special(sig);
498
499                         if (_thread_sigq[i].blocked == 0) {
500                                 /*
501                                  * Block future signals until this one
502                                  * is handled:
503                                  */
504                                 _thread_sigq[i].blocked = 1;
505
506                                 if ((pthread = thread_sig_find(sig)) != NULL) {
507                                         /*
508                                          * Setup the target thread to receive
509                                          * the signal:
510                                          */
511                                         thread_sig_add(pthread, sig,
512                                             /*has_args*/ 1);
513                                 }
514                         }
515                 }
516         }
517 }
518
519 static void
520 thread_sig_handle_special(int sig)
521 {
522         struct pthread  *pthread, *pthread_next;
523         int             i;
524
525         switch (sig) {
526         case SIGCHLD:
527                 /*
528                  * Go through the file list and set all files
529                  * to non-blocking again in case the child
530                  * set some of them to block. Sigh.
531                  */
532                 for (i = 0; i < _thread_dtablesize; i++) {
533                         /* Check if this file is used: */
534                         if (_thread_fd_table[i] != NULL) {
535                                 /*
536                                  * Set the file descriptor to non-blocking:
537                                  */
538                                 __sys_fcntl(i, F_SETFL,
539                                     _thread_fd_getflags(i) | O_NONBLOCK);
540                         }
541                 }
542                 /*
543                  * Enter a loop to wake up all threads waiting
544                  * for a process to complete:
545                  */
546                 for (pthread = TAILQ_FIRST(&_waitingq);
547                     pthread != NULL; pthread = pthread_next) {
548                         /*
549                          * Grab the next thread before possibly
550                          * destroying the link entry:
551                          */
552                         pthread_next = TAILQ_NEXT(pthread, pqe);
553
554                         /*
555                          * If this thread is waiting for a child
556                          * process to complete, wake it up:
557                          */
558                         if (pthread->state == PS_WAIT_WAIT) {
559                                 /* Make the thread runnable: */
560                                 PTHREAD_NEW_STATE(pthread,PS_RUNNING);
561
562                                 /* Return the signal number: */
563                                 pthread->signo = sig;
564                         }
565                 }
566                 break;
567
568         /*
569          * POSIX says that pending SIGCONT signals are
570          * discarded when one of these signals occurs.
571          */
572         case SIGTSTP:
573         case SIGTTIN:
574         case SIGTTOU:
575                 /*
576                  * Enter a loop to discard pending SIGCONT
577                  * signals:
578                  */
579                 TAILQ_FOREACH(pthread, &_thread_list, tle) {
580                         sigdelset(&pthread->sigpend, SIGCONT);
581                 }
582                 break;
583
584         default:
585                 break;
586         }
587 }
588
589 /*
590  * Perform thread specific actions in response to a signal.
591  * This function is only called if there is a handler installed
592  * for the signal, and if the target thread has the signal
593  * unmasked.
594  */
595 static void
596 thread_sig_add(struct pthread *pthread, int sig, int has_args)
597 {
598         int     restart;
599         int     suppress_handler = 0;
600         int     thread_is_active = 0;
601
602         restart = _thread_sigact[sig - 1].sa_flags & SA_RESTART;
603
604         /* Make sure this signal isn't still in the pending set: */
605         sigdelset(&pthread->sigpend, sig);
606
607         /*
608          * Process according to thread state:
609          */
610         switch (pthread->state) {
611         /*
612          * States which do not change when a signal is trapped:
613          */
614         case PS_DEAD:
615         case PS_DEADLOCK:
616         case PS_STATE_MAX:
617         case PS_SIGTHREAD:
618                 /*
619                  * You can't call a signal handler for threads in these
620                  * states.
621                  */
622                 suppress_handler = 1;
623                 break;
624
625         /*
626          * States which do not need any cleanup handling when signals
627          * occur:
628          */
629         case PS_RUNNING:
630                 /*
631                  * Remove the thread from the queue before changing its
632                  * priority:
633                  */
634                 if ((pthread->flags & PTHREAD_FLAGS_IN_PRIOQ) != 0)
635                         PTHREAD_PRIOQ_REMOVE(pthread);
636                 else
637                         /*
638                          * This thread is running; avoid placing it in
639                          * the run queue:
640                          */
641                         thread_is_active = 1;
642                 break;
643
644         case PS_SUSPENDED:
645                 break;
646
647         case PS_SPINBLOCK:
648                 /* Remove the thread from the workq and waitq: */
649                 PTHREAD_WORKQ_REMOVE(pthread);
650                 PTHREAD_WAITQ_REMOVE(pthread);
651                 /* Make the thread runnable: */
652                 PTHREAD_SET_STATE(pthread, PS_RUNNING);
653                 break;
654
655         case PS_SIGWAIT:
656                 /* The signal handler is not called for threads in SIGWAIT. */
657                 suppress_handler = 1;
658                 /* Wake up the thread if the signal is blocked. */
659                 if (sigismember(pthread->data.sigwait, sig)) {
660                         /* Change the state of the thread to run: */
661                         PTHREAD_NEW_STATE(pthread, PS_RUNNING);
662
663                         /* Return the signal number: */
664                         pthread->signo = sig;
665                 } else
666                         /* Increment the pending signal count. */
667                         sigaddset(&pthread->sigpend, sig);
668                 break;
669
670         /*
671          * The wait state is a special case due to the handling of
672          * SIGCHLD signals.
673          */
674         case PS_WAIT_WAIT:
675                 if (sig == SIGCHLD) {
676                         /* Change the state of the thread to run: */
677                         PTHREAD_WAITQ_REMOVE(pthread);
678                         PTHREAD_SET_STATE(pthread, PS_RUNNING);
679
680                         /* Return the signal number: */
681                         pthread->signo = sig;
682                 }
683                 else {
684                         /*
685                          * Mark the thread as interrupted only if the
686                          * restart flag is not set on the signal action:
687                          */
688                         if (restart == 0)
689                                 pthread->interrupted = 1;
690                         PTHREAD_WAITQ_REMOVE(pthread);
691                         PTHREAD_SET_STATE(pthread, PS_RUNNING);
692                 }
693                 break;
694
695         /*
696          * States which cannot be interrupted but still require the
697          * signal handler to run:
698          */
699         case PS_COND_WAIT:
700         case PS_MUTEX_WAIT:
701                 /*
702                  * Remove the thread from the wait queue.  It will
703                  * be added back to the wait queue once all signal
704                  * handlers have been invoked.
705                  */
706                 PTHREAD_WAITQ_REMOVE(pthread);
707                 break;
708
709         case PS_JOIN:
710                 /*
711                  * Remove the thread from the wait queue.  It will
712                  * be added back to the wait queue once all signal
713                  * handlers have been invoked.
714                  */
715                 PTHREAD_WAITQ_REMOVE(pthread);
716                 /* Make the thread runnable: */
717                 PTHREAD_SET_STATE(pthread, PS_RUNNING);
718                 break;
719
720         /*
721          * States which are interruptible but may need to be removed
722          * from queues before any signal handler is called.
723          *
724          * XXX - We may not need to handle this condition, but will
725          *       mark it as a potential problem.
726          */
727         case PS_FDLR_WAIT:
728         case PS_FDLW_WAIT:
729         case PS_FILE_WAIT:
730                 if (restart == 0)
731                         pthread->interrupted = 1;
732                 /*
733                  * Remove the thread from the wait queue.  Our
734                  * signal handler hook will remove this thread
735                  * from the fd or file queue before invoking
736                  * the actual handler.
737                  */
738                 PTHREAD_WAITQ_REMOVE(pthread);
739                 break;
740
741         /*
742          * States which are interruptible:
743          */
744         case PS_FDR_WAIT:
745         case PS_FDW_WAIT:
746                 if (restart == 0) {
747                         /*
748                          * Flag the operation as interrupted and
749                          * set the state to running:
750                          */
751                         pthread->interrupted = 1;
752                         PTHREAD_SET_STATE(pthread, PS_RUNNING);
753                 }
754                 PTHREAD_WORKQ_REMOVE(pthread);
755                 PTHREAD_WAITQ_REMOVE(pthread);
756                 break;
757
758         case PS_POLL_WAIT:
759         case PS_SELECT_WAIT:
760         case PS_SLEEP_WAIT:
761                 /*
762                  * Unmasked signals always cause poll, select, and sleep
763                  * to terminate early, regardless of SA_RESTART:
764                  */
765                 pthread->interrupted = 1;
766                 /* Remove threads in poll and select from the workq: */
767                 if ((pthread->flags & PTHREAD_FLAGS_IN_WORKQ) != 0)
768                         PTHREAD_WORKQ_REMOVE(pthread);
769                 PTHREAD_WAITQ_REMOVE(pthread);
770                 PTHREAD_SET_STATE(pthread, PS_RUNNING);
771                 break;
772
773         case PS_SIGSUSPEND:
774                 PTHREAD_WAITQ_REMOVE(pthread);
775                 PTHREAD_SET_STATE(pthread, PS_RUNNING);
776                 break;
777         }
778
779         if (suppress_handler == 0) {
780                 /* Setup a signal frame and save the current threads state: */
781                 thread_sigframe_add(pthread, sig, has_args);
782
783                 /*
784                  * Signals are deferred until just before the threads
785                  * signal handler is invoked:
786                  */
787                 pthread->sig_defer_count = 1;
788
789                 /* Make sure the thread is runnable: */
790                 if (pthread->state != PS_RUNNING)
791                         PTHREAD_SET_STATE(pthread, PS_RUNNING);
792                 /*
793                  * The thread should be removed from all scheduling
794                  * queues at this point.  Raise the priority and place
795                  * the thread in the run queue.  It is also possible
796                  * for a signal to be sent to a suspended thread,
797                  * mostly via pthread_kill().  If a thread is suspended,
798                  * don't insert it into the priority queue; just set
799                  * its state to suspended and it will run the signal
800                  * handler when it is resumed.
801                  */
802                 pthread->active_priority |= PTHREAD_SIGNAL_PRIORITY;
803                 if ((pthread->flags & PTHREAD_FLAGS_SUSPENDED) != 0)
804                         PTHREAD_SET_STATE(pthread, PS_SUSPENDED);
805                 else if (thread_is_active == 0)
806                         PTHREAD_PRIOQ_INSERT_TAIL(pthread);
807         }
808 }
809
810 static void
811 thread_sig_check_state(struct pthread *pthread, int sig)
812 {
813         /*
814          * Process according to thread state:
815          */
816         switch (pthread->state) {
817         /*
818          * States which do not change when a signal is trapped:
819          */
820         case PS_DEAD:
821         case PS_DEADLOCK:
822         case PS_STATE_MAX:
823         case PS_SIGTHREAD:
824         case PS_RUNNING:
825         case PS_SUSPENDED:
826         case PS_SPINBLOCK:
827         case PS_COND_WAIT:
828         case PS_JOIN:
829         case PS_MUTEX_WAIT:
830                 break;
831
832         case PS_SIGWAIT:
833                 /* Wake up the thread if the signal is blocked. */
834                 if (sigismember(pthread->data.sigwait, sig)) {
835                         /* Change the state of the thread to run: */
836                         PTHREAD_NEW_STATE(pthread, PS_RUNNING);
837
838                         /* Return the signal number: */
839                         pthread->signo = sig;
840                 } else
841                         /* Increment the pending signal count. */
842                         sigaddset(&pthread->sigpend, sig);
843                 break;
844
845         /*
846          * The wait state is a special case due to the handling of
847          * SIGCHLD signals.
848          */
849         case PS_WAIT_WAIT:
850                 if (sig == SIGCHLD) {
851                         /*
852                          * Remove the thread from the wait queue and
853                          * make it runnable:
854                          */
855                         PTHREAD_NEW_STATE(pthread, PS_RUNNING);
856
857                         /* Return the signal number: */
858                         pthread->signo = sig;
859                 }
860                 break;
861
862         case PS_FDLR_WAIT:
863         case PS_FDLW_WAIT:
864         case PS_SIGSUSPEND:
865         case PS_SLEEP_WAIT:
866                 /*
867                  * Remove the thread from the wait queue and make it
868                  * runnable:
869                  */
870                 PTHREAD_NEW_STATE(pthread, PS_RUNNING);
871
872                 /* Flag the operation as interrupted: */
873                 pthread->interrupted = 1;
874                 break;
875
876         /*
877          * These states are additionally in the work queue:
878          */
879         case PS_FDR_WAIT:
880         case PS_FDW_WAIT:
881         case PS_FILE_WAIT:
882         case PS_POLL_WAIT:
883         case PS_SELECT_WAIT:
884                 /*
885                  * Remove the thread from the wait and work queues, and
886                  * make it runnable:
887                  */
888                 PTHREAD_WORKQ_REMOVE(pthread);
889                 PTHREAD_NEW_STATE(pthread, PS_RUNNING);
890
891                 /* Flag the operation as interrupted: */
892                 pthread->interrupted = 1;
893                 break;
894         }
895 }
896
897 /*
898  * Send a signal to a specific thread (ala pthread_kill):
899  */
900 void
901 _thread_sig_send(struct pthread *pthread, int sig)
902 {
903         struct pthread  *curthread = _get_curthread();
904
905         /* Check for signals whose actions are SIG_DFL: */
906         if (_thread_sigact[sig - 1].sa_handler == SIG_DFL) {
907                 /*
908                  * Check to see if a temporary signal handler is
909                  * installed for sigwaiters:
910                  */
911                 if (_thread_dfl_count[sig] == 0)
912                         /*
913                          * Deliver the signal to the process if a handler
914                          * is not installed:
915                          */
916                         kill(getpid(), sig);
917                 /*
918                  * Assuming we're still running after the above kill(),
919                  * make any necessary state changes to the thread:
920                  */
921                 thread_sig_check_state(pthread, sig);
922         }
923         /*
924          * Check that the signal is not being ignored:
925          */
926         else if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) {
927                 if (pthread->state == PS_SIGWAIT &&
928                     sigismember(pthread->data.sigwait, sig)) {
929                         /* Change the state of the thread to run: */
930                         PTHREAD_NEW_STATE(pthread, PS_RUNNING);
931         
932                         /* Return the signal number: */
933                         pthread->signo = sig;
934                 } else if (sigismember(&pthread->sigmask, sig))
935                         /* Add the signal to the pending set: */
936                         sigaddset(&pthread->sigpend, sig);
937                 else if (pthread == curthread)
938                         /* Call the signal handler for the current thread: */
939                         thread_sig_invoke_handler(sig, NULL, NULL);
940                 else {
941                         /* Protect the scheduling queues: */
942                         _thread_kern_sig_defer();
943                         /*
944                          * Perform any state changes due to signal
945                          * arrival:
946                          */
947                         thread_sig_add(pthread, sig, /* has args */ 0);
948                         /* Unprotect the scheduling queues: */
949                         _thread_kern_sig_undefer();
950                 }
951         }
952 }
953
954 /*
955  * User thread signal handler wrapper.
956  *
957  *   thread - current running thread
958  */
959 void
960 _thread_sig_wrapper(void)
961 {
962         struct pthread_signal_frame *psf;
963         struct pthread  *thread = _get_curthread();
964
965         /* Get the current frame and state: */
966         psf = thread->curframe;
967         thread->curframe = NULL;
968         PTHREAD_ASSERT(psf != NULL, "Invalid signal frame in signal handler");
969
970         /*
971          * We're coming from the kernel scheduler; clear the in
972          * scheduler flag:
973          */
974         _thread_kern_in_sched = 0;
975
976         /* Check the threads previous state: */
977         if (psf->saved_state.psd_state != PS_RUNNING) {
978                 /*
979                  * Do a little cleanup handling for those threads in
980                  * queues before calling the signal handler.  Signals
981                  * for these threads are temporarily blocked until
982                  * after cleanup handling.
983                  */
984                 switch (psf->saved_state.psd_state) {
985                 case PS_FDLR_WAIT:
986                 case PS_FDLW_WAIT:
987                         _fd_lock_backout(thread);
988                         psf->saved_state.psd_state = PS_RUNNING;
989                         break;
990
991                 case PS_FILE_WAIT:
992                         _flockfile_backout(thread);
993                         psf->saved_state.psd_state = PS_RUNNING;
994                         break;
995
996                 case PS_COND_WAIT:
997                         _cond_wait_backout(thread);
998                         psf->saved_state.psd_state = PS_RUNNING;
999                         break;
1000
1001                 case PS_MUTEX_WAIT:
1002                         _mutex_lock_backout(thread);
1003                         psf->saved_state.psd_state = PS_RUNNING;
1004                         break;
1005
1006                 default:
1007                         break;
1008                 }
1009         }
1010
1011         /* Unblock the signal in case we don't return from the handler: */
1012         _thread_sigq[psf->signo - 1].blocked = 0;
1013
1014         /*
1015          * Lower the priority before calling the handler in case
1016          * it never returns (longjmps back):
1017          */
1018         thread->active_priority &= ~PTHREAD_SIGNAL_PRIORITY;
1019
1020         /*
1021          * Reenable interruptions without checking for the need to
1022          * context switch:
1023          */
1024         thread->sig_defer_count = 0;
1025
1026         /*
1027          * Dispatch the signal via the custom signal handler:
1028          */
1029         if (psf->sig_has_args == 0)
1030                 thread_sig_invoke_handler(psf->signo, NULL, NULL);
1031         else
1032                 thread_sig_invoke_handler(psf->signo, &psf->siginfo, &psf->uc);
1033
1034         /*
1035          * Call the kernel scheduler to safely restore the frame and
1036          * schedule the next thread:
1037          */
1038         _thread_kern_sched_frame(psf);
1039 }
1040
1041 static void
1042 thread_sigframe_add(struct pthread *thread, int sig, int has_args)
1043 {
1044         struct pthread_signal_frame *psf = NULL;
1045         unsigned long   stackp;
1046
1047         /* Get the top of the threads stack: */
1048         stackp = GET_STACK_JB(thread->ctx.jb);
1049
1050         /*
1051          * Leave a little space on the stack and round down to the
1052          * nearest aligned word:
1053          */
1054         stackp -= sizeof(double);
1055         stackp &= ~0x3UL;
1056
1057         /* Allocate room on top of the stack for a new signal frame: */
1058         stackp -= sizeof(struct pthread_signal_frame);
1059
1060         psf = (struct pthread_signal_frame *) stackp;
1061
1062         /* Save the current context in the signal frame: */
1063         thread_sigframe_save(thread, psf);
1064
1065         /* Set handler specific information: */
1066         psf->sig_has_args = has_args;
1067         psf->signo = sig;
1068         if (has_args) {
1069                 /* Copy the signal handler arguments to the signal frame: */
1070                 memcpy(&psf->uc, &_thread_sigq[psf->signo - 1].uc,
1071                     sizeof(psf->uc));
1072                 memcpy(&psf->siginfo, &_thread_sigq[psf->signo - 1].siginfo,
1073                     sizeof(psf->siginfo));
1074         }
1075
1076         /* Setup the signal mask: */
1077         SIGSETOR(thread->sigmask, _thread_sigact[sig - 1].sa_mask);
1078         sigaddset(&thread->sigmask, sig);
1079
1080         /* Set up the new frame: */
1081         thread->curframe = psf;
1082         thread->flags &= PTHREAD_FLAGS_PRIVATE | PTHREAD_FLAGS_TRACE |
1083             PTHREAD_FLAGS_IN_SYNCQ;
1084         /*
1085          * Set up the context:
1086          */
1087         stackp -= sizeof(double);
1088         _setjmp(thread->ctx.jb);
1089         SET_STACK_JB(thread->ctx.jb, stackp);
1090         SET_RETURN_ADDR_JB(thread->ctx.jb, _thread_sig_wrapper);
1091 }
1092
1093 void
1094 _thread_sigframe_restore(struct pthread *thread,
1095     struct pthread_signal_frame *psf)
1096 {
1097         memcpy(&thread->ctx, &psf->ctx, sizeof(thread->ctx));
1098         /*
1099          * Only restore the signal mask if it hasn't been changed
1100          * by the application during invocation of the signal handler:
1101          */
1102         if (thread->sigmask_seqno == psf->saved_state.psd_sigmask_seqno)
1103                 thread->sigmask = psf->saved_state.psd_sigmask;
1104         thread->curframe = psf->saved_state.psd_curframe;
1105         thread->wakeup_time = psf->saved_state.psd_wakeup_time;
1106         thread->data = psf->saved_state.psd_wait_data;
1107         thread->state = psf->saved_state.psd_state;
1108         thread->flags = psf->saved_state.psd_flags;
1109         thread->interrupted = psf->saved_state.psd_interrupted;
1110         thread->signo = psf->saved_state.psd_signo;
1111         thread->sig_defer_count = psf->saved_state.psd_sig_defer_count;
1112 }
1113
1114 static void
1115 thread_sigframe_save(struct pthread *thread, struct pthread_signal_frame *psf)
1116 {
1117         memcpy(&psf->ctx, &thread->ctx, sizeof(thread->ctx));
1118         psf->saved_state.psd_sigmask = thread->sigmask;
1119         psf->saved_state.psd_curframe = thread->curframe;
1120         psf->saved_state.psd_wakeup_time = thread->wakeup_time;
1121         psf->saved_state.psd_wait_data = thread->data;
1122         psf->saved_state.psd_state = thread->state;
1123         psf->saved_state.psd_flags = thread->flags &
1124             (PTHREAD_FLAGS_PRIVATE | PTHREAD_FLAGS_TRACE);
1125         psf->saved_state.psd_interrupted = thread->interrupted;
1126         psf->saved_state.psd_sigmask_seqno = thread->sigmask_seqno;
1127         psf->saved_state.psd_signo = thread->signo;
1128         psf->saved_state.psd_sig_defer_count = thread->sig_defer_count;
1129 }
1130