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}
|