1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2005, David Xu <davidxu@freebsd.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice unmodified, this list of conditions, and the following 12 * disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "namespace.h" 30 #include <sys/param.h> 31 #include <sys/auxv.h> 32 #include <sys/elf.h> 33 #include <sys/signalvar.h> 34 #include <sys/syscall.h> 35 #include <signal.h> 36 #include <errno.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <pthread.h> 40 #include "un-namespace.h" 41 #include "libc_private.h" 42 43 #include "libc_private.h" 44 #include "thr_private.h" 45 46 /* #define DEBUG_SIGNAL */ 47 #ifdef DEBUG_SIGNAL 48 #define DBG_MSG stdout_debug 49 #else 50 #define DBG_MSG(x...) 51 #endif 52 53 struct usigaction { 54 struct sigaction sigact; 55 struct urwlock lock; 56 }; 57 58 static struct usigaction _thr_sigact[_SIG_MAXSIG]; 59 60 static inline struct usigaction * 61 __libc_sigaction_slot(int signo) 62 { 63 64 return (&_thr_sigact[signo - 1]); 65 } 66 67 static void thr_sighandler(int, siginfo_t *, void *); 68 static void handle_signal(struct sigaction *, int, siginfo_t *, ucontext_t *); 69 static void check_deferred_signal(struct pthread *); 70 static void check_suspend(struct pthread *); 71 static void check_cancel(struct pthread *curthread, ucontext_t *ucp); 72 73 int _sigtimedwait(const sigset_t *set, siginfo_t *info, 74 const struct timespec * timeout); 75 int _sigwaitinfo(const sigset_t *set, siginfo_t *info); 76 int _sigwait(const sigset_t *set, int *sig); 77 int _setcontext(const ucontext_t *); 78 int _swapcontext(ucontext_t *, const ucontext_t *); 79 80 static const sigset_t _thr_deferset={{ 81 0xffffffff & ~(_SIG_BIT(SIGBUS)|_SIG_BIT(SIGILL)|_SIG_BIT(SIGFPE)| 82 _SIG_BIT(SIGSEGV)|_SIG_BIT(SIGTRAP)|_SIG_BIT(SIGSYS)), 83 0xffffffff, 84 0xffffffff, 85 0xffffffff}}; 86 87 static const sigset_t _thr_maskset={{ 88 0xffffffff, 89 0xffffffff, 90 0xffffffff, 91 0xffffffff}}; 92 93 static void 94 thr_signal_block_slow(struct pthread *curthread) 95 { 96 if (curthread->sigblock > 0) { 97 curthread->sigblock++; 98 return; 99 } 100 __sys_sigprocmask(SIG_BLOCK, &_thr_maskset, &curthread->sigmask); 101 curthread->sigblock++; 102 } 103 104 static void 105 thr_signal_unblock_slow(struct pthread *curthread) 106 { 107 if (--curthread->sigblock == 0) 108 __sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL); 109 } 110 111 static void 112 thr_signal_block_fast(struct pthread *curthread) 113 { 114 atomic_add_32(&curthread->fsigblock, SIGFASTBLOCK_INC); 115 } 116 117 static void 118 thr_signal_unblock_fast(struct pthread *curthread) 119 { 120 uint32_t oldval; 121 122 oldval = atomic_fetchadd_32(&curthread->fsigblock, -SIGFASTBLOCK_INC); 123 if (oldval == (SIGFASTBLOCK_PEND | SIGFASTBLOCK_INC)) 124 __sys_sigfastblock(SIGFASTBLOCK_UNBLOCK, NULL); 125 } 126 127 static bool fast_sigblock; 128 129 void 130 _thr_signal_block(struct pthread *curthread) 131 { 132 if (fast_sigblock) 133 thr_signal_block_fast(curthread); 134 else 135 thr_signal_block_slow(curthread); 136 } 137 138 void 139 _thr_signal_unblock(struct pthread *curthread) 140 { 141 if (fast_sigblock) 142 thr_signal_unblock_fast(curthread); 143 else 144 thr_signal_unblock_slow(curthread); 145 } 146 147 void 148 _thr_signal_block_check_fast(void) 149 { 150 int bsdflags, error; 151 152 error = elf_aux_info(AT_BSDFLAGS, &bsdflags, sizeof(bsdflags)); 153 if (error != 0) 154 return; 155 fast_sigblock = (bsdflags & ELF_BSDF_SIGFASTBLK) != 0; 156 } 157 158 void 159 _thr_signal_block_setup(struct pthread *curthread) 160 { 161 if (!fast_sigblock) 162 return; 163 __sys_sigfastblock(SIGFASTBLOCK_SETPTR, &curthread->fsigblock); 164 } 165 166 int 167 _thr_send_sig(struct pthread *thread, int sig) 168 { 169 return thr_kill(thread->tid, sig); 170 } 171 172 static inline void 173 remove_thr_signals(sigset_t *set) 174 { 175 if (SIGISMEMBER(*set, SIGCANCEL)) 176 SIGDELSET(*set, SIGCANCEL); 177 } 178 179 static const sigset_t * 180 thr_remove_thr_signals(const sigset_t *set, sigset_t *newset) 181 { 182 *newset = *set; 183 remove_thr_signals(newset); 184 return (newset); 185 } 186 187 static void 188 sigcancel_handler(int sig __unused, 189 siginfo_t *info __unused, ucontext_t *ucp) 190 { 191 struct pthread *curthread = _get_curthread(); 192 int err; 193 194 if (THR_IN_CRITICAL(curthread)) 195 return; 196 err = errno; 197 check_suspend(curthread); 198 check_cancel(curthread, ucp); 199 errno = err; 200 } 201 202 typedef void (*ohandler)(int sig, int code, struct sigcontext *scp, 203 char *addr, __sighandler_t *catcher); 204 205 /* 206 * The signal handler wrapper is entered with all signal masked. 207 */ 208 static void 209 thr_sighandler(int sig, siginfo_t *info, void *_ucp) 210 { 211 struct pthread *curthread; 212 ucontext_t *ucp; 213 struct sigaction act; 214 struct usigaction *usa; 215 int err; 216 217 err = errno; 218 curthread = _get_curthread(); 219 ucp = _ucp; 220 usa = __libc_sigaction_slot(sig); 221 _thr_rwl_rdlock(&usa->lock); 222 act = usa->sigact; 223 _thr_rwl_unlock(&usa->lock); 224 errno = err; 225 curthread->deferred_run = 0; 226 227 /* 228 * if a thread is in critical region, for example it holds low level locks, 229 * try to defer the signal processing, however if the signal is synchronous 230 * signal, it means a bad thing has happened, this is a programming error, 231 * resuming fault point can not help anything (normally causes deadloop), 232 * so here we let user code handle it immediately. 233 */ 234 if (THR_IN_CRITICAL(curthread) && SIGISMEMBER(_thr_deferset, sig)) { 235 memcpy(&curthread->deferred_sigact, &act, sizeof(struct sigaction)); 236 memcpy(&curthread->deferred_siginfo, info, sizeof(siginfo_t)); 237 curthread->deferred_sigmask = ucp->uc_sigmask; 238 /* mask all signals, we will restore it later. */ 239 ucp->uc_sigmask = _thr_deferset; 240 return; 241 } 242 243 handle_signal(&act, sig, info, ucp); 244 } 245 246 static void 247 handle_signal(struct sigaction *actp, int sig, siginfo_t *info, ucontext_t *ucp) 248 { 249 struct pthread *curthread = _get_curthread(); 250 __siginfohandler_t *sigfunc; 251 int cancel_point; 252 int cancel_async; 253 int cancel_enable; 254 int in_sigsuspend; 255 int err; 256 257 /* add previous level mask */ 258 SIGSETOR(actp->sa_mask, ucp->uc_sigmask); 259 260 /* add this signal's mask */ 261 if (!(actp->sa_flags & SA_NODEFER)) 262 SIGADDSET(actp->sa_mask, sig); 263 264 in_sigsuspend = curthread->in_sigsuspend; 265 curthread->in_sigsuspend = 0; 266 267 /* 268 * If thread is in deferred cancellation mode, disable cancellation 269 * in signal handler. 270 * If user signal handler calls a cancellation point function, e.g, 271 * it calls write() to write data to file, because write() is a 272 * cancellation point, the thread is immediately cancelled if 273 * cancellation is pending, to avoid this problem while thread is in 274 * deferring mode, cancellation is temporarily disabled. 275 */ 276 cancel_point = curthread->cancel_point; 277 cancel_async = curthread->cancel_async; 278 cancel_enable = curthread->cancel_enable; 279 curthread->cancel_point = 0; 280 if (!cancel_async) 281 curthread->cancel_enable = 0; 282 283 /* restore correct mask before calling user handler */ 284 __sys_sigprocmask(SIG_SETMASK, &actp->sa_mask, NULL); 285 286 sigfunc = actp->sa_sigaction; 287 288 /* 289 * We have already reset cancellation point flags, so if user's code 290 * longjmp()s out of its signal handler, wish its jmpbuf was set 291 * outside of a cancellation point, in most cases, this would be 292 * true. However, there is no way to save cancel_enable in jmpbuf, 293 * so after setjmps() returns once more, the user code may need to 294 * re-set cancel_enable flag by calling pthread_setcancelstate(). 295 */ 296 if ((actp->sa_flags & SA_SIGINFO) != 0) { 297 sigfunc(sig, info, ucp); 298 } else { 299 ((ohandler)sigfunc)(sig, info->si_code, 300 (struct sigcontext *)ucp, info->si_addr, 301 (__sighandler_t *)sigfunc); 302 } 303 err = errno; 304 305 curthread->in_sigsuspend = in_sigsuspend; 306 curthread->cancel_point = cancel_point; 307 curthread->cancel_enable = cancel_enable; 308 309 SIGDELSET(ucp->uc_sigmask, SIGCANCEL); 310 311 /* reschedule cancellation */ 312 check_cancel(curthread, ucp); 313 errno = err; 314 } 315 316 void 317 _thr_ast(struct pthread *curthread) 318 { 319 320 if (!THR_IN_CRITICAL(curthread)) { 321 check_deferred_signal(curthread); 322 check_suspend(curthread); 323 check_cancel(curthread, NULL); 324 } 325 } 326 327 /* reschedule cancellation */ 328 static void 329 check_cancel(struct pthread *curthread, ucontext_t *ucp) 330 { 331 332 if (__predict_true(!curthread->cancel_pending || 333 !curthread->cancel_enable || curthread->no_cancel)) 334 return; 335 336 /* 337 * Otherwise, we are in defer mode, and we are at 338 * cancel point, tell kernel to not block the current 339 * thread on next cancelable system call. 340 * 341 * There are three cases we should call thr_wake() to 342 * turn on TDP_WAKEUP or send SIGCANCEL in kernel: 343 * 1) we are going to call a cancelable system call, 344 * non-zero cancel_point means we are already in 345 * cancelable state, next system call is cancelable. 346 * 2) because _thr_ast() may be called by 347 * THR_CRITICAL_LEAVE() which is used by rtld rwlock 348 * and any libthr internal locks, when rtld rwlock 349 * is used, it is mostly caused by an unresolved PLT. 350 * Those routines may clear the TDP_WAKEUP flag by 351 * invoking some system calls, in those cases, we 352 * also should reenable the flag. 353 * 3) thread is in sigsuspend(), and the syscall insists 354 * on getting a signal before it agrees to return. 355 */ 356 if (curthread->cancel_point) { 357 if (curthread->in_sigsuspend && ucp) { 358 SIGADDSET(ucp->uc_sigmask, SIGCANCEL); 359 curthread->unblock_sigcancel = 1; 360 _thr_send_sig(curthread, SIGCANCEL); 361 } else 362 thr_wake(curthread->tid); 363 } else if (curthread->cancel_async) { 364 /* 365 * asynchronous cancellation mode, act upon 366 * immediately. 367 */ 368 _pthread_exit_mask(PTHREAD_CANCELED, 369 ucp? &ucp->uc_sigmask : NULL); 370 } 371 } 372 373 static void 374 check_deferred_signal(struct pthread *curthread) 375 { 376 ucontext_t *uc; 377 struct sigaction act; 378 siginfo_t info; 379 int uc_len; 380 381 if (__predict_true(curthread->deferred_siginfo.si_signo == 0 || 382 curthread->deferred_run)) 383 return; 384 385 curthread->deferred_run = 1; 386 uc_len = __getcontextx_size(); 387 uc = alloca(uc_len); 388 getcontext(uc); 389 if (curthread->deferred_siginfo.si_signo == 0) { 390 curthread->deferred_run = 0; 391 return; 392 } 393 __fillcontextx2((char *)uc); 394 act = curthread->deferred_sigact; 395 uc->uc_sigmask = curthread->deferred_sigmask; 396 memcpy(&info, &curthread->deferred_siginfo, sizeof(siginfo_t)); 397 /* remove signal */ 398 curthread->deferred_siginfo.si_signo = 0; 399 handle_signal(&act, info.si_signo, &info, uc); 400 syscall(SYS_sigreturn, uc); 401 } 402 403 static void 404 check_suspend(struct pthread *curthread) 405 { 406 uint32_t cycle; 407 408 if (__predict_true((curthread->flags & 409 (THR_FLAGS_NEED_SUSPEND | THR_FLAGS_SUSPENDED)) 410 != THR_FLAGS_NEED_SUSPEND)) 411 return; 412 if (curthread == _single_thread) 413 return; 414 if (curthread->force_exit) 415 return; 416 417 /* 418 * Blocks SIGCANCEL which other threads must send. 419 */ 420 _thr_signal_block(curthread); 421 422 /* 423 * Increase critical_count, here we don't use THR_LOCK/UNLOCK 424 * because we are leaf code, we don't want to recursively call 425 * ourself. 426 */ 427 curthread->critical_count++; 428 THR_UMUTEX_LOCK(curthread, &(curthread)->lock); 429 while ((curthread->flags & THR_FLAGS_NEED_SUSPEND) != 0) { 430 curthread->cycle++; 431 cycle = curthread->cycle; 432 433 /* Wake the thread suspending us. */ 434 _thr_umtx_wake(&curthread->cycle, INT_MAX, 0); 435 436 /* 437 * if we are from pthread_exit, we don't want to 438 * suspend, just go and die. 439 */ 440 if (curthread->state == PS_DEAD) 441 break; 442 curthread->flags |= THR_FLAGS_SUSPENDED; 443 THR_UMUTEX_UNLOCK(curthread, &(curthread)->lock); 444 _thr_umtx_wait_uint(&curthread->cycle, cycle, NULL, 0); 445 THR_UMUTEX_LOCK(curthread, &(curthread)->lock); 446 } 447 THR_UMUTEX_UNLOCK(curthread, &(curthread)->lock); 448 curthread->critical_count--; 449 450 _thr_signal_unblock(curthread); 451 } 452 453 void 454 _thr_signal_init(int dlopened) 455 { 456 struct sigaction act, nact, oact; 457 struct usigaction *usa; 458 sigset_t oldset; 459 int sig, error; 460 461 if (dlopened) { 462 __sys_sigprocmask(SIG_SETMASK, &_thr_maskset, &oldset); 463 for (sig = 1; sig <= _SIG_MAXSIG; sig++) { 464 if (sig == SIGCANCEL) 465 continue; 466 error = __sys_sigaction(sig, NULL, &oact); 467 if (error == -1 || oact.sa_handler == SIG_DFL || 468 oact.sa_handler == SIG_IGN) 469 continue; 470 usa = __libc_sigaction_slot(sig); 471 usa->sigact = oact; 472 nact = oact; 473 remove_thr_signals(&usa->sigact.sa_mask); 474 nact.sa_flags &= ~SA_NODEFER; 475 nact.sa_flags |= SA_SIGINFO; 476 nact.sa_sigaction = thr_sighandler; 477 nact.sa_mask = _thr_maskset; 478 (void)__sys_sigaction(sig, &nact, NULL); 479 } 480 __sys_sigprocmask(SIG_SETMASK, &oldset, NULL); 481 } 482 483 /* Install SIGCANCEL handler. */ 484 SIGFILLSET(act.sa_mask); 485 act.sa_flags = SA_SIGINFO; 486 act.sa_sigaction = (__siginfohandler_t *)&sigcancel_handler; 487 __sys_sigaction(SIGCANCEL, &act, NULL); 488 489 /* Unblock SIGCANCEL */ 490 SIGEMPTYSET(act.sa_mask); 491 SIGADDSET(act.sa_mask, SIGCANCEL); 492 __sys_sigprocmask(SIG_UNBLOCK, &act.sa_mask, NULL); 493 } 494 495 void 496 _thr_sigact_unload(struct dl_phdr_info *phdr_info __unused) 497 { 498 #if 0 499 struct pthread *curthread = _get_curthread(); 500 struct urwlock *rwlp; 501 struct sigaction *actp; 502 struct usigaction *usa; 503 struct sigaction kact; 504 void (*handler)(int); 505 int sig; 506 507 _thr_signal_block(curthread); 508 for (sig = 1; sig <= _SIG_MAXSIG; sig++) { 509 usa = __libc_sigaction_slot(sig); 510 actp = &usa->sigact; 511 retry: 512 handler = actp->sa_handler; 513 if (handler != SIG_DFL && handler != SIG_IGN && 514 __elf_phdr_match_addr(phdr_info, handler)) { 515 rwlp = &usa->lock; 516 _thr_rwl_wrlock(rwlp); 517 if (handler != actp->sa_handler) { 518 _thr_rwl_unlock(rwlp); 519 goto retry; 520 } 521 actp->sa_handler = SIG_DFL; 522 actp->sa_flags = SA_SIGINFO; 523 SIGEMPTYSET(actp->sa_mask); 524 if (__sys_sigaction(sig, NULL, &kact) == 0 && 525 kact.sa_handler != SIG_DFL && 526 kact.sa_handler != SIG_IGN) 527 __sys_sigaction(sig, actp, NULL); 528 _thr_rwl_unlock(rwlp); 529 } 530 } 531 _thr_signal_unblock(curthread); 532 #endif 533 } 534 535 void 536 _thr_signal_prefork(void) 537 { 538 int i; 539 540 for (i = 1; i <= _SIG_MAXSIG; ++i) 541 _thr_rwl_rdlock(&__libc_sigaction_slot(i)->lock); 542 } 543 544 void 545 _thr_signal_postfork(void) 546 { 547 int i; 548 549 for (i = 1; i <= _SIG_MAXSIG; ++i) 550 _thr_rwl_unlock(&__libc_sigaction_slot(i)->lock); 551 } 552 553 void 554 _thr_signal_postfork_child(void) 555 { 556 int i; 557 558 for (i = 1; i <= _SIG_MAXSIG; ++i) { 559 bzero(&__libc_sigaction_slot(i) -> lock, 560 sizeof(struct urwlock)); 561 } 562 } 563 564 void 565 _thr_signal_deinit(void) 566 { 567 } 568 569 int 570 __thr_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) 571 { 572 struct sigaction newact, oldact, oldact2; 573 sigset_t oldset; 574 struct usigaction *usa; 575 int ret, err; 576 577 if (!_SIG_VALID(sig) || sig == SIGCANCEL) { 578 errno = EINVAL; 579 return (-1); 580 } 581 582 ret = 0; 583 err = 0; 584 usa = __libc_sigaction_slot(sig); 585 586 __sys_sigprocmask(SIG_SETMASK, &_thr_maskset, &oldset); 587 _thr_rwl_wrlock(&usa->lock); 588 589 if (act != NULL) { 590 oldact2 = usa->sigact; 591 newact = *act; 592 593 /* 594 * if a new sig handler is SIG_DFL or SIG_IGN, 595 * don't remove old handler from __libc_sigact[], 596 * so deferred signals still can use the handlers, 597 * multiple threads invoking sigaction itself is 598 * a race condition, so it is not a problem. 599 */ 600 if (newact.sa_handler != SIG_DFL && 601 newact.sa_handler != SIG_IGN) { 602 usa->sigact = newact; 603 remove_thr_signals(&usa->sigact.sa_mask); 604 newact.sa_flags &= ~SA_NODEFER; 605 newact.sa_flags |= SA_SIGINFO; 606 newact.sa_sigaction = thr_sighandler; 607 newact.sa_mask = _thr_maskset; /* mask all signals */ 608 } 609 ret = __sys_sigaction(sig, &newact, &oldact); 610 if (ret == -1) { 611 err = errno; 612 usa->sigact = oldact2; 613 } 614 } else if (oact != NULL) { 615 ret = __sys_sigaction(sig, NULL, &oldact); 616 err = errno; 617 } 618 619 if (oldact.sa_handler != SIG_DFL && oldact.sa_handler != SIG_IGN) { 620 if (act != NULL) 621 oldact = oldact2; 622 else if (oact != NULL) 623 oldact = usa->sigact; 624 } 625 626 _thr_rwl_unlock(&usa->lock); 627 __sys_sigprocmask(SIG_SETMASK, &oldset, NULL); 628 629 if (ret == 0) { 630 if (oact != NULL) 631 *oact = oldact; 632 } else { 633 errno = err; 634 } 635 return (ret); 636 } 637 638 int 639 __thr_sigprocmask(int how, const sigset_t *set, sigset_t *oset) 640 { 641 const sigset_t *p = set; 642 sigset_t newset; 643 644 if (how != SIG_UNBLOCK) { 645 if (set != NULL) { 646 newset = *set; 647 SIGDELSET(newset, SIGCANCEL); 648 p = &newset; 649 } 650 } 651 return (__sys_sigprocmask(how, p, oset)); 652 } 653 654 __weak_reference(_thr_sigmask, pthread_sigmask); 655 __weak_reference(_thr_sigmask, _pthread_sigmask); 656 657 int 658 _thr_sigmask(int how, const sigset_t *set, sigset_t *oset) 659 { 660 661 if (__thr_sigprocmask(how, set, oset)) 662 return (errno); 663 return (0); 664 } 665 666 int 667 _sigsuspend(const sigset_t * set) 668 { 669 sigset_t newset; 670 671 return (__sys_sigsuspend(thr_remove_thr_signals(set, &newset))); 672 } 673 674 int 675 __thr_sigsuspend(const sigset_t * set) 676 { 677 struct pthread *curthread; 678 sigset_t newset; 679 int ret, old; 680 681 curthread = _get_curthread(); 682 683 old = curthread->in_sigsuspend; 684 curthread->in_sigsuspend = 1; 685 _thr_cancel_enter(curthread); 686 ret = __sys_sigsuspend(thr_remove_thr_signals(set, &newset)); 687 _thr_cancel_leave(curthread, 1); 688 curthread->in_sigsuspend = old; 689 if (curthread->unblock_sigcancel) { 690 curthread->unblock_sigcancel = 0; 691 SIGEMPTYSET(newset); 692 SIGADDSET(newset, SIGCANCEL); 693 __sys_sigprocmask(SIG_UNBLOCK, &newset, NULL); 694 } 695 696 return (ret); 697 } 698 699 int 700 _sigtimedwait(const sigset_t *set, siginfo_t *info, 701 const struct timespec * timeout) 702 { 703 sigset_t newset; 704 705 return (__sys_sigtimedwait(thr_remove_thr_signals(set, &newset), info, 706 timeout)); 707 } 708 709 /* 710 * Cancellation behavior: 711 * Thread may be canceled at start, if thread got signal, 712 * it is not canceled. 713 */ 714 int 715 __thr_sigtimedwait(const sigset_t *set, siginfo_t *info, 716 const struct timespec * timeout) 717 { 718 struct pthread *curthread = _get_curthread(); 719 sigset_t newset; 720 int ret; 721 722 _thr_cancel_enter(curthread); 723 ret = __sys_sigtimedwait(thr_remove_thr_signals(set, &newset), info, 724 timeout); 725 _thr_cancel_leave(curthread, (ret == -1)); 726 return (ret); 727 } 728 729 int 730 _sigwaitinfo(const sigset_t *set, siginfo_t *info) 731 { 732 sigset_t newset; 733 734 return (__sys_sigwaitinfo(thr_remove_thr_signals(set, &newset), info)); 735 } 736 737 /* 738 * Cancellation behavior: 739 * Thread may be canceled at start, if thread got signal, 740 * it is not canceled. 741 */ 742 int 743 __thr_sigwaitinfo(const sigset_t *set, siginfo_t *info) 744 { 745 struct pthread *curthread = _get_curthread(); 746 sigset_t newset; 747 int ret; 748 749 _thr_cancel_enter(curthread); 750 ret = __sys_sigwaitinfo(thr_remove_thr_signals(set, &newset), info); 751 _thr_cancel_leave(curthread, ret == -1); 752 return (ret); 753 } 754 755 int 756 _sigwait(const sigset_t *set, int *sig) 757 { 758 sigset_t newset; 759 760 return (__sys_sigwait(thr_remove_thr_signals(set, &newset), sig)); 761 } 762 763 /* 764 * Cancellation behavior: 765 * Thread may be canceled at start, if thread got signal, 766 * it is not canceled. 767 */ 768 int 769 __thr_sigwait(const sigset_t *set, int *sig) 770 { 771 struct pthread *curthread = _get_curthread(); 772 sigset_t newset; 773 int ret; 774 775 do { 776 _thr_cancel_enter(curthread); 777 ret = __sys_sigwait(thr_remove_thr_signals(set, &newset), sig); 778 _thr_cancel_leave(curthread, (ret != 0)); 779 } while (ret == EINTR); 780 return (ret); 781 } 782 783 int 784 __thr_setcontext(const ucontext_t *ucp) 785 { 786 ucontext_t uc; 787 788 if (ucp == NULL) { 789 errno = EINVAL; 790 return (-1); 791 } 792 if (!SIGISMEMBER(ucp->uc_sigmask, SIGCANCEL)) 793 return (__sys_setcontext(ucp)); 794 (void) memcpy(&uc, ucp, sizeof(uc)); 795 SIGDELSET(uc.uc_sigmask, SIGCANCEL); 796 return (__sys_setcontext(&uc)); 797 } 798 799 int 800 __thr_swapcontext(ucontext_t *oucp, const ucontext_t *ucp) 801 { 802 ucontext_t uc; 803 804 if (oucp == NULL || ucp == NULL) { 805 errno = EINVAL; 806 return (-1); 807 } 808 if (SIGISMEMBER(ucp->uc_sigmask, SIGCANCEL)) { 809 (void) memcpy(&uc, ucp, sizeof(uc)); 810 SIGDELSET(uc.uc_sigmask, SIGCANCEL); 811 ucp = &uc; 812 } 813 return (__sys_swapcontext(oucp, ucp)); 814 } 815