Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 27 Jul 2026 16:17:56 +0000
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: e1136fbcab18 - main - libthr: implement pthread_cond_clockwait(3)
Message-ID:  <6a6784b4.1e302.52074cf8@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by kib:

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

commit e1136fbcab184b8fb87456ca0d115d502bab6643
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-07-25 23:45:11 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-07-27 16:17:28 +0000

    libthr: implement pthread_cond_clockwait(3)
    
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D58463
---
 include/pthread.h               |  5 ++++
 lib/libthr/pthread.map          |  1 +
 lib/libthr/thread/thr_barrier.c |  6 ++--
 lib/libthr/thread/thr_cond.c    | 64 ++++++++++++++++++++++++++++++-----------
 lib/libthr/thread/thr_umtx.c    | 30 ++++++++++++++-----
 lib/libthr/thread/thr_umtx.h    |  3 +-
 6 files changed, 83 insertions(+), 26 deletions(-)

diff --git a/include/pthread.h b/include/pthread.h
index 311211cb48f1..1686b54314ef 100644
--- a/include/pthread.h
+++ b/include/pthread.h
@@ -199,6 +199,11 @@ int		pthread_condattr_init(pthread_condattr_t *);
 int		pthread_condattr_setclock(pthread_condattr_t *, clockid_t);
 int		pthread_condattr_setpshared(pthread_condattr_t *, int);
 int		pthread_cond_broadcast(pthread_cond_t *);
+#if __POSIX_VISIBLE >= 202405
+int		pthread_cond_clockwait(pthread_cond_t * __restrict,
+		    pthread_mutex_t * __restrict, clockid_t,
+		    const struct timespec * __restrict);
+#endif
 int		pthread_cond_destroy(pthread_cond_t *);
 int		pthread_cond_init(pthread_cond_t * __restrict,
 		    const pthread_condattr_t * __restrict);
diff --git a/lib/libthr/pthread.map b/lib/libthr/pthread.map
index ad0c28de98c1..4fe5f2c28331 100644
--- a/lib/libthr/pthread.map
+++ b/lib/libthr/pthread.map
@@ -344,5 +344,6 @@ FBSD_1.8 {
 };
 
 FBSD_1.9 {
+	 pthread_cond_clockwait;
 	 pthread_tryjoin_np;
 };
diff --git a/lib/libthr/thread/thr_barrier.c b/lib/libthr/thread/thr_barrier.c
index 13dec864e2f6..e15b1627ee5d 100644
--- a/lib/libthr/thread/thr_barrier.c
+++ b/lib/libthr/thread/thr_barrier.c
@@ -76,7 +76,8 @@ _pthread_barrier_destroy(pthread_barrier_t *barrier)
 			return (EBUSY);
 		}
 		if (bar->b_refcount != 0) {
-			_thr_ucond_wait(&bar->b_cv, &bar->b_lock, NULL, 0);
+			_thr_ucond_wait(&bar->b_cv, &bar->b_lock, NULL,
+			    NULL, 0);
 			THR_UMUTEX_LOCK(curthread, &bar->b_lock);
 		} else
 			break;
@@ -158,7 +159,8 @@ _pthread_barrier_wait(pthread_barrier_t *barrier)
 		cycle = bar->b_cycle;
 		bar->b_refcount++;
 		do {
-			_thr_ucond_wait(&bar->b_cv, &bar->b_lock, NULL, 0);
+			_thr_ucond_wait(&bar->b_cv, &bar->b_lock, NULL,
+			    NULL, 0);
 			THR_UMUTEX_LOCK(curthread, &bar->b_lock);
 			/* test cycle to avoid bogus wakeup */
 		} while (cycle == bar->b_cycle);
diff --git a/lib/libthr/thread/thr_cond.c b/lib/libthr/thread/thr_cond.c
index f8c9118968bb..cce2ba7b6c3c 100644
--- a/lib/libthr/thread/thr_cond.c
+++ b/lib/libthr/thread/thr_cond.c
@@ -46,11 +46,14 @@ _Static_assert(sizeof(struct pthread_cond) <= THR_PAGE_SIZE_MIN,
 /*
  * Prototypes
  */
+int __pthread_cond_clockwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
+    clockid_t clockid, const struct timespec *abstime);
 int __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
     const struct timespec * abstime);
 static int cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
 static int cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex,
-    const struct timespec *abstime, bool cancel);
+    clockid_t clockid, const struct timespec *abstime, bool cancel,
+    bool clockwait);
 static int cond_signal_common(pthread_cond_t *cond);
 static int cond_broadcast_common(pthread_cond_t *cond);
 
@@ -64,6 +67,7 @@ __weak_reference(__thr_cond_wait, __pthread_cond_wait);
 __weak_reference(_thr_cond_wait, _pthread_cond_wait);
 __weak_reference(__pthread_cond_timedwait, pthread_cond_timedwait);
 __weak_reference(_thr_cond_timedwait, _pthread_cond_timedwait);
