Page MenuHomeFreeBSD

D58463.id182738.diff
No OneTemporary

D58463.id182738.diff

diff --git a/contrib/netbsd-tests/lib/libpthread/t_condwait.c b/contrib/netbsd-tests/lib/libpthread/t_condwait.c
--- a/contrib/netbsd-tests/lib/libpthread/t_condwait.c
+++ b/contrib/netbsd-tests/lib/libpthread/t_condwait.c
@@ -47,25 +47,41 @@
static const int debug = 1;
+struct run_param {
+ clockid_t clck;
+ bool clockwait;
+ bool pshared;
+};
+
static void *
run(void *param)
{
struct timespec ts, to, te, twmin, twmax;
- clockid_t clck;
- pthread_condattr_t attr;
+ struct run_param *rp;
+ pthread_condattr_t cattr;
pthread_cond_t cond;
- pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+ pthread_mutexattr_t mattr;
+ pthread_mutex_t m;
int ret = 0;
+ rp = param;
- clck = *(clockid_t *)param;
- PTHREAD_REQUIRE(pthread_condattr_init(&attr));
- PTHREAD_REQUIRE(pthread_condattr_setclock(&attr, clck));
- pthread_cond_init(&cond, &attr);
+ PTHREAD_REQUIRE(pthread_condattr_init(&cattr));
+ PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr));
+ if (!rp->clockwait)
+ PTHREAD_REQUIRE(pthread_condattr_setclock(&cattr, rp->clck));
+ if (rp->pshared) {
+ PTHREAD_REQUIRE(pthread_condattr_setpshared(&cattr,
+ PTHREAD_PROCESS_SHARED));
+ PTHREAD_REQUIRE(pthread_mutexattr_setpshared(&mattr,
+ PTHREAD_PROCESS_SHARED));
+ }
+ pthread_mutex_init(&m, &mattr);
+ pthread_cond_init(&cond, &cattr);
ATF_REQUIRE_EQ((ret = pthread_mutex_lock(&m)), 0);
- ATF_REQUIRE_EQ(clock_gettime(clck, &ts), 0);
+ ATF_REQUIRE_EQ(clock_gettime(rp->clck, &ts), 0);
to = ts;
if (debug)
@@ -74,10 +90,14 @@
ts.tv_sec += WAITTIME; /* Timeout wait */
- switch (ret = pthread_cond_timedwait(&cond, &m, &ts)) {
+ if (rp->clockwait)
+ ret = pthread_cond_clockwait(&cond, &m, rp->clck, &ts);
+ else
+ ret = pthread_cond_timedwait(&cond, &m, &ts);
+ switch(ret) {
case ETIMEDOUT:
/* Timeout */
- ATF_REQUIRE_EQ(clock_gettime(clck, &te), 0);
+ ATF_REQUIRE_EQ(clock_gettime(rp->clck, &te), 0);
timespecsub(&te, &to, &to);
if (debug) {
printf("timeout: %lld.%09ld sec\n",
@@ -113,12 +133,18 @@
}
static void
-cond_wait(clockid_t clck, const char *msg) {
+cond_wait(clockid_t clck, bool clockwait, bool pshared, const char *msg)
+{
pthread_t child;
+ struct run_param rp;
+
+ rp.clck = clck;
+ rp.clockwait = clockwait;
+ rp.pshared = pshared;
if (debug)
printf( "**** %s clock wait starting\n", msg);
- ATF_REQUIRE_EQ(pthread_create(&child, NULL, run, &clck), 0);
+ ATF_REQUIRE_EQ(pthread_create(&child, NULL, run, &rp), 0);
ATF_REQUIRE_EQ(pthread_join(child, NULL), 0); /* wait for terminate */
if (debug)
printf( "**** %s clock wait ended\n", msg);
@@ -127,28 +153,76 @@
ATF_TC(cond_wait_real);
ATF_TC_HEAD(cond_wait_real, tc)
{
- atf_tc_set_md_var(tc, "descr", "Checks pthread_cond_timedwait "
- "with CLOCK_REALTIME");
+ atf_tc_set_md_var(tc, "descr",
+ "Checks pthread_cond_timedwait with CLOCK_REALTIME");
}
ATF_TC_BODY(cond_wait_real, tc) {
- cond_wait(CLOCK_REALTIME, "CLOCK_REALTIME");
+ cond_wait(CLOCK_REALTIME, false, false, "CLOCK_REALTIME");
}
ATF_TC(cond_wait_mono);
ATF_TC_HEAD(cond_wait_mono, tc)
{
- atf_tc_set_md_var(tc, "descr", "Checks pthread_cond_timedwait "
- "with CLOCK_MONOTONIC");
+ atf_tc_set_md_var(tc, "descr",
+ "Checks pthread_cond_timedwait with CLOCK_MONOTONIC");
}
ATF_TC_BODY(cond_wait_mono, tc) {
- cond_wait(CLOCK_MONOTONIC, "CLOCK_MONOTONIC");
+ cond_wait(CLOCK_MONOTONIC, false, false, "CLOCK_MONOTONIC");
+}
+
+ATF_TC(cond_clockwait_real);
+ATF_TC_HEAD(cond_clockwait_real, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Checks pthread_cond_clockwait with CLOCK_REALTIME");
+}
+
+ATF_TC_BODY(cond_clockwait_real, tc) {
+ cond_wait(CLOCK_REALTIME, true, false, "CLOCK_REALTIME");
+}
+
+ATF_TC(cond_clockwait_mono);
+ATF_TC_HEAD(cond_clockwait_mono, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Checks pthread_cond_clockwait with CLOCK_MONOTONIC");
+}
+
+ATF_TC_BODY(cond_clockwait_mono, tc) {
+ cond_wait(CLOCK_MONOTONIC, true, false, "CLOCK_MONOTONIC");
+}
+
+ATF_TC(cond_klockwait_real);
+ATF_TC_HEAD(cond_klockwait_real, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Checks pthread_cond_clockwait with CLOCK_REALTIME calling kernel");
+}
+
+ATF_TC_BODY(cond_klockwait_real, tc) {
+ cond_wait(CLOCK_REALTIME, true, true, "CLOCK_REALTIME");
+}
+
+ATF_TC(cond_klockwait_mono);
+ATF_TC_HEAD(cond_klockwait_mono, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Checks pthread_cond_clockwait with CLOCK_MONOTONIC calling kernel");
+}
+
+ATF_TC_BODY(cond_klockwait_mono, tc) {
+ cond_wait(CLOCK_MONOTONIC, true, true, "CLOCK_MONOTONIC");
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, cond_wait_real);
ATF_TP_ADD_TC(tp, cond_wait_mono);
+ ATF_TP_ADD_TC(tp, cond_clockwait_real);
+ ATF_TP_ADD_TC(tp, cond_clockwait_mono);
+ ATF_TP_ADD_TC(tp, cond_klockwait_real);
+ ATF_TP_ADD_TC(tp, cond_klockwait_mono);
return atf_no_error();
}
diff --git a/include/pthread.h b/include/pthread.h
--- a/include/pthread.h
+++ b/include/pthread.h
@@ -199,6 +199,11 @@
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/libsys/_umtx_op.2 b/lib/libsys/_umtx_op.2
--- a/lib/libsys/_umtx_op.2
+++ b/lib/libsys/_umtx_op.2
@@ -752,15 +752,21 @@
umutex is not relocked.
.Pp
The following flags are defined:
-.Bl -tag -width "CVWAIT_CLOCKID"
+.Bl -tag -width "CVWAIT_UMTX_TIME"
.It Dv CVWAIT_ABSTIME
Timeout is absolute.
.It Dv CVWAIT_CLOCKID
Clockid is provided.
+.It Dv CVWAIT_UMTX_TIME
+Timeout is specified by
+.Vt struct umtx_time
.El
.Pp
Optionally, a timeout for the request may be specified.
-Unlike other requests, the timeout value is specified directly by a
+If the
+.Dv CVWAIT_UMTX_TIME
+flag is not passed, then, unlike other requests,
+the timeout value is specified directly by a
.Vt struct timespec ,
pointed to by the
.Fa uaddr2
@@ -783,6 +789,19 @@
flag is supplied, the timeout specifies absolute time value, otherwise
it denotes a relative time interval.
.Pp
+Alternatively, if the
+.Dv CVWAIT_UMTX_TIME
+flag is passed, then the
+.Dv CVWAIT_CLOCKID
+and
+.Dv CVWAIT_ABSTIME
+flags must be not passed.
+In this case, the
+.Fa uaddr2
+points to the
+.Va struct umtx_time
+structure which specifes the timeout.
+.Pp
The request is not restartable.
An unblocked signal delivered during
the wait always results in sleep interruption and
diff --git a/lib/libthr/pthread.map b/lib/libthr/pthread.map
--- a/lib/libthr/pthread.map
+++ b/lib/libthr/pthread.map
@@ -344,5 +344,6 @@
};
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
--- a/lib/libthr/thread/thr_barrier.c
+++ b/lib/libthr/thread/thr_barrier.c
@@ -76,7 +76,8 @@
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 @@
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
--- a/lib/libthr/thread/thr_cond.c
+++ b/lib/libthr/thread/thr_cond.c
@@ -46,11 +46,14 @@
/*
* Prototypes
*/
-int __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
- const struct timespec * abstime);
+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, int 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(__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,11 +206,19 @@
*/
static int
cond_wait_kernel(struct pthread_cond *cvp, struct pthread_mutex *mp,
- const struct timespec *abstime, int cancel)
+ clockid_t clockid, const struct timespec *abstime, bool cancel,
+ bool clockwait)
{
struct pthread *curthread;
+ struct _umtx_time utime;
int error, error2, recurse, robust;
+ if (clockwait) {
+ utime._timeout = *abstime;
+ utime._flags = UMTX_ABSTIME;
+ utime._clockid = clockid;
+ }
+
curthread = _get_curthread();
robust = _mutex_enter_robust(curthread, mp);
@@ -219,8 +231,13 @@
if (cancel)
_thr_cancel_enter2(curthread, 0);
- error = _thr_ucond_wait(&cvp->kcond, &mp->m_lock, abstime,
- CVWAIT_ABSTIME | CVWAIT_CLOCKID);
+ if (clockwait) {
+ 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 +291,7 @@
static int
cond_wait_user(struct pthread_cond *cvp, struct pthread_mutex *mp,
- const struct timespec *abstime, int cancel)
+ clockid_t clockid, const struct timespec *abstime, bool cancel)
{
struct pthread *curthread;
struct sleepqueue *sq;
@@ -315,7 +332,7 @@
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,15 +367,19 @@
static int
cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex,
- const struct timespec *abstime, int cancel)
+ clockid_t clockid, const struct timespec *abstime, bool cancel,
+ bool clockwait)
{
struct pthread *curthread = _get_curthread();
struct pthread_cond *cvp;
struct pthread_mutex *mp;
- int error;
+ int error;
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,25 +393,25 @@
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, 0));
+ 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, 1));
+ return (cond_wait_common(cond, mutex, 0, NULL, true, false));
}
int
@@ -398,24 +419,34 @@
pthread_mutex_t * __restrict mutex,
const struct timespec * __restrict 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, 0));
+ 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, 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, abstime, 1));
+ return (cond_wait_common(cond, mutex, clockid, abstime, true, true));
}
static int
diff --git a/lib/libthr/thread/thr_umtx.h b/lib/libthr/thread/thr_umtx.h
--- a/lib/libthr/thread/thr_umtx.h
+++ b/lib/libthr/thread/thr_umtx.h
@@ -59,7 +59,8 @@
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;
diff --git a/lib/libthr/thread/thr_umtx.c b/lib/libthr/thread/thr_umtx.c
--- 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 @@
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;
+ const struct timespec *ts;
+ void *arg2;
- if (timeout && (timeout->tv_sec < 0 || (timeout->tv_sec == 0 &&
- timeout->tv_nsec <= 0))) {
+ 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/share/man/man3/Makefile b/share/man/man3/Makefile
--- a/share/man/man3/Makefile
+++ b/share/man/man3/Makefile
@@ -510,6 +510,7 @@
pthread_condattr.3 pthread_condattr_setclock.3 \
pthread_condattr.3 pthread_condattr_getpshared.3 \
pthread_condattr.3 pthread_condattr_setpshared.3
+PTHREAD_MLINKS+=pthread_cond_timedwait.3 pthread_cond_clockwait.3
PTHREAD_MLINKS+=pthread_getconcurrency.3 pthread_setconcurrency.3
PTHREAD_MLINKS+=pthread_multi_np.3 pthread_single_np.3
PTHREAD_MLINKS+=pthread_mutexattr.3 pthread_mutexattr_destroy.3 \
diff --git a/share/man/man3/pthread_cond_timedwait.3 b/share/man/man3/pthread_cond_timedwait.3
--- a/share/man/man3/pthread_cond_timedwait.3
+++ b/share/man/man3/pthread_cond_timedwait.3
@@ -36,7 +36,19 @@
.Sh SYNOPSIS
.In pthread.h
.Ft int
-.Fn pthread_cond_timedwait "pthread_cond_t *cond" "pthread_mutex_t *mutex" "const struct timespec *abstime"
+.Fo pthread_cond_timedwait
+.Fa "pthread_cond_t *cond"
+.Fa "pthread_mutex_t *mutex"
+.Fa "const struct timespec *abstime"
+.Fc
+.In time.h
+.Ft int
+.Fo pthread_cond_clockwait
+.Fa "pthread_cond_t *cond"
+.Fa "pthread_mutex_t *mutex"
+.Fa "clockid_t clockid"
+.Fa "const struct timespec *abstime"
+.Fc
.Sh DESCRIPTION
The
.Fn pthread_cond_timedwait
@@ -55,10 +67,17 @@
and the current thread reacquires the lock on
.Fa mutex .
.Pp
-The clock used to measure
+For the
+.Fn pthread_cond_timedwait
+function, the clock used to measure
.Fa abstime
can be specified during creation of the condition variable using
.Xr pthread_condattr_setclock 3 .
+For the
+.Fn pthread_cond_clockwait
+function, the clock is specified by the
+.Fa clockid
+argument.
.Sh RETURN VALUES
If successful, the
.Fn pthread_cond_timedwait
@@ -97,3 +116,9 @@
.Fn pthread_cond_timedwait
function conforms to
.St -p1003.1-96 .
+The
+.Fn pthread_cond_clockwait
+function conforms to
+.St -p1003.1-2024
+and appeared in
+.Fx 16.0 .
diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c
--- a/sys/kern/kern_umtx.c
+++ b/sys/kern/kern_umtx.c
@@ -2934,11 +2934,10 @@
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 @@
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 @@
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,65 @@
__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);
- if (error != 0)
- return (error);
- ts = &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) {
+ timop = NULL;
+ } else {
+ error = ops->copyin_umtx_time(uap->uaddr2,
+ ops->umtx_time_sz, &umtime);
+ if (error != 0)
+ return (error);
+ 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
--- 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

File Metadata

Mime Type
text/plain
Expires
Wed, Oct 7, 2:09 PM (7 h, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40352926
Default Alt Text
D58463.id182738.diff (20 KB)

Event Timeline