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