+__weak_reference(__pthread_cond_clockwait, pthread_cond_clockwait);
 __weak_reference(_thr_cond_init, pthread_cond_init);
 __weak_reference(_thr_cond_init, _pthread_cond_init);
 __weak_reference(_thr_cond_destroy, pthread_cond_destroy);
@@ -202,9 +206,11 @@ _thr_cond_destroy(pthread_cond_t *cond)
  */
 static int
 cond_wait_kernel(struct pthread_cond *cvp, struct pthread_mutex *mp,
-    const struct timespec *abstime, bool cancel)
+    clockid_t clockid, const struct timespec *abstime, bool cancel,
+    bool clockwait)
 {
 	struct pthread *curthread;
+	struct _umtx_time utime;
 	int error, error2, recurse, robust;
 
 	curthread = _get_curthread();
@@ -219,8 +225,16 @@ cond_wait_kernel(struct pthread_cond *cvp, struct pthread_mutex *mp,
 
 	if (cancel)
 		_thr_cancel_enter2(curthread, 0);
-	error = _thr_ucond_wait(&cvp->kcond, &mp->m_lock, abstime,
-	    CVWAIT_ABSTIME | CVWAIT_CLOCKID);
+	if (clockwait) {
+		utime._timeout = *abstime;
+		utime._flags = UMTX_ABSTIME;
+		utime._clockid = clockid;
+		error = _thr_ucond_wait(&cvp->kcond, &mp->m_lock, NULL,
+		    &utime, CVWAIT_UMTX_TIME);
+	} else {
+		error = _thr_ucond_wait(&cvp->kcond, &mp->m_lock, abstime,
+		    NULL, CVWAIT_ABSTIME | CVWAIT_CLOCKID);
+	}
 	if (cancel)
 		_thr_cancel_leave(curthread, 0);
 
@@ -274,7 +288,7 @@ cond_wait_kernel(struct pthread_cond *cvp, struct pthread_mutex *mp,
 
 static int
 cond_wait_user(struct pthread_cond *cvp, struct pthread_mutex *mp,
-    const struct timespec *abstime, bool cancel)
+    clockid_t clockid, const struct timespec *abstime, bool cancel)
 {
 	struct pthread *curthread;
 	struct sleepqueue *sq;
@@ -315,7 +329,7 @@ cond_wait_user(struct pthread_cond *cvp, struct pthread_mutex *mp,
 
 		if (cancel)
 			_thr_cancel_enter2(curthread, 0);
-		error = _thr_sleep(curthread, cvp->kcond.c_clockid, abstime);
+		error = _thr_sleep(curthread, clockid, abstime);
 		if (cancel)
 			_thr_cancel_leave(curthread, 0);
 
@@ -350,7 +364,8 @@ cond_wait_user(struct pthread_cond *cvp, struct pthread_mutex *mp,
 
 static int
 cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex,
-    const struct timespec *abstime, bool cancel)
+    clockid_t clockid, const struct timespec *abstime, bool cancel,
+    bool clockwait)
 {
 	struct pthread	*curthread = _get_curthread();
 	struct pthread_cond *cvp;
@@ -359,6 +374,9 @@ cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex,
 
 	CHECK_AND_INIT_COND
 
+	if (!clockwait)
+		clockid = cvp->kcond.c_clockid;
+
 	if (*mutex == THR_PSHARED_PTR) {
 		mp = __thr_pshared_offpage(mutex, 0);
 		if (mp == NULL)
@@ -372,23 +390,25 @@ cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex,
 
 	if (curthread->attr.sched_policy != SCHED_OTHER ||
 	    (mp->m_lock.m_flags & (UMUTEX_PRIO_PROTECT | UMUTEX_PRIO_INHERIT |
-	    USYNC_PROCESS_SHARED)) != 0 || CV_PSHARED(cvp))
-		return (cond_wait_kernel(cvp, mp, abstime, cancel));
-	else
-		return (cond_wait_user(cvp, mp, abstime, cancel));
+	    USYNC_PROCESS_SHARED)) != 0 || CV_PSHARED(cvp)) {
+		return (cond_wait_kernel(cvp, mp, clockid, abstime, cancel,
+		    clockwait));
+	} else {
+		return (cond_wait_user(cvp, mp, clockid, abstime, cancel));
+	}
 }
 
 int
 _thr_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
 {
-	return (cond_wait_common(cond, mutex, NULL, false));
+	return (cond_wait_common(cond, mutex, 0, NULL, false, false));
 }
 
 int
 __thr_cond_wait(pthread_cond_t * __restrict cond,
     pthread_mutex_t * __restrict mutex)
 {
-	return (cond_wait_common(cond, mutex, NULL, true));
+	return (cond_wait_common(cond, mutex, 0, NULL, true, false));
 }
 
 int
@@ -400,18 +420,30 @@ _thr_cond_timedwait(pthread_cond_t * __restrict cond,
 	    abstime->tv_nsec >= 1000000000)
 		return (EINVAL);
 
-	return (cond_wait_common(cond, mutex, abstime, false));
+	return (cond_wait_common(cond, mutex, 0, abstime, false, false));
 }
 
 int
 __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
