Deleted Added
full compact
thr_sig.c (211737) thr_sig.c (212076)
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 *
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 211737 2010-08-24 09:57:06Z davidxu $
26 * $FreeBSD: head/lib/libthr/thread/thr_sig.c 212076 2010-09-01 02:18:33Z 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 */
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>
35#include <fcntl.h>
36#include <unistd.h>
37#include <string.h>
38#include <pthread.h>
39#include "un-namespace.h"
35#include <string.h>
36#include <pthread.h>
37#include "un-namespace.h"
38#include "libc_private.h"
40
41#include "thr_private.h"
42
43/* #define DEBUG_SIGNAL */
44#ifdef DEBUG_SIGNAL
45#define DBG_MSG stdout_debug
46#else
47#define DBG_MSG(x...)
48#endif
49
39
40#include "thr_private.h"
41
42/* #define DEBUG_SIGNAL */
43#ifdef DEBUG_SIGNAL
44#define DBG_MSG stdout_debug
45#else
46#define DBG_MSG(x...)
47#endif
48
50extern int __pause(void);
49struct usigaction {
50 struct sigaction sigact;
51 struct urwlock lock;
52};
53
54static struct usigaction _thr_sigact[_SIG_MAXSIG];
55
56static void thr_sighandler(int, siginfo_t *, void *);
57static void handle_signal(struct sigaction *, int, siginfo_t *, ucontext_t *);
58static void check_deferred_signal(struct pthread *);
59static void check_suspend(struct pthread *);
60static void check_cancel(struct pthread *curthread, ucontext_t *ucp);
61
51int ___pause(void);
52int _raise(int);
53int __sigtimedwait(const sigset_t *set, siginfo_t *info,
54 const struct timespec * timeout);
55int _sigtimedwait(const sigset_t *set, siginfo_t *info,
56 const struct timespec * timeout);
57int __sigwaitinfo(const sigset_t *set, siginfo_t *info);
58int _sigwaitinfo(const sigset_t *set, siginfo_t *info);
59int __sigwait(const sigset_t *set, int *sig);
60int _sigwait(const sigset_t *set, int *sig);
61int __sigsuspend(const sigset_t *sigmask);
62int ___pause(void);
63int _raise(int);
64int __sigtimedwait(const sigset_t *set, siginfo_t *info,
65 const struct timespec * timeout);
66int _sigtimedwait(const sigset_t *set, siginfo_t *info,
67 const struct timespec * timeout);
68int __sigwaitinfo(const sigset_t *set, siginfo_t *info);
69int _sigwaitinfo(const sigset_t *set, siginfo_t *info);
70int __sigwait(const sigset_t *set, int *sig);
71int _sigwait(const sigset_t *set, int *sig);
72int __sigsuspend(const sigset_t *sigmask);
73int _sigaction(int, const struct sigaction *, struct sigaction *);
62int _setcontext(const ucontext_t *);
63int _swapcontext(ucontext_t *, const ucontext_t *);
64
74int _setcontext(const ucontext_t *);
75int _swapcontext(ucontext_t *, const ucontext_t *);
76
65static void
77static const sigset_t _thr_deferset={{
78 0xffffffff & ~(_SIG_BIT(SIGBUS)|_SIG_BIT(SIGILL)|_SIG_BIT(SIGFPE)|
79 _SIG_BIT(SIGSEGV)|_SIG_BIT(SIGTRAP)|_SIG_BIT(SIGSYS)),
80 0xffffffff,
81 0xffffffff,
82 0xffffffff}};
83
84static const sigset_t _thr_maskset={{
85 0xffffffff,
86 0xffffffff,
87 0xffffffff,
88 0xffffffff}};
89
90void
91_thr_signal_block(struct pthread *curthread)
92{
93
94 if (curthread->sigblock > 0) {
95 curthread->sigblock++;
96 return;
97 }
98 __sys_sigprocmask(SIG_BLOCK, &_thr_maskset, &curthread->sigmask);
99 curthread->sigblock++;
100}
101
102void
103_thr_signal_unblock(struct pthread *curthread)
104{
105 if (--curthread->sigblock == 0)
106 __sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL);
107}
108
109int
110_thr_send_sig(struct pthread *thread, int sig)
111{
112 return thr_kill(thread->tid, sig);
113}
114
115static inline void
66remove_thr_signals(sigset_t *set)
67{
68 if (SIGISMEMBER(*set, SIGCANCEL))
69 SIGDELSET(*set, SIGCANCEL);
70}
71
72static const sigset_t *
73thr_remove_thr_signals(const sigset_t *set, sigset_t *newset)
74{
116remove_thr_signals(sigset_t *set)
117{
118 if (SIGISMEMBER(*set, SIGCANCEL))
119 SIGDELSET(*set, SIGCANCEL);
120}
121
122static const sigset_t *
123thr_remove_thr_signals(const sigset_t *set, sigset_t *newset)
124{
75 const sigset_t *pset;
76
77 if (SIGISMEMBER(*set, SIGCANCEL)) {
78 *newset = *set;
79 SIGDELSET(*newset, SIGCANCEL);
80 pset = newset;
81 } else
82 pset = set;
83 return (pset);
125 *newset = *set;
126 remove_thr_signals(newset);
127 return (newset);
84}
85
86static void
87sigcancel_handler(int sig __unused,
128}
129
130static void
131sigcancel_handler(int sig __unused,
88 siginfo_t *info __unused, ucontext_t *ucp __unused)
132 siginfo_t *info __unused, ucontext_t *ucp)
89{
90 struct pthread *curthread = _get_curthread();
133{
134 struct pthread *curthread = _get_curthread();
135 int err;
91
136
92 curthread->in_sigcancel_handler++;
93 _thr_ast(curthread);
94 curthread->in_sigcancel_handler--;
137 if (THR_IN_CRITICAL(curthread))
138 return;
139 err = errno;
140 check_suspend(curthread);
141 check_cancel(curthread, ucp);
142 errno = err;
95}
96
143}
144
145typedef void (*ohandler)(int sig, int code,
146 struct sigcontext *scp, char *addr, __sighandler_t *catcher);
147
148/*
149 * The signal handler wrapper is entered with all signal masked.
150 */
151static void
152thr_sighandler(int sig, siginfo_t *info, void *_ucp)
153{
154 struct pthread *curthread = _get_curthread();
155 ucontext_t *ucp = _ucp;
156 struct sigaction act;
157 int err;
158
159 err = errno;
160 _thr_rwl_rdlock(&_thr_sigact[sig-1].lock);
161 act = _thr_sigact[sig-1].sigact;
162 _thr_rwl_unlock(&_thr_sigact[sig-1].lock);
163 errno = err;
164
165 /*
166 * if a thread is in critical region, for example it holds low level locks,
167 * try to defer the signal processing, however if the signal is synchronous
168 * signal, it means a bad thing has happened, this is a programming error,
169 * resuming fault point can not help anything (normally causes deadloop),
170 * so here we let user code handle it immediately.
171 */
172 if (THR_IN_CRITICAL(curthread) && SIGISMEMBER(_thr_deferset, sig)) {
173 memcpy(&curthread->deferred_sigact, &act, sizeof(struct sigaction));
174 memcpy(&curthread->deferred_siginfo, info, sizeof(siginfo_t));
175 curthread->deferred_sigmask = ucp->uc_sigmask;
176 /* mask all signals, we will restore it later. */
177 ucp->uc_sigmask = _thr_deferset;
178 return;
179 }
180
181 handle_signal(&act, sig, info, ucp);
182}
183
184static void
185handle_signal(struct sigaction *actp, int sig, siginfo_t *info, ucontext_t *ucp)
186{
187 struct pthread *curthread = _get_curthread();
188 ucontext_t uc2;
189 __siginfohandler_t *sigfunc;
190 int cancel_defer;
191 int cancel_point;
192 int cancel_async;
193 int cancel_enable;
194 int in_sigsuspend;
195 int err;
196
197 /* add previous level mask */
198 SIGSETOR(actp->sa_mask, ucp->uc_sigmask);
199
200 /* add this signal's mask */
201 if (!(actp->sa_flags & SA_NODEFER))
202 SIGADDSET(actp->sa_mask, sig);
203
204 in_sigsuspend = curthread->in_sigsuspend;
205 curthread->in_sigsuspend = 0;
206
207 /*
208 * if thread is in deferred cancellation mode, disable cancellation
209 * in signal handler.
210 * if user signal handler calls a cancellation point function, e.g,
211 * it calls write() to write data to file, because write() is a
212 * cancellation point, the thread is immediately cancelled if
213 * cancellation is pending, to avoid this problem while thread is in
214 * deferring mode, cancellation is temporarily disabled.
215 */
216 cancel_defer = curthread->cancel_defer;
217 cancel_point = curthread->cancel_point;
218 cancel_async = curthread->cancel_async;
219 cancel_enable = curthread->cancel_enable;
220 curthread->cancel_point = 0;
221 curthread->cancel_defer = 0;
222 if (!cancel_async)
223 curthread->cancel_enable = 0;
224
225 /* restore correct mask before calling user handler */
226 __sys_sigprocmask(SIG_SETMASK, &actp->sa_mask, NULL);
227
228 sigfunc = actp->sa_sigaction;
229
230 /*
231 * We have already reset cancellation point flags, so if user's code
232 * longjmp()s out of its signal handler, wish its jmpbuf was set
233 * outside of a cancellation point, in most cases, this would be
234 * true. however, ther is no way to save cancel_enable in jmpbuf,
235 * so after setjmps() returns once more, the user code may need to
236 * re-set cancel_enable flag by calling pthread_setcancelstate().
237 */
238 if ((actp->sa_flags & SA_SIGINFO) != 0)
239 (*(sigfunc))(sig, info, ucp);
240 else {
241 ((ohandler)(*sigfunc))(
242 sig, info->si_code, (struct sigcontext *)ucp,
243 info->si_addr, (__sighandler_t *)sigfunc);
244 }
245 err = errno;
246
247 curthread->in_sigsuspend = in_sigsuspend;
248 curthread->cancel_defer = cancel_defer;
249 curthread->cancel_point = cancel_point;
250 curthread->cancel_enable = cancel_enable;
251
252 memcpy(&uc2, ucp, sizeof(uc2));
253 SIGDELSET(uc2.uc_sigmask, SIGCANCEL);
254
255 /* reschedule cancellation */
256 check_cancel(curthread, &uc2);
257 errno = err;
258 __sys_sigreturn(&uc2);
259}
260
97void
98_thr_ast(struct pthread *curthread)
99{
100
261void
262_thr_ast(struct pthread *curthread)
263{
264
101 if (THR_IN_CRITICAL(curthread))
265 if (!THR_IN_CRITICAL(curthread)) {
266 check_deferred_signal(curthread);
267 check_suspend(curthread);
268 check_cancel(curthread, NULL);
269 }
270}
271
272/* reschedule cancellation */
273static void
274check_cancel(struct pthread *curthread, ucontext_t *ucp)
275{
276
277 if (__predict_true(!curthread->cancel_pending || !curthread->cancel_enable ||
278 curthread->cancelling))
102 return;
103
279 return;
280
104 if (curthread->cancel_pending && curthread->cancel_enable
105 && !curthread->cancelling) {
106 if (curthread->cancel_async) {
107 /*
108 * asynchronous cancellation mode, act upon
109 * immediately.
110 */
111 _pthread_exit(PTHREAD_CANCELED);
112 } else {
113 /*
114 * Otherwise, we are in defer mode, and we are at
115 * cancel point, tell kernel to not block the current
116 * thread on next cancelable system call.
117 *
118 * There are two cases we should call thr_wake() to
119 * turn on TDP_WAKEUP in kernel:
120 * 1) we are going to call a cancelable system call,
121 * non-zero cancel_point means we are already in
122 * cancelable state, next system call is cancelable.
123 * 2) because _thr_ast() may be called by
124 * THR_CRITICAL_LEAVE() which is used by rtld rwlock
125 * and any libthr internal locks, when rtld rwlock
126 * is used, it is mostly caused my an unresolved PLT.
127 * those routines may clear the TDP_WAKEUP flag by
128 * invoking some system calls, in those cases, we
129 * also should reenable the flag.
130 */
131 if (curthread->cancel_point) {
132 if (curthread->cancel_defer)
133 thr_wake(curthread->tid);
134 else
135 _pthread_exit(PTHREAD_CANCELED);
136 }
281 if (curthread->cancel_async) {
282 /*
283 * asynchronous cancellation mode, act upon
284 * immediately.
285 */
286 _pthread_exit_mask(PTHREAD_CANCELED,
287 ucp? &ucp->uc_sigmask : NULL);
288 } else {
289 /*
290 * Otherwise, we are in defer mode, and we are at
291 * cancel point, tell kernel to not block the current
292 * thread on next cancelable system call.
293 *
294 * There are three cases we should call thr_wake() to
295 * turn on TDP_WAKEUP or send SIGCANCEL in kernel:
296 * 1) we are going to call a cancelable system call,
297 * non-zero cancel_point means we are already in
298 * cancelable state, next system call is cancelable.
299 * 2) because _thr_ast() may be called by
300 * THR_CRITICAL_LEAVE() which is used by rtld rwlock
301 * and any libthr internal locks, when rtld rwlock
302 * is used, it is mostly caused my an unresolved PLT.
303 * those routines may clear the TDP_WAKEUP flag by
304 * invoking some system calls, in those cases, we
305 * also should reenable the flag.
306 * 3) thread is in sigsuspend(), and the syscall insists
307 * on getting a signal before it agrees to return.
308 */
309 if (curthread->cancel_point) {
310 if (curthread->in_sigsuspend && ucp) {
311 SIGADDSET(ucp->uc_sigmask, SIGCANCEL);
312 curthread->unblock_sigcancel = 1;
313 _thr_send_sig(curthread, SIGCANCEL);
314 } else
315 thr_wake(curthread->tid);
137 }
138 }
316 }
317 }
318}
139
319
140 if (__predict_false((curthread->flags &
141 (THR_FLAGS_NEED_SUSPEND | THR_FLAGS_SUSPENDED))
142 == THR_FLAGS_NEED_SUSPEND))
143 _thr_suspend_check(curthread);
320static void
321check_deferred_signal(struct pthread *curthread)
322{
323 ucontext_t uc;
324 struct sigaction act;
325 siginfo_t info;
326 volatile int first;
327
328 if (__predict_true(curthread->deferred_siginfo.si_signo == 0))
329 return;
330 first = 1;
331 getcontext(&uc);
332 if (first) {
333 first = 0;
334 act = curthread->deferred_sigact;
335 uc.uc_sigmask = curthread->deferred_sigmask;
336 memcpy(&info, &curthread->deferred_siginfo, sizeof(siginfo_t));
337 /* remove signal */
338 curthread->deferred_siginfo.si_signo = 0;
339 if (act.sa_flags & SA_RESETHAND) {
340 struct sigaction tact;
341
342 tact = act;
343 tact.sa_handler = SIG_DFL;
344 _sigaction(info.si_signo, &tact, NULL);
345 }
346 handle_signal(&act, info.si_signo, &info, &uc);
347 }
144}
145
348}
349
146void
147_thr_suspend_check(struct pthread *curthread)
350static void
351check_suspend(struct pthread *curthread)
148{
149 uint32_t cycle;
352{
353 uint32_t cycle;
150 int err;
151
354
355 if (__predict_true((curthread->flags &
356 (THR_FLAGS_NEED_SUSPEND | THR_FLAGS_SUSPENDED))
357 != THR_FLAGS_NEED_SUSPEND))
358 return;
359
152 if (curthread->force_exit)
153 return;
154
360 if (curthread->force_exit)
361 return;
362
155 err = errno;
156 /*
157 * Blocks SIGCANCEL which other threads must send.
158 */
159 _thr_signal_block(curthread);
160
161 /*
162 * Increase critical_count, here we don't use THR_LOCK/UNLOCK
163 * because we are leaf code, we don't want to recursively call

--- 19 unchanged lines hidden (view full) ---

183 THR_UMUTEX_UNLOCK(curthread, &(curthread)->lock);
184 _thr_umtx_wait_uint(&curthread->cycle, cycle, NULL, 0);
185 THR_UMUTEX_LOCK(curthread, &(curthread)->lock);
186 curthread->flags &= ~THR_FLAGS_SUSPENDED;
187 }
188 THR_UMUTEX_UNLOCK(curthread, &(curthread)->lock);
189 curthread->critical_count--;
190
363 /*
364 * Blocks SIGCANCEL which other threads must send.
365 */
366 _thr_signal_block(curthread);
367
368 /*
369 * Increase critical_count, here we don't use THR_LOCK/UNLOCK
370 * because we are leaf code, we don't want to recursively call

--- 19 unchanged lines hidden (view full) ---

390 THR_UMUTEX_UNLOCK(curthread, &(curthread)->lock);
391 _thr_umtx_wait_uint(&curthread->cycle, cycle, NULL, 0);
392 THR_UMUTEX_LOCK(curthread, &(curthread)->lock);
393 curthread->flags &= ~THR_FLAGS_SUSPENDED;
394 }
395 THR_UMUTEX_UNLOCK(curthread, &(curthread)->lock);
396 curthread->critical_count--;
397
191 /*
192 * Unblocks SIGCANCEL, it is possible a new SIGCANCEL is ready and
193 * a new signal frame will nest us, this seems a problem because
194 * stack will grow and overflow, but because kernel will automatically
195 * mask the SIGCANCEL when delivering the signal, so we at most only
196 * have one nesting signal frame, this should be fine.
197 */
198 _thr_signal_unblock(curthread);
398 _thr_signal_unblock(curthread);
199 errno = err;
200}
201
202void
203_thr_signal_init(void)
204{
205 struct sigaction act;
206
399}
400
401void
402_thr_signal_init(void)
403{
404 struct sigaction act;
405
207 /* Install cancel handler. */
208 SIGEMPTYSET(act.sa_mask);
209 act.sa_flags = SA_SIGINFO | SA_RESTART;
406 /* Install SIGCANCEL handler. */
407 SIGFILLSET(act.sa_mask);
408 act.sa_flags = SA_SIGINFO;
210 act.sa_sigaction = (__siginfohandler_t *)&sigcancel_handler;
211 __sys_sigaction(SIGCANCEL, &act, NULL);
409 act.sa_sigaction = (__siginfohandler_t *)&sigcancel_handler;
410 __sys_sigaction(SIGCANCEL, &act, NULL);
411
412 /* Unblock SIGCANCEL */
413 SIGEMPTYSET(act.sa_mask);
414 SIGADDSET(act.sa_mask, SIGCANCEL);
415 __sys_sigprocmask(SIG_UNBLOCK, &act.sa_mask, NULL);
212}
213
416}
417
418/*
419 * called from rtld with rtld_lock locked, because rtld_lock is
420 * a critical region, so all signals have already beeen masked.
421 */
214void
422void
423_thr_sigact_unload(struct dl_phdr_info *phdr_info)
424{
425 struct urwlock *rwlp;
426 struct sigaction *actp;
427 struct sigaction kact;
428 void (*handler)(int);
429 int sig;
430
431 for (sig = 1; sig < _SIG_MAXSIG; sig++) {
432 actp = &_thr_sigact[sig].sigact;
433retry:
434 handler = actp->sa_handler;
435 if (handler != SIG_DFL && handler != SIG_IGN &&
436 __elf_phdr_match_addr(phdr_info, handler)) {
437 rwlp = &_thr_sigact[sig].lock;
438 _thr_rwl_wrlock(rwlp);
439 if (handler != actp->sa_handler) {
440 _thr_rwl_unlock(rwlp);
441 goto retry;
442 }
443 actp->sa_handler = SIG_DFL;
444 actp->sa_flags = SA_SIGINFO;
445 SIGEMPTYSET(actp->sa_mask);
446 if (__sys_sigaction(sig, NULL, &kact) == 0 &&
447 kact.sa_handler != SIG_DFL &&
448 kact.sa_handler != SIG_IGN)
449 __sys_sigaction(sig, actp, NULL);
450 _thr_rwl_unlock(rwlp);
451 }
452 }
453}
454
455void
456_thr_signal_prefork(void)
457{
458 int i;
459
460 for (i = 1; i < _SIG_MAXSIG; ++i)
461 _thr_rwl_rdlock(&_thr_sigact[i-1].lock);
462}
463
464void
465_thr_signal_postfork(void)
466{
467 int i;
468
469 for (i = 1; i < _SIG_MAXSIG; ++i)
470 _thr_rwl_unlock(&_thr_sigact[i-1].lock);
471}
472
473void
474_thr_signal_postfork_child(void)
475{
476 int i;
477
478 for (i = 1; i < _SIG_MAXSIG; ++i)
479 bzero(&_thr_sigact[i-1].lock, sizeof(struct urwlock));
480}
481
482void
215_thr_signal_deinit(void)
216{
217}
218
219__weak_reference(___pause, pause);
220
221int
222___pause(void)
223{
483_thr_signal_deinit(void)
484{
485}
486
487__weak_reference(___pause, pause);
488
489int
490___pause(void)
491{
224 struct pthread *curthread = _get_curthread();
225 int ret;
492 sigset_t oset;
226
493
227 _thr_cancel_enter(curthread);
228 ret = __pause();
229 _thr_cancel_leave(curthread);
230
231 return ret;
494 if (_sigprocmask(SIG_BLOCK, NULL, &oset) == -1)
495 return (-1);
496 return (__sigsuspend(&oset));
232}
233
234__weak_reference(_raise, raise);
235
236int
237_raise(int sig)
238{
497}
498
499__weak_reference(_raise, raise);
500
501int
502_raise(int sig)
503{
239 int ret;
240
241 if (!_thr_isthreaded())
242 ret = kill(getpid(), sig);
243 else
244 ret = _thr_send_sig(_get_curthread(), sig);
245 return (ret);
504 return _thr_send_sig(_get_curthread(), sig);
246}
247
248__weak_reference(_sigaction, sigaction);
249
250int
251_sigaction(int sig, const struct sigaction * act, struct sigaction * oact)
252{
505}
506
507__weak_reference(_sigaction, sigaction);
508
509int
510_sigaction(int sig, const struct sigaction * act, struct sigaction * oact)
511{
253 /* Check if the signal number is out of range: */
512 struct sigaction newact, oldact, oldact2;
513 sigset_t oldset;
514 int ret = 0, err = 0;
515
254 if (!_SIG_VALID(sig) || sig == SIGCANCEL) {
516 if (!_SIG_VALID(sig) || sig == SIGCANCEL) {
255 /* Return an invalid argument: */
256 errno = EINVAL;
257 return (-1);
258 }
259
517 errno = EINVAL;
518 return (-1);
519 }
520
260 return __sys_sigaction(sig, act, oact);
521 if (act)
522 newact = *act;
523
524 __sys_sigprocmask(SIG_SETMASK, &_thr_maskset, &oldset);
525 _thr_rwl_wrlock(&_thr_sigact[sig-1].lock);
526
527 if (act != NULL) {
528 oldact2 = _thr_sigact[sig-1].sigact;
529
530 /*
531 * if a new sig handler is SIG_DFL or SIG_IGN,
532 * don't remove old handler from _thr_sigact[],
533 * so deferred signals still can use the handlers,
534 * multiple threads invoking sigaction itself is
535 * a race condition, so it is not a problem.
536 */
537 if (newact.sa_handler != SIG_DFL &&
538 newact.sa_handler != SIG_IGN) {
539 _thr_sigact[sig-1].sigact = newact;
540 remove_thr_signals(
541 &_thr_sigact[sig-1].sigact.sa_mask);
542 newact.sa_flags &= ~SA_NODEFER;
543 newact.sa_flags |= SA_SIGINFO;
544 newact.sa_sigaction = thr_sighandler;
545 newact.sa_mask = _thr_maskset; /* mask all signals */
546 }
547 if ((ret = __sys_sigaction(sig, &newact, &oldact))) {
548 err = errno;
549 _thr_sigact[sig-1].sigact = oldact2;
550 }
551 } else if (oact != NULL) {
552 ret = __sys_sigaction(sig, NULL, &oldact);
553 err = errno;
554 }
555
556 if (oldact.sa_handler != SIG_DFL &&
557 oldact.sa_handler != SIG_IGN) {
558 oldact = _thr_sigact[sig-1].sigact;
559 }
560
561 _thr_rwl_unlock(&_thr_sigact[sig-1].lock);
562 __sys_sigprocmask(SIG_SETMASK, &oldset, NULL);
563
564 if (ret == 0) {
565 if (oact != NULL)
566 *oact = oldact;
567 } else {
568 errno = err;
569 }
570 return (ret);
261}
262
263__weak_reference(_sigprocmask, sigprocmask);
264
265int
266_sigprocmask(int how, const sigset_t *set, sigset_t *oset)
267{
268 const sigset_t *p = set;

--- 27 unchanged lines hidden (view full) ---

296 sigset_t newset;
297
298 return (__sys_sigsuspend(thr_remove_thr_signals(set, &newset)));
299}
300
301int
302__sigsuspend(const sigset_t * set)
303{
571}
572
573__weak_reference(_sigprocmask, sigprocmask);
574
575int
576_sigprocmask(int how, const sigset_t *set, sigset_t *oset)
577{
578 const sigset_t *p = set;

--- 27 unchanged lines hidden (view full) ---

606 sigset_t newset;
607
608 return (__sys_sigsuspend(thr_remove_thr_signals(set, &newset)));
609}
610
611int
612__sigsuspend(const sigset_t * set)
613{
304 struct pthread *curthread = _get_curthread();
614 struct pthread *curthread;
305 sigset_t newset;
615 sigset_t newset;
306 int ret;
616 int ret, old;
307
617
618 curthread = _get_curthread();
619
620 old = curthread->in_sigsuspend;
621 curthread->in_sigsuspend = 1;
308 _thr_cancel_enter(curthread);
309 ret = __sys_sigsuspend(thr_remove_thr_signals(set, &newset));
622 _thr_cancel_enter(curthread);
623 ret = __sys_sigsuspend(thr_remove_thr_signals(set, &newset));
310 _thr_cancel_leave(curthread);
624 _thr_cancel_leave(curthread, 1);
625 curthread->in_sigsuspend = old;
626 if (curthread->unblock_sigcancel) {
627 curthread->unblock_sigcancel = 0;
628 SIGEMPTYSET(newset);
629 SIGADDSET(newset, SIGCANCEL);
630 __sys_sigprocmask(SIG_UNBLOCK, &newset, NULL);
631 }
311
312 return (ret);
313}
314
315__weak_reference(__sigwait, sigwait);
316__weak_reference(__sigtimedwait, sigtimedwait);
317__weak_reference(__sigwaitinfo, sigwaitinfo);
318

--- 15 unchanged lines hidden (view full) ---

334int
335__sigtimedwait(const sigset_t *set, siginfo_t *info,
336 const struct timespec * timeout)
337{
338 struct pthread *curthread = _get_curthread();
339 sigset_t newset;
340 int ret;
341
632
633 return (ret);
634}
635
636__weak_reference(__sigwait, sigwait);
637__weak_reference(__sigtimedwait, sigtimedwait);
638__weak_reference(__sigwaitinfo, sigwaitinfo);
639

--- 15 unchanged lines hidden (view full) ---

655int
656__sigtimedwait(const sigset_t *set, siginfo_t *info,
657 const struct timespec * timeout)
658{
659 struct pthread *curthread = _get_curthread();
660 sigset_t newset;
661 int ret;
662
342 _thr_cancel_enter_defer(curthread, 1);
663 _thr_cancel_enter(curthread);
343 ret = __sys_sigtimedwait(thr_remove_thr_signals(set, &newset), info,
344 timeout);
664 ret = __sys_sigtimedwait(thr_remove_thr_signals(set, &newset), info,
665 timeout);
345 _thr_cancel_leave_defer(curthread, (ret == -1));
666 _thr_cancel_leave(curthread, (ret == -1));
346 return (ret);
347}
348
349int
350_sigwaitinfo(const sigset_t *set, siginfo_t *info)
351{
352 sigset_t newset;
353

--- 7 unchanged lines hidden (view full) ---

361 */
362int
363__sigwaitinfo(const sigset_t *set, siginfo_t *info)
364{
365 struct pthread *curthread = _get_curthread();
366 sigset_t newset;
367 int ret;
368
667 return (ret);
668}
669
670int
671_sigwaitinfo(const sigset_t *set, siginfo_t *info)
672{
673 sigset_t newset;
674

--- 7 unchanged lines hidden (view full) ---

682 */
683int
684__sigwaitinfo(const sigset_t *set, siginfo_t *info)
685{
686 struct pthread *curthread = _get_curthread();
687 sigset_t newset;
688 int ret;
689
369 _thr_cancel_enter_defer(curthread, 1);
690 _thr_cancel_enter(curthread);
370 ret = __sys_sigwaitinfo(thr_remove_thr_signals(set, &newset), info);
691 ret = __sys_sigwaitinfo(thr_remove_thr_signals(set, &newset), info);
371 _thr_cancel_leave_defer(curthread, ret == -1);
692 _thr_cancel_leave(curthread, ret == -1);
372 return (ret);
373}
374
375int
376_sigwait(const sigset_t *set, int *sig)
377{
378 sigset_t newset;
379

--- 7 unchanged lines hidden (view full) ---

387 */
388int
389__sigwait(const sigset_t *set, int *sig)
390{
391 struct pthread *curthread = _get_curthread();
392 sigset_t newset;
393 int ret;
394
693 return (ret);
694}
695
696int
697_sigwait(const sigset_t *set, int *sig)
698{
699 sigset_t newset;
700

--- 7 unchanged lines hidden (view full) ---

708 */
709int
710__sigwait(const sigset_t *set, int *sig)
711{
712 struct pthread *curthread = _get_curthread();
713 sigset_t newset;
714 int ret;
715
395 _thr_cancel_enter_defer(curthread, 1);
716 _thr_cancel_enter(curthread);
396 ret = __sys_sigwait(thr_remove_thr_signals(set, &newset), sig);
717 ret = __sys_sigwait(thr_remove_thr_signals(set, &newset), sig);
397 _thr_cancel_leave_defer(curthread, (ret != 0));
718 _thr_cancel_leave(curthread, (ret != 0));
398 return (ret);
399}
400
401__weak_reference(_setcontext, setcontext);
402int
403_setcontext(const ucontext_t *ucp)
404{
405 ucontext_t uc;
406
719 return (ret);
720}
721
722__weak_reference(_setcontext, setcontext);
723int
724_setcontext(const ucontext_t *ucp)
725{
726 ucontext_t uc;
727
407 (void) memcpy(&uc, ucp, sizeof (uc));
728 (void) memcpy(&uc, ucp, sizeof(uc));
408 remove_thr_signals(&uc.uc_sigmask);
729 remove_thr_signals(&uc.uc_sigmask);
409
410 return __sys_setcontext(&uc);
411}
412
413__weak_reference(_swapcontext, swapcontext);
414int
415_swapcontext(ucontext_t *oucp, const ucontext_t *ucp)
416{
417 ucontext_t uc;
418
730 return __sys_setcontext(&uc);
731}
732
733__weak_reference(_swapcontext, swapcontext);
734int
735_swapcontext(ucontext_t *oucp, const ucontext_t *ucp)
736{
737 ucontext_t uc;
738
419 (void) memcpy(&uc, ucp, sizeof (uc));
739 (void) memcpy(&uc, ucp, sizeof(uc));
420 remove_thr_signals(&uc.uc_sigmask);
421 return __sys_swapcontext(oucp, &uc);
422}
740 remove_thr_signals(&uc.uc_sigmask);
741 return __sys_swapcontext(oucp, &uc);
742}