From nobody Mon Aug 3 00:25:33 2026 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hCyBQ3kxkz6mjKq for ; Mon, 03 Aug 2026 00:25:34 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hCyBQ1RNRz4PL0 for ; Mon, 03 Aug 2026 00:25:34 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1785716734; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=wPktiNDVgKhwMD/gcFt3TK92q+6PkMDXhQmzu8O5kgs=; b=eJxnGsMmSxNQa8/KvB6wUhLozfSkA97fwteF9UwMwiahfcRoiyaNpEPk6Mw99uTaRnMW2W xT1BAlBNW2asVsEVAPBoqjJKkgqzKMrMaL4NL5K3RRQe6pKugJEpk8V9Rr/QJ2ewAaEq8k rerSHbdEunSKhGwaJVBXzlSrDG/y0i4rfkRKqMVE/30vZu7VPcOwFak3tUUJKgs2WfaxmF Hs4Eh/nR0rloSQEz3PpJ0ywC7DNIuPFYa82KXkoPvG1Pag+r6uzI+iX+eOiHsPx3UezdC2 PYGhKZmL79OJbOjtiuMLW8Cc3fsQxYTC+tn9i1A0cPpU8Hx/1BX0oxm0sRf30g== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1785716734; a=rsa-sha256; cv=none; b=np81H2FgSbuHcgFi5Rs38hhlncheQ1aaZG7cP5ZpmaEx3FJ0K2E1Pzh3CMHC1KAxKkTBlF sF1F1mOR9fc1BLvccj/2mBQb22iNLxB5VabSKyy2OhmDuNrNOB4cOngFR2hkZ8cKxJFfAT 9hpMxZitAx2g7o1ef1xI+WpSGsxUWyCOJBR97hMdZe5DXJYzdXVRCdiGNZVnNikk7U0XP9 xzSnvYPtU0QK2pxQVmyFSSXhic8K4RWAqOlwzgpASC9W+16DPKXO+oONuNEH7z2IG8YPdj IC+zVdrsZPxeGcvHK3IWvSe3PhR6OYXBh/6yu8cNpcCN/VGQfZ8kI4CFcxfDPA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1785716734; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=wPktiNDVgKhwMD/gcFt3TK92q+6PkMDXhQmzu8O5kgs=; b=eBJuOwOLlnvb5CsafSw1u2oSmikCDqvdbf9mlgOsqOCczvNxNqyBW+Llm/j/YiZLtVA9Pm g8h/0kAXhRh8+5q4fiqs6wAp4TnP7SIAFcUjUdMOJ9Ec8v/8kVhUEZNm4/DN4KVCoTHgBq pn1zCPgzA6CRUqk0Fa9sTCelB+m89n9Lar3CSiKWpxKG4tos7woMt7H3e06wok8QQgJaQ1 1oKSO/U/gTC4fYyXIoFEQWK7u/X6GOANYDuUhmzCA5N2R955vrPlrriVeCmzvyYjPLM7Ww 1vbBk8mmFC71BFbHZ7Ps+0fyBiLWMC8yqm8D7Ek++eh0WnfNF5WivEu+Si2iXg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hCyBP74mqzdQg for ; Mon, 03 Aug 2026 00:25:33 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 1ce90 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 03 Aug 2026 00:25:33 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Konstantin Belousov Subject: git: 4dcfa6d003e0 - stable/15 - libthr: implement pthread_cond_clockwait(3) List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kib X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: 4dcfa6d003e027be54d78ad14601170ae3a625f2 Auto-Submitted: auto-generated Date: Mon, 03 Aug 2026 00:25:33 +0000 Message-Id: <6a6fdffd.1ce90.7b841bcd@gitrepo.freebsd.org> The branch stable/15 has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=4dcfa6d003e027be54d78ad14601170ae3a625f2 commit 4dcfa6d003e027be54d78ad14601170ae3a625f2 Author: Konstantin Belousov AuthorDate: 2026-07-25 23:45:11 +0000 Commit: Konstantin Belousov CommitDate: 2026-08-03 00:23:16 +0000 libthr: implement pthread_cond_clockwait(3) (cherry picked from commit e1136fbcab184b8fb87456ca0d115d502bab6643) --- 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 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;