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 inline void build_siginfo(siginfo_t *info, int signo);
47 #ifndef SYSTEM_SCOPE_ONLY
48 static struct pthread *thr_sig_find(struct kse *curkse, int sig,
51 static inline void thr_sigframe_restore(struct pthread *thread,
52 struct pthread_sigframe *psf);
53 static inline void thr_sigframe_save(struct pthread *thread,
54 struct pthread_sigframe *psf);
56 #define SA_KILL 0x01 /* terminates process by default */
60 static int sigproptbl[NSIG] = {
63 SA_KILL, /* SIGQUIT */
65 SA_KILL, /* SIGTRAP */
66 SA_KILL, /* SIGABRT */
69 SA_KILL, /* SIGKILL */
71 SA_KILL, /* SIGSEGV */
73 SA_KILL, /* SIGPIPE */
74 SA_KILL, /* SIGALRM */
75 SA_KILL, /* SIGTERM */
77 SA_STOP, /* SIGSTOP */
78 SA_STOP, /* SIGTSTP */
79 SA_CONT, /* SIGCONT */
81 SA_STOP, /* SIGTTIN */
82 SA_STOP, /* SIGTTOU */
84 SA_KILL, /* SIGXCPU */
85 SA_KILL, /* SIGXFSZ */
86 SA_KILL, /* SIGVTALRM */
87 SA_KILL, /* SIGPROF */
90 SA_KILL, /* SIGUSR1 */
94 /* #define DEBUG_SIGNAL */
96 #define DBG_MSG stdout_debug
102 * Signal setup and delivery.
104 * 1) Delivering signals to threads in the same KSE.
105 * These signals are sent by upcall events and are set in the
106 * km_sigscaught field of the KSE mailbox. Since these signals
107 * are received while operating on the KSE stack, they can be
108 * delivered either by using signalcontext() to add a stack frame
109 * to the target thread's stack, or by adding them in the thread's
110 * pending set and having the thread run them down after it
111 * 2) Delivering signals to threads in other KSEs/KSEGs.
112 * 3) Delivering signals to threads in critical regions.
113 * 4) Delivering signals to threads after they change their signal masks.
115 * Methods of delivering signals.
117 * 1) Add a signal frame to the thread's saved context.
118 * 2) Add the signal to the thread structure, mark the thread as
119 * having signals to handle, and let the thread run them down
120 * after it resumes from the KSE scheduler.
122 * Problem with 1). You can't do this to a running thread or a
123 * thread in a critical region.
125 * Problem with 2). You can't do this to a thread that doesn't
126 * yield in some way (explicitly enters the scheduler). A thread
127 * blocked in the kernel or a CPU hungry thread will not see the
128 * signal without entering the scheduler.
130 * The solution is to use both 1) and 2) to deliver signals:
132 * o Thread in critical region - use 2). When the thread
133 * leaves the critical region it will check to see if it
134 * has pending signals and run them down.
136 * o Thread enters scheduler explicitly - use 2). The thread
137 * can check for pending signals after it returns from the
140 * o Thread is running and not current thread - use 2). When the
141 * thread hits a condition specified by one of the other bullets,
142 * the signal will be delivered.
144 * o Thread is running and is current thread (e.g., the thread
145 * has just changed its signal mask and now sees that it has
146 * pending signals) - just run down the pending signals.
148 * o Thread is swapped out due to quantum expiration - use 1)
150 * o Thread is blocked in kernel - kse_thr_wakeup() and then
155 * Rules for selecting threads for signals received:
157 * 1) If the signal is a sychronous signal, it is delivered to
158 * the generating (current thread). If the thread has the
159 * signal masked, it is added to the threads pending signal
160 * set until the thread unmasks it.
162 * 2) A thread in sigwait() where the signal is in the thread's
165 * 3) A thread in sigsuspend() where the signal is not in the
166 * thread's suspended signal mask.
168 * 4) Any thread (first found/easiest to deliver) that has the
172 #ifndef SYSTEM_SCOPE_ONLY
175 sig_daemon(void *arg /* Unused */)
182 struct pthread *curthread = _get_curthread();
184 DBG_MSG("signal daemon started(%p)\n", curthread);
186 curthread->name = strdup("signal thread");
187 crit = _kse_critical_enter();
188 curkse = _get_curkse();
191 * Daemon thread is a bound thread and we must be created with
196 __sys_sigprocmask(SIG_SETMASK, &set, NULL);
198 __sys_sigpending(&set);
202 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
203 _thr_proc_sigpending = set;
204 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
205 for (i = 1; i <= _SIG_MAXSIG; i++) {
206 if (SIGISMEMBER(set, i) != 0)
207 _thr_sig_dispatch(curkse, i,
208 NULL /* no siginfo */);
212 curkse->k_kcb->kcb_kmbx.km_flags =
213 KMF_NOUPCALL | KMF_NOCOMPLETED | KMF_WAITSIGEVENT;
215 curkse->k_kcb->kcb_kmbx.km_flags = 0;
216 set = curkse->k_kcb->kcb_kmbx.km_sigscaught;
222 /* Utility function to create signal daemon thread */
224 _thr_start_sig_daemon(void)
227 sigset_t sigset, oldset;
230 pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
231 pthread_attr_init(&attr);
232 pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
233 attr->flags |= THR_SIGNAL_THREAD;
234 /* sigmask will be inherited */
235 if (pthread_create(&_thr_sig_daemon, &attr, sig_daemon, NULL))
236 PANIC("can not create signal daemon thread!\n");
237 pthread_attr_destroy(&attr);
238 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
243 * This signal handler only delivers asynchronous signals.
244 * This must be called with upcalls disabled and without
248 _thr_sig_dispatch(struct kse *curkse, int sig, siginfo_t *info)
250 struct kse_mailbox *kmbx;
251 struct pthread *thread;
253 DBG_MSG(">>> _thr_sig_dispatch(%d)\n", sig);
255 /* Check if the signal requires a dump of thread information: */
256 if (sig == SIGINFO) {
257 /* Dump thread information to file: */
261 while ((thread = thr_sig_find(curkse, sig, info)) != NULL) {
263 * Setup the target thread to receive the signal:
265 DBG_MSG("Got signal %d, selecting thread %p\n", sig, thread);
266 KSE_SCHED_LOCK(curkse, thread->kseg);
267 if ((thread->state == PS_DEAD) ||
268 (thread->state == PS_DEADLOCK) ||
269 THR_IS_EXITING(thread) || THR_IS_SUSPENDED(thread)) {
270 KSE_SCHED_UNLOCK(curkse, thread->kseg);
271 _thr_ref_delete(NULL, thread);
272 } else if (SIGISMEMBER(thread->sigmask, sig)) {
273 KSE_SCHED_UNLOCK(curkse, thread->kseg);
274 _thr_ref_delete(NULL, thread);
276 kmbx = _thr_sig_add(thread, sig, info);
277 KSE_SCHED_UNLOCK(curkse, thread->kseg);
278 _thr_ref_delete(NULL, thread);
284 DBG_MSG("<<< _thr_sig_dispatch\n");
287 #endif /* ! SYSTEM_SCOPE_ONLY */
293 if (sig > 0 && sig < NSIG)
294 return (sigproptbl[_SIG_IDX(sig)]);
298 typedef void (*ohandler)(int sig, int code,
299 struct sigcontext *scp, char *addr, __sighandler_t *catcher);
302 _thr_sig_handler(int sig, siginfo_t *info, ucontext_t *ucp)
304 struct pthread_sigframe psf;
305 __siginfohandler_t *sigfunc;
306 struct pthread *curthread;
308 struct sigaction act;
309 int sa_flags, err_save;
313 DBG_MSG(">>> _thr_sig_handler(%d)\n", sig);
315 curthread = _get_curthread();
316 if (curthread == NULL)
317 PANIC("No current thread.\n");
318 if (!(curthread->attr.flags & PTHREAD_SCOPE_SYSTEM))
319 PANIC("Thread is not system scope.\n");
320 if (curthread->flags & THR_FLAGS_EXITING) {
325 curkse = _get_curkse();
327 * If thread is in critical region or if thread is on
328 * the way of state transition, then latch signal into buffer.
330 if (_kse_in_critical() || THR_IN_CRITICAL(curthread) ||
331 curthread->state != PS_RUNNING) {
332 DBG_MSG(">>> _thr_sig_handler(%d) in critical\n", sig);
333 curthread->siginfo[sig-1] = *info;
334 curthread->check_pending = 1;
335 curkse->k_sigseqno++;
336 SIGADDSET(curthread->sigpend, sig);
338 * If the kse is on the way to idle itself, but
339 * we have signal ready, we should prevent it
340 * to sleep, kernel will latch the wakeup request,
341 * so kse_release will return from kernel immediately.
343 if (KSE_IS_IDLE(curkse))
344 kse_wakeup(&curkse->k_kcb->kcb_kmbx);
349 /* Check if the signal requires a dump of thread information: */
350 if (sig == SIGINFO) {
351 /* Dump thread information to file: */
355 /* Check the threads previous state: */
356 curthread->critical_count++;
357 if (curthread->sigbackout != NULL)
358 curthread->sigbackout((void *)curthread);
359 curthread->critical_count--;
360 thr_sigframe_save(curthread, &psf);
361 THR_ASSERT(!(curthread->sigbackout), "sigbackout was not cleared.");
363 _kse_critical_enter();
364 /* Get a fresh copy of signal mask */
365 __sys_sigprocmask(SIG_BLOCK, NULL, &curthread->sigmask);
366 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
367 sigfunc = _thread_sigact[sig - 1].sa_sigaction;
368 sa_flags = _thread_sigact[sig - 1].sa_flags;
369 if (sa_flags & SA_RESETHAND) {
370 act.sa_handler = SIG_DFL;
371 act.sa_flags = SA_RESTART;
372 SIGEMPTYSET(act.sa_mask);
373 __sys_sigaction(sig, &act, NULL);
374 __sys_sigaction(sig, NULL, &_thread_sigact[sig - 1]);
376 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
377 _kse_critical_leave(&curthread->tcb->tcb_tmbx);
379 /* Now invoke real handler */
380 if (((__sighandler_t *)sigfunc != SIG_DFL) &&
381 ((__sighandler_t *)sigfunc != SIG_IGN) &&
382 (sigfunc != (__siginfohandler_t *)_thr_sig_handler)) {
383 if ((sa_flags & SA_SIGINFO) != 0 || info == NULL)
384 (*(sigfunc))(sig, info, ucp);
386 ((ohandler)(*sigfunc))(
387 sig, info->si_code, (struct sigcontext *)ucp,
388 info->si_addr, (__sighandler_t *)sigfunc);
391 if ((__sighandler_t *)sigfunc == SIG_DFL) {
392 if (sigprop(sig) & SA_KILL) {
393 if (_kse_isthreaded())
394 kse_thr_interrupt(NULL,
395 KSE_INTR_SIGEXIT, sig);
400 else if (sigprop(sig) & SA_STOP)
401 kse_thr_interrupt(NULL, KSE_INTR_JOBSTOP, sig);
405 _kse_critical_enter();
406 curthread->sigmask = ucp->uc_sigmask;
407 SIG_CANTMASK(curthread->sigmask);
408 _kse_critical_leave(&curthread->tcb->tcb_tmbx);
410 thr_sigframe_restore(curthread, &psf);
412 DBG_MSG("<<< _thr_sig_handler(%d)\n", sig);
417 struct sighandle_info {
418 __siginfohandler_t *sigfunc;
425 static void handle_signal(struct pthread *curthread,
426 struct sighandle_info *shi);
427 static void handle_signal_altstack(struct pthread *curthread,
428 struct sighandle_info *shi);
430 /* Must be called with signal lock and schedule lock held in order */
432 thr_sig_invoke_handler(struct pthread *curthread, int sig, siginfo_t *info,
435 __siginfohandler_t *sigfunc;
439 struct sigaction act;
441 struct sighandle_info shi;
444 * Invoke the signal handler without going through the scheduler:
446 DBG_MSG("Got signal %d, calling handler for current thread %p\n",
449 if (!_kse_in_critical())
450 PANIC("thr_sig_invoke_handler without in critical\n");
451 curkse = curthread->kse;
453 * Check that a custom handler is installed and if
454 * the signal is not blocked:
456 sigfunc = _thread_sigact[sig - 1].sa_sigaction;
457 sa_flags = _thread_sigact[sig - 1].sa_flags;
458 sigmask = curthread->sigmask;
459 SIGSETOR(curthread->sigmask, _thread_sigact[sig - 1].sa_mask);
460 if (!(sa_flags & (SA_NODEFER | SA_RESETHAND)))
461 SIGADDSET(curthread->sigmask, sig);
462 if ((sig != SIGILL) && (sa_flags & SA_RESETHAND)) {
463 act.sa_handler = SIG_DFL;
464 act.sa_flags = SA_RESTART;
465 SIGEMPTYSET(act.sa_mask);
466 __sys_sigaction(sig, &act, NULL);
467 __sys_sigaction(sig, NULL, &_thread_sigact[sig - 1]);
469 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
470 KSE_SCHED_UNLOCK(curkse, curkse->k_kseg);
472 * We are processing buffered signals, synchronize working
473 * signal mask into kernel.
475 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
476 __sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL);
477 onstack = _thr_sigonstack(&sigfunc);
478 ucp->uc_stack = curthread->sigstk;
479 ucp->uc_stack.ss_flags = (curthread->sigstk.ss_flags & SS_DISABLE)
480 ? SS_DISABLE : ((onstack) ? SS_ONSTACK : 0);
481 if (curthread->oldsigmask) {
482 ucp->uc_sigmask = *(curthread->oldsigmask);
483 curthread->oldsigmask = NULL;
485 ucp->uc_sigmask = sigmask;
486 shi.sigfunc = sigfunc;
488 shi.sa_flags = sa_flags;
491 if ((curthread->sigstk.ss_flags & SS_DISABLE) == 0) {
492 /* Deliver signal on alternative stack */
493 if (sa_flags & SA_ONSTACK && !onstack)
494 handle_signal_altstack(curthread, &shi);
496 handle_signal(curthread, &shi);
498 handle_signal(curthread, &shi);
501 _kse_critical_enter();
502 /* Don't trust after critical leave/enter */
503 curkse = curthread->kse;
506 * Restore the thread's signal mask.
508 curthread->sigmask = ucp->uc_sigmask;
509 SIG_CANTMASK(curthread->sigmask);
510 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
511 __sys_sigprocmask(SIG_SETMASK, &ucp->uc_sigmask, NULL);
512 KSE_SCHED_LOCK(curkse, curkse->k_kseg);
513 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
515 DBG_MSG("Got signal %d, handler returned %p\n", sig, curthread);
519 handle_signal(struct pthread *curthread, struct sighandle_info *shi)
521 _kse_critical_leave(&curthread->tcb->tcb_tmbx);
523 /* Check if the signal requires a dump of thread information: */
524 if (shi->sig == SIGINFO) {
525 /* Dump thread information to file: */
529 if (((__sighandler_t *)shi->sigfunc != SIG_DFL) &&
530 ((__sighandler_t *)shi->sigfunc != SIG_IGN)) {
531 if ((shi->sa_flags & SA_SIGINFO) != 0 || shi->info == NULL)
532 (*(shi->sigfunc))(shi->sig, shi->info, shi->ucp);
534 ((ohandler)(*shi->sigfunc))(
535 shi->sig, shi->info->si_code,
536 (struct sigcontext *)shi->ucp,
538 (__sighandler_t *)shi->sigfunc);
541 if ((__sighandler_t *)shi->sigfunc == SIG_DFL) {
542 if (sigprop(shi->sig) & SA_KILL) {
543 if (_kse_isthreaded())
544 kse_thr_interrupt(NULL,
545 KSE_INTR_SIGEXIT, shi->sig);
547 kill(getpid(), shi->sig);
550 else if (sigprop(shi->sig) & SA_STOP)
551 kse_thr_interrupt(NULL, KSE_INTR_JOBSTOP,
559 handle_signal_wrapper(struct pthread *curthread, ucontext_t *ret_uc,
560 struct sighandle_info *shi)
562 shi->ucp->uc_stack.ss_flags = SS_ONSTACK;
563 handle_signal(curthread, shi);
564 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
567 /* Work around for ia64, THR_SETCONTEXT does not work */
568 _kse_critical_enter();
569 curthread->tcb->tcb_tmbx.tm_context = *ret_uc;
570 _thread_switch(curthread->kse->k_kcb, curthread->tcb, 1);
576 * Jump to stack set by sigaltstack before invoking signal handler
579 handle_signal_altstack(struct pthread *curthread, struct sighandle_info *shi)
582 ucontext_t uc1, *uc2;
584 THR_ASSERT(_kse_in_critical(), "Not in critical");
587 THR_GETCONTEXT(&uc1);
591 * We are still in critical region, it is safe to operate thread
594 uc2 = &curthread->tcb->tcb_tmbx.tm_context;
595 uc2->uc_stack = curthread->sigstk;
596 makecontext(uc2, (void (*)(void))handle_signal_wrapper,
597 3, curthread, &uc1, shi);
598 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
601 _thread_switch(curthread->kse->k_kcb, curthread->tcb, 1);
602 /* THR_SETCONTEXT(uc2); */
608 _thr_getprocsig(int sig, siginfo_t *siginfo)
614 DBG_MSG(">>> _thr_getprocsig\n");
616 crit = _kse_critical_enter();
617 curkse = _get_curkse();
618 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
619 ret = _thr_getprocsig_unlocked(sig, siginfo);
620 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
621 _kse_critical_leave(crit);
623 DBG_MSG("<<< _thr_getprocsig\n");
628 _thr_getprocsig_unlocked(int sig, siginfo_t *siginfo)
633 /* try to retrieve signal from kernel */
635 SIGADDSET(sigset, sig);
638 SIGDELSET(_thr_proc_sigpending, sig);
639 if (__sys_sigtimedwait(&sigset, siginfo, &ts) > 0)
644 #ifndef SYSTEM_SCOPE_ONLY
646 * Find a thread that can handle the signal. This must be called
647 * with upcalls disabled.
650 thr_sig_find(struct kse *curkse, int sig, siginfo_t *info)
652 struct kse_mailbox *kmbx = NULL;
653 struct pthread *pthread;
654 struct pthread *suspended_thread, *signaled_thread;
655 __siginfohandler_t *sigfunc;
658 DBG_MSG("Looking for thread to handle signal %d\n", sig);
661 * Enter a loop to look for threads that have the signal
662 * unmasked. POSIX specifies that a thread in a sigwait
663 * will get the signal over any other threads. Second
664 * preference will be threads in in a sigsuspend. Third
665 * preference will be the current thread. If none of the
666 * above, then the signal is delivered to the first thread
667 * that is found. Note that if a custom handler is not
668 * installed, the signal only affects threads in sigwait.
670 suspended_thread = NULL;
671 signaled_thread = NULL;
673 KSE_LOCK_ACQUIRE(curkse, &_thread_list_lock);
674 TAILQ_FOREACH(pthread, &_thread_list, tle) {
675 if (pthread == _thr_sig_daemon)
677 /* Signal delivering to bound thread is done by kernel */
678 if (pthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
680 /* Take the scheduling lock. */
681 KSE_SCHED_LOCK(curkse, pthread->kseg);
682 if ((pthread->state == PS_DEAD) ||
683 (pthread->state == PS_DEADLOCK) ||
684 THR_IS_EXITING(pthread) ||
685 THR_IS_SUSPENDED(pthread)) {
686 ; /* Skip this thread. */
687 } else if (pthread->state == PS_SIGWAIT &&
688 SIGISMEMBER(*(pthread->data.sigwait->waitset), sig)) {
690 * retrieve signal from kernel, if it is job control
691 * signal, and sigaction is SIG_DFL, then we will
692 * be stopped in kernel, we hold lock here, but that
693 * does not matter, because that's job control, and
694 * whole process should be stopped.
696 if (_thr_getprocsig(sig, &si)) {
697 DBG_MSG("Waking thread %p in sigwait"
698 " with signal %d\n", pthread, sig);
699 /* where to put siginfo ? */
700 *(pthread->data.sigwait->siginfo) = si;
701 kmbx = _thr_setrunnable_unlocked(pthread);
703 KSE_SCHED_UNLOCK(curkse, pthread->kseg);
705 * POSIX doesn't doesn't specify which thread
706 * will get the signal if there are multiple
707 * waiters, so we give it to the first thread
710 * Do not attempt to deliver this signal
711 * to other threads and do not add the signal
712 * to the process pending set.
714 KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
717 if (suspended_thread != NULL)
718 _thr_ref_delete(NULL, suspended_thread);
719 if (signaled_thread != NULL)
720 _thr_ref_delete(NULL, signaled_thread);
722 } else if (!SIGISMEMBER(pthread->sigmask, sig)) {
724 * If debugger is running, we don't quick exit,
725 * and give it a chance to check the signal.
727 if (_libkse_debug == 0) {
728 sigfunc = _thread_sigact[sig - 1].sa_sigaction;
729 if ((__sighandler_t *)sigfunc == SIG_DFL) {
730 if (sigprop(sig) & SA_KILL) {
731 kse_thr_interrupt(NULL,
732 KSE_INTR_SIGEXIT, sig);
737 if (pthread->state == PS_SIGSUSPEND) {
738 if (suspended_thread == NULL) {
739 suspended_thread = pthread;
740 suspended_thread->refcount++;
742 } else if (signaled_thread == NULL) {
743 signaled_thread = pthread;
744 signaled_thread->refcount++;
747 KSE_SCHED_UNLOCK(curkse, pthread->kseg);
749 KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
751 if (suspended_thread != NULL) {
752 pthread = suspended_thread;
754 _thr_ref_delete(NULL, signaled_thread);
755 } else if (signaled_thread) {
756 pthread = signaled_thread;
762 #endif /* ! SYSTEM_SCOPE_ONLY */
765 build_siginfo(siginfo_t *info, int signo)
767 bzero(info, sizeof(*info));
768 info->si_signo = signo;
769 info->si_pid = _thr_pid;
773 * This is called by a thread when it has pending signals to deliver.
774 * It should only be called from the context of the thread.
777 _thr_sig_rundown(struct pthread *curthread, ucontext_t *ucp)
779 struct pthread_sigframe psf;
788 DBG_MSG(">>> thr_sig_rundown (%p)\n", curthread);
790 /* Check the threads previous state: */
791 curthread->critical_count++;
792 if (curthread->sigbackout != NULL)
793 curthread->sigbackout((void *)curthread);
794 curthread->critical_count--;
796 THR_ASSERT(!(curthread->sigbackout), "sigbackout was not cleared.");
797 THR_ASSERT((curthread->state == PS_RUNNING), "state is not PS_RUNNING");
799 thr_sigframe_save(curthread, &psf);
801 * Lower the priority before calling the handler in case
802 * it never returns (longjmps back):
804 crit = _kse_critical_enter();
805 curkse = curthread->kse;
806 KSE_SCHED_LOCK(curkse, curkse->k_kseg);
807 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
808 curthread->active_priority &= ~THR_SIGNAL_PRIORITY;
812 * For bound thread, we mask all signals and get a fresh
813 * copy of signal mask from kernel
815 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
816 __sys_sigprocmask(SIG_SETMASK, &sigmask,
817 &curthread->sigmask);
819 for (i = 1; i <= _SIG_MAXSIG; i++) {
820 if (SIGISMEMBER(curthread->sigmask, i))
822 if (SIGISMEMBER(curthread->sigpend, i)) {
823 SIGDELSET(curthread->sigpend, i);
824 siginfo = curthread->siginfo[i-1];
827 if (!(curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
828 && SIGISMEMBER(_thr_proc_sigpending, i)) {
829 if (_thr_getprocsig_unlocked(i, &siginfo))
833 if (i <= _SIG_MAXSIG)
834 thr_sig_invoke_handler(curthread, i, &siginfo, ucp);
836 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
837 __sys_sigprocmask(SIG_SETMASK,
838 &curthread->sigmask, NULL);
844 /* Don't trust after signal handling */
845 curkse = curthread->kse;
846 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
847 KSE_SCHED_UNLOCK(curkse, curkse->k_kseg);
848 _kse_critical_leave(&curthread->tcb->tcb_tmbx);
849 /* repost masked signal to kernel, it hardly happens in real world */
850 if ((curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) &&
851 !SIGISEMPTY(curthread->sigpend)) { /* dirty read */
852 __sys_sigprocmask(SIG_SETMASK, &sigmask, &curthread->sigmask);
853 for (i = 1; i <= _SIG_MAXSIG; ++i) {
854 if (SIGISMEMBER(curthread->sigpend, i)) {
855 SIGDELSET(curthread->sigpend, i);
856 if (!_kse_isthreaded())
860 &curthread->tcb->tcb_tmbx,
865 __sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL);
867 DBG_MSG("<<< thr_sig_rundown (%p)\n", curthread);
869 thr_sigframe_restore(curthread, &psf);
874 * This checks pending signals for the current thread. It should be
875 * called whenever a thread changes its signal mask. Note that this
876 * is called from a thread (using its stack).
878 * XXX - We might want to just check to see if there are pending
879 * signals for the thread here, but enter the UTS scheduler
880 * to actually install the signal handler(s).
883 _thr_sig_check_pending(struct pthread *curthread)
890 * If the thread is in critical region, delay processing signals.
891 * If the thread state is not PS_RUNNING, it might be switching
892 * into UTS and but a THR_LOCK_RELEASE saw check_pending, and it
893 * goes here, in the case we delay processing signals, lets UTS
894 * process complicated things, normally UTS will call _thr_sig_add
895 * to resume the thread, so we needn't repeat doing it here.
897 if (THR_IN_CRITICAL(curthread) || curthread->state != PS_RUNNING)
905 curthread->check_pending = 0;
906 _thr_sig_rundown(curthread, &uc);
912 * Perform thread specific actions in response to a signal.
913 * This function is only called if there is a handler installed
914 * for the signal, and if the target thread has the signal
917 * This must be called with the thread's scheduling lock held.
920 _thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info)
924 struct kse_mailbox *kmbx = NULL;
925 struct pthread *curthread = _get_curthread();
927 int suppress_handler = 0;
929 __sighandler_t *sigfunc;
931 DBG_MSG(">>> _thr_sig_add %p (%d)\n", pthread, sig);
933 curkse = _get_curkse();
934 restart = _thread_sigact[sig - 1].sa_flags & SA_RESTART;
935 sigfunc = _thread_sigact[sig - 1].sa_handler;
936 fromproc = (curthread == _thr_sig_daemon);
938 if (pthread->state == PS_DEAD || pthread->state == PS_DEADLOCK ||
939 pthread->state == PS_STATE_MAX)
940 return (NULL); /* return false */
942 if ((pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) &&
943 (curthread != pthread)) {
944 PANIC("Please use _thr_send_sig for bound thread");
948 if (pthread->state != PS_SIGWAIT &&
949 SIGISMEMBER(pthread->sigmask, sig)) {
950 /* signal is masked, just add signal to thread. */
952 SIGADDSET(pthread->sigpend, sig);
954 build_siginfo(&pthread->siginfo[sig-1], sig);
955 else if (info != &pthread->siginfo[sig-1])
956 memcpy(&pthread->siginfo[sig-1], info,
959 if (!_thr_getprocsig(sig, &pthread->siginfo[sig-1]))
961 SIGADDSET(pthread->sigpend, sig);
965 /* if process signal not exists, just return */
967 if (!_thr_getprocsig(sig, &siginfo))
972 if (pthread->state != PS_SIGWAIT && sigfunc == SIG_DFL &&
973 (sigprop(sig) & SA_KILL)) {
974 kse_thr_interrupt(NULL, KSE_INTR_SIGEXIT, sig);
979 * Process according to thread state:
981 switch (pthread->state) {
985 return (NULL); /* XXX return false */
989 * You can't call a signal handler for threads in these
992 suppress_handler = 1;
995 if ((pthread->flags & THR_FLAGS_IN_RUNQ)) {
996 THR_RUNQ_REMOVE(pthread);
997 pthread->active_priority |= THR_SIGNAL_PRIORITY;
998 THR_RUNQ_INSERT_TAIL(pthread);
1000 /* Possible not in RUNQ and has curframe ? */
1001 pthread->active_priority |= THR_SIGNAL_PRIORITY;
1005 * States which cannot be interrupted but still require the
1006 * signal handler to run:
1014 * Unmasked signals always cause sleep to terminate
1015 * early regardless of SA_RESTART:
1017 pthread->interrupted = 1;
1024 pthread->interrupted = 1;
1029 build_siginfo(&pthread->siginfo[sig-1], sig);
1030 else if (info != &pthread->siginfo[sig-1])
1031 memcpy(&pthread->siginfo[sig-1], info,
1034 * The signal handler is not called for threads in
1037 suppress_handler = 1;
1038 /* Wake up the thread if the signal is not blocked. */
1039 if (SIGISMEMBER(*(pthread->data.sigwait->waitset), sig)) {
1040 /* Return the signal number: */
1041 *(pthread->data.sigwait->siginfo) = pthread->siginfo[sig-1];
1042 /* Make the thread runnable: */
1043 kmbx = _thr_setrunnable_unlocked(pthread);
1045 /* Increment the pending signal count. */
1046 SIGADDSET(pthread->sigpend, sig);
1047 if (!SIGISMEMBER(pthread->sigmask, sig)) {
1048 if (sigfunc == SIG_DFL &&
1049 sigprop(sig) & SA_KILL) {
1050 kse_thr_interrupt(NULL,
1055 pthread->check_pending = 1;
1056 pthread->interrupted = 1;
1057 kmbx = _thr_setrunnable_unlocked(pthread);
1063 SIGADDSET(pthread->sigpend, sig);
1065 build_siginfo(&pthread->siginfo[sig-1], sig);
1066 else if (info != &pthread->siginfo[sig-1])
1067 memcpy(&pthread->siginfo[sig-1], info, sizeof(*info));
1068 pthread->check_pending = 1;
1069 if (!(pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) &&
1070 (pthread->blocked != 0) && !THR_IN_CRITICAL(pthread))
1071 kse_thr_interrupt(&pthread->tcb->tcb_tmbx,
1072 restart ? KSE_INTR_RESTART : KSE_INTR_INTERRUPT, 0);
1073 if (suppress_handler == 0) {
1075 * Setup a signal frame and save the current threads
1078 if (pthread->state != PS_RUNNING) {
1079 if (pthread->flags & THR_FLAGS_IN_RUNQ)
1080 THR_RUNQ_REMOVE(pthread);
1081 pthread->active_priority |= THR_SIGNAL_PRIORITY;
1082 kmbx = _thr_setrunnable_unlocked(pthread);
1090 * Send a signal to a specific thread (ala pthread_kill):
1093 _thr_sig_send(struct pthread *pthread, int sig)
1095 struct pthread *curthread = _get_curthread();
1096 struct kse_mailbox *kmbx;
1098 if (pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
1099 kse_thr_interrupt(&pthread->tcb->tcb_tmbx, KSE_INTR_SENDSIG, sig);
1103 /* Lock the scheduling queue of the target thread. */
1104 THR_SCHED_LOCK(curthread, pthread);
1105 if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) {
1106 kmbx = _thr_sig_add(pthread, sig, NULL);
1107 /* Add a preemption point. */
1108 if (kmbx == NULL && (curthread->kseg == pthread->kseg) &&
1109 (pthread->active_priority > curthread->active_priority))
1110 curthread->critical_yield = 1;
1111 THR_SCHED_UNLOCK(curthread, pthread);
1115 * If thread sent signal to itself, check signals now.
1116 * It is not really needed, _kse_critical_leave should
1117 * have already checked signals.
1119 if (pthread == curthread && curthread->check_pending)
1120 _thr_sig_check_pending(curthread);
1123 THR_SCHED_UNLOCK(curthread, pthread);
1128 thr_sigframe_restore(struct pthread *curthread, struct pthread_sigframe *psf)
1130 kse_critical_t crit;
1133 THR_THREAD_LOCK(curthread, curthread);
1134 curthread->cancelflags = psf->psf_cancelflags;
1135 crit = _kse_critical_enter();
1136 curkse = curthread->kse;
1137 KSE_SCHED_LOCK(curkse, curthread->kseg);
1138 curthread->flags = psf->psf_flags;
1139 curthread->interrupted = psf->psf_interrupted;
1140 curthread->timeout = psf->psf_timeout;
1141 curthread->data = psf->psf_wait_data;
1142 curthread->wakeup_time = psf->psf_wakeup_time;
1143 curthread->continuation = psf->psf_continuation;
1144 KSE_SCHED_UNLOCK(curkse, curthread->kseg);
1145 _kse_critical_leave(crit);
1146 THR_THREAD_UNLOCK(curthread, curthread);
1150 thr_sigframe_save(struct pthread *curthread, struct pthread_sigframe *psf)
1152 kse_critical_t crit;
1155 THR_THREAD_LOCK(curthread, curthread);
1156 psf->psf_cancelflags = curthread->cancelflags;
1157 crit = _kse_critical_enter();
1158 curkse = curthread->kse;
1159 KSE_SCHED_LOCK(curkse, curthread->kseg);
1160 /* This has to initialize all members of the sigframe. */
1161 psf->psf_flags = (curthread->flags & (THR_FLAGS_PRIVATE | THR_FLAGS_EXITING));
1162 psf->psf_interrupted = curthread->interrupted;
1163 psf->psf_timeout = curthread->timeout;
1164 psf->psf_wait_data = curthread->data;
1165 psf->psf_wakeup_time = curthread->wakeup_time;
1166 psf->psf_continuation = curthread->continuation;
1167 KSE_SCHED_UNLOCK(curkse, curthread->kseg);
1168 _kse_critical_leave(crit);
1169 THR_THREAD_UNLOCK(curthread, curthread);
1173 _thr_signal_init(void)
1175 struct sigaction act;
1176 __siginfohandler_t *sigfunc;
1181 __sys_sigprocmask(SIG_SETMASK, &sigset, &_thr_initial->sigmask);
1182 /* Enter a loop to get the existing signal status: */
1183 for (i = 1; i <= _SIG_MAXSIG; i++) {
1184 /* Get the signal handler details: */
1185 if (__sys_sigaction(i, NULL, &_thread_sigact[i - 1]) != 0) {
1187 * Abort this process if signal
1188 * initialisation fails:
1190 PANIC("Cannot read signal handler info");
1192 /* Intall wrapper if handler was set */
1193 sigfunc = _thread_sigact[i - 1].sa_sigaction;
1194 if (((__sighandler_t *)sigfunc) != SIG_DFL &&
1195 ((__sighandler_t *)sigfunc) != SIG_IGN) {
1196 act = _thread_sigact[i - 1];
1197 act.sa_flags |= SA_SIGINFO;
1199 (__siginfohandler_t *)_thr_sig_handler;
1200 __sys_sigaction(i, &act, NULL);
1204 * Install the signal handler for SIGINFO. It isn't
1205 * really needed, but it is nice to have for debugging
1208 _thread_sigact[SIGINFO - 1].sa_flags = SA_SIGINFO | SA_RESTART;
1209 SIGEMPTYSET(act.sa_mask);
1210 act.sa_flags = SA_SIGINFO | SA_RESTART;
1211 act.sa_sigaction = (__siginfohandler_t *)&_thr_sig_handler;
1212 if (__sys_sigaction(SIGINFO, &act, NULL) != 0) {
1213 __sys_sigprocmask(SIG_SETMASK, &_thr_initial->sigmask, NULL);
1215 * Abort this process if signal initialisation fails:
1217 PANIC("Cannot initialize signal handler");
1219 __sys_sigprocmask(SIG_SETMASK, &_thr_initial->sigmask, NULL);
1220 __sys_sigaltstack(NULL, &_thr_initial->sigstk);
1224 _thr_signal_deinit(void)
1227 struct pthread *curthread = _get_curthread();
1229 /* Clear process pending signals. */
1230 sigemptyset(&_thr_proc_sigpending);
1232 /* Enter a loop to get the existing signal status: */
1233 for (i = 1; i <= _SIG_MAXSIG; i++) {
1234 /* Check for signals which cannot be trapped: */
1235 if (i == SIGKILL || i == SIGSTOP) {
1238 /* Set the signal handler details: */
1239 else if (__sys_sigaction(i, &_thread_sigact[i - 1],
1242 * Abort this process if signal
1243 * initialisation fails:
1245 PANIC("Cannot set signal handler info");
1248 __sys_sigaltstack(&curthread->sigstk, NULL);