aboutsummaryrefslogtreecommitdiff
path: root/lib/libthr
diff options
context:
space:
mode:
authorDavid Xu <davidxu@FreeBSD.org>2010-08-24 09:57:06 +0000
committerDavid Xu <davidxu@FreeBSD.org>2010-08-24 09:57:06 +0000
commit5cf22195352544e71d37658bf716f0f4c8570600 (patch)
treeff0cb0e2451250239015c5c3eb2814aacac94b03 /lib/libthr
parent3586381d50d246bdc86ca22712db4f0675fc6519 (diff)
downloadsrc-5cf22195352544e71d37658bf716f0f4c8570600.tar.gz
src-5cf22195352544e71d37658bf716f0f4c8570600.zip
Add wrapper for setcontext() and swapcontext(), the wrappers
unblock SIGCANCEL which is needed by thread cancellation.
Notes
Notes: svn path=/head/; revision=211737
Diffstat (limited to 'lib/libthr')
-rw-r--r--lib/libthr/pthread.map4
-rw-r--r--lib/libthr/thread/thr_private.h6
-rw-r--r--lib/libthr/thread/thr_sig.c59
3 files changed, 55 insertions, 14 deletions
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 <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 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);
+}