thr_sig.c revision 102590
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 102590 2002-08-29 23:06:07Z deischen $
33 */
34#include <sys/param.h>
35#include <sys/types.h>
36#include <sys/signalvar.h>
37#include <signal.h>
38#include <fcntl.h>
39#include <unistd.h>
40#include <setjmp.h>
41#include <errno.h>
42#include <pthread.h>
43#include "pthread_private.h"
44
45/* Prototypes: */
46static void	thread_sig_add(struct pthread *pthread, int sig, int has_args);
47static void	thread_sig_check_state(struct pthread *pthread, int sig);
48static struct pthread *thread_sig_find(int sig);
49static void	thread_sig_handle_special(int sig);
50static void	thread_sigframe_add(struct pthread *thread, int sig,
51		    int has_args);
52static void	thread_sigframe_save(struct pthread *thread,
53		    struct pthread_signal_frame *psf);
54static void	thread_sig_invoke_handler(int sig, siginfo_t *info,
55		    ucontext_t *ucp);
56
57/*#define DEBUG_SIGNAL*/
58#ifdef DEBUG_SIGNAL
59#define DBG_MSG		stdout_debug
60#else
61#define DBG_MSG(x...)
62#endif
63
64#if defined(_PTHREADS_INVARIANTS)
65#define SIG_SET_ACTIVE()	_sig_in_handler = 1
66#define SIG_SET_INACTIVE()	_sig_in_handler = 0
67#else
68#define SIG_SET_ACTIVE()
69#define SIG_SET_INACTIVE()
70#endif
71
72void
73_thread_sig_handler(int sig, siginfo_t *info, ucontext_t *ucp)
74{
75	struct pthread	*curthread = _get_curthread();
76	struct pthread	*pthread, *pthread_h;
77	int		in_sched = _thread_kern_in_sched;
78	char		c;
79
80	if (ucp == NULL)
81		PANIC("Thread signal handler received null context");
82	DBG_MSG("Got signal %d, current thread %p\n", sig, curthread);
83
84	/* Check if an interval timer signal: */
85	if (sig == _SCHED_SIGNAL) {
86		/* Update the scheduling clock: */
87		gettimeofday((struct timeval *)&_sched_tod, NULL);
88		_sched_ticks++;
89
90		if (in_sched != 0) {
91			/*
92			 * The scheduler is already running; ignore this
93			 * signal.
94			 */
95		}
96		/*
97		 * Check if the scheduler interrupt has come when
98		 * the currently running thread has deferred thread
99		 * signals.
100		 */
101		else if (curthread->sig_defer_count > 0)
102			curthread->yield_on_sig_undefer = 1;
103		else {
104			/* Schedule the next thread: */
105			_thread_kern_sched(ucp);
106
107			/*
108			 * This point should not be reached, so abort the
109			 * process:
110			 */
111			PANIC("Returned to signal function from scheduler");
112		}
113	}
114	/*
115	 * Check if the kernel has been interrupted while the scheduler
116	 * is accessing the scheduling queues or if there is a currently
117	 * running thread that has deferred signals.
118	 */
119	else if ((in_sched != 0) || (curthread->sig_defer_count > 0)) {
120		/* Cast the signal number to a character variable: */
121		c = sig;
122
123		/*
124		 * Write the signal number to the kernel pipe so that it will
125		 * be ready to read when this signal handler returns.
126		 */
127		if (_queue_signals != 0) {
128			__sys_write(_thread_kern_pipe[1], &c, 1);
129			DBG_MSG("Got signal %d, queueing to kernel pipe\n", sig);
130		}
131		if (_thread_sigq[sig - 1].blocked == 0) {
132			DBG_MSG("Got signal %d, adding to _thread_sigq\n", sig);
133			/*
134			 * Do not block this signal; it will be blocked
135			 * when the pending signals are run down.
136			 */
137			/* _thread_sigq[sig - 1].blocked = 1; */
138
139			/*
140			 * Queue the signal, saving siginfo and sigcontext
141			 * (ucontext).
142			 *
143			 * XXX - Do we need to copy siginfo and ucp?
144			 */
145			_thread_sigq[sig - 1].signo = sig;
146			if (info != NULL)
147				memcpy(&_thread_sigq[sig - 1].siginfo, info,
148				    sizeof(*info));
149			memcpy(&_thread_sigq[sig - 1].uc, ucp, sizeof(*ucp));
150
151			/* Indicate that there are queued signals: */
152			_thread_sigq[sig - 1].pending = 1;
153			_sigq_check_reqd = 1;
154		}
155		/* These signals need special handling: */
156		else if (sig == SIGCHLD || sig == SIGTSTP ||
157		    sig == SIGTTIN || sig == SIGTTOU) {
158			_thread_sigq[sig - 1].pending = 1;
159			_thread_sigq[sig - 1].signo = sig;
160			_sigq_check_reqd = 1;
161		}
162		else
163			DBG_MSG("Got signal %d, ignored.\n", sig);
164	}
165	/*
166	 * The signal handlers should have been installed so that they
167	 * cannot be interrupted by other signals.
168	 */
169	else if (_thread_sigq[sig - 1].blocked == 0) {
170		/*
171		 * The signal is not blocked; handle the signal.
172		 *
173		 * Ignore subsequent occurrences of this signal
174		 * until the current signal is handled:
175		 */
176		_thread_sigq[sig - 1].blocked = 1;
177
178		/* This signal will be handled; clear the pending flag: */
179		_thread_sigq[sig - 1].pending = 0;
180
181		/*
182		 * Save siginfo and sigcontext (ucontext).
183		 *
184		 * XXX - Do we need to copy siginfo and ucp?
185		 */
186		_thread_sigq[sig - 1].signo = sig;
187
188		if (info != NULL)
189			memcpy(&_thread_sigq[sig - 1].siginfo, info,
190			    sizeof(*info));
191		memcpy(&_thread_sigq[sig - 1].uc, ucp, sizeof(*ucp));
192		SIG_SET_ACTIVE();
193
194		/* Handle special signals: */
195		thread_sig_handle_special(sig);
196
197		pthread_h = NULL;
198		if ((pthread = thread_sig_find(sig)) == NULL)
199			DBG_MSG("No thread to handle signal %d\n", sig);
200		else if (pthread == curthread) {
201			/*
202			 * Unblock the signal and restore the process signal
203			 * mask in case we don't return from the handler:
204			 */
205			_thread_sigq[sig - 1].blocked = 0;
206			__sys_sigprocmask(SIG_SETMASK, &_process_sigmask, NULL);
207
208			/* Call the signal handler for the current thread: */
209			thread_sig_invoke_handler(sig, info, ucp);
210
211			/*
212			 * Set the process signal mask in the context; it
213			 * could have changed by the handler.
214 			 */
215			ucp->uc_sigmask = _process_sigmask;
216
217			/* Resume the interrupted thread: */
218			__sys_sigreturn(ucp);
219		} else {
220			DBG_MSG("Got signal %d, adding frame to thread %p\n",
221			    sig, pthread);
222
223			/* Setup the target thread to receive the signal: */
224			thread_sig_add(pthread, sig, /*has_args*/ 1);
225
226			/* Take a peek at the next ready to run thread: */
227			pthread_h = PTHREAD_PRIOQ_FIRST();
228			DBG_MSG("Finished adding frame, head of prio list %p\n",
229			    pthread_h);
230		}
231		SIG_SET_INACTIVE();
232
233		/*
234		 * Switch to a different context if the currently running
235		 * thread takes a signal, or if another thread takes a
236		 * signal and the currently running thread is not in a
237		 * signal handler.
238		 */
239		if ((pthread_h != NULL) &&
240		    (pthread_h->active_priority > curthread->active_priority)) {
241			/* Enter the kernel scheduler: */
242			_thread_kern_sched(ucp);
243		}
244	}
245	else {
246		SIG_SET_ACTIVE();
247		thread_sig_handle_special(sig);
248		SIG_SET_INACTIVE();
249	}
250}
251
252static void
253thread_sig_invoke_handler(int sig, siginfo_t *info, ucontext_t *ucp)
254 {
255	struct pthread	*curthread = _get_curthread();
256	void (*sigfunc)(int, siginfo_t *, void *);
257	int		saved_seqno;
258	sigset_t	saved_sigmask;
259
260	/* Invoke the signal handler without going through the scheduler:
261	 */
262	DBG_MSG("Got signal %d, calling handler for current thread %p\n",
263	    sig, curthread);
264
265	/* Save the threads signal mask: */
266	saved_sigmask = curthread->sigmask;
267	saved_seqno = curthread->sigmask_seqno;
268
269	/* Setup the threads signal mask: */
270	SIGSETOR(curthread->sigmask, _thread_sigact[sig - 1].sa_mask);
271	sigaddset(&curthread->sigmask, sig);
272
273	/*
274	 * Check that a custom handler is installed and if
275	 * the signal is not blocked:
276	 */
277	sigfunc = _thread_sigact[sig - 1].sa_sigaction;
278	if (((__sighandler_t *)sigfunc != SIG_DFL) &&
279	    ((__sighandler_t *)sigfunc != SIG_IGN)) {
280		if (((_thread_sigact[sig - 1].sa_flags & SA_SIGINFO) != 0) ||
281		    (info == NULL))
282			(*(sigfunc))(sig, info, ucp);
283		else
284			(*(sigfunc))(sig, (siginfo_t *)info->si_code, ucp);
285	}
286	/*
287	 * Only restore the signal mask if it hasn't been changed by the
288	 * application during invocation of the signal handler:
289	 */
290	if (curthread->sigmask_seqno == saved_seqno)
291		curthread->sigmask = saved_sigmask;
292}
293
294/*
295 * Find a thread that can handle the signal.
296 */
297struct pthread *
298thread_sig_find(int sig)
299{
300	struct pthread	*curthread = _get_curthread();
301	int		handler_installed;
302	struct pthread	*pthread, *pthread_next;
303	struct pthread	*suspended_thread, *signaled_thread;
304
305	DBG_MSG("Looking for thread to handle signal %d\n", sig);
306	/* Check if the signal requires a dump of thread information: */
307	if (sig == SIGINFO) {
308		/* Dump thread information to file: */
309		_thread_dump_info();
310
311		/* Unblock this signal to allow further dumps: */
312		_thread_sigq[sig - 1].blocked = 0;
313	}
314	/* Check if an interval timer signal: */
315	else if (sig == _SCHED_SIGNAL) {
316		/*
317		 * This shouldn't ever occur (should this panic?).
318		 */
319	} else {
320		/*
321		 * Enter a loop to look for threads that have the signal
322		 * unmasked.  POSIX specifies that a thread in a sigwait
323		 * will get the signal over any other threads.  Second
324		 * preference will be threads in in a sigsuspend.  Third
325		 * preference will be the current thread.  If none of the
326		 * above, then the signal is delivered to the first thread
327		 * that is found.  Note that if a custom handler is not
328		 * installed, the signal only affects threads in sigwait.
329		 */
330		suspended_thread = NULL;
331		if ((curthread != &_thread_kern_thread) &&
332		    !sigismember(&curthread->sigmask, sig))
333			signaled_thread = curthread;
334		else
335			signaled_thread = NULL;
336		if ((_thread_sigact[sig - 1].sa_handler == SIG_IGN) ||
337		    (_thread_sigact[sig - 1].sa_handler == SIG_DFL))
338			handler_installed = 0;
339		else
340			handler_installed = 1;
341
342		for (pthread = TAILQ_FIRST(&_waitingq);
343		    pthread != NULL; pthread = pthread_next) {
344			/*
345			 * Grab the next thread before possibly destroying
346			 * the link entry.
347			 */
348			pthread_next = TAILQ_NEXT(pthread, pqe);
349
350			if ((pthread->state == PS_SIGWAIT) &&
351			    sigismember(pthread->data.sigwait, sig)) {
352				/* Change the state of the thread to run: */
353				PTHREAD_NEW_STATE(pthread,PS_RUNNING);
354				/*
355				 * A signal handler is not invoked for threads
356				 * in sigwait.  Clear the blocked and pending
357				 * flags.
358				 */
359				_thread_sigq[sig - 1].blocked = 0;
360				_thread_sigq[sig - 1].pending = 0;
361
362				/* Return the signal number: */
363				pthread->signo = sig;
364
365				/*
366				 * POSIX doesn't doesn't specify which thread
367				 * will get the signal if there are multiple
368				 * waiters, so we give it to the first thread
369				 * we find.
370				 *
371				 * Do not attempt to deliver this signal
372				 * to other threads and do not add the signal
373				 * to the process pending set.
374				 */
375				return (NULL);
376			}
377			else if ((handler_installed != 0) &&
378			    !sigismember(&pthread->sigmask, sig) &&
379			    ((pthread->flags & PTHREAD_FLAGS_SUSPENDED) == 0)) {
380				if (pthread->state == PS_SIGSUSPEND) {
381					if (suspended_thread == NULL)
382						suspended_thread = pthread;
383				} else if (signaled_thread == NULL)
384					signaled_thread = pthread;
385			}
386		}
387
388		/*
389		 * Only perform wakeups and signal delivery if there is a
390		 * custom handler installed:
391		 */
392		if (handler_installed == 0) {
393			/*
394			 * There is no handler installed.  Unblock the
395			 * signal so that if a handler _is_ installed, any
396			 * subsequent signals can be handled.
397			 */
398			_thread_sigq[sig - 1].blocked = 0;
399		} else {
400			/*
401			 * If we didn't find a thread in the waiting queue,
402			 * check the all threads queue:
403			 */
404			if (suspended_thread == NULL &&
405			    signaled_thread == NULL) {
406				/*
407				 * Enter a loop to look for other threads
408				 * capable of receiving the signal:
409				 */
410				TAILQ_FOREACH(pthread, &_thread_list, tle) {
411					if (!sigismember(&pthread->sigmask,
412					    sig)) {
413						signaled_thread = pthread;
414						break;
415					}
416				}
417			}
418
419			if (suspended_thread == NULL &&
420			    signaled_thread == NULL)
421				/*
422				 * Add it to the set of signals pending
423				 * on the process:
424				 */
425				sigaddset(&_process_sigpending, sig);
426			else {
427				/*
428				 * We only deliver the signal to one thread;
429				 * give preference to the suspended thread:
430				 */
431				if (suspended_thread != NULL)
432					pthread = suspended_thread;
433				else
434					pthread = signaled_thread;
435				return (pthread);
436			}
437		}
438	}
439
440	/* Returns nothing. */
441	return (NULL);
442}
443
444void
445_thread_sig_check_pending(struct pthread *pthread)
446{
447	sigset_t	sigset;
448	int		i;
449
450	/*
451	 * Check if there are pending signals for the running
452	 * thread or process that aren't blocked:
453	 */
454	sigset = pthread->sigpend;
455	SIGSETOR(sigset, _process_sigpending);
456	SIGSETNAND(sigset, pthread->sigmask);
457	if (SIGNOTEMPTY(sigset)) {
458		for (i = 1; i < NSIG; i++) {
459			if (sigismember(&sigset, i) != 0) {
460				if (sigismember(&pthread->sigpend, i) != 0)
461					thread_sig_add(pthread, i,
462					    /*has_args*/ 0);
463				else {
464					thread_sig_add(pthread, i,
465					    /*has_args*/ 1);
466					sigdelset(&_process_sigpending, i);
467				}
468			}
469		}
470	}
471}
472
473/*
474 * This can only be called from the kernel scheduler.  It assumes that
475 * all thread contexts are saved and that a signal frame can safely be
476 * added to any user thread.
477 */
478void
479_thread_sig_handle_pending(void)
480{
481	struct pthread	*pthread;
482	int		i, sig;
483
484	PTHREAD_ASSERT(_thread_kern_in_sched != 0,
485	    "_thread_sig_handle_pending called from outside kernel schedule");
486	/*
487	 * Check the array of pending signals:
488	 */
489	for (i = 0; i < NSIG; i++) {
490		if (_thread_sigq[i].pending != 0) {
491			/* This signal is no longer pending. */
492			_thread_sigq[i].pending = 0;
493
494			sig = _thread_sigq[i].signo;
495
496			/* Some signals need special handling: */
497			thread_sig_handle_special(sig);
498
499			if (_thread_sigq[i].blocked == 0) {
500				/*
501				 * Block future signals until this one
502				 * is handled:
503				 */
504				_thread_sigq[i].blocked = 1;
505
506				if ((pthread = thread_sig_find(sig)) != NULL) {
507					/*
508					 * Setup the target thread to receive
509					 * the signal:
510					 */
511					thread_sig_add(pthread, sig,
512					    /*has_args*/ 1);
513				}
514			}
515		}
516	}
517}
518
519static void
520thread_sig_handle_special(int sig)
521{
522	struct pthread	*pthread, *pthread_next;
523	int		i;
524
525	switch (sig) {
526	case SIGCHLD:
527		/*
528		 * Go through the file list and set all files
529		 * to non-blocking again in case the child
530		 * set some of them to block. Sigh.
531		 */
532		for (i = 0; i < _thread_dtablesize; i++) {
533			/* Check if this file is used: */
534			if (_thread_fd_table[i] != NULL) {
535				/*
536				 * Set the file descriptor to non-blocking:
537				 */
538				__sys_fcntl(i, F_SETFL,
539				    _thread_fd_getflags(i) | O_NONBLOCK);
540			}
541		}
542		/*
543		 * Enter a loop to wake up all threads waiting
544		 * for a process to complete:
545		 */
546		for (pthread = TAILQ_FIRST(&_waitingq);
547		    pthread != NULL; pthread = pthread_next) {
548			/*
549			 * Grab the next thread before possibly
550			 * destroying the link entry:
551			 */
552			pthread_next = TAILQ_NEXT(pthread, pqe);
553
554			/*
555			 * If this thread is waiting for a child
556			 * process to complete, wake it up:
557			 */
558			if (pthread->state == PS_WAIT_WAIT) {
559				/* Make the thread runnable: */
560				PTHREAD_NEW_STATE(pthread,PS_RUNNING);
561
562				/* Return the signal number: */
563				pthread->signo = sig;
564			}
565		}
566		break;
567
568	/*
569	 * POSIX says that pending SIGCONT signals are
570	 * discarded when one of these signals occurs.
571	 */
572	case SIGTSTP:
573	case SIGTTIN:
574	case SIGTTOU:
575		/*
576		 * Enter a loop to discard pending SIGCONT
577		 * signals:
578		 */
579		TAILQ_FOREACH(pthread, &_thread_list, tle) {
580			sigdelset(&pthread->sigpend, SIGCONT);
581		}
582		break;
583
584	default:
585		break;
586	}
587}
588
589/*
590 * Perform thread specific actions in response to a signal.
591 * This function is only called if there is a handler installed
592 * for the signal, and if the target thread has the signal
593 * unmasked.
594 */
595static void
596thread_sig_add(struct pthread *pthread, int sig, int has_args)
597{
598	int	restart;
599	int	suppress_handler = 0;
600	int	thread_is_active = 0;
601
602	restart = _thread_sigact[sig - 1].sa_flags & SA_RESTART;
603
604	/* Make sure this signal isn't still in the pending set: */
605	sigdelset(&pthread->sigpend, sig);
606
607	/*
608	 * Process according to thread state:
609	 */
610	switch (pthread->state) {
611	/*
612	 * States which do not change when a signal is trapped:
613	 */
614	case PS_DEAD:
615	case PS_DEADLOCK:
616	case PS_STATE_MAX:
617	case PS_SIGTHREAD:
618		/*
619		 * You can't call a signal handler for threads in these
620		 * states.
621		 */
622		suppress_handler = 1;
623		break;
624
625	/*
626	 * States which do not need any cleanup handling when signals
627	 * occur:
628	 */
629	case PS_RUNNING:
630		/*
631		 * Remove the thread from the queue before changing its
632		 * priority:
633		 */
634		if ((pthread->flags & PTHREAD_FLAGS_IN_PRIOQ) != 0)
635			PTHREAD_PRIOQ_REMOVE(pthread);
636		else
637			/*
638			 * This thread is running; avoid placing it in
639			 * the run queue:
640			 */
641			thread_is_active = 1;
642		break;
643
644	case PS_SUSPENDED:
645		break;
646
647	case PS_SPINBLOCK:
648		/* Remove the thread from the workq and waitq: */
649		PTHREAD_WORKQ_REMOVE(pthread);
650		PTHREAD_WAITQ_REMOVE(pthread);
651		/* Make the thread runnable: */
652		PTHREAD_SET_STATE(pthread, PS_RUNNING);
653		break;
654
655	case PS_SIGWAIT:
656		/* The signal handler is not called for threads in SIGWAIT. */
657		suppress_handler = 1;
658		/* Wake up the thread if the signal is blocked. */
659		if (sigismember(pthread->data.sigwait, sig)) {
660			/* Change the state of the thread to run: */
661			PTHREAD_NEW_STATE(pthread, PS_RUNNING);
662
663			/* Return the signal number: */
664			pthread->signo = sig;
665		} else
666			/* Increment the pending signal count. */
667			sigaddset(&pthread->sigpend, sig);
668		break;
669
670	/*
671	 * The wait state is a special case due to the handling of
672	 * SIGCHLD signals.
673	 */
674	case PS_WAIT_WAIT:
675		if (sig == SIGCHLD) {
676			/* Change the state of the thread to run: */
677			PTHREAD_WAITQ_REMOVE(pthread);
678			PTHREAD_SET_STATE(pthread, PS_RUNNING);
679
680			/* Return the signal number: */
681			pthread->signo = sig;
682		}
683		else {
684			/*
685			 * Mark the thread as interrupted only if the
686			 * restart flag is not set on the signal action:
687			 */
688			if (restart == 0)
689				pthread->interrupted = 1;
690			PTHREAD_WAITQ_REMOVE(pthread);
691			PTHREAD_SET_STATE(pthread, PS_RUNNING);
692		}
693		break;
694
695	/*
696	 * States which cannot be interrupted but still require the
697	 * signal handler to run:
698	 */
699	case PS_COND_WAIT:
700	case PS_MUTEX_WAIT:
701		/*
702		 * Remove the thread from the wait queue.  It will
703		 * be added back to the wait queue once all signal
704		 * handlers have been invoked.
705		 */
706		PTHREAD_WAITQ_REMOVE(pthread);
707		break;
708
709	case PS_JOIN:
710		/*
711		 * Remove the thread from the wait queue.  It will
712		 * be added back to the wait queue once all signal
713		 * handlers have been invoked.
714		 */
715		PTHREAD_WAITQ_REMOVE(pthread);
716		/* Make the thread runnable: */
717		PTHREAD_SET_STATE(pthread, PS_RUNNING);
718		break;
719
720	/*
721	 * States which are interruptible but may need to be removed
722	 * from queues before any signal handler is called.
723	 *
724	 * XXX - We may not need to handle this condition, but will
725	 *       mark it as a potential problem.
726	 */
727	case PS_FDLR_WAIT:
728	case PS_FDLW_WAIT:
729	case PS_FILE_WAIT:
730		if (restart == 0)
731			pthread->interrupted = 1;
732		/*
733		 * Remove the thread from the wait queue.  Our
734		 * signal handler hook will remove this thread
735		 * from the fd or file queue before invoking
736		 * the actual handler.
737		 */
738		PTHREAD_WAITQ_REMOVE(pthread);
739		break;
740
741	/*
742	 * States which are interruptible:
743	 */
744	case PS_FDR_WAIT:
745	case PS_FDW_WAIT:
746		if (restart == 0) {
747			/*
748			 * Flag the operation as interrupted and
749			 * set the state to running:
750			 */
751			pthread->interrupted = 1;
752			PTHREAD_SET_STATE(pthread, PS_RUNNING);
753		}
754		PTHREAD_WORKQ_REMOVE(pthread);
755		PTHREAD_WAITQ_REMOVE(pthread);
756		break;
757
758	case PS_POLL_WAIT:
759	case PS_SELECT_WAIT:
760	case PS_SLEEP_WAIT:
761		/*
762		 * Unmasked signals always cause poll, select, and sleep
763		 * to terminate early, regardless of SA_RESTART:
764		 */
765		pthread->interrupted = 1;
766		/* Remove threads in poll and select from the workq: */
767		if ((pthread->flags & PTHREAD_FLAGS_IN_WORKQ) != 0)
768			PTHREAD_WORKQ_REMOVE(pthread);
769		PTHREAD_WAITQ_REMOVE(pthread);
770		PTHREAD_SET_STATE(pthread, PS_RUNNING);
771		break;
772
773	case PS_SIGSUSPEND:
774		PTHREAD_WAITQ_REMOVE(pthread);
775		PTHREAD_SET_STATE(pthread, PS_RUNNING);
776		break;
777	}
778
779	if (suppress_handler == 0) {
780		/* Setup a signal frame and save the current threads state: */
781		thread_sigframe_add(pthread, sig, has_args);
782
783		/*
784		 * Signals are deferred until just before the threads
785		 * signal handler is invoked:
786		 */
787		pthread->sig_defer_count = 1;
788
789		/* Make sure the thread is runnable: */
790		if (pthread->state != PS_RUNNING)
791			PTHREAD_SET_STATE(pthread, PS_RUNNING);
792		/*
793		 * The thread should be removed from all scheduling
794		 * queues at this point.  Raise the priority and place
795		 * the thread in the run queue.  It is also possible
796		 * for a signal to be sent to a suspended thread,
797		 * mostly via pthread_kill().  If a thread is suspended,
798		 * don't insert it into the priority queue; just set
799		 * its state to suspended and it will run the signal
800		 * handler when it is resumed.
801		 */
802		pthread->active_priority |= PTHREAD_SIGNAL_PRIORITY;
803		if ((pthread->flags & PTHREAD_FLAGS_SUSPENDED) != 0)
804			PTHREAD_SET_STATE(pthread, PS_SUSPENDED);
805		else if (thread_is_active == 0)
806			PTHREAD_PRIOQ_INSERT_TAIL(pthread);
807	}
808}
809
810static void
811thread_sig_check_state(struct pthread *pthread, int sig)
812{
813	/*
814	 * Process according to thread state:
815	 */
816	switch (pthread->state) {
817	/*
818	 * States which do not change when a signal is trapped:
819	 */
820	case PS_DEAD:
821	case PS_DEADLOCK:
822	case PS_STATE_MAX:
823	case PS_SIGTHREAD:
824	case PS_RUNNING:
825	case PS_SUSPENDED:
826	case PS_SPINBLOCK:
827	case PS_COND_WAIT:
828	case PS_JOIN:
829	case PS_MUTEX_WAIT:
830		break;
831
832	case PS_SIGWAIT:
833		/* Wake up the thread if the signal is blocked. */
834		if (sigismember(pthread->data.sigwait, sig)) {
835			/* Change the state of the thread to run: */
836			PTHREAD_NEW_STATE(pthread, PS_RUNNING);
837
838			/* Return the signal number: */
839			pthread->signo = sig;
840		} else
841			/* Increment the pending signal count. */
842			sigaddset(&pthread->sigpend, sig);
843		break;
844
845	/*
846	 * The wait state is a special case due to the handling of
847	 * SIGCHLD signals.
848	 */
849	case PS_WAIT_WAIT:
850		if (sig == SIGCHLD) {
851			/*
852			 * Remove the thread from the wait queue and
853			 * make it runnable:
854			 */
855			PTHREAD_NEW_STATE(pthread, PS_RUNNING);
856
857			/* Return the signal number: */
858			pthread->signo = sig;
859		}
860		break;
861
862	case PS_FDLR_WAIT:
863	case PS_FDLW_WAIT:
864	case PS_SIGSUSPEND:
865	case PS_SLEEP_WAIT:
866		/*
867		 * Remove the thread from the wait queue and make it
868		 * runnable:
869		 */
870		PTHREAD_NEW_STATE(pthread, PS_RUNNING);
871
872		/* Flag the operation as interrupted: */
873		pthread->interrupted = 1;
874		break;
875
876	/*
877	 * These states are additionally in the work queue:
878	 */
879	case PS_FDR_WAIT:
880	case PS_FDW_WAIT:
881	case PS_FILE_WAIT:
882	case PS_POLL_WAIT:
883	case PS_SELECT_WAIT:
884		/*
885		 * Remove the thread from the wait and work queues, and
886		 * make it runnable:
887		 */
888		PTHREAD_WORKQ_REMOVE(pthread);
889		PTHREAD_NEW_STATE(pthread, PS_RUNNING);
890
891		/* Flag the operation as interrupted: */
892		pthread->interrupted = 1;
893		break;
894	}
895}
896
897/*
898 * Send a signal to a specific thread (ala pthread_kill):
899 */
900void
901_thread_sig_send(struct pthread *pthread, int sig)
902{
903	struct pthread	*curthread = _get_curthread();
904
905	/* Check for signals whose actions are SIG_DFL: */
906	if (_thread_sigact[sig - 1].sa_handler == SIG_DFL) {
907		/*
908		 * Check to see if a temporary signal handler is
909		 * installed for sigwaiters:
910		 */
911		if (_thread_dfl_count[sig] == 0)
912			/*
913			 * Deliver the signal to the process if a handler
914			 * is not installed:
915			 */
916			kill(getpid(), sig);
917		/*
918		 * Assuming we're still running after the above kill(),
919		 * make any necessary state changes to the thread:
920		 */
921		thread_sig_check_state(pthread, sig);
922	}
923	/*
924	 * Check that the signal is not being ignored:
925	 */
926	else if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) {
927		if (pthread->state == PS_SIGWAIT &&
928		    sigismember(pthread->data.sigwait, sig)) {
929			/* Change the state of the thread to run: */
930			PTHREAD_NEW_STATE(pthread, PS_RUNNING);
931
932			/* Return the signal number: */
933			pthread->signo = sig;
934		} else if (sigismember(&pthread->sigmask, sig))
935			/* Add the signal to the pending set: */
936			sigaddset(&pthread->sigpend, sig);
937		else if (pthread == curthread)
938			/* Call the signal handler for the current thread: */
939			thread_sig_invoke_handler(sig, NULL, NULL);
940		else {
941			/* Protect the scheduling queues: */
942			_thread_kern_sig_defer();
943			/*
944			 * Perform any state changes due to signal
945			 * arrival:
946			 */
947			thread_sig_add(pthread, sig, /* has args */ 0);
948			/* Unprotect the scheduling queues: */
949			_thread_kern_sig_undefer();
950		}
951	}
952}
953
954/*
955 * User thread signal handler wrapper.
956 *
957 *   thread - current running thread
958 */
959void
960_thread_sig_wrapper(void)
961{
962	struct pthread_signal_frame *psf;
963	struct pthread	*thread = _get_curthread();
964
965	/* Get the current frame and state: */
966	psf = thread->curframe;
967	thread->curframe = NULL;
968	PTHREAD_ASSERT(psf != NULL, "Invalid signal frame in signal handler");
969
970	/*
971	 * We're coming from the kernel scheduler; clear the in
972	 * scheduler flag:
973	 */
974	_thread_kern_in_sched = 0;
975
976	/* Check the threads previous state: */
977	if (psf->saved_state.psd_state != PS_RUNNING) {
978		/*
979		 * Do a little cleanup handling for those threads in
980		 * queues before calling the signal handler.  Signals
981		 * for these threads are temporarily blocked until
982		 * after cleanup handling.
983		 */
984		switch (psf->saved_state.psd_state) {
985		case PS_FDLR_WAIT:
986		case PS_FDLW_WAIT:
987			_fd_lock_backout(thread);
988			psf->saved_state.psd_state = PS_RUNNING;
989			break;
990
991		case PS_COND_WAIT:
992			_cond_wait_backout(thread);
993			psf->saved_state.psd_state = PS_RUNNING;
994			break;
995
996		case PS_MUTEX_WAIT:
997			_mutex_lock_backout(thread);
998			psf->saved_state.psd_state = PS_RUNNING;
999			break;
1000
1001		default:
1002			break;
1003		}
1004	}
1005
1006	/* Unblock the signal in case we don't return from the handler: */
1007	_thread_sigq[psf->signo - 1].blocked = 0;
1008
1009	/*
1010	 * Lower the priority before calling the handler in case
1011	 * it never returns (longjmps back):
1012	 */
1013	thread->active_priority &= ~PTHREAD_SIGNAL_PRIORITY;
1014
1015	/*
1016	 * Reenable interruptions without checking for the need to
1017	 * context switch:
1018	 */
1019	thread->sig_defer_count = 0;
1020
1021	/*
1022	 * Dispatch the signal via the custom signal handler:
1023	 */
1024	if (psf->sig_has_args == 0)
1025		thread_sig_invoke_handler(psf->signo, NULL, NULL);
1026	else
1027		thread_sig_invoke_handler(psf->signo, &psf->siginfo, &psf->uc);
1028
1029	/*
1030	 * Call the kernel scheduler to safely restore the frame and
1031	 * schedule the next thread:
1032	 */
1033	_thread_kern_sched_frame(psf);
1034}
1035
1036static void
1037thread_sigframe_add(struct pthread *thread, int sig, int has_args)
1038{
1039	struct pthread_signal_frame *psf = NULL;
1040	unsigned long	stackp;
1041
1042 	/* Get the top of the threads stack: */
1043	stackp = GET_STACK_JB(thread->ctx.jb);
1044
1045	/*
1046	 * Leave a little space on the stack and round down to the
1047	 * nearest aligned word:
1048	 */
1049	stackp -= sizeof(double);
1050	stackp &= ~0x3UL;
1051
1052	/* Allocate room on top of the stack for a new signal frame: */
1053	stackp -= sizeof(struct pthread_signal_frame);
1054
1055	psf = (struct pthread_signal_frame *) stackp;
1056
1057	/* Save the current context in the signal frame: */
1058	thread_sigframe_save(thread, psf);
1059
1060	/* Set handler specific information: */
1061	psf->sig_has_args = has_args;
1062	psf->signo = sig;
1063	if (has_args) {
1064		/* Copy the signal handler arguments to the signal frame: */
1065		memcpy(&psf->uc, &_thread_sigq[psf->signo - 1].uc,
1066		    sizeof(psf->uc));
1067		memcpy(&psf->siginfo, &_thread_sigq[psf->signo - 1].siginfo,
1068		    sizeof(psf->siginfo));
1069	}
1070
1071	/* Setup the signal mask: */
1072	SIGSETOR(thread->sigmask, _thread_sigact[sig - 1].sa_mask);
1073	sigaddset(&thread->sigmask, sig);
1074
1075	/* Set up the new frame: */
1076	thread->curframe = psf;
1077	thread->flags &= PTHREAD_FLAGS_PRIVATE | PTHREAD_FLAGS_TRACE |
1078	    PTHREAD_FLAGS_IN_SYNCQ;
1079	/*
1080	 * Set up the context:
1081	 */
1082	stackp -= sizeof(double);
1083	_setjmp(thread->ctx.jb);
1084	SET_STACK_JB(thread->ctx.jb, stackp);
1085	SET_RETURN_ADDR_JB(thread->ctx.jb, _thread_sig_wrapper);
1086}
1087
1088void
1089_thread_sigframe_restore(struct pthread *thread,
1090    struct pthread_signal_frame *psf)
1091{
1092	memcpy(&thread->ctx, &psf->ctx, sizeof(thread->ctx));
1093	/*
1094	 * Only restore the signal mask if it hasn't been changed
1095	 * by the application during invocation of the signal handler:
1096	 */
1097	if (thread->sigmask_seqno == psf->saved_state.psd_sigmask_seqno)
1098		thread->sigmask = psf->saved_state.psd_sigmask;
1099	thread->curframe = psf->saved_state.psd_curframe;
1100	thread->wakeup_time = psf->saved_state.psd_wakeup_time;
1101	thread->data = psf->saved_state.psd_wait_data;
1102	thread->state = psf->saved_state.psd_state;
1103	thread->flags = psf->saved_state.psd_flags;
1104	thread->interrupted = psf->saved_state.psd_interrupted;
1105	thread->signo = psf->saved_state.psd_signo;
1106	thread->sig_defer_count = psf->saved_state.psd_sig_defer_count;
1107}
1108
1109static void
1110thread_sigframe_save(struct pthread *thread, struct pthread_signal_frame *psf)
1111{
1112	memcpy(&psf->ctx, &thread->ctx, sizeof(thread->ctx));
1113	psf->saved_state.psd_sigmask = thread->sigmask;
1114	psf->saved_state.psd_curframe = thread->curframe;
1115	psf->saved_state.psd_wakeup_time = thread->wakeup_time;
1116	psf->saved_state.psd_wait_data = thread->data;
1117	psf->saved_state.psd_state = thread->state;
1118	psf->saved_state.psd_flags = thread->flags &
1119	    (PTHREAD_FLAGS_PRIVATE | PTHREAD_FLAGS_TRACE);
1120	psf->saved_state.psd_interrupted = thread->interrupted;
1121	psf->saved_state.psd_sigmask_seqno = thread->sigmask_seqno;
1122	psf->saved_state.psd_signo = thread->signo;
1123	psf->saved_state.psd_sig_defer_count = thread->sig_defer_count;
1124}
1125
1126