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 ucp->uc_sigmask = sigmask;
467 shi.sigfunc = sigfunc;
469 shi.sa_flags = sa_flags;
472 if ((curthread->sigstk.ss_flags & SS_DISABLE) == 0) {
473 /* Deliver signal on alternative stack */
474 if (sa_flags & SA_ONSTACK && !onstack)
475 handle_signal_altstack(curthread, &shi);
477 handle_signal(curthread, &shi);
479 handle_signal(curthread, &shi);
482 _kse_critical_enter();
483 /* Don't trust after critical leave/enter */
484 curkse = _get_curkse();
487 * Restore the thread's signal mask.
489 curthread->sigmask = ucp->uc_sigmask;
490 SIG_CANTMASK(curthread->sigmask);
491 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
492 __sys_sigprocmask(SIG_SETMASK, &ucp->uc_sigmask, NULL);
493 KSE_SCHED_LOCK(curkse, curkse->k_kseg);
494 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
496 DBG_MSG("Got signal %d, handler returned %p\n", sig, curthread);
500 handle_signal(struct pthread *curthread, struct sighandle_info *shi)
502 _kse_critical_leave(&curthread->tcb->tcb_tmbx);
504 if (((__sighandler_t *)shi->sigfunc != SIG_DFL) &&
505 ((__sighandler_t *)shi->sigfunc != SIG_IGN)) {
506 if ((shi->sa_flags & SA_SIGINFO) != 0 || shi->info == NULL)
507 (*(shi->sigfunc))(shi->sig, shi->info, shi->ucp);
509 ((ohandler)(*shi->sigfunc))(
510 shi->sig, shi->info->si_code,
511 (struct sigcontext *)shi->ucp,
513 (__sighandler_t *)shi->sigfunc);
516 if ((__sighandler_t *)shi->sigfunc == SIG_DFL) {
517 if (sigprop(shi->sig) & SA_KILL) {
518 if (_kse_isthreaded())
519 kse_thr_interrupt(NULL,
520 KSE_INTR_SIGEXIT, shi->sig);
522 kill(getpid(), shi->sig);
525 else if (sigprop(shi->sig) & SA_STOP)
526 kse_thr_interrupt(NULL, KSE_INTR_JOBSTOP,
534 handle_signal_wrapper(struct pthread *curthread, ucontext_t *ret_uc,
535 struct sighandle_info *shi)
537 shi->ucp->uc_stack.ss_flags = SS_ONSTACK;
538 handle_signal(curthread, shi);
539 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
542 /* Work around for ia64, THR_SETCONTEXT does not work */
543 _kse_critical_enter();
544 curthread->tcb->tcb_tmbx.tm_context = *ret_uc;
545 _thread_switch(curthread->kse->k_kcb, curthread->tcb, 1);
551 * Jump to stack set by sigaltstack before invoking signal handler
554 handle_signal_altstack(struct pthread *curthread, struct sighandle_info *shi)
557 ucontext_t uc1, *uc2;
559 THR_ASSERT(_kse_in_critical(), "Not in critical");
562 THR_GETCONTEXT(&uc1);
566 * We are still in critical region, it is safe to operate thread
569 uc2 = &curthread->tcb->tcb_tmbx.tm_context;
570 uc2->uc_stack = curthread->sigstk;
571 makecontext(uc2, (void (*)(void))handle_signal_wrapper,
572 3, curthread, &uc1, shi);
573 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
576 _thread_switch(curthread->kse->k_kcb, curthread->tcb, 1);
577 /* THR_SETCONTEXT(uc2); */
583 _thr_getprocsig(int sig, siginfo_t *siginfo)
589 DBG_MSG(">>> _thr_getprocsig\n");
591 crit = _kse_critical_enter();
592 curkse = _get_curkse();
593 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
594 ret = _thr_getprocsig_unlocked(sig, siginfo);
595 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
596 _kse_critical_leave(crit);
598 DBG_MSG("<<< _thr_getprocsig\n");
603 _thr_getprocsig_unlocked(int sig, siginfo_t *siginfo)
608 /* try to retrieve signal from kernel */
610 SIGADDSET(sigset, sig);
613 SIGDELSET(_thr_proc_sigpending, sig);
614 if (__sys_sigtimedwait(&sigset, siginfo, &ts) > 0)
619 #ifndef SYSTEM_SCOPE_ONLY
621 * Find a thread that can handle the signal. This must be called
622 * with upcalls disabled.
625 thr_sig_find(struct kse *curkse, int sig, siginfo_t *info)
627 struct kse_mailbox *kmbx = NULL;
628 struct pthread *pthread;
629 struct pthread *suspended_thread, *signaled_thread;
630 __siginfohandler_t *sigfunc;
633 DBG_MSG("Looking for thread to handle signal %d\n", sig);
636 * Enter a loop to look for threads that have the signal
637 * unmasked. POSIX specifies that a thread in a sigwait
638 * will get the signal over any other threads. Second
639 * preference will be threads in in a sigsuspend. Third
640 * preference will be the current thread. If none of the
641 * above, then the signal is delivered to the first thread
642 * that is found. Note that if a custom handler is not
643 * installed, the signal only affects threads in sigwait.
645 suspended_thread = NULL;
646 signaled_thread = NULL;
648 KSE_LOCK_ACQUIRE(curkse, &_thread_list_lock);
649 TAILQ_FOREACH(pthread, &_thread_list, tle) {
650 if (pthread == _thr_sig_daemon)
652 /* Signal delivering to bound thread is done by kernel */
653 if (pthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
655 /* Take the scheduling lock. */
656 KSE_SCHED_LOCK(curkse, pthread->kseg);
657 if ((pthread->state == PS_DEAD) ||
658 (pthread->state == PS_DEADLOCK) ||
659 THR_IS_EXITING(pthread) ||
660 THR_IS_SUSPENDED(pthread)) {
661 ; /* Skip this thread. */
662 } else if (pthread->state == PS_SIGWAIT &&
663 SIGISMEMBER(*(pthread->data.sigwait->waitset), sig)) {
665 * retrieve signal from kernel, if it is job control
666 * signal, and sigaction is SIG_DFL, then we will
667 * be stopped in kernel, we hold lock here, but that
668 * does not matter, because that's job control, and
669 * whole process should be stopped.
671 if (_thr_getprocsig(sig, &si)) {
672 DBG_MSG("Waking thread %p in sigwait"
673 " with signal %d\n", pthread, sig);
674 /* where to put siginfo ? */
675 *(pthread->data.sigwait->siginfo) = si;
676 kmbx = _thr_setrunnable_unlocked(pthread);
678 KSE_SCHED_UNLOCK(curkse, pthread->kseg);
680 * POSIX doesn't doesn't specify which thread
681 * will get the signal if there are multiple
682 * waiters, so we give it to the first thread
685 * Do not attempt to deliver this signal
686 * to other threads and do not add the signal
687 * to the process pending set.
689 KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
693 } else if (!SIGISMEMBER(pthread->sigmask, sig)) {
694 sigfunc = _thread_sigact[sig - 1].sa_sigaction;
695 if ((__sighandler_t *)sigfunc == SIG_DFL) {
696 if (sigprop(sig) & SA_KILL) {
697 kse_thr_interrupt(NULL,
698 KSE_INTR_SIGEXIT, sig);
702 if (pthread->state == PS_SIGSUSPEND) {
703 if (suspended_thread == NULL) {
704 suspended_thread = pthread;
705 suspended_thread->refcount++;
707 } else if (signaled_thread == NULL) {
708 signaled_thread = pthread;
709 signaled_thread->refcount++;
712 KSE_SCHED_UNLOCK(curkse, pthread->kseg);
714 KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
716 if (suspended_thread != NULL) {
717 pthread = suspended_thread;
719 _thr_ref_delete(NULL, signaled_thread);
720 } else if (signaled_thread) {
721 pthread = signaled_thread;
727 #endif /* ! SYSTEM_SCOPE_ONLY */
730 build_siginfo(siginfo_t *info, int signo)
732 bzero(info, sizeof(*info));
733 info->si_signo = signo;
734 info->si_pid = _thr_pid;
738 * This is called by a thread when it has pending signals to deliver.
739 * It should only be called from the context of the thread.
742 _thr_sig_rundown(struct pthread *curthread, ucontext_t *ucp,
743 struct pthread_sigframe *psf)
745 int interrupted = curthread->interrupted;
746 int timeout = curthread->timeout;
753 DBG_MSG(">>> thr_sig_rundown (%p)\n", curthread);
754 /* Check the threads previous state: */
755 if ((psf != NULL) && (psf->psf_valid != 0)) {
757 * Do a little cleanup handling for those threads in
758 * queues before calling the signal handler. Signals
759 * for these threads are temporarily blocked until
760 * after cleanup handling.
762 switch (psf->psf_state) {
764 _cond_wait_backout(curthread);
765 psf->psf_state = PS_RUNNING;
769 _mutex_lock_backout(curthread);
770 psf->psf_state = PS_RUNNING;
777 psf->psf_state = PS_RUNNING;
780 /* XXX see comment in thr_sched_switch_unlocked */
781 curthread->critical_count--;
785 * Lower the priority before calling the handler in case
786 * it never returns (longjmps back):
788 crit = _kse_critical_enter();
789 curkse = _get_curkse();
790 KSE_SCHED_LOCK(curkse, curkse->k_kseg);
791 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
792 curthread->active_priority &= ~THR_SIGNAL_PRIORITY;
796 * For bound thread, we mask all signals and get a fresh
797 * copy of signal mask from kernel
799 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
800 __sys_sigprocmask(SIG_SETMASK, &sigmask,
801 &curthread->sigmask);
803 for (i = 1; i <= _SIG_MAXSIG; i++) {
804 if (SIGISMEMBER(curthread->sigmask, i))
806 if (SIGISMEMBER(curthread->sigpend, i)) {
807 SIGDELSET(curthread->sigpend, i);
808 siginfo = curthread->siginfo[i-1];
811 if (!(curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
812 && SIGISMEMBER(_thr_proc_sigpending, i)) {
813 if (_thr_getprocsig_unlocked(i, &siginfo))
817 if (i <= _SIG_MAXSIG)
818 thr_sig_invoke_handler(curthread, i, &siginfo, ucp);
820 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
821 __sys_sigprocmask(SIG_SETMASK,
822 &curthread->sigmask, NULL);
828 if (psf != NULL && psf->psf_valid != 0)
829 thr_sigframe_restore(curthread, psf);
830 curkse = _get_curkse();
831 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
832 KSE_SCHED_UNLOCK(curkse, curkse->k_kseg);
833 _kse_critical_leave(&curthread->tcb->tcb_tmbx);
834 /* repost masked signal to kernel, it hardly happens in real world */
835 if ((curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) &&
836 !SIGISEMPTY(curthread->sigpend)) { /* dirty read */
837 __sys_sigprocmask(SIG_SETMASK, &sigmask, &curthread->sigmask);
838 for (i = 1; i <= _SIG_MAXSIG; ++i) {
839 if (SIGISMEMBER(curthread->sigpend, i)) {
840 SIGDELSET(curthread->sigpend, i);
841 if (!_kse_isthreaded())
845 &curthread->tcb->tcb_tmbx,
850 __sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL);
852 curthread->interrupted = interrupted;
853 curthread->timeout = timeout;
855 DBG_MSG("<<< thr_sig_rundown (%p)\n", curthread);
859 * This checks pending signals for the current thread. It should be
860 * called whenever a thread changes its signal mask. Note that this
861 * is called from a thread (using its stack).
863 * XXX - We might want to just check to see if there are pending
864 * signals for the thread here, but enter the UTS scheduler
865 * to actually install the signal handler(s).
868 _thr_sig_check_pending(struct pthread *curthread)
874 if (THR_IN_CRITICAL(curthread))
882 curthread->check_pending = 0;
883 _thr_sig_rundown(curthread, &uc, NULL);
888 #ifndef SYSTEM_SCOPE_ONLY
890 * This must be called with upcalls disabled.
893 handle_special_signals(struct kse *curkse, int sig)
897 * POSIX says that pending SIGCONT signals are
898 * discarded when one of these signals occurs.
903 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
904 SIGDELSET(_thr_proc_sigpending, SIGCONT);
905 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
908 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
909 SIGDELSET(_thr_proc_sigpending, SIGTSTP);
910 SIGDELSET(_thr_proc_sigpending, SIGTTIN);
911 SIGDELSET(_thr_proc_sigpending, SIGTTOU);
912 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
917 #endif /* ! SYSTEM_SCOPE_ONLY */
920 * Perform thread specific actions in response to a signal.
921 * This function is only called if there is a handler installed
922 * for the signal, and if the target thread has the signal
925 * This must be called with the thread's scheduling lock held.
928 _thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info)
932 struct kse_mailbox *kmbx = NULL;
933 struct pthread *curthread = _get_curthread();
935 int suppress_handler = 0;
937 __sighandler_t *sigfunc;
939 DBG_MSG(">>> _thr_sig_add %p (%d)\n", pthread, sig);
941 curkse = _get_curkse();
942 restart = _thread_sigact[sig - 1].sa_flags & SA_RESTART;
943 sigfunc = _thread_sigact[sig - 1].sa_handler;
944 fromproc = (curthread == _thr_sig_daemon);
946 if (pthread->state == PS_DEAD || pthread->state == PS_DEADLOCK ||
947 pthread->state == PS_STATE_MAX)
948 return (NULL); /* return false */
950 if ((pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) &&
951 (curthread != pthread)) {
952 PANIC("Please use _thr_send_sig for bound thread");
956 if (pthread->curframe == NULL ||
957 (pthread->state != PS_SIGWAIT &&
958 SIGISMEMBER(pthread->sigmask, sig)) ||
959 THR_IN_CRITICAL(pthread)) {
960 /* thread is running or signal was being masked */
962 SIGADDSET(pthread->sigpend, sig);
964 build_siginfo(&pthread->siginfo[sig-1], sig);
965 else if (info != &pthread->siginfo[sig-1])
966 memcpy(&pthread->siginfo[sig-1], info,
969 if (!_thr_getprocsig(sig, &pthread->siginfo[sig-1]))
971 SIGADDSET(pthread->sigpend, sig);
973 if (!SIGISMEMBER(pthread->sigmask, sig)) {
974 /* A quick path to exit process */
975 if (sigfunc == SIG_DFL && sigprop(sig) & SA_KILL) {
976 kse_thr_interrupt(NULL, KSE_INTR_SIGEXIT, sig);
979 pthread->check_pending = 1;
980 if (!(pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) &&
981 (pthread->blocked != 0) &&
982 !THR_IN_CRITICAL(pthread))
983 kse_thr_interrupt(&pthread->tcb->tcb_tmbx,
984 restart ? KSE_INTR_RESTART : KSE_INTR_INTERRUPT, 0);
988 /* if process signal not exists, just return */
990 if (!_thr_getprocsig(sig, &siginfo))
995 if (pthread->state != PS_SIGWAIT && sigfunc == SIG_DFL &&
996 (sigprop(sig) & SA_KILL)) {
997 kse_thr_interrupt(NULL, KSE_INTR_SIGEXIT, sig);
1002 * Process according to thread state:
1004 switch (pthread->state) {
1008 return (NULL); /* XXX return false */
1012 * You can't call a signal handler for threads in these
1015 suppress_handler = 1;
1018 if ((pthread->flags & THR_FLAGS_IN_RUNQ)) {
1019 THR_RUNQ_REMOVE(pthread);
1020 pthread->active_priority |= THR_SIGNAL_PRIORITY;
1021 THR_RUNQ_INSERT_TAIL(pthread);
1023 /* Possible not in RUNQ and has curframe ? */
1024 pthread->active_priority |= THR_SIGNAL_PRIORITY;
1026 suppress_handler = 1;
1029 * States which cannot be interrupted but still require the
1030 * signal handler to run:
1038 * Unmasked signals always cause sleep to terminate
1039 * early regardless of SA_RESTART:
1041 pthread->interrupted = 1;
1048 pthread->interrupted = 1;
1053 build_siginfo(&pthread->siginfo[sig-1], sig);
1054 else if (info != &pthread->siginfo[sig-1])
1055 memcpy(&pthread->siginfo[sig-1], info,
1058 * The signal handler is not called for threads in
1061 suppress_handler = 1;
1062 /* Wake up the thread if the signal is not blocked. */
1063 if (SIGISMEMBER(*(pthread->data.sigwait->waitset), sig)) {
1064 /* Return the signal number: */
1065 *(pthread->data.sigwait->siginfo) = pthread->siginfo[sig-1];
1066 /* Make the thread runnable: */
1067 kmbx = _thr_setrunnable_unlocked(pthread);
1069 /* Increment the pending signal count. */
1070 SIGADDSET(pthread->sigpend, sig);
1071 if (!SIGISMEMBER(pthread->sigmask, sig)) {
1072 if (sigfunc == SIG_DFL &&
1073 sigprop(sig) & SA_KILL) {
1074 kse_thr_interrupt(NULL,
1079 pthread->check_pending = 1;
1080 pthread->interrupted = 1;
1081 kmbx = _thr_setrunnable_unlocked(pthread);
1087 SIGADDSET(pthread->sigpend, sig);
1089 build_siginfo(&pthread->siginfo[sig-1], sig);
1090 else if (info != &pthread->siginfo[sig-1])
1091 memcpy(&pthread->siginfo[sig-1], info, sizeof(*info));
1093 if (suppress_handler == 0) {
1095 * Setup a signal frame and save the current threads
1098 thr_sigframe_add(pthread);
1099 if (pthread->flags & THR_FLAGS_IN_RUNQ)
1100 THR_RUNQ_REMOVE(pthread);
1101 pthread->active_priority |= THR_SIGNAL_PRIORITY;
1102 kmbx = _thr_setrunnable_unlocked(pthread);
1104 pthread->check_pending = 1;
1111 * Send a signal to a specific thread (ala pthread_kill):
1114 _thr_sig_send(struct pthread *pthread, int sig)
1116 struct pthread *curthread = _get_curthread();
1117 struct kse_mailbox *kmbx;
1119 if (pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
1120 kse_thr_interrupt(&pthread->tcb->tcb_tmbx, KSE_INTR_SENDSIG, sig);
1124 /* Lock the scheduling queue of the target thread. */
1125 THR_SCHED_LOCK(curthread, pthread);
1126 if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) {
1127 kmbx = _thr_sig_add(pthread, sig, NULL);
1128 THR_SCHED_UNLOCK(curthread, pthread);
1132 * If thread sent signal to itself, check signals now.
1133 * It is not really needed, _kse_critical_leave should
1134 * have already checked signals.
1136 if (pthread == curthread && curthread->check_pending)
1137 _thr_sig_check_pending(curthread);
1139 THR_SCHED_UNLOCK(curthread, pthread);
1144 thr_sigframe_add(struct pthread *thread)
1146 if (thread->curframe == NULL)
1147 PANIC("Thread doesn't have signal frame ");
1149 if (thread->curframe->psf_valid == 0) {
1150 thread->curframe->psf_valid = 1;
1152 * Multiple signals can be added to the same signal
1153 * frame. Only save the thread's state the first time.
1155 thr_sigframe_save(thread, thread->curframe);
1160 thr_sigframe_restore(struct pthread *thread, struct pthread_sigframe *psf)
1162 if (psf->psf_valid == 0)
1163 PANIC("invalid pthread_sigframe\n");
1164 thread->flags = psf->psf_flags;
1165 thread->interrupted = psf->psf_interrupted;
1166 thread->timeout = psf->psf_timeout;
1167 thread->state = psf->psf_state;
1168 thread->data = psf->psf_wait_data;
1169 thread->wakeup_time = psf->psf_wakeup_time;
1173 thr_sigframe_save(struct pthread *thread, struct pthread_sigframe *psf)
1175 /* This has to initialize all members of the sigframe. */
1177 thread->flags & (THR_FLAGS_PRIVATE | THR_FLAGS_IN_TDLIST);
1178 psf->psf_interrupted = thread->interrupted;
1179 psf->psf_timeout = thread->timeout;
1180 psf->psf_state = thread->state;
1181 psf->psf_wait_data = thread->data;
1182 psf->psf_wakeup_time = thread->wakeup_time;
1186 _thr_signal_init(void)
1188 struct sigaction act;
1189 __siginfohandler_t *sigfunc;
1194 __sys_sigprocmask(SIG_SETMASK, &sigset, &_thr_initial->sigmask);
1195 /* Enter a loop to get the existing signal status: */
1196 for (i = 1; i <= _SIG_MAXSIG; i++) {
1197 /* Check for signals which cannot be trapped: */
1198 if (i == SIGKILL || i == SIGSTOP) {
1201 /* Get the signal handler details: */
1202 else if (__sys_sigaction(i, NULL,
1203 &_thread_sigact[i - 1]) != 0) {
1205 * Abort this process if signal
1206 * initialisation fails:
1208 PANIC("Cannot read signal handler info");
1210 /* Intall wrapper if handler was set */
1211 sigfunc = _thread_sigact[i - 1].sa_sigaction;
1212 if (((__sighandler_t *)sigfunc) != SIG_DFL &&
1213 ((__sighandler_t *)sigfunc) != SIG_IGN) {
1214 act = _thread_sigact[i - 1];
1215 act.sa_flags |= SA_SIGINFO;
1217 (__siginfohandler_t *)_thr_sig_handler;
1218 __sys_sigaction(i, &act, NULL);
1222 * Install the signal handler for SIGINFO. It isn't
1223 * really needed, but it is nice to have for debugging
1226 _thread_sigact[SIGINFO - 1].sa_flags = SA_SIGINFO | SA_RESTART;
1227 SIGEMPTYSET(act.sa_mask);
1228 act.sa_flags = SA_SIGINFO | SA_RESTART;
1229 act.sa_sigaction = (__siginfohandler_t *)&_thr_sig_handler;
1230 if (__sys_sigaction(SIGINFO, &act, NULL) != 0) {
1231 __sys_sigprocmask(SIG_SETMASK, &_thr_initial->sigmask, NULL);
1233 * Abort this process if signal initialisation fails:
1235 PANIC("Cannot initialize signal handler");
1237 __sys_sigprocmask(SIG_SETMASK, &_thr_initial->sigmask, NULL);
1238 __sys_sigaltstack(NULL, &_thr_initial->sigstk);
1242 _thr_signal_deinit(void)
1245 struct pthread *curthread = _get_curthread();
1247 /* Enter a loop to get the existing signal status: */
1248 for (i = 1; i <= _SIG_MAXSIG; i++) {
1249 /* Check for signals which cannot be trapped: */
1250 if (i == SIGKILL || i == SIGSTOP) {
1253 /* Set the signal handler details: */
1254 else if (__sys_sigaction(i, &_thread_sigact[i - 1],
1257 * Abort this process if signal
1258 * initialisation fails:
1260 PANIC("Cannot set signal handler info");
1263 __sys_sigaltstack(&curthread->sigstk, NULL);