diff --git a/lib/libthr/pthread.map b/lib/libthr/pthread.map index 8457996825b7..4eebb6254d46 100644 --- a/lib/libthr/pthread.map +++ b/lib/libthr/pthread.map @@ -342,6 +342,7 @@ FBSDprivate_1.0 { _pthread_timedjoin_np; _pthread_yield; _raise; + _setcontext; _sigaction; _sigprocmask; _sigsuspend; @@ -351,6 +352,7 @@ FBSDprivate_1.0 { _spinlock; _spinlock_debug; _spinunlock; + _swapcontext; /* Debugger needs these. */ _libthr_debug; @@ -397,4 +399,6 @@ FBSD_1.1 { FBSD_1.2 { openat; + setcontext; + swapcontext; }; diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h index f0c3aa0ec9a3..c9e14c523516 100644 --- a/lib/libthr/thread/thr_private.h +++ b/lib/libthr/thread/thr_private.h @@ -709,6 +709,12 @@ int __sys_sigwaitinfo(const sigset_t *set, siginfo_t *info); int __sys_nanosleep(const struct timespec *, struct timespec *); #endif +/* #include */ +#ifdef _SYS_UCONTEXT_H_ +int __sys_setcontext(const ucontext_t *ucp); +int __sys_swapcontext(ucontext_t *oucp, const ucontext_t *ucp); +#endif + /* #include */ #ifdef _UNISTD_H_ int __sys_close(int); diff --git a/lib/libthr/thread/thr_sig.c b/lib/libthr/thread/thr_sig.c index 115aa65a1ccf..312c15f4a3bf 100644 --- a/lib/libthr/thread/thr_sig.c +++ b/lib/libthr/thread/thr_sig.c @@ -59,7 +59,29 @@ int _sigwaitinfo(const sigset_t *set, siginfo_t *info); int __sigwait(const sigset_t *set, int *sig); int _sigwait(const sigset_t *set, int *sig); int __sigsuspend(const sigset_t *sigmask); +int _setcontext(const ucontext_t *); +int _swapcontext(ucontext_t *, const ucontext_t *); +static void +remove_thr_signals(sigset_t *set) +{ + if (SIGISMEMBER(*set, SIGCANCEL)) + SIGDELSET(*set, SIGCANCEL); +} + +static const sigset_t * +thr_remove_thr_signals(const sigset_t *set, sigset_t *newset) +{ + const sigset_t *pset; + + if (SIGISMEMBER(*set, SIGCANCEL)) { + *newset = *set; + SIGDELSET(*newset, SIGCANCEL); + pset = newset; + } else + pset = set; + return (pset); +} static void sigcancel_handler(int sig __unused, @@ -268,20 +290,6 @@ _pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) __weak_reference(__sigsuspend, sigsuspend); -static const sigset_t * -thr_remove_thr_signals(const sigset_t *set, sigset_t *newset) -{ - const sigset_t *pset; - - if (SIGISMEMBER(*set, SIGCANCEL)) { - *newset = *set; - SIGDELSET(*newset, SIGCANCEL); - pset = newset; - } else - pset = set; - return (pset); -} - int _sigsuspend(const sigset_t * set) { @@ -389,3 +397,26 @@ __sigwait(const sigset_t *set, int *sig) _thr_cancel_leave_defer(curthread, (ret != 0)); return (ret); } + +__weak_reference(_setcontext, setcontext); +int +_setcontext(const ucontext_t *ucp) +{ + ucontext_t uc; + + (void) memcpy(&uc, ucp, sizeof (uc)); + remove_thr_signals(&uc.uc_sigmask); + + return __sys_setcontext(&uc); +} + +__weak_reference(_swapcontext, swapcontext); +int +_swapcontext(ucontext_t *oucp, const ucontext_t *ucp) +{ + ucontext_t uc; + + (void) memcpy(&uc, ucp, sizeof (uc)); + remove_thr_signals(&uc.uc_sigmask); + return __sys_swapcontext(oucp, &uc); +}