summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_umtx.c
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2006-12-04 14:15:12 +0000
committerdavidxu <davidxu@FreeBSD.org>2006-12-04 14:15:12 +0000
commit22a81fc246efb2668eddcb6ccd27129feaa5910c (patch)
tree96b0dbfdbf6b0cc6b79bddb39c447b7346ae3471 /sys/kern/kern_umtx.c
parent1f83d70e044c52a4ed74fe1aae9685e70ead1409 (diff)
downloadFreeBSD-src-22a81fc246efb2668eddcb6ccd27129feaa5910c.zip
FreeBSD-src-22a81fc246efb2668eddcb6ccd27129feaa5910c.tar.gz
if a thread blocked on userland condition variable is
pthread_cancel()ed, it is expected that the thread will not consume a pthread_cond_signal(), therefor, we use thr_wake() to mark a flag, the flag tells a thread calling do_cv_wait() in umtx code to not block on a condition variable. Thread library is expected that once a thread detected itself is in pthread_cond_wait, it will call the thr_wake() for itself in its SIGCANCEL handler.
Diffstat (limited to 'sys/kern/kern_umtx.c')
-rw-r--r--sys/kern/kern_umtx.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c
index 89faec8..328fb57 100644
--- a/sys/kern/kern_umtx.c
+++ b/sys/kern/kern_umtx.c
@@ -2170,7 +2170,7 @@ do_unlock_umutex(struct thread *td, struct umutex *m)
static int
do_cv_wait(struct thread *td, struct ucond *cv, struct umutex *m,
- struct timespec *timeout)
+ struct timespec *timeout, u_long wflags)
{
struct umtx_q *uq;
struct timeval tv;
@@ -2202,7 +2202,11 @@ do_cv_wait(struct thread *td, struct ucond *cv, struct umutex *m,
umtxq_lock(&uq->uq_key);
if (error == 0) {
- if (timeout == NULL) {
+ if ((wflags & UMTX_CHECK_UNPARKING) &&
+ (td->td_pflags & TDP_WAKEUP)) {
+ td->td_pflags &= ~TDP_WAKEUP;
+ error = EINTR;
+ } else if (timeout == NULL) {
error = umtxq_sleep(uq, "ucond", 0);
} else {
getnanouptime(&ets);
@@ -2236,7 +2240,8 @@ do_cv_wait(struct thread *td, struct ucond *cv, struct umutex *m,
* occur, and indeed a kernel based implementation
* can not avoid it.
*/
- umtxq_signal(&uq->uq_key, 1);
+ if (!umtxq_signal(&uq->uq_key, 1))
+ error = 0;
}
if (error == ERESTART)
error = EINTR;
@@ -2431,7 +2436,7 @@ __umtx_op_cv_wait(struct thread *td, struct _umtx_op_args *uap)
}
ts = &timeout;
}
- return (do_cv_wait(td, uap->obj, uap->uaddr1, ts));
+ return (do_cv_wait(td, uap->obj, uap->uaddr1, ts, uap->val));
}
static int
@@ -2592,7 +2597,7 @@ __umtx_op_cv_wait_compat32(struct thread *td, struct _umtx_op_args *uap)
return (EINVAL);
ts = &timeout;
}
- return (do_cv_wait(td, uap->obj, uap->uaddr1, ts));
+ return (do_cv_wait(td, uap->obj, uap->uaddr1, ts, uap->val));
}
static _umtx_op_func op_table_compat32[] = {
OpenPOWER on IntegriCloud