2 * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
34 #include <sys/param.h>
35 #include <sys/types.h>
36 #include <sys/signalvar.h>
43 #include "thr_private.h"
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,
50 static void handle_special_signals(struct kse *curkse, int sig);
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);
58 #define SA_KILL 0x01 /* terminates process by default */
62 static int sigproptbl[NSIG] = {
65 SA_KILL, /* SIGQUIT */
67 SA_KILL, /* SIGTRAP */
68 SA_KILL, /* SIGABRT */
71 SA_KILL, /* SIGKILL */
73 SA_KILL, /* SIGSEGV */
75 SA_KILL, /* SIGPIPE */
76 SA_KILL, /* SIGALRM */
77 SA_KILL, /* SIGTERM */
79 SA_STOP, /* SIGSTOP */
80 SA_STOP, /* SIGTSTP */
81 SA_CONT, /* SIGCONT */
83 SA_STOP, /* SIGTTIN */
84 SA_STOP, /* SIGTTOU */
86 SA_KILL, /* SIGXCPU */
87 SA_KILL, /* SIGXFSZ */
88 SA_KILL, /* SIGVTALRM */
89 SA_KILL, /* SIGPROF */
92 SA_KILL, /* SIGUSR1 */
96 /* #define DEBUG_SIGNAL */
98 #define DBG_MSG stdout_debug
100 #define DBG_MSG(x...)
104 * Signal setup and delivery.
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.
117 * Methods of delivering signals.
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.
124 * Problem with 1). You can't do this to a running thread or a
125 * thread in a critical region.
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.
132 * The solution is to use both 1) and 2) to deliver signals:
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.
138 * o Thread enters scheduler explicitly - use 2). The thread
139 * can check for pending signals after it returns from the
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.
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.
150 * o Thread is swapped out due to quantum expiration - use 1)
152 * o Thread is blocked in kernel - kse_thr_wakeup() and then
157 * Rules for selecting threads for signals received:
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.
164 * 2) A thread in sigwait() where the signal is in the thread's
167 * 3) A thread in sigsuspend() where the signal is not in the
168 * thread's suspended signal mask.
170 * 4) Any thread (first found/easiest to deliver) that has the
174 #ifndef SYSTEM_SCOPE_ONLY
177 sig_daemon(void *arg /* Unused */)
184 struct pthread *curthread = _get_curthread();
186 DBG_MSG("signal daemon started(%p)\n", curthread);
188 curthread->name = strdup("signal thread");
189 crit = _kse_critical_enter();
190 curkse = _get_curkse();
193 * Daemon thread is a bound thread and we must be created with
198 __sys_sigprocmask(SIG_SETMASK, &set, NULL);
200 __sys_sigpending(&set);
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 */);
214 curkse->k_kcb->kcb_kmbx.km_flags =
215 KMF_NOUPCALL | KMF_NOCOMPLETED | KMF_WAITSIGEVENT;
217 curkse->k_kcb->kcb_kmbx.km_flags = 0;
218 set = curkse->k_kcb->kcb_kmbx.km_sigscaught;
224 /* Utility function to create signal daemon thread */
226 _thr_start_sig_daemon(void)
229 sigset_t sigset, oldset;
232 pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
233 pthread_attr_init(&attr);
234 pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
235 /* sigmask will be inherited */
236 if (pthread_create(&_thr_sig_daemon, &attr, sig_daemon, NULL))
237 PANIC("can not create signal daemon thread!\n");
238 pthread_attr_destroy(&attr);
239 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
244 * This signal handler only delivers asynchronous signals.
245 * This must be called with upcalls disabled and without
249 _thr_sig_dispatch(struct kse *curkse, int sig, siginfo_t *info)
251 struct kse_mailbox *kmbx;
252 struct pthread *thread;
254 DBG_MSG(">>> _thr_sig_dispatch(%d)\n", sig);
256 /* Some signals need special handling: */
257 handle_special_signals(curkse, sig);
259 /* Check if the signal requires a dump of thread information: */
260 if (sig == SIGINFO) {
261 /* Dump thread information to file: */
265 while ((thread = thr_sig_find(curkse, sig, info)) != NULL) {
267 * Setup the target thread to receive the signal:
269 DBG_MSG("Got signal %d, selecting thread %p\n", sig, thread);
270 KSE_SCHED_LOCK(curkse, thread->kseg);
271 if ((thread->state == PS_DEAD) ||
272 (thread->state == PS_DEADLOCK) ||
273 THR_IS_EXITING(thread) || THR_IS_SUSPENDED(thread)) {
274 KSE_SCHED_UNLOCK(curkse, thread->kseg);
275 _thr_ref_delete(NULL, thread);
276 } else if (SIGISMEMBER(thread->sigmask, sig)) {
277 KSE_SCHED_UNLOCK(curkse, thread->kseg);
278 _thr_ref_delete(NULL, thread);
280 kmbx = _thr_sig_add(thread, sig, info);
281 KSE_SCHED_UNLOCK(curkse, thread->kseg);
282 _thr_ref_delete(NULL, thread);
288 DBG_MSG("<<< _thr_sig_dispatch\n");
291 #endif /* ! SYSTEM_SCOPE_ONLY */
297 if (sig > 0 && sig < NSIG)
298 return (sigproptbl[_SIG_IDX(sig)]);
302 typedef void (*ohandler)(int sig, int code,
303 struct sigcontext *scp, char *addr, __sighandler_t *catcher);
306 _thr_sig_handler(int sig, siginfo_t *info, ucontext_t *ucp)
308 __siginfohandler_t *sigfunc;
309 struct pthread *curthread;
311 struct sigaction act;
312 int sa_flags, err_save, intr_save, timeout_save;
314 DBG_MSG(">>> _thr_sig_handler(%d)\n", sig);
316 curthread = _get_curthread();
317 if (curthread == NULL)
318 PANIC("No current thread.\n");
319 if (!(curthread->attr.flags & PTHREAD_SCOPE_SYSTEM))
320 PANIC("Thread is not system scope.\n");
321 if (curthread->flags & THR_FLAGS_EXITING)
323 curkse = _get_curkse();
325 * If thread is in critical region or if thread is on
326 * the way of state transition, then latch signal into buffer.
328 if (_kse_in_critical() || THR_IN_CRITICAL(curthread) ||
329 (curthread->state != PS_RUNNING && curthread->curframe == NULL)) {
330 DBG_MSG(">>> _thr_sig_handler(%d) in critical\n", sig);
331 curthread->siginfo[sig-1] = *info;
332 curthread->check_pending = 1;
333 curkse->k_sigseqno++;
334 SIGADDSET(curthread->sigpend, sig);
336 * If the kse is on the way to idle itself, but
337 * we have signal ready, we should prevent it
338 * to sleep, kernel will latch the wakeup request,
339 * so kse_release will return from kernel immediately.
341 if (KSE_IS_IDLE(curkse))
342 kse_wakeup(&curkse->k_kcb->kcb_kmbx);
346 /* It is now safe to invoke signal handler */
348 timeout_save = curthread->timeout;
349 intr_save = curthread->interrupted;
350 _kse_critical_enter();
351 /* Get a fresh copy of signal mask */
352 __sys_sigprocmask(SIG_BLOCK, NULL, &curthread->sigmask);
353 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
354 sigfunc = _thread_sigact[sig - 1].sa_sigaction;
355 sa_flags = _thread_sigact[sig - 1].sa_flags;
356 if (sa_flags & SA_RESETHAND) {
357 act.sa_handler = SIG_DFL;
358 act.sa_flags = SA_RESTART;
359 SIGEMPTYSET(act.sa_mask);
360 __sys_sigaction(sig, &act, NULL);
361 __sys_sigaction(sig, NULL, &_thread_sigact[sig - 1]);
363 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
364 _kse_critical_leave(&curthread->tcb->tcb_tmbx);
366 /* Now invoke real handler */
367 if (((__sighandler_t *)sigfunc != SIG_DFL) &&
368 ((__sighandler_t *)sigfunc != SIG_IGN) &&
369 (sigfunc != (__siginfohandler_t *)_thr_sig_handler)) {
370 if ((sa_flags & SA_SIGINFO) != 0 || info == NULL)
371 (*(sigfunc))(sig, info, ucp);
373 ((ohandler)(*sigfunc))(
374 sig, info->si_code, (struct sigcontext *)ucp,
375 info->si_addr, (__sighandler_t *)sigfunc);
378 if ((__sighandler_t *)sigfunc == SIG_DFL) {
379 if (sigprop(sig) & SA_KILL) {
380 if (_kse_isthreaded())
381 kse_thr_interrupt(NULL,
382 KSE_INTR_SIGEXIT, sig);
387 else if (sigprop(sig) & SA_STOP)
388 kse_thr_interrupt(NULL, KSE_INTR_JOBSTOP, sig);
393 curthread->timeout = timeout_save;
394 curthread->interrupted = intr_save;
395 _kse_critical_enter();
396 curthread->sigmask = ucp->uc_sigmask;
397 SIG_CANTMASK(curthread->sigmask);
398 _kse_critical_leave(&curthread->tcb->tcb_tmbx);
399 DBG_MSG("<<< _thr_sig_handler(%d)\n", sig);
402 struct sighandle_info {
403 __siginfohandler_t *sigfunc;
410 static void handle_signal(struct pthread *curthread,
411 struct sighandle_info *shi);
412 static void handle_signal_altstack(struct pthread *curthread,
413 struct sighandle_info *shi);
415 /* Must be called with signal lock and schedule lock held in order */
417 thr_sig_invoke_handler(struct pthread *curthread, int sig, siginfo_t *info,
420 __siginfohandler_t *sigfunc;
424 struct sigaction act;
426 struct sighandle_info shi;
429 * Invoke the signal handler without going through the scheduler:
431 DBG_MSG("Got signal %d, calling handler for current thread %p\n",
434 if (!_kse_in_critical())
435 PANIC("thr_sig_invoke_handler without in critical\n");
436 curkse = _get_curkse();
438 * Check that a custom handler is installed and if
439 * the signal is not blocked:
441 sigfunc = _thread_sigact[sig - 1].sa_sigaction;
442 sa_flags = _thread_sigact[sig - 1].sa_flags;
443 sigmask = curthread->sigmask;
444 SIGSETOR(curthread->sigmask, _thread_sigact[sig - 1].sa_mask);
445 if (!(sa_flags & (SA_NODEFER | SA_RESETHAND)))
446 SIGADDSET(curthread->sigmask, sig);
447 if ((sig != SIGILL) && (sa_flags & SA_RESETHAND)) {
448 act.sa_handler = SIG_DFL;
449 act.sa_flags = SA_RESTART;
450 SIGEMPTYSET(act.sa_mask);
451 __sys_sigaction(sig, &act, NULL);
452 __sys_sigaction(sig, NULL, &_thread_sigact[sig - 1]);
454 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
455 KSE_SCHED_UNLOCK(curkse, curkse->k_kseg);
457 * We are processing buffered signals, synchronize working
458 * signal mask into kernel.
460 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
461 __sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL);
462 onstack = _thr_sigonstack(&sigfunc);
463 ucp->uc_stack = curthread->sigstk;
464 ucp->uc_stack.ss_flags = (curthread->sigstk.ss_flags & SS_DISABLE)
465 ? SS_DISABLE : ((onstack) ? SS_ONSTACK : 0);
466 if (curthread->oldsigmask) {
467 ucp->uc_sigmask = *(curthread->oldsigmask);
468 curthread->oldsigmask = NULL;
470 ucp->uc_sigmask = sigmask;
471 shi.sigfunc = sigfunc;
473 shi.sa_flags = sa_flags;
476 if ((curthread->sigstk.ss_flags & SS_DISABLE) == 0) {
477 /* Deliver signal on alternative stack */
478 if (sa_flags & SA_ONSTACK && !onstack)
479 handle_signal_altstack(curthread, &shi);
481 handle_signal(curthread, &shi);
483 handle_signal(curthread, &shi);
486 _kse_critical_enter();
487 /* Don't trust after critical leave/enter */
488 curkse = _get_curkse();
491 * Restore the thread's signal mask.
493 curthread->sigmask = ucp->uc_sigmask;
494 SIG_CANTMASK(curthread->sigmask);
495 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
496 __sys_sigprocmask(SIG_SETMASK, &ucp->uc_sigmask, NULL);
497 KSE_SCHED_LOCK(curkse, curkse->k_kseg);
498 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
500 DBG_MSG("Got signal %d, handler returned %p\n", sig, curthread);
504 handle_signal(struct pthread *curthread, struct sighandle_info *shi)
506 _kse_critical_leave(&curthread->tcb->tcb_tmbx);
508 if (((__sighandler_t *)shi->sigfunc != SIG_DFL) &&
509 ((__sighandler_t *)shi->sigfunc != SIG_IGN)) {
510 if ((shi->sa_flags & SA_SIGINFO) != 0 || shi->info == NULL)
511 (*(shi->sigfunc))(shi->sig, shi->info, shi->ucp);
513 ((ohandler)(*shi->sigfunc))(
514 shi->sig, shi->info->si_code,
515 (struct sigcontext *)shi->ucp,
517 (__sighandler_t *)shi->sigfunc);
520 if ((__sighandler_t *)shi->sigfunc == SIG_DFL) {
521 if (sigprop(shi->sig) & SA_KILL) {
522 if (_kse_isthreaded())
523 kse_thr_interrupt(NULL,
524 KSE_INTR_SIGEXIT, shi->sig);
526 kill(getpid(), shi->sig);
529 else if (sigprop(shi->sig) & SA_STOP)
530 kse_thr_interrupt(NULL, KSE_INTR_JOBSTOP,
538 handle_signal_wrapper(struct pthread *curthread, ucontext_t *ret_uc,
539 struct sighandle_info *shi)
541 shi->ucp->uc_stack.ss_flags = SS_ONSTACK;
542 handle_signal(curthread, shi);
543 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
546 /* Work around for ia64, THR_SETCONTEXT does not work */
547 _kse_critical_enter();
548 curthread->tcb->tcb_tmbx.tm_context = *ret_uc;
549 _thread_switch(curthread->kse->k_kcb, curthread->tcb, 1);
555 * Jump to stack set by sigaltstack before invoking signal handler
558 handle_signal_altstack(struct pthread *curthread, struct sighandle_info *shi)
561 ucontext_t uc1, *uc2;
563 THR_ASSERT(_kse_in_critical(), "Not in critical");
566 THR_GETCONTEXT(&uc1);
570 * We are still in critical region, it is safe to operate thread
573 uc2 = &curthread->tcb->tcb_tmbx.tm_context;
574 uc2->uc_stack = curthread->sigstk;
575 makecontext(uc2, (void (*)(void))handle_signal_wrapper,
576 3, curthread, &uc1, shi);
577 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
580 _thread_switch(curthread->kse->k_kcb, curthread->tcb, 1);
581 /* THR_SETCONTEXT(uc2); */
587 _thr_getprocsig(int sig, siginfo_t *siginfo)
593 DBG_MSG(">>> _thr_getprocsig\n");
595 crit = _kse_critical_enter();
596 curkse = _get_curkse();
597 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
598 ret = _thr_getprocsig_unlocked(sig, siginfo);
599 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
600 _kse_critical_leave(crit);
602 DBG_MSG("<<< _thr_getprocsig\n");
607 _thr_getprocsig_unlocked(int sig, siginfo_t *siginfo)
612 /* try to retrieve signal from kernel */
614 SIGADDSET(sigset, sig);
617 SIGDELSET(_thr_proc_sigpending, sig);
618 if (__sys_sigtimedwait(&sigset, siginfo, &ts) > 0)
623 #ifndef SYSTEM_SCOPE_ONLY
625 * Find a thread that can handle the signal. This must be called
626 * with upcalls disabled.
629 thr_sig_find(struct kse *curkse, int sig, siginfo_t *info)
631 struct kse_mailbox *kmbx = NULL;
632 struct pthread *pthread;
633 struct pthread *suspended_thread, *signaled_thread;
634 __siginfohandler_t *sigfunc;
637 DBG_MSG("Looking for thread to handle signal %d\n", sig);
640 * Enter a loop to look for threads that have the signal
641 * unmasked. POSIX specifies that a thread in a sigwait
642 * will get the signal over any other threads. Second
643 * preference will be threads in in a sigsuspend. Third
644 * preference will be the current thread. If none of the
645 * above, then the signal is delivered to the first thread
646 * that is found. Note that if a custom handler is not
647 * installed, the signal only affects threads in sigwait.
649 suspended_thread = NULL;
650 signaled_thread = NULL;
652 KSE_LOCK_ACQUIRE(curkse, &_thread_list_lock);
653 TAILQ_FOREACH(pthread, &_thread_list, tle) {
654 if (pthread == _thr_sig_daemon)
656 /* Signal delivering to bound thread is done by kernel */
657 if (pthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
659 /* Take the scheduling lock. */
660 KSE_SCHED_LOCK(curkse, pthread->kseg);
661 if ((pthread->state == PS_DEAD) ||
662 (pthread->state == PS_DEADLOCK) ||
663 THR_IS_EXITING(pthread) ||
664 THR_IS_SUSPENDED(pthread)) {
665 ; /* Skip this thread. */
666 } else if (pthread->state == PS_SIGWAIT &&
667 SIGISMEMBER(*(pthread->data.sigwait->waitset), sig)) {
669 * retrieve signal from kernel, if it is job control
670 * signal, and sigaction is SIG_DFL, then we will
671 * be stopped in kernel, we hold lock here, but that
672 * does not matter, because that's job control, and
673 * whole process should be stopped.
675 if (_thr_getprocsig(sig, &si)) {
676 DBG_MSG("Waking thread %p in sigwait"
677 " with signal %d\n", pthread, sig);
678 /* where to put siginfo ? */
679 *(pthread->data.sigwait->siginfo) = si;
680 kmbx = _thr_setrunnable_unlocked(pthread);
682 KSE_SCHED_UNLOCK(curkse, pthread->kseg);
684 * POSIX doesn't doesn't specify which thread
685 * will get the signal if there are multiple
686 * waiters, so we give it to the first thread
689 * Do not attempt to deliver this signal
690 * to other threads and do not add the signal
691 * to the process pending set.
693 KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
697 } else if (!SIGISMEMBER(pthread->sigmask, sig)) {
698 sigfunc = _thread_sigact[sig - 1].sa_sigaction;
699 if ((__sighandler_t *)sigfunc == SIG_DFL) {
700 if (sigprop(sig) & SA_KILL) {
701 kse_thr_interrupt(NULL,
702 KSE_INTR_SIGEXIT, sig);
706 if (pthread->state == PS_SIGSUSPEND) {
707 if (suspended_thread == NULL) {
708 suspended_thread = pthread;
709 suspended_thread->refcount++;
711 } else if (signaled_thread == NULL) {
712 signaled_thread = pthread;
713 signaled_thread->refcount++;
716 KSE_SCHED_UNLOCK(curkse, pthread->kseg);
718 KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
720 if (suspended_thread != NULL) {
721 pthread = suspended_thread;
723 _thr_ref_delete(NULL, signaled_thread);
724 } else if (signaled_thread) {
725 pthread = signaled_thread;
731 #endif /* ! SYSTEM_SCOPE_ONLY */
734 build_siginfo(siginfo_t *info, int signo)
736 bzero(info, sizeof(*info));
737 info->si_signo = signo;
738 info->si_pid = _thr_pid;
742 * This is called by a thread when it has pending signals to deliver.
743 * It should only be called from the context of the thread.
746 _thr_sig_rundown(struct pthread *curthread, ucontext_t *ucp,
747 struct pthread_sigframe *psf)
749 int interrupted = curthread->interrupted;
750 int timeout = curthread->timeout;
757 DBG_MSG(">>> thr_sig_rundown (%p)\n", curthread);
758 /* Check the threads previous state: */
759 if ((psf != NULL) && (psf->psf_valid != 0)) {
761 * Do a little cleanup handling for those threads in
762 * queues before calling the signal handler. Signals
763 * for these threads are temporarily blocked until
764 * after cleanup handling.
766 switch (psf->psf_state) {
768 _cond_wait_backout(curthread);
769 psf->psf_state = PS_RUNNING;
773 _mutex_lock_backout(curthread);
774 psf->psf_state = PS_RUNNING;
781 psf->psf_state = PS_RUNNING;
784 /* XXX see comment in thr_sched_switch_unlocked */
785 curthread->critical_count--;
789 * Lower the priority before calling the handler in case
790 * it never returns (longjmps back):
792 crit = _kse_critical_enter();
793 curkse = _get_curkse();
794 KSE_SCHED_LOCK(curkse, curkse->k_kseg);
795 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
796 curthread->active_priority &= ~THR_SIGNAL_PRIORITY;
800 * For bound thread, we mask all signals and get a fresh
801 * copy of signal mask from kernel
803 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
804 __sys_sigprocmask(SIG_SETMASK, &sigmask,
805 &curthread->sigmask);
807 for (i = 1; i <= _SIG_MAXSIG; i++) {
808 if (SIGISMEMBER(curthread->sigmask, i))
810 if (SIGISMEMBER(curthread->sigpend, i)) {
811 SIGDELSET(curthread->sigpend, i);
812 siginfo = curthread->siginfo[i-1];
815 if (!(curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
816 && SIGISMEMBER(_thr_proc_sigpending, i)) {
817 if (_thr_getprocsig_unlocked(i, &siginfo))
821 if (i <= _SIG_MAXSIG)
822 thr_sig_invoke_handler(curthread, i, &siginfo, ucp);
824 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
825 __sys_sigprocmask(SIG_SETMASK,
826 &curthread->sigmask, NULL);
832 if (psf != NULL && psf->psf_valid != 0)
833 thr_sigframe_restore(curthread, psf);
834 curkse = _get_curkse();
835 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
836 KSE_SCHED_UNLOCK(curkse, curkse->k_kseg);
837 _kse_critical_leave(&curthread->tcb->tcb_tmbx);
838 /* repost masked signal to kernel, it hardly happens in real world */
839 if ((curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) &&
840 !SIGISEMPTY(curthread->sigpend)) { /* dirty read */
841 __sys_sigprocmask(SIG_SETMASK, &sigmask, &curthread->sigmask);
842 for (i = 1; i <= _SIG_MAXSIG; ++i) {
843 if (SIGISMEMBER(curthread->sigpend, i)) {
844 SIGDELSET(curthread->sigpend, i);
845 if (!_kse_isthreaded())
849 &curthread->tcb->tcb_tmbx,
854 __sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL);
856 curthread->interrupted = interrupted;
857 curthread->timeout = timeout;
859 DBG_MSG("<<< thr_sig_rundown (%p)\n", curthread);
863 * This checks pending signals for the current thread. It should be
864 * called whenever a thread changes its signal mask. Note that this
865 * is called from a thread (using its stack).
867 * XXX - We might want to just check to see if there are pending
868 * signals for the thread here, but enter the UTS scheduler
869 * to actually install the signal handler(s).
872 _thr_sig_check_pending(struct pthread *curthread)
878 if (THR_IN_CRITICAL(curthread))
886 curthread->check_pending = 0;
887 _thr_sig_rundown(curthread, &uc, NULL);
892 #ifndef SYSTEM_SCOPE_ONLY
894 * This must be called with upcalls disabled.
897 handle_special_signals(struct kse *curkse, int sig)
901 * POSIX says that pending SIGCONT signals are
902 * discarded when one of these signals occurs.
907 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
908 SIGDELSET(_thr_proc_sigpending, SIGCONT);
909 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
912 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
913 SIGDELSET(_thr_proc_sigpending, SIGTSTP);
914 SIGDELSET(_thr_proc_sigpending, SIGTTIN);
915 SIGDELSET(_thr_proc_sigpending, SIGTTOU);
916 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
921 #endif /* ! SYSTEM_SCOPE_ONLY */
924 * Perform thread specific actions in response to a signal.
925 * This function is only called if there is a handler installed
926 * for the signal, and if the target thread has the signal
929 * This must be called with the thread's scheduling lock held.
932 _thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info)
936 struct kse_mailbox *kmbx = NULL;
937 struct pthread *curthread = _get_curthread();
939 int suppress_handler = 0;
941 __sighandler_t *sigfunc;
943 DBG_MSG(">>> _thr_sig_add %p (%d)\n", pthread, sig);
945 curkse = _get_curkse();
946 restart = _thread_sigact[sig - 1].sa_flags & SA_RESTART;
947 sigfunc = _thread_sigact[sig - 1].sa_handler;
948 fromproc = (curthread == _thr_sig_daemon);
950 if (pthread->state == PS_DEAD || pthread->state == PS_DEADLOCK ||
951 pthread->state == PS_STATE_MAX)
952 return (NULL); /* return false */
954 if ((pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) &&
955 (curthread != pthread)) {
956 PANIC("Please use _thr_send_sig for bound thread");
960 if (pthread->curframe == NULL ||
961 (pthread->state != PS_SIGWAIT &&
962 SIGISMEMBER(pthread->sigmask, sig)) ||
963 THR_IN_CRITICAL(pthread)) {
964 /* thread is running or signal was being masked */
966 SIGADDSET(pthread->sigpend, sig);
968 build_siginfo(&pthread->siginfo[sig-1], sig);
969 else if (info != &pthread->siginfo[sig-1])
970 memcpy(&pthread->siginfo[sig-1], info,
973 if (!_thr_getprocsig(sig, &pthread->siginfo[sig-1]))
975 SIGADDSET(pthread->sigpend, sig);
977 if (!SIGISMEMBER(pthread->sigmask, sig)) {
978 /* A quick path to exit process */
979 if (sigfunc == SIG_DFL && sigprop(sig) & SA_KILL) {
980 kse_thr_interrupt(NULL, KSE_INTR_SIGEXIT, sig);
983 pthread->check_pending = 1;
984 if (!(pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) &&
985 (pthread->blocked != 0) &&
986 !THR_IN_CRITICAL(pthread))
987 kse_thr_interrupt(&pthread->tcb->tcb_tmbx,
988 restart ? KSE_INTR_RESTART : KSE_INTR_INTERRUPT, 0);
992 /* if process signal not exists, just return */
994 if (!_thr_getprocsig(sig, &siginfo))
999 if (pthread->state != PS_SIGWAIT && sigfunc == SIG_DFL &&
1000 (sigprop(sig) & SA_KILL)) {
1001 kse_thr_interrupt(NULL, KSE_INTR_SIGEXIT, sig);
1006 * Process according to thread state:
1008 switch (pthread->state) {
1012 return (NULL); /* XXX return false */
1016 * You can't call a signal handler for threads in these
1019 suppress_handler = 1;
1022 if ((pthread->flags & THR_FLAGS_IN_RUNQ)) {
1023 THR_RUNQ_REMOVE(pthread);
1024 pthread->active_priority |= THR_SIGNAL_PRIORITY;
1025 THR_RUNQ_INSERT_TAIL(pthread);
1027 /* Possible not in RUNQ and has curframe ? */
1028 pthread->active_priority |= THR_SIGNAL_PRIORITY;
1030 suppress_handler = 1;
1033 * States which cannot be interrupted but still require the
1034 * signal handler to run:
1042 * Unmasked signals always cause sleep to terminate
1043 * early regardless of SA_RESTART:
1045 pthread->interrupted = 1;
1052 pthread->interrupted = 1;
1057 build_siginfo(&pthread->siginfo[sig-1], sig);
1058 else if (info != &pthread->siginfo[sig-1])
1059 memcpy(&pthread->siginfo[sig-1], info,
1062 * The signal handler is not called for threads in
1065 suppress_handler = 1;
1066 /* Wake up the thread if the signal is not blocked. */
1067 if (SIGISMEMBER(*(pthread->data.sigwait->waitset), sig)) {
1068 /* Return the signal number: */
1069 *(pthread->data.sigwait->siginfo) = pthread->siginfo[sig-1];
1070 /* Make the thread runnable: */
1071 kmbx = _thr_setrunnable_unlocked(pthread);
1073 /* Increment the pending signal count. */
1074 SIGADDSET(pthread->sigpend, sig);
1075 if (!SIGISMEMBER(pthread->sigmask, sig)) {
1076 if (sigfunc == SIG_DFL &&
1077 sigprop(sig) & SA_KILL) {
1078 kse_thr_interrupt(NULL,
1083 pthread->check_pending = 1;
1084 pthread->interrupted = 1;
1085 kmbx = _thr_setrunnable_unlocked(pthread);
1091 SIGADDSET(pthread->sigpend, sig);
1093 build_siginfo(&pthread->siginfo[sig-1], sig);
1094 else if (info != &pthread->siginfo[sig-1])
1095 memcpy(&pthread->siginfo[sig-1], info, sizeof(*info));
1097 if (suppress_handler == 0) {
1099 * Setup a signal frame and save the current threads
1102 thr_sigframe_add(pthread);
1103 if (pthread->flags & THR_FLAGS_IN_RUNQ)
1104 THR_RUNQ_REMOVE(pthread);
1105 pthread->active_priority |= THR_SIGNAL_PRIORITY;
1106 kmbx = _thr_setrunnable_unlocked(pthread);
1108 pthread->check_pending = 1;
1115 * Send a signal to a specific thread (ala pthread_kill):
1118 _thr_sig_send(struct pthread *pthread, int sig)
1120 struct pthread *curthread = _get_curthread();
1121 struct kse_mailbox *kmbx;
1123 if (pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
1124 kse_thr_interrupt(&pthread->tcb->tcb_tmbx, KSE_INTR_SENDSIG, sig);
1128 /* Lock the scheduling queue of the target thread. */
1129 THR_SCHED_LOCK(curthread, pthread);
1130 if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) {
1131 kmbx = _thr_sig_add(pthread, sig, NULL);
1132 THR_SCHED_UNLOCK(curthread, pthread);
1136 * If thread sent signal to itself, check signals now.
1137 * It is not really needed, _kse_critical_leave should
1138 * have already checked signals.
1140 if (pthread == curthread && curthread->check_pending)
1141 _thr_sig_check_pending(curthread);
1143 THR_SCHED_UNLOCK(curthread, pthread);
1148 thr_sigframe_add(struct pthread *thread)
1150 if (thread->curframe == NULL)
1151 PANIC("Thread doesn't have signal frame ");
1153 if (thread->curframe->psf_valid == 0) {
1154 thread->curframe->psf_valid = 1;
1156 * Multiple signals can be added to the same signal
1157 * frame. Only save the thread's state the first time.
1159 thr_sigframe_save(thread, thread->curframe);
1164 thr_sigframe_restore(struct pthread *thread, struct pthread_sigframe *psf)
1166 if (psf->psf_valid == 0)
1167 PANIC("invalid pthread_sigframe\n");
1168 thread->flags = psf->psf_flags;
1169 thread->interrupted = psf->psf_interrupted;
1170 thread->timeout = psf->psf_timeout;
1171 thread->state = psf->psf_state;
1172 thread->data = psf->psf_wait_data;
1173 thread->wakeup_time = psf->psf_wakeup_time;
1177 thr_sigframe_save(struct pthread *thread, struct pthread_sigframe *psf)
1179 /* This has to initialize all members of the sigframe. */
1181 thread->flags & (THR_FLAGS_PRIVATE | THR_FLAGS_IN_TDLIST);
1182 psf->psf_interrupted = thread->interrupted;
1183 psf->psf_timeout = thread->timeout;
1184 psf->psf_state = thread->state;
1185 psf->psf_wait_data = thread->data;
1186 psf->psf_wakeup_time = thread->wakeup_time;
1190 _thr_signal_init(void)
1192 struct sigaction act;
1193 __siginfohandler_t *sigfunc;
1198 __sys_sigprocmask(SIG_SETMASK, &sigset, &_thr_initial->sigmask);
1199 /* Enter a loop to get the existing signal status: */
1200 for (i = 1; i <= _SIG_MAXSIG; i++) {
1201 /* Check for signals which cannot be trapped: */
1202 if (i == SIGKILL || i == SIGSTOP) {
1205 /* Get the signal handler details: */
1206 else if (__sys_sigaction(i, NULL,
1207 &_thread_sigact[i - 1]) != 0) {
1209 * Abort this process if signal
1210 * initialisation fails:
1212 PANIC("Cannot read signal handler info");
1214 /* Intall wrapper if handler was set */
1215 sigfunc = _thread_sigact[i - 1].sa_sigaction;
1216 if (((__sighandler_t *)sigfunc) != SIG_DFL &&
1217 ((__sighandler_t *)sigfunc) != SIG_IGN) {
1218 act = _thread_sigact[i - 1];
1219 act.sa_flags |= SA_SIGINFO;
1221 (__siginfohandler_t *)_thr_sig_handler;
1222 __sys_sigaction(i, &act, NULL);
1226 * Install the signal handler for SIGINFO. It isn't
1227 * really needed, but it is nice to have for debugging
1230 _thread_sigact[SIGINFO - 1].sa_flags = SA_SIGINFO | SA_RESTART;
1231 SIGEMPTYSET(act.sa_mask);
1232 act.sa_flags = SA_SIGINFO | SA_RESTART;
1233 act.sa_sigaction = (__siginfohandler_t *)&_thr_sig_handler;
1234 if (__sys_sigaction(SIGINFO, &act, NULL) != 0) {
1235 __sys_sigprocmask(SIG_SETMASK, &_thr_initial->sigmask, NULL);
1237 * Abort this process if signal initialisation fails:
1239 PANIC("Cannot initialize signal handler");
1241 __sys_sigprocmask(SIG_SETMASK, &_thr_initial->sigmask, NULL);
1242 __sys_sigaltstack(NULL, &_thr_initial->sigstk);
1246 _thr_signal_deinit(void)
1249 struct pthread *curthread = _get_curthread();
1251 /* Enter a loop to get the existing signal status: */
1252 for (i = 1; i <= _SIG_MAXSIG; i++) {
1253 /* Check for signals which cannot be trapped: */
1254 if (i == SIGKILL || i == SIGSTOP) {
1257 /* Set the signal handler details: */
1258 else if (__sys_sigaction(i, &_thread_sigact[i - 1],
1261 * Abort this process if signal
1262 * initialisation fails:
1264 PANIC("Cannot set signal handler info");
1267 __sys_sigaltstack(&curthread->sigstk, NULL);