Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[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.2 2003/06/17 04:26:48 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_write(_thread_kern_pipe[1], &c, 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         case PS_FILE_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_FILE_WAIT:
883         case PS_POLL_WAIT:
884         case PS_SELECT_WAIT:
885                 /*
886                  * Remove the thread from the wait and work queues, and
887                  * make it runnable:
888                  */
889                 PTHREAD_WORKQ_REMOVE(pthread);
890                 PTHREAD_NEW_STATE(pthread, PS_RUNNING);
891
892                 /* Flag the operation as interrupted: */
893                 pthread->interrupted = 1;
894                 break;
895         }
896 }
897
898 /*
899  * Send a signal to a specific thread (ala pthread_kill):
900  */
901 void
902 _thread_sig_send(struct pthread *pthread, int sig)
903 {
904         struct pthread  *curthread = _get_curthread();
905
906         /* Check for signals whose actions are SIG_DFL: */
907         if (_thread_sigact[sig - 1].sa_handler == SIG_DFL) {
908                 /*
909                  * Check to see if a temporary signal handler is
910                  * installed for sigwaiters:
911                  */
912                 if (_thread_dfl_count[sig] == 0)
913                         /*
914                          * Deliver the signal to the process if a handler
915                          * is not installed:
916                          */
917                         kill(getpid(), sig);
918                 /*
919                  * Assuming we're still running after the above kill(),
920                  * make any necessary state changes to the thread:
921                  */
922                 thread_sig_check_state(pthread, sig);
923         }
924         /*
925          * Check that the signal is not being ignored:
926          */
927         else if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) {
928                 if (pthread->state == PS_SIGWAIT &&
929                     sigismember(pthread->data.sigwait, sig)) {
930                         /* Change the state of the thread to run: */
931                         PTHREAD_NEW_STATE(pthread, PS_RUNNING);
932         
933                         /* Return the signal number: */
934                         pthread->signo = sig;
935                 } else if (sigismember(&pthread->sigmask, sig))
936                         /* Add the signal to the pending set: */
937                         sigaddset(&pthread->sigpend, sig);
938                 else if (pthread == curthread)
939                         /* Call the signal handler for the current thread: */
940                         thread_sig_invoke_handler(sig, NULL, NULL);
941                 else {
942                         /* Protect the scheduling queues: */
943                         _thread_kern_sig_defer();
944                         /*
945                          * Perform any state changes due to signal
946                          * arrival:
947                          */
948                         thread_sig_add(pthread, sig, /* has args */ 0);
949                         /* Unprotect the scheduling queues: */
950                         _thread_kern_sig_undefer();
951                 }
952         }
953 }
954
955 /*
956  * User thread signal handler wrapper.
957  *
958  *   thread - current running thread
959  */
960 void
961 _thread_sig_wrapper(void)
962 {
963         struct pthread_signal_frame *psf;
964         struct pthread  *thread = _get_curthread();
965
966         /* Get the current frame and state: */
967         psf = thread->curframe;
968         thread->curframe = NULL;
969         PTHREAD_ASSERT(psf != NULL, "Invalid signal frame in signal handler");
970
971         /*
972          * We're coming from the kernel scheduler; clear the in
973          * scheduler flag:
974          */
975         _thread_kern_in_sched = 0;
976
977         /* Check the threads previous state: */
978         if (psf->saved_state.psd_state != PS_RUNNING) {
979                 /*
980                  * Do a little cleanup handling for those threads in
981                  * queues before calling the signal handler.  Signals
982                  * for these threads are temporarily blocked until
983                  * after cleanup handling.
984                  */
985                 switch (psf->saved_state.psd_state) {
986                 case PS_FDLR_WAIT:
987                 case PS_FDLW_WAIT:
988                         _fd_lock_backout(thread);
989                         psf->saved_state.psd_state = PS_RUNNING;
990                         break;
991
992                 case PS_FILE_WAIT:
993                         _flockfile_backout(thread);
994                         psf->saved_state.psd_state = PS_RUNNING;
995                         break;
996
997                 case PS_COND_WAIT:
998                         _cond_wait_backout(thread);
999                         psf->saved_state.psd_state = PS_RUNNING;
1000                         break;
1001
1002                 case PS_MUTEX_WAIT:
1003                         _mutex_lock_backout(thread);
1004                         psf->saved_state.psd_state = PS_RUNNING;
1005                         break;
1006
1007                 default:
1008                         break;
1009                 }
1010         }
1011
1012         /* Unblock the signal in case we don't return from the handler: */
1013         _thread_sigq[psf->signo - 1].blocked = 0;
1014
1015         /*
1016          * Lower the priority before calling the handler in case
1017          * it never returns (longjmps back):
1018          */
1019         thread->active_priority &= ~PTHREAD_SIGNAL_PRIORITY;
1020
1021         /*
1022          * Reenable interruptions without checking for the need to
1023          * context switch:
1024          */
1025         thread->sig_defer_count = 0;
1026
1027         /*
1028          * Dispatch the signal via the custom signal handler:
1029          */
1030         if (psf->sig_has_args == 0)
1031                 thread_sig_invoke_handler(psf->signo, NULL, NULL);
1032         else
1033                 thread_sig_invoke_handler(psf->signo, &psf->siginfo, &psf->uc);
1034
1035         /*
1036          * Call the kernel scheduler to safely restore the frame and
1037          * schedule the next thread:
1038          */
1039         _thread_kern_sched_frame(psf);
1040 }
1041
1042 static void
1043 thread_sigframe_add(struct pthread *thread, int sig, int has_args)
1044 {
1045         struct pthread_signal_frame *psf = NULL;
1046         unsigned long   stackp;
1047
1048         /* Get the top of the threads stack: */
1049         stackp = GET_STACK_JB(thread->ctx.jb);
1050
1051         /*
1052          * Leave a little space on the stack and round down to the
1053          * nearest aligned word:
1054          */
1055         stackp -= sizeof(double);
1056         stackp &= ~0x3UL;
1057
1058         /* Allocate room on top of the stack for a new signal frame: */
1059         stackp -= sizeof(struct pthread_signal_frame);
1060
1061         psf = (struct pthread_signal_frame *) stackp;
1062
1063         /* Save the current context in the signal frame: */
1064         thread_sigframe_save(thread, psf);
1065
1066         /* Set handler specific information: */
1067         psf->sig_has_args = has_args;
1068         psf->signo = sig;
1069         if (has_args) {
1070                 /* Copy the signal handler arguments to the signal frame: */
1071                 memcpy(&psf->uc, &_thread_sigq[psf->signo - 1].uc,
1072                     sizeof(psf->uc));
1073                 memcpy(&psf->siginfo, &_thread_sigq[psf->signo - 1].siginfo,
1074                     sizeof(psf->siginfo));
1075         }
1076
1077         /* Setup the signal mask: */
1078         SIGSETOR(thread->sigmask, _thread_sigact[sig - 1].sa_mask);
1079         sigaddset(&thread->sigmask, sig);
1080
1081         /* Set up the new frame: */
1082         thread->curframe = psf;
1083         thread->flags &= PTHREAD_FLAGS_PRIVATE | PTHREAD_FLAGS_TRACE |
1084             PTHREAD_FLAGS_IN_SYNCQ;
1085         /*
1086          * Set up the context:
1087          */
1088         stackp -= sizeof(double);
1089         _setjmp(thread->ctx.jb);
1090         SET_STACK_JB(thread->ctx.jb, stackp);
1091         SET_RETURN_ADDR_JB(thread->ctx.jb, _thread_sig_wrapper);
1092 }
1093
1094 void
1095 _thread_sigframe_restore(struct pthread *thread,
1096     struct pthread_signal_frame *psf)
1097 {
1098         memcpy(&thread->ctx, &psf->ctx, sizeof(thread->ctx));
1099         /*
1100          * Only restore the signal mask if it hasn't been changed
1101          * by the application during invocation of the signal handler:
1102          */
1103         if (thread->sigmask_seqno == psf->saved_state.psd_sigmask_seqno)
1104                 thread->sigmask = psf->saved_state.psd_sigmask;
1105         thread->curframe = psf->saved_state.psd_curframe;
1106         thread->wakeup_time = psf->saved_state.psd_wakeup_time;
1107         thread->data = psf->saved_state.psd_wait_data;
1108         thread->state = psf->saved_state.psd_state;
1109         thread->flags = psf->saved_state.psd_flags;
1110         thread->interrupted = psf->saved_state.psd_interrupted;
1111         thread->signo = psf->saved_state.psd_signo;
1112         thread->sig_defer_count = psf->saved_state.psd_sig_defer_count;
1113 }
1114
1115 static void
1116 thread_sigframe_save(struct pthread *thread, struct pthread_signal_frame *psf)
1117 {
1118         memcpy(&psf->ctx, &thread->ctx, sizeof(thread->ctx));
1119         psf->saved_state.psd_sigmask = thread->sigmask;
1120         psf->saved_state.psd_curframe = thread->curframe;
1121         psf->saved_state.psd_wakeup_time = thread->wakeup_time;
1122         psf->saved_state.psd_wait_data = thread->data;
1123         psf->saved_state.psd_state = thread->state;
1124         psf->saved_state.psd_flags = thread->flags &
1125             (PTHREAD_FLAGS_PRIVATE | PTHREAD_FLAGS_TRACE);
1126         psf->saved_state.psd_interrupted = thread->interrupted;
1127         psf->saved_state.psd_sigmask_seqno = thread->sigmask_seqno;
1128         psf->saved_state.psd_signo = thread->signo;
1129         psf->saved_state.psd_sig_defer_count = thread->sig_defer_count;
1130 }
1131