thr_sig.c revision 117366
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 117366 2003-07-09 22:30:55Z davidxu $
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_check_state(struct pthread *pthread, int sig);
49static struct pthread *thr_sig_find(struct kse *curkse, int sig,
50		    siginfo_t *info);
51static void	handle_special_signals(struct kse *curkse, int sig);
52static void	thr_sigframe_add(struct pthread *thread);
53static void	thr_sigframe_restore(struct pthread *thread,
54		    struct pthread_sigframe *psf);
55static void	thr_sigframe_save(struct pthread *thread,
56		    struct pthread_sigframe *psf);
57
58/* #define DEBUG_SIGNAL */
59#ifdef DEBUG_SIGNAL
60#define DBG_MSG		stdout_debug
61#else
62#define DBG_MSG(x...)
63#endif
64
65/*
66 * Signal setup and delivery.
67 *
68 * 1) Delivering signals to threads in the same KSE.
69 *    These signals are sent by upcall events and are set in the
70 *    km_sigscaught field of the KSE mailbox.  Since these signals
71 *    are received while operating on the KSE stack, they can be
72 *    delivered either by using signalcontext() to add a stack frame
73 *    to the target thread's stack, or by adding them in the thread's
74 *    pending set and having the thread run them down after it
75 * 2) Delivering signals to threads in other KSEs/KSEGs.
76 * 3) Delivering signals to threads in critical regions.
77 * 4) Delivering signals to threads after they change their signal masks.
78 *
79 * Methods of delivering signals.
80 *
81 *   1) Add a signal frame to the thread's saved context.
82 *   2) Add the signal to the thread structure, mark the thread as
83 *  	having signals to handle, and let the thread run them down
84 *  	after it resumes from the KSE scheduler.
85 *
86 * Problem with 1).  You can't do this to a running thread or a
87 * thread in a critical region.
88 *
89 * Problem with 2).  You can't do this to a thread that doesn't
90 * yield in some way (explicitly enters the scheduler).  A thread
91 * blocked in the kernel or a CPU hungry thread will not see the
92 * signal without entering the scheduler.
93 *
94 * The solution is to use both 1) and 2) to deliver signals:
95 *
96 *   o Thread in critical region - use 2).  When the thread
97 *     leaves the critical region it will check to see if it
98 *     has pending signals and run them down.
99 *
100 *   o Thread enters scheduler explicitly - use 2).  The thread
101 *     can check for pending signals after it returns from the
102 *     the scheduler.
103 *
104 *   o Thread is running and not current thread - use 2).  When the
105 *     thread hits a condition specified by one of the other bullets,
106 *     the signal will be delivered.
107 *
108 *   o Thread is running and is current thread (e.g., the thread
109 *     has just changed its signal mask and now sees that it has
110 *     pending signals) - just run down the pending signals.
111 *
112 *   o Thread is swapped out due to quantum expiration - use 1)
113 *
114 *   o Thread is blocked in kernel - kse_thr_wakeup() and then
115 *     use 1)
116 */
117
118/*
119 * Rules for selecting threads for signals received:
120 *
121 *   1) If the signal is a sychronous signal, it is delivered to
122 *      the generating (current thread).  If the thread has the
123 *      signal masked, it is added to the threads pending signal
124 *      set until the thread unmasks it.
125 *
126 *   2) A thread in sigwait() where the signal is in the thread's
127 *      waitset.
128 *
129 *   3) A thread in sigsuspend() where the signal is not in the
130 *      thread's suspended signal mask.
131 *
132 *   4) Any thread (first found/easiest to deliver) that has the
133 *      signal unmasked.
134 */
135
136static void *
137sig_daemon(void *arg /* Unused */)
138{
139	int i;
140	kse_critical_t crit;
141	struct timespec ts;
142	sigset_t set;
143	struct kse *curkse;
144	struct pthread *curthread = _get_curthread();
145
146	DBG_MSG("signal daemon started\n");
147
148	curthread->name = strdup("signal thread");
149	crit = _kse_critical_enter();
150	curkse = _get_curkse();
151	SIGFILLSET(set);
152	__sys_sigprocmask(SIG_SETMASK, &set, NULL);
153	__sys_sigpending(&set);
154	ts.tv_sec = 0;
155	ts.tv_nsec = 0;
156	while (1) {
157		KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
158		_thr_proc_sigpending = set;
159		KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
160		for (i = 1; i <= _SIG_MAXSIG; i++) {
161			if (SIGISMEMBER(set, i) != 0)
162				_thr_sig_dispatch(curkse, i,
163				    NULL /* no siginfo */);
164		}
165		ts.tv_sec = 30;
166		ts.tv_nsec = 0;
167		curkse->k_mbx.km_flags =
168		    KMF_NOUPCALL | KMF_NOCOMPLETED | KMF_WAITSIGEVENT;
169		kse_release(&ts);
170		curkse->k_mbx.km_flags = 0;
171		set = curkse->k_mbx.km_sigscaught;
172	}
173	return (0);
174}
175
176/* Utility function to create signal daemon thread */
177int
178_thr_start_sig_daemon(void)
179{
180	pthread_attr_t attr;
181	sigset_t sigset, oldset;
182
183	SIGFILLSET(sigset);
184	pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
185	pthread_attr_init(&attr);
186	pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
187	/* sigmask will be inherited */
188	if (pthread_create(&_thr_sig_daemon, &attr, sig_daemon, NULL))
189		PANIC("can not create signal daemon thread!\n");
190	pthread_attr_destroy(&attr);
191	pthread_sigmask(SIG_SETMASK, &oldset, NULL);
192	return (0);
193}
194
195/*
196 * This signal handler only delivers asynchronous signals.
197 * This must be called with upcalls disabled and without
198 * holding any locks.
199 */
200void
201_thr_sig_dispatch(struct kse *curkse, int sig, siginfo_t *info)
202{
203	struct pthread *thread;
204
205	DBG_MSG(">>> _thr_sig_dispatch(%d)\n", sig);
206
207	/* Some signals need special handling: */
208	handle_special_signals(curkse, sig);
209	while ((thread = thr_sig_find(curkse, sig, info)) != NULL) {
210		/*
211		 * Setup the target thread to receive the signal:
212		 */
213		DBG_MSG("Got signal %d, selecting thread %p\n", sig, thread);
214		KSE_SCHED_LOCK(curkse, thread->kseg);
215		if ((thread->state == PS_DEAD) ||
216		    (thread->state == PS_DEADLOCK) ||
217		    THR_IS_EXITING(thread) || THR_IS_SUSPENDED(thread)) {
218			KSE_SCHED_UNLOCK(curkse, thread->kseg);
219			_thr_ref_delete(NULL, thread);
220		} else if ((thread->state == PS_SIGWAIT &&
221			    SIGISMEMBER(thread->oldsigmask, sig)) ||
222			   (thread->state != PS_SIGWAIT &&
223			    SIGISMEMBER(thread->sigmask, sig))) {
224			KSE_SCHED_UNLOCK(curkse, thread->kseg);
225			_thr_ref_delete(NULL, thread);
226		} else {
227			_thr_sig_add(thread, sig, info);
228			KSE_SCHED_UNLOCK(curkse, thread->kseg);
229			_thr_ref_delete(NULL, thread);
230			break;
231		}
232	}
233	DBG_MSG("<<< _thr_sig_dispatch\n");
234}
235
236void
237_thr_sig_handler(int sig, siginfo_t *info, ucontext_t *ucp)
238{
239	__siginfohandler_t *sigfunc;
240	struct kse *curkse;
241
242	curkse = _get_curkse();
243	if ((curkse == NULL) || ((curkse->k_flags & KF_STARTED) == 0)) {
244		/* Upcalls are not yet started; just call the handler. */
245		sigfunc = _thread_sigact[sig - 1].sa_sigaction;
246		if (((__sighandler_t *)sigfunc != SIG_DFL) &&
247		    ((__sighandler_t *)sigfunc != SIG_IGN) &&
248		    (sigfunc != (__siginfohandler_t *)_thr_sig_handler)) {
249			if (((_thread_sigact[sig - 1].sa_flags & SA_SIGINFO)
250			    != 0) || (info == NULL))
251				(*(sigfunc))(sig, info, ucp);
252			else
253				(*(sigfunc))(sig,
254				    (siginfo_t*)(intptr_t)info->si_code, ucp);
255		}
256	}
257	else {
258		/* Nothing. */
259		DBG_MSG("Got signal %d\n", sig);
260		/* XXX Bound thread will fall into this... */
261	}
262}
263
264/* Must be called with signal lock and schedule lock held in order */
265static void
266thr_sig_invoke_handler(struct pthread *curthread, int sig, siginfo_t *info,
267    ucontext_t *ucp)
268{
269	void (*sigfunc)(int, siginfo_t *, void *);
270	sigset_t sigmask;
271	int sa_flags;
272	struct sigaction act;
273	struct kse *curkse;
274
275	/*
276	 * Invoke the signal handler without going through the scheduler:
277	 */
278	DBG_MSG("Got signal %d, calling handler for current thread %p\n",
279	    sig, curthread);
280
281	if (!_kse_in_critical())
282		PANIC("thr_sig_invoke_handler without in critical\n");
283	curkse = _get_curkse();
284	/*
285	 * Check that a custom handler is installed and if
286	 * the signal is not blocked:
287	 */
288	sigfunc = _thread_sigact[sig - 1].sa_sigaction;
289	sa_flags = _thread_sigact[sig - 1].sa_flags & SA_SIGINFO;
290	sigmask = curthread->sigmask;
291	SIGSETOR(curthread->sigmask, _thread_sigact[sig - 1].sa_mask);
292	if (!(sa_flags & (SA_NODEFER | SA_RESETHAND)))
293		SIGADDSET(curthread->sigmask, sig);
294	if ((sig != SIGILL) && (sa_flags & SA_RESETHAND)) {
295		if (_thread_dfl_count[sig - 1] == 0) {
296			act.sa_handler = SIG_DFL;
297			act.sa_flags = SA_RESTART;
298			SIGEMPTYSET(act.sa_mask);
299			__sys_sigaction(sig, &act, NULL);
300			__sys_sigaction(sig, NULL, &_thread_sigact[sig - 1]);
301		}
302	}
303	KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
304	KSE_SCHED_UNLOCK(curkse, curkse->k_kseg);
305	_kse_critical_leave(&curthread->tmbx);
306	ucp->uc_sigmask = sigmask;
307
308	if (((__sighandler_t *)sigfunc != SIG_DFL) &&
309	    ((__sighandler_t *)sigfunc != SIG_IGN)) {
310		if ((sa_flags & SA_SIGINFO) != 0 || info == NULL)
311			(*(sigfunc))(sig, info, ucp);
312		else
313			(*(sigfunc))(sig, (siginfo_t*)(intptr_t)info->si_code,
314			    ucp);
315	} else {
316		/* XXX
317		 * TODO: exit process if signal would kill it.
318		 */
319#ifdef NOTYET
320			if (sigprop(sig) & SA_KILL)
321				kse_sigexit(sig);
322#endif
323	}
324	_kse_critical_enter();
325	/* Don't trust after critical leave/enter */
326	curkse = _get_curkse();
327	KSE_SCHED_LOCK(curkse, curkse->k_kseg);
328	KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
329	/*
330	 * Restore the thread's signal mask.
331	 */
332	curthread->sigmask = ucp->uc_sigmask;
333
334	DBG_MSG("Got signal %d, handler returned %p\n", sig, curthread);
335}
336
337int
338_thr_getprocsig(int sig, siginfo_t *siginfo)
339{
340	kse_critical_t crit;
341	struct kse *curkse;
342	int ret;
343
344	DBG_MSG(">>> _thr_getprocsig\n");
345
346	crit = _kse_critical_enter();
347	curkse = _get_curkse();
348	KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
349	ret = _thr_getprocsig_unlocked(sig, siginfo);
350	KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
351	_kse_critical_leave(crit);
352
353	DBG_MSG("<<< _thr_getprocsig\n");
354	return (ret);
355}
356
357int
358_thr_getprocsig_unlocked(int sig, siginfo_t *siginfo)
359{
360	sigset_t sigset;
361	struct timespec ts;
362
363	/* try to retrieve signal from kernel */
364	SIGEMPTYSET(sigset);
365	SIGADDSET(sigset, sig);
366	ts.tv_sec = 0;
367	ts.tv_nsec = 0;
368	if (__sys_sigtimedwait(&sigset, siginfo, &ts) > 0) {
369		SIGDELSET(_thr_proc_sigpending, sig);
370		return (sig);
371	}
372	return (0);
373}
374
375/*
376 * Find a thread that can handle the signal.  This must be called
377 * with upcalls disabled.
378 */
379struct pthread *
380thr_sig_find(struct kse *curkse, int sig, siginfo_t *info)
381{
382	struct pthread	*pthread;
383	struct pthread	*suspended_thread, *signaled_thread;
384	siginfo_t si;
385
386	DBG_MSG("Looking for thread to handle signal %d\n", sig);
387
388	/* Check if the signal requires a dump of thread information: */
389	if (sig == SIGINFO) {
390		/* Dump thread information to file: */
391		_thread_dump_info();
392	}
393	/*
394	 * Enter a loop to look for threads that have the signal
395	 * unmasked.  POSIX specifies that a thread in a sigwait
396	 * will get the signal over any other threads.  Second
397	 * preference will be threads in in a sigsuspend.  Third
398	 * preference will be the current thread.  If none of the
399	 * above, then the signal is delivered to the first thread
400	 * that is found.  Note that if a custom handler is not
401	 * installed, the signal only affects threads in sigwait.
402	 */
403	suspended_thread = NULL;
404	signaled_thread = NULL;
405
406	KSE_LOCK_ACQUIRE(curkse, &_thread_list_lock);
407	TAILQ_FOREACH(pthread, &_thread_list, tle) {
408		if (pthread == _thr_sig_daemon)
409			continue;
410#ifdef NOTYET
411		/* Signal delivering to bound thread is done by kernel */
412		if (pthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
413			continue;
414#endif
415
416		/* Take the scheduling lock. */
417		KSE_SCHED_LOCK(curkse, pthread->kseg);
418		if ((pthread->state == PS_DEAD)		||
419		    (pthread->state == PS_DEADLOCK)	||
420		    THR_IS_EXITING(pthread)		||
421		    THR_IS_SUSPENDED(pthread)) {
422			; /* Skip this thread. */
423		} else if (pthread->state == PS_SIGWAIT &&
424			   !SIGISMEMBER(pthread->sigmask, sig)) {
425			/*
426			 * retrieve signal from kernel, if it is job control
427			 * signal, and sigaction is SIG_DFL, then we will
428			 * be stopped in kernel, we hold lock here, but that
429			 * does not matter, because that's job control, and
430			 * whole process should be stopped.
431			 */
432			if (_thr_getprocsig(sig, &si)) {
433				DBG_MSG("Waking thread %p in sigwait"
434					" with signal %d\n", pthread, sig);
435				/*  where to put siginfo ? */
436				*(pthread->data.sigwaitinfo) = si;
437				pthread->sigmask = pthread->oldsigmask;
438				_thr_setrunnable_unlocked(pthread);
439			}
440			KSE_SCHED_UNLOCK(curkse, pthread->kseg);
441			/*
442			 * POSIX doesn't doesn't specify which thread
443			 * will get the signal if there are multiple
444			 * waiters, so we give it to the first thread
445			 * we find.
446			 *
447			 * Do not attempt to deliver this signal
448			 * to other threads and do not add the signal
449			 * to the process pending set.
450			 */
451			KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
452			return (NULL);
453		} else if (!SIGISMEMBER(pthread->sigmask, sig) ||
454			(!SIGISMEMBER(pthread->oldsigmask, sig) &&
455			 pthread->state == PS_SIGWAIT)) {
456			if (pthread->state == PS_SIGSUSPEND) {
457				if (suspended_thread == NULL) {
458					suspended_thread = pthread;
459					suspended_thread->refcount++;
460				}
461			} else if (signaled_thread == NULL) {
462				signaled_thread = pthread;
463				signaled_thread->refcount++;
464			}
465		}
466		KSE_SCHED_UNLOCK(curkse, pthread->kseg);
467	}
468	KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
469
470	if (suspended_thread != NULL) {
471		pthread = suspended_thread;
472		if (signaled_thread)
473			_thr_ref_delete(NULL, signaled_thread);
474	} else if (signaled_thread) {
475		pthread = signaled_thread;
476	} else {
477		pthread = NULL;
478	}
479	return (pthread);
480}
481
482static void
483build_siginfo(siginfo_t *info, int signo)
484{
485	bzero(info, sizeof(*info));
486	info->si_signo = signo;
487	info->si_pid = _thr_pid;
488}
489
490/*
491 * This is called by a thread when it has pending signals to deliver.
492 * It should only be called from the context of the thread.
493 */
494void
495_thr_sig_rundown(struct pthread *curthread, ucontext_t *ucp,
496    struct pthread_sigframe *psf)
497{
498	int interrupted = curthread->interrupted;
499	int timeout = curthread->timeout;
500	siginfo_t siginfo;
501	int i;
502	kse_critical_t crit;
503	struct kse *curkse;
504
505	DBG_MSG(">>> thr_sig_rundown %p\n", curthread);
506	/* Check the threads previous state: */
507	if ((psf != NULL) && (psf->psf_valid != 0)) {
508		/*
509		 * Do a little cleanup handling for those threads in
510		 * queues before calling the signal handler.  Signals
511		 * for these threads are temporarily blocked until
512		 * after cleanup handling.
513		 */
514		switch (psf->psf_state) {
515		case PS_COND_WAIT:
516			_cond_wait_backout(curthread);
517			psf->psf_state = PS_RUNNING;
518			break;
519
520		case PS_MUTEX_WAIT:
521			_mutex_lock_backout(curthread);
522			psf->psf_state = PS_RUNNING;
523			break;
524
525		case PS_RUNNING:
526			break;
527
528		default:
529			psf->psf_state = PS_RUNNING;
530			break;
531		}
532		/* XXX see comment in thr_sched_switch_unlocked */
533		curthread->critical_count--;
534	}
535
536	/*
537	 * Lower the priority before calling the handler in case
538	 * it never returns (longjmps back):
539	 */
540	crit = _kse_critical_enter();
541	curkse = _get_curkse();
542	KSE_SCHED_LOCK(curkse, curkse->k_kseg);
543	KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
544	curthread->active_priority &= ~THR_SIGNAL_PRIORITY;
545
546	while (1) {
547		for (i = 1; i <= _SIG_MAXSIG; i++) {
548			if (SIGISMEMBER(curthread->sigmask, i))
549				continue;
550			if (SIGISMEMBER(curthread->sigpend, i)) {
551				SIGDELSET(curthread->sigpend, i);
552				siginfo = curthread->siginfo[i-1];
553				break;
554			}
555			if (SIGISMEMBER(_thr_proc_sigpending, i)) {
556				if (_thr_getprocsig_unlocked(i, &siginfo))
557					break;
558			}
559		}
560		if (i <= _SIG_MAXSIG)
561			thr_sig_invoke_handler(curthread, i, &siginfo, ucp);
562		else
563			break;
564	}
565
566	if (psf != NULL && psf->psf_valid != 0)
567		thr_sigframe_restore(curthread, psf);
568	curkse = _get_curkse();
569	KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
570	KSE_SCHED_UNLOCK(curkse, curkse->k_kseg);
571	_kse_critical_leave(&curthread->tmbx);
572
573	curthread->interrupted = interrupted;
574	curthread->timeout = timeout;
575
576	DBG_MSG("<<< thr_sig_rundown %p\n", curthread);
577}
578
579/*
580 * This checks pending signals for the current thread.  It should be
581 * called whenever a thread changes its signal mask.  Note that this
582 * is called from a thread (using its stack).
583 *
584 * XXX - We might want to just check to see if there are pending
585 *       signals for the thread here, but enter the UTS scheduler
586 *       to actually install the signal handler(s).
587 */
588void
589_thr_sig_check_pending(struct pthread *curthread)
590{
591	ucontext_t uc;
592	volatile int once;
593
594	if (THR_IN_CRITICAL(curthread))
595		return;
596
597	once = 0;
598	THR_GETCONTEXT(&uc);
599	if (once == 0) {
600		once = 1;
601		curthread->check_pending = 0;
602		_thr_sig_rundown(curthread, &uc, NULL);
603	}
604}
605
606/*
607 * This must be called with upcalls disabled.
608 */
609static void
610handle_special_signals(struct kse *curkse, int sig)
611{
612	switch (sig) {
613	/*
614	 * POSIX says that pending SIGCONT signals are
615	 * discarded when one of these signals occurs.
616	 */
617	case SIGTSTP:
618	case SIGTTIN:
619	case SIGTTOU:
620		KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
621		SIGDELSET(_thr_proc_sigpending, SIGCONT);
622		KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
623		break;
624	case SIGCONT:
625		KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
626		SIGDELSET(_thr_proc_sigpending, SIGTSTP);
627		SIGDELSET(_thr_proc_sigpending, SIGTTIN);
628		SIGDELSET(_thr_proc_sigpending, SIGTTOU);
629		KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
630	default:
631		break;
632	}
633}
634
635/*
636 * Perform thread specific actions in response to a signal.
637 * This function is only called if there is a handler installed
638 * for the signal, and if the target thread has the signal
639 * unmasked.
640 *
641 * This must be called with the thread's scheduling lock held.
642 */
643void
644_thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info)
645{
646	int	restart;
647	int	suppress_handler = 0;
648	int	fromproc = 0;
649	struct  pthread *curthread = _get_curthread();
650	struct	kse *curkse;
651	siginfo_t siginfo;
652
653	DBG_MSG(">>> _thr_sig_add\n");
654
655	curkse = _get_curkse();
656	restart = _thread_sigact[sig - 1].sa_flags & SA_RESTART;
657	fromproc = (curthread == _thr_sig_daemon);
658
659	if (pthread->state == PS_DEAD || pthread->state == PS_DEADLOCK ||
660	    pthread->state == PS_STATE_MAX)
661	    	return; /* return false */
662
663#ifdef NOTYET
664	if ((pthread->attrs.flags & PTHREAD_SCOPE_SYSTEM) != 0) {
665		if (!fromproc)
666			kse_thr_interrupt(&pthread->tmbx, 0, sig);
667		return;
668	}
669#endif
670
671	if (pthread->curframe == NULL ||
672	    (pthread->state != PS_SIGWAIT &&
673	    SIGISMEMBER(pthread->sigmask, sig)) ||
674	    THR_IN_CRITICAL(pthread)) {
675		/* thread is running or signal was being masked */
676		if (!fromproc) {
677			SIGADDSET(pthread->sigpend, sig);
678			if (info == NULL)
679				build_siginfo(&pthread->siginfo[sig-1], sig);
680			else if (info != &pthread->siginfo[sig-1])
681				memcpy(&pthread->siginfo[sig-1], info,
682					 sizeof(*info));
683		} else {
684			if (!_thr_getprocsig(sig, &pthread->siginfo[sig-1]))
685				return;
686			SIGADDSET(pthread->sigpend, sig);
687		}
688		if (!SIGISMEMBER(pthread->sigmask, sig)) {
689			pthread->check_pending = 1;
690			if (pthread->blocked != 0 && !THR_IN_CRITICAL(pthread))
691				kse_thr_interrupt(&pthread->tmbx,
692					 restart ? -2 : -1);
693		}
694	}
695	else {
696		/* if process signal not exists, just return */
697		if (fromproc) {
698			if (!_thr_getprocsig(sig, &siginfo))
699				return;
700			info = &siginfo;
701		}
702		/*
703		 * Process according to thread state:
704		 */
705		switch (pthread->state) {
706		case PS_DEAD:
707		case PS_DEADLOCK:
708		case PS_STATE_MAX:
709			return;	/* XXX return false */
710		case PS_LOCKWAIT:
711		case PS_SUSPENDED:
712			/*
713			 * You can't call a signal handler for threads in these
714			 * states.
715			 */
716			suppress_handler = 1;
717			break;
718		case PS_RUNNING:
719			if ((pthread->flags & THR_FLAGS_IN_RUNQ)) {
720				THR_RUNQ_REMOVE(pthread);
721				pthread->active_priority |= THR_SIGNAL_PRIORITY;
722				THR_RUNQ_INSERT_TAIL(pthread);
723			} else {
724				/* Possible not in RUNQ and has curframe ? */
725				pthread->active_priority |= THR_SIGNAL_PRIORITY;
726			}
727			suppress_handler = 1;
728			break;
729		/*
730		 * States which cannot be interrupted but still require the
731		 * signal handler to run:
732		 */
733		case PS_COND_WAIT:
734		case PS_MUTEX_WAIT:
735			break;
736
737		case PS_SLEEP_WAIT:
738			/*
739			 * Unmasked signals always cause sleep to terminate
740			 * early regardless of SA_RESTART:
741			 */
742			pthread->interrupted = 1;
743			break;
744
745		case PS_JOIN:
746			break;
747
748		case PS_SIGSUSPEND:
749			pthread->interrupted = 1;
750			break;
751
752		case PS_SIGWAIT:
753			if (info == NULL)
754				build_siginfo(&pthread->siginfo[sig-1], sig);
755			else if (info != &pthread->siginfo[sig-1])
756				memcpy(&pthread->siginfo[sig-1], info,
757					sizeof(*info));
758			/*
759			 * The signal handler is not called for threads in
760			 * SIGWAIT.
761			 */
762			suppress_handler = 1;
763			/* Wake up the thread if the signal is not blocked. */
764			if (!SIGISMEMBER(pthread->sigmask, sig)) {
765				/* Return the signal number: */
766				*(pthread->data.sigwaitinfo) = pthread->siginfo[sig-1];
767				pthread->sigmask = pthread->oldsigmask;
768				/* Make the thread runnable: */
769				_thr_setrunnable_unlocked(pthread);
770			} else {
771				/* Increment the pending signal count. */
772				SIGADDSET(pthread->sigpend, sig);
773				if (!SIGISMEMBER(pthread->oldsigmask, sig)) {
774					pthread->check_pending = 1;
775					pthread->interrupted = 1;
776					pthread->sigmask = pthread->oldsigmask;
777					_thr_setrunnable_unlocked(pthread);
778				}
779			}
780
781			return;
782		}
783
784		SIGADDSET(pthread->sigpend, sig);
785		if (info == NULL)
786			build_siginfo(&pthread->siginfo[sig-1], sig);
787		else if (info != &pthread->siginfo[sig-1])
788			memcpy(&pthread->siginfo[sig-1], info, sizeof(*info));
789
790		if (suppress_handler == 0) {
791			/*
792			 * Setup a signal frame and save the current threads
793			 * state:
794			 */
795			thr_sigframe_add(pthread);
796			if (pthread->flags & THR_FLAGS_IN_RUNQ)
797				THR_RUNQ_REMOVE(pthread);
798			pthread->active_priority |= THR_SIGNAL_PRIORITY;
799			_thr_setrunnable_unlocked(pthread);
800		} else {
801			pthread->check_pending = 1;
802		}
803	}
804
805	DBG_MSG("<<< _thr_sig_add\n");
806}
807
808static void
809thr_sig_check_state(struct pthread *pthread, int sig)
810{
811	/*
812	 * Process according to thread state:
813	 */
814	switch (pthread->state) {
815	/*
816	 * States which do not change when a signal is trapped:
817	 */
818	case PS_RUNNING:
819	case PS_LOCKWAIT:
820	case PS_MUTEX_WAIT:
821	case PS_COND_WAIT:
822	case PS_JOIN:
823	case PS_SUSPENDED:
824	case PS_DEAD:
825	case PS_DEADLOCK:
826	case PS_STATE_MAX:
827		break;
828
829	case PS_SIGWAIT:
830		build_siginfo(&pthread->siginfo[sig-1], sig);
831		/* Wake up the thread if the signal is blocked. */
832		if (!SIGISMEMBER(pthread->sigmask, sig)) {
833			/* Return the signal number: */
834			*(pthread->data.sigwaitinfo) = pthread->siginfo[sig-1];
835			pthread->sigmask = pthread->oldsigmask;
836			/* Change the state of the thread to run: */
837			_thr_setrunnable_unlocked(pthread);
838		} else {
839			/* Increment the pending signal count. */
840			SIGADDSET(pthread->sigpend, sig);
841			if (!SIGISMEMBER(pthread->oldsigmask, sig)) {
842				pthread->check_pending = 1;
843				pthread->interrupted = 1;
844				pthread->sigmask = pthread->oldsigmask;
845				_thr_setrunnable_unlocked(pthread);
846			}
847		}
848		break;
849
850	case PS_SIGSUSPEND:
851	case PS_SLEEP_WAIT:
852		/*
853		 * Remove the thread from the wait queue and make it
854		 * runnable:
855		 */
856		_thr_setrunnable_unlocked(pthread);
857
858		/* Flag the operation as interrupted: */
859		pthread->interrupted = 1;
860		break;
861	}
862}
863
864/*
865 * Send a signal to a specific thread (ala pthread_kill):
866 */
867void
868_thr_sig_send(struct pthread *pthread, int sig)
869{
870	struct pthread *curthread = _get_curthread();
871
872#ifdef NOTYET
873	if ((pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) == 0) {
874		kse_thr_interrupt(&pthread->tmbx, sig);
875		return;
876	}
877#endif
878	/* Lock the scheduling queue of the target thread. */
879	THR_SCHED_LOCK(curthread, pthread);
880
881	/* Check for signals whose actions are SIG_DFL: */
882	if (_thread_sigact[sig - 1].sa_handler == SIG_DFL) {
883		/*
884		 * Check to see if a temporary signal handler is
885		 * installed for sigwaiters:
886		 */
887		if (_thread_dfl_count[sig - 1] == 0) {
888			/*
889			 * Deliver the signal to the process if a handler
890			 * is not installed:
891			 */
892			THR_SCHED_UNLOCK(curthread, pthread);
893			kill(getpid(), sig);
894			THR_SCHED_LOCK(curthread, pthread);
895		}
896		/*
897		 * Assuming we're still running after the above kill(),
898		 * make any necessary state changes to the thread:
899		 */
900		thr_sig_check_state(pthread, sig);
901		THR_SCHED_UNLOCK(curthread, pthread);
902	}
903	/*
904	 * Check that the signal is not being ignored:
905	 */
906	else if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) {
907		_thr_sig_add(pthread, sig, NULL);
908		THR_SCHED_UNLOCK(curthread, pthread);
909		/* XXX
910		 * If thread sent signal to itself, check signals now.
911		 * It is not really needed, _kse_critical_leave should
912		 * have already checked signals.
913		 */
914		if (pthread == curthread && curthread->check_pending)
915			_thr_sig_check_pending(curthread);
916	} else  {
917		THR_SCHED_UNLOCK(curthread, pthread);
918	}
919}
920
921static void
922thr_sigframe_add(struct pthread *thread)
923{
924	if (thread->curframe == NULL)
925		PANIC("Thread doesn't have signal frame ");
926
927	if (thread->curframe->psf_valid == 0) {
928		thread->curframe->psf_valid = 1;
929		/*
930		 * Multiple signals can be added to the same signal
931		 * frame.  Only save the thread's state the first time.
932		 */
933		thr_sigframe_save(thread, thread->curframe);
934	}
935}
936
937static void
938thr_sigframe_restore(struct pthread *thread, struct pthread_sigframe *psf)
939{
940	if (psf->psf_valid == 0)
941		PANIC("invalid pthread_sigframe\n");
942	thread->flags = psf->psf_flags;
943	thread->interrupted = psf->psf_interrupted;
944	thread->signo = psf->psf_signo;
945	thread->state = psf->psf_state;
946	thread->data = psf->psf_wait_data;
947	thread->wakeup_time = psf->psf_wakeup_time;
948}
949
950static void
951thr_sigframe_save(struct pthread *thread, struct pthread_sigframe *psf)
952{
953	/* This has to initialize all members of the sigframe. */
954	psf->psf_flags =
955	    thread->flags & (THR_FLAGS_PRIVATE | THR_FLAGS_IN_TDLIST);
956	psf->psf_interrupted = thread->interrupted;
957	psf->psf_signo = thread->signo;
958	psf->psf_state = thread->state;
959	psf->psf_wait_data = thread->data;
960	psf->psf_wakeup_time = thread->wakeup_time;
961}
962
963void
964_thr_signal_init(void)
965{
966	sigset_t sigset;
967	struct sigaction act;
968	int i;
969
970	SIGFILLSET(sigset);
971	__sys_sigprocmask(SIG_SETMASK, &sigset, &_thr_initial->sigmask);
972	/* Enter a loop to get the existing signal status: */
973	for (i = 1; i <= _SIG_MAXSIG; i++) {
974		/* Check for signals which cannot be trapped: */
975		if (i == SIGKILL || i == SIGSTOP) {
976		}
977
978		/* Get the signal handler details: */
979		else if (__sys_sigaction(i, NULL,
980			    &_thread_sigact[i - 1]) != 0) {
981			/*
982			 * Abort this process if signal
983			 * initialisation fails:
984			 */
985			PANIC("Cannot read signal handler info");
986		}
987	}
988	/*
989	 * Install the signal handler for SIGINFO.  It isn't
990	 * really needed, but it is nice to have for debugging
991	 * purposes.
992	 */
993	_thread_sigact[SIGINFO - 1].sa_flags = SA_SIGINFO | SA_RESTART;
994	SIGEMPTYSET(act.sa_mask);
995	act.sa_flags = SA_SIGINFO | SA_RESTART;
996	act.sa_sigaction = (__siginfohandler_t *)&_thr_sig_handler;
997	if (__sys_sigaction(SIGINFO, &act, NULL) != 0) {
998		/*
999		 * Abort this process if signal initialisation fails:
1000		 */
1001		PANIC("Cannot initialize signal handler");
1002	}
1003}
1004
1005void
1006_thr_signal_deinit(void)
1007{
1008	struct pthread *curthread = _get_curthread();
1009	sigset_t tmpmask;
1010	int i;
1011
1012	SIGFILLSET(tmpmask);
1013	SIG_CANTMASK(tmpmask);
1014	__sys_sigprocmask(SIG_SETMASK, &tmpmask, NULL);
1015	/* Enter a loop to get the existing signal status: */
1016	for (i = 1; i <= _SIG_MAXSIG; i++) {
1017		/* Check for signals which cannot be trapped: */
1018		if (i == SIGKILL || i == SIGSTOP) {
1019		}
1020
1021		/* Set the signal handler details: */
1022		else if (__sys_sigaction(i, &_thread_sigact[i - 1], NULL) != 0) {
1023			/*
1024			 * Abort this process if signal
1025			 * initialisation fails:
1026			 */
1027			PANIC("Cannot set signal handler info");
1028		}
1029	}
1030	__sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL);
1031}
1032
1033