git: d738f66fab92 - main - umtx_op(2): add the CVWAIT_UMTX_TIME flag for the UMTX_OP_CV_WAIT_UC request

Konstantin Belousov <[email protected]>
Newsgroups gmane.os.freebsd.devel.cvs.src
Message-ID <6a6784b0.1be71.61251996__49010.372131464$1785169124$gmane$org@gitrepo.freebsd.org>
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=d738f66fab9208ee3bccea5fed293d8ce3ee5ca3

commit d738f66fab9208ee3bccea5fed293d8ce3ee5ca3
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2026-07-25 22:30:37 +0000
Commit:     Konstantin Belousov <[email protected]>
CommitDate: 2026-07-27 16:17:28 +0000

    umtx_op(2): add the CVWAIT_UMTX_TIME flag for the UMTX_OP_CV_WAIT_UC request
    
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D58463
---
 sys/kern/kern_umtx.c | 90 ++++++++++++++++++++++++++++++++--------------------
 sys/sys/umtx.h       |  1 +
 2 files changed, 56 insertions(+), 35 deletions(-)

diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c
index d9798fb2adb6..ab6e578ab380 100644
--- a/sys/kern/kern_umtx.c
+++ b/sys/kern/kern_umtx.c
@@ -2934,11 +2934,10 @@ do_unlock_umutex(struct thread *td, struct umutex *m, bool rb)
 
 static int
 do_cv_wait(struct thread *td, struct ucond *cv, struct umutex *m,
-    struct timespec *timeout, u_long wflags)
+    struct umtx_abs_timeout *timo, u_long wflags)
 {
-	struct umtx_abs_timeout timo;
 	struct umtx_q *uq;
-	uint32_t flags, clockid, hasw;
+	uint32_t flags, hasw;
 	int error;
 
 	uq = td->td_umtxq;
@@ -2949,23 +2948,6 @@ do_cv_wait(struct thread *td, struct ucond *cv, struct umutex *m,
 	if (error != 0)
 		return (error);
 
-	if ((wflags & CVWAIT_CLOCKID) != 0) {
-		error = fueword32(&cv->c_clockid, &clockid);
-		if (error == -1) {
-			umtx_key_release(&uq->uq_key);
-			return (EFAULT);
-		}
-		if ((clockid < CLOCK_REALTIME ||
-		    clockid >= CLOCK_THREAD_CPUTIME_ID) &&
-		    clockid != CLOCK_TAI) {
-			/* hmm, only HW clock id will work. */
-			umtx_key_release(&uq->uq_key);
-			return (EINVAL);
-		}
-	} else {
-		clockid = CLOCK_REALTIME;
-	}
-
 	umtxq_lock(&uq->uq_key);
 	umtxq_busy(&uq->uq_key);
 	umtxq_insert(uq);
@@ -2990,15 +2972,9 @@ do_cv_wait(struct thread *td, struct ucond *cv, struct umutex *m,
 
 	error = do_unlock_umutex(td, m, false);
 
-	if (timeout != NULL)
-		umtx_abs_timeout_init(&timo, clockid,
-		    (wflags & CVWAIT_ABSTIME) != 0, timeout);
-
 	umtxq_lock(&uq->uq_key);
-	if (error == 0) {
-		error = umtxq_sleep(uq, "ucond", timeout == NULL ?
-		    NULL : &timo);
-	}
+	if (error == 0)
+		error = umtxq_sleep(uq, "ucond", timo);
 
 	if ((uq->uq_flags & UQF_UMTXQ) == 0)
 		error = 0;
@@ -4138,19 +4114,63 @@ static int
 __umtx_op_cv_wait(struct thread *td, struct _umtx_op_args *uap,
     const struct umtx_copyops *ops)
 {
+	struct umtx_abs_timeout *timop, timo;
 	struct timespec *ts, timeout;
+	struct _umtx_time umtime;
+	struct ucond *cv;
+	u_long wflags;
+	uint32_t clockid;
 	int error;
 
-	/* Allow a null timespec (wait forever). */
-	if (uap->uaddr2 == NULL)
-		ts = NULL;
-	else {
-		error = ops->copyin_timeout(uap->uaddr2, &timeout);
+	cv = uap->obj;
+	wflags = uap->val;
+	if ((wflags & ~(CVWAIT_CHECK_UNPARKING | CVWAIT_ABSTIME |
+	    CVWAIT_CLOCKID | CVWAIT_UMTX_TIME)) != 0 ||
+	    ((wflags & (CVWAIT_ABSTIME | CVWAIT_CLOCKID)) != 0 &&
+	    (wflags & CVWAIT_UMTX_TIME) != 0))
+		return (EINVAL);
+
+	if ((wflags & CVWAIT_UMTX_TIME) == 0) {
+		/* Allow a null timespec (wait forever). */
+		if (uap->uaddr2 == NULL) {
+			ts = NULL;
+		} else {
+			error = ops->copyin_timeout(uap->uaddr2, &timeout);
+			if (error != 0)
+				return (error);
+			ts = &timeout;
+		}
+		if ((wflags & CVWAIT_CLOCKID) != 0) {
+			error = fueword32(&cv->c_clockid, &clockid);
+			if (error == -1)
+				return (EFAULT);
+		} else {
+			clockid = CLOCK_REALTIME;
+		}
+		if (ts != NULL) {
+			umtx_abs_timeout_init(&timo, clockid,
+			    (wflags & CVWAIT_ABSTIME) != 0, ts);
+			timop = &timo;
+		} else {
+			timop = NULL;
+		}
+	} else {
+		if (uap->uaddr2 == NULL)
+			return (EINVAL);
+		error = ops->copyin_umtx_time(uap->uaddr2, ops->umtx_time_sz,
+		    &umtime);
 		if (error != 0)
 			return (error);
-		ts = &timeout;
+		timop = &timo;
+		umtx_abs_timeout_init2(timop, &umtime);
 	}
-	return (do_cv_wait(td, uap->obj, uap->uaddr1, ts, uap->val));
+	/* only HW clock id will work. */
+	if (timop != NULL && (timop->clockid < CLOCK_REALTIME ||
+	    timop->clockid >= CLOCK_THREAD_CPUTIME_ID) &&
+	    timop->clockid != CLOCK_TAI)
+		return (EINVAL);
+
+	return (do_cv_wait(td, cv, uap->uaddr1, timop, wflags));
 }
 
 static int
diff --git a/sys/sys/umtx.h b/sys/sys/umtx.h
index f7a69ae772c3..1cd9e2070977 100644
--- a/sys/sys/umtx.h
+++ b/sys/sys/umtx.h
@@ -115,6 +115,7 @@
 #define	CVWAIT_CHECK_UNPARKING	0x01
 #define	CVWAIT_ABSTIME		0x02
 #define	CVWAIT_CLOCKID		0x04
+#define	CVWAIT_UMTX_TIME	0x08
 
 #define	UMTX_ABSTIME		0x01
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.