xref: /freebsd/lib/libthr/thread/thr_sig.c (revision bb535300dd871731b2542594a917bc2892479ca0)
1bb535300SJeff Roberson /*
2bb535300SJeff Roberson  * Copyright (c) 2003 Jeffrey Roberson <jeff@freebsd.org>
3bb535300SJeff Roberson  * Copyright (c) 2003 Jonathan Mini <mini@freebsd.org>
4bb535300SJeff Roberson  * All rights reserved.
5bb535300SJeff Roberson  *
6bb535300SJeff Roberson  * Redistribution and use in source and binary forms, with or without
7bb535300SJeff Roberson  * modification, are permitted provided that the following conditions
8bb535300SJeff Roberson  * are met:
9bb535300SJeff Roberson  * 1. Redistributions of source code must retain the above copyright
10bb535300SJeff Roberson  *    notice unmodified, this list of conditions, and the following
11bb535300SJeff Roberson  *    disclaimer.
12bb535300SJeff Roberson  * 2. Redistributions in binary form must reproduce the above copyright
13bb535300SJeff Roberson  *    notice, this list of conditions and the following disclaimer in the
14bb535300SJeff Roberson  *    documentation and/or other materials provided with the distribution.
15bb535300SJeff Roberson  *
16bb535300SJeff Roberson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17bb535300SJeff Roberson  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18bb535300SJeff Roberson  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19bb535300SJeff Roberson  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20bb535300SJeff Roberson  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21bb535300SJeff Roberson  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22bb535300SJeff Roberson  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23bb535300SJeff Roberson  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24bb535300SJeff Roberson  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25bb535300SJeff Roberson  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26bb535300SJeff Roberson  *
27bb535300SJeff Roberson  * $FreeBSD$
28bb535300SJeff Roberson  */
29bb535300SJeff Roberson 
30bb535300SJeff Roberson #include <sys/param.h>
31bb535300SJeff Roberson #include <sys/types.h>
32bb535300SJeff Roberson #include <sys/signalvar.h>
33bb535300SJeff Roberson #include <signal.h>
34bb535300SJeff Roberson #include <fcntl.h>
35bb535300SJeff Roberson #include <unistd.h>
36bb535300SJeff Roberson #include <setjmp.h>
37bb535300SJeff Roberson #include <errno.h>
38bb535300SJeff Roberson #include <pthread.h>
39bb535300SJeff Roberson #include "thr_private.h"
40bb535300SJeff Roberson 
41bb535300SJeff Roberson /* #define DEBUG_SIGNAL */
42bb535300SJeff Roberson #ifdef DEBUG_SIGNAL
43bb535300SJeff Roberson #define DBG_MSG		stdout_debug
44bb535300SJeff Roberson #else
45bb535300SJeff Roberson #define DBG_MSG(x...)
46bb535300SJeff Roberson #endif
47bb535300SJeff Roberson 
48bb535300SJeff Roberson __weak_reference(_sigprocmask, sigprocmask);
49bb535300SJeff Roberson 
50bb535300SJeff Roberson int
51bb535300SJeff Roberson _sigprocmask(int how, const sigset_t *set, sigset_t *oset)
52bb535300SJeff Roberson {
53bb535300SJeff Roberson 	sigset_t new;
54bb535300SJeff Roberson 
55bb535300SJeff Roberson 	/*
56bb535300SJeff Roberson 	 * Make sure applications can't unblock our synchronization
57bb535300SJeff Roberson 	 * signal. We always want to take this with sigwait().
58bb535300SJeff Roberson 	 */
59bb535300SJeff Roberson 	if (set != NULL) {
60bb535300SJeff Roberson 		new = *set;
61bb535300SJeff Roberson 		switch (how) {
62bb535300SJeff Roberson 		case SIG_BLOCK:
63bb535300SJeff Roberson 		case SIG_SETMASK:
64bb535300SJeff Roberson 			SIGADDSET(new, SIGTHR);
65bb535300SJeff Roberson 			break;
66bb535300SJeff Roberson 		case SIG_UNBLOCK:
67bb535300SJeff Roberson 			SIGDELSET(new, SIGTHR);
68bb535300SJeff Roberson 			break;
69bb535300SJeff Roberson 		default:
70bb535300SJeff Roberson 			break;
71bb535300SJeff Roberson 		}
72bb535300SJeff Roberson 		set = &new;
73bb535300SJeff Roberson 	}
74bb535300SJeff Roberson 
75bb535300SJeff Roberson 	return (__sys_sigprocmask(how, set, oset));
76bb535300SJeff Roberson }
77bb535300SJeff Roberson 
78bb535300SJeff Roberson __weak_reference(_pthread_sigmask, pthread_sigmask);
79bb535300SJeff Roberson 
80bb535300SJeff Roberson int
81bb535300SJeff Roberson _pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
82bb535300SJeff Roberson {
83bb535300SJeff Roberson 	int error;
84bb535300SJeff Roberson 
85bb535300SJeff Roberson 	/*
86bb535300SJeff Roberson 	 * This always sets the mask on the current thread.
87bb535300SJeff Roberson 	 */
88bb535300SJeff Roberson 	error = sigprocmask(how, set, oset);
89bb535300SJeff Roberson 
90bb535300SJeff Roberson 	/*
91bb535300SJeff Roberson 	 * pthread_sigmask returns errno or success while sigprocmask returns
92bb535300SJeff Roberson 	 * -1 and sets errno.
93bb535300SJeff Roberson 	 */
94bb535300SJeff Roberson 	if (error == -1)
95bb535300SJeff Roberson 		error = errno;
96bb535300SJeff Roberson 
97bb535300SJeff Roberson 	return (error);
98bb535300SJeff Roberson }
99bb535300SJeff Roberson 
100bb535300SJeff Roberson 
101bb535300SJeff Roberson __weak_reference(_pthread_kill, pthread_kill);
102bb535300SJeff Roberson 
103bb535300SJeff Roberson int
104bb535300SJeff Roberson _pthread_kill(pthread_t pthread, int sig)
105bb535300SJeff Roberson {
106bb535300SJeff Roberson 
107bb535300SJeff Roberson 	if (_thread_initial == NULL)
108bb535300SJeff Roberson 		_thread_init();
109bb535300SJeff Roberson 	return (thr_kill(pthread->thr_id, sig));
110bb535300SJeff Roberson }
111bb535300SJeff Roberson 
112bb535300SJeff Roberson /*
113bb535300SJeff Roberson  * User thread signal handler wrapper.
114bb535300SJeff Roberson  */
115bb535300SJeff Roberson void
116bb535300SJeff Roberson _thread_sig_wrapper(int sig, siginfo_t *info, ucontext_t *context)
117bb535300SJeff Roberson {
118bb535300SJeff Roberson 	struct pthread_state_data psd;
119bb535300SJeff Roberson 	struct pthread	*curthread = _get_curthread();
120bb535300SJeff Roberson 	__siginfohandler_t *handler;
121bb535300SJeff Roberson 
122bb535300SJeff Roberson 	GIANT_LOCK(curthread);
123bb535300SJeff Roberson 	/* Save the thread's previous state. */
124bb535300SJeff Roberson 	curthread->data = psd.psd_wait_data;
125bb535300SJeff Roberson 	curthread->state = psd.psd_state;
126bb535300SJeff Roberson 	curthread->flags = psd.psd_flags;
127bb535300SJeff Roberson 
128bb535300SJeff Roberson 	/* Check the threads previous state: */
129bb535300SJeff Roberson 	if (psd.psd_state != PS_RUNNING) {
130bb535300SJeff Roberson 		/*
131bb535300SJeff Roberson 		 * Do a little cleanup handling for those threads in
132bb535300SJeff Roberson 		 * queues before calling the signal handler.  Signals
133bb535300SJeff Roberson 		 * for these threads are temporarily blocked until
134bb535300SJeff Roberson 		 * after cleanup handling.
135bb535300SJeff Roberson 		 */
136bb535300SJeff Roberson 		switch (psd.psd_state) {
137bb535300SJeff Roberson 		case PS_COND_WAIT:
138bb535300SJeff Roberson 			_cond_wait_backout(curthread);
139bb535300SJeff Roberson 			psd.psd_state = PS_RUNNING;
140bb535300SJeff Roberson 			break;
141bb535300SJeff Roberson 
142bb535300SJeff Roberson 		case PS_MUTEX_WAIT:
143bb535300SJeff Roberson 			/* _mutex_lock_backout(curthread); XXXTHR */
144bb535300SJeff Roberson 			psd.psd_state = PS_RUNNING;
145bb535300SJeff Roberson 			break;
146bb535300SJeff Roberson 
147bb535300SJeff Roberson 		default:
148bb535300SJeff Roberson 			break;
149bb535300SJeff Roberson 		}
150bb535300SJeff Roberson 	}
151bb535300SJeff Roberson 
152bb535300SJeff Roberson 	if (_thread_sigact[sig -1].sa_handler != NULL) {
153bb535300SJeff Roberson 		GIANT_UNLOCK(curthread);
154bb535300SJeff Roberson 		handler = (__siginfohandler_t *)
155bb535300SJeff Roberson 			_thread_sigact[sig - 1].sa_handler;
156bb535300SJeff Roberson 		handler(sig, info, context);
157bb535300SJeff Roberson 		GIANT_LOCK(curthread);
158bb535300SJeff Roberson 	}
159bb535300SJeff Roberson 
160bb535300SJeff Roberson         /* Restore the signal frame. */
161bb535300SJeff Roberson 	psd.psd_wait_data = curthread->data;
162bb535300SJeff Roberson 	psd.psd_state = curthread->state;
163bb535300SJeff Roberson 	psd.psd_flags = curthread->flags &
164bb535300SJeff Roberson 	    (PTHREAD_FLAGS_PRIVATE | PTHREAD_FLAGS_TRACE);
165bb535300SJeff Roberson 	GIANT_UNLOCK(curthread);
166bb535300SJeff Roberson }
167