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