summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/kern_thr.c11
-rw-r--r--sys/kern/kern_umtx.c15
-rw-r--r--sys/sys/proc.h1
-rw-r--r--sys/sys/umtx.h3
4 files changed, 25 insertions, 5 deletions
diff --git a/sys/kern/kern_thr.c b/sys/kern/kern_thr.c
index 29c7614..37e3df2 100644
--- a/sys/kern/kern_thr.c
+++ b/sys/kern/kern_thr.c
@@ -402,6 +402,12 @@ kern_thr_suspend(struct thread *td, struct timespec *tsp)
TIMESPEC_TO_TIMEVAL(&tv, tsp);
hz = tvtohz(&tv);
}
+
+ if (td->td_pflags & TDP_WAKEUP) {
+ td->td_pflags &= ~TDP_WAKEUP;
+ return (0);
+ }
+
PROC_LOCK(td->td_proc);
if ((td->td_flags & TDF_THRWAKEUP) == 0)
error = msleep((void *)td, &td->td_proc->p_mtx, PCATCH, "lthr",
@@ -430,6 +436,11 @@ thr_wake(struct thread *td, struct thr_wake_args *uap)
struct proc *p;
struct thread *ttd;
+ if (uap->id == td->td_tid) {
+ td->td_pflags |= TDP_WAKEUP;
+ return (0);
+ }
+
p = td->td_proc;
PROC_LOCK(p);
ttd = thread_find(p, uap->id);
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[] = {
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 454982a..99dbfc6 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -455,6 +455,7 @@ struct thread {
#define TDP_GEOM 0x00010000 /* Settle GEOM before finishing syscall */
#define TDP_SOFTDEP 0x00020000 /* Stuck processing softdep worklist */
#define TDP_NORUNNINGBUF 0x00040000 /* Ignore runningbufspace check */
+#define TDP_WAKEUP 0x00080000 /* Don't sleep in umtx cond_wait */
/*
* Reasons that the current thread can not be run yet.
diff --git a/sys/sys/umtx.h b/sys/sys/umtx.h
index cfcf740..e7e534a 100644
--- a/sys/sys/umtx.h
+++ b/sys/sys/umtx.h
@@ -80,6 +80,9 @@ struct ucond {
#define UMTX_OP_CV_BROADCAST 10
#define UMTX_OP_MAX 11
+/* flags for UMTX_OP_CV_WAIT */
+#define UMTX_CHECK_UNPARKING 0x01
+
#ifndef _KERNEL
int _umtx_op(void *obj, int op, u_long val, void *uaddr, void *uaddr2);
OpenPOWER on IntegriCloud