1bb535300SJeff Roberson /* 2df2cf821SDavid Xu * Copyright (c) 2005, David Xu <davidxu@freebsd.org> 3bb535300SJeff Roberson * All rights reserved. 4bb535300SJeff Roberson * 5bb535300SJeff Roberson * Redistribution and use in source and binary forms, with or without 6bb535300SJeff Roberson * modification, are permitted provided that the following conditions 7bb535300SJeff Roberson * are met: 8bb535300SJeff Roberson * 1. Redistributions of source code must retain the above copyright 9df2cf821SDavid Xu * notice unmodified, this list of conditions, and the following 10df2cf821SDavid Xu * disclaimer. 11bb535300SJeff Roberson * 2. Redistributions in binary form must reproduce the above copyright 12bb535300SJeff Roberson * notice, this list of conditions and the following disclaimer in the 13bb535300SJeff Roberson * documentation and/or other materials provided with the distribution. 14bb535300SJeff Roberson * 15df2cf821SDavid Xu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16df2cf821SDavid Xu * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17df2cf821SDavid Xu * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18df2cf821SDavid Xu * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19df2cf821SDavid Xu * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20df2cf821SDavid Xu * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21df2cf821SDavid Xu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22df2cf821SDavid Xu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23df2cf821SDavid Xu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24df2cf821SDavid Xu * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25bb535300SJeff Roberson * 26bb535300SJeff Roberson * $FreeBSD$ 27bb535300SJeff Roberson */ 28bb535300SJeff Roberson 2937a6356bSDavid Xu #include "namespace.h" 30bb535300SJeff Roberson #include <sys/param.h> 31bb535300SJeff Roberson #include <sys/types.h> 32bb535300SJeff Roberson #include <sys/signalvar.h> 33bb535300SJeff Roberson #include <signal.h> 34a091d823SDavid Xu #include <errno.h> 35bb535300SJeff Roberson #include <fcntl.h> 36bb535300SJeff Roberson #include <unistd.h> 37a091d823SDavid Xu #include <string.h> 38bb535300SJeff Roberson #include <pthread.h> 3937a6356bSDavid Xu #include "un-namespace.h" 4089552201SMike Makonnen 41bb535300SJeff Roberson #include "thr_private.h" 42bb535300SJeff Roberson 43bb535300SJeff Roberson /* #define DEBUG_SIGNAL */ 44bb535300SJeff Roberson #ifdef DEBUG_SIGNAL 45bb535300SJeff Roberson #define DBG_MSG stdout_debug 46bb535300SJeff Roberson #else 47bb535300SJeff Roberson #define DBG_MSG(x...) 48bb535300SJeff Roberson #endif 49bb535300SJeff Roberson 5005c3a5eaSDavid Xu extern int __pause(void); 5105c3a5eaSDavid Xu int ___pause(void); 5205c3a5eaSDavid Xu int _raise(int); 5337a6356bSDavid Xu int __sigtimedwait(const sigset_t *set, siginfo_t *info, 5437a6356bSDavid Xu const struct timespec * timeout); 55922d56f9SDavid Xu int _sigtimedwait(const sigset_t *set, siginfo_t *info, 56922d56f9SDavid Xu const struct timespec * timeout); 5737a6356bSDavid Xu int __sigwaitinfo(const sigset_t *set, siginfo_t *info); 58922d56f9SDavid Xu int _sigwaitinfo(const sigset_t *set, siginfo_t *info); 5937a6356bSDavid Xu int __sigwait(const sigset_t *set, int *sig); 60922d56f9SDavid Xu int _sigwait(const sigset_t *set, int *sig); 61922d56f9SDavid Xu int __sigsuspend(const sigset_t *sigmask); 6237a6356bSDavid Xu 636fdfcacbSDavid Xu 64a091d823SDavid Xu static void 6537a6356bSDavid Xu sigcancel_handler(int sig __unused, 6637a6356bSDavid Xu siginfo_t *info __unused, ucontext_t *ucp __unused) 67a091d823SDavid Xu { 68a091d823SDavid Xu struct pthread *curthread = _get_curthread(); 69a091d823SDavid Xu 701cb51125SDavid Xu curthread->in_sigcancel_handler++; 71bc414752SDavid Xu _thr_ast(curthread); 721cb51125SDavid Xu curthread->in_sigcancel_handler--; 73bc414752SDavid Xu } 74bc414752SDavid Xu 75bc414752SDavid Xu void 76bc414752SDavid Xu _thr_ast(struct pthread *curthread) 77bc414752SDavid Xu { 78*635f917aSDavid Xu 79*635f917aSDavid Xu if (THR_IN_CRITICAL(curthread)) 80*635f917aSDavid Xu return; 81*635f917aSDavid Xu 82*635f917aSDavid Xu if (curthread->cancel_pending && curthread->cancel_enable 83*635f917aSDavid Xu && !curthread->cancelling) { 84*635f917aSDavid Xu if (curthread->cancel_async) { 85*635f917aSDavid Xu /* 86*635f917aSDavid Xu * asynchronous cancellation mode, act upon 87*635f917aSDavid Xu * immediately. 88*635f917aSDavid Xu */ 89*635f917aSDavid Xu _pthread_exit(PTHREAD_CANCELED); 90*635f917aSDavid Xu } else { 91*635f917aSDavid Xu /* 92*635f917aSDavid Xu * Otherwise, we are in defer mode, and we are at 93*635f917aSDavid Xu * cancel point, tell kernel to not block the current 94*635f917aSDavid Xu * thread on next cancelable system call. 95*635f917aSDavid Xu * 96*635f917aSDavid Xu * There are two cases we should call thr_wake() to 97*635f917aSDavid Xu * turn on TDP_WAKEUP in kernel: 98*635f917aSDavid Xu * 1) we are going to call a cancelable system call, 99*635f917aSDavid Xu * non-zero cancel_point means we are already in 100*635f917aSDavid Xu * cancelable state, next system call is cancelable. 101*635f917aSDavid Xu * 2) because _thr_ast() may be called by 102*635f917aSDavid Xu * THR_CRITICAL_LEAVE() which is used by rtld rwlock 103*635f917aSDavid Xu * and any libthr internal locks, when rtld rwlock 104*635f917aSDavid Xu * is used, it is mostly caused my an unresolved PLT. 105*635f917aSDavid Xu * those routines may clear the TDP_WAKEUP flag by 106*635f917aSDavid Xu * invoking some system calls, in those cases, we 107*635f917aSDavid Xu * also should reenable the flag. 108*635f917aSDavid Xu */ 109*635f917aSDavid Xu if (curthread->cancel_point) { 110*635f917aSDavid Xu if (curthread->cancel_defer) 111*635f917aSDavid Xu thr_wake(curthread->tid); 112*635f917aSDavid Xu else 113*635f917aSDavid Xu _pthread_exit(PTHREAD_CANCELED); 114*635f917aSDavid Xu } 115*635f917aSDavid Xu } 116*635f917aSDavid Xu } 117*635f917aSDavid Xu 118bc414752SDavid Xu if (__predict_false((curthread->flags & 119bc414752SDavid Xu (THR_FLAGS_NEED_SUSPEND | THR_FLAGS_SUSPENDED)) 120bc414752SDavid Xu == THR_FLAGS_NEED_SUSPEND)) 121a091d823SDavid Xu _thr_suspend_check(curthread); 122a091d823SDavid Xu } 123a091d823SDavid Xu 124a091d823SDavid Xu void 125a091d823SDavid Xu _thr_suspend_check(struct pthread *curthread) 126a091d823SDavid Xu { 1278d6a11a0SDavid Xu uint32_t cycle; 128d448272dSDavid Xu int err; 129a091d823SDavid Xu 1302ea1f90aSDavid Xu if (curthread->force_exit) 1312ea1f90aSDavid Xu return; 1322ea1f90aSDavid Xu 133d448272dSDavid Xu err = errno; 134bc414752SDavid Xu /* 135bc414752SDavid Xu * Blocks SIGCANCEL which other threads must send. 136bc414752SDavid Xu */ 137a091d823SDavid Xu _thr_signal_block(curthread); 138bc414752SDavid Xu 139bc414752SDavid Xu /* 140bc414752SDavid Xu * Increase critical_count, here we don't use THR_LOCK/UNLOCK 141bc414752SDavid Xu * because we are leaf code, we don't want to recursively call 142bc414752SDavid Xu * ourself. 143bc414752SDavid Xu */ 144bc414752SDavid Xu curthread->critical_count++; 145bddd24cdSDavid Xu THR_UMUTEX_LOCK(curthread, &(curthread)->lock); 146bc414752SDavid Xu while ((curthread->flags & (THR_FLAGS_NEED_SUSPEND | 147bc414752SDavid Xu THR_FLAGS_SUSPENDED)) == THR_FLAGS_NEED_SUSPEND) { 148bc414752SDavid Xu curthread->cycle++; 149a091d823SDavid Xu cycle = curthread->cycle; 150bc414752SDavid Xu 151bc414752SDavid Xu /* Wake the thread suspending us. */ 1528d6a11a0SDavid Xu _thr_umtx_wake(&curthread->cycle, INT_MAX, 0); 153bc414752SDavid Xu 154bc414752SDavid Xu /* 155bc414752SDavid Xu * if we are from pthread_exit, we don't want to 156bc414752SDavid Xu * suspend, just go and die. 157bc414752SDavid Xu */ 158bc414752SDavid Xu if (curthread->state == PS_DEAD) 159bc414752SDavid Xu break; 160bc414752SDavid Xu curthread->flags |= THR_FLAGS_SUSPENDED; 161bddd24cdSDavid Xu THR_UMUTEX_UNLOCK(curthread, &(curthread)->lock); 1628d6a11a0SDavid Xu _thr_umtx_wait_uint(&curthread->cycle, cycle, NULL, 0); 163bddd24cdSDavid Xu THR_UMUTEX_LOCK(curthread, &(curthread)->lock); 164a091d823SDavid Xu curthread->flags &= ~THR_FLAGS_SUSPENDED; 165a091d823SDavid Xu } 166bddd24cdSDavid Xu THR_UMUTEX_UNLOCK(curthread, &(curthread)->lock); 167bc414752SDavid Xu curthread->critical_count--; 168bc414752SDavid Xu 169bc414752SDavid Xu /* 170bc414752SDavid Xu * Unblocks SIGCANCEL, it is possible a new SIGCANCEL is ready and 171bc414752SDavid Xu * a new signal frame will nest us, this seems a problem because 172bc414752SDavid Xu * stack will grow and overflow, but because kernel will automatically 173bc414752SDavid Xu * mask the SIGCANCEL when delivering the signal, so we at most only 174bc414752SDavid Xu * have one nesting signal frame, this should be fine. 175bc414752SDavid Xu */ 176a091d823SDavid Xu _thr_signal_unblock(curthread); 177d448272dSDavid Xu errno = err; 178a091d823SDavid Xu } 179a091d823SDavid Xu 180a091d823SDavid Xu void 181a091d823SDavid Xu _thr_signal_init(void) 182a091d823SDavid Xu { 183a091d823SDavid Xu struct sigaction act; 184a091d823SDavid Xu 185a091d823SDavid Xu /* Install cancel handler. */ 186a091d823SDavid Xu SIGEMPTYSET(act.sa_mask); 187a091d823SDavid Xu act.sa_flags = SA_SIGINFO | SA_RESTART; 188a091d823SDavid Xu act.sa_sigaction = (__siginfohandler_t *)&sigcancel_handler; 189a091d823SDavid Xu __sys_sigaction(SIGCANCEL, &act, NULL); 190a091d823SDavid Xu } 191a091d823SDavid Xu 192a091d823SDavid Xu void 193a091d823SDavid Xu _thr_signal_deinit(void) 194a091d823SDavid Xu { 195a091d823SDavid Xu } 196a091d823SDavid Xu 19705c3a5eaSDavid Xu __weak_reference(___pause, pause); 19805c3a5eaSDavid Xu 19905c3a5eaSDavid Xu int 20005c3a5eaSDavid Xu ___pause(void) 20105c3a5eaSDavid Xu { 20205c3a5eaSDavid Xu struct pthread *curthread = _get_curthread(); 20305c3a5eaSDavid Xu int ret; 20405c3a5eaSDavid Xu 205f08e1bf6SDavid Xu _thr_cancel_enter(curthread); 20605c3a5eaSDavid Xu ret = __pause(); 207f08e1bf6SDavid Xu _thr_cancel_leave(curthread); 20805c3a5eaSDavid Xu 20905c3a5eaSDavid Xu return ret; 21005c3a5eaSDavid Xu } 21105c3a5eaSDavid Xu 21205c3a5eaSDavid Xu __weak_reference(_raise, raise); 21305c3a5eaSDavid Xu 21405c3a5eaSDavid Xu int 21505c3a5eaSDavid Xu _raise(int sig) 21605c3a5eaSDavid Xu { 21705c3a5eaSDavid Xu int ret; 21805c3a5eaSDavid Xu 21905c3a5eaSDavid Xu if (!_thr_isthreaded()) 22005c3a5eaSDavid Xu ret = kill(getpid(), sig); 22105c3a5eaSDavid Xu else 22205c3a5eaSDavid Xu ret = _thr_send_sig(_get_curthread(), sig); 22305c3a5eaSDavid Xu return (ret); 22405c3a5eaSDavid Xu } 22505c3a5eaSDavid Xu 226a091d823SDavid Xu __weak_reference(_sigaction, sigaction); 227a091d823SDavid Xu 228a091d823SDavid Xu int 229a091d823SDavid Xu _sigaction(int sig, const struct sigaction * act, struct sigaction * oact) 230a091d823SDavid Xu { 231a091d823SDavid Xu /* Check if the signal number is out of range: */ 232b144e48bSKonstantin Belousov if (!_SIG_VALID(sig) || sig == SIGCANCEL) { 233a091d823SDavid Xu /* Return an invalid argument: */ 234a091d823SDavid Xu errno = EINVAL; 235a091d823SDavid Xu return (-1); 236a091d823SDavid Xu } 237a091d823SDavid Xu 238a091d823SDavid Xu return __sys_sigaction(sig, act, oact); 239a091d823SDavid Xu } 240a091d823SDavid Xu 241a091d823SDavid Xu __weak_reference(_sigprocmask, sigprocmask); 242a091d823SDavid Xu 243a091d823SDavid Xu int 244a091d823SDavid Xu _sigprocmask(int how, const sigset_t *set, sigset_t *oset) 245a091d823SDavid Xu { 246a091d823SDavid Xu const sigset_t *p = set; 247a091d823SDavid Xu sigset_t newset; 248a091d823SDavid Xu 249a091d823SDavid Xu if (how != SIG_UNBLOCK) { 250a091d823SDavid Xu if (set != NULL) { 251a091d823SDavid Xu newset = *set; 252a091d823SDavid Xu SIGDELSET(newset, SIGCANCEL); 253a091d823SDavid Xu p = &newset; 254a091d823SDavid Xu } 255a091d823SDavid Xu } 256a091d823SDavid Xu return (__sys_sigprocmask(how, p, oset)); 257a091d823SDavid Xu } 258a091d823SDavid Xu 259bb535300SJeff Roberson __weak_reference(_pthread_sigmask, pthread_sigmask); 260bb535300SJeff Roberson 261bb535300SJeff Roberson int 262bb535300SJeff Roberson _pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) 263bb535300SJeff Roberson { 264a091d823SDavid Xu if (_sigprocmask(how, set, oset)) 265a091d823SDavid Xu return (errno); 266a091d823SDavid Xu return (0); 267bb535300SJeff Roberson } 268bb535300SJeff Roberson 26905c3a5eaSDavid Xu __weak_reference(__sigsuspend, sigsuspend); 270bb535300SJeff Roberson 271bb535300SJeff Roberson int 272a091d823SDavid Xu _sigsuspend(const sigset_t * set) 273bb535300SJeff Roberson { 27405c3a5eaSDavid Xu sigset_t newset; 27505c3a5eaSDavid Xu const sigset_t *pset; 27605c3a5eaSDavid Xu int ret; 27705c3a5eaSDavid Xu 27805c3a5eaSDavid Xu if (SIGISMEMBER(*set, SIGCANCEL)) { 27905c3a5eaSDavid Xu newset = *set; 28005c3a5eaSDavid Xu SIGDELSET(newset, SIGCANCEL); 28105c3a5eaSDavid Xu pset = &newset; 28205c3a5eaSDavid Xu } else 28305c3a5eaSDavid Xu pset = set; 28405c3a5eaSDavid Xu 28505c3a5eaSDavid Xu ret = __sys_sigsuspend(pset); 28605c3a5eaSDavid Xu 28705c3a5eaSDavid Xu return (ret); 28805c3a5eaSDavid Xu } 28905c3a5eaSDavid Xu 29005c3a5eaSDavid Xu int 29105c3a5eaSDavid Xu __sigsuspend(const sigset_t * set) 29205c3a5eaSDavid Xu { 293a091d823SDavid Xu struct pthread *curthread = _get_curthread(); 294a091d823SDavid Xu sigset_t newset; 295a091d823SDavid Xu const sigset_t *pset; 296a091d823SDavid Xu int ret; 297bb535300SJeff Roberson 298a091d823SDavid Xu if (SIGISMEMBER(*set, SIGCANCEL)) { 299a091d823SDavid Xu newset = *set; 300a091d823SDavid Xu SIGDELSET(newset, SIGCANCEL); 301a091d823SDavid Xu pset = &newset; 302a091d823SDavid Xu } else 303a091d823SDavid Xu pset = set; 3040ad70ba9SMike Makonnen 305f08e1bf6SDavid Xu _thr_cancel_enter(curthread); 306a091d823SDavid Xu ret = __sys_sigsuspend(pset); 307f08e1bf6SDavid Xu _thr_cancel_leave(curthread); 3080ad70ba9SMike Makonnen 309a091d823SDavid Xu return (ret); 310a091d823SDavid Xu } 311a091d823SDavid Xu 312a091d823SDavid Xu __weak_reference(__sigwait, sigwait); 313a091d823SDavid Xu __weak_reference(__sigtimedwait, sigtimedwait); 314a091d823SDavid Xu __weak_reference(__sigwaitinfo, sigwaitinfo); 315a091d823SDavid Xu 316a091d823SDavid Xu int 31705c3a5eaSDavid Xu _sigtimedwait(const sigset_t *set, siginfo_t *info, 31805c3a5eaSDavid Xu const struct timespec * timeout) 31905c3a5eaSDavid Xu { 32005c3a5eaSDavid Xu sigset_t newset; 32105c3a5eaSDavid Xu const sigset_t *pset; 32205c3a5eaSDavid Xu int ret; 32305c3a5eaSDavid Xu 32405c3a5eaSDavid Xu if (SIGISMEMBER(*set, SIGCANCEL)) { 32505c3a5eaSDavid Xu newset = *set; 32605c3a5eaSDavid Xu SIGDELSET(newset, SIGCANCEL); 32705c3a5eaSDavid Xu pset = &newset; 32805c3a5eaSDavid Xu } else 32905c3a5eaSDavid Xu pset = set; 33005c3a5eaSDavid Xu ret = __sys_sigtimedwait(pset, info, timeout); 33105c3a5eaSDavid Xu return (ret); 33205c3a5eaSDavid Xu } 33305c3a5eaSDavid Xu 334*635f917aSDavid Xu /* 335*635f917aSDavid Xu * Cancellation behavior: 336*635f917aSDavid Xu * Thread may be canceled at start, if thread got signal, 337*635f917aSDavid Xu * it is not canceled. 338*635f917aSDavid Xu */ 33905c3a5eaSDavid Xu int 340a091d823SDavid Xu __sigtimedwait(const sigset_t *set, siginfo_t *info, 341a091d823SDavid Xu const struct timespec * timeout) 342a091d823SDavid Xu { 343a091d823SDavid Xu struct pthread *curthread = _get_curthread(); 344a091d823SDavid Xu sigset_t newset; 345a091d823SDavid Xu const sigset_t *pset; 346a091d823SDavid Xu int ret; 347a091d823SDavid Xu 348a091d823SDavid Xu if (SIGISMEMBER(*set, SIGCANCEL)) { 349a091d823SDavid Xu newset = *set; 350a091d823SDavid Xu SIGDELSET(newset, SIGCANCEL); 351a091d823SDavid Xu pset = &newset; 352a091d823SDavid Xu } else 353a091d823SDavid Xu pset = set; 354*635f917aSDavid Xu _thr_cancel_enter_defer(curthread, 1); 355a091d823SDavid Xu ret = __sys_sigtimedwait(pset, info, timeout); 356*635f917aSDavid Xu _thr_cancel_leave_defer(curthread, (ret == -1)); 357a091d823SDavid Xu return (ret); 358a091d823SDavid Xu } 359a091d823SDavid Xu 360a091d823SDavid Xu int 36105c3a5eaSDavid Xu _sigwaitinfo(const sigset_t *set, siginfo_t *info) 36205c3a5eaSDavid Xu { 36305c3a5eaSDavid Xu sigset_t newset; 36405c3a5eaSDavid Xu const sigset_t *pset; 36505c3a5eaSDavid Xu int ret; 36605c3a5eaSDavid Xu 36705c3a5eaSDavid Xu if (SIGISMEMBER(*set, SIGCANCEL)) { 36805c3a5eaSDavid Xu newset = *set; 36905c3a5eaSDavid Xu SIGDELSET(newset, SIGCANCEL); 37005c3a5eaSDavid Xu pset = &newset; 37105c3a5eaSDavid Xu } else 37205c3a5eaSDavid Xu pset = set; 37305c3a5eaSDavid Xu 37405c3a5eaSDavid Xu ret = __sys_sigwaitinfo(pset, info); 37505c3a5eaSDavid Xu return (ret); 37605c3a5eaSDavid Xu } 37705c3a5eaSDavid Xu 378*635f917aSDavid Xu /* 379*635f917aSDavid Xu * Cancellation behavior: 380*635f917aSDavid Xu * Thread may be canceled at start, if thread got signal, 381*635f917aSDavid Xu * it is not canceled. 382*635f917aSDavid Xu */ 38305c3a5eaSDavid Xu int 384a091d823SDavid Xu __sigwaitinfo(const sigset_t *set, siginfo_t *info) 385a091d823SDavid Xu { 386a091d823SDavid Xu struct pthread *curthread = _get_curthread(); 387a091d823SDavid Xu sigset_t newset; 388a091d823SDavid Xu const sigset_t *pset; 389a091d823SDavid Xu int ret; 390a091d823SDavid Xu 391a091d823SDavid Xu if (SIGISMEMBER(*set, SIGCANCEL)) { 392a091d823SDavid Xu newset = *set; 393a091d823SDavid Xu SIGDELSET(newset, SIGCANCEL); 394a091d823SDavid Xu pset = &newset; 395a091d823SDavid Xu } else 396a091d823SDavid Xu pset = set; 397a091d823SDavid Xu 398*635f917aSDavid Xu _thr_cancel_enter_defer(curthread, 1); 399a091d823SDavid Xu ret = __sys_sigwaitinfo(pset, info); 400*635f917aSDavid Xu _thr_cancel_leave_defer(curthread, ret == -1); 401a091d823SDavid Xu return (ret); 402a091d823SDavid Xu } 403a091d823SDavid Xu 404a091d823SDavid Xu int 40505c3a5eaSDavid Xu _sigwait(const sigset_t *set, int *sig) 40605c3a5eaSDavid Xu { 40705c3a5eaSDavid Xu sigset_t newset; 40805c3a5eaSDavid Xu const sigset_t *pset; 40905c3a5eaSDavid Xu int ret; 41005c3a5eaSDavid Xu 41105c3a5eaSDavid Xu if (SIGISMEMBER(*set, SIGCANCEL)) { 41205c3a5eaSDavid Xu newset = *set; 41305c3a5eaSDavid Xu SIGDELSET(newset, SIGCANCEL); 41405c3a5eaSDavid Xu pset = &newset; 41505c3a5eaSDavid Xu } else 41605c3a5eaSDavid Xu pset = set; 41705c3a5eaSDavid Xu 41805c3a5eaSDavid Xu ret = __sys_sigwait(pset, sig); 41905c3a5eaSDavid Xu return (ret); 42005c3a5eaSDavid Xu } 42105c3a5eaSDavid Xu 422*635f917aSDavid Xu /* 423*635f917aSDavid Xu * Cancellation behavior: 424*635f917aSDavid Xu * Thread may be canceled at start, if thread got signal, 425*635f917aSDavid Xu * it is not canceled. 426*635f917aSDavid Xu */ 42705c3a5eaSDavid Xu int 428a091d823SDavid Xu __sigwait(const sigset_t *set, int *sig) 429a091d823SDavid Xu { 430a091d823SDavid Xu struct pthread *curthread = _get_curthread(); 431a091d823SDavid Xu sigset_t newset; 432a091d823SDavid Xu const sigset_t *pset; 433a091d823SDavid Xu int ret; 434a091d823SDavid Xu 435a091d823SDavid Xu if (SIGISMEMBER(*set, SIGCANCEL)) { 436a091d823SDavid Xu newset = *set; 437a091d823SDavid Xu SIGDELSET(newset, SIGCANCEL); 438a091d823SDavid Xu pset = &newset; 439a091d823SDavid Xu } else 440a091d823SDavid Xu pset = set; 441a091d823SDavid Xu 442*635f917aSDavid Xu _thr_cancel_enter_defer(curthread, 1); 443a091d823SDavid Xu ret = __sys_sigwait(pset, sig); 444*635f917aSDavid Xu _thr_cancel_leave_defer(curthread, (ret != 0)); 445a091d823SDavid Xu return (ret); 446bb535300SJeff Roberson } 447