113546Sjulian/*
235509Sjb * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
313546Sjulian * All rights reserved.
413546Sjulian *
513546Sjulian * Redistribution and use in source and binary forms, with or without
613546Sjulian * modification, are permitted provided that the following conditions
713546Sjulian * are met:
813546Sjulian * 1. Redistributions of source code must retain the above copyright
913546Sjulian *    notice, this list of conditions and the following disclaimer.
1013546Sjulian * 2. Redistributions in binary form must reproduce the above copyright
1113546Sjulian *    notice, this list of conditions and the following disclaimer in the
1213546Sjulian *    documentation and/or other materials provided with the distribution.
13165967Simp * 3. Neither the name of the author nor the names of any co-contributors
1413546Sjulian *    may be used to endorse or promote products derived from this software
1513546Sjulian *    without specific prior written permission.
1613546Sjulian *
1713546Sjulian * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
1813546Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1913546Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2049439Sdeischen * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2113546Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2213546Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2313546Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2413546Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2513546Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2613546Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2713546Sjulian * SUCH DAMAGE.
2813546Sjulian *
2950476Speter * $FreeBSD$
3013546Sjulian */
31174112Sdeischen
32174112Sdeischen#include "namespace.h"
3351794Smarcel#include <sys/param.h>
3451794Smarcel#include <sys/types.h>
3551794Smarcel#include <sys/signalvar.h>
3613546Sjulian#include <signal.h>
37113658Sdeischen#include <errno.h>
3817706Sjulian#include <fcntl.h>
3917706Sjulian#include <unistd.h>
40113658Sdeischen#include <string.h>
4113546Sjulian#include <pthread.h>
42174112Sdeischen#include "un-namespace.h"
43103388Smini#include "thr_private.h"
4413546Sjulian
4554138Sdeischen/* Prototypes: */
46139023Sdeischenstatic inline void build_siginfo(siginfo_t *info, int signo);
47117706Sdavidxu#ifndef SYSTEM_SCOPE_ONLY
48113658Sdeischenstatic struct pthread *thr_sig_find(struct kse *curkse, int sig,
49113658Sdeischen		    siginfo_t *info);
50117706Sdavidxu#endif
51139023Sdeischenstatic inline void thr_sigframe_restore(struct pthread *thread,
52139023Sdeischen	struct pthread_sigframe *psf);
53139023Sdeischenstatic inline void thr_sigframe_save(struct pthread *thread,
54139023Sdeischen	struct pthread_sigframe *psf);
55111035Smini
56117706Sdavidxu#define SA_KILL         0x01            /* terminates process by default */
57117706Sdavidxu#define	SA_STOP		0x02
58117706Sdavidxu#define	SA_CONT		0x04
59117706Sdavidxu
60117706Sdavidxustatic int sigproptbl[NSIG] = {
61117706Sdavidxu	SA_KILL,	/* SIGHUP */
62117706Sdavidxu	SA_KILL,	/* SIGINT */
63117706Sdavidxu	SA_KILL,	/* SIGQUIT */
64117706Sdavidxu	SA_KILL,	/* SIGILL */
65117706Sdavidxu	SA_KILL,	/* SIGTRAP */
66117706Sdavidxu	SA_KILL,	/* SIGABRT */
67117706Sdavidxu	SA_KILL,	/* SIGEMT */
68117706Sdavidxu	SA_KILL,	/* SIGFPE */
69117706Sdavidxu	SA_KILL,	/* SIGKILL */
70117706Sdavidxu	SA_KILL,	/* SIGBUS */
71117706Sdavidxu	SA_KILL,	/* SIGSEGV */
72117706Sdavidxu	SA_KILL,	/* SIGSYS */
73117706Sdavidxu	SA_KILL,	/* SIGPIPE */
74117706Sdavidxu	SA_KILL,	/* SIGALRM */
75117706Sdavidxu	SA_KILL,	/* SIGTERM */
76117706Sdavidxu	0,		/* SIGURG */
77117706Sdavidxu	SA_STOP,	/* SIGSTOP */
78117706Sdavidxu	SA_STOP,	/* SIGTSTP */
79117706Sdavidxu	SA_CONT,	/* SIGCONT */
80117706Sdavidxu	0,		/* SIGCHLD */
81117706Sdavidxu	SA_STOP,	/* SIGTTIN */
82117706Sdavidxu	SA_STOP,	/* SIGTTOU */
83117706Sdavidxu	0,		/* SIGIO */
84117706Sdavidxu	SA_KILL,	/* SIGXCPU */
85117706Sdavidxu	SA_KILL,	/* SIGXFSZ */
86117706Sdavidxu	SA_KILL,	/* SIGVTALRM */
87117706Sdavidxu	SA_KILL,	/* SIGPROF */
88117706Sdavidxu	0,		/* SIGWINCH  */
89117706Sdavidxu	0,		/* SIGINFO */
90117706Sdavidxu	SA_KILL,	/* SIGUSR1 */
91117706Sdavidxu	SA_KILL		/* SIGUSR2 */
92117706Sdavidxu};
93117706Sdavidxu
94111035Smini/* #define DEBUG_SIGNAL */
9567097Sdeischen#ifdef DEBUG_SIGNAL
9667097Sdeischen#define DBG_MSG		stdout_debug
9767097Sdeischen#else
9867097Sdeischen#define DBG_MSG(x...)
9967097Sdeischen#endif
10056277Sjasone
101111035Smini/*
102113658Sdeischen * Signal setup and delivery.
103113658Sdeischen *
104113658Sdeischen * 1) Delivering signals to threads in the same KSE.
105113658Sdeischen *    These signals are sent by upcall events and are set in the
106113658Sdeischen *    km_sigscaught field of the KSE mailbox.  Since these signals
107113658Sdeischen *    are received while operating on the KSE stack, they can be
108113658Sdeischen *    delivered either by using signalcontext() to add a stack frame
109113658Sdeischen *    to the target thread's stack, or by adding them in the thread's
110113658Sdeischen *    pending set and having the thread run them down after it
111113658Sdeischen * 2) Delivering signals to threads in other KSEs/KSEGs.
112113658Sdeischen * 3) Delivering signals to threads in critical regions.
113113658Sdeischen * 4) Delivering signals to threads after they change their signal masks.
114113658Sdeischen *
115113658Sdeischen * Methods of delivering signals.
116113658Sdeischen *
117113658Sdeischen *   1) Add a signal frame to the thread's saved context.
118113658Sdeischen *   2) Add the signal to the thread structure, mark the thread as
119113658Sdeischen *  	having signals to handle, and let the thread run them down
120113658Sdeischen *  	after it resumes from the KSE scheduler.
121113658Sdeischen *
122113658Sdeischen * Problem with 1).  You can't do this to a running thread or a
123113658Sdeischen * thread in a critical region.
124113658Sdeischen *
125113658Sdeischen * Problem with 2).  You can't do this to a thread that doesn't
126113658Sdeischen * yield in some way (explicitly enters the scheduler).  A thread
127113658Sdeischen * blocked in the kernel or a CPU hungry thread will not see the
128113658Sdeischen * signal without entering the scheduler.
129113658Sdeischen *
130113658Sdeischen * The solution is to use both 1) and 2) to deliver signals:
131113658Sdeischen *
132113658Sdeischen *   o Thread in critical region - use 2).  When the thread
133113658Sdeischen *     leaves the critical region it will check to see if it
134113658Sdeischen *     has pending signals and run them down.
135113658Sdeischen *
136113658Sdeischen *   o Thread enters scheduler explicitly - use 2).  The thread
137113658Sdeischen *     can check for pending signals after it returns from the
138113658Sdeischen *     the scheduler.
139113658Sdeischen *
140113658Sdeischen *   o Thread is running and not current thread - use 2).  When the
141113658Sdeischen *     thread hits a condition specified by one of the other bullets,
142113658Sdeischen *     the signal will be delivered.
143113658Sdeischen *
144113658Sdeischen *   o Thread is running and is current thread (e.g., the thread
145113658Sdeischen *     has just changed its signal mask and now sees that it has
146113658Sdeischen *     pending signals) - just run down the pending signals.
147113658Sdeischen *
148113658Sdeischen *   o Thread is swapped out due to quantum expiration - use 1)
149113658Sdeischen *
150113658Sdeischen *   o Thread is blocked in kernel - kse_thr_wakeup() and then
151113658Sdeischen *     use 1)
152111035Smini */
153113658Sdeischen
154113658Sdeischen/*
155113658Sdeischen * Rules for selecting threads for signals received:
156113658Sdeischen *
157113658Sdeischen *   1) If the signal is a sychronous signal, it is delivered to
158113658Sdeischen *      the generating (current thread).  If the thread has the
159113658Sdeischen *      signal masked, it is added to the threads pending signal
160113658Sdeischen *      set until the thread unmasks it.
161113658Sdeischen *
162113658Sdeischen *   2) A thread in sigwait() where the signal is in the thread's
163113658Sdeischen *      waitset.
164113658Sdeischen *
165113658Sdeischen *   3) A thread in sigsuspend() where the signal is not in the
166113658Sdeischen *      thread's suspended signal mask.
167113658Sdeischen *
168113658Sdeischen *   4) Any thread (first found/easiest to deliver) that has the
169113658Sdeischen *      signal unmasked.
170113658Sdeischen */
171113658Sdeischen
172117706Sdavidxu#ifndef SYSTEM_SCOPE_ONLY
173117706Sdavidxu
174116977Sdavidxustatic void *
175174112Sdeischensig_daemon(void *arg __unused)
176116977Sdavidxu{
177116977Sdavidxu	int i;
178116977Sdavidxu	kse_critical_t crit;
179116977Sdavidxu	struct timespec ts;
180116977Sdavidxu	sigset_t set;
181116977Sdavidxu	struct kse *curkse;
182116977Sdavidxu	struct pthread *curthread = _get_curthread();
183116977Sdavidxu
184117706Sdavidxu	DBG_MSG("signal daemon started(%p)\n", curthread);
185116977Sdavidxu
186116977Sdavidxu	curthread->name = strdup("signal thread");
187116977Sdavidxu	crit = _kse_critical_enter();
188116977Sdavidxu	curkse = _get_curkse();
189117706Sdavidxu
190117706Sdavidxu	/*
191117706Sdavidxu	 * Daemon thread is a bound thread and we must be created with
192117706Sdavidxu	 * all signals masked
193117706Sdavidxu	 */
194117706Sdavidxu#if 0
195116977Sdavidxu	SIGFILLSET(set);
196116977Sdavidxu	__sys_sigprocmask(SIG_SETMASK, &set, NULL);
197117706Sdavidxu#endif
198116977Sdavidxu	__sys_sigpending(&set);
199116977Sdavidxu	ts.tv_sec = 0;
200116977Sdavidxu	ts.tv_nsec = 0;
201116977Sdavidxu	while (1) {
202116977Sdavidxu		KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
203116977Sdavidxu		_thr_proc_sigpending = set;
204116977Sdavidxu		KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
205116977Sdavidxu		for (i = 1; i <= _SIG_MAXSIG; i++) {
206116977Sdavidxu			if (SIGISMEMBER(set, i) != 0)
207116977Sdavidxu				_thr_sig_dispatch(curkse, i,
208116977Sdavidxu				    NULL /* no siginfo */);
209116977Sdavidxu		}
210116977Sdavidxu		ts.tv_sec = 30;
211116977Sdavidxu		ts.tv_nsec = 0;
212118510Sdeischen		curkse->k_kcb->kcb_kmbx.km_flags =
213116977Sdavidxu		    KMF_NOUPCALL | KMF_NOCOMPLETED | KMF_WAITSIGEVENT;
214116977Sdavidxu		kse_release(&ts);
215118510Sdeischen		curkse->k_kcb->kcb_kmbx.km_flags = 0;
216118510Sdeischen		set = curkse->k_kcb->kcb_kmbx.km_sigscaught;
217116977Sdavidxu	}
218116977Sdavidxu	return (0);
219116977Sdavidxu}
220116977Sdavidxu
221117706Sdavidxu
222116977Sdavidxu/* Utility function to create signal daemon thread */
223116977Sdavidxuint
224116977Sdavidxu_thr_start_sig_daemon(void)
225116977Sdavidxu{
226116977Sdavidxu	pthread_attr_t attr;
227116977Sdavidxu	sigset_t sigset, oldset;
228117706Sdavidxu
229116977Sdavidxu	SIGFILLSET(sigset);
230174112Sdeischen	_pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
231174112Sdeischen	_pthread_attr_init(&attr);
232174112Sdeischen	_pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
233132122Sdavidxu	attr->flags |= THR_SIGNAL_THREAD;
234116977Sdavidxu	/* sigmask will be inherited */
235174112Sdeischen	if (_pthread_create(&_thr_sig_daemon, &attr, sig_daemon, NULL))
236116977Sdavidxu		PANIC("can not create signal daemon thread!\n");
237174112Sdeischen	_pthread_attr_destroy(&attr);
238174112Sdeischen	_pthread_sigmask(SIG_SETMASK, &oldset, NULL);
239116977Sdavidxu	return (0);
240116977Sdavidxu}
241116977Sdavidxu
242113658Sdeischen/*
243113658Sdeischen * This signal handler only delivers asynchronous signals.
244113658Sdeischen * This must be called with upcalls disabled and without
245113658Sdeischen * holding any locks.
246113658Sdeischen */
24713546Sjulianvoid
248113658Sdeischen_thr_sig_dispatch(struct kse *curkse, int sig, siginfo_t *info)
24935509Sjb{
250117907Sdeischen	struct kse_mailbox *kmbx;
251113658Sdeischen	struct pthread *thread;
25235509Sjb
253113658Sdeischen	DBG_MSG(">>> _thr_sig_dispatch(%d)\n", sig);
25435509Sjb
255117706Sdavidxu	/* Check if the signal requires a dump of thread information: */
256156330Sdeischen	if (_thr_dump_enabled() && (sig == SIGINFO)) {
257117706Sdavidxu		/* Dump thread information to file: */
258117706Sdavidxu		_thread_dump_info();
259117706Sdavidxu	}
260117706Sdavidxu
261115278Sdeischen	while ((thread = thr_sig_find(curkse, sig, info)) != NULL) {
262113658Sdeischen		/*
263113658Sdeischen		 * Setup the target thread to receive the signal:
264113658Sdeischen		 */
265113658Sdeischen		DBG_MSG("Got signal %d, selecting thread %p\n", sig, thread);
266113658Sdeischen		KSE_SCHED_LOCK(curkse, thread->kseg);
267115278Sdeischen		if ((thread->state == PS_DEAD) ||
268115278Sdeischen		    (thread->state == PS_DEADLOCK) ||
269115278Sdeischen		    THR_IS_EXITING(thread) || THR_IS_SUSPENDED(thread)) {
270115278Sdeischen			KSE_SCHED_UNLOCK(curkse, thread->kseg);
271115278Sdeischen			_thr_ref_delete(NULL, thread);
272118075Sdavidxu		} else if (SIGISMEMBER(thread->sigmask, sig)) {
273116061Sdeischen			KSE_SCHED_UNLOCK(curkse, thread->kseg);
274116061Sdeischen			_thr_ref_delete(NULL, thread);
275116977Sdavidxu		} else {
276117907Sdeischen			kmbx = _thr_sig_add(thread, sig, info);
277115278Sdeischen			KSE_SCHED_UNLOCK(curkse, thread->kseg);
278115278Sdeischen			_thr_ref_delete(NULL, thread);
279117907Sdeischen			if (kmbx != NULL)
280117907Sdeischen				kse_wakeup(kmbx);
281115278Sdeischen			break;
282115278Sdeischen		}
283113658Sdeischen	}
284116977Sdavidxu	DBG_MSG("<<< _thr_sig_dispatch\n");
285113658Sdeischen}
286113658Sdeischen
287117706Sdavidxu#endif /* ! SYSTEM_SCOPE_ONLY */
288117706Sdavidxu
289117706Sdavidxustatic __inline int
290117706Sdavidxusigprop(int sig)
291117706Sdavidxu{
292117706Sdavidxu
293117706Sdavidxu	if (sig > 0 && sig < NSIG)
294117706Sdavidxu                return (sigproptbl[_SIG_IDX(sig)]);
295117706Sdavidxu        return (0);
296117706Sdavidxu}
297117706Sdavidxu
298120073Sdavidxutypedef void (*ohandler)(int sig, int code,
299120073Sdavidxu	struct sigcontext *scp, char *addr, __sighandler_t *catcher);
300120073Sdavidxu
301113658Sdeischenvoid
302174112Sdeischen_thr_sig_handler(int sig, siginfo_t *info, void *ucp_arg)
303113658Sdeischen{
304139023Sdeischen	struct pthread_sigframe psf;
305115381Sdeischen	__siginfohandler_t *sigfunc;
306117706Sdavidxu	struct pthread *curthread;
307113658Sdeischen	struct kse *curkse;
308174112Sdeischen	ucontext_t *ucp;
309117706Sdavidxu	struct sigaction act;
310139023Sdeischen	int sa_flags, err_save;
311113658Sdeischen
312139023Sdeischen	err_save = errno;
313174112Sdeischen	ucp = (ucontext_t *)ucp_arg;
314139023Sdeischen
315117706Sdavidxu	DBG_MSG(">>> _thr_sig_handler(%d)\n", sig);
316117706Sdavidxu
317117706Sdavidxu	curthread = _get_curthread();
318117706Sdavidxu	if (curthread == NULL)
319117706Sdavidxu		PANIC("No current thread.\n");
320117706Sdavidxu	if (!(curthread->attr.flags & PTHREAD_SCOPE_SYSTEM))
321117706Sdavidxu		PANIC("Thread is not system scope.\n");
322139023Sdeischen	if (curthread->flags & THR_FLAGS_EXITING) {
323139023Sdeischen		errno = err_save;
324117706Sdavidxu		return;
325139023Sdeischen	}
326139023Sdeischen
327117706Sdavidxu	curkse = _get_curkse();
328117706Sdavidxu	/*
329117706Sdavidxu	 * If thread is in critical region or if thread is on
330117706Sdavidxu	 * the way of state transition, then latch signal into buffer.
331117706Sdavidxu	 */
332117706Sdavidxu	if (_kse_in_critical() || THR_IN_CRITICAL(curthread) ||
333139023Sdeischen	    curthread->state != PS_RUNNING) {
334117706Sdavidxu		DBG_MSG(">>> _thr_sig_handler(%d) in critical\n", sig);
335117706Sdavidxu		curthread->siginfo[sig-1] = *info;
336117706Sdavidxu		curthread->check_pending = 1;
337117706Sdavidxu		curkse->k_sigseqno++;
338117706Sdavidxu		SIGADDSET(curthread->sigpend, sig);
339117706Sdavidxu		/*
340117706Sdavidxu		 * If the kse is on the way to idle itself, but
341117706Sdavidxu		 * we have signal ready, we should prevent it
342117706Sdavidxu		 * to sleep, kernel will latch the wakeup request,
343117706Sdavidxu		 * so kse_release will return from kernel immediately.
344117706Sdavidxu		 */
345117706Sdavidxu		if (KSE_IS_IDLE(curkse))
346118510Sdeischen			kse_wakeup(&curkse->k_kcb->kcb_kmbx);
347139023Sdeischen		errno = err_save;
348117706Sdavidxu		return;
349113658Sdeischen	}
350117706Sdavidxu
351132122Sdavidxu	/* Check if the signal requires a dump of thread information: */
352156330Sdeischen	if (_thr_dump_enabled() && (sig == SIGINFO)) {
353132122Sdavidxu		/* Dump thread information to file: */
354132122Sdavidxu		_thread_dump_info();
355132122Sdavidxu	}
356139023Sdeischen
357139023Sdeischen	/* Check the threads previous state: */
358139023Sdeischen	curthread->critical_count++;
359139023Sdeischen	if (curthread->sigbackout != NULL)
360139023Sdeischen		curthread->sigbackout((void *)curthread);
361139023Sdeischen	curthread->critical_count--;
362139023Sdeischen	thr_sigframe_save(curthread, &psf);
363139023Sdeischen	THR_ASSERT(!(curthread->sigbackout), "sigbackout was not cleared.");
364139023Sdeischen
365120079Sdavidxu	_kse_critical_enter();
366120079Sdavidxu	/* Get a fresh copy of signal mask */
367120338Sdavidxu	__sys_sigprocmask(SIG_BLOCK, NULL, &curthread->sigmask);
368117706Sdavidxu	KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
369117706Sdavidxu	sigfunc = _thread_sigact[sig - 1].sa_sigaction;
370123933Sdavidxu	sa_flags = _thread_sigact[sig - 1].sa_flags;
371117706Sdavidxu	if (sa_flags & SA_RESETHAND) {
372117706Sdavidxu		act.sa_handler = SIG_DFL;
373117706Sdavidxu		act.sa_flags = SA_RESTART;
374117706Sdavidxu		SIGEMPTYSET(act.sa_mask);
375117706Sdavidxu		__sys_sigaction(sig, &act, NULL);
376117706Sdavidxu		__sys_sigaction(sig, NULL, &_thread_sigact[sig - 1]);
377117706Sdavidxu	}
378117706Sdavidxu	KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
379118510Sdeischen	_kse_critical_leave(&curthread->tcb->tcb_tmbx);
380117706Sdavidxu
381117706Sdavidxu	/* Now invoke real handler */
382117706Sdavidxu	if (((__sighandler_t *)sigfunc != SIG_DFL) &&
383117706Sdavidxu	    ((__sighandler_t *)sigfunc != SIG_IGN) &&
384117706Sdavidxu	    (sigfunc != (__siginfohandler_t *)_thr_sig_handler)) {
385117706Sdavidxu		if ((sa_flags & SA_SIGINFO) != 0 || info == NULL)
386117706Sdavidxu			(*(sigfunc))(sig, info, ucp);
387120073Sdavidxu		else {
388120073Sdavidxu			((ohandler)(*sigfunc))(
389120073Sdavidxu				sig, info->si_code, (struct sigcontext *)ucp,
390120073Sdavidxu				info->si_addr, (__sighandler_t *)sigfunc);
391120073Sdavidxu		}
392117706Sdavidxu	} else {
393117706Sdavidxu		if ((__sighandler_t *)sigfunc == SIG_DFL) {
394119063Sdavidxu			if (sigprop(sig) & SA_KILL) {
395119063Sdavidxu				if (_kse_isthreaded())
396119063Sdavidxu					kse_thr_interrupt(NULL,
397119063Sdavidxu						 KSE_INTR_SIGEXIT, sig);
398119063Sdavidxu				else
399119063Sdavidxu					kill(getpid(), sig);
400119063Sdavidxu			}
401117706Sdavidxu#ifdef NOTYET
402117706Sdavidxu			else if (sigprop(sig) & SA_STOP)
403117706Sdavidxu				kse_thr_interrupt(NULL, KSE_INTR_JOBSTOP, sig);
404117706Sdavidxu#endif
405117706Sdavidxu		}
406117706Sdavidxu	}
407117706Sdavidxu	_kse_critical_enter();
408117706Sdavidxu	curthread->sigmask = ucp->uc_sigmask;
409120079Sdavidxu	SIG_CANTMASK(curthread->sigmask);
410118510Sdeischen	_kse_critical_leave(&curthread->tcb->tcb_tmbx);
411139023Sdeischen
412139023Sdeischen	thr_sigframe_restore(curthread, &psf);
413139023Sdeischen
414117706Sdavidxu	DBG_MSG("<<< _thr_sig_handler(%d)\n", sig);
415139023Sdeischen
416139023Sdeischen	errno = err_save;
417113658Sdeischen}
418113658Sdeischen
419123974Sdavidxustruct sighandle_info {
420123974Sdavidxu	__siginfohandler_t *sigfunc;
421123974Sdavidxu	int sa_flags;
422123974Sdavidxu	int sig;
423123974Sdavidxu	siginfo_t *info;
424123974Sdavidxu	ucontext_t *ucp;
425123974Sdavidxu};
426123974Sdavidxu
427123974Sdavidxustatic void handle_signal(struct pthread *curthread,
428123974Sdavidxu	struct sighandle_info *shi);
429123974Sdavidxustatic void handle_signal_altstack(struct pthread *curthread,
430123974Sdavidxu	struct sighandle_info *shi);
431123974Sdavidxu
432116977Sdavidxu/* Must be called with signal lock and schedule lock held in order */
433113658Sdeischenstatic void
434113658Sdeischenthr_sig_invoke_handler(struct pthread *curthread, int sig, siginfo_t *info,
435113658Sdeischen    ucontext_t *ucp)
436113658Sdeischen{
437123974Sdavidxu	__siginfohandler_t *sigfunc;
438116977Sdavidxu	sigset_t sigmask;
439116977Sdavidxu	int sa_flags;
440123974Sdavidxu	int onstack;
441116977Sdavidxu	struct sigaction act;
442116977Sdavidxu	struct kse *curkse;
443123974Sdavidxu	struct sighandle_info shi;
444113658Sdeischen
445116977Sdavidxu	/*
446116977Sdavidxu	 * Invoke the signal handler without going through the scheduler:
447113658Sdeischen	 */
448113658Sdeischen	DBG_MSG("Got signal %d, calling handler for current thread %p\n",
449113658Sdeischen	    sig, curthread);
450113658Sdeischen
451116977Sdavidxu	if (!_kse_in_critical())
452116977Sdavidxu		PANIC("thr_sig_invoke_handler without in critical\n");
453139023Sdeischen	curkse = curthread->kse;
45448046Sjb	/*
455113658Sdeischen	 * Check that a custom handler is installed and if
456113658Sdeischen	 * the signal is not blocked:
457113658Sdeischen	 */
458113658Sdeischen	sigfunc = _thread_sigact[sig - 1].sa_sigaction;
459123933Sdavidxu	sa_flags = _thread_sigact[sig - 1].sa_flags;
460116977Sdavidxu	sigmask = curthread->sigmask;
461116977Sdavidxu	SIGSETOR(curthread->sigmask, _thread_sigact[sig - 1].sa_mask);
462116977Sdavidxu	if (!(sa_flags & (SA_NODEFER | SA_RESETHAND)))
463116977Sdavidxu		SIGADDSET(curthread->sigmask, sig);
464116977Sdavidxu	if ((sig != SIGILL) && (sa_flags & SA_RESETHAND)) {
465117706Sdavidxu		act.sa_handler = SIG_DFL;
466117706Sdavidxu		act.sa_flags = SA_RESTART;
467117706Sdavidxu		SIGEMPTYSET(act.sa_mask);
468117706Sdavidxu		__sys_sigaction(sig, &act, NULL);
469117706Sdavidxu		__sys_sigaction(sig, NULL, &_thread_sigact[sig - 1]);
470116977Sdavidxu	}
471116977Sdavidxu	KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
472116977Sdavidxu	KSE_SCHED_UNLOCK(curkse, curkse->k_kseg);
473117706Sdavidxu	/*
474117706Sdavidxu	 * We are processing buffered signals, synchronize working
475117706Sdavidxu	 * signal mask into kernel.
476117706Sdavidxu	 */
477117706Sdavidxu	if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
478117706Sdavidxu		__sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL);
479123974Sdavidxu	onstack = _thr_sigonstack(&sigfunc);
480123974Sdavidxu	ucp->uc_stack = curthread->sigstk;
481123974Sdavidxu	ucp->uc_stack.ss_flags = (curthread->sigstk.ss_flags & SS_DISABLE)
482123974Sdavidxu		? SS_DISABLE : ((onstack) ? SS_ONSTACK : 0);
483130374Sdavidxu	if (curthread->oldsigmask) {
484130374Sdavidxu		ucp->uc_sigmask = *(curthread->oldsigmask);
485130374Sdavidxu		curthread->oldsigmask = NULL;
486130374Sdavidxu	} else
487130374Sdavidxu		ucp->uc_sigmask = sigmask;
488123974Sdavidxu	shi.sigfunc = sigfunc;
489123974Sdavidxu	shi.sig = sig;
490124055Sdavidxu	shi.sa_flags = sa_flags;
491123974Sdavidxu	shi.info = info;
492123974Sdavidxu	shi.ucp = ucp;
493124095Sdavidxu	if ((curthread->sigstk.ss_flags & SS_DISABLE) == 0) {
494123974Sdavidxu		/* Deliver signal on alternative stack */
495123974Sdavidxu		if (sa_flags & SA_ONSTACK && !onstack)
496123974Sdavidxu			handle_signal_altstack(curthread, &shi);
497123974Sdavidxu		else
498123974Sdavidxu			handle_signal(curthread, &shi);
499116977Sdavidxu	} else {
500123974Sdavidxu		handle_signal(curthread, &shi);
50167097Sdeischen	}
502117706Sdavidxu
503116977Sdavidxu	_kse_critical_enter();
504116977Sdavidxu	/* Don't trust after critical leave/enter */
505139023Sdeischen	curkse = curthread->kse;
506117706Sdavidxu
507113658Sdeischen	/*
508113658Sdeischen	 * Restore the thread's signal mask.
509113658Sdeischen	 */
510116977Sdavidxu	curthread->sigmask = ucp->uc_sigmask;
511120079Sdavidxu	SIG_CANTMASK(curthread->sigmask);
512117706Sdavidxu	if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
513117706Sdavidxu		__sys_sigprocmask(SIG_SETMASK, &ucp->uc_sigmask, NULL);
514117706Sdavidxu	KSE_SCHED_LOCK(curkse, curkse->k_kseg);
515117706Sdavidxu	KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
516117706Sdavidxu
517116977Sdavidxu	DBG_MSG("Got signal %d, handler returned %p\n", sig, curthread);
51848046Sjb}
51948046Sjb
520123974Sdavidxustatic void
521123974Sdavidxuhandle_signal(struct pthread *curthread, struct sighandle_info *shi)
522123974Sdavidxu{
523123974Sdavidxu	_kse_critical_leave(&curthread->tcb->tcb_tmbx);
524123974Sdavidxu
525132122Sdavidxu	/* Check if the signal requires a dump of thread information: */
526156330Sdeischen	if (_thr_dump_enabled() && (shi->sig == SIGINFO)) {
527132122Sdavidxu		/* Dump thread information to file: */
528132122Sdavidxu		_thread_dump_info();
529132122Sdavidxu	}
530132122Sdavidxu
531123974Sdavidxu	if (((__sighandler_t *)shi->sigfunc != SIG_DFL) &&
532123974Sdavidxu	    ((__sighandler_t *)shi->sigfunc != SIG_IGN)) {
533123974Sdavidxu		if ((shi->sa_flags & SA_SIGINFO) != 0 || shi->info == NULL)
534123974Sdavidxu			(*(shi->sigfunc))(shi->sig, shi->info, shi->ucp);
535123974Sdavidxu		else {
536123974Sdavidxu			((ohandler)(*shi->sigfunc))(
537123974Sdavidxu				shi->sig, shi->info->si_code,
538123974Sdavidxu				(struct sigcontext *)shi->ucp,
539123974Sdavidxu				shi->info->si_addr,
540123974Sdavidxu				(__sighandler_t *)shi->sigfunc);
541123974Sdavidxu		}
542123974Sdavidxu	} else {
543123974Sdavidxu		if ((__sighandler_t *)shi->sigfunc == SIG_DFL) {
544123974Sdavidxu			if (sigprop(shi->sig) & SA_KILL) {
545123974Sdavidxu				if (_kse_isthreaded())
546123974Sdavidxu					kse_thr_interrupt(NULL,
547123974Sdavidxu						 KSE_INTR_SIGEXIT, shi->sig);
548123974Sdavidxu				else
549123974Sdavidxu					kill(getpid(), shi->sig);
550123974Sdavidxu			}
551123974Sdavidxu#ifdef NOTYET
552123974Sdavidxu			else if (sigprop(shi->sig) & SA_STOP)
553123974Sdavidxu				kse_thr_interrupt(NULL, KSE_INTR_JOBSTOP,
554123974Sdavidxu					shi->sig);
555123974Sdavidxu#endif
556123974Sdavidxu		}
557123974Sdavidxu	}
558123974Sdavidxu}
559123974Sdavidxu
560123974Sdavidxustatic void
561123974Sdavidxuhandle_signal_wrapper(struct pthread *curthread, ucontext_t *ret_uc,
562123974Sdavidxu	struct sighandle_info *shi)
563123974Sdavidxu{
564123974Sdavidxu	shi->ucp->uc_stack.ss_flags = SS_ONSTACK;
565123974Sdavidxu	handle_signal(curthread, shi);
566123974Sdavidxu	if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
567123974Sdavidxu		setcontext(ret_uc);
568123974Sdavidxu	else {
569123974Sdavidxu		/* Work around for ia64, THR_SETCONTEXT does not work */
570123974Sdavidxu		_kse_critical_enter();
571123974Sdavidxu        	curthread->tcb->tcb_tmbx.tm_context = *ret_uc;
572123974Sdavidxu        	_thread_switch(curthread->kse->k_kcb, curthread->tcb, 1);
573123974Sdavidxu		/* THR_SETCONTEXT */
574123974Sdavidxu	}
575123974Sdavidxu}
576123974Sdavidxu
577123974Sdavidxu/*
578123974Sdavidxu * Jump to stack set by sigaltstack before invoking signal handler
579123974Sdavidxu */
580123974Sdavidxustatic void
581123974Sdavidxuhandle_signal_altstack(struct pthread *curthread, struct sighandle_info *shi)
582123974Sdavidxu{
583123974Sdavidxu	volatile int once;
584123974Sdavidxu	ucontext_t uc1, *uc2;
585123974Sdavidxu
586123974Sdavidxu	THR_ASSERT(_kse_in_critical(), "Not in critical");
587123974Sdavidxu
588123974Sdavidxu	once = 0;
589123974Sdavidxu	THR_GETCONTEXT(&uc1);
590123974Sdavidxu	if (once == 0) {
591123974Sdavidxu		once = 1;
592123974Sdavidxu		/* XXX
593123974Sdavidxu		 * We are still in critical region, it is safe to operate thread
594123974Sdavidxu		 * context
595123974Sdavidxu		 */
596123974Sdavidxu		uc2 = &curthread->tcb->tcb_tmbx.tm_context;
597123974Sdavidxu		uc2->uc_stack = curthread->sigstk;
598123974Sdavidxu		makecontext(uc2, (void (*)(void))handle_signal_wrapper,
599123974Sdavidxu			3, curthread, &uc1, shi);
600123974Sdavidxu		if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
601123974Sdavidxu			setcontext(uc2);
602123974Sdavidxu		else {
603123974Sdavidxu			_thread_switch(curthread->kse->k_kcb, curthread->tcb, 1);
604123974Sdavidxu			/* THR_SETCONTEXT(uc2); */
605123974Sdavidxu		}
606123974Sdavidxu	}
607123974Sdavidxu}
608123974Sdavidxu
609116977Sdavidxuint
610116977Sdavidxu_thr_getprocsig(int sig, siginfo_t *siginfo)
611116977Sdavidxu{
612116977Sdavidxu	kse_critical_t crit;
613116977Sdavidxu	struct kse *curkse;
614116977Sdavidxu	int ret;
615116977Sdavidxu
616116977Sdavidxu	DBG_MSG(">>> _thr_getprocsig\n");
617116977Sdavidxu
618116977Sdavidxu	crit = _kse_critical_enter();
619116977Sdavidxu	curkse = _get_curkse();
620116977Sdavidxu	KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
621116977Sdavidxu	ret = _thr_getprocsig_unlocked(sig, siginfo);
622116977Sdavidxu	KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
623116977Sdavidxu	_kse_critical_leave(crit);
624116977Sdavidxu
625116977Sdavidxu	DBG_MSG("<<< _thr_getprocsig\n");
626116977Sdavidxu	return (ret);
627116977Sdavidxu}
628116977Sdavidxu
629116977Sdavidxuint
630116977Sdavidxu_thr_getprocsig_unlocked(int sig, siginfo_t *siginfo)
631116977Sdavidxu{
632116977Sdavidxu	sigset_t sigset;
633116977Sdavidxu	struct timespec ts;
634116977Sdavidxu
635116977Sdavidxu	/* try to retrieve signal from kernel */
636116977Sdavidxu	SIGEMPTYSET(sigset);
637116977Sdavidxu	SIGADDSET(sigset, sig);
638116977Sdavidxu	ts.tv_sec = 0;
639116977Sdavidxu	ts.tv_nsec = 0;
640117706Sdavidxu	SIGDELSET(_thr_proc_sigpending, sig);
641117706Sdavidxu	if (__sys_sigtimedwait(&sigset, siginfo, &ts) > 0)
642116977Sdavidxu		return (sig);
643116977Sdavidxu	return (0);
644116977Sdavidxu}
645116977Sdavidxu
646117706Sdavidxu#ifndef SYSTEM_SCOPE_ONLY
64767097Sdeischen/*
648113658Sdeischen * Find a thread that can handle the signal.  This must be called
649113658Sdeischen * with upcalls disabled.
65067097Sdeischen */
651113658Sdeischenstruct pthread *
652174112Sdeischenthr_sig_find(struct kse *curkse, int sig, siginfo_t *info __unused)
65348046Sjb{
654117907Sdeischen	struct kse_mailbox *kmbx = NULL;
655114180Sdeischen	struct pthread	*pthread;
65690431Sdeischen	struct pthread	*suspended_thread, *signaled_thread;
657117706Sdavidxu	__siginfohandler_t *sigfunc;
658116977Sdavidxu	siginfo_t si;
65948046Sjb
66067097Sdeischen	DBG_MSG("Looking for thread to handle signal %d\n", sig);
661113658Sdeischen
662111035Smini	/*
663111035Smini	 * Enter a loop to look for threads that have the signal
664111035Smini	 * unmasked.  POSIX specifies that a thread in a sigwait
665111035Smini	 * will get the signal over any other threads.  Second
666177626Sbrueffer	 * preference will be threads in a sigsuspend.  Third
667111035Smini	 * preference will be the current thread.  If none of the
668111035Smini	 * above, then the signal is delivered to the first thread
669111035Smini	 * that is found.  Note that if a custom handler is not
670111035Smini	 * installed, the signal only affects threads in sigwait.
671111035Smini	 */
672111035Smini	suspended_thread = NULL;
673113658Sdeischen	signaled_thread = NULL;
674111035Smini
675113658Sdeischen	KSE_LOCK_ACQUIRE(curkse, &_thread_list_lock);
676114180Sdeischen	TAILQ_FOREACH(pthread, &_thread_list, tle) {
677116977Sdavidxu		if (pthread == _thr_sig_daemon)
678116977Sdavidxu			continue;
679116977Sdavidxu		/* Signal delivering to bound thread is done by kernel */
680116977Sdavidxu		if (pthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
681116977Sdavidxu			continue;
682114254Sdeischen		/* Take the scheduling lock. */
683114254Sdeischen		KSE_SCHED_LOCK(curkse, pthread->kseg);
684116977Sdavidxu		if ((pthread->state == PS_DEAD)		||
685116977Sdavidxu		    (pthread->state == PS_DEADLOCK)	||
686116977Sdavidxu		    THR_IS_EXITING(pthread)		||
687117353Sdavidxu		    THR_IS_SUSPENDED(pthread)) {
688116977Sdavidxu			; /* Skip this thread. */
689117353Sdavidxu		} else if (pthread->state == PS_SIGWAIT &&
690118075Sdavidxu			   SIGISMEMBER(*(pthread->data.sigwait->waitset), sig)) {
69148046Sjb			/*
692116977Sdavidxu			 * retrieve signal from kernel, if it is job control
693116977Sdavidxu			 * signal, and sigaction is SIG_DFL, then we will
694116977Sdavidxu			 * be stopped in kernel, we hold lock here, but that
695116977Sdavidxu			 * does not matter, because that's job control, and
696116977Sdavidxu			 * whole process should be stopped.
69748046Sjb			 */
698116977Sdavidxu			if (_thr_getprocsig(sig, &si)) {
699116977Sdavidxu				DBG_MSG("Waking thread %p in sigwait"
700116977Sdavidxu					" with signal %d\n", pthread, sig);
701116977Sdavidxu				/*  where to put siginfo ? */
702118075Sdavidxu				*(pthread->data.sigwait->siginfo) = si;
703117907Sdeischen				kmbx = _thr_setrunnable_unlocked(pthread);
704116977Sdavidxu			}
705113658Sdeischen			KSE_SCHED_UNLOCK(curkse, pthread->kseg);
706111035Smini			/*
707111035Smini			 * POSIX doesn't doesn't specify which thread
708111035Smini			 * will get the signal if there are multiple
709111035Smini			 * waiters, so we give it to the first thread
710111035Smini			 * we find.
711111035Smini			 *
712111035Smini			 * Do not attempt to deliver this signal
713111035Smini			 * to other threads and do not add the signal
714111035Smini			 * to the process pending set.
715111035Smini			 */
716113658Sdeischen			KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
717117907Sdeischen			if (kmbx != NULL)
718117907Sdeischen				kse_wakeup(kmbx);
719136735Sdavidxu			if (suspended_thread != NULL)
720136735Sdavidxu				_thr_ref_delete(NULL, suspended_thread);
721136735Sdavidxu			if (signaled_thread != NULL)
722136735Sdavidxu				_thr_ref_delete(NULL, signaled_thread);
723111035Smini			return (NULL);
724118075Sdavidxu		} else if (!SIGISMEMBER(pthread->sigmask, sig)) {
725132122Sdavidxu			/*
726132122Sdavidxu			 * If debugger is running, we don't quick exit,
727132122Sdavidxu			 * and give it a chance to check the signal.
728132122Sdavidxu			 */
729132122Sdavidxu			if (_libkse_debug == 0) {
730132122Sdavidxu				sigfunc = _thread_sigact[sig - 1].sa_sigaction;
731132122Sdavidxu				if ((__sighandler_t *)sigfunc == SIG_DFL) {
732132122Sdavidxu					if (sigprop(sig) & SA_KILL) {
733132122Sdavidxu						kse_thr_interrupt(NULL,
734132122Sdavidxu							 KSE_INTR_SIGEXIT, sig);
735132122Sdavidxu						/* Never reach */
736132122Sdavidxu					}
737117706Sdavidxu				}
738117706Sdavidxu			}
739111035Smini			if (pthread->state == PS_SIGSUSPEND) {
740115278Sdeischen				if (suspended_thread == NULL) {
741111035Smini					suspended_thread = pthread;
742115278Sdeischen					suspended_thread->refcount++;
743115278Sdeischen				}
744115278Sdeischen			} else if (signaled_thread == NULL) {
745111035Smini				signaled_thread = pthread;
746115278Sdeischen				signaled_thread->refcount++;
747116977Sdavidxu			}
748111035Smini		}
749114254Sdeischen		KSE_SCHED_UNLOCK(curkse, pthread->kseg);
750111035Smini	}
751113658Sdeischen	KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
75239805Sjb
753116977Sdavidxu	if (suspended_thread != NULL) {
754116977Sdavidxu		pthread = suspended_thread;
755116977Sdavidxu		if (signaled_thread)
756116977Sdavidxu			_thr_ref_delete(NULL, signaled_thread);
757116977Sdavidxu	} else if (signaled_thread) {
758116977Sdavidxu		pthread = signaled_thread;
759113658Sdeischen	} else {
760116977Sdavidxu		pthread = NULL;
761111035Smini	}
762116977Sdavidxu	return (pthread);
76335509Sjb}
764117706Sdavidxu#endif /* ! SYSTEM_SCOPE_ONLY */
76535509Sjb
766139023Sdeischenstatic inline void
767113658Sdeischenbuild_siginfo(siginfo_t *info, int signo)
768113658Sdeischen{
769113658Sdeischen	bzero(info, sizeof(*info));
770113658Sdeischen	info->si_signo = signo;
771113658Sdeischen	info->si_pid = _thr_pid;
772113658Sdeischen}
773113658Sdeischen
774113658Sdeischen/*
775113658Sdeischen * This is called by a thread when it has pending signals to deliver.
776113658Sdeischen * It should only be called from the context of the thread.
777113658Sdeischen */
77867097Sdeischenvoid
779139023Sdeischen_thr_sig_rundown(struct pthread *curthread, ucontext_t *ucp)
78056277Sjasone{
781139023Sdeischen	struct pthread_sigframe psf;
782116977Sdavidxu	siginfo_t siginfo;
783139023Sdeischen	int i, err_save;
784116977Sdavidxu	kse_critical_t crit;
785116977Sdavidxu	struct kse *curkse;
786117706Sdavidxu	sigset_t sigmask;
78767097Sdeischen
788139023Sdeischen	err_save = errno;
789139023Sdeischen
790117706Sdavidxu	DBG_MSG(">>> thr_sig_rundown (%p)\n", curthread);
791139023Sdeischen
792113658Sdeischen	/* Check the threads previous state: */
793139023Sdeischen	curthread->critical_count++;
794139023Sdeischen	if (curthread->sigbackout != NULL)
795139023Sdeischen		curthread->sigbackout((void *)curthread);
796139023Sdeischen	curthread->critical_count--;
797116977Sdavidxu
798139023Sdeischen	THR_ASSERT(!(curthread->sigbackout), "sigbackout was not cleared.");
799139023Sdeischen	THR_ASSERT((curthread->state == PS_RUNNING), "state is not PS_RUNNING");
800116977Sdavidxu
801139023Sdeischen	thr_sigframe_save(curthread, &psf);
80256277Sjasone	/*
803113658Sdeischen	 * Lower the priority before calling the handler in case
804113658Sdeischen	 * it never returns (longjmps back):
80556277Sjasone	 */
806116977Sdavidxu	crit = _kse_critical_enter();
807139023Sdeischen	curkse = curthread->kse;
808116977Sdavidxu	KSE_SCHED_LOCK(curkse, curkse->k_kseg);
809116977Sdavidxu	KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
810113658Sdeischen	curthread->active_priority &= ~THR_SIGNAL_PRIORITY;
811119249Sdavidxu	SIGFILLSET(sigmask);
812116977Sdavidxu	while (1) {
813117706Sdavidxu		/*
814117706Sdavidxu		 * For bound thread, we mask all signals and get a fresh
815117706Sdavidxu		 * copy of signal mask from kernel
816117706Sdavidxu		 */
817117706Sdavidxu		if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
818117706Sdavidxu			__sys_sigprocmask(SIG_SETMASK, &sigmask,
819117706Sdavidxu				 &curthread->sigmask);
820117706Sdavidxu		}
821116977Sdavidxu		for (i = 1; i <= _SIG_MAXSIG; i++) {
822116977Sdavidxu			if (SIGISMEMBER(curthread->sigmask, i))
823116977Sdavidxu				continue;
824116977Sdavidxu			if (SIGISMEMBER(curthread->sigpend, i)) {
825116977Sdavidxu				SIGDELSET(curthread->sigpend, i);
826117066Sdavidxu				siginfo = curthread->siginfo[i-1];
827116977Sdavidxu				break;
828116977Sdavidxu			}
829117706Sdavidxu			if (!(curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
830117706Sdavidxu			    && SIGISMEMBER(_thr_proc_sigpending, i)) {
831116977Sdavidxu				if (_thr_getprocsig_unlocked(i, &siginfo))
832116977Sdavidxu					break;
833116977Sdavidxu			}
83467097Sdeischen		}
835116977Sdavidxu		if (i <= _SIG_MAXSIG)
836116977Sdavidxu			thr_sig_invoke_handler(curthread, i, &siginfo, ucp);
837119249Sdavidxu		else {
838119249Sdavidxu			if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
839119249Sdavidxu				__sys_sigprocmask(SIG_SETMASK,
840119249Sdavidxu						 &curthread->sigmask, NULL);
841119249Sdavidxu			}
842116977Sdavidxu			break;
843119249Sdavidxu		}
84456277Sjasone	}
845113658Sdeischen
846139023Sdeischen	/* Don't trust after signal handling */
847139023Sdeischen	curkse = curthread->kse;
848116977Sdavidxu	KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
849116977Sdavidxu	KSE_SCHED_UNLOCK(curkse, curkse->k_kseg);
850119249Sdavidxu	_kse_critical_leave(&curthread->tcb->tcb_tmbx);
851119249Sdavidxu	/* repost masked signal to kernel, it hardly happens in real world */
852119249Sdavidxu	if ((curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) &&
853119249Sdavidxu	    !SIGISEMPTY(curthread->sigpend)) { /* dirty read */
854119249Sdavidxu		__sys_sigprocmask(SIG_SETMASK, &sigmask, &curthread->sigmask);
855119249Sdavidxu		for (i = 1; i <= _SIG_MAXSIG; ++i) {
856119249Sdavidxu			if (SIGISMEMBER(curthread->sigpend, i)) {
857119249Sdavidxu				SIGDELSET(curthread->sigpend, i);
858119249Sdavidxu				if (!_kse_isthreaded())
859119249Sdavidxu					kill(getpid(), i);
860119249Sdavidxu				else
861119249Sdavidxu					kse_thr_interrupt(
862119249Sdavidxu						&curthread->tcb->tcb_tmbx,
863119249Sdavidxu						KSE_INTR_SENDSIG,
864119249Sdavidxu						i);
865119249Sdavidxu			}
866119249Sdavidxu		}
867117706Sdavidxu		__sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL);
868119249Sdavidxu	}
869139023Sdeischen	DBG_MSG("<<< thr_sig_rundown (%p)\n", curthread);
870117353Sdavidxu
871139023Sdeischen	thr_sigframe_restore(curthread, &psf);
872139023Sdeischen	errno = err_save;
87367097Sdeischen}
87467097Sdeischen
87567097Sdeischen/*
876113658Sdeischen * This checks pending signals for the current thread.  It should be
877113658Sdeischen * called whenever a thread changes its signal mask.  Note that this
878113658Sdeischen * is called from a thread (using its stack).
879113658Sdeischen *
880113658Sdeischen * XXX - We might want to just check to see if there are pending
881113658Sdeischen *       signals for the thread here, but enter the UTS scheduler
882113658Sdeischen *       to actually install the signal handler(s).
88367097Sdeischen */
88467097Sdeischenvoid
885113658Sdeischen_thr_sig_check_pending(struct pthread *curthread)
88667097Sdeischen{
887116977Sdavidxu	ucontext_t uc;
888116977Sdavidxu	volatile int once;
889119177Sdavidxu	int errsave;
89067097Sdeischen
891139023Sdeischen	/*
892139023Sdeischen	 * If the thread is in critical region, delay processing signals.
893139023Sdeischen	 * If the thread state is not PS_RUNNING, it might be switching
894139023Sdeischen	 * into UTS and but a THR_LOCK_RELEASE saw check_pending, and it
895139023Sdeischen	 * goes here, in the case we delay processing signals, lets UTS
896139023Sdeischen	 * process complicated things, normally UTS will call _thr_sig_add
897139023Sdeischen	 * to resume the thread, so we needn't repeat doing it here.
898139023Sdeischen	 */
899139023Sdeischen	if (THR_IN_CRITICAL(curthread) || curthread->state != PS_RUNNING)
900116977Sdavidxu		return;
901113658Sdeischen
902119177Sdavidxu	errsave = errno;
903116977Sdavidxu	once = 0;
904116977Sdavidxu	THR_GETCONTEXT(&uc);
905116977Sdavidxu	if (once == 0) {
906116977Sdavidxu		once = 1;
907113658Sdeischen		curthread->check_pending = 0;
908139023Sdeischen		_thr_sig_rundown(curthread, &uc);
90956277Sjasone	}
910119177Sdavidxu	errno = errsave;
91156277Sjasone}
91256277Sjasone
913111035Smini/*
91467097Sdeischen * Perform thread specific actions in response to a signal.
91567097Sdeischen * This function is only called if there is a handler installed
91667097Sdeischen * for the signal, and if the target thread has the signal
91767097Sdeischen * unmasked.
918113658Sdeischen *
919113658Sdeischen * This must be called with the thread's scheduling lock held.
92067097Sdeischen */
921117907Sdeischenstruct kse_mailbox *
922115080Sdeischen_thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info)
92335509Sjb{
924117907Sdeischen	siginfo_t siginfo;
925117907Sdeischen	struct kse *curkse;
926117907Sdeischen	struct kse_mailbox *kmbx = NULL;
927117907Sdeischen	struct pthread *curthread = _get_curthread();
928113658Sdeischen	int	restart;
92967097Sdeischen	int	suppress_handler = 0;
930116977Sdavidxu	int	fromproc = 0;
931118748Sdavidxu	__sighandler_t *sigfunc;
93267097Sdeischen
933117706Sdavidxu	DBG_MSG(">>> _thr_sig_add %p (%d)\n", pthread, sig);
934116977Sdavidxu
935116977Sdavidxu	curkse = _get_curkse();
936116977Sdavidxu	restart = _thread_sigact[sig - 1].sa_flags & SA_RESTART;
937118748Sdavidxu	sigfunc = _thread_sigact[sig - 1].sa_handler;
938116977Sdavidxu	fromproc = (curthread == _thr_sig_daemon);
939116977Sdavidxu
940116977Sdavidxu	if (pthread->state == PS_DEAD || pthread->state == PS_DEADLOCK ||
941116977Sdavidxu	    pthread->state == PS_STATE_MAX)
942117907Sdeischen	    	return (NULL); /* return false */
943116977Sdavidxu
944117706Sdavidxu	if ((pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) &&
945117706Sdavidxu	    (curthread != pthread)) {
946117706Sdavidxu	    	PANIC("Please use _thr_send_sig for bound thread");
947117907Sdeischen		return (NULL);
948115080Sdeischen	}
949116977Sdavidxu
950139023Sdeischen	if (pthread->state != PS_SIGWAIT &&
951139023Sdeischen	    SIGISMEMBER(pthread->sigmask, sig)) {
952139023Sdeischen		/* signal is masked, just add signal to thread. */
953116977Sdavidxu		if (!fromproc) {
954116977Sdavidxu			SIGADDSET(pthread->sigpend, sig);
955116977Sdavidxu			if (info == NULL)
956117066Sdavidxu				build_siginfo(&pthread->siginfo[sig-1], sig);
957117066Sdavidxu			else if (info != &pthread->siginfo[sig-1])
958117066Sdavidxu				memcpy(&pthread->siginfo[sig-1], info,
959116977Sdavidxu					 sizeof(*info));
960116977Sdavidxu		} else {
961117066Sdavidxu			if (!_thr_getprocsig(sig, &pthread->siginfo[sig-1]))
962117907Sdeischen				return (NULL);
963116977Sdavidxu			SIGADDSET(pthread->sigpend, sig);
964116977Sdavidxu		}
965116977Sdavidxu	}
966115080Sdeischen	else {
967116977Sdavidxu		/* if process signal not exists, just return */
968116977Sdavidxu		if (fromproc) {
969116977Sdavidxu			if (!_thr_getprocsig(sig, &siginfo))
970117907Sdeischen				return (NULL);
971116977Sdavidxu			info = &siginfo;
972116977Sdavidxu		}
973118748Sdavidxu
974118748Sdavidxu		if (pthread->state != PS_SIGWAIT && sigfunc == SIG_DFL &&
975118748Sdavidxu		    (sigprop(sig) & SA_KILL)) {
976118748Sdavidxu			kse_thr_interrupt(NULL, KSE_INTR_SIGEXIT, sig);
977118748Sdavidxu			/* Never reach */
978118748Sdavidxu		}
979118748Sdavidxu
98067097Sdeischen		/*
981115080Sdeischen		 * Process according to thread state:
98267097Sdeischen		 */
983115080Sdeischen		switch (pthread->state) {
984115080Sdeischen		case PS_DEAD:
985115080Sdeischen		case PS_DEADLOCK:
986116977Sdavidxu		case PS_STATE_MAX:
987117907Sdeischen			return (NULL);	/* XXX return false */
988115080Sdeischen		case PS_LOCKWAIT:
989115080Sdeischen		case PS_SUSPENDED:
99067097Sdeischen			/*
991115080Sdeischen			 * You can't call a signal handler for threads in these
992115080Sdeischen			 * states.
99367097Sdeischen			 */
994113658Sdeischen			suppress_handler = 1;
995115080Sdeischen			break;
996115080Sdeischen		case PS_RUNNING:
997116977Sdavidxu			if ((pthread->flags & THR_FLAGS_IN_RUNQ)) {
998115080Sdeischen				THR_RUNQ_REMOVE(pthread);
999116977Sdavidxu				pthread->active_priority |= THR_SIGNAL_PRIORITY;
1000116977Sdavidxu				THR_RUNQ_INSERT_TAIL(pthread);
1001116977Sdavidxu			} else {
1002116977Sdavidxu				/* Possible not in RUNQ and has curframe ? */
1003116977Sdavidxu				pthread->active_priority |= THR_SIGNAL_PRIORITY;
1004116977Sdavidxu			}
1005115080Sdeischen			break;
100639805Sjb		/*
1007115080Sdeischen		 * States which cannot be interrupted but still require the
1008115080Sdeischen		 * signal handler to run:
100939805Sjb		 */
1010115080Sdeischen		case PS_COND_WAIT:
1011115080Sdeischen		case PS_MUTEX_WAIT:
1012115080Sdeischen			break;
101339805Sjb
1014115080Sdeischen		case PS_SLEEP_WAIT:
1015115080Sdeischen			/*
1016115080Sdeischen			 * Unmasked signals always cause sleep to terminate
1017115080Sdeischen			 * early regardless of SA_RESTART:
1018115080Sdeischen			 */
1019115080Sdeischen			pthread->interrupted = 1;
1020115080Sdeischen			break;
1021113658Sdeischen
1022115080Sdeischen		case PS_JOIN:
1023116977Sdavidxu			break;
1024116977Sdavidxu
1025115080Sdeischen		case PS_SIGSUSPEND:
1026116977Sdavidxu			pthread->interrupted = 1;
1027115080Sdeischen			break;
1028113658Sdeischen
1029115080Sdeischen		case PS_SIGWAIT:
1030116977Sdavidxu			if (info == NULL)
1031117066Sdavidxu				build_siginfo(&pthread->siginfo[sig-1], sig);
1032117066Sdavidxu			else if (info != &pthread->siginfo[sig-1])
1033117066Sdavidxu				memcpy(&pthread->siginfo[sig-1], info,
1034116977Sdavidxu					sizeof(*info));
1035113658Sdeischen			/*
1036115080Sdeischen			 * The signal handler is not called for threads in
1037115080Sdeischen			 * SIGWAIT.
1038113658Sdeischen			 */
1039115080Sdeischen			suppress_handler = 1;
1040116977Sdavidxu			/* Wake up the thread if the signal is not blocked. */
1041118075Sdavidxu			if (SIGISMEMBER(*(pthread->data.sigwait->waitset), sig)) {
1042115080Sdeischen				/* Return the signal number: */
1043118075Sdavidxu				*(pthread->data.sigwait->siginfo) = pthread->siginfo[sig-1];
1044115080Sdeischen				/* Make the thread runnable: */
1045117907Sdeischen				kmbx = _thr_setrunnable_unlocked(pthread);
1046116977Sdavidxu			} else {
1047115080Sdeischen				/* Increment the pending signal count. */
1048116977Sdavidxu				SIGADDSET(pthread->sigpend, sig);
1049118075Sdavidxu				if (!SIGISMEMBER(pthread->sigmask, sig)) {
1050118748Sdavidxu					if (sigfunc == SIG_DFL &&
1051118748Sdavidxu					    sigprop(sig) & SA_KILL) {
1052118748Sdavidxu						kse_thr_interrupt(NULL,
1053118748Sdavidxu							 KSE_INTR_SIGEXIT,
1054118748Sdavidxu							 sig);
1055118748Sdavidxu						/* Never reach */
1056118748Sdavidxu					}
1057117366Sdavidxu					pthread->check_pending = 1;
1058117366Sdavidxu					pthread->interrupted = 1;
1059117907Sdeischen					kmbx = _thr_setrunnable_unlocked(pthread);
1060117366Sdavidxu				}
1061116977Sdavidxu			}
1062117907Sdeischen			return (kmbx);
1063115080Sdeischen		}
1064115080Sdeischen
1065116977Sdavidxu		SIGADDSET(pthread->sigpend, sig);
1066116977Sdavidxu		if (info == NULL)
1067117066Sdavidxu			build_siginfo(&pthread->siginfo[sig-1], sig);
1068117066Sdavidxu		else if (info != &pthread->siginfo[sig-1])
1069117066Sdavidxu			memcpy(&pthread->siginfo[sig-1], info, sizeof(*info));
1070139023Sdeischen		pthread->check_pending = 1;
1071139023Sdeischen		if (!(pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) &&
1072139023Sdeischen		    (pthread->blocked != 0) && !THR_IN_CRITICAL(pthread))
1073139023Sdeischen			kse_thr_interrupt(&pthread->tcb->tcb_tmbx,
1074139023Sdeischen			    restart ? KSE_INTR_RESTART : KSE_INTR_INTERRUPT, 0);
1075115080Sdeischen		if (suppress_handler == 0) {
1076113658Sdeischen			/*
1077113658Sdeischen			 * Setup a signal frame and save the current threads
1078113658Sdeischen			 * state:
1079113658Sdeischen			 */
1080139023Sdeischen			if (pthread->state != PS_RUNNING) {
1081139023Sdeischen				if (pthread->flags & THR_FLAGS_IN_RUNQ)
1082139023Sdeischen					THR_RUNQ_REMOVE(pthread);
1083139023Sdeischen				pthread->active_priority |= THR_SIGNAL_PRIORITY;
1084139023Sdeischen				kmbx = _thr_setrunnable_unlocked(pthread);
1085139023Sdeischen			}
1086115080Sdeischen		}
108767097Sdeischen	}
1088117907Sdeischen	return (kmbx);
108935509Sjb}
109013546Sjulian
109167097Sdeischen/*
109267097Sdeischen * Send a signal to a specific thread (ala pthread_kill):
109367097Sdeischen */
109454707Sdeischenvoid
1095113658Sdeischen_thr_sig_send(struct pthread *pthread, int sig)
109654707Sdeischen{
1097113658Sdeischen	struct pthread *curthread = _get_curthread();
1098117907Sdeischen	struct kse_mailbox *kmbx;
109971581Sdeischen
1100117706Sdavidxu	if (pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
1101118510Sdeischen		kse_thr_interrupt(&pthread->tcb->tcb_tmbx, KSE_INTR_SENDSIG, sig);
1102116977Sdavidxu		return;
1103116977Sdavidxu	}
1104117706Sdavidxu
1105113658Sdeischen	/* Lock the scheduling queue of the target thread. */
1106113658Sdeischen	THR_SCHED_LOCK(curthread, pthread);
1107117706Sdavidxu	if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) {
1108117907Sdeischen		kmbx = _thr_sig_add(pthread, sig, NULL);
1109139023Sdeischen		/* Add a preemption point. */
1110139023Sdeischen		if (kmbx == NULL && (curthread->kseg == pthread->kseg) &&
1111139023Sdeischen		    (pthread->active_priority > curthread->active_priority))
1112139023Sdeischen			curthread->critical_yield = 1;
1113116977Sdavidxu		THR_SCHED_UNLOCK(curthread, pthread);
1114117907Sdeischen		if (kmbx != NULL)
1115117907Sdeischen			kse_wakeup(kmbx);
1116116977Sdavidxu		/* XXX
1117116977Sdavidxu		 * If thread sent signal to itself, check signals now.
1118116977Sdavidxu		 * It is not really needed, _kse_critical_leave should
1119116977Sdavidxu		 * have already checked signals.
1120116977Sdavidxu		 */
1121116977Sdavidxu		if (pthread == curthread && curthread->check_pending)
1122116977Sdavidxu			_thr_sig_check_pending(curthread);
1123139023Sdeischen
1124116977Sdavidxu	} else  {
1125116977Sdavidxu		THR_SCHED_UNLOCK(curthread, pthread);
112654707Sdeischen	}
112754707Sdeischen}
112854707Sdeischen
1129139023Sdeischenstatic inline void
1130139023Sdeischenthr_sigframe_restore(struct pthread *curthread, struct pthread_sigframe *psf)
113135509Sjb{
1132139023Sdeischen	kse_critical_t crit;
1133139023Sdeischen	struct kse *curkse;
113413546Sjulian
1135139023Sdeischen	THR_THREAD_LOCK(curthread, curthread);
1136139023Sdeischen	curthread->cancelflags = psf->psf_cancelflags;
1137139023Sdeischen	crit = _kse_critical_enter();
1138139023Sdeischen	curkse = curthread->kse;
1139139023Sdeischen	KSE_SCHED_LOCK(curkse, curthread->kseg);
1140139023Sdeischen	curthread->flags = psf->psf_flags;
1141139023Sdeischen	curthread->interrupted = psf->psf_interrupted;
1142139023Sdeischen	curthread->timeout = psf->psf_timeout;
1143139023Sdeischen	curthread->data = psf->psf_wait_data;
1144139023Sdeischen	curthread->wakeup_time = psf->psf_wakeup_time;
1145139023Sdeischen	curthread->continuation = psf->psf_continuation;
1146139023Sdeischen	KSE_SCHED_UNLOCK(curkse, curthread->kseg);
1147139023Sdeischen	_kse_critical_leave(crit);
1148139023Sdeischen	THR_THREAD_UNLOCK(curthread, curthread);
114967097Sdeischen}
115054707Sdeischen
1151139023Sdeischenstatic inline void
1152139023Sdeischenthr_sigframe_save(struct pthread *curthread, struct pthread_sigframe *psf)
115367097Sdeischen{
1154139023Sdeischen	kse_critical_t crit;
1155139023Sdeischen	struct kse *curkse;
115667097Sdeischen
1157139023Sdeischen	THR_THREAD_LOCK(curthread, curthread);
1158139023Sdeischen	psf->psf_cancelflags = curthread->cancelflags;
1159139023Sdeischen	crit = _kse_critical_enter();
1160139023Sdeischen	curkse = curthread->kse;
1161139023Sdeischen	KSE_SCHED_LOCK(curkse, curthread->kseg);
1162113658Sdeischen	/* This has to initialize all members of the sigframe. */
1163139023Sdeischen	psf->psf_flags = (curthread->flags & (THR_FLAGS_PRIVATE | THR_FLAGS_EXITING));
1164139023Sdeischen	psf->psf_interrupted = curthread->interrupted;
1165139023Sdeischen	psf->psf_timeout = curthread->timeout;
1166139023Sdeischen	psf->psf_wait_data = curthread->data;
1167139023Sdeischen	psf->psf_wakeup_time = curthread->wakeup_time;
1168139023Sdeischen	psf->psf_continuation = curthread->continuation;
1169139023Sdeischen	KSE_SCHED_UNLOCK(curkse, curthread->kseg);
1170139023Sdeischen	_kse_critical_leave(crit);
1171139023Sdeischen	THR_THREAD_UNLOCK(curthread, curthread);
117267097Sdeischen}
1173116977Sdavidxu
1174116977Sdavidxuvoid
1175116977Sdavidxu_thr_signal_init(void)
1176116977Sdavidxu{
1177116977Sdavidxu	struct sigaction act;
1178117706Sdavidxu	__siginfohandler_t *sigfunc;
1179116977Sdavidxu	int i;
1180119063Sdavidxu	sigset_t sigset;
1181116977Sdavidxu
1182119063Sdavidxu	SIGFILLSET(sigset);
1183119063Sdavidxu	__sys_sigprocmask(SIG_SETMASK, &sigset, &_thr_initial->sigmask);
1184116977Sdavidxu	/* Enter a loop to get the existing signal status: */
1185116977Sdavidxu	for (i = 1; i <= _SIG_MAXSIG; i++) {
1186116977Sdavidxu		/* Get the signal handler details: */
1187132122Sdavidxu		if (__sys_sigaction(i, NULL, &_thread_sigact[i - 1]) != 0) {
1188116977Sdavidxu			/*
1189116977Sdavidxu			 * Abort this process if signal
1190116977Sdavidxu			 * initialisation fails:
1191116977Sdavidxu			 */
1192116977Sdavidxu			PANIC("Cannot read signal handler info");
1193116977Sdavidxu		}
1194117706Sdavidxu		/* Intall wrapper if handler was set */
1195117706Sdavidxu		sigfunc = _thread_sigact[i - 1].sa_sigaction;
1196117706Sdavidxu		if (((__sighandler_t *)sigfunc) != SIG_DFL &&
1197117706Sdavidxu		    ((__sighandler_t *)sigfunc) != SIG_IGN) {
1198117706Sdavidxu		    	act = _thread_sigact[i - 1];
1199117706Sdavidxu			act.sa_flags |= SA_SIGINFO;
1200118747Sdavidxu			act.sa_sigaction =
1201118747Sdavidxu				(__siginfohandler_t *)_thr_sig_handler;
1202117706Sdavidxu			__sys_sigaction(i, &act, NULL);
1203117706Sdavidxu		}
1204116977Sdavidxu	}
1205156330Sdeischen	if (_thr_dump_enabled()) {
1206116977Sdavidxu		/*
1207156330Sdeischen		 * Install the signal handler for SIGINFO.  It isn't
1208156330Sdeischen		 * really needed, but it is nice to have for debugging
1209156330Sdeischen		 * purposes.
1210116977Sdavidxu		 */
1211156330Sdeischen		_thread_sigact[SIGINFO - 1].sa_flags = SA_SIGINFO | SA_RESTART;
1212156330Sdeischen		SIGEMPTYSET(act.sa_mask);
1213156330Sdeischen		act.sa_flags = SA_SIGINFO | SA_RESTART;
1214156330Sdeischen		act.sa_sigaction = (__siginfohandler_t *)&_thr_sig_handler;
1215156330Sdeischen		if (__sys_sigaction(SIGINFO, &act, NULL) != 0) {
1216156330Sdeischen			__sys_sigprocmask(SIG_SETMASK, &_thr_initial->sigmask,
1217156330Sdeischen			    NULL);
1218156330Sdeischen			/*
1219156330Sdeischen			 * Abort this process if signal initialisation fails:
1220156330Sdeischen			 */
1221156330Sdeischen			PANIC("Cannot initialize signal handler");
1222156330Sdeischen		}
1223116977Sdavidxu	}
1224119063Sdavidxu	__sys_sigprocmask(SIG_SETMASK, &_thr_initial->sigmask, NULL);
1225123974Sdavidxu	__sys_sigaltstack(NULL, &_thr_initial->sigstk);
1226116977Sdavidxu}
1227116977Sdavidxu
1228116977Sdavidxuvoid
1229116977Sdavidxu_thr_signal_deinit(void)
1230116977Sdavidxu{
1231116977Sdavidxu	int i;
1232123974Sdavidxu	struct pthread *curthread = _get_curthread();
1233116977Sdavidxu
1234139023Sdeischen	/* Clear process pending signals. */
1235139023Sdeischen	sigemptyset(&_thr_proc_sigpending);
1236139023Sdeischen
1237116977Sdavidxu	/* Enter a loop to get the existing signal status: */
1238116977Sdavidxu	for (i = 1; i <= _SIG_MAXSIG; i++) {
1239116977Sdavidxu		/* Check for signals which cannot be trapped: */
1240116977Sdavidxu		if (i == SIGKILL || i == SIGSTOP) {
1241116977Sdavidxu		}
1242116977Sdavidxu
1243116977Sdavidxu		/* Set the signal handler details: */
1244118747Sdavidxu		else if (__sys_sigaction(i, &_thread_sigact[i - 1],
1245118747Sdavidxu			 NULL) != 0) {
1246116977Sdavidxu			/*
1247116977Sdavidxu			 * Abort this process if signal
1248116977Sdavidxu			 * initialisation fails:
1249116977Sdavidxu			 */
1250116977Sdavidxu			PANIC("Cannot set signal handler info");
1251116977Sdavidxu		}
1252116977Sdavidxu	}
1253123974Sdavidxu	__sys_sigaltstack(&curthread->sigstk, NULL);
1254116977Sdavidxu}
1255116977Sdavidxu
1256