thr_sig.c revision 114664
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 114664 2003-05-04 16:17:01Z 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); 48static 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) { 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); 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) { 324 if (suspended_thread == NULL) 325 suspended_thread = pthread; 326 } else if (signaled_thread == NULL) 327 signaled_thread = pthread; 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 */ 362 if (suspended_thread != NULL) 363 pthread = suspended_thread; 364 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 */ 574static void 575thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info) 576{ 577 int restart; 578 int suppress_handler = 0; 579 580 restart = _thread_sigact[sig - 1].sa_flags & SA_RESTART; 581 582 /* Make sure this signal isn't still in the pending set: */ 583 sigdelset(&pthread->sigpend, sig); 584 585 /* 586 * Process according to thread state: 587 */ 588 switch (pthread->state) { 589 /* 590 * States which do not change when a signal is trapped: 591 */ 592 case PS_DEAD: 593 case PS_DEADLOCK: 594 case PS_LOCKWAIT: 595 case PS_SUSPENDED: 596 case PS_STATE_MAX: 597 /* 598 * You can't call a signal handler for threads in these 599 * states. 600 */ 601 suppress_handler = 1; 602 break; 603 604 /* 605 * States which do not need any cleanup handling when signals 606 * occur: 607 */ 608 case PS_RUNNING: 609 /* 610 * Remove the thread from the queue before changing its 611 * priority: 612 */ 613 if ((pthread->flags & THR_FLAGS_IN_RUNQ) != 0) 614 THR_RUNQ_REMOVE(pthread); 615 else { 616 /* 617 * This thread is active; add the signal to the 618 * pending set and mark it as having pending 619 * signals. 620 */ 621 suppress_handler = 1; 622 sigaddset(&pthread->sigpend, sig); 623 build_siginfo(&pthread->siginfo[sig], sig); 624 pthread->check_pending = 1; 625 if ((pthread->blocked != 0) && 626 !THR_IN_CRITICAL(pthread)) 627 kse_thr_interrupt(&pthread->tmbx /* XXX - restart?!?! */); 628 } 629 break; 630 631 /* 632 * States which cannot be interrupted but still require the 633 * signal handler to run: 634 */ 635 case PS_COND_WAIT: 636 case PS_MUTEX_WAIT: 637 /* 638 * Remove the thread from the wait queue. It will 639 * be added back to the wait queue once all signal 640 * handlers have been invoked. 641 */ 642 KSE_WAITQ_REMOVE(pthread->kse, pthread); 643 break; 644 645 case PS_SLEEP_WAIT: 646 /* 647 * Unmasked signals always cause sleep to terminate early, 648 * regardless of SA_RESTART: 649 */ 650 pthread->interrupted = 1; 651 KSE_WAITQ_REMOVE(pthread->kse, pthread); 652 THR_SET_STATE(pthread, PS_RUNNING); 653 break; 654 655 case PS_JOIN: 656 case PS_SIGSUSPEND: 657 KSE_WAITQ_REMOVE(pthread->kse, pthread); 658 THR_SET_STATE(pthread, PS_RUNNING); 659 break; 660 661 case PS_SIGWAIT: 662 /* The signal handler is not called for threads in SIGWAIT. */ 663 suppress_handler = 1; 664 /* Wake up the thread if the signal is blocked. */ 665 if (sigismember(pthread->data.sigwait, sig)) { 666 /* Return the signal number: */ 667 pthread->signo = sig; 668 669 /* Make the thread runnable: */ 670 _thr_setrunnable_unlocked(pthread); 671 } else 672 /* Increment the pending signal count. */ 673 sigaddset(&pthread->sigpend, sig); 674 break; 675 } 676 677 if (suppress_handler == 0) { 678 if (pthread->curframe == NULL) { 679 /* 680 * This thread is active. Just add it to the 681 * thread's pending set. 682 */ 683 sigaddset(&pthread->sigpend, sig); 684 pthread->check_pending = 1; 685 if (info == NULL) 686 build_siginfo(&pthread->siginfo[sig], sig); 687 else 688 memcpy(&pthread->siginfo[sig], info, 689 sizeof(*info)); 690 } else { 691 /* 692 * Setup a signal frame and save the current threads 693 * state: 694 */ 695 thr_sigframe_add(pthread, sig, info); 696 } 697 698 if (pthread->state != PS_RUNNING) 699 THR_SET_STATE(pthread, PS_RUNNING); 700 701 /* 702 * The thread should be removed from all scheduling 703 * queues at this point. Raise the priority and 704 * place the thread in the run queue. It is also 705 * possible for a signal to be sent to a suspended 706 * thread, mostly via pthread_kill(). If a thread 707 * is suspended, don't insert it into the priority 708 * queue; just set its state to suspended and it 709 * will run the signal handler when it is resumed. 710 */ 711 pthread->active_priority |= THR_SIGNAL_PRIORITY; 712 if ((pthread->flags & THR_FLAGS_IN_RUNQ) == 0) 713 THR_RUNQ_INSERT_TAIL(pthread); 714 } 715} 716 717static void 718thr_sig_check_state(struct pthread *pthread, int sig) 719{ 720 /* 721 * Process according to thread state: 722 */ 723 switch (pthread->state) { 724 /* 725 * States which do not change when a signal is trapped: 726 */ 727 case PS_RUNNING: 728 case PS_LOCKWAIT: 729 case PS_MUTEX_WAIT: 730 case PS_COND_WAIT: 731 case PS_JOIN: 732 case PS_SUSPENDED: 733 case PS_DEAD: 734 case PS_DEADLOCK: 735 case PS_STATE_MAX: 736 break; 737 738 case PS_SIGWAIT: 739 /* Wake up the thread if the signal is blocked. */ 740 if (sigismember(pthread->data.sigwait, sig)) { 741 /* Return the signal number: */ 742 pthread->signo = sig; 743 744 /* Change the state of the thread to run: */ 745 _thr_setrunnable_unlocked(pthread); 746 } else 747 /* Increment the pending signal count. */ 748 sigaddset(&pthread->sigpend, sig); 749 break; 750 751 case PS_SIGSUSPEND: 752 case PS_SLEEP_WAIT: 753 /* 754 * Remove the thread from the wait queue and make it 755 * runnable: 756 */ 757 _thr_setrunnable_unlocked(pthread); 758 759 /* Flag the operation as interrupted: */ 760 pthread->interrupted = 1; 761 break; 762 } 763} 764 765/* 766 * Send a signal to a specific thread (ala pthread_kill): 767 */ 768void 769_thr_sig_send(struct pthread *pthread, int sig) 770{ 771 struct pthread *curthread = _get_curthread(); 772 773 /* Lock the scheduling queue of the target thread. */ 774 THR_SCHED_LOCK(curthread, pthread); 775 776 /* Check for signals whose actions are SIG_DFL: */ 777 if (_thread_sigact[sig - 1].sa_handler == SIG_DFL) { 778 /* 779 * Check to see if a temporary signal handler is 780 * installed for sigwaiters: 781 */ 782 if (_thread_dfl_count[sig] == 0) { 783 /* 784 * Deliver the signal to the process if a handler 785 * is not installed: 786 */ 787 THR_SCHED_UNLOCK(curthread, pthread); 788 kill(getpid(), sig); 789 THR_SCHED_LOCK(curthread, pthread); 790 } 791 /* 792 * Assuming we're still running after the above kill(), 793 * make any necessary state changes to the thread: 794 */ 795 thr_sig_check_state(pthread, sig); 796 THR_SCHED_UNLOCK(curthread, pthread); 797 } 798 /* 799 * Check that the signal is not being ignored: 800 */ 801 else if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) { 802 if (pthread->state == PS_SIGWAIT && 803 sigismember(pthread->data.sigwait, sig)) { 804 /* Return the signal number: */ 805 pthread->signo = sig; 806 807 /* Change the state of the thread to run: */ 808 _thr_setrunnable_unlocked(pthread); 809 THR_SCHED_UNLOCK(curthread, pthread); 810 } else if (sigismember(&pthread->tmbx.tm_context.uc_sigmask, sig)) { 811 /* Add the signal to the pending set: */ 812 sigaddset(&pthread->sigpend, sig); 813 THR_SCHED_UNLOCK(curthread, pthread); 814 } else if (pthread == curthread) { 815 ucontext_t uc; 816 siginfo_t info; 817 volatile int once; 818 819 THR_SCHED_UNLOCK(curthread, pthread); 820 build_siginfo(&info, sig); 821 once = 0; 822 THR_GETCONTEXT(&uc); 823 if (once == 0) { 824 once = 1; 825 /* 826 * Call the signal handler for the current 827 * thread: 828 */ 829 thr_sig_invoke_handler(curthread, sig, 830 &info, &uc); 831 } 832 } else { 833 /* 834 * Perform any state changes due to signal 835 * arrival: 836 */ 837 thr_sig_add(pthread, sig, NULL); 838 THR_SCHED_UNLOCK(curthread, pthread); 839 } 840 } 841} 842 843static void 844thr_sigframe_add(struct pthread *thread, int sig, siginfo_t *info) 845{ 846 if (thread->curframe == NULL) 847 PANIC("Thread doesn't have signal frame "); 848 849 if (thread->check_pending == 0) { 850 /* 851 * Multiple signals can be added to the same signal 852 * frame. Only save the thread's state the first time. 853 */ 854 thr_sigframe_save(thread, thread->curframe); 855 thread->check_pending = 1; 856 thread->flags &= THR_FLAGS_PRIVATE; 857 } 858 sigaddset(&thread->curframe->psf_sigset, sig); 859 if (info != NULL) 860 memcpy(&thread->siginfo[sig], info, sizeof(*info)); 861 else 862 build_siginfo(&thread->siginfo[sig], sig); 863 864 /* Setup the new signal mask. */ 865 SIGSETOR(thread->tmbx.tm_context.uc_sigmask, 866 _thread_sigact[sig - 1].sa_mask); 867 sigaddset(&thread->tmbx.tm_context.uc_sigmask, sig); 868} 869 870void 871thr_sigframe_restore(struct pthread *thread, struct pthread_sigframe *psf) 872{ 873 thread->flags = psf->psf_flags; 874 thread->interrupted = psf->psf_interrupted; 875 thread->signo = psf->psf_signo; 876 thread->state = psf->psf_state; 877 thread->data = psf->psf_wait_data; 878 thread->wakeup_time = psf->psf_wakeup_time; 879 if (thread->sigmask_seqno == psf->psf_seqno) 880 thread->tmbx.tm_context.uc_sigmask = psf->psf_sigmask; 881 else 882 thread->tmbx.tm_context.uc_sigmask = thread->sigmask; 883} 884 885static void 886thr_sigframe_save(struct pthread *thread, struct pthread_sigframe *psf) 887{ 888 /* This has to initialize all members of the sigframe. */ 889 psf->psf_flags = thread->flags & THR_FLAGS_PRIVATE; 890 psf->psf_interrupted = thread->interrupted; 891 psf->psf_signo = thread->signo; 892 psf->psf_state = thread->state; 893 psf->psf_wait_data = thread->data; 894 psf->psf_wakeup_time = thread->wakeup_time; 895 psf->psf_sigmask = thread->tmbx.tm_context.uc_sigmask; 896 psf->psf_seqno = thread->sigmask_seqno; 897 sigemptyset(&psf->psf_sigset); 898} 899