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);
|
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);
|
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 } |
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) { |
334 suspended_thread = pthread;
|
326 } else if (signaled_thread == NULL)
|
335 suspended_thread->refcount++; 336 } 337 } else if (signaled_thread == NULL) { |
338 signaled_thread = pthread;
|
339 signaled_thread->refcount++; 340 } |
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) { |
376 pthread = suspended_thread;
|
364 else
|
377 _thr_ref_delete(NULL, signaled_thread); 378 } else |
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}
|