Deleted Added
full compact
thr_sig.c (115080) thr_sig.c (115278)
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 *
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 115080 2003-05-16 19:58:30Z deischen $
32 * $FreeBSD: head/lib/libkse/thread/thr_sig.c 115278 2003-05-24 02:29:25Z deischen $
33 */
34#include <sys/param.h>
35#include <sys/types.h>
36#include <sys/signalvar.h>
37#include <signal.h>
38#include <errno.h>
39#include <fcntl.h>
40#include <unistd.h>
41#include <string.h>
42#include <pthread.h>
43#include "thr_private.h"
44#include "pthread_md.h"
45
46/* Prototypes: */
47static void build_siginfo(siginfo_t *info, int signo);
48/* static void thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info); */
49static void thr_sig_check_state(struct pthread *pthread, int sig);
50static struct pthread *thr_sig_find(struct kse *curkse, int sig,
51 siginfo_t *info);
52static void handle_special_signals(struct kse *curkse, int sig);
53static void thr_sigframe_add(struct pthread *thread, int sig,
54 siginfo_t *info);
55static void thr_sigframe_restore(struct pthread *thread,
56 struct pthread_sigframe *psf);
57static void thr_sigframe_save(struct pthread *thread,
58 struct pthread_sigframe *psf);
59static void thr_sig_invoke_handler(struct pthread *, int sig,
60 siginfo_t *info, ucontext_t *ucp);
61
62/* #define DEBUG_SIGNAL */
63#ifdef DEBUG_SIGNAL
64#define DBG_MSG stdout_debug
65#else
66#define DBG_MSG(x...)
67#endif
68
69/*
70 * Signal setup and delivery.
71 *
72 * 1) Delivering signals to threads in the same KSE.
73 * These signals are sent by upcall events and are set in the
74 * km_sigscaught field of the KSE mailbox. Since these signals
75 * are received while operating on the KSE stack, they can be
76 * delivered either by using signalcontext() to add a stack frame
77 * to the target thread's stack, or by adding them in the thread's
78 * pending set and having the thread run them down after it
79 * 2) Delivering signals to threads in other KSEs/KSEGs.
80 * 3) Delivering signals to threads in critical regions.
81 * 4) Delivering signals to threads after they change their signal masks.
82 *
83 * Methods of delivering signals.
84 *
85 * 1) Add a signal frame to the thread's saved context.
86 * 2) Add the signal to the thread structure, mark the thread as
87 * having signals to handle, and let the thread run them down
88 * after it resumes from the KSE scheduler.
89 *
90 * Problem with 1). You can't do this to a running thread or a
91 * thread in a critical region.
92 *
93 * Problem with 2). You can't do this to a thread that doesn't
94 * yield in some way (explicitly enters the scheduler). A thread
95 * blocked in the kernel or a CPU hungry thread will not see the
96 * signal without entering the scheduler.
97 *
98 * The solution is to use both 1) and 2) to deliver signals:
99 *
100 * o Thread in critical region - use 2). When the thread
101 * leaves the critical region it will check to see if it
102 * has pending signals and run them down.
103 *
104 * o Thread enters scheduler explicitly - use 2). The thread
105 * can check for pending signals after it returns from the
106 * the scheduler.
107 *
108 * o Thread is running and not current thread - use 2). When the
109 * thread hits a condition specified by one of the other bullets,
110 * the signal will be delivered.
111 *
112 * o Thread is running and is current thread (e.g., the thread
113 * has just changed its signal mask and now sees that it has
114 * pending signals) - just run down the pending signals.
115 *
116 * o Thread is swapped out due to quantum expiration - use 1)
117 *
118 * o Thread is blocked in kernel - kse_thr_wakeup() and then
119 * use 1)
120 */
121
122/*
123 * Rules for selecting threads for signals received:
124 *
125 * 1) If the signal is a sychronous signal, it is delivered to
126 * the generating (current thread). If the thread has the
127 * signal masked, it is added to the threads pending signal
128 * set until the thread unmasks it.
129 *
130 * 2) A thread in sigwait() where the signal is in the thread's
131 * waitset.
132 *
133 * 3) A thread in sigsuspend() where the signal is not in the
134 * thread's suspended signal mask.
135 *
136 * 4) Any thread (first found/easiest to deliver) that has the
137 * signal unmasked.
138 */
139
140/*
141 * This signal handler only delivers asynchronous signals.
142 * This must be called with upcalls disabled and without
143 * holding any locks.
144 */
145void
146_thr_sig_dispatch(struct kse *curkse, int sig, siginfo_t *info)
147{
148 struct pthread *thread;
149
150 DBG_MSG(">>> _thr_sig_dispatch(%d)\n", sig);
151
152 /* Some signals need special handling: */
153 handle_special_signals(curkse, sig);
33 */
34#include <sys/param.h>
35#include <sys/types.h>
36#include <sys/signalvar.h>
37#include <signal.h>
38#include <errno.h>
39#include <fcntl.h>
40#include <unistd.h>
41#include <string.h>
42#include <pthread.h>
43#include "thr_private.h"
44#include "pthread_md.h"
45
46/* Prototypes: */
47static void build_siginfo(siginfo_t *info, int signo);
48/* static void thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info); */
49static void thr_sig_check_state(struct pthread *pthread, int sig);
50static struct pthread *thr_sig_find(struct kse *curkse, int sig,
51 siginfo_t *info);
52static void handle_special_signals(struct kse *curkse, int sig);
53static void thr_sigframe_add(struct pthread *thread, int sig,
54 siginfo_t *info);
55static void thr_sigframe_restore(struct pthread *thread,
56 struct pthread_sigframe *psf);
57static void thr_sigframe_save(struct pthread *thread,
58 struct pthread_sigframe *psf);
59static void thr_sig_invoke_handler(struct pthread *, int sig,
60 siginfo_t *info, ucontext_t *ucp);
61
62/* #define DEBUG_SIGNAL */
63#ifdef DEBUG_SIGNAL
64#define DBG_MSG stdout_debug
65#else
66#define DBG_MSG(x...)
67#endif
68
69/*
70 * Signal setup and delivery.
71 *
72 * 1) Delivering signals to threads in the same KSE.
73 * These signals are sent by upcall events and are set in the
74 * km_sigscaught field of the KSE mailbox. Since these signals
75 * are received while operating on the KSE stack, they can be
76 * delivered either by using signalcontext() to add a stack frame
77 * to the target thread's stack, or by adding them in the thread's
78 * pending set and having the thread run them down after it
79 * 2) Delivering signals to threads in other KSEs/KSEGs.
80 * 3) Delivering signals to threads in critical regions.
81 * 4) Delivering signals to threads after they change their signal masks.
82 *
83 * Methods of delivering signals.
84 *
85 * 1) Add a signal frame to the thread's saved context.
86 * 2) Add the signal to the thread structure, mark the thread as
87 * having signals to handle, and let the thread run them down
88 * after it resumes from the KSE scheduler.
89 *
90 * Problem with 1). You can't do this to a running thread or a
91 * thread in a critical region.
92 *
93 * Problem with 2). You can't do this to a thread that doesn't
94 * yield in some way (explicitly enters the scheduler). A thread
95 * blocked in the kernel or a CPU hungry thread will not see the
96 * signal without entering the scheduler.
97 *
98 * The solution is to use both 1) and 2) to deliver signals:
99 *
100 * o Thread in critical region - use 2). When the thread
101 * leaves the critical region it will check to see if it
102 * has pending signals and run them down.
103 *
104 * o Thread enters scheduler explicitly - use 2). The thread
105 * can check for pending signals after it returns from the
106 * the scheduler.
107 *
108 * o Thread is running and not current thread - use 2). When the
109 * thread hits a condition specified by one of the other bullets,
110 * the signal will be delivered.
111 *
112 * o Thread is running and is current thread (e.g., the thread
113 * has just changed its signal mask and now sees that it has
114 * pending signals) - just run down the pending signals.
115 *
116 * o Thread is swapped out due to quantum expiration - use 1)
117 *
118 * o Thread is blocked in kernel - kse_thr_wakeup() and then
119 * use 1)
120 */
121
122/*
123 * Rules for selecting threads for signals received:
124 *
125 * 1) If the signal is a sychronous signal, it is delivered to
126 * the generating (current thread). If the thread has the
127 * signal masked, it is added to the threads pending signal
128 * set until the thread unmasks it.
129 *
130 * 2) A thread in sigwait() where the signal is in the thread's
131 * waitset.
132 *
133 * 3) A thread in sigsuspend() where the signal is not in the
134 * thread's suspended signal mask.
135 *
136 * 4) Any thread (first found/easiest to deliver) that has the
137 * signal unmasked.
138 */
139
140/*
141 * This signal handler only delivers asynchronous signals.
142 * This must be called with upcalls disabled and without
143 * holding any locks.
144 */
145void
146_thr_sig_dispatch(struct kse *curkse, int sig, siginfo_t *info)
147{
148 struct pthread *thread;
149
150 DBG_MSG(">>> _thr_sig_dispatch(%d)\n", sig);
151
152 /* Some signals need special handling: */
153 handle_special_signals(curkse, sig);
154
155 if ((thread = thr_sig_find(curkse, sig, info)) != NULL) {
154 stderr_debug("dispatch sig:%d\n", sig);
155 while ((thread = thr_sig_find(curkse, sig, info)) != NULL) {
156 /*
157 * Setup the target thread to receive the signal:
158 */
159 DBG_MSG("Got signal %d, selecting thread %p\n", sig, thread);
160 KSE_SCHED_LOCK(curkse, thread->kseg);
156 /*
157 * Setup the target thread to receive the signal:
158 */
159 DBG_MSG("Got signal %d, selecting thread %p\n", sig, thread);
160 KSE_SCHED_LOCK(curkse, thread->kseg);
161 _thr_sig_add(thread, sig, info);
162 KSE_SCHED_UNLOCK(curkse, thread->kseg);
161 if ((thread->state == PS_DEAD) ||
162 (thread->state == PS_DEADLOCK) ||
163 THR_IS_EXITING(thread) || THR_IS_SUSPENDED(thread)) {
164 KSE_SCHED_UNLOCK(curkse, thread->kseg);
165 _thr_ref_delete(NULL, thread);
166 } else {
167 _thr_sig_add(thread, sig, info);
168 KSE_SCHED_UNLOCK(curkse, thread->kseg);
169 _thr_ref_delete(NULL, thread);
170 break;
171 }
163 }
164}
165
166void
167_thr_sig_handler(int sig, siginfo_t *info, ucontext_t *ucp)
168{
169 void (*sigfunc)(int, siginfo_t *, void *);
170 struct kse *curkse;
171
172 curkse = _get_curkse();
173 if ((curkse == NULL) || ((curkse->k_flags & KF_STARTED) == 0)) {
174 /* Upcalls are not yet started; just call the handler. */
175 sigfunc = _thread_sigact[sig - 1].sa_sigaction;
176 ucp->uc_sigmask = _thr_proc_sigmask;
177 if (((__sighandler_t *)sigfunc != SIG_DFL) &&
178 ((__sighandler_t *)sigfunc != SIG_IGN)) {
179 if (((_thread_sigact[sig - 1].sa_flags & SA_SIGINFO)
180 != 0) || (info == NULL))
181 (*(sigfunc))(sig, info, ucp);
182 else
183 (*(sigfunc))(sig, (siginfo_t *)info->si_code,
184 ucp);
185 }
186 }
187 else {
188 /* Nothing. */
189 DBG_MSG("Got signal %d\n", sig);
190 sigaddset(&curkse->k_mbx.km_sigscaught, sig);
191 ucp->uc_sigmask = _thr_proc_sigmask;
192 }
193}
194
195static void
196thr_sig_invoke_handler(struct pthread *curthread, int sig, siginfo_t *info,
197 ucontext_t *ucp)
198{
199 void (*sigfunc)(int, siginfo_t *, void *);
200 sigset_t saved_mask;
201 int saved_seqno;
202
203 /* Invoke the signal handler without going through the scheduler:
204 */
205 DBG_MSG("Got signal %d, calling handler for current thread %p\n",
206 sig, curthread);
207
208 /*
209 * Setup the threads signal mask.
210 *
211 * The mask is changed in the thread's active signal mask
212 * (in the context) and not in the base signal mask because
213 * a thread is allowed to change its signal mask within a
214 * signal handler. If it does, the signal mask restored
215 * after the handler should be the same as that set by the
216 * thread during the handler, not the original mask from
217 * before calling the handler. The thread could also
218 * modify the signal mask in the context and expect this
219 * mask to be used.
220 */
221 THR_SCHED_LOCK(curthread, curthread);
222 saved_mask = curthread->tmbx.tm_context.uc_sigmask;
223 saved_seqno = curthread->sigmask_seqno;
224 SIGSETOR(curthread->tmbx.tm_context.uc_sigmask,
225 _thread_sigact[sig - 1].sa_mask);
226 sigaddset(&curthread->tmbx.tm_context.uc_sigmask, sig);
227 THR_SCHED_UNLOCK(curthread, curthread);
228
229 /*
230 * Check that a custom handler is installed and if
231 * the signal is not blocked:
232 */
233 sigfunc = _thread_sigact[sig - 1].sa_sigaction;
234 ucp->uc_sigmask = _thr_proc_sigmask;
235 if (((__sighandler_t *)sigfunc != SIG_DFL) &&
236 ((__sighandler_t *)sigfunc != SIG_IGN)) {
237 if (((_thread_sigact[sig - 1].sa_flags & SA_SIGINFO) != 0) ||
238 (info == NULL))
239 (*(sigfunc))(sig, info, ucp);
240 else
241 (*(sigfunc))(sig, (siginfo_t *)info->si_code, ucp);
242 }
243
244 /*
245 * Restore the thread's signal mask.
246 */
247 if (saved_seqno == curthread->sigmask_seqno)
248 curthread->tmbx.tm_context.uc_sigmask = saved_mask;
249 else
250 curthread->tmbx.tm_context.uc_sigmask = curthread->sigmask;
251}
252
253/*
254 * Find a thread that can handle the signal. This must be called
255 * with upcalls disabled.
256 */
257struct pthread *
258thr_sig_find(struct kse *curkse, int sig, siginfo_t *info)
259{
260 int handler_installed;
261 struct pthread *pthread;
262 struct pthread *suspended_thread, *signaled_thread;
263
264 DBG_MSG("Looking for thread to handle signal %d\n", sig);
265
266 handler_installed = (_thread_sigact[sig - 1].sa_handler != SIG_IGN) &&
267 (_thread_sigact[sig - 1].sa_handler != SIG_DFL);
268
269 /* Check if the signal requires a dump of thread information: */
270 if (sig == SIGINFO) {
271 /* Dump thread information to file: */
272 _thread_dump_info();
273 }
274 /*
275 * Enter a loop to look for threads that have the signal
276 * unmasked. POSIX specifies that a thread in a sigwait
277 * will get the signal over any other threads. Second
278 * preference will be threads in in a sigsuspend. Third
279 * preference will be the current thread. If none of the
280 * above, then the signal is delivered to the first thread
281 * that is found. Note that if a custom handler is not
282 * installed, the signal only affects threads in sigwait.
283 */
284 suspended_thread = NULL;
285 signaled_thread = NULL;
286
287 KSE_LOCK_ACQUIRE(curkse, &_thread_list_lock);
288 TAILQ_FOREACH(pthread, &_thread_list, tle) {
289 /* Take the scheduling lock. */
290 KSE_SCHED_LOCK(curkse, pthread->kseg);
291 if ((pthread->state == PS_SIGWAIT) &&
292 sigismember(pthread->data.sigwait, sig)) {
293 /*
294 * Return the signal number and make the
295 * thread runnable.
296 */
297 pthread->signo = sig;
298 _thr_setrunnable_unlocked(pthread);
299
300 KSE_SCHED_UNLOCK(curkse, pthread->kseg);
301
302 /*
303 * POSIX doesn't doesn't specify which thread
304 * will get the signal if there are multiple
305 * waiters, so we give it to the first thread
306 * we find.
307 *
308 * Do not attempt to deliver this signal
309 * to other threads and do not add the signal
310 * to the process pending set.
311 */
312 KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
313 DBG_MSG("Waking thread %p in sigwait with signal %d\n",
314 pthread, sig);
315 return (NULL);
316 }
317 else if ((pthread->state == PS_DEAD) ||
318 (pthread->state == PS_DEADLOCK) ||
319 THR_IS_EXITING(pthread) || THR_IS_SUSPENDED(pthread))
320 ; /* Skip this thread. */
321 else if ((handler_installed != 0) &&
322 !sigismember(&pthread->tmbx.tm_context.uc_sigmask, sig)) {
323 if (pthread->state == PS_SIGSUSPEND) {
172 }
173}
174
175void
176_thr_sig_handler(int sig, siginfo_t *info, ucontext_t *ucp)
177{
178 void (*sigfunc)(int, siginfo_t *, void *);
179 struct kse *curkse;
180
181 curkse = _get_curkse();
182 if ((curkse == NULL) || ((curkse->k_flags & KF_STARTED) == 0)) {
183 /* Upcalls are not yet started; just call the handler. */
184 sigfunc = _thread_sigact[sig - 1].sa_sigaction;
185 ucp->uc_sigmask = _thr_proc_sigmask;
186 if (((__sighandler_t *)sigfunc != SIG_DFL) &&
187 ((__sighandler_t *)sigfunc != SIG_IGN)) {
188 if (((_thread_sigact[sig - 1].sa_flags & SA_SIGINFO)
189 != 0) || (info == NULL))
190 (*(sigfunc))(sig, info, ucp);
191 else
192 (*(sigfunc))(sig, (siginfo_t *)info->si_code,
193 ucp);
194 }
195 }
196 else {
197 /* Nothing. */
198 DBG_MSG("Got signal %d\n", sig);
199 sigaddset(&curkse->k_mbx.km_sigscaught, sig);
200 ucp->uc_sigmask = _thr_proc_sigmask;
201 }
202}
203
204static void
205thr_sig_invoke_handler(struct pthread *curthread, int sig, siginfo_t *info,
206 ucontext_t *ucp)
207{
208 void (*sigfunc)(int, siginfo_t *, void *);
209 sigset_t saved_mask;
210 int saved_seqno;
211
212 /* Invoke the signal handler without going through the scheduler:
213 */
214 DBG_MSG("Got signal %d, calling handler for current thread %p\n",
215 sig, curthread);
216
217 /*
218 * Setup the threads signal mask.
219 *
220 * The mask is changed in the thread's active signal mask
221 * (in the context) and not in the base signal mask because
222 * a thread is allowed to change its signal mask within a
223 * signal handler. If it does, the signal mask restored
224 * after the handler should be the same as that set by the
225 * thread during the handler, not the original mask from
226 * before calling the handler. The thread could also
227 * modify the signal mask in the context and expect this
228 * mask to be used.
229 */
230 THR_SCHED_LOCK(curthread, curthread);
231 saved_mask = curthread->tmbx.tm_context.uc_sigmask;
232 saved_seqno = curthread->sigmask_seqno;
233 SIGSETOR(curthread->tmbx.tm_context.uc_sigmask,
234 _thread_sigact[sig - 1].sa_mask);
235 sigaddset(&curthread->tmbx.tm_context.uc_sigmask, sig);
236 THR_SCHED_UNLOCK(curthread, curthread);
237
238 /*
239 * Check that a custom handler is installed and if
240 * the signal is not blocked:
241 */
242 sigfunc = _thread_sigact[sig - 1].sa_sigaction;
243 ucp->uc_sigmask = _thr_proc_sigmask;
244 if (((__sighandler_t *)sigfunc != SIG_DFL) &&
245 ((__sighandler_t *)sigfunc != SIG_IGN)) {
246 if (((_thread_sigact[sig - 1].sa_flags & SA_SIGINFO) != 0) ||
247 (info == NULL))
248 (*(sigfunc))(sig, info, ucp);
249 else
250 (*(sigfunc))(sig, (siginfo_t *)info->si_code, ucp);
251 }
252
253 /*
254 * Restore the thread's signal mask.
255 */
256 if (saved_seqno == curthread->sigmask_seqno)
257 curthread->tmbx.tm_context.uc_sigmask = saved_mask;
258 else
259 curthread->tmbx.tm_context.uc_sigmask = curthread->sigmask;
260}
261
262/*
263 * Find a thread that can handle the signal. This must be called
264 * with upcalls disabled.
265 */
266struct pthread *
267thr_sig_find(struct kse *curkse, int sig, siginfo_t *info)
268{
269 int handler_installed;
270 struct pthread *pthread;
271 struct pthread *suspended_thread, *signaled_thread;
272
273 DBG_MSG("Looking for thread to handle signal %d\n", sig);
274
275 handler_installed = (_thread_sigact[sig - 1].sa_handler != SIG_IGN) &&
276 (_thread_sigact[sig - 1].sa_handler != SIG_DFL);
277
278 /* Check if the signal requires a dump of thread information: */
279 if (sig == SIGINFO) {
280 /* Dump thread information to file: */
281 _thread_dump_info();
282 }
283 /*
284 * Enter a loop to look for threads that have the signal
285 * unmasked. POSIX specifies that a thread in a sigwait
286 * will get the signal over any other threads. Second
287 * preference will be threads in in a sigsuspend. Third
288 * preference will be the current thread. If none of the
289 * above, then the signal is delivered to the first thread
290 * that is found. Note that if a custom handler is not
291 * installed, the signal only affects threads in sigwait.
292 */
293 suspended_thread = NULL;
294 signaled_thread = NULL;
295
296 KSE_LOCK_ACQUIRE(curkse, &_thread_list_lock);
297 TAILQ_FOREACH(pthread, &_thread_list, tle) {
298 /* Take the scheduling lock. */
299 KSE_SCHED_LOCK(curkse, pthread->kseg);
300 if ((pthread->state == PS_SIGWAIT) &&
301 sigismember(pthread->data.sigwait, sig)) {
302 /*
303 * Return the signal number and make the
304 * thread runnable.
305 */
306 pthread->signo = sig;
307 _thr_setrunnable_unlocked(pthread);
308
309 KSE_SCHED_UNLOCK(curkse, pthread->kseg);
310
311 /*
312 * POSIX doesn't doesn't specify which thread
313 * will get the signal if there are multiple
314 * waiters, so we give it to the first thread
315 * we find.
316 *
317 * Do not attempt to deliver this signal
318 * to other threads and do not add the signal
319 * to the process pending set.
320 */
321 KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
322 DBG_MSG("Waking thread %p in sigwait with signal %d\n",
323 pthread, sig);
324 return (NULL);
325 }
326 else if ((pthread->state == PS_DEAD) ||
327 (pthread->state == PS_DEADLOCK) ||
328 THR_IS_EXITING(pthread) || THR_IS_SUSPENDED(pthread))
329 ; /* Skip this thread. */
330 else if ((handler_installed != 0) &&
331 !sigismember(&pthread->tmbx.tm_context.uc_sigmask, sig)) {
332 if (pthread->state == PS_SIGSUSPEND) {
324 if (suspended_thread == NULL)
333 if (suspended_thread == NULL) {
325 suspended_thread = pthread;
334 suspended_thread = pthread;
326 } else if (signaled_thread == NULL)
335 suspended_thread->refcount++;
336 }
337 } else if (signaled_thread == NULL) {
327 signaled_thread = pthread;
338 signaled_thread = pthread;
339 signaled_thread->refcount++;
340 }
328 }
329 KSE_SCHED_UNLOCK(curkse, pthread->kseg);
330 }
331 KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
332
333 /*
334 * Only perform wakeups and signal delivery if there is a
335 * custom handler installed:
336 */
337 if (handler_installed == 0) {
338 /*
339 * There is no handler installed; nothing to do here.
340 */
341 } else if (suspended_thread == NULL &&
342 signaled_thread == NULL) {
343 /*
344 * Add it to the set of signals pending
345 * on the process:
346 */
347 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
348 if (!sigismember(&_thr_proc_sigpending, sig)) {
349 sigaddset(&_thr_proc_sigpending, sig);
350 if (info == NULL)
351 build_siginfo(&_thr_proc_siginfo[sig], sig);
352 else
353 memcpy(&_thr_proc_siginfo[sig], info,
354 sizeof(*info));
355 }
356 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
357 } else {
358 /*
359 * We only deliver the signal to one thread;
360 * give preference to the suspended thread:
361 */
341 }
342 KSE_SCHED_UNLOCK(curkse, pthread->kseg);
343 }
344 KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
345
346 /*
347 * Only perform wakeups and signal delivery if there is a
348 * custom handler installed:
349 */
350 if (handler_installed == 0) {
351 /*
352 * There is no handler installed; nothing to do here.
353 */
354 } else if (suspended_thread == NULL &&
355 signaled_thread == NULL) {
356 /*
357 * Add it to the set of signals pending
358 * on the process:
359 */
360 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
361 if (!sigismember(&_thr_proc_sigpending, sig)) {
362 sigaddset(&_thr_proc_sigpending, sig);
363 if (info == NULL)
364 build_siginfo(&_thr_proc_siginfo[sig], sig);
365 else
366 memcpy(&_thr_proc_siginfo[sig], info,
367 sizeof(*info));
368 }
369 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
370 } else {
371 /*
372 * We only deliver the signal to one thread;
373 * give preference to the suspended thread:
374 */
362 if (suspended_thread != NULL)
375 if (suspended_thread != NULL) {
363 pthread = suspended_thread;
376 pthread = suspended_thread;
364 else
377 _thr_ref_delete(NULL, signaled_thread);
378 } else
365 pthread = signaled_thread;
366 return (pthread);
367 }
368 return (NULL);
369}
370
371static void
372build_siginfo(siginfo_t *info, int signo)
373{
374 bzero(info, sizeof(*info));
375 info->si_signo = signo;
376 info->si_pid = _thr_pid;
377}
378
379/*
380 * This is called by a thread when it has pending signals to deliver.
381 * It should only be called from the context of the thread.
382 */
383void
384_thr_sig_rundown(struct pthread *curthread, ucontext_t *ucp,
385 struct pthread_sigframe *psf)
386{
387 struct pthread_sigframe psf_save;
388 sigset_t sigset;
389 int i;
390
391 THR_SCHED_LOCK(curthread, curthread);
392 memcpy(&sigset, &curthread->sigpend, sizeof(sigset));
393 sigemptyset(&curthread->sigpend);
394 if (psf != NULL) {
395 memcpy(&psf_save, psf, sizeof(*psf));
396 SIGSETOR(sigset, psf_save.psf_sigset);
397 sigemptyset(&psf->psf_sigset);
398 }
399 THR_SCHED_UNLOCK(curthread, curthread);
400
401 /* Check the threads previous state: */
402 if ((psf != NULL) && (psf_save.psf_state != PS_RUNNING)) {
403 /*
404 * Do a little cleanup handling for those threads in
405 * queues before calling the signal handler. Signals
406 * for these threads are temporarily blocked until
407 * after cleanup handling.
408 */
409 switch (psf_save.psf_state) {
410 case PS_COND_WAIT:
411 _cond_wait_backout(curthread);
412 psf_save.psf_state = PS_RUNNING;
413 break;
414
415 case PS_MUTEX_WAIT:
416 _mutex_lock_backout(curthread);
417 psf_save.psf_state = PS_RUNNING;
418 break;
419
420 default:
421 break;
422 }
423 }
424 /*
425 * Lower the priority before calling the handler in case
426 * it never returns (longjmps back):
427 */
428 curthread->active_priority &= ~THR_SIGNAL_PRIORITY;
429
430 for (i = 1; i < NSIG; i++) {
431 if (sigismember(&sigset, i) != 0) {
432 /* Call the handler: */
433 thr_sig_invoke_handler(curthread, i,
434 &curthread->siginfo[i], ucp);
435 }
436 }
437
438 THR_SCHED_LOCK(curthread, curthread);
439 if (psf != NULL)
440 thr_sigframe_restore(curthread, &psf_save);
441 /* Restore the signal mask. */
442 curthread->tmbx.tm_context.uc_sigmask = curthread->sigmask;
443 THR_SCHED_UNLOCK(curthread, curthread);
444 _thr_sig_check_pending(curthread);
445}
446
447/*
448 * This checks pending signals for the current thread. It should be
449 * called whenever a thread changes its signal mask. Note that this
450 * is called from a thread (using its stack).
451 *
452 * XXX - We might want to just check to see if there are pending
453 * signals for the thread here, but enter the UTS scheduler
454 * to actually install the signal handler(s).
455 */
456void
457_thr_sig_check_pending(struct pthread *curthread)
458{
459 sigset_t sigset;
460 sigset_t pending_process;
461 sigset_t pending_thread;
462 kse_critical_t crit;
463 int i;
464
465 curthread->check_pending = 0;
466
467 /*
468 * Check if there are pending signals for the running
469 * thread or process that aren't blocked:
470 */
471 crit = _kse_critical_enter();
472 KSE_LOCK_ACQUIRE(curthread->kse, &_thread_signal_lock);
473 sigset = _thr_proc_sigpending;
474 KSE_LOCK_RELEASE(curthread->kse, &_thread_signal_lock);
475 _kse_critical_leave(crit);
476
477 THR_SCHED_LOCK(curthread, curthread);
478 SIGSETOR(sigset, curthread->sigpend);
479 SIGSETNAND(sigset, curthread->tmbx.tm_context.uc_sigmask);
480 if (SIGNOTEMPTY(sigset)) {
481 ucontext_t uc;
482 volatile int once;
483
484 curthread->check_pending = 0;
485 THR_SCHED_UNLOCK(curthread, curthread);
486
487 /*
488 * Split the pending signals into those that were
489 * pending on the process and those that were pending
490 * on the thread.
491 */
492 sigfillset(&pending_process);
493 sigfillset(&pending_thread);
494 for (i = 1; i < NSIG; i++) {
495 if (sigismember(&sigset, i) != 0) {
496 if (sigismember(&curthread->sigpend, i) != 0) {
497 build_siginfo(&curthread->siginfo[i], i);
498 sigdelset(&pending_thread, i);
499 } else {
500 memcpy(&curthread->siginfo[i],
501 &_thr_proc_siginfo[i],
502 sizeof(siginfo_t));
503 sigdelset(&pending_process, i);
504 }
505 }
506 }
507 /*
508 * Remove any process pending signals that were scheduled
509 * to be delivered from process' pending set.
510 */
511 crit = _kse_critical_enter();
512 KSE_LOCK_ACQUIRE(curthread->kse, &_thread_signal_lock);
513 SIGSETAND(_thr_proc_sigpending, pending_process);
514 KSE_LOCK_RELEASE(curthread->kse, &_thread_signal_lock);
515 _kse_critical_leave(crit);
516
517 /*
518 * Remove any thread pending signals that were scheduled
519 * to be delivered from thread's pending set.
520 */
521 THR_SCHED_LOCK(curthread, curthread);
522 SIGSETAND(curthread->sigpend, pending_thread);
523 THR_SCHED_UNLOCK(curthread, curthread);
524
525 once = 0;
526 THR_GETCONTEXT(&uc);
527 if (once == 0) {
528 once = 1;
529 for (i = 1; i < NSIG; i++) {
530 if (sigismember(&sigset, i) != 0) {
531 /* Call the handler: */
532 thr_sig_invoke_handler(curthread, i,
533 &curthread->siginfo[i], &uc);
534 }
535 }
536 }
537 }
538 else
539 THR_SCHED_UNLOCK(curthread, curthread);
540}
541
542/*
543 * This must be called with upcalls disabled.
544 */
545static void
546handle_special_signals(struct kse *curkse, int sig)
547{
548 switch (sig) {
549 /*
550 * POSIX says that pending SIGCONT signals are
551 * discarded when one of these signals occurs.
552 */
553 case SIGTSTP:
554 case SIGTTIN:
555 case SIGTTOU:
556 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
557 sigdelset(&_thr_proc_sigpending, SIGCONT);
558 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
559 break;
560
561 default:
562 break;
563 }
564}
565
566/*
567 * Perform thread specific actions in response to a signal.
568 * This function is only called if there is a handler installed
569 * for the signal, and if the target thread has the signal
570 * unmasked.
571 *
572 * This must be called with the thread's scheduling lock held.
573 */
574void
575_thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info)
576{
577 int restart;
578 int suppress_handler = 0;
579
580 if (pthread->curframe == NULL) {
581 /*
582 * This thread is active. Just add it to the
583 * thread's pending set.
584 */
585 sigaddset(&pthread->sigpend, sig);
586 pthread->check_pending = 1;
587 if (info == NULL)
588 build_siginfo(&pthread->siginfo[sig], sig);
589 else if (info != &pthread->siginfo[sig])
590 memcpy(&pthread->siginfo[sig], info,
591 sizeof(*info));
592 if ((pthread->blocked != 0) && !THR_IN_CRITICAL(pthread))
593 kse_thr_interrupt(&pthread->tmbx /* XXX - restart?!?! */);
594 }
595 else {
596 restart = _thread_sigact[sig - 1].sa_flags & SA_RESTART;
597
598 /* Make sure this signal isn't still in the pending set: */
599 sigdelset(&pthread->sigpend, sig);
600
601 /*
602 * Process according to thread state:
603 */
604 switch (pthread->state) {
605 /*
606 * States which do not change when a signal is trapped:
607 */
608 case PS_DEAD:
609 case PS_DEADLOCK:
610 case PS_LOCKWAIT:
611 case PS_SUSPENDED:
612 case PS_STATE_MAX:
613 /*
614 * You can't call a signal handler for threads in these
615 * states.
616 */
617 suppress_handler = 1;
618 break;
619
620 /*
621 * States which do not need any cleanup handling when signals
622 * occur:
623 */
624 case PS_RUNNING:
625 /*
626 * Remove the thread from the queue before changing its
627 * priority:
628 */
629 if ((pthread->flags & THR_FLAGS_IN_RUNQ) != 0)
630 THR_RUNQ_REMOVE(pthread);
631 break;
632
633 /*
634 * States which cannot be interrupted but still require the
635 * signal handler to run:
636 */
637 case PS_COND_WAIT:
638 case PS_MUTEX_WAIT:
639 /*
640 * Remove the thread from the wait queue. It will
641 * be added back to the wait queue once all signal
642 * handlers have been invoked.
643 */
644 KSE_WAITQ_REMOVE(pthread->kse, pthread);
645 break;
646
647 case PS_SLEEP_WAIT:
648 /*
649 * Unmasked signals always cause sleep to terminate
650 * early regardless of SA_RESTART:
651 */
652 pthread->interrupted = 1;
653 KSE_WAITQ_REMOVE(pthread->kse, pthread);
654 THR_SET_STATE(pthread, PS_RUNNING);
655 break;
656
657 case PS_JOIN:
658 case PS_SIGSUSPEND:
659 KSE_WAITQ_REMOVE(pthread->kse, pthread);
660 THR_SET_STATE(pthread, PS_RUNNING);
661 break;
662
663 case PS_SIGWAIT:
664 /*
665 * The signal handler is not called for threads in
666 * SIGWAIT.
667 */
668 suppress_handler = 1;
669 /* Wake up the thread if the signal is blocked. */
670 if (sigismember(pthread->data.sigwait, sig)) {
671 /* Return the signal number: */
672 pthread->signo = sig;
673
674 /* Make the thread runnable: */
675 _thr_setrunnable_unlocked(pthread);
676 } else
677 /* Increment the pending signal count. */
678 sigaddset(&pthread->sigpend, sig);
679 break;
680 }
681
682 if (suppress_handler == 0) {
683 /*
684 * Setup a signal frame and save the current threads
685 * state:
686 */
687 thr_sigframe_add(pthread, sig, info);
688
689 if (pthread->state != PS_RUNNING)
690 THR_SET_STATE(pthread, PS_RUNNING);
691
692 /*
693 * The thread should be removed from all scheduling
694 * queues at this point. Raise the priority and
695 * place the thread in the run queue. It is also
696 * possible for a signal to be sent to a suspended
697 * thread, mostly via pthread_kill(). If a thread
698 * is suspended, don't insert it into the priority
699 * queue; just set its state to suspended and it
700 * will run the signal handler when it is resumed.
701 */
702 pthread->active_priority |= THR_SIGNAL_PRIORITY;
703 if ((pthread->flags & THR_FLAGS_IN_RUNQ) == 0)
704 THR_RUNQ_INSERT_TAIL(pthread);
705 }
706 }
707}
708
709static void
710thr_sig_check_state(struct pthread *pthread, int sig)
711{
712 /*
713 * Process according to thread state:
714 */
715 switch (pthread->state) {
716 /*
717 * States which do not change when a signal is trapped:
718 */
719 case PS_RUNNING:
720 case PS_LOCKWAIT:
721 case PS_MUTEX_WAIT:
722 case PS_COND_WAIT:
723 case PS_JOIN:
724 case PS_SUSPENDED:
725 case PS_DEAD:
726 case PS_DEADLOCK:
727 case PS_STATE_MAX:
728 break;
729
730 case PS_SIGWAIT:
731 /* Wake up the thread if the signal is blocked. */
732 if (sigismember(pthread->data.sigwait, sig)) {
733 /* Return the signal number: */
734 pthread->signo = sig;
735
736 /* Change the state of the thread to run: */
737 _thr_setrunnable_unlocked(pthread);
738 } else
739 /* Increment the pending signal count. */
740 sigaddset(&pthread->sigpend, sig);
741 break;
742
743 case PS_SIGSUSPEND:
744 case PS_SLEEP_WAIT:
745 /*
746 * Remove the thread from the wait queue and make it
747 * runnable:
748 */
749 _thr_setrunnable_unlocked(pthread);
750
751 /* Flag the operation as interrupted: */
752 pthread->interrupted = 1;
753 break;
754 }
755}
756
757/*
758 * Send a signal to a specific thread (ala pthread_kill):
759 */
760void
761_thr_sig_send(struct pthread *pthread, int sig)
762{
763 struct pthread *curthread = _get_curthread();
764
765 /* Lock the scheduling queue of the target thread. */
766 THR_SCHED_LOCK(curthread, pthread);
767
768 /* Check for signals whose actions are SIG_DFL: */
769 if (_thread_sigact[sig - 1].sa_handler == SIG_DFL) {
770 /*
771 * Check to see if a temporary signal handler is
772 * installed for sigwaiters:
773 */
774 if (_thread_dfl_count[sig] == 0) {
775 /*
776 * Deliver the signal to the process if a handler
777 * is not installed:
778 */
779 THR_SCHED_UNLOCK(curthread, pthread);
780 kill(getpid(), sig);
781 THR_SCHED_LOCK(curthread, pthread);
782 }
783 /*
784 * Assuming we're still running after the above kill(),
785 * make any necessary state changes to the thread:
786 */
787 thr_sig_check_state(pthread, sig);
788 THR_SCHED_UNLOCK(curthread, pthread);
789 }
790 /*
791 * Check that the signal is not being ignored:
792 */
793 else if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) {
794 if (pthread->state == PS_SIGWAIT &&
795 sigismember(pthread->data.sigwait, sig)) {
796 /* Return the signal number: */
797 pthread->signo = sig;
798
799 /* Change the state of the thread to run: */
800 _thr_setrunnable_unlocked(pthread);
801 THR_SCHED_UNLOCK(curthread, pthread);
802 } else if (sigismember(&pthread->tmbx.tm_context.uc_sigmask, sig)) {
803 /* Add the signal to the pending set: */
804 sigaddset(&pthread->sigpend, sig);
805 THR_SCHED_UNLOCK(curthread, pthread);
806 } else if (pthread == curthread) {
807 ucontext_t uc;
808 siginfo_t info;
809 volatile int once;
810
811 THR_SCHED_UNLOCK(curthread, pthread);
812 build_siginfo(&info, sig);
813 once = 0;
814 THR_GETCONTEXT(&uc);
815 if (once == 0) {
816 once = 1;
817 /*
818 * Call the signal handler for the current
819 * thread:
820 */
821 thr_sig_invoke_handler(curthread, sig,
822 &info, &uc);
823 }
824 } else {
825 /*
826 * Perform any state changes due to signal
827 * arrival:
828 */
829 _thr_sig_add(pthread, sig, NULL);
830 THR_SCHED_UNLOCK(curthread, pthread);
831 }
832 }
833}
834
835static void
836thr_sigframe_add(struct pthread *thread, int sig, siginfo_t *info)
837{
838 if (thread->curframe == NULL)
839 PANIC("Thread doesn't have signal frame ");
840
841 if (thread->have_signals == 0) {
842 /*
843 * Multiple signals can be added to the same signal
844 * frame. Only save the thread's state the first time.
845 */
846 thr_sigframe_save(thread, thread->curframe);
847 thread->have_signals = 1;
848 thread->flags &= THR_FLAGS_PRIVATE;
849 }
850 sigaddset(&thread->curframe->psf_sigset, sig);
851 if (info == NULL)
852 build_siginfo(&thread->siginfo[sig], sig);
853 else if (info != &thread->siginfo[sig])
854 memcpy(&thread->siginfo[sig], info, sizeof(*info));
855
856 /* Setup the new signal mask. */
857 SIGSETOR(thread->tmbx.tm_context.uc_sigmask,
858 _thread_sigact[sig - 1].sa_mask);
859 sigaddset(&thread->tmbx.tm_context.uc_sigmask, sig);
860}
861
862void
863thr_sigframe_restore(struct pthread *thread, struct pthread_sigframe *psf)
864{
865 thread->flags = psf->psf_flags;
866 thread->interrupted = psf->psf_interrupted;
867 thread->signo = psf->psf_signo;
868 thread->state = psf->psf_state;
869 thread->data = psf->psf_wait_data;
870 thread->wakeup_time = psf->psf_wakeup_time;
871 if (thread->sigmask_seqno == psf->psf_seqno)
872 thread->tmbx.tm_context.uc_sigmask = psf->psf_sigmask;
873 else
874 thread->tmbx.tm_context.uc_sigmask = thread->sigmask;
875}
876
877static void
878thr_sigframe_save(struct pthread *thread, struct pthread_sigframe *psf)
879{
880 /* This has to initialize all members of the sigframe. */
881 psf->psf_flags = thread->flags & THR_FLAGS_PRIVATE;
882 psf->psf_interrupted = thread->interrupted;
883 psf->psf_signo = thread->signo;
884 psf->psf_state = thread->state;
885 psf->psf_wait_data = thread->data;
886 psf->psf_wakeup_time = thread->wakeup_time;
887 psf->psf_sigmask = thread->tmbx.tm_context.uc_sigmask;
888 psf->psf_seqno = thread->sigmask_seqno;
889 sigemptyset(&psf->psf_sigset);
890}
379 pthread = signaled_thread;
380 return (pthread);
381 }
382 return (NULL);
383}
384
385static void
386build_siginfo(siginfo_t *info, int signo)
387{
388 bzero(info, sizeof(*info));
389 info->si_signo = signo;
390 info->si_pid = _thr_pid;
391}
392
393/*
394 * This is called by a thread when it has pending signals to deliver.
395 * It should only be called from the context of the thread.
396 */
397void
398_thr_sig_rundown(struct pthread *curthread, ucontext_t *ucp,
399 struct pthread_sigframe *psf)
400{
401 struct pthread_sigframe psf_save;
402 sigset_t sigset;
403 int i;
404
405 THR_SCHED_LOCK(curthread, curthread);
406 memcpy(&sigset, &curthread->sigpend, sizeof(sigset));
407 sigemptyset(&curthread->sigpend);
408 if (psf != NULL) {
409 memcpy(&psf_save, psf, sizeof(*psf));
410 SIGSETOR(sigset, psf_save.psf_sigset);
411 sigemptyset(&psf->psf_sigset);
412 }
413 THR_SCHED_UNLOCK(curthread, curthread);
414
415 /* Check the threads previous state: */
416 if ((psf != NULL) && (psf_save.psf_state != PS_RUNNING)) {
417 /*
418 * Do a little cleanup handling for those threads in
419 * queues before calling the signal handler. Signals
420 * for these threads are temporarily blocked until
421 * after cleanup handling.
422 */
423 switch (psf_save.psf_state) {
424 case PS_COND_WAIT:
425 _cond_wait_backout(curthread);
426 psf_save.psf_state = PS_RUNNING;
427 break;
428
429 case PS_MUTEX_WAIT:
430 _mutex_lock_backout(curthread);
431 psf_save.psf_state = PS_RUNNING;
432 break;
433
434 default:
435 break;
436 }
437 }
438 /*
439 * Lower the priority before calling the handler in case
440 * it never returns (longjmps back):
441 */
442 curthread->active_priority &= ~THR_SIGNAL_PRIORITY;
443
444 for (i = 1; i < NSIG; i++) {
445 if (sigismember(&sigset, i) != 0) {
446 /* Call the handler: */
447 thr_sig_invoke_handler(curthread, i,
448 &curthread->siginfo[i], ucp);
449 }
450 }
451
452 THR_SCHED_LOCK(curthread, curthread);
453 if (psf != NULL)
454 thr_sigframe_restore(curthread, &psf_save);
455 /* Restore the signal mask. */
456 curthread->tmbx.tm_context.uc_sigmask = curthread->sigmask;
457 THR_SCHED_UNLOCK(curthread, curthread);
458 _thr_sig_check_pending(curthread);
459}
460
461/*
462 * This checks pending signals for the current thread. It should be
463 * called whenever a thread changes its signal mask. Note that this
464 * is called from a thread (using its stack).
465 *
466 * XXX - We might want to just check to see if there are pending
467 * signals for the thread here, but enter the UTS scheduler
468 * to actually install the signal handler(s).
469 */
470void
471_thr_sig_check_pending(struct pthread *curthread)
472{
473 sigset_t sigset;
474 sigset_t pending_process;
475 sigset_t pending_thread;
476 kse_critical_t crit;
477 int i;
478
479 curthread->check_pending = 0;
480
481 /*
482 * Check if there are pending signals for the running
483 * thread or process that aren't blocked:
484 */
485 crit = _kse_critical_enter();
486 KSE_LOCK_ACQUIRE(curthread->kse, &_thread_signal_lock);
487 sigset = _thr_proc_sigpending;
488 KSE_LOCK_RELEASE(curthread->kse, &_thread_signal_lock);
489 _kse_critical_leave(crit);
490
491 THR_SCHED_LOCK(curthread, curthread);
492 SIGSETOR(sigset, curthread->sigpend);
493 SIGSETNAND(sigset, curthread->tmbx.tm_context.uc_sigmask);
494 if (SIGNOTEMPTY(sigset)) {
495 ucontext_t uc;
496 volatile int once;
497
498 curthread->check_pending = 0;
499 THR_SCHED_UNLOCK(curthread, curthread);
500
501 /*
502 * Split the pending signals into those that were
503 * pending on the process and those that were pending
504 * on the thread.
505 */
506 sigfillset(&pending_process);
507 sigfillset(&pending_thread);
508 for (i = 1; i < NSIG; i++) {
509 if (sigismember(&sigset, i) != 0) {
510 if (sigismember(&curthread->sigpend, i) != 0) {
511 build_siginfo(&curthread->siginfo[i], i);
512 sigdelset(&pending_thread, i);
513 } else {
514 memcpy(&curthread->siginfo[i],
515 &_thr_proc_siginfo[i],
516 sizeof(siginfo_t));
517 sigdelset(&pending_process, i);
518 }
519 }
520 }
521 /*
522 * Remove any process pending signals that were scheduled
523 * to be delivered from process' pending set.
524 */
525 crit = _kse_critical_enter();
526 KSE_LOCK_ACQUIRE(curthread->kse, &_thread_signal_lock);
527 SIGSETAND(_thr_proc_sigpending, pending_process);
528 KSE_LOCK_RELEASE(curthread->kse, &_thread_signal_lock);
529 _kse_critical_leave(crit);
530
531 /*
532 * Remove any thread pending signals that were scheduled
533 * to be delivered from thread's pending set.
534 */
535 THR_SCHED_LOCK(curthread, curthread);
536 SIGSETAND(curthread->sigpend, pending_thread);
537 THR_SCHED_UNLOCK(curthread, curthread);
538
539 once = 0;
540 THR_GETCONTEXT(&uc);
541 if (once == 0) {
542 once = 1;
543 for (i = 1; i < NSIG; i++) {
544 if (sigismember(&sigset, i) != 0) {
545 /* Call the handler: */
546 thr_sig_invoke_handler(curthread, i,
547 &curthread->siginfo[i], &uc);
548 }
549 }
550 }
551 }
552 else
553 THR_SCHED_UNLOCK(curthread, curthread);
554}
555
556/*
557 * This must be called with upcalls disabled.
558 */
559static void
560handle_special_signals(struct kse *curkse, int sig)
561{
562 switch (sig) {
563 /*
564 * POSIX says that pending SIGCONT signals are
565 * discarded when one of these signals occurs.
566 */
567 case SIGTSTP:
568 case SIGTTIN:
569 case SIGTTOU:
570 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
571 sigdelset(&_thr_proc_sigpending, SIGCONT);
572 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
573 break;
574
575 default:
576 break;
577 }
578}
579
580/*
581 * Perform thread specific actions in response to a signal.
582 * This function is only called if there is a handler installed
583 * for the signal, and if the target thread has the signal
584 * unmasked.
585 *
586 * This must be called with the thread's scheduling lock held.
587 */
588void
589_thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info)
590{
591 int restart;
592 int suppress_handler = 0;
593
594 if (pthread->curframe == NULL) {
595 /*
596 * This thread is active. Just add it to the
597 * thread's pending set.
598 */
599 sigaddset(&pthread->sigpend, sig);
600 pthread->check_pending = 1;
601 if (info == NULL)
602 build_siginfo(&pthread->siginfo[sig], sig);
603 else if (info != &pthread->siginfo[sig])
604 memcpy(&pthread->siginfo[sig], info,
605 sizeof(*info));
606 if ((pthread->blocked != 0) && !THR_IN_CRITICAL(pthread))
607 kse_thr_interrupt(&pthread->tmbx /* XXX - restart?!?! */);
608 }
609 else {
610 restart = _thread_sigact[sig - 1].sa_flags & SA_RESTART;
611
612 /* Make sure this signal isn't still in the pending set: */
613 sigdelset(&pthread->sigpend, sig);
614
615 /*
616 * Process according to thread state:
617 */
618 switch (pthread->state) {
619 /*
620 * States which do not change when a signal is trapped:
621 */
622 case PS_DEAD:
623 case PS_DEADLOCK:
624 case PS_LOCKWAIT:
625 case PS_SUSPENDED:
626 case PS_STATE_MAX:
627 /*
628 * You can't call a signal handler for threads in these
629 * states.
630 */
631 suppress_handler = 1;
632 break;
633
634 /*
635 * States which do not need any cleanup handling when signals
636 * occur:
637 */
638 case PS_RUNNING:
639 /*
640 * Remove the thread from the queue before changing its
641 * priority:
642 */
643 if ((pthread->flags & THR_FLAGS_IN_RUNQ) != 0)
644 THR_RUNQ_REMOVE(pthread);
645 break;
646
647 /*
648 * States which cannot be interrupted but still require the
649 * signal handler to run:
650 */
651 case PS_COND_WAIT:
652 case PS_MUTEX_WAIT:
653 /*
654 * Remove the thread from the wait queue. It will
655 * be added back to the wait queue once all signal
656 * handlers have been invoked.
657 */
658 KSE_WAITQ_REMOVE(pthread->kse, pthread);
659 break;
660
661 case PS_SLEEP_WAIT:
662 /*
663 * Unmasked signals always cause sleep to terminate
664 * early regardless of SA_RESTART:
665 */
666 pthread->interrupted = 1;
667 KSE_WAITQ_REMOVE(pthread->kse, pthread);
668 THR_SET_STATE(pthread, PS_RUNNING);
669 break;
670
671 case PS_JOIN:
672 case PS_SIGSUSPEND:
673 KSE_WAITQ_REMOVE(pthread->kse, pthread);
674 THR_SET_STATE(pthread, PS_RUNNING);
675 break;
676
677 case PS_SIGWAIT:
678 /*
679 * The signal handler is not called for threads in
680 * SIGWAIT.
681 */
682 suppress_handler = 1;
683 /* Wake up the thread if the signal is blocked. */
684 if (sigismember(pthread->data.sigwait, sig)) {
685 /* Return the signal number: */
686 pthread->signo = sig;
687
688 /* Make the thread runnable: */
689 _thr_setrunnable_unlocked(pthread);
690 } else
691 /* Increment the pending signal count. */
692 sigaddset(&pthread->sigpend, sig);
693 break;
694 }
695
696 if (suppress_handler == 0) {
697 /*
698 * Setup a signal frame and save the current threads
699 * state:
700 */
701 thr_sigframe_add(pthread, sig, info);
702
703 if (pthread->state != PS_RUNNING)
704 THR_SET_STATE(pthread, PS_RUNNING);
705
706 /*
707 * The thread should be removed from all scheduling
708 * queues at this point. Raise the priority and
709 * place the thread in the run queue. It is also
710 * possible for a signal to be sent to a suspended
711 * thread, mostly via pthread_kill(). If a thread
712 * is suspended, don't insert it into the priority
713 * queue; just set its state to suspended and it
714 * will run the signal handler when it is resumed.
715 */
716 pthread->active_priority |= THR_SIGNAL_PRIORITY;
717 if ((pthread->flags & THR_FLAGS_IN_RUNQ) == 0)
718 THR_RUNQ_INSERT_TAIL(pthread);
719 }
720 }
721}
722
723static void
724thr_sig_check_state(struct pthread *pthread, int sig)
725{
726 /*
727 * Process according to thread state:
728 */
729 switch (pthread->state) {
730 /*
731 * States which do not change when a signal is trapped:
732 */
733 case PS_RUNNING:
734 case PS_LOCKWAIT:
735 case PS_MUTEX_WAIT:
736 case PS_COND_WAIT:
737 case PS_JOIN:
738 case PS_SUSPENDED:
739 case PS_DEAD:
740 case PS_DEADLOCK:
741 case PS_STATE_MAX:
742 break;
743
744 case PS_SIGWAIT:
745 /* Wake up the thread if the signal is blocked. */
746 if (sigismember(pthread->data.sigwait, sig)) {
747 /* Return the signal number: */
748 pthread->signo = sig;
749
750 /* Change the state of the thread to run: */
751 _thr_setrunnable_unlocked(pthread);
752 } else
753 /* Increment the pending signal count. */
754 sigaddset(&pthread->sigpend, sig);
755 break;
756
757 case PS_SIGSUSPEND:
758 case PS_SLEEP_WAIT:
759 /*
760 * Remove the thread from the wait queue and make it
761 * runnable:
762 */
763 _thr_setrunnable_unlocked(pthread);
764
765 /* Flag the operation as interrupted: */
766 pthread->interrupted = 1;
767 break;
768 }
769}
770
771/*
772 * Send a signal to a specific thread (ala pthread_kill):
773 */
774void
775_thr_sig_send(struct pthread *pthread, int sig)
776{
777 struct pthread *curthread = _get_curthread();
778
779 /* Lock the scheduling queue of the target thread. */
780 THR_SCHED_LOCK(curthread, pthread);
781
782 /* Check for signals whose actions are SIG_DFL: */
783 if (_thread_sigact[sig - 1].sa_handler == SIG_DFL) {
784 /*
785 * Check to see if a temporary signal handler is
786 * installed for sigwaiters:
787 */
788 if (_thread_dfl_count[sig] == 0) {
789 /*
790 * Deliver the signal to the process if a handler
791 * is not installed:
792 */
793 THR_SCHED_UNLOCK(curthread, pthread);
794 kill(getpid(), sig);
795 THR_SCHED_LOCK(curthread, pthread);
796 }
797 /*
798 * Assuming we're still running after the above kill(),
799 * make any necessary state changes to the thread:
800 */
801 thr_sig_check_state(pthread, sig);
802 THR_SCHED_UNLOCK(curthread, pthread);
803 }
804 /*
805 * Check that the signal is not being ignored:
806 */
807 else if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) {
808 if (pthread->state == PS_SIGWAIT &&
809 sigismember(pthread->data.sigwait, sig)) {
810 /* Return the signal number: */
811 pthread->signo = sig;
812
813 /* Change the state of the thread to run: */
814 _thr_setrunnable_unlocked(pthread);
815 THR_SCHED_UNLOCK(curthread, pthread);
816 } else if (sigismember(&pthread->tmbx.tm_context.uc_sigmask, sig)) {
817 /* Add the signal to the pending set: */
818 sigaddset(&pthread->sigpend, sig);
819 THR_SCHED_UNLOCK(curthread, pthread);
820 } else if (pthread == curthread) {
821 ucontext_t uc;
822 siginfo_t info;
823 volatile int once;
824
825 THR_SCHED_UNLOCK(curthread, pthread);
826 build_siginfo(&info, sig);
827 once = 0;
828 THR_GETCONTEXT(&uc);
829 if (once == 0) {
830 once = 1;
831 /*
832 * Call the signal handler for the current
833 * thread:
834 */
835 thr_sig_invoke_handler(curthread, sig,
836 &info, &uc);
837 }
838 } else {
839 /*
840 * Perform any state changes due to signal
841 * arrival:
842 */
843 _thr_sig_add(pthread, sig, NULL);
844 THR_SCHED_UNLOCK(curthread, pthread);
845 }
846 }
847}
848
849static void
850thr_sigframe_add(struct pthread *thread, int sig, siginfo_t *info)
851{
852 if (thread->curframe == NULL)
853 PANIC("Thread doesn't have signal frame ");
854
855 if (thread->have_signals == 0) {
856 /*
857 * Multiple signals can be added to the same signal
858 * frame. Only save the thread's state the first time.
859 */
860 thr_sigframe_save(thread, thread->curframe);
861 thread->have_signals = 1;
862 thread->flags &= THR_FLAGS_PRIVATE;
863 }
864 sigaddset(&thread->curframe->psf_sigset, sig);
865 if (info == NULL)
866 build_siginfo(&thread->siginfo[sig], sig);
867 else if (info != &thread->siginfo[sig])
868 memcpy(&thread->siginfo[sig], info, sizeof(*info));
869
870 /* Setup the new signal mask. */
871 SIGSETOR(thread->tmbx.tm_context.uc_sigmask,
872 _thread_sigact[sig - 1].sa_mask);
873 sigaddset(&thread->tmbx.tm_context.uc_sigmask, sig);
874}
875
876void
877thr_sigframe_restore(struct pthread *thread, struct pthread_sigframe *psf)
878{
879 thread->flags = psf->psf_flags;
880 thread->interrupted = psf->psf_interrupted;
881 thread->signo = psf->psf_signo;
882 thread->state = psf->psf_state;
883 thread->data = psf->psf_wait_data;
884 thread->wakeup_time = psf->psf_wakeup_time;
885 if (thread->sigmask_seqno == psf->psf_seqno)
886 thread->tmbx.tm_context.uc_sigmask = psf->psf_sigmask;
887 else
888 thread->tmbx.tm_context.uc_sigmask = thread->sigmask;
889}
890
891static void
892thr_sigframe_save(struct pthread *thread, struct pthread_sigframe *psf)
893{
894 /* This has to initialize all members of the sigframe. */
895 psf->psf_flags = thread->flags & THR_FLAGS_PRIVATE;
896 psf->psf_interrupted = thread->interrupted;
897 psf->psf_signo = thread->signo;
898 psf->psf_state = thread->state;
899 psf->psf_wait_data = thread->data;
900 psf->psf_wakeup_time = thread->wakeup_time;
901 psf->psf_sigmask = thread->tmbx.tm_context.uc_sigmask;
902 psf->psf_seqno = thread->sigmask_seqno;
903 sigemptyset(&psf->psf_sigset);
904}