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