summaryrefslogtreecommitdiffstats
path: root/lib/libthr/thread
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2010-09-21 06:47:04 +0000
committerdavidxu <davidxu@FreeBSD.org>2010-09-21 06:47:04 +0000
commit585e6320d26e15f5dff4229f1a26ce1e355a6c11 (patch)
tree760e6d7b8318698197d8b89fb444c785f39ea09c /lib/libthr/thread
parentdaa9ae80c8f7311a4f1186dcf7b9ca8293a17450 (diff)
downloadFreeBSD-src-585e6320d26e15f5dff4229f1a26ce1e355a6c11.zip
FreeBSD-src-585e6320d26e15f5dff4229f1a26ce1e355a6c11.tar.gz
If we are at cancellation point, always work as deferred mode despite
whether asynchronous mode is turned on or not, this always gives us a chance to decide whether thread should be canceled or not in cancellation points.
Diffstat (limited to 'lib/libthr/thread')
-rw-r--r--lib/libthr/thread/thr_sig.c66
1 files changed, 32 insertions, 34 deletions
diff --git a/lib/libthr/thread/thr_sig.c b/lib/libthr/thread/thr_sig.c
index a9b8d1c..a2c1e53 100644
--- a/lib/libthr/thread/thr_sig.c
+++ b/lib/libthr/thread/thr_sig.c
@@ -270,46 +270,44 @@ static void
check_cancel(struct pthread *curthread, ucontext_t *ucp)
{
- if (__predict_true(!curthread->cancel_pending || !curthread->cancel_enable ||
- curthread->no_cancel))
+ if (__predict_true(!curthread->cancel_pending ||
+ !curthread->cancel_enable || curthread->no_cancel))
return;
- if (curthread->cancel_async) {
+ /*
+ * Otherwise, we are in defer mode, and we are at
+ * cancel point, tell kernel to not block the current
+ * thread on next cancelable system call.
+ *
+ * There are three cases we should call thr_wake() to
+ * turn on TDP_WAKEUP or send SIGCANCEL in kernel:
+ * 1) we are going to call a cancelable system call,
+ * non-zero cancel_point means we are already in
+ * cancelable state, next system call is cancelable.
+ * 2) because _thr_ast() may be called by
+ * THR_CRITICAL_LEAVE() which is used by rtld rwlock
+ * and any libthr internal locks, when rtld rwlock
+ * is used, it is mostly caused my an unresolved PLT.
+ * those routines may clear the TDP_WAKEUP flag by
+ * invoking some system calls, in those cases, we
+ * also should reenable the flag.
+ * 3) thread is in sigsuspend(), and the syscall insists
+ * on getting a signal before it agrees to return.
+ */
+ if (curthread->cancel_point) {
+ if (curthread->in_sigsuspend && ucp) {
+ SIGADDSET(ucp->uc_sigmask, SIGCANCEL);
+ curthread->unblock_sigcancel = 1;
+ _thr_send_sig(curthread, SIGCANCEL);
+ } else
+ thr_wake(curthread->tid);
+ } else if (curthread->cancel_async) {
/*
- * asynchronous cancellation mode, act upon
+ * asynchronous cancellation mode, act upon
* immediately.
- */
+ */
_pthread_exit_mask(PTHREAD_CANCELED,
ucp? &ucp->uc_sigmask : NULL);
- } else {
- /*
- * Otherwise, we are in defer mode, and we are at
- * cancel point, tell kernel to not block the current
- * thread on next cancelable system call.
- *
- * There are three cases we should call thr_wake() to
- * turn on TDP_WAKEUP or send SIGCANCEL in kernel:
- * 1) we are going to call a cancelable system call,
- * non-zero cancel_point means we are already in
- * cancelable state, next system call is cancelable.
- * 2) because _thr_ast() may be called by
- * THR_CRITICAL_LEAVE() which is used by rtld rwlock
- * and any libthr internal locks, when rtld rwlock
- * is used, it is mostly caused my an unresolved PLT.
- * those routines may clear the TDP_WAKEUP flag by
- * invoking some system calls, in those cases, we
- * also should reenable the flag.
- * 3) thread is in sigsuspend(), and the syscall insists
- * on getting a signal before it agrees to return.
- */
- if (curthread->cancel_point) {
- if (curthread->in_sigsuspend && ucp) {
- SIGADDSET(ucp->uc_sigmask, SIGCANCEL);
- curthread->unblock_sigcancel = 1;
- _thr_send_sig(curthread, SIGCANCEL);
- } else
- thr_wake(curthread->tid);
- }
}
}
OpenPOWER on IntegriCloud