-		       const struct timespec *abstime)
+    const struct timespec *abstime)
 {
 	if (abstime == NULL || abstime->tv_sec < 0 || abstime->tv_nsec < 0 ||
 	    abstime->tv_nsec >= 1000000000)
 		return (EINVAL);
 
-	return (cond_wait_common(cond, mutex, abstime, true));
+	return (cond_wait_common(cond, mutex, 0, abstime, true, false));
+}
+
+int
+__pthread_cond_clockwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
+    clockid_t clockid, const struct timespec *abstime)
+{
+
+	if (abstime == NULL || abstime->tv_sec < 0 || abstime->tv_nsec < 0 ||
+	    abstime->tv_nsec >= 1000000000)
+		return (EINVAL);
+
+	return (cond_wait_common(cond, mutex, clockid, abstime, true, true));
 }
 
 static int
diff --git a/lib/libthr/thread/thr_umtx.c b/lib/libthr/thread/thr_umtx.c
index db63017a6a13..edd0dacdaff1 100644
--- a/lib/libthr/thread/thr_umtx.c
+++ b/lib/libthr/thread/thr_umtx.c
@@ -28,6 +28,7 @@
 
 #include "thr_private.h"
 #include "thr_umtx.h"
+#include <assert.h>
 
 void
 _thr_umutex_init(struct umutex *mtx)
@@ -242,20 +243,35 @@ _thr_ucond_init(struct ucond *cv)
 
 int
 _thr_ucond_wait(struct ucond *cv, struct umutex *m,
-    const struct timespec *timeout, int flags)
+    const struct timespec *timeout, const struct _umtx_time *utimep, int flags)
 {
 	struct pthread *curthread;
-
-	if (timeout != NULL && (timeout->tv_sec < 0 || (timeout->tv_sec == 0 &&
-	    timeout->tv_nsec <= 0))) {
+	const struct timespec *ts;
+	void *arg2;
+
+	assert(timeout == NULL || utimep == NULL);
+	if (timeout != NULL) {
+		ts = timeout;
+		arg2 = __DECONST(void *, timeout);
+		assert((flags & CVWAIT_UMTX_TIME) == 0);
+	} else if (utimep != NULL) {
+		ts = &utimep->_timeout;
+		arg2 = __DECONST(void *, utimep);
+		assert((flags & CVWAIT_UMTX_TIME) != 0);
+	} else {
+		ts = NULL;
+		arg2 = NULL;
+		assert((flags & CVWAIT_UMTX_TIME) == 0);
+	}
+	if (ts != NULL && (ts->tv_sec < 0 || (ts->tv_sec == 0 &&
+	    ts->tv_nsec <= 0))) {
 		curthread = _get_curthread();
 		_thr_umutex_unlock(m, TID(curthread));
                 return (ETIMEDOUT);
 	}
-	return (_umtx_op_err(cv, UMTX_OP_CV_WAIT, flags, m,
-	    __DECONST(void *, timeout)));
+	return (_umtx_op_err(cv, UMTX_OP_CV_WAIT, flags, m, arg2));
 }
- 
+
 int
 _thr_ucond_signal(struct ucond *cv)
 {
diff --git a/lib/libthr/thread/thr_umtx.h b/lib/libthr/thread/thr_umtx.h
index 89f70e4ab14f..4e1c08ca64e8 100644
--- a/lib/libthr/thread/thr_umtx.h
+++ b/lib/libthr/thread/thr_umtx.h
@@ -59,7 +59,8 @@ int _thr_umtx_timedwait_uint(volatile u_int *mtx, u_int exp, int clockid,
 	const struct timespec *timeout, int shared) __hidden;
 int _thr_umtx_wake(volatile void *mtx, int count, int shared) __hidden;
 int _thr_ucond_wait(struct ucond *cv, struct umutex *m,
-        const struct timespec *timeout, int flags) __hidden;
+        const struct timespec *timeout, const struct _umtx_time *utimep,
+	int flags) __hidden;
 void _thr_ucond_init(struct ucond *cv) __hidden;
 int _thr_ucond_signal(struct ucond *cv) __hidden;
 int _thr_ucond_broadcast(struct ucond *cv) __hidden;


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a6784b4.1e302.52074cf8>