git: d738f66fab92 - main - umtx_op(2): add the CVWAIT_UMTX_TIME flag for the UMTX_OP_CV_WAIT_UC request
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 27 Jul 2026 16:17:52 UTC
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=d738f66fab9208ee3bccea5fed293d8ce3ee5ca3
commit d738f66fab9208ee3bccea5fed293d8ce3ee5ca3
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-07-25 22:30:37 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
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