1/* 2 * Copyright (c) 2005, David Xu <davidxu@freebsd.org> 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 unchanged lines hidden (view full) --- 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * |
26 * $FreeBSD: head/lib/libthr/thread/thr_sig.c 211524 2010-08-20 05:15:39Z davidxu $ |
27 */ 28 29#include "namespace.h" 30#include <sys/param.h> 31#include <sys/types.h> 32#include <sys/signalvar.h> 33#include <signal.h> 34#include <errno.h> --- 27 unchanged lines hidden (view full) --- 62 63 64static void 65sigcancel_handler(int sig __unused, 66 siginfo_t *info __unused, ucontext_t *ucp __unused) 67{ 68 struct pthread *curthread = _get_curthread(); 69 |
70 curthread->in_sigcancel_handler++; 71 _thr_ast(curthread); 72 curthread->in_sigcancel_handler--; 73} 74 75void 76_thr_ast(struct pthread *curthread) 77{ |
78 79 if (THR_IN_CRITICAL(curthread)) 80 return; 81 82 if (curthread->cancel_pending && curthread->cancel_enable 83 && !curthread->cancelling) { 84 if (curthread->cancel_async) { 85 /* 86 * asynchronous cancellation mode, act upon 87 * immediately. 88 */ 89 _pthread_exit(PTHREAD_CANCELED); 90 } else { 91 /* 92 * Otherwise, we are in defer mode, and we are at 93 * cancel point, tell kernel to not block the current 94 * thread on next cancelable system call. 95 * 96 * There are two cases we should call thr_wake() to 97 * turn on TDP_WAKEUP in kernel: 98 * 1) we are going to call a cancelable system call, 99 * non-zero cancel_point means we are already in 100 * cancelable state, next system call is cancelable. 101 * 2) because _thr_ast() may be called by 102 * THR_CRITICAL_LEAVE() which is used by rtld rwlock 103 * and any libthr internal locks, when rtld rwlock 104 * is used, it is mostly caused my an unresolved PLT. 105 * those routines may clear the TDP_WAKEUP flag by 106 * invoking some system calls, in those cases, we 107 * also should reenable the flag. 108 */ 109 if (curthread->cancel_point) { 110 if (curthread->cancel_defer) 111 thr_wake(curthread->tid); 112 else 113 _pthread_exit(PTHREAD_CANCELED); 114 } 115 } |
116 } |
117 118 if (__predict_false((curthread->flags & 119 (THR_FLAGS_NEED_SUSPEND | THR_FLAGS_SUSPENDED)) 120 == THR_FLAGS_NEED_SUSPEND)) 121 _thr_suspend_check(curthread); |
122} 123 124void 125_thr_suspend_check(struct pthread *curthread) 126{ 127 uint32_t cycle; 128 int err; 129 --- 196 unchanged lines hidden (view full) --- 326 SIGDELSET(newset, SIGCANCEL); 327 pset = &newset; 328 } else 329 pset = set; 330 ret = __sys_sigtimedwait(pset, info, timeout); 331 return (ret); 332} 333 |
334/* 335 * Cancellation behavior: 336 * Thread may be canceled at start, if thread got signal, 337 * it is not canceled. 338 */ |
339int 340__sigtimedwait(const sigset_t *set, siginfo_t *info, 341 const struct timespec * timeout) 342{ 343 struct pthread *curthread = _get_curthread(); 344 sigset_t newset; 345 const sigset_t *pset; 346 int ret; 347 348 if (SIGISMEMBER(*set, SIGCANCEL)) { 349 newset = *set; 350 SIGDELSET(newset, SIGCANCEL); 351 pset = &newset; 352 } else 353 pset = set; |
354 _thr_cancel_enter_defer(curthread, 1); |
355 ret = __sys_sigtimedwait(pset, info, timeout); |
356 _thr_cancel_leave_defer(curthread, (ret == -1)); |
357 return (ret); 358} 359 360int 361_sigwaitinfo(const sigset_t *set, siginfo_t *info) 362{ 363 sigset_t newset; 364 const sigset_t *pset; --- 5 unchanged lines hidden (view full) --- 370 pset = &newset; 371 } else 372 pset = set; 373 374 ret = __sys_sigwaitinfo(pset, info); 375 return (ret); 376} 377 |
378/* 379 * Cancellation behavior: 380 * Thread may be canceled at start, if thread got signal, 381 * it is not canceled. 382 */ |
383int 384__sigwaitinfo(const sigset_t *set, siginfo_t *info) 385{ 386 struct pthread *curthread = _get_curthread(); 387 sigset_t newset; 388 const sigset_t *pset; 389 int ret; 390 391 if (SIGISMEMBER(*set, SIGCANCEL)) { 392 newset = *set; 393 SIGDELSET(newset, SIGCANCEL); 394 pset = &newset; 395 } else 396 pset = set; 397 |
398 _thr_cancel_enter_defer(curthread, 1); |
399 ret = __sys_sigwaitinfo(pset, info); |
400 _thr_cancel_leave_defer(curthread, ret == -1); |
401 return (ret); 402} 403 404int 405_sigwait(const sigset_t *set, int *sig) 406{ 407 sigset_t newset; 408 const sigset_t *pset; --- 5 unchanged lines hidden (view full) --- 414 pset = &newset; 415 } else 416 pset = set; 417 418 ret = __sys_sigwait(pset, sig); 419 return (ret); 420} 421 |
422/* 423 * Cancellation behavior: 424 * Thread may be canceled at start, if thread got signal, 425 * it is not canceled. 426 */ |
427int 428__sigwait(const sigset_t *set, int *sig) 429{ 430 struct pthread *curthread = _get_curthread(); 431 sigset_t newset; 432 const sigset_t *pset; 433 int ret; 434 435 if (SIGISMEMBER(*set, SIGCANCEL)) { 436 newset = *set; 437 SIGDELSET(newset, SIGCANCEL); 438 pset = &newset; 439 } else 440 pset = set; 441 |
442 _thr_cancel_enter_defer(curthread, 1); |
443 ret = __sys_sigwait(pset, sig); |
444 _thr_cancel_leave_defer(curthread, (ret != 0)); |
445 return (ret); 446} |