summaryrefslogtreecommitdiff
path: root/pthread/pt-cancel.c
diff options
context:
space:
mode:
Diffstat (limited to 'pthread/pt-cancel.c')
-rw-r--r--pthread/pt-cancel.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/pthread/pt-cancel.c b/pthread/pt-cancel.c
index d19c557..96c77f7 100644
--- a/pthread/pt-cancel.c
+++ b/pthread/pt-cancel.c
@@ -31,10 +31,33 @@ pthread_cancel (pthread_t t)
if (! p)
return ESRCH;
+ __pthread_mutex_lock (&p->cancel_lock);
+ if (p->cancel_pending)
+ {
+ __pthread_mutex_unlock (&p->cancel_lock);
+ return 0;
+ }
+
p->cancel_pending = 1;
- if (p->cancel_state == PTHREAD_CANCEL_ENABLE
- && p->cancel_type == PTHREAD_CANCEL_ASYNCHRONOUS)
+
+ if (p->cancel_state != PTHREAD_CANCEL_ENABLE)
+ {
+ __pthread_mutex_unlock (&p->cancel_lock);
+ return 0;
+ }
+
+ if (p->cancel_type == PTHREAD_CANCEL_ASYNCHRONOUS)
+ /* CANCEL_LOCK is unlocked by this call. */
err = __pthread_do_cancel (p);
+ else
+ {
+ if (p->cancel_hook != NULL)
+ /* Thread blocking on a cancellation point. Invoke hook to unblock.
+ See __pthread_cond_timedwait_internal. */
+ p->cancel_hook (p->cancel_hook_arg);
+
+ __pthread_mutex_unlock (&p->cancel_lock);
+ }
return err;
}