mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 21:05:08 +00:00
Add wrapper for setcontext() and swapcontext(), the wrappers
unblock SIGCANCEL which is needed by thread cancellation.
This commit is contained in:
parent
3586381d50
commit
5cf2219535
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=211737
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -709,6 +709,12 @@ int __sys_sigwaitinfo(const sigset_t *set, siginfo_t *info);
|
|||
int __sys_nanosleep(const struct timespec *, struct timespec *);
|
||||
#endif
|
||||
|
||||
/* #include <sys/ucontext.h> */
|
||||
#ifdef _SYS_UCONTEXT_H_
|
||||
int __sys_setcontext(const ucontext_t *ucp);
|
||||
int __sys_swapcontext(ucontext_t *oucp, const ucontext_t *ucp);
|
||||
#endif
|
||||
|
||||
/* #include <unistd.h> */
|
||||
#ifdef _UNISTD_H_
|
||||
int __sys_close(int);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue