thr_sig.c revision 114664
1/*
2 * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by John Birrell.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $FreeBSD: head/lib/libkse/thread/thr_sig.c 114664 2003-05-04 16:17:01Z deischen $
33 */
34#include <sys/param.h>
35#include <sys/types.h>
36#include <sys/signalvar.h>
37#include <signal.h>
38#include <errno.h>
39#include <fcntl.h>
40#include <unistd.h>
41#include <string.h>
42#include <pthread.h>
43#include "thr_private.h"
44#include "pthread_md.h"
45
46/* Prototypes: */
47static void	build_siginfo(siginfo_t *info, int signo);
48static void	thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info);
49static void	thr_sig_check_state(struct pthread *pthread, int sig);
50static struct pthread *thr_sig_find(struct kse *curkse, int sig,
51		    siginfo_t *info);
52static void	handle_special_signals(struct kse *curkse, int sig);
53static void	thr_sigframe_add(struct pthread *thread, int sig,
54		    siginfo_t *info);
55static void	thr_sigframe_restore(struct pthread *thread,
56		    struct pthread_sigframe *psf);
57static void	thr_sigframe_save(struct pthread *thread,
58		    struct pthread_sigframe *psf);
59static void	thr_sig_invoke_handler(struct pthread *, int sig,
60		    siginfo_t *info, ucontext_t *ucp);
61
62/* #define DEBUG_SIGNAL */
63#ifdef DEBUG_SIGNAL
64#define DBG_MSG		stdout_debug
65#else
66#define DBG_MSG(x...)
67#endif
68
69/*
70 * Signal setup and delivery.
71 *
72 * 1) Delivering signals to threads in the same KSE.
73 *    These signals are sent by upcall events and are set in the
74 *    km_sigscaught field of the KSE mailbox.  Since these signals
75 *    are received while operating on the KSE stack, they can be
76 *    delivered either by using signalcontext() to add a stack frame
77 *    to the target thread's stack, or by adding them in the thread's
78 *    pending set and having the thread run them down after it
79 * 2) Delivering signals to threads in other KSEs/KSEGs.
80 * 3) Delivering signals to threads in critical regions.
81 * 4) Delivering signals to threads after they change their signal masks.
82 *
83 * Methods of delivering signals.
84 *
85 *   1) Add a signal frame to the thread's saved context.
86 *   2) Add the signal to the thread structure, mark the thread as
87 *  	having signals to handle, and let the thread run them down
88 *  	after it resumes from the KSE scheduler.
89 *
90 * Problem with 1).  You can't do this to a running thread or a
91 * thread in a critical region.
92 *
93 * Problem with 2).  You can't do this to a thread that doesn't
94 * yield in some way (explicitly enters the scheduler).  A thread
95 * blocked in the kernel or a CPU hungry thread will not see the
96 * signal without entering the scheduler.
97 *
98 * The solution is to use both 1) and 2) to deliver signals:
99 *
100 *   o Thread in critical region - use 2).  When the thread
101 *     leaves the critical region it will check to see if it
102 *     has pending signals and run them down.
103 *
104 *   o Thread enters scheduler explicitly - use 2).  The thread
105 *     can check for pending signals after it returns from the
106 *     the scheduler.
107 *
108 *   o Thread is running and not current thread - use 2).  When the
109 *     thread hits a condition specified by one of the other bullets,
110 *     the signal will be delivered.
111 *
112 *   o Thread is running and is current thread (e.g., the thread
113 *     has just changed its signal mask and now sees that it has
114 *     pending signals) - just run down the pending signals.
115 *
116 *   o Thread is swapped out due to quantum expiration - use 1)
117 *
118 *   o Thread is blocked in kernel - kse_thr_wakeup() and then
119 *     use 1)
120 */
121
122/*
123 * Rules for selecting threads for signals received:
124 *
125 *   1) If the signal is a sychronous signal, it is delivered to
126 *      the generating (current thread).  If the thread has the
127 *      signal masked, it is added to the threads pending signal
128 *      set until the thread unmasks it.
129 *
130 *   2) A thread in sigwait() where the signal is in the thread's
131 *      waitset.
132 *
133 *   3) A thread in sigsuspend() where the signal is not in the
134 *      thread's suspended signal mask.
135 *
136 *   4) Any thread (first found/easiest to deliver) that has the
137 *      signal unmasked.
138 */
139
140/*
141 * This signal handler only delivers asynchronous signals.
142 * This must be called with upcalls disabled and without
143 * holding any locks.
144 */
145void
146_thr_sig_dispatch(struct kse *curkse, int sig, siginfo_t *info)
147{
148	struct pthread *thread;
149
150	DBG_MSG(">>> _thr_sig_dispatch(%d)\n", sig);
151
152	/* Some signals need special handling: */
153	handle_special_signals(curkse, sig);
154
155	if ((thread = thr_sig_find(curkse, sig, info)) != NULL) {
156		/*
157		 * Setup the target thread to receive the signal:
158		 */
159		DBG_MSG("Got signal %d, selecting thread %p\n", sig, thread);
160		KSE_SCHED_LOCK(curkse, thread->kseg);
161		thr_sig_add(thread, sig, info);
162		KSE_SCHED_UNLOCK(curkse, thread->kseg);
163	}
164}
165
166void
167_thr_sig_handler(int sig, siginfo_t *info, ucontext_t *ucp)
168{
169	void (*sigfunc)(int, siginfo_t *, void *);
170	struct kse *curkse;
171
172	curkse = _get_curkse();
173	if ((curkse == NULL) || ((curkse->k_flags & KF_STARTED) == 0)) {
174		/* Upcalls are not yet started; just call the handler. */
175		sigfunc = _thread_sigact[sig - 1].sa_sigaction;
176		ucp->uc_sigmask = _thr_proc_sigmask;
177		if (((__sighandler_t *)sigfunc != SIG_DFL) &&
178		    ((__sighandler_t *)sigfunc != SIG_IGN)) {
179			if (((_thread_sigact[sig - 1].sa_flags & SA_SIGINFO)
180			    != 0) || (info == NULL))
181				(*(sigfunc))(sig, info, ucp);
182			else
183				(*(sigfunc))(sig, (siginfo_t *)info->si_code,
184				    ucp);
185		}
186	}
187	else {
188		/* Nothing. */
189		DBG_MSG("Got signal %d\n", sig);
190		sigaddset(&curkse->k_mbx.km_sigscaught, sig);
191		ucp->uc_sigmask = _thr_proc_sigmask;
192	}
193}
194
195static void
196thr_sig_invoke_handler(struct pthread *curthread, int sig, siginfo_t *info,
197    ucontext_t *ucp)
198{
199	void (*sigfunc)(int, siginfo_t *, void *);
200	sigset_t saved_mask;
201	int saved_seqno;
202
203	/* Invoke the signal handler without going through the scheduler:
204	 */
205	DBG_MSG("Got signal %d, calling handler for current thread %p\n",
206	    sig, curthread);
207
208	/*
209	 * Setup the threads signal mask.
210	 *
211	 * The mask is changed in the thread's active signal mask
212	 * (in the context) and not in the base signal mask because
213	 * a thread is allowed to change its signal mask within a
214	 * signal handler.  If it does, the signal mask restored
215	 * after the handler should be the same as that set by the
216	 * thread during the handler, not the original mask from
217	 * before calling the handler.  The thread could also
218	 * modify the signal mask in the context and expect this
219	 * mask to be used.
220	 */
221	THR_SCHED_LOCK(curthread, curthread);
222	saved_mask = curthread->tmbx.tm_context.uc_sigmask;
223	saved_seqno = curthread->sigmask_seqno;
224	SIGSETOR(curthread->tmbx.tm_context.uc_sigmask,
225	    _thread_sigact[sig - 1].sa_mask);
226	sigaddset(&curthread->tmbx.tm_context.uc_sigmask, sig);
227	THR_SCHED_UNLOCK(curthread, curthread);
228
229	/*
230	 * Check that a custom handler is installed and if
231	 * the signal is not blocked:
232	 */
233	sigfunc = _thread_sigact[sig - 1].sa_sigaction;
234	ucp->uc_sigmask = _thr_proc_sigmask;
235	if (((__sighandler_t *)sigfunc != SIG_DFL) &&
236	    ((__sighandler_t *)sigfunc != SIG_IGN)) {
237		if (((_thread_sigact[sig - 1].sa_flags & SA_SIGINFO) != 0) ||
238		    (info == NULL))
239			(*(sigfunc))(sig, info, ucp);
240		else
241			(*(sigfunc))(sig, (siginfo_t *)info->si_code, ucp);
242	}
243
244	/*
245	 * Restore the thread's signal mask.
246	 */
247	if (saved_seqno == curthread->sigmask_seqno)
248		curthread->tmbx.tm_context.uc_sigmask = saved_mask;
249	else
250		curthread->tmbx.tm_context.uc_sigmask = curthread->sigmask;
251}
252
253/*
254 * Find a thread that can handle the signal.  This must be called
255 * with upcalls disabled.
256 */
257struct pthread *
258thr_sig_find(struct kse *curkse, int sig, siginfo_t *info)
259{
260	int		handler_installed;
261	struct pthread	*pthread;
262	struct pthread	*suspended_thread, *signaled_thread;
263
264	DBG_MSG("Looking for thread to handle signal %d\n", sig);
265
266	handler_installed = (_thread_sigact[sig - 1].sa_handler != SIG_IGN) &&
267	    (_thread_sigact[sig - 1].sa_handler != SIG_DFL);
268
269	/* Check if the signal requires a dump of thread information: */
270	if (sig == SIGINFO) {
271		/* Dump thread information to file: */
272		_thread_dump_info();
273	}
274	/*
275	 * Enter a loop to look for threads that have the signal
276	 * unmasked.  POSIX specifies that a thread in a sigwait
277	 * will get the signal over any other threads.  Second
278	 * preference will be threads in in a sigsuspend.  Third
279	 * preference will be the current thread.  If none of the
280	 * above, then the signal is delivered to the first thread
281	 * that is found.  Note that if a custom handler is not
282	 * installed, the signal only affects threads in sigwait.
283	 */
284	suspended_thread = NULL;
285	signaled_thread = NULL;
286
287	KSE_LOCK_ACQUIRE(curkse, &_thread_list_lock);
288	TAILQ_FOREACH(pthread, &_thread_list, tle) {
289		/* Take the scheduling lock. */
290		KSE_SCHED_LOCK(curkse, pthread->kseg);
291		if ((pthread->state == PS_SIGWAIT) &&
292		    sigismember(pthread->data.sigwait, sig)) {
293			/*
294			 * Return the signal number and make the
295			 * thread runnable.
296			 */
297			pthread->signo = sig;
298			_thr_setrunnable_unlocked(pthread);
299
300			KSE_SCHED_UNLOCK(curkse, pthread->kseg);
301
302			/*
303			 * POSIX doesn't doesn't specify which thread
304			 * will get the signal if there are multiple
305			 * waiters, so we give it to the first thread
306			 * we find.
307			 *
308			 * Do not attempt to deliver this signal
309			 * to other threads and do not add the signal
310			 * to the process pending set.
311			 */
312			KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
313			DBG_MSG("Waking thread %p in sigwait with signal %d\n",
314			    pthread, sig);
315			return (NULL);
316		}
317		else if ((pthread->state == PS_DEAD) ||
318		    (pthread->state == PS_DEADLOCK) ||
319		    THR_IS_EXITING(pthread) || THR_IS_SUSPENDED(pthread))
320			;	/* Skip this thread. */
321		else if ((handler_installed != 0) &&
322		    !sigismember(&pthread->tmbx.tm_context.uc_sigmask, sig)) {
323			if (pthread->state == PS_SIGSUSPEND) {
324				if (suspended_thread == NULL)
325					suspended_thread = pthread;
326			} else if (signaled_thread == NULL)
327				signaled_thread = pthread;
328		}
329		KSE_SCHED_UNLOCK(curkse, pthread->kseg);
330	}
331	KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
332
333	/*
334	 * Only perform wakeups and signal delivery if there is a
335	 * custom handler installed:
336	 */
337	if (handler_installed == 0) {
338		/*
339		 * There is no handler installed; nothing to do here.
340		 */
341	} else if (suspended_thread == NULL &&
342	    signaled_thread == NULL) {
343		/*
344		 * Add it to the set of signals pending
345		 * on the process:
346		 */
347		KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
348		if (!sigismember(&_thr_proc_sigpending, sig)) {
349			sigaddset(&_thr_proc_sigpending, sig);
350			if (info == NULL)
351				build_siginfo(&_thr_proc_siginfo[sig], sig);
352			else
353				memcpy(&_thr_proc_siginfo[sig], info,
354				    sizeof(*info));
355		}
356		KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
357	} else {
358		/*
359		 * We only deliver the signal to one thread;
360		 * give preference to the suspended thread:
361		 */
362		if (suspended_thread != NULL)
363			pthread = suspended_thread;
364		else
365			pthread = signaled_thread;
366		return (pthread);
367	}
368	return (NULL);
369}
370
371static void
372build_siginfo(siginfo_t *info, int signo)
373{
374	bzero(info, sizeof(*info));
375	info->si_signo = signo;
376	info->si_pid = _thr_pid;
377}
378
379/*
380 * This is called by a thread when it has pending signals to deliver.
381 * It should only be called from the context of the thread.
382 */
383void
384_thr_sig_rundown(struct pthread *curthread, ucontext_t *ucp,
385    struct pthread_sigframe *psf)
386{
387	struct pthread_sigframe psf_save;
388	sigset_t sigset;
389	int i;
390
391	THR_SCHED_LOCK(curthread, curthread);
392	memcpy(&sigset, &curthread->sigpend, sizeof(sigset));
393	sigemptyset(&curthread->sigpend);
394	if (psf != NULL) {
395		memcpy(&psf_save, psf, sizeof(*psf));
396		SIGSETOR(sigset, psf_save.psf_sigset);
397		sigemptyset(&psf->psf_sigset);
398	}
399	THR_SCHED_UNLOCK(curthread, curthread);
400
401	/* Check the threads previous state: */
402	if ((psf != NULL) && (psf_save.psf_state != PS_RUNNING)) {
403		/*
404		 * Do a little cleanup handling for those threads in
405		 * queues before calling the signal handler.  Signals
406		 * for these threads are temporarily blocked until
407		 * after cleanup handling.
408		 */
409		switch (psf_save.psf_state) {
410		case PS_COND_WAIT:
411			_cond_wait_backout(curthread);
412			psf_save.psf_state = PS_RUNNING;
413			break;
414
415		case PS_MUTEX_WAIT:
416			_mutex_lock_backout(curthread);
417			psf_save.psf_state = PS_RUNNING;
418			break;
419
420		default:
421			break;
422		}
423	}
424	/*
425	 * Lower the priority before calling the handler in case
426	 * it never returns (longjmps back):
427	 */
428	curthread->active_priority &= ~THR_SIGNAL_PRIORITY;
429
430	for (i = 1; i < NSIG; i++) {
431		if (sigismember(&sigset, i) != 0) {
432			/* Call the handler: */
433			thr_sig_invoke_handler(curthread, i,
434			    &curthread->siginfo[i], ucp);
435		}
436	}
437
438	THR_SCHED_LOCK(curthread, curthread);
439	if (psf != NULL)
440		thr_sigframe_restore(curthread, &psf_save);
441	/* Restore the signal mask. */
442	curthread->tmbx.tm_context.uc_sigmask = curthread->sigmask;
443	THR_SCHED_UNLOCK(curthread, curthread);
444	_thr_sig_check_pending(curthread);
445}
446
447/*
448 * This checks pending signals for the current thread.  It should be
449 * called whenever a thread changes its signal mask.  Note that this
450 * is called from a thread (using its stack).
451 *
452 * XXX - We might want to just check to see if there are pending
453 *       signals for the thread here, but enter the UTS scheduler
454 *       to actually install the signal handler(s).
455 */
456void
457_thr_sig_check_pending(struct pthread *curthread)
458{
459	sigset_t sigset;
460	sigset_t pending_process;
461	sigset_t pending_thread;
462	kse_critical_t crit;
463	int i;
464
465	curthread->check_pending = 0;
466
467	/*
468	 * Check if there are pending signals for the running
469	 * thread or process that aren't blocked:
470	 */
471	crit = _kse_critical_enter();
472	KSE_LOCK_ACQUIRE(curthread->kse, &_thread_signal_lock);
473	sigset = _thr_proc_sigpending;
474	KSE_LOCK_RELEASE(curthread->kse, &_thread_signal_lock);
475	_kse_critical_leave(crit);
476
477	THR_SCHED_LOCK(curthread, curthread);
478	SIGSETOR(sigset, curthread->sigpend);
479	SIGSETNAND(sigset, curthread->tmbx.tm_context.uc_sigmask);
480	if (SIGNOTEMPTY(sigset)) {
481		ucontext_t uc;
482		volatile int once;
483
484		curthread->check_pending = 0;
485		THR_SCHED_UNLOCK(curthread, curthread);
486
487		/*
488		 * Split the pending signals into those that were
489		 * pending on the process and those that were pending
490		 * on the thread.
491		 */
492		sigfillset(&pending_process);
493		sigfillset(&pending_thread);
494		for (i = 1; i < NSIG; i++) {
495			if (sigismember(&sigset, i) != 0) {
496				if (sigismember(&curthread->sigpend, i) != 0) {
497					build_siginfo(&curthread->siginfo[i], i);
498					sigdelset(&pending_thread, i);
499				} else {
500					memcpy(&curthread->siginfo[i],
501					    &_thr_proc_siginfo[i],
502					    sizeof(siginfo_t));
503					sigdelset(&pending_process, i);
504				}
505			}
506		}
507		/*
508		 * Remove any process pending signals that were scheduled
509		 * to be delivered from process' pending set.
510		 */
511		crit = _kse_critical_enter();
512		KSE_LOCK_ACQUIRE(curthread->kse, &_thread_signal_lock);
513		SIGSETAND(_thr_proc_sigpending, pending_process);
514		KSE_LOCK_RELEASE(curthread->kse, &_thread_signal_lock);
515		_kse_critical_leave(crit);
516
517		/*
518		 * Remove any thread pending signals that were scheduled
519		 * to be delivered from thread's pending set.
520		 */
521		THR_SCHED_LOCK(curthread, curthread);
522		SIGSETAND(curthread->sigpend, pending_thread);
523		THR_SCHED_UNLOCK(curthread, curthread);
524
525		once = 0;
526		THR_GETCONTEXT(&uc);
527		if (once == 0) {
528			once = 1;
529			for (i = 1; i < NSIG; i++) {
530				if (sigismember(&sigset, i) != 0) {
531					/* Call the handler: */
532					thr_sig_invoke_handler(curthread, i,
533					    &curthread->siginfo[i], &uc);
534				}
535			}
536		}
537	}
538	else
539		THR_SCHED_UNLOCK(curthread, curthread);
540}
541
542/*
543 * This must be called with upcalls disabled.
544 */
545static void
546handle_special_signals(struct kse *curkse, int sig)
547{
548	switch (sig) {
549	/*
550	 * POSIX says that pending SIGCONT signals are
551	 * discarded when one of these signals occurs.
552	 */
553	case SIGTSTP:
554	case SIGTTIN:
555	case SIGTTOU:
556		KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
557		sigdelset(&_thr_proc_sigpending, SIGCONT);
558		KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
559		break;
560
561	default:
562		break;
563	}
564}
565
566/*
567 * Perform thread specific actions in response to a signal.
568 * This function is only called if there is a handler installed
569 * for the signal, and if the target thread has the signal
570 * unmasked.
571 *
572 * This must be called with the thread's scheduling lock held.
573 */
574static void
575thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info)
576{
577	int	restart;
578	int	suppress_handler = 0;
579
580	restart = _thread_sigact[sig - 1].sa_flags & SA_RESTART;
581
582	/* Make sure this signal isn't still in the pending set: */
583	sigdelset(&pthread->sigpend, sig);
584
585	/*
586	 * Process according to thread state:
587	 */
588	switch (pthread->state) {
589	/*
590	 * States which do not change when a signal is trapped:
591	 */
592	case PS_DEAD:
593	case PS_DEADLOCK:
594	case PS_LOCKWAIT:
595	case PS_SUSPENDED:
596	case PS_STATE_MAX:
597		/*
598		 * You can't call a signal handler for threads in these
599		 * states.
600		 */
601		suppress_handler = 1;
602		break;
603
604	/*
605	 * States which do not need any cleanup handling when signals
606	 * occur:
607	 */
608	case PS_RUNNING:
609		/*
610		 * Remove the thread from the queue before changing its
611		 * priority:
612		 */
613		if ((pthread->flags & THR_FLAGS_IN_RUNQ) != 0)
614			THR_RUNQ_REMOVE(pthread);
615		else {
616			/*
617			 * This thread is active; add the signal to the
618			 * pending set and mark it as having pending
619			 * signals.
620			 */
621			suppress_handler = 1;
622			sigaddset(&pthread->sigpend, sig);
623			build_siginfo(&pthread->siginfo[sig], sig);
624			pthread->check_pending = 1;
625			if ((pthread->blocked != 0) &&
626			    !THR_IN_CRITICAL(pthread))
627				kse_thr_interrupt(&pthread->tmbx /* XXX - restart?!?! */);
628		}
629		break;
630
631	/*
632	 * States which cannot be interrupted but still require the
633	 * signal handler to run:
634	 */
635	case PS_COND_WAIT:
636	case PS_MUTEX_WAIT:
637		/*
638		 * Remove the thread from the wait queue.  It will
639		 * be added back to the wait queue once all signal
640		 * handlers have been invoked.
641		 */
642		KSE_WAITQ_REMOVE(pthread->kse, pthread);
643		break;
644
645	case PS_SLEEP_WAIT:
646		/*
647		 * Unmasked signals always cause sleep to terminate early,
648		 * regardless of SA_RESTART:
649		 */
650		pthread->interrupted = 1;
651		KSE_WAITQ_REMOVE(pthread->kse, pthread);
652		THR_SET_STATE(pthread, PS_RUNNING);
653		break;
654
655	case PS_JOIN:
656	case PS_SIGSUSPEND:
657		KSE_WAITQ_REMOVE(pthread->kse, pthread);
658		THR_SET_STATE(pthread, PS_RUNNING);
659		break;
660
661	case PS_SIGWAIT:
662		/* The signal handler is not called for threads in SIGWAIT. */
663		suppress_handler = 1;
664		/* Wake up the thread if the signal is blocked. */
665		if (sigismember(pthread->data.sigwait, sig)) {
666			/* Return the signal number: */
667			pthread->signo = sig;
668
669			/* Make the thread runnable: */
670			_thr_setrunnable_unlocked(pthread);
671		} else
672			/* Increment the pending signal count. */
673			sigaddset(&pthread->sigpend, sig);
674		break;
675	}
676
677	if (suppress_handler == 0) {
678		if (pthread->curframe == NULL) {
679			/*
680			 * This thread is active.  Just add it to the
681			 * thread's pending set.
682			 */
683			sigaddset(&pthread->sigpend, sig);
684			pthread->check_pending = 1;
685			if (info == NULL)
686				build_siginfo(&pthread->siginfo[sig], sig);
687			else
688				memcpy(&pthread->siginfo[sig], info,
689				    sizeof(*info));
690		} else {
691			/*
692			 * Setup a signal frame and save the current threads
693			 * state:
694			 */
695			thr_sigframe_add(pthread, sig, info);
696		}
697
698		if (pthread->state != PS_RUNNING)
699			THR_SET_STATE(pthread, PS_RUNNING);
700
701		/*
702		 * The thread should be removed from all scheduling
703		 * queues at this point.  Raise the priority and
704		 * place the thread in the run queue.  It is also
705		 * possible for a signal to be sent to a suspended
706		 * thread, mostly via pthread_kill().  If a thread
707		 * is suspended, don't insert it into the priority
708		 * queue; just set its state to suspended and it
709		 * will run the signal handler when it is resumed.
710		 */
711		pthread->active_priority |= THR_SIGNAL_PRIORITY;
712		if ((pthread->flags & THR_FLAGS_IN_RUNQ) == 0)
713			THR_RUNQ_INSERT_TAIL(pthread);
714	}
715}
716
717static void
718thr_sig_check_state(struct pthread *pthread, int sig)
719{
720	/*
721	 * Process according to thread state:
722	 */
723	switch (pthread->state) {
724	/*
725	 * States which do not change when a signal is trapped:
726	 */
727	case PS_RUNNING:
728	case PS_LOCKWAIT:
729	case PS_MUTEX_WAIT:
730	case PS_COND_WAIT:
731	case PS_JOIN:
732	case PS_SUSPENDED:
733	case PS_DEAD:
734	case PS_DEADLOCK:
735	case PS_STATE_MAX:
736		break;
737
738	case PS_SIGWAIT:
739		/* Wake up the thread if the signal is blocked. */
740		if (sigismember(pthread->data.sigwait, sig)) {
741			/* Return the signal number: */
742			pthread->signo = sig;
743
744			/* Change the state of the thread to run: */
745			_thr_setrunnable_unlocked(pthread);
746		} else
747			/* Increment the pending signal count. */
748			sigaddset(&pthread->sigpend, sig);
749		break;
750
751	case PS_SIGSUSPEND:
752	case PS_SLEEP_WAIT:
753		/*
754		 * Remove the thread from the wait queue and make it
755		 * runnable:
756		 */
757		_thr_setrunnable_unlocked(pthread);
758
759		/* Flag the operation as interrupted: */
760		pthread->interrupted = 1;
761		break;
762	}
763}
764
765/*
766 * Send a signal to a specific thread (ala pthread_kill):
767 */
768void
769_thr_sig_send(struct pthread *pthread, int sig)
770{
771	struct pthread *curthread = _get_curthread();
772
773	/* Lock the scheduling queue of the target thread. */
774	THR_SCHED_LOCK(curthread, pthread);
775
776	/* Check for signals whose actions are SIG_DFL: */
777	if (_thread_sigact[sig - 1].sa_handler == SIG_DFL) {
778		/*
779		 * Check to see if a temporary signal handler is
780		 * installed for sigwaiters:
781		 */
782		if (_thread_dfl_count[sig] == 0) {
783			/*
784			 * Deliver the signal to the process if a handler
785			 * is not installed:
786			 */
787			THR_SCHED_UNLOCK(curthread, pthread);
788			kill(getpid(), sig);
789			THR_SCHED_LOCK(curthread, pthread);
790		}
791		/*
792		 * Assuming we're still running after the above kill(),
793		 * make any necessary state changes to the thread:
794		 */
795		thr_sig_check_state(pthread, sig);
796		THR_SCHED_UNLOCK(curthread, pthread);
797	}
798	/*
799	 * Check that the signal is not being ignored:
800	 */
801	else if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) {
802		if (pthread->state == PS_SIGWAIT &&
803		    sigismember(pthread->data.sigwait, sig)) {
804			/* Return the signal number: */
805			pthread->signo = sig;
806
807			/* Change the state of the thread to run: */
808			_thr_setrunnable_unlocked(pthread);
809			THR_SCHED_UNLOCK(curthread, pthread);
810		} else if (sigismember(&pthread->tmbx.tm_context.uc_sigmask, sig)) {
811			/* Add the signal to the pending set: */
812			sigaddset(&pthread->sigpend, sig);
813			THR_SCHED_UNLOCK(curthread, pthread);
814		} else if (pthread == curthread) {
815			ucontext_t uc;
816			siginfo_t info;
817			volatile int once;
818
819			THR_SCHED_UNLOCK(curthread, pthread);
820			build_siginfo(&info, sig);
821			once = 0;
822			THR_GETCONTEXT(&uc);
823			if (once == 0) {
824				once = 1;
825				/*
826				 * Call the signal handler for the current
827				 * thread:
828				 */
829				thr_sig_invoke_handler(curthread, sig,
830				    &info, &uc);
831			}
832		} else {
833			/*
834			 * Perform any state changes due to signal
835			 * arrival:
836			 */
837			thr_sig_add(pthread, sig, NULL);
838			THR_SCHED_UNLOCK(curthread, pthread);
839		}
840	}
841}
842
843static void
844thr_sigframe_add(struct pthread *thread, int sig, siginfo_t *info)
845{
846	if (thread->curframe == NULL)
847		PANIC("Thread doesn't have signal frame ");
848
849	if (thread->check_pending == 0) {
850		/*
851		 * Multiple signals can be added to the same signal
852		 * frame.  Only save the thread's state the first time.
853		 */
854		thr_sigframe_save(thread, thread->curframe);
855		thread->check_pending = 1;
856		thread->flags &= THR_FLAGS_PRIVATE;
857	}
858	sigaddset(&thread->curframe->psf_sigset, sig);
859	if (info != NULL)
860		memcpy(&thread->siginfo[sig], info, sizeof(*info));
861	else
862		build_siginfo(&thread->siginfo[sig], sig);
863
864	/* Setup the new signal mask. */
865	SIGSETOR(thread->tmbx.tm_context.uc_sigmask,
866	    _thread_sigact[sig - 1].sa_mask);
867	sigaddset(&thread->tmbx.tm_context.uc_sigmask, sig);
868}
869
870void
871thr_sigframe_restore(struct pthread *thread, struct pthread_sigframe *psf)
872{
873	thread->flags = psf->psf_flags;
874	thread->interrupted = psf->psf_interrupted;
875	thread->signo = psf->psf_signo;
876	thread->state = psf->psf_state;
877	thread->data = psf->psf_wait_data;
878	thread->wakeup_time = psf->psf_wakeup_time;
879	if (thread->sigmask_seqno == psf->psf_seqno)
880		thread->tmbx.tm_context.uc_sigmask = psf->psf_sigmask;
881	else
882		thread->tmbx.tm_context.uc_sigmask = thread->sigmask;
883}
884
885static void
886thr_sigframe_save(struct pthread *thread, struct pthread_sigframe *psf)
887{
888	/* This has to initialize all members of the sigframe. */
889	psf->psf_flags = thread->flags & THR_FLAGS_PRIVATE;
890	psf->psf_interrupted = thread->interrupted;
891	psf->psf_signo = thread->signo;
892	psf->psf_state = thread->state;
893	psf->psf_wait_data = thread->data;
894	psf->psf_wakeup_time = thread->wakeup_time;
895	psf->psf_sigmask = thread->tmbx.tm_context.uc_sigmask;
896	psf->psf_seqno = thread->sigmask_seqno;
897	sigemptyset(&psf->psf_sigset);
898}
899