summaryrefslogtreecommitdiffstats
path: root/lib/libthr/thread
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2010-08-24 09:57:06 +0000
committerdavidxu <davidxu@FreeBSD.org>2010-08-24 09:57:06 +0000
commit14556ea4793fe097c15c7c0c773de11d1a17f153 (patch)
treeff0cb0e2451250239015c5c3eb2814aacac94b03 /lib/libthr/thread
parent284fdd96030832dd4e95f60282ea14b186a254a0 (diff)
downloadFreeBSD-src-14556ea4793fe097c15c7c0c773de11d1a17f153.zip
FreeBSD-src-14556ea4793fe097c15c7c0c773de11d1a17f153.tar.gz
Add wrapper for setcontext() and swapcontext(), the wrappers
unblock SIGCANCEL which is needed by thread cancellation.
Diffstat (limited to 'lib/libthr/thread')
-rw-r--r--lib/libthr/thread/thr_private.h6
-rw-r--r--lib/libthr/thread/thr_sig.c59
2 files changed, 51 insertions, 14 deletions
diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h
index f0c3aa0..c9e14c5 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 <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);
diff --git a/lib/libthr/thread/thr_sig.c b/lib/libthr/thread/thr_sig.c
index 115aa65..312c15f 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);
+}
OpenPOWER on IntegriCloud