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
 

Reply via email to