Add wrapper for setcontext() and swapcontext(), the wrappers

unblock SIGCANCEL which is needed by thread cancellation.
This commit is contained in:
David Xu 2010-08-24 09:57:06 +00:00
parent 3586381d50
commit 5cf2219535
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=211737
3 changed files with 55 additions and 14 deletions

View File

@ -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;
};

View File

@ -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);

View File

@ -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);
}