Merge from vendor branch OPENSSL:
[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.5 2007/01/08 21:41:53 dillon 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 "pthread_private.h"
45
46 /* Prototypes: */
47 static void     thread_sig_add(struct pthread *pthread, int sig, int has_args);
48 static void     thread_sig_check_state(struct pthread *pthread, int sig);
49 static struct pthread *thread_sig_find(int sig);
50 static void     thread_sig_handle_special(int sig);
51 static void     thread_sigframe_add(struct pthread *thread, int sig,
52                     int has_args);
53 static void     thread_sigframe_save(struct pthread *thread,
54                     struct pthread_signal_frame *psf);
55 static void     thread_sig_invoke_handler(int sig, siginfo_t *info,
56                     ucontext_t *ucp);
57
58 /*#define DEBUG_SIGNAL*/
59 #ifdef DEBUG_SIGNAL
60 #define DBG_MSG         stdout_debug
61 #else
62 #define DBG_MSG(x...)
63 #endif
64
65 #if defined(_PTHREADS_INVARIANTS)
66 #define SIG_SET_ACTIVE()        _sig_in_handler = 1
67 #define SIG_SET_INACTIVE()      _sig_in_handler = 0
68 #else
69 #define SIG_SET_ACTIVE()
70 #define SIG_SET_INACTIVE()
71 #endif
72
73 void
74 _thread_sig_handler(int sig, siginfo_t *info, ucontext_t *ucp)
75 {
76         struct pthread  *curthread = _get_curthread();
77         struct pthread  *pthread, *pthread_h;
78         int             in_sched = _thread_kern_in_sched;
79         char            c;
80
81         if (ucp == NULL)
82                 PANIC("Thread signal handler received null context");
83         DBG_MSG("Got signal %d, current thread %p\n", sig, curthread);
84
85         /* Check if an interval timer signal: */
86         if (sig == _SCHED_SIGNAL) {
87                 /* Update the scheduling clock: */
88                 gettimeofday((struct timeval *)&_sched_tod, NULL);
89                 _sched_ticks++;
90
91                 if (in_sched != 0) {
92                         /*
93                          * The scheduler is already running; ignore this
94                          * signal.
95                          */
96                 }
97                 /*
98                  * Check if the scheduler interrupt has come when
99                  * the currently running thread has deferred thread
100                  * signals.
101                  */
102                 else if (curthread->sig_defer_count > 0)
103                         curthread->yield_on_sig_undefer = 1;
104                 else {
105                         /* Schedule the next thread: */
106                         _thread_kern_sched(ucp);
107
108                         /*
109                          * This point should not be reached, so abort the
110                          * process:
111                          */
112                         PANIC("Returned to signal function from scheduler");
113                 }
114         }
115         /*
116          * Check if the kernel has been interrupted while the scheduler
117          * is accessing the scheduling queues or if there is a currently
118          * running thread that has deferred signals.
119          */
120         else if ((in_sched != 0) || (curthread->sig_defer_count > 0)) {
121                 /* Cast the signal number to a character variable: */
122                 c = sig;
123
124                 /*
125                  * Write the signal number to the kernel pipe so that it will
126                  * be ready to read when this signal handler returns.
127                  */
128                 if (_queue_signals != 0) {
129                         __sys_extpwrite(_thread_kern_pipe[1], &c, 1, O_FBLOCKING, -1);
130                         DBG_MSG("Got signal %d, queueing to kernel pipe\n", sig);
131                 }
132                 if (_thread_sigq[sig - 1].blocked == 0) {
133                         DBG_MSG("Got signal %d, adding to _thread_sigq\n", sig);
134                         /*
135                          * Do not block this signal; it will be blocked
136                          * when the pending signals are run down.
137                          */
138                         /* _thread_sigq[sig - 1].blocked = 1; */
139
140                         /*
141                          * Queue the signal, saving siginfo and sigcontext
142                          * (ucontext).
143                          *
144                          * XXX - Do we need to copy siginfo and ucp?
145                          */
146                         _thread_sigq[sig - 1].signo = sig;
147                         if (info != NULL)
148                                 memcpy(&_thread_sigq[sig - 1].siginfo, info,
149                                     sizeof(*info));
150                         memcpy(&_thread_sigq[sig - 1].uc, ucp, sizeof(*ucp));
151
152                         /* Indicate that there are queued signals: */
153                         _thread_sigq[sig - 1].pending = 1;
154                         _sigq_check_reqd = 1;
155                 }
156                 /* These signals need special handling: */
157                 else if (sig == SIGCHLD || sig == SIGTSTP ||
158                     sig == SIGTTIN || sig == SIGTTOU) {
159                         _thread_sigq[sig - 1].pending = 1;
160                         _thread_sigq[sig - 1].signo = sig;
161                         _sigq_check_reqd = 1;
162                 }
163                 else
164                         DBG_MSG("Got signal %d, ignored.\n", sig);
165         }
166         /*
167          * The signal handlers should have been installed so that they
168          * cannot be interrupted by other signals.
169          */
170         else if (_thread_sigq[sig - 1].blocked == 0) {
171                 /*
172                  * The signal is not blocked; handle the signal.
173                  *
174                  * Ignore subsequent occurrences of this signal
175                  * until the current signal is handled:
176                  */
177                 _thread_sigq[sig - 1].blocked = 1;
178
179                 /* This signal will be handled; clear the pending flag: */
180                 _thread_sigq[sig - 1].pending = 0;
181
182                 /*
183                  * Save siginfo and sigcontext (ucontext).
184                  *
185                  * XXX - Do we need to copy siginfo and ucp?
186                  */
187                 _thread_sigq[sig - 1].signo = sig;
188
189                 if (info != NULL)
190                         memcpy(&_thread_sigq[sig - 1].siginfo, info,
191                             sizeof(*info));
192                 memcpy(&_thread_sigq[sig - 1].uc, ucp, sizeof(*ucp));
193                 SIG_SET_ACTIVE();
194
195                 /* Handle special signals: */
196                 thread_sig_handle_special(sig);
197
198                 pthread_h = NULL;
199                 if ((pthread = thread_sig_find(sig)) == NULL)
200                         DBG_MSG("No thread to handle signal %d\n", sig);
201                 else if (pthread == curthread) {
202                         /*
203                          * Unblock the signal and restore the process signal
204                          * mask in case we don't return from the handler:
205                          */
206                         _thread_sigq[sig - 1].blocked = 0;
207                         __sys_sigprocmask(SIG_SETMASK, &_process_sigmask, NULL);
208
209                         /* Call the signal handler for the current thread: */
210                         thread_sig_invoke_handler(sig, info, ucp);
211
212                         /*
213                          * Set the process signal mask in the context; it
214                          * could have changed by the handler.
215                          */
216                         ucp->uc_sigmask = _process_sigmask;
217  
218                         /* Resume the interrupted thread: */
219                         sigreturn(ucp);
220                 } else {
221                         DBG_MSG("Got signal %d, adding frame to thread %p\n",
222                             sig, pthread);
223
224                         /* Setup the target thread to receive the signal: */
225                         thread_sig_add(pthread, sig, /*has_args*/ 1);
226
227                         /* Take a peek at the next ready to run thread: */
228                         pthread_h = PTHREAD_PRIOQ_FIRST();
229                         DBG_MSG("Finished adding frame, head of prio list %p\n",
230                             pthread_h);
231                 }
232                 SIG_SET_INACTIVE();
233
234                 /*
235                  * Switch to a different context if the currently running
236                  * thread takes a signal, or if another thread takes a
237                  * signal and the currently running thread is not in a
238                  * signal handler.
239                  */
240                 if ((pthread_h != NULL) &&
241                     (pthread_h->active_priority > curthread->active_priority)) {
242                         /* Enter the kernel scheduler: */
243                         _thread_kern_sched(ucp);
244                 }
245         }
246         else {
247                 SIG_SET_ACTIVE();
248                 thread_sig_handle_special(sig);
249                 SIG_SET_INACTIVE();
250         }
251 }
252
253 static void
254 thread_sig_invoke_handler(int sig, siginfo_t *info, ucontext_t *ucp)
255  {
256         struct pthread  *curthread = _get_curthread();
257         void (*sigfunc)(int, siginfo_t *, void *);
258         int             saved_seqno;
259         sigset_t        saved_sigmask;
260
261         /* Invoke the signal handler without going through the scheduler:
262          */
263         DBG_MSG("Got signal %d, calling handler for current thread %p\n",
264             sig, curthread);
265
266         /* Save the threads signal mask: */
267         saved_sigmask = curthread->sigmask;
268         saved_seqno = curthread->sigmask_seqno;
269  
270         /* Setup the threads signal mask: */
271         SIGSETOR(curthread->sigmask, _thread_sigact[sig - 1].sa_mask);
272         sigaddset(&curthread->sigmask, sig);
273  
274         /*
275          * Check that a custom handler is installed and if
276          * the signal is not blocked:
277          */
278         sigfunc = _thread_sigact[sig - 1].sa_sigaction;
279         if (((__sighandler_t *)sigfunc != SIG_DFL) &&
280             ((__sighandler_t *)sigfunc != SIG_IGN)) {
281                 if (((_thread_sigact[sig - 1].sa_flags & SA_SIGINFO) != 0) ||
282                     (info == NULL))
283                         (*(sigfunc))(sig, info, ucp);
284                 else
285                         (*(sigfunc))(sig, (siginfo_t *)info->si_code, ucp);
286         }
287         /*
288          * Only restore the signal mask if it hasn't been changed by the
289          * application during invocation of the signal handler:
290          */
291         if (curthread->sigmask_seqno == saved_seqno)
292                 curthread->sigmask = saved_sigmask;
293 }
294
295 /*
296  * Find a thread that can handle the signal.
297  */
298 struct pthread *
299 thread_sig_find(int sig)
300 {
301         struct pthread  *curthread = _get_curthread();
302         int             handler_installed;
303         struct pthread  *pthread, *pthread_next;
304         struct pthread  *suspended_thread, *signaled_thread;
305
306         DBG_MSG("Looking for thread to handle signal %d\n", sig);
307         /* Check if the signal requires a dump of thread information: */
308         if (sig == SIGINFO) {
309                 /* Dump thread information to file: */
310                 _thread_dump_info();
311
312                 /* Unblock this signal to allow further dumps: */
313                 _thread_sigq[sig - 1].blocked = 0;
314         }
315         /* Check if an interval timer signal: */
316         else if (sig == _SCHED_SIGNAL) {
317                 /*
318                  * This shouldn't ever occur (should this panic?).
319                  */
320         } else {
321                 /*
322                  * Enter a loop to look for threads that have the signal
323                  * unmasked.  POSIX specifies that a thread in a sigwait
324                  * will get the signal over any other threads.  Second
325                  * preference will be threads in in a sigsuspend.  Third
326                  * preference will be the current thread.  If none of the
327                  * above, then the signal is delivered to the first thread
328                  * that is found.  Note that if a custom handler is not
329                  * installed, the signal only affects threads in sigwait.
330                  */
331                 suspended_thread = NULL;
332                 if ((curthread != &_thread_kern_thread) &&
333                     !sigismember(&curthread->sigmask, sig))
334                         signaled_thread = curthread;
335                 else
336                         signaled_thread = NULL;
337                 if ((_thread_sigact[sig - 1].sa_handler == SIG_IGN) ||
338                     (_thread_sigact[sig - 1].sa_handler == SIG_DFL))
339                         handler_installed = 0;
340                 else
341                         handler_installed = 1;
342
343                 for (pthread = TAILQ_FIRST(&_waitingq);
344                     pthread != NULL; pthread = pthread_next) {
345                         /*
346                          * Grab the next thread before possibly destroying
347                          * the link entry.
348                          */
349                         pthread_next = TAILQ_NEXT(pthread, pqe);
350
351                         if ((pthread->state == PS_SIGWAIT) &&
352                             sigismember(pthread->data.sigwait, sig)) {
353                                 /* Change the state of the thread to run: */
354                                 PTHREAD_NEW_STATE(pthread,PS_RUNNING);
355                                 /*
356                                  * A signal handler is not invoked for threads
357                                  * in sigwait.  Clear the blocked and pending
358                                  * flags.
359                                  */
360                                 _thread_sigq[sig - 1].blocked = 0;
361                                 _thread_sigq[sig - 1].pending = 0;
362
363                                 /* Return the signal number: */
364                                 pthread->signo = sig;
365
366                                 /*
367                                  * POSIX doesn't doesn't specify which thread
368                                  * will get the signal if there are multiple
369                                  * waiters, so we give it to the first thread
370                                  * we find.
371                                  *
372                                  * Do not attempt to deliver this signal
373                                  * to other threads and do not add the signal
374                                  * to the process pending set.
375                                  */
376                                 return (NULL);
377                         }
378                         else if ((handler_installed != 0) &&
379                             !sigismember(&pthread->sigmask, sig) &&
380                             ((pthread->flags & PTHREAD_FLAGS_SUSPENDED) == 0)) {
381                                 if (pthread->state == PS_SIGSUSPEND) {
382                                         if (suspended_thread == NULL)
383                                                 suspended_thread = pthread;
384                                 } else if (signaled_thread == NULL)
385                                         signaled_thread = pthread;
386                         }
387                 }
388
389                 /*
390                  * Only perform wakeups and signal delivery if there is a
391                  * custom handler installed:
392                  */
393                 if (handler_installed == 0) {
394                         /*
395                          * There is no handler installed.  Unblock the
396                          * signal so that if a handler _is_ installed, any
397                          * subsequent signals can be handled.
398                          */
399                         _thread_sigq[sig - 1].blocked = 0;
400                 } else {
401                         /*
402                          * If we didn't find a thread in the waiting queue,
403                          * check the all threads queue:
404                          */
405                         if (suspended_thread == NULL &&
406                             signaled_thread == NULL) {
407                                 /*
408                                  * Enter a loop to look for other threads
409                                  * capable of receiving the signal:
410                                  */
411                                 TAILQ_FOREACH(pthread, &_thread_list, tle) {
412                                         if (!sigismember(&pthread->sigmask,
413                                             sig)) {
414                                                 signaled_thread = pthread;
415                                                 break;
416                                         }
417                                 }
418                         }
419
420                         if (suspended_thread == NULL &&
421                             signaled_thread == NULL)
422                                 /*
423                                  * Add it to the set of signals pending
424                                  * on the process:
425                                  */
426                                 sigaddset(&_process_sigpending, sig);
427                         else {
428                                 /*
429                                  * We only deliver the signal to one thread;
430                                  * give preference to the suspended thread:
431                                  */
432                                 if (suspended_thread != NULL)
433                                         pthread = suspended_thread;
434                                 else
435                                         pthread = signaled_thread;
436                                 return (pthread);
437                         }
438                 }
439         }
440
441         /* Returns nothing. */
442         return (NULL);
443 }
444
445 void
446 _thread_sig_check_pending(struct pthread *pthread)
447 {
448         sigset_t        sigset;
449         int             i;
450
451         /*
452          * Check if there are pending signals for the running
453          * thread or process that aren't blocked:
454          */
455         sigset = pthread->sigpend;
456         SIGSETOR(sigset, _process_sigpending);
457         SIGSETNAND(sigset, pthread->sigmask);
458         if (SIGNOTEMPTY(sigset)) {
459                 for (i = 1; i < NSIG; i++) {
460                         if (sigismember(&sigset, i) != 0) {
461                                 if (sigismember(&pthread->sigpend, i) != 0)
462                                         thread_sig_add(pthread, i,
463                                             /*has_args*/ 0);
464                                 else {
465                                         thread_sig_add(pthread, i,
466                                             /*has_args*/ 1);
467                                         sigdelset(&_process_sigpending, i);
468                                 }
469                         }
470                 }
471         }
472 }
473
474 /*
475  * This can only be called from the kernel scheduler.  It assumes that
476  * all thread contexts are saved and that a signal frame can safely be
477  * added to any user thread.
478  */
479 void
480 _thread_sig_handle_pending(void)
481 {
482         struct pthread  *pthread;
483         int             i, sig;
484
485         PTHREAD_ASSERT(_thread_kern_in_sched != 0,
486             "_thread_sig_handle_pending called from outside kernel schedule");
487         /*
488          * Check the array of pending signals:
489          */
490         for (i = 0; i < NSIG; i++) {
491                 if (_thread_sigq[i].pending != 0) {
492                         /* This signal is no longer pending. */
493                         _thread_sigq[i].pending = 0;
494
495                         sig = _thread_sigq[i].signo;
496
497                         /* Some signals need special handling: */
498                         thread_sig_handle_special(sig);
499
500                         if (_thread_sigq[i].blocked == 0) {
501                                 /*
502                                  * Block future signals until this one
503                                  * is handled:
504                                  */
505                                 _thread_sigq[i].blocked = 1;
506
507                                 if ((pthread = thread_sig_find(sig)) != NULL) {
508                                         /*
509                                          * Setup the target thread to receive
510                                          * the signal:
511                                          */
512                                         thread_sig_add(pthread, sig,
513                                             /*has_args*/ 1);
514                                 }
515                         }
516                 }
517         }
518 }
519
520 static void
521 thread_sig_handle_special(int sig)
522 {
523         struct pthread  *pthread, *pthread_next;
524         int             i;
525
526         switch (sig) {
527         case SIGCHLD:
528                 /*
529                  * Go through the file list and set all files
530                  * to non-blocking again in case the child
531                  * set some of them to block. Sigh.
532                  */
533                 for (i = 0; i < _thread_dtablesize; i++) {
534                         /* Check if this file is used: */
535                         if (_thread_fd_table[i] != NULL) {
536                                 /*
537                                  * Set the file descriptor to non-blocking:
538                                  */
539                                 __sys_fcntl(i, F_SETFL,
540                                     _thread_fd_getflags(i) | O_NONBLOCK);
541                         }
542                 }
543                 /*
544                  * Enter a loop to wake up all threads waiting
545                  * for a process to complete:
546                  */
547                 for (pthread = TAILQ_FIRST(&_waitingq);
548                     pthread != NULL; pthread = pthread_next) {
549                         /*
550                          * Grab the next thread before possibly
551                          * destroying the link entry:
552                          */
553                         pthread_next = TAILQ_NEXT(pthread, pqe);
554
555                         /*
556                          * If this thread is waiting for a child
557                          * process to complete, wake it up:
558                          */
559                         if (pthread->state == PS_WAIT_WAIT) {
560                                 /* Make the thread runnable: */
561                                 PTHREAD_NEW_STATE(pthread,PS_RUNNING);
562
563                                 /* Return the signal number: */
564                                 pthread->signo = sig;
565                         }
566                 }
567                 break;
568
569         /*
570          * POSIX says that pending SIGCONT signals are
571          * discarded when one of these signals occurs.
572          */
573         case SIGTSTP:
574         case SIGTTIN:
575         case SIGTTOU:
576                 /*
577                  * Enter a loop to discard pending SIGCONT
578                  * signals:
579                  */
580                 TAILQ_FOREACH(pthread, &_thread_list, tle) {
581                         sigdelset(&pthread->sigpend, SIGCONT);
582                 }
583                 break;
584
585         default:
586                 break;
587         }
588 }
589
590 /*
591  * Perform thread specific actions in response to a signal.
592  * This function is only called if there is a handler installed
593  * for the signal, and if the target thread has the signal
594  * unmasked.
595  */
596 static void
597 thread_sig_add(struct pthread *pthread, int sig, int has_args)
598 {
599         int     restart;
600         int     suppress_handler = 0;
601         int     thread_is_active = 0;
602
603         restart = _thread_sigact[sig - 1].sa_flags & SA_RESTART;
604
605         /* Make sure this signal isn't still in the pending set: */
606         sigdelset(&pthread->sigpend, sig);
607
608         /*
609          * Process according to thread state:
610          */
611         switch (pthread->state) {
612         /*
613          * States which do not change when a signal is trapped:
614          */
615         case PS_DEAD:
616         case PS_DEADLOCK:
617         case PS_STATE_MAX:
618         case PS_SIGTHREAD:
619                 /*
620                  * You can't call a signal handler for threads in these
621                  * states.
622                  */
623                 suppress_handler = 1;
624                 break;
625
626         /*
627          * States which do not need any cleanup handling when signals
628          * occur:
629          */
630         case PS_RUNNING:
631                 /*
632                  * Remove the thread from the queue before changing its
633                  * priority:
634                  */
635                 if ((pthread->flags & PTHREAD_FLAGS_IN_PRIOQ) != 0)
636                         PTHREAD_PRIOQ_REMOVE(pthread);
637                 else
638                         /*
639                          * This thread is running; avoid placing it in
640                          * the run queue:
641                          */
642                         thread_is_active = 1;
643                 break;
644
645         case PS_SUSPENDED:
646                 break;
647
648         case PS_SPINBLOCK:
649                 /* Remove the thread from the workq and waitq: */
650                 PTHREAD_WORKQ_REMOVE(pthread);
651                 PTHREAD_WAITQ_REMOVE(pthread);
652                 /* Make the thread runnable: */
653                 PTHREAD_SET_STATE(pthread, PS_RUNNING);
654                 break;
655
656         case PS_SIGWAIT:
657                 /* The signal handler is not called for threads in SIGWAIT. */
658                 suppress_handler = 1;
659                 /* Wake up the thread if the signal is blocked. */
660                 if (sigismember(pthread->data.sigwait, sig)) {
661                         /* Change the state of the thread to run: */
662                         PTHREAD_NEW_STATE(pthread, PS_RUNNING);
663
664                         /* Return the signal number: */
665                         pthread->signo = sig;
666                 } else
667                         /* Increment the pending signal count. */
668                         sigaddset(&pthread->sigpend, sig);
669                 break;
670
671         /*
672          * The wait state is a special case due to the handling of
673          * SIGCHLD signals.
674          */
675         case PS_WAIT_WAIT:
676                 if (sig == SIGCHLD) {
677                         /* Change the state of the thread to run: */
678                         PTHREAD_WAITQ_REMOVE(pthread);
679                         PTHREAD_SET_STATE(pthread, PS_RUNNING);
680
681                         /* Return the signal number: */
682                         pthread->signo = sig;
683                 }
684                 else {
685                         /*
686                          * Mark the thread as interrupted only if the
687                          * restart flag is not set on the signal action:
688                          */
689                         if (restart == 0)
690                                 pthread->interrupted = 1;
691                         PTHREAD_WAITQ_REMOVE(pthread);
692                         PTHREAD_SET_STATE(pthread, PS_RUNNING);
693                 }
694                 break;
695
696         /*
697          * States which cannot be interrupted but still require the
698          * signal handler to run:
699          */
700         case PS_COND_WAIT:
701         case PS_MUTEX_WAIT:
702                 /*
703                  * Remove the thread from the wait queue.  It will
704                  * be added back to the wait queue once all signal
705                  * handlers have been invoked.
706                  */
707                 PTHREAD_WAITQ_REMOVE(pthread);
708                 break;
709
710         case PS_JOIN:
711                 /*
712                  * Remove the thread from the wait queue.  It will
713                  * be added back to the wait queue once all signal
714                  * handlers have been invoked.
715                  */
716                 PTHREAD_WAITQ_REMOVE(pthread);
717                 /* Make the thread runnable: */
718                 PTHREAD_SET_STATE(pthread, PS_RUNNING);
719                 break;
720
721         /*
722          * States which are interruptible but may need to be removed
723          * from queues before any signal handler is called.
724          *
725          * XXX - We may not need to handle this condition, but will
726          *       mark it as a potential problem.
727          */
728         case PS_FDLR_WAIT:
729         case PS_FDLW_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_POLL_WAIT:
882         case PS_SELECT_WAIT:
883                 /*
884                  * Remove the thread from the wait and work queues, and
885                  * make it runnable:
886                  */
887                 PTHREAD_WORKQ_REMOVE(pthread);
888                 PTHREAD_NEW_STATE(pthread, PS_RUNNING);
889
890                 /* Flag the operation as interrupted: */
891                 pthread->interrupted = 1;
892                 break;
893         }
894 }
895
896 /*
897  * Send a signal to a specific thread (ala pthread_kill):
898  */
899 void
900 _thread_sig_send(struct pthread *pthread, int sig)
901 {
902         struct pthread  *curthread = _get_curthread();
903
904         /* Check for signals whose actions are SIG_DFL: */
905         if (_thread_sigact[sig - 1].sa_handler == SIG_DFL) {
906                 /*
907                  * Check to see if a temporary signal handler is
908                  * installed for sigwaiters:
909                  */
910                 if (_thread_dfl_count[sig] == 0)
911                         /*
912                          * Deliver the signal to the process if a handler
913                          * is not installed:
914                          */
915                         kill(getpid(), sig);
916                 /*
917                  * Assuming we're still running after the above kill(),
918                  * make any necessary state changes to the thread:
919                  */
920                 thread_sig_check_state(pthread, sig);
921         }
922         /*
923          * Check that the signal is not being ignored:
924          */
925         else if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) {
926                 if (pthread->state == PS_SIGWAIT &&
927                     sigismember(pthread->data.sigwait, sig)) {
928                         /* Change the state of the thread to run: */
929                         PTHREAD_NEW_STATE(pthread, PS_RUNNING);
930         
931                         /* Return the signal number: */
932                         pthread->signo = sig;
933                 } else if (sigismember(&pthread->sigmask, sig))
934                         /* Add the signal to the pending set: */
935                         sigaddset(&pthread->sigpend, sig);
936                 else if (pthread == curthread)
937                         /* Call the signal handler for the current thread: */
938                         thread_sig_invoke_handler(sig, NULL, NULL);
939                 else {
940                         /* Protect the scheduling queues: */
941                         _thread_kern_sig_defer();
942                         /*
943                          * Perform any state changes due to signal
944                          * arrival:
945                          */
946                         thread_sig_add(pthread, sig, /* has args */ 0);
947                         /* Unprotect the scheduling queues: */
948                         _thread_kern_sig_undefer();
949                 }
950         }
951 }
952
953 /*
954  * User thread signal handler wrapper.
955  *
956  *   thread - current running thread
957  */
958 void
959 _thread_sig_wrapper(void)
960 {
961         struct pthread_signal_frame *psf;
962         struct pthread  *thread = _get_curthread();
963
964         /* Get the current frame and state: */
965         psf = thread->curframe;
966         thread->curframe = NULL;
967         PTHREAD_ASSERT(psf != NULL, "Invalid signal frame in signal handler");
968
969         /*
970          * We're coming from the kernel scheduler; clear the in
971          * scheduler flag:
972          */
973         _thread_kern_in_sched = 0;
974
975         /* Check the threads previous state: */
976         if (psf->saved_state.psd_state != PS_RUNNING) {
977                 /*
978                  * Do a little cleanup handling for those threads in
979                  * queues before calling the signal handler.  Signals
980                  * for these threads are temporarily blocked until
981                  * after cleanup handling.
982                  */
983                 switch (psf->saved_state.psd_state) {
984                 case PS_FDLR_WAIT:
985                 case PS_FDLW_WAIT:
986                         _fd_lock_backout(thread);
987                         psf->saved_state.psd_state = PS_RUNNING;
988                         break;
989
990                 case PS_COND_WAIT:
991                         _cond_wait_backout(thread);
992                         psf->saved_state.psd_state = PS_RUNNING;
993                         break;
994
995                 case PS_MUTEX_WAIT:
996                         _mutex_lock_backout(thread);
997                         psf->saved_state.psd_state = PS_RUNNING;
998                         break;
999
1000                 default:
1001                         break;
1002                 }
1003         }
1004
1005         /* Unblock the signal in case we don't return from the handler: */
1006         _thread_sigq[psf->signo - 1].blocked = 0;
1007
1008         /*
1009          * Lower the priority before calling the handler in case
1010          * it never returns (longjmps back):
1011          */
1012         thread->active_priority &= ~PTHREAD_SIGNAL_PRIORITY;
1013
1014         /*
1015          * Reenable interruptions without checking for the need to
1016          * context switch:
1017          */
1018         thread->sig_defer_count = 0;
1019
1020         /*
1021          * Dispatch the signal via the custom signal handler:
1022          */
1023         if (psf->sig_has_args == 0)
1024                 thread_sig_invoke_handler(psf->signo, NULL, NULL);
1025         else
1026                 thread_sig_invoke_handler(psf->signo, &psf->siginfo, &psf->uc);
1027
1028         /*
1029          * Call the kernel scheduler to safely restore the frame and
1030          * schedule the next thread:
1031          */
1032         _thread_kern_sched_frame(psf);
1033 }
1034
1035 static void
1036 thread_sigframe_add(struct pthread *thread, int sig, int has_args)
1037 {
1038         struct pthread_signal_frame *psf = NULL;
1039         unsigned long   stackp;
1040
1041         /* Get the top of the threads stack: */
1042         stackp = GET_STACK_JB(thread->ctx.jb);
1043
1044         /*
1045          * Leave a little space on the stack and round down to the
1046          * nearest aligned word:
1047          */
1048         stackp -= sizeof(double);
1049         stackp &= ~0x3UL;
1050
1051         /* Allocate room on top of the stack for a new signal frame: */
1052         stackp -= sizeof(struct pthread_signal_frame);
1053
1054         psf = (struct pthread_signal_frame *) stackp;
1055
1056         /* Save the current context in the signal frame: */
1057         thread_sigframe_save(thread, psf);
1058
1059         /* Set handler specific information: */
1060         psf->sig_has_args = has_args;
1061         psf->signo = sig;
1062         if (has_args) {
1063                 /* Copy the signal handler arguments to the signal frame: */
1064                 memcpy(&psf->uc, &_thread_sigq[psf->signo - 1].uc,
1065                     sizeof(psf->uc));
1066                 memcpy(&psf->siginfo, &_thread_sigq[psf->signo - 1].siginfo,
1067                     sizeof(psf->siginfo));
1068         }
1069
1070         /* Setup the signal mask: */
1071         SIGSETOR(thread->sigmask, _thread_sigact[sig - 1].sa_mask);
1072         sigaddset(&thread->sigmask, sig);
1073
1074         /* Set up the new frame: */
1075         thread->curframe = psf;
1076         thread->flags &= PTHREAD_FLAGS_PRIVATE | PTHREAD_FLAGS_TRACE |
1077             PTHREAD_FLAGS_IN_SYNCQ;
1078         /*
1079          * Set up the context:
1080          */
1081         stackp -= sizeof(double);
1082         _setjmp(thread->ctx.jb);
1083         SET_STACK_JB(thread->ctx.jb, stackp);
1084         SET_RETURN_ADDR_JB(thread->ctx.jb, _thread_sig_wrapper);
1085 }
1086
1087 void
1088 _thread_sigframe_restore(struct pthread *thread,
1089     struct pthread_signal_frame *psf)
1090 {
1091         memcpy(&thread->ctx, &psf->ctx, sizeof(thread->ctx));
1092         /*
1093          * Only restore the signal mask if it hasn't been changed
1094          * by the application during invocation of the signal handler:
1095          */
1096         if (thread->sigmask_seqno == psf->saved_state.psd_sigmask_seqno)
1097                 thread->sigmask = psf->saved_state.psd_sigmask;
1098         thread->curframe = psf->saved_state.psd_curframe;
1099         thread->wakeup_time = psf->saved_state.psd_wakeup_time;
1100         thread->data = psf->saved_state.psd_wait_data;
1101         thread->state = psf->saved_state.psd_state;
1102         thread->flags = psf->saved_state.psd_flags;
1103         thread->interrupted = psf->saved_state.psd_interrupted;
1104         thread->signo = psf->saved_state.psd_signo;
1105         thread->sig_defer_count = psf->saved_state.psd_sig_defer_count;
1106 }
1107
1108 static void
1109 thread_sigframe_save(struct pthread *thread, struct pthread_signal_frame *psf)
1110 {
1111         memcpy(&psf->ctx, &thread->ctx, sizeof(thread->ctx));
1112         psf->saved_state.psd_sigmask = thread->sigmask;
1113         psf->saved_state.psd_curframe = thread->curframe;
1114         psf->saved_state.psd_wakeup_time = thread->wakeup_time;
1115         psf->saved_state.psd_wait_data = thread->data;
1116         psf->saved_state.psd_state = thread->state;
1117         psf->saved_state.psd_flags = thread->flags &
1118             (PTHREAD_FLAGS_PRIVATE | PTHREAD_FLAGS_TRACE);
1119         psf->saved_state.psd_interrupted = thread->interrupted;
1120         psf->saved_state.psd_sigmask_seqno = thread->sigmask_seqno;
1121         psf->saved_state.psd_signo = thread->signo;
1122         psf->saved_state.psd_sig_defer_count = thread->sig_defer_count;
1123 }
1124