Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F174857132
D58463.id182738.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
20 KB
Referenced Files
None
Subscribers
None
D58463.id182738.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D58463: libthr: implement pthread_cond_clockwait(3)
Attached
Detach File
Event Timeline
Log In to Comment