xref: /freebsd/lib/libthr/thread/thr_sig.c (revision 5cf22195352544e71d37658bf716f0f4c8570600)
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);
62*5cf22195SDavid Xu int	_setcontext(const ucontext_t *);
63*5cf22195SDavid Xu int	_swapcontext(ucontext_t *, const ucontext_t *);
6437a6356bSDavid Xu 
65*5cf22195SDavid Xu static void
66*5cf22195SDavid Xu remove_thr_signals(sigset_t *set)
67*5cf22195SDavid Xu {
68*5cf22195SDavid Xu 	if (SIGISMEMBER(*set, SIGCANCEL))
69*5cf22195SDavid Xu 		SIGDELSET(*set, SIGCANCEL);
70*5cf22195SDavid Xu }
71*5cf22195SDavid Xu 
72*5cf22195SDavid Xu static const sigset_t *
73*5cf22195SDavid Xu thr_remove_thr_signals(const sigset_t *set, sigset_t *newset)
74*5cf22195SDavid Xu {
75*5cf22195SDavid Xu 	const sigset_t *pset;
76*5cf22195SDavid Xu 
77*5cf22195SDavid Xu 	if (SIGISMEMBER(*set, SIGCANCEL)) {
78*5cf22195SDavid Xu 		*newset = *set;
79*5cf22195SDavid Xu 		SIGDELSET(*newset, SIGCANCEL);
80*5cf22195SDavid Xu 		pset = newset;
81*5cf22195SDavid Xu 	} else
82*5cf22195SDavid Xu 		pset = set;
83*5cf22195SDavid Xu 	return (pset);
84*5cf22195SDavid Xu }
856fdfcacbSDavid Xu 
86a091d823SDavid Xu static void
8737a6356bSDavid Xu sigcancel_handler(int sig __unused,
8837a6356bSDavid Xu 	siginfo_t *info __unused, ucontext_t *ucp __unused)
89a091d823SDavid Xu {
90a091d823SDavid Xu 	struct pthread *curthread = _get_curthread();
91a091d823SDavid Xu 
921cb51125SDavid Xu 	curthread->in_sigcancel_handler++;
93bc414752SDavid Xu 	_thr_ast(curthread);
941cb51125SDavid Xu 	curthread->in_sigcancel_handler--;
95bc414752SDavid Xu }
96bc414752SDavid Xu 
97bc414752SDavid Xu void
98bc414752SDavid Xu _thr_ast(struct pthread *curthread)
99bc414752SDavid Xu {
100635f917aSDavid Xu 
101635f917aSDavid Xu 	if (THR_IN_CRITICAL(curthread))
102635f917aSDavid Xu 		return;
103635f917aSDavid Xu 
104635f917aSDavid Xu 	if (curthread->cancel_pending && curthread->cancel_enable
105635f917aSDavid Xu 		&& !curthread->cancelling) {
106635f917aSDavid Xu 		if (curthread->cancel_async) {
107635f917aSDavid Xu 			/*
108635f917aSDavid Xu 		 	 * asynchronous cancellation mode, act upon
109635f917aSDavid Xu 			 * immediately.
110635f917aSDavid Xu 		 	 */
111635f917aSDavid Xu 			_pthread_exit(PTHREAD_CANCELED);
112635f917aSDavid Xu 		} else {
113635f917aSDavid Xu 			/*
114635f917aSDavid Xu 		 	 * Otherwise, we are in defer mode, and we are at
115635f917aSDavid Xu 			 * cancel point, tell kernel to not block the current
116635f917aSDavid Xu 			 * thread on next cancelable system call.
117635f917aSDavid Xu 			 *
118635f917aSDavid Xu 			 * There are two cases we should call thr_wake() to
119635f917aSDavid Xu 			 * turn on TDP_WAKEUP in kernel:
120635f917aSDavid Xu 			 * 1) we are going to call a cancelable system call,
121635f917aSDavid Xu 			 *    non-zero cancel_point means we are already in
122635f917aSDavid Xu 			 *    cancelable state, next system call is cancelable.
123635f917aSDavid Xu 			 * 2) because _thr_ast() may be called by
124635f917aSDavid Xu 			 *    THR_CRITICAL_LEAVE() which is used by rtld rwlock
125635f917aSDavid Xu 			 *    and any libthr internal locks, when rtld rwlock
126635f917aSDavid Xu 			 *    is used, it is mostly caused my an unresolved PLT.
127635f917aSDavid Xu 			 *    those routines may clear the TDP_WAKEUP flag by
128635f917aSDavid Xu 			 *    invoking some system calls, in those cases, we
129635f917aSDavid Xu 			 *    also should reenable the flag.
130635f917aSDavid Xu 		 	 */
131635f917aSDavid Xu 			if (curthread->cancel_point) {
132635f917aSDavid Xu 				if (curthread->cancel_defer)
133635f917aSDavid Xu 					thr_wake(curthread->tid);
134635f917aSDavid Xu 				else
135635f917aSDavid Xu 					_pthread_exit(PTHREAD_CANCELED);
136635f917aSDavid Xu 			}
137635f917aSDavid Xu 		}
138635f917aSDavid Xu 	}
139635f917aSDavid Xu 
140bc414752SDavid Xu 	if (__predict_false((curthread->flags &
141bc414752SDavid Xu 	    (THR_FLAGS_NEED_SUSPEND | THR_FLAGS_SUSPENDED))
142bc414752SDavid Xu 		== THR_FLAGS_NEED_SUSPEND))
143a091d823SDavid Xu 		_thr_suspend_check(curthread);
144a091d823SDavid Xu }
145a091d823SDavid Xu 
146a091d823SDavid Xu void
147a091d823SDavid Xu _thr_suspend_check(struct pthread *curthread)
148a091d823SDavid Xu {
1498d6a11a0SDavid Xu 	uint32_t cycle;
150d448272dSDavid Xu 	int err;
151a091d823SDavid Xu 
1522ea1f90aSDavid Xu 	if (curthread->force_exit)
1532ea1f90aSDavid Xu 		return;
1542ea1f90aSDavid Xu 
155d448272dSDavid Xu 	err = errno;
156bc414752SDavid Xu 	/*
157bc414752SDavid Xu 	 * Blocks SIGCANCEL which other threads must send.
158bc414752SDavid Xu 	 */
159a091d823SDavid Xu 	_thr_signal_block(curthread);
160bc414752SDavid Xu 
161bc414752SDavid Xu 	/*
162bc414752SDavid Xu 	 * Increase critical_count, here we don't use THR_LOCK/UNLOCK
163bc414752SDavid Xu 	 * because we are leaf code, we don't want to recursively call
164bc414752SDavid Xu 	 * ourself.
165bc414752SDavid Xu 	 */
166bc414752SDavid Xu 	curthread->critical_count++;
167bddd24cdSDavid Xu 	THR_UMUTEX_LOCK(curthread, &(curthread)->lock);
168bc414752SDavid Xu 	while ((curthread->flags & (THR_FLAGS_NEED_SUSPEND |
169bc414752SDavid Xu 		THR_FLAGS_SUSPENDED)) == THR_FLAGS_NEED_SUSPEND) {
170bc414752SDavid Xu 		curthread->cycle++;
171a091d823SDavid Xu 		cycle = curthread->cycle;
172bc414752SDavid Xu 
173bc414752SDavid Xu 		/* Wake the thread suspending us. */
1748d6a11a0SDavid Xu 		_thr_umtx_wake(&curthread->cycle, INT_MAX, 0);
175bc414752SDavid Xu 
176bc414752SDavid Xu 		/*
177bc414752SDavid Xu 		 * if we are from pthread_exit, we don't want to
178bc414752SDavid Xu 		 * suspend, just go and die.
179bc414752SDavid Xu 		 */
180bc414752SDavid Xu 		if (curthread->state == PS_DEAD)
181bc414752SDavid Xu 			break;
182bc414752SDavid Xu 		curthread->flags |= THR_FLAGS_SUSPENDED;
183bddd24cdSDavid Xu 		THR_UMUTEX_UNLOCK(curthread, &(curthread)->lock);
1848d6a11a0SDavid Xu 		_thr_umtx_wait_uint(&curthread->cycle, cycle, NULL, 0);
185bddd24cdSDavid Xu 		THR_UMUTEX_LOCK(curthread, &(curthread)->lock);
186a091d823SDavid Xu 		curthread->flags &= ~THR_FLAGS_SUSPENDED;
187a091d823SDavid Xu 	}
188bddd24cdSDavid Xu 	THR_UMUTEX_UNLOCK(curthread, &(curthread)->lock);
189bc414752SDavid Xu 	curthread->critical_count--;
190bc414752SDavid Xu 
191bc414752SDavid Xu 	/*
192bc414752SDavid Xu 	 * Unblocks SIGCANCEL, it is possible a new SIGCANCEL is ready and
193bc414752SDavid Xu 	 * a new signal frame will nest us, this seems a problem because
194bc414752SDavid Xu 	 * stack will grow and overflow, but because kernel will automatically
195bc414752SDavid Xu 	 * mask the SIGCANCEL when delivering the signal, so we at most only
196bc414752SDavid Xu 	 * have one nesting signal frame, this should be fine.
197bc414752SDavid Xu 	 */
198a091d823SDavid Xu 	_thr_signal_unblock(curthread);
199d448272dSDavid Xu 	errno = err;
200a091d823SDavid Xu }
201a091d823SDavid Xu 
202a091d823SDavid Xu void
203a091d823SDavid Xu _thr_signal_init(void)
204a091d823SDavid Xu {
205a091d823SDavid Xu 	struct sigaction act;
206a091d823SDavid Xu 
207a091d823SDavid Xu 	/* Install cancel handler. */
208a091d823SDavid Xu 	SIGEMPTYSET(act.sa_mask);
209a091d823SDavid Xu 	act.sa_flags = SA_SIGINFO | SA_RESTART;
210a091d823SDavid Xu 	act.sa_sigaction = (__siginfohandler_t *)&sigcancel_handler;
211a091d823SDavid Xu 	__sys_sigaction(SIGCANCEL, &act, NULL);
212a091d823SDavid Xu }
213a091d823SDavid Xu 
214a091d823SDavid Xu void
215a091d823SDavid Xu _thr_signal_deinit(void)
216a091d823SDavid Xu {
217a091d823SDavid Xu }
218a091d823SDavid Xu 
21905c3a5eaSDavid Xu __weak_reference(___pause, pause);
22005c3a5eaSDavid Xu 
22105c3a5eaSDavid Xu int
22205c3a5eaSDavid Xu ___pause(void)
22305c3a5eaSDavid Xu {
22405c3a5eaSDavid Xu 	struct pthread *curthread = _get_curthread();
22505c3a5eaSDavid Xu 	int	ret;
22605c3a5eaSDavid Xu 
227f08e1bf6SDavid Xu 	_thr_cancel_enter(curthread);
22805c3a5eaSDavid Xu 	ret = __pause();
229f08e1bf6SDavid Xu 	_thr_cancel_leave(curthread);
23005c3a5eaSDavid Xu 
23105c3a5eaSDavid Xu 	return ret;
23205c3a5eaSDavid Xu }
23305c3a5eaSDavid Xu 
23405c3a5eaSDavid Xu __weak_reference(_raise, raise);
23505c3a5eaSDavid Xu 
23605c3a5eaSDavid Xu int
23705c3a5eaSDavid Xu _raise(int sig)
23805c3a5eaSDavid Xu {
23905c3a5eaSDavid Xu 	int ret;
24005c3a5eaSDavid Xu 
24105c3a5eaSDavid Xu 	if (!_thr_isthreaded())
24205c3a5eaSDavid Xu 		ret = kill(getpid(), sig);
24305c3a5eaSDavid Xu 	else
24405c3a5eaSDavid Xu 		ret = _thr_send_sig(_get_curthread(), sig);
24505c3a5eaSDavid Xu 	return (ret);
24605c3a5eaSDavid Xu }
24705c3a5eaSDavid Xu 
248a091d823SDavid Xu __weak_reference(_sigaction, sigaction);
249a091d823SDavid Xu 
250a091d823SDavid Xu int
251a091d823SDavid Xu _sigaction(int sig, const struct sigaction * act, struct sigaction * oact)
252a091d823SDavid Xu {
253a091d823SDavid Xu 	/* Check if the signal number is out of range: */
254b144e48bSKonstantin Belousov 	if (!_SIG_VALID(sig) || sig == SIGCANCEL) {
255a091d823SDavid Xu 		/* Return an invalid argument: */
256a091d823SDavid Xu 		errno = EINVAL;
257a091d823SDavid Xu 		return (-1);
258a091d823SDavid Xu 	}
259a091d823SDavid Xu 
260a091d823SDavid Xu 	return __sys_sigaction(sig, act, oact);
261a091d823SDavid Xu }
262a091d823SDavid Xu 
263a091d823SDavid Xu __weak_reference(_sigprocmask, sigprocmask);
264a091d823SDavid Xu 
265a091d823SDavid Xu int
266a091d823SDavid Xu _sigprocmask(int how, const sigset_t *set, sigset_t *oset)
267a091d823SDavid Xu {
268a091d823SDavid Xu 	const sigset_t *p = set;
269a091d823SDavid Xu 	sigset_t newset;
270a091d823SDavid Xu 
271a091d823SDavid Xu 	if (how != SIG_UNBLOCK) {
272a091d823SDavid Xu 		if (set != NULL) {
273a091d823SDavid Xu 			newset = *set;
274a091d823SDavid Xu 			SIGDELSET(newset, SIGCANCEL);
275a091d823SDavid Xu 			p = &newset;
276a091d823SDavid Xu 		}
277a091d823SDavid Xu 	}
278a091d823SDavid Xu 	return (__sys_sigprocmask(how, p, oset));
279a091d823SDavid Xu }
280a091d823SDavid Xu 
281bb535300SJeff Roberson __weak_reference(_pthread_sigmask, pthread_sigmask);
282bb535300SJeff Roberson 
283bb535300SJeff Roberson int
284bb535300SJeff Roberson _pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
285bb535300SJeff Roberson {
286a091d823SDavid Xu 	if (_sigprocmask(how, set, oset))
287a091d823SDavid Xu 		return (errno);
288a091d823SDavid Xu 	return (0);
289bb535300SJeff Roberson }
290bb535300SJeff Roberson 
29105c3a5eaSDavid Xu __weak_reference(__sigsuspend, sigsuspend);
292bb535300SJeff Roberson 
293bb535300SJeff Roberson int
294a091d823SDavid Xu _sigsuspend(const sigset_t * set)
295bb535300SJeff Roberson {
29605c3a5eaSDavid Xu 	sigset_t newset;
29705c3a5eaSDavid Xu 
29882746ea5SDavid Xu 	return (__sys_sigsuspend(thr_remove_thr_signals(set, &newset)));
29905c3a5eaSDavid Xu }
30005c3a5eaSDavid Xu 
30105c3a5eaSDavid Xu int
30205c3a5eaSDavid Xu __sigsuspend(const sigset_t * set)
30305c3a5eaSDavid Xu {
304a091d823SDavid Xu 	struct pthread *curthread = _get_curthread();
305a091d823SDavid Xu 	sigset_t newset;
306a091d823SDavid Xu 	int ret;
307bb535300SJeff Roberson 
308f08e1bf6SDavid Xu 	_thr_cancel_enter(curthread);
30982746ea5SDavid Xu 	ret = __sys_sigsuspend(thr_remove_thr_signals(set, &newset));
310f08e1bf6SDavid Xu 	_thr_cancel_leave(curthread);
3110ad70ba9SMike Makonnen 
312a091d823SDavid Xu 	return (ret);
313a091d823SDavid Xu }
314a091d823SDavid Xu 
315a091d823SDavid Xu __weak_reference(__sigwait, sigwait);
316a091d823SDavid Xu __weak_reference(__sigtimedwait, sigtimedwait);
317a091d823SDavid Xu __weak_reference(__sigwaitinfo, sigwaitinfo);
318a091d823SDavid Xu 
319a091d823SDavid Xu int
32005c3a5eaSDavid Xu _sigtimedwait(const sigset_t *set, siginfo_t *info,
32105c3a5eaSDavid Xu 	const struct timespec * timeout)
32205c3a5eaSDavid Xu {
32305c3a5eaSDavid Xu 	sigset_t newset;
32405c3a5eaSDavid Xu 
32582746ea5SDavid Xu 	return (__sys_sigtimedwait(thr_remove_thr_signals(set, &newset), info,
32682746ea5SDavid Xu 	    timeout));
32705c3a5eaSDavid Xu }
32805c3a5eaSDavid Xu 
329635f917aSDavid Xu /*
330635f917aSDavid Xu  * Cancellation behavior:
331635f917aSDavid Xu  *   Thread may be canceled at start, if thread got signal,
332635f917aSDavid Xu  *   it is not canceled.
333635f917aSDavid Xu  */
33405c3a5eaSDavid Xu int
335a091d823SDavid Xu __sigtimedwait(const sigset_t *set, siginfo_t *info,
336a091d823SDavid Xu 	const struct timespec * timeout)
337a091d823SDavid Xu {
338a091d823SDavid Xu 	struct pthread	*curthread = _get_curthread();
339a091d823SDavid Xu 	sigset_t newset;
340a091d823SDavid Xu 	int ret;
341a091d823SDavid Xu 
342635f917aSDavid Xu 	_thr_cancel_enter_defer(curthread, 1);
34382746ea5SDavid Xu 	ret = __sys_sigtimedwait(thr_remove_thr_signals(set, &newset), info,
34482746ea5SDavid Xu 	    timeout);
345635f917aSDavid Xu 	_thr_cancel_leave_defer(curthread, (ret == -1));
346a091d823SDavid Xu 	return (ret);
347a091d823SDavid Xu }
348a091d823SDavid Xu 
349a091d823SDavid Xu int
35005c3a5eaSDavid Xu _sigwaitinfo(const sigset_t *set, siginfo_t *info)
35105c3a5eaSDavid Xu {
35205c3a5eaSDavid Xu 	sigset_t newset;
35305c3a5eaSDavid Xu 
35482746ea5SDavid Xu 	return (__sys_sigwaitinfo(thr_remove_thr_signals(set, &newset), info));
35505c3a5eaSDavid Xu }
35605c3a5eaSDavid Xu 
357635f917aSDavid Xu /*
358635f917aSDavid Xu  * Cancellation behavior:
359635f917aSDavid Xu  *   Thread may be canceled at start, if thread got signal,
360635f917aSDavid Xu  *   it is not canceled.
361635f917aSDavid Xu  */
36205c3a5eaSDavid Xu int
363a091d823SDavid Xu __sigwaitinfo(const sigset_t *set, siginfo_t *info)
364a091d823SDavid Xu {
365a091d823SDavid Xu 	struct pthread	*curthread = _get_curthread();
366a091d823SDavid Xu 	sigset_t newset;
367a091d823SDavid Xu 	int ret;
368a091d823SDavid Xu 
369635f917aSDavid Xu 	_thr_cancel_enter_defer(curthread, 1);
37082746ea5SDavid Xu 	ret = __sys_sigwaitinfo(thr_remove_thr_signals(set, &newset), info);
371635f917aSDavid Xu 	_thr_cancel_leave_defer(curthread, ret == -1);
372a091d823SDavid Xu 	return (ret);
373a091d823SDavid Xu }
374a091d823SDavid Xu 
375a091d823SDavid Xu int
37605c3a5eaSDavid Xu _sigwait(const sigset_t *set, int *sig)
37705c3a5eaSDavid Xu {
37805c3a5eaSDavid Xu 	sigset_t newset;
37905c3a5eaSDavid Xu 
38082746ea5SDavid Xu 	return (__sys_sigwait(thr_remove_thr_signals(set, &newset), sig));
38105c3a5eaSDavid Xu }
38205c3a5eaSDavid Xu 
383635f917aSDavid Xu /*
384635f917aSDavid Xu  * Cancellation behavior:
385635f917aSDavid Xu  *   Thread may be canceled at start, if thread got signal,
386635f917aSDavid Xu  *   it is not canceled.
387635f917aSDavid Xu  */
38805c3a5eaSDavid Xu int
389a091d823SDavid Xu __sigwait(const sigset_t *set, int *sig)
390a091d823SDavid Xu {
391a091d823SDavid Xu 	struct pthread	*curthread = _get_curthread();
392a091d823SDavid Xu 	sigset_t newset;
393a091d823SDavid Xu 	int ret;
394a091d823SDavid Xu 
395635f917aSDavid Xu 	_thr_cancel_enter_defer(curthread, 1);
39682746ea5SDavid Xu 	ret = __sys_sigwait(thr_remove_thr_signals(set, &newset), sig);
397635f917aSDavid Xu 	_thr_cancel_leave_defer(curthread, (ret != 0));
398a091d823SDavid Xu 	return (ret);
399bb535300SJeff Roberson }
400*5cf22195SDavid Xu 
401*5cf22195SDavid Xu __weak_reference(_setcontext, setcontext);
402*5cf22195SDavid Xu int
403*5cf22195SDavid Xu _setcontext(const ucontext_t *ucp)
404*5cf22195SDavid Xu {
405*5cf22195SDavid Xu 	ucontext_t uc;
406*5cf22195SDavid Xu 
407*5cf22195SDavid Xu 	(void) memcpy(&uc, ucp, sizeof (uc));
408*5cf22195SDavid Xu 	remove_thr_signals(&uc.uc_sigmask);
409*5cf22195SDavid Xu 
410*5cf22195SDavid Xu 	return __sys_setcontext(&uc);
411*5cf22195SDavid Xu }
412*5cf22195SDavid Xu 
413*5cf22195SDavid Xu __weak_reference(_swapcontext, swapcontext);
414*5cf22195SDavid Xu int
415*5cf22195SDavid Xu _swapcontext(ucontext_t *oucp, const ucontext_t *ucp)
416*5cf22195SDavid Xu {
417*5cf22195SDavid Xu 	ucontext_t uc;
418*5cf22195SDavid Xu 
419*5cf22195SDavid Xu 	(void) memcpy(&uc, ucp, sizeof (uc));
420*5cf22195SDavid Xu 	remove_thr_signals(&uc.uc_sigmask);
421*5cf22195SDavid Xu 	return __sys_swapcontext(oucp, &uc);
422*5cf22195SDavid Xu }
423