]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libkse/thread/thr_sig.c
Use a generic way to back threads out of wait queues when handling
[FreeBSD/FreeBSD.git] / lib / libkse / thread / thr_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$
33  */
34 #include <sys/param.h>
35 #include <sys/types.h>
36 #include <sys/signalvar.h>
37 #include <signal.h>
38 #include <errno.h>
39 #include <fcntl.h>
40 #include <unistd.h>
41 #include <string.h>
42 #include <pthread.h>
43 #include "thr_private.h"
44
45 /* Prototypes: */
46 static inline void build_siginfo(siginfo_t *info, int signo);
47 #ifndef SYSTEM_SCOPE_ONLY
48 static struct pthread *thr_sig_find(struct kse *curkse, int sig,
49                     siginfo_t *info);
50 #endif
51 static inline void thr_sigframe_restore(struct pthread *thread,
52         struct pthread_sigframe *psf);
53 static inline void thr_sigframe_save(struct pthread *thread,
54         struct pthread_sigframe *psf);
55
56 #define SA_KILL         0x01            /* terminates process by default */
57 #define SA_STOP         0x02
58 #define SA_CONT         0x04
59
60 static int sigproptbl[NSIG] = {
61         SA_KILL,        /* SIGHUP */
62         SA_KILL,        /* SIGINT */
63         SA_KILL,        /* SIGQUIT */
64         SA_KILL,        /* SIGILL */
65         SA_KILL,        /* SIGTRAP */
66         SA_KILL,        /* SIGABRT */
67         SA_KILL,        /* SIGEMT */
68         SA_KILL,        /* SIGFPE */
69         SA_KILL,        /* SIGKILL */
70         SA_KILL,        /* SIGBUS */
71         SA_KILL,        /* SIGSEGV */
72         SA_KILL,        /* SIGSYS */
73         SA_KILL,        /* SIGPIPE */
74         SA_KILL,        /* SIGALRM */
75         SA_KILL,        /* SIGTERM */
76         0,              /* SIGURG */
77         SA_STOP,        /* SIGSTOP */
78         SA_STOP,        /* SIGTSTP */
79         SA_CONT,        /* SIGCONT */
80         0,              /* SIGCHLD */
81         SA_STOP,        /* SIGTTIN */
82         SA_STOP,        /* SIGTTOU */
83         0,              /* SIGIO */
84         SA_KILL,        /* SIGXCPU */
85         SA_KILL,        /* SIGXFSZ */
86         SA_KILL,        /* SIGVTALRM */
87         SA_KILL,        /* SIGPROF */
88         0,              /* SIGWINCH  */
89         0,              /* SIGINFO */
90         SA_KILL,        /* SIGUSR1 */
91         SA_KILL         /* SIGUSR2 */
92 };
93
94 /* #define DEBUG_SIGNAL */
95 #ifdef DEBUG_SIGNAL
96 #define DBG_MSG         stdout_debug
97 #else
98 #define DBG_MSG(x...)
99 #endif
100
101 /*
102  * Signal setup and delivery.
103  *
104  * 1) Delivering signals to threads in the same KSE.
105  *    These signals are sent by upcall events and are set in the
106  *    km_sigscaught field of the KSE mailbox.  Since these signals
107  *    are received while operating on the KSE stack, they can be
108  *    delivered either by using signalcontext() to add a stack frame
109  *    to the target thread's stack, or by adding them in the thread's
110  *    pending set and having the thread run them down after it 
111  * 2) Delivering signals to threads in other KSEs/KSEGs.
112  * 3) Delivering signals to threads in critical regions.
113  * 4) Delivering signals to threads after they change their signal masks.
114  *
115  * Methods of delivering signals.
116  *
117  *   1) Add a signal frame to the thread's saved context.
118  *   2) Add the signal to the thread structure, mark the thread as
119  *      having signals to handle, and let the thread run them down
120  *      after it resumes from the KSE scheduler.
121  *
122  * Problem with 1).  You can't do this to a running thread or a
123  * thread in a critical region.
124  *
125  * Problem with 2).  You can't do this to a thread that doesn't
126  * yield in some way (explicitly enters the scheduler).  A thread
127  * blocked in the kernel or a CPU hungry thread will not see the
128  * signal without entering the scheduler.
129  *
130  * The solution is to use both 1) and 2) to deliver signals:
131  *
132  *   o Thread in critical region - use 2).  When the thread
133  *     leaves the critical region it will check to see if it
134  *     has pending signals and run them down.
135  *
136  *   o Thread enters scheduler explicitly - use 2).  The thread
137  *     can check for pending signals after it returns from the
138  *     the scheduler.
139  *
140  *   o Thread is running and not current thread - use 2).  When the
141  *     thread hits a condition specified by one of the other bullets,
142  *     the signal will be delivered.
143  *
144  *   o Thread is running and is current thread (e.g., the thread
145  *     has just changed its signal mask and now sees that it has
146  *     pending signals) - just run down the pending signals.
147  *
148  *   o Thread is swapped out due to quantum expiration - use 1)
149  *
150  *   o Thread is blocked in kernel - kse_thr_wakeup() and then
151  *     use 1)
152  */
153
154 /*
155  * Rules for selecting threads for signals received:
156  *
157  *   1) If the signal is a sychronous signal, it is delivered to
158  *      the generating (current thread).  If the thread has the
159  *      signal masked, it is added to the threads pending signal
160  *      set until the thread unmasks it.
161  *
162  *   2) A thread in sigwait() where the signal is in the thread's
163  *      waitset.
164  *
165  *   3) A thread in sigsuspend() where the signal is not in the
166  *      thread's suspended signal mask.
167  *
168  *   4) Any thread (first found/easiest to deliver) that has the
169  *      signal unmasked.
170  */
171
172 #ifndef SYSTEM_SCOPE_ONLY
173
174 static void *
175 sig_daemon(void *arg /* Unused */)
176 {
177         int i;
178         kse_critical_t crit;
179         struct timespec ts;
180         sigset_t set;
181         struct kse *curkse;
182         struct pthread *curthread = _get_curthread();
183
184         DBG_MSG("signal daemon started(%p)\n", curthread);
185         
186         curthread->name = strdup("signal thread");
187         crit = _kse_critical_enter();
188         curkse = _get_curkse();
189
190         /*
191          * Daemon thread is a bound thread and we must be created with
192          * all signals masked
193          */
194 #if 0   
195         SIGFILLSET(set);
196         __sys_sigprocmask(SIG_SETMASK, &set, NULL);
197 #endif  
198         __sys_sigpending(&set);
199         ts.tv_sec = 0;
200         ts.tv_nsec = 0;
201         while (1) {
202                 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
203                 _thr_proc_sigpending = set;
204                 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
205                 for (i = 1; i <= _SIG_MAXSIG; i++) {
206                         if (SIGISMEMBER(set, i) != 0)
207                                 _thr_sig_dispatch(curkse, i,
208                                     NULL /* no siginfo */);
209                 }
210                 ts.tv_sec = 30;
211                 ts.tv_nsec = 0;
212                 curkse->k_kcb->kcb_kmbx.km_flags =
213                     KMF_NOUPCALL | KMF_NOCOMPLETED | KMF_WAITSIGEVENT;
214                 kse_release(&ts);
215                 curkse->k_kcb->kcb_kmbx.km_flags = 0;
216                 set = curkse->k_kcb->kcb_kmbx.km_sigscaught;
217         }
218         return (0);
219 }
220
221
222 /* Utility function to create signal daemon thread */
223 int
224 _thr_start_sig_daemon(void)
225 {
226         pthread_attr_t attr;
227         sigset_t sigset, oldset;
228
229         SIGFILLSET(sigset);
230         pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
231         pthread_attr_init(&attr);
232         pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
233         attr->flags |= THR_SIGNAL_THREAD;
234         /* sigmask will be inherited */
235         if (pthread_create(&_thr_sig_daemon, &attr, sig_daemon, NULL))
236                 PANIC("can not create signal daemon thread!\n");
237         pthread_attr_destroy(&attr);
238         pthread_sigmask(SIG_SETMASK, &oldset, NULL);
239         return (0);
240 }
241
242 /*
243  * This signal handler only delivers asynchronous signals.
244  * This must be called with upcalls disabled and without
245  * holding any locks.
246  */
247 void
248 _thr_sig_dispatch(struct kse *curkse, int sig, siginfo_t *info)
249 {
250         struct kse_mailbox *kmbx;
251         struct pthread *thread;
252
253         DBG_MSG(">>> _thr_sig_dispatch(%d)\n", sig);
254
255         /* Check if the signal requires a dump of thread information: */
256         if (sig == SIGINFO) {
257                 /* Dump thread information to file: */
258                 _thread_dump_info();
259         }
260
261         while ((thread = thr_sig_find(curkse, sig, info)) != NULL) {
262                 /*
263                  * Setup the target thread to receive the signal:
264                  */
265                 DBG_MSG("Got signal %d, selecting thread %p\n", sig, thread);
266                 KSE_SCHED_LOCK(curkse, thread->kseg);
267                 if ((thread->state == PS_DEAD) ||
268                     (thread->state == PS_DEADLOCK) ||
269                     THR_IS_EXITING(thread) || THR_IS_SUSPENDED(thread)) {
270                         KSE_SCHED_UNLOCK(curkse, thread->kseg);
271                         _thr_ref_delete(NULL, thread);
272                 } else if (SIGISMEMBER(thread->sigmask, sig)) {
273                         KSE_SCHED_UNLOCK(curkse, thread->kseg);
274                         _thr_ref_delete(NULL, thread);
275                 } else {
276                         kmbx = _thr_sig_add(thread, sig, info);
277                         KSE_SCHED_UNLOCK(curkse, thread->kseg);
278                         _thr_ref_delete(NULL, thread);
279                         if (kmbx != NULL)
280                                 kse_wakeup(kmbx);
281                         break;
282                 }
283         }
284         DBG_MSG("<<< _thr_sig_dispatch\n");
285 }
286
287 #endif /* ! SYSTEM_SCOPE_ONLY */
288
289 static __inline int
290 sigprop(int sig)
291 {
292
293         if (sig > 0 && sig < NSIG)
294                 return (sigproptbl[_SIG_IDX(sig)]);
295         return (0);
296 }
297
298 typedef void (*ohandler)(int sig, int code,
299         struct sigcontext *scp, char *addr, __sighandler_t *catcher);
300
301 void
302 _thr_sig_handler(int sig, siginfo_t *info, ucontext_t *ucp)
303 {
304         struct pthread_sigframe psf;
305         __siginfohandler_t *sigfunc;
306         struct pthread *curthread;
307         struct kse *curkse;
308         struct sigaction act;
309         int sa_flags, err_save;
310
311         err_save = errno;
312
313         DBG_MSG(">>> _thr_sig_handler(%d)\n", sig);
314
315         curthread = _get_curthread();
316         if (curthread == NULL)
317                 PANIC("No current thread.\n");
318         if (!(curthread->attr.flags & PTHREAD_SCOPE_SYSTEM))
319                 PANIC("Thread is not system scope.\n");
320         if (curthread->flags & THR_FLAGS_EXITING) {
321                 errno = err_save;
322                 return;
323         }
324
325         curkse = _get_curkse();
326         /*
327          * If thread is in critical region or if thread is on
328          * the way of state transition, then latch signal into buffer.
329          */
330         if (_kse_in_critical() || THR_IN_CRITICAL(curthread) ||
331             curthread->state != PS_RUNNING) {
332                 DBG_MSG(">>> _thr_sig_handler(%d) in critical\n", sig);
333                 curthread->siginfo[sig-1] = *info;
334                 curthread->check_pending = 1;
335                 curkse->k_sigseqno++;
336                 SIGADDSET(curthread->sigpend, sig);
337                 /* 
338                  * If the kse is on the way to idle itself, but
339                  * we have signal ready, we should prevent it
340                  * to sleep, kernel will latch the wakeup request,
341                  * so kse_release will return from kernel immediately.
342                  */
343                 if (KSE_IS_IDLE(curkse))
344                         kse_wakeup(&curkse->k_kcb->kcb_kmbx);
345                 errno = err_save;
346                 return;
347         }
348
349         /* Check if the signal requires a dump of thread information: */
350         if (sig == SIGINFO) {
351                 /* Dump thread information to file: */
352                 _thread_dump_info();
353         }
354
355         /* Check the threads previous state: */
356         curthread->critical_count++;
357         if (curthread->sigbackout != NULL)
358                 curthread->sigbackout((void *)curthread);
359         curthread->critical_count--;
360         thr_sigframe_save(curthread, &psf);
361         THR_ASSERT(!(curthread->sigbackout), "sigbackout was not cleared.");
362
363         _kse_critical_enter();
364         /* Get a fresh copy of signal mask */
365         __sys_sigprocmask(SIG_BLOCK, NULL, &curthread->sigmask);
366         KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
367         sigfunc = _thread_sigact[sig - 1].sa_sigaction;
368         sa_flags = _thread_sigact[sig - 1].sa_flags;
369         if (sa_flags & SA_RESETHAND) {
370                 act.sa_handler = SIG_DFL;
371                 act.sa_flags = SA_RESTART;
372                 SIGEMPTYSET(act.sa_mask);
373                 __sys_sigaction(sig, &act, NULL);
374                 __sys_sigaction(sig, NULL, &_thread_sigact[sig - 1]);
375         }
376         KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
377         _kse_critical_leave(&curthread->tcb->tcb_tmbx);
378
379         /* Now invoke real handler */
380         if (((__sighandler_t *)sigfunc != SIG_DFL) &&
381             ((__sighandler_t *)sigfunc != SIG_IGN) && 
382             (sigfunc != (__siginfohandler_t *)_thr_sig_handler)) {
383                 if ((sa_flags & SA_SIGINFO) != 0 || info == NULL)
384                         (*(sigfunc))(sig, info, ucp);
385                 else {
386                         ((ohandler)(*sigfunc))(
387                                 sig, info->si_code, (struct sigcontext *)ucp,
388                                 info->si_addr, (__sighandler_t *)sigfunc);
389                 }
390         } else {
391                 if ((__sighandler_t *)sigfunc == SIG_DFL) {
392                         if (sigprop(sig) & SA_KILL) {
393                                 if (_kse_isthreaded())
394                                         kse_thr_interrupt(NULL,
395                                                  KSE_INTR_SIGEXIT, sig);
396                                 else
397                                         kill(getpid(), sig);
398                         }
399 #ifdef NOTYET
400                         else if (sigprop(sig) & SA_STOP)
401                                 kse_thr_interrupt(NULL, KSE_INTR_JOBSTOP, sig);
402 #endif
403                 }
404         }
405         _kse_critical_enter();
406         curthread->sigmask = ucp->uc_sigmask;
407         SIG_CANTMASK(curthread->sigmask);
408         _kse_critical_leave(&curthread->tcb->tcb_tmbx);
409
410         thr_sigframe_restore(curthread, &psf);
411
412         DBG_MSG("<<< _thr_sig_handler(%d)\n", sig);
413
414         errno = err_save;
415 }
416
417 struct sighandle_info {
418         __siginfohandler_t *sigfunc;
419         int sa_flags;
420         int sig;
421         siginfo_t *info;
422         ucontext_t *ucp;
423 };
424
425 static void handle_signal(struct pthread *curthread,
426         struct sighandle_info *shi);
427 static void handle_signal_altstack(struct pthread *curthread,
428         struct sighandle_info *shi);
429
430 /* Must be called with signal lock and schedule lock held in order */
431 static void
432 thr_sig_invoke_handler(struct pthread *curthread, int sig, siginfo_t *info,
433     ucontext_t *ucp)
434 {
435         __siginfohandler_t *sigfunc;
436         sigset_t sigmask;
437         int sa_flags;
438         int onstack;
439         struct sigaction act;
440         struct kse *curkse;
441         struct sighandle_info shi;
442
443         /*
444          * Invoke the signal handler without going through the scheduler:
445          */
446         DBG_MSG("Got signal %d, calling handler for current thread %p\n",
447             sig, curthread);
448
449         if (!_kse_in_critical())
450                 PANIC("thr_sig_invoke_handler without in critical\n");
451         curkse = curthread->kse;
452         /*
453          * Check that a custom handler is installed and if
454          * the signal is not blocked:
455          */
456         sigfunc = _thread_sigact[sig - 1].sa_sigaction;
457         sa_flags = _thread_sigact[sig - 1].sa_flags;
458         sigmask = curthread->sigmask;
459         SIGSETOR(curthread->sigmask, _thread_sigact[sig - 1].sa_mask);
460         if (!(sa_flags & (SA_NODEFER | SA_RESETHAND)))
461                 SIGADDSET(curthread->sigmask, sig);
462         if ((sig != SIGILL) && (sa_flags & SA_RESETHAND)) {
463                 act.sa_handler = SIG_DFL;
464                 act.sa_flags = SA_RESTART;
465                 SIGEMPTYSET(act.sa_mask);
466                 __sys_sigaction(sig, &act, NULL);
467                 __sys_sigaction(sig, NULL, &_thread_sigact[sig - 1]);
468         }
469         KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
470         KSE_SCHED_UNLOCK(curkse, curkse->k_kseg);
471         /*
472          * We are processing buffered signals, synchronize working
473          * signal mask into kernel.
474          */
475         if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
476                 __sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL);
477         onstack = _thr_sigonstack(&sigfunc);
478         ucp->uc_stack = curthread->sigstk;
479         ucp->uc_stack.ss_flags = (curthread->sigstk.ss_flags & SS_DISABLE)
480                 ? SS_DISABLE : ((onstack) ? SS_ONSTACK : 0);
481         if (curthread->oldsigmask) {
482                 ucp->uc_sigmask = *(curthread->oldsigmask);
483                 curthread->oldsigmask = NULL;
484         } else
485                 ucp->uc_sigmask = sigmask;
486         shi.sigfunc = sigfunc;
487         shi.sig = sig;
488         shi.sa_flags = sa_flags;
489         shi.info = info;
490         shi.ucp = ucp;
491         if ((curthread->sigstk.ss_flags & SS_DISABLE) == 0) {
492                 /* Deliver signal on alternative stack */
493                 if (sa_flags & SA_ONSTACK && !onstack)
494                         handle_signal_altstack(curthread, &shi);
495                 else
496                         handle_signal(curthread, &shi);
497         } else {
498                 handle_signal(curthread, &shi);
499         }
500
501         _kse_critical_enter();
502         /* Don't trust after critical leave/enter */
503         curkse = curthread->kse;
504
505         /*
506          * Restore the thread's signal mask.
507          */
508         curthread->sigmask = ucp->uc_sigmask;
509         SIG_CANTMASK(curthread->sigmask);
510         if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
511                 __sys_sigprocmask(SIG_SETMASK, &ucp->uc_sigmask, NULL);
512         KSE_SCHED_LOCK(curkse, curkse->k_kseg);
513         KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
514         
515         DBG_MSG("Got signal %d, handler returned %p\n", sig, curthread);
516 }
517
518 static void
519 handle_signal(struct pthread *curthread, struct sighandle_info *shi)
520 {
521         _kse_critical_leave(&curthread->tcb->tcb_tmbx);
522
523         /* Check if the signal requires a dump of thread information: */
524         if (shi->sig == SIGINFO) {
525                 /* Dump thread information to file: */
526                 _thread_dump_info();
527         }
528
529         if (((__sighandler_t *)shi->sigfunc != SIG_DFL) &&
530             ((__sighandler_t *)shi->sigfunc != SIG_IGN)) {
531                 if ((shi->sa_flags & SA_SIGINFO) != 0 || shi->info == NULL)
532                         (*(shi->sigfunc))(shi->sig, shi->info, shi->ucp);
533                 else {
534                         ((ohandler)(*shi->sigfunc))(
535                                 shi->sig, shi->info->si_code,
536                                 (struct sigcontext *)shi->ucp,
537                                 shi->info->si_addr,
538                                 (__sighandler_t *)shi->sigfunc);
539                 }
540         } else {
541                 if ((__sighandler_t *)shi->sigfunc == SIG_DFL) {
542                         if (sigprop(shi->sig) & SA_KILL) {
543                                 if (_kse_isthreaded())
544                                         kse_thr_interrupt(NULL,
545                                                  KSE_INTR_SIGEXIT, shi->sig);
546                                 else
547                                         kill(getpid(), shi->sig);
548                         }
549 #ifdef NOTYET
550                         else if (sigprop(shi->sig) & SA_STOP)
551                                 kse_thr_interrupt(NULL, KSE_INTR_JOBSTOP,
552                                         shi->sig);
553 #endif
554                 }
555         }
556 }
557
558 static void
559 handle_signal_wrapper(struct pthread *curthread, ucontext_t *ret_uc,
560         struct sighandle_info *shi)
561 {
562         shi->ucp->uc_stack.ss_flags = SS_ONSTACK;
563         handle_signal(curthread, shi);
564         if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
565                 setcontext(ret_uc);
566         else {
567                 /* Work around for ia64, THR_SETCONTEXT does not work */
568                 _kse_critical_enter();
569                 curthread->tcb->tcb_tmbx.tm_context = *ret_uc;
570                 _thread_switch(curthread->kse->k_kcb, curthread->tcb, 1);
571                 /* THR_SETCONTEXT */
572         }
573 }
574
575 /*
576  * Jump to stack set by sigaltstack before invoking signal handler
577  */
578 static void
579 handle_signal_altstack(struct pthread *curthread, struct sighandle_info *shi)
580 {
581         volatile int once;
582         ucontext_t uc1, *uc2;
583
584         THR_ASSERT(_kse_in_critical(), "Not in critical");
585
586         once = 0;
587         THR_GETCONTEXT(&uc1);
588         if (once == 0) {
589                 once = 1;
590                 /* XXX
591                  * We are still in critical region, it is safe to operate thread
592                  * context
593                  */
594                 uc2 = &curthread->tcb->tcb_tmbx.tm_context;
595                 uc2->uc_stack = curthread->sigstk;
596                 makecontext(uc2, (void (*)(void))handle_signal_wrapper,
597                         3, curthread, &uc1, shi);
598                 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
599                         setcontext(uc2);
600                 else {
601                         _thread_switch(curthread->kse->k_kcb, curthread->tcb, 1);
602                         /* THR_SETCONTEXT(uc2); */
603                 }
604         }
605 }
606
607 int
608 _thr_getprocsig(int sig, siginfo_t *siginfo)
609 {
610         kse_critical_t crit;
611         struct kse *curkse;
612         int ret;
613
614         DBG_MSG(">>> _thr_getprocsig\n");
615
616         crit = _kse_critical_enter();
617         curkse = _get_curkse();
618         KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
619         ret = _thr_getprocsig_unlocked(sig, siginfo);
620         KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
621         _kse_critical_leave(crit);
622
623         DBG_MSG("<<< _thr_getprocsig\n");
624         return (ret);
625 }
626
627 int
628 _thr_getprocsig_unlocked(int sig, siginfo_t *siginfo)
629 {
630         sigset_t sigset;
631         struct timespec ts;
632
633         /* try to retrieve signal from kernel */
634         SIGEMPTYSET(sigset);
635         SIGADDSET(sigset, sig);
636         ts.tv_sec = 0;
637         ts.tv_nsec = 0;
638         SIGDELSET(_thr_proc_sigpending, sig);
639         if (__sys_sigtimedwait(&sigset, siginfo, &ts) > 0)
640                 return (sig);
641         return (0);
642 }
643
644 #ifndef SYSTEM_SCOPE_ONLY
645 /*
646  * Find a thread that can handle the signal.  This must be called
647  * with upcalls disabled.
648  */
649 struct pthread *
650 thr_sig_find(struct kse *curkse, int sig, siginfo_t *info)
651 {
652         struct kse_mailbox *kmbx = NULL;
653         struct pthread  *pthread;
654         struct pthread  *suspended_thread, *signaled_thread;
655         __siginfohandler_t *sigfunc;
656         siginfo_t si;
657
658         DBG_MSG("Looking for thread to handle signal %d\n", sig);
659
660         /*
661          * Enter a loop to look for threads that have the signal
662          * unmasked.  POSIX specifies that a thread in a sigwait
663          * will get the signal over any other threads.  Second
664          * preference will be threads in in a sigsuspend.  Third
665          * preference will be the current thread.  If none of the
666          * above, then the signal is delivered to the first thread
667          * that is found.  Note that if a custom handler is not
668          * installed, the signal only affects threads in sigwait.
669          */
670         suspended_thread = NULL;
671         signaled_thread = NULL;
672
673         KSE_LOCK_ACQUIRE(curkse, &_thread_list_lock);
674         TAILQ_FOREACH(pthread, &_thread_list, tle) {
675                 if (pthread == _thr_sig_daemon)
676                         continue;
677                 /* Signal delivering to bound thread is done by kernel */
678                 if (pthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
679                         continue;
680                 /* Take the scheduling lock. */
681                 KSE_SCHED_LOCK(curkse, pthread->kseg);
682                 if ((pthread->state == PS_DEAD)         ||
683                     (pthread->state == PS_DEADLOCK)     ||
684                     THR_IS_EXITING(pthread)             ||
685                     THR_IS_SUSPENDED(pthread)) {
686                         ; /* Skip this thread. */
687                 } else if (pthread->state == PS_SIGWAIT &&
688                            SIGISMEMBER(*(pthread->data.sigwait->waitset), sig)) {
689                         /*
690                          * retrieve signal from kernel, if it is job control
691                          * signal, and sigaction is SIG_DFL, then we will
692                          * be stopped in kernel, we hold lock here, but that 
693                          * does not matter, because that's job control, and
694                          * whole process should be stopped.
695                          */
696                         if (_thr_getprocsig(sig, &si)) {
697                                 DBG_MSG("Waking thread %p in sigwait"
698                                         " with signal %d\n", pthread, sig);
699                                 /*  where to put siginfo ? */
700                                 *(pthread->data.sigwait->siginfo) = si;
701                                 kmbx = _thr_setrunnable_unlocked(pthread);
702                         }
703                         KSE_SCHED_UNLOCK(curkse, pthread->kseg);
704                         /*
705                          * POSIX doesn't doesn't specify which thread
706                          * will get the signal if there are multiple
707                          * waiters, so we give it to the first thread
708                          * we find.
709                          *
710                          * Do not attempt to deliver this signal
711                          * to other threads and do not add the signal
712                          * to the process pending set.
713                          */
714                         KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
715                         if (kmbx != NULL)
716                                 kse_wakeup(kmbx);
717                         if (suspended_thread != NULL)
718                                 _thr_ref_delete(NULL, suspended_thread);
719                         if (signaled_thread != NULL)
720                                 _thr_ref_delete(NULL, signaled_thread);
721                         return (NULL);
722                 } else if (!SIGISMEMBER(pthread->sigmask, sig)) {
723                         /*
724                          * If debugger is running, we don't quick exit,
725                          * and give it a chance to check the signal.
726                          */  
727                         if (_libkse_debug == 0) {
728                                 sigfunc = _thread_sigact[sig - 1].sa_sigaction;
729                                 if ((__sighandler_t *)sigfunc == SIG_DFL) {
730                                         if (sigprop(sig) & SA_KILL) {
731                                                 kse_thr_interrupt(NULL,
732                                                          KSE_INTR_SIGEXIT, sig);
733                                                 /* Never reach */
734                                         }
735                                 }
736                         }
737                         if (pthread->state == PS_SIGSUSPEND) {
738                                 if (suspended_thread == NULL) {
739                                         suspended_thread = pthread;
740                                         suspended_thread->refcount++;
741                                 }
742                         } else if (signaled_thread == NULL) {
743                                 signaled_thread = pthread;
744                                 signaled_thread->refcount++;
745                         }
746                 }
747                 KSE_SCHED_UNLOCK(curkse, pthread->kseg);
748         }
749         KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
750
751         if (suspended_thread != NULL) {
752                 pthread = suspended_thread;
753                 if (signaled_thread)
754                         _thr_ref_delete(NULL, signaled_thread);
755         } else if (signaled_thread) {
756                 pthread = signaled_thread;
757         } else {
758                 pthread = NULL;
759         }
760         return (pthread);
761 }
762 #endif /* ! SYSTEM_SCOPE_ONLY */
763
764 static inline void
765 build_siginfo(siginfo_t *info, int signo)
766 {
767         bzero(info, sizeof(*info));
768         info->si_signo = signo;
769         info->si_pid = _thr_pid;
770 }
771
772 /*
773  * This is called by a thread when it has pending signals to deliver.
774  * It should only be called from the context of the thread.
775  */
776 void
777 _thr_sig_rundown(struct pthread *curthread, ucontext_t *ucp)
778 {
779         struct pthread_sigframe psf;
780         siginfo_t siginfo;
781         int i, err_save;
782         kse_critical_t crit;
783         struct kse *curkse;
784         sigset_t sigmask;
785
786         err_save = errno;
787
788         DBG_MSG(">>> thr_sig_rundown (%p)\n", curthread);
789
790         /* Check the threads previous state: */
791         curthread->critical_count++;
792         if (curthread->sigbackout != NULL)
793                 curthread->sigbackout((void *)curthread);
794         curthread->critical_count--;
795
796         THR_ASSERT(!(curthread->sigbackout), "sigbackout was not cleared.");
797         THR_ASSERT((curthread->state == PS_RUNNING), "state is not PS_RUNNING");
798
799         thr_sigframe_save(curthread, &psf);
800         /*
801          * Lower the priority before calling the handler in case
802          * it never returns (longjmps back):
803          */
804         crit = _kse_critical_enter();
805         curkse = curthread->kse;
806         KSE_SCHED_LOCK(curkse, curkse->k_kseg);
807         KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
808         curthread->active_priority &= ~THR_SIGNAL_PRIORITY;
809         SIGFILLSET(sigmask);
810         while (1) {
811                 /*
812                  * For bound thread, we mask all signals and get a fresh
813                  * copy of signal mask from kernel
814                  */
815                 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
816                         __sys_sigprocmask(SIG_SETMASK, &sigmask,
817                                  &curthread->sigmask);
818                 }
819                 for (i = 1; i <= _SIG_MAXSIG; i++) {
820                         if (SIGISMEMBER(curthread->sigmask, i))
821                                 continue;
822                         if (SIGISMEMBER(curthread->sigpend, i)) {
823                                 SIGDELSET(curthread->sigpend, i);
824                                 siginfo = curthread->siginfo[i-1];
825                                 break;
826                         }
827                         if (!(curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) 
828                             && SIGISMEMBER(_thr_proc_sigpending, i)) {
829                                 if (_thr_getprocsig_unlocked(i, &siginfo))
830                                         break;
831                         }
832                 }
833                 if (i <= _SIG_MAXSIG)
834                         thr_sig_invoke_handler(curthread, i, &siginfo, ucp);
835                 else {
836                         if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
837                                 __sys_sigprocmask(SIG_SETMASK,
838                                                  &curthread->sigmask, NULL);
839                         }
840                         break;
841                 }
842         }
843
844         /* Don't trust after signal handling */
845         curkse = curthread->kse;
846         KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
847         KSE_SCHED_UNLOCK(curkse, curkse->k_kseg);
848         _kse_critical_leave(&curthread->tcb->tcb_tmbx);
849         /* repost masked signal to kernel, it hardly happens in real world */
850         if ((curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) &&
851             !SIGISEMPTY(curthread->sigpend)) { /* dirty read */
852                 __sys_sigprocmask(SIG_SETMASK, &sigmask, &curthread->sigmask);
853                 for (i = 1; i <= _SIG_MAXSIG; ++i) {
854                         if (SIGISMEMBER(curthread->sigpend, i)) {
855                                 SIGDELSET(curthread->sigpend, i);
856                                 if (!_kse_isthreaded())
857                                         kill(getpid(), i);
858                                 else
859                                         kse_thr_interrupt(
860                                                 &curthread->tcb->tcb_tmbx,
861                                                 KSE_INTR_SENDSIG,
862                                                 i);
863                         }
864                 }
865                 __sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL);
866         }
867         DBG_MSG("<<< thr_sig_rundown (%p)\n", curthread);
868
869         thr_sigframe_restore(curthread, &psf);
870         errno = err_save;
871 }
872
873 /*
874  * This checks pending signals for the current thread.  It should be
875  * called whenever a thread changes its signal mask.  Note that this
876  * is called from a thread (using its stack).
877  *
878  * XXX - We might want to just check to see if there are pending
879  *       signals for the thread here, but enter the UTS scheduler
880  *       to actually install the signal handler(s).
881  */
882 void
883 _thr_sig_check_pending(struct pthread *curthread)
884 {
885         ucontext_t uc;
886         volatile int once;
887         int errsave;
888
889         /*
890          * If the thread is in critical region, delay processing signals.
891          * If the thread state is not PS_RUNNING, it might be switching
892          * into UTS and but a THR_LOCK_RELEASE saw check_pending, and it
893          * goes here, in the case we delay processing signals, lets UTS
894          * process complicated things, normally UTS will call _thr_sig_add
895          * to resume the thread, so we needn't repeat doing it here.
896          */
897         if (THR_IN_CRITICAL(curthread) || curthread->state != PS_RUNNING)
898                 return;
899
900         errsave = errno;
901         once = 0;
902         THR_GETCONTEXT(&uc);
903         if (once == 0) {
904                 once = 1;
905                 curthread->check_pending = 0;
906                 _thr_sig_rundown(curthread, &uc);
907         }
908         errno = errsave;
909 }
910
911 /*
912  * Perform thread specific actions in response to a signal.
913  * This function is only called if there is a handler installed
914  * for the signal, and if the target thread has the signal
915  * unmasked.
916  *
917  * This must be called with the thread's scheduling lock held.
918  */
919 struct kse_mailbox *
920 _thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info)
921 {
922         siginfo_t siginfo;
923         struct kse *curkse;
924         struct kse_mailbox *kmbx = NULL;
925         struct pthread *curthread = _get_curthread();
926         int     restart;
927         int     suppress_handler = 0;
928         int     fromproc = 0;
929         __sighandler_t *sigfunc;
930
931         DBG_MSG(">>> _thr_sig_add %p (%d)\n", pthread, sig);
932
933         curkse = _get_curkse();
934         restart = _thread_sigact[sig - 1].sa_flags & SA_RESTART;
935         sigfunc = _thread_sigact[sig - 1].sa_handler;
936         fromproc = (curthread == _thr_sig_daemon);
937
938         if (pthread->state == PS_DEAD || pthread->state == PS_DEADLOCK ||
939             pthread->state == PS_STATE_MAX)
940                 return (NULL); /* return false */
941
942         if ((pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) &&
943             (curthread != pthread)) {
944                 PANIC("Please use _thr_send_sig for bound thread");
945                 return (NULL);
946         }
947
948         if (pthread->state != PS_SIGWAIT &&
949             SIGISMEMBER(pthread->sigmask, sig)) {
950                 /* signal is masked, just add signal to thread. */
951                 if (!fromproc) {
952                         SIGADDSET(pthread->sigpend, sig);
953                         if (info == NULL)
954                                 build_siginfo(&pthread->siginfo[sig-1], sig);
955                         else if (info != &pthread->siginfo[sig-1])
956                                 memcpy(&pthread->siginfo[sig-1], info,
957                                          sizeof(*info));
958                 } else {
959                         if (!_thr_getprocsig(sig, &pthread->siginfo[sig-1]))
960                                 return (NULL);
961                         SIGADDSET(pthread->sigpend, sig);
962                 }
963         }
964         else {
965                 /* if process signal not exists, just return */
966                 if (fromproc) {
967                         if (!_thr_getprocsig(sig, &siginfo))
968                                 return (NULL);
969                         info = &siginfo;
970                 }
971
972                 if (pthread->state != PS_SIGWAIT && sigfunc == SIG_DFL &&
973                     (sigprop(sig) & SA_KILL)) {
974                         kse_thr_interrupt(NULL, KSE_INTR_SIGEXIT, sig);
975                         /* Never reach */
976                 }
977
978                 /*
979                  * Process according to thread state:
980                  */
981                 switch (pthread->state) {
982                 case PS_DEAD:
983                 case PS_DEADLOCK:
984                 case PS_STATE_MAX:
985                         return (NULL);  /* XXX return false */
986                 case PS_LOCKWAIT:
987                 case PS_SUSPENDED:
988                         /*
989                          * You can't call a signal handler for threads in these
990                          * states.
991                          */
992                         suppress_handler = 1;
993                         break;
994                 case PS_RUNNING:
995                         if ((pthread->flags & THR_FLAGS_IN_RUNQ)) {
996                                 THR_RUNQ_REMOVE(pthread);
997                                 pthread->active_priority |= THR_SIGNAL_PRIORITY;
998                                 THR_RUNQ_INSERT_TAIL(pthread);
999                         } else {
1000                                 /* Possible not in RUNQ and has curframe ? */
1001                                 pthread->active_priority |= THR_SIGNAL_PRIORITY;
1002                         }
1003                         break;
1004                 /*
1005                  * States which cannot be interrupted but still require the
1006                  * signal handler to run:
1007                  */
1008                 case PS_COND_WAIT:
1009                 case PS_MUTEX_WAIT:
1010                         break;
1011
1012                 case PS_SLEEP_WAIT:
1013                         /*
1014                          * Unmasked signals always cause sleep to terminate
1015                          * early regardless of SA_RESTART:
1016                          */
1017                         pthread->interrupted = 1;
1018                         break;
1019
1020                 case PS_JOIN:
1021                         break;
1022
1023                 case PS_SIGSUSPEND:
1024                         pthread->interrupted = 1;
1025                         break;
1026
1027                 case PS_SIGWAIT:
1028                         if (info == NULL)
1029                                 build_siginfo(&pthread->siginfo[sig-1], sig);
1030                         else if (info != &pthread->siginfo[sig-1])
1031                                 memcpy(&pthread->siginfo[sig-1], info,
1032                                         sizeof(*info));
1033                         /*
1034                          * The signal handler is not called for threads in
1035                          * SIGWAIT.
1036                          */
1037                         suppress_handler = 1;
1038                         /* Wake up the thread if the signal is not blocked. */
1039                         if (SIGISMEMBER(*(pthread->data.sigwait->waitset), sig)) {
1040                                 /* Return the signal number: */
1041                                 *(pthread->data.sigwait->siginfo) = pthread->siginfo[sig-1];
1042                                 /* Make the thread runnable: */
1043                                 kmbx = _thr_setrunnable_unlocked(pthread);
1044                         } else {
1045                                 /* Increment the pending signal count. */
1046                                 SIGADDSET(pthread->sigpend, sig);
1047                                 if (!SIGISMEMBER(pthread->sigmask, sig)) {
1048                                         if (sigfunc == SIG_DFL &&
1049                                             sigprop(sig) & SA_KILL) {
1050                                                 kse_thr_interrupt(NULL,
1051                                                          KSE_INTR_SIGEXIT,
1052                                                          sig);
1053                                                 /* Never reach */
1054                                         }
1055                                         pthread->check_pending = 1;
1056                                         pthread->interrupted = 1;
1057                                         kmbx = _thr_setrunnable_unlocked(pthread);
1058                                 }
1059                         }
1060                         return (kmbx);
1061                 }
1062
1063                 SIGADDSET(pthread->sigpend, sig);
1064                 if (info == NULL)
1065                         build_siginfo(&pthread->siginfo[sig-1], sig);
1066                 else if (info != &pthread->siginfo[sig-1])
1067                         memcpy(&pthread->siginfo[sig-1], info, sizeof(*info));
1068                 pthread->check_pending = 1;
1069                 if (!(pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) &&
1070                     (pthread->blocked != 0) && !THR_IN_CRITICAL(pthread))
1071                         kse_thr_interrupt(&pthread->tcb->tcb_tmbx,
1072                             restart ? KSE_INTR_RESTART : KSE_INTR_INTERRUPT, 0);
1073                 if (suppress_handler == 0) {
1074                         /*
1075                          * Setup a signal frame and save the current threads
1076                          * state:
1077                          */
1078                         if (pthread->state != PS_RUNNING) {
1079                                 if (pthread->flags & THR_FLAGS_IN_RUNQ)
1080                                         THR_RUNQ_REMOVE(pthread);
1081                                 pthread->active_priority |= THR_SIGNAL_PRIORITY;
1082                                 kmbx = _thr_setrunnable_unlocked(pthread);
1083                         }
1084                 }
1085         }
1086         return (kmbx);
1087 }
1088
1089 /*
1090  * Send a signal to a specific thread (ala pthread_kill):
1091  */
1092 void
1093 _thr_sig_send(struct pthread *pthread, int sig)
1094 {
1095         struct pthread *curthread = _get_curthread();
1096         struct kse_mailbox *kmbx;
1097
1098         if (pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
1099                 kse_thr_interrupt(&pthread->tcb->tcb_tmbx, KSE_INTR_SENDSIG, sig);
1100                 return;
1101         }
1102
1103         /* Lock the scheduling queue of the target thread. */
1104         THR_SCHED_LOCK(curthread, pthread);
1105         if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) {
1106                 kmbx = _thr_sig_add(pthread, sig, NULL);
1107                 /* Add a preemption point. */
1108                 if (kmbx == NULL && (curthread->kseg == pthread->kseg) &&
1109                     (pthread->active_priority > curthread->active_priority))
1110                         curthread->critical_yield = 1;
1111                 THR_SCHED_UNLOCK(curthread, pthread);
1112                 if (kmbx != NULL)
1113                         kse_wakeup(kmbx);
1114                 /* XXX
1115                  * If thread sent signal to itself, check signals now.
1116                  * It is not really needed, _kse_critical_leave should
1117                  * have already checked signals.
1118                  */
1119                 if (pthread == curthread && curthread->check_pending)
1120                         _thr_sig_check_pending(curthread);
1121
1122         } else  {
1123                 THR_SCHED_UNLOCK(curthread, pthread);
1124         }
1125 }
1126
1127 static inline void
1128 thr_sigframe_restore(struct pthread *curthread, struct pthread_sigframe *psf)
1129 {
1130         kse_critical_t crit;
1131         struct kse *curkse;
1132
1133         THR_THREAD_LOCK(curthread, curthread);
1134         curthread->cancelflags = psf->psf_cancelflags;
1135         crit = _kse_critical_enter();
1136         curkse = curthread->kse;
1137         KSE_SCHED_LOCK(curkse, curthread->kseg);
1138         curthread->flags = psf->psf_flags;
1139         curthread->interrupted = psf->psf_interrupted;
1140         curthread->timeout = psf->psf_timeout;
1141         curthread->data = psf->psf_wait_data;
1142         curthread->wakeup_time = psf->psf_wakeup_time;
1143         curthread->continuation = psf->psf_continuation;
1144         KSE_SCHED_UNLOCK(curkse, curthread->kseg);
1145         _kse_critical_leave(crit);
1146         THR_THREAD_UNLOCK(curthread, curthread);
1147 }
1148
1149 static inline void
1150 thr_sigframe_save(struct pthread *curthread, struct pthread_sigframe *psf)
1151 {
1152         kse_critical_t crit;
1153         struct kse *curkse;
1154
1155         THR_THREAD_LOCK(curthread, curthread);
1156         psf->psf_cancelflags = curthread->cancelflags;
1157         crit = _kse_critical_enter();
1158         curkse = curthread->kse;
1159         KSE_SCHED_LOCK(curkse, curthread->kseg);
1160         /* This has to initialize all members of the sigframe. */
1161         psf->psf_flags = (curthread->flags & (THR_FLAGS_PRIVATE | THR_FLAGS_EXITING));
1162         psf->psf_interrupted = curthread->interrupted;
1163         psf->psf_timeout = curthread->timeout;
1164         psf->psf_wait_data = curthread->data;
1165         psf->psf_wakeup_time = curthread->wakeup_time;
1166         psf->psf_continuation = curthread->continuation;
1167         KSE_SCHED_UNLOCK(curkse, curthread->kseg);
1168         _kse_critical_leave(crit);
1169         THR_THREAD_UNLOCK(curthread, curthread);
1170 }
1171
1172 void
1173 _thr_signal_init(void)
1174 {
1175         struct sigaction act;
1176         __siginfohandler_t *sigfunc;
1177         int i;
1178         sigset_t sigset;
1179
1180         SIGFILLSET(sigset);
1181         __sys_sigprocmask(SIG_SETMASK, &sigset, &_thr_initial->sigmask);
1182         /* Enter a loop to get the existing signal status: */
1183         for (i = 1; i <= _SIG_MAXSIG; i++) {
1184                 /* Get the signal handler details: */
1185                 if (__sys_sigaction(i, NULL, &_thread_sigact[i - 1]) != 0) {
1186                         /*
1187                          * Abort this process if signal
1188                          * initialisation fails:
1189                          */
1190                         PANIC("Cannot read signal handler info");
1191                 }
1192                 /* Intall wrapper if handler was set */
1193                 sigfunc = _thread_sigact[i - 1].sa_sigaction;
1194                 if (((__sighandler_t *)sigfunc) != SIG_DFL &&
1195                     ((__sighandler_t *)sigfunc) != SIG_IGN) {
1196                         act = _thread_sigact[i - 1];
1197                         act.sa_flags |= SA_SIGINFO;
1198                         act.sa_sigaction =
1199                                 (__siginfohandler_t *)_thr_sig_handler;
1200                         __sys_sigaction(i, &act, NULL);
1201                 }
1202         }
1203         /*
1204          * Install the signal handler for SIGINFO.  It isn't
1205          * really needed, but it is nice to have for debugging
1206          * purposes.
1207          */
1208         _thread_sigact[SIGINFO - 1].sa_flags = SA_SIGINFO | SA_RESTART;
1209         SIGEMPTYSET(act.sa_mask);
1210         act.sa_flags = SA_SIGINFO | SA_RESTART;
1211         act.sa_sigaction = (__siginfohandler_t *)&_thr_sig_handler;
1212         if (__sys_sigaction(SIGINFO, &act, NULL) != 0) {
1213                 __sys_sigprocmask(SIG_SETMASK, &_thr_initial->sigmask, NULL);
1214                 /*
1215                  * Abort this process if signal initialisation fails:
1216                  */
1217                 PANIC("Cannot initialize signal handler");
1218         }
1219         __sys_sigprocmask(SIG_SETMASK, &_thr_initial->sigmask, NULL);
1220         __sys_sigaltstack(NULL, &_thr_initial->sigstk);
1221 }
1222
1223 void
1224 _thr_signal_deinit(void)
1225 {
1226         int i;
1227         struct pthread *curthread = _get_curthread();
1228
1229         /* Clear process pending signals. */
1230         sigemptyset(&_thr_proc_sigpending);
1231
1232         /* Enter a loop to get the existing signal status: */
1233         for (i = 1; i <= _SIG_MAXSIG; i++) {
1234                 /* Check for signals which cannot be trapped: */
1235                 if (i == SIGKILL || i == SIGSTOP) {
1236                 }
1237
1238                 /* Set the signal handler details: */
1239                 else if (__sys_sigaction(i, &_thread_sigact[i - 1],
1240                          NULL) != 0) {
1241                         /*
1242                          * Abort this process if signal
1243                          * initialisation fails:
1244                          */
1245                         PANIC("Cannot set signal handler info");
1246                 }
1247         }
1248         __sys_sigaltstack(&curthread->sigstk, NULL);
1249 }
1250