summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_sleepqueue.c
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2010-08-20 04:28:30 +0000
committerdavidxu <davidxu@FreeBSD.org>2010-08-20 04:28:30 +0000
commit89f466d2b24eb304fba1cca7584fbd61aa0a8c94 (patch)
tree6e87e70a75d2de5dd44cf0f94627cf1dcafa58e7 /sys/kern/subr_sleepqueue.c
parent07b66dcf06596326ea9d81d40d460bdef6f50b34 (diff)
downloadFreeBSD-src-89f466d2b24eb304fba1cca7584fbd61aa0a8c94.zip
FreeBSD-src-89f466d2b24eb304fba1cca7584fbd61aa0a8c94.tar.gz
If thread set a TDP_WAKEUP for itself, clears the flag and returns EINTR
immediately, this is used for implementing reliable pthread cancellation.
Diffstat (limited to 'sys/kern/subr_sleepqueue.c')
-rw-r--r--sys/kern/subr_sleepqueue.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/sys/kern/subr_sleepqueue.c b/sys/kern/subr_sleepqueue.c
index c51def6..0d2c65e 100644
--- a/sys/kern/subr_sleepqueue.c
+++ b/sys/kern/subr_sleepqueue.c
@@ -408,6 +408,12 @@ sleepq_catch_signals(void *wchan, int pri)
sc = SC_LOOKUP(wchan);
mtx_assert(&sc->sc_lock, MA_OWNED);
MPASS(wchan != NULL);
+ if ((td->td_pflags & TDP_WAKEUP) != 0) {
+ td->td_pflags &= ~TDP_WAKEUP;
+ ret = EINTR;
+ goto out;
+ }
+
/*
* See if there are any pending signals for this thread. If not
* we can switch immediately. Otherwise do the signal processing
@@ -453,6 +459,7 @@ sleepq_catch_signals(void *wchan, int pri)
sleepq_switch(wchan, pri);
return (0);
}
+out:
/*
* There were pending signals and this thread is still
* on the sleep queue, remove it from the sleep queue.
OpenPOWER on IntegriCloud