Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F177257506
D61253.1794015845.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
39 KB
Referenced Files
None
Subscribers
None
D61253.1794015845.diff
View Options
diff --git a/include/pthread.h b/include/pthread.h
--- a/include/pthread.h
+++ b/include/pthread.h
@@ -235,6 +235,11 @@
const pthread_mutexattr_t * __restrict, int * __restrict);
int pthread_mutexattr_settype(pthread_mutexattr_t *, int);
int pthread_mutexattr_setpshared(pthread_mutexattr_t *, int);
+#if __POSIX_VISIBLE >= 202405
+int pthread_mutex_clocklock(pthread_mutex_t * __restrict __mutex,
+ clockid_t, const struct timespec * __restrict)
+ __trylocks_exclusive(0, *__mutex);
+#endif
int pthread_mutex_consistent(pthread_mutex_t * __mutex)
__requires_exclusive(*__mutex);
int pthread_mutex_destroy(pthread_mutex_t * __mutex)
@@ -252,6 +257,16 @@
int pthread_mutex_unlock(pthread_mutex_t * __mutex)
__unlocks(*__mutex);
int pthread_once(pthread_once_t *, void (*) (void));
+#if __POSIX_VISIBLE >= 202405
+int pthread_rwlock_clockrdlock(
+ pthread_rwlock_t * __restrict __rwlock,
+ clockid_t, const struct timespec * __restrict)
+ __trylocks_shared(0, *__rwlock);
+int pthread_rwlock_clockwrlock(
+ pthread_rwlock_t * __restrict __rwlock,
+ clockid_t, const struct timespec * __restrict)
+ __trylocks_exclusive(0, *__rwlock);
+#endif
int pthread_rwlock_destroy(pthread_rwlock_t * __rwlock)
__requires_unlocked(*__rwlock);
int pthread_rwlock_init(pthread_rwlock_t * __restrict __rwlock,
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
@@ -190,36 +190,10 @@
request has both the
.Dv CVWAIT_CLOCKID
flag and the timeout specified.
-Valid clock identifiers are a subset of those for
-.Xr clock_gettime 2 :
-.Bl -bullet -compact
-.It
-.Dv CLOCK_MONOTONIC
-.It
-.Dv CLOCK_MONOTONIC_FAST
-.It
-.Dv CLOCK_MONOTONIC_PRECISE
-.It
-.Dv CLOCK_PROF
-.It
-.Dv CLOCK_REALTIME
-.It
-.Dv CLOCK_REALTIME_FAST
-.It
-.Dv CLOCK_REALTIME_PRECISE
-.It
-.Dv CLOCK_SECOND
-.It
-.Dv CLOCK_TAI
-.It
-.Dv CLOCK_UPTIME
-.It
-.Dv CLOCK_UPTIME_FAST
-.It
-.Dv CLOCK_UPTIME_PRECISE
-.It
-.Dv CLOCK_VIRTUAL
-.El
+Valid clock identifiers are the same as for the
+.Dv _clockid
+member of the
+.Vt struct _umtx_time .
.It Sy Reader/writer lock
.Bd -literal
struct urwlock {
@@ -357,15 +331,46 @@
member specifies the time when the timeout should occur.
Legal values for clock identifier
.Dv _clockid
-are shared with the
+are a subset of the valid values for the
.Fa clock_id
argument to the
.Xr clock_gettime 2
-function,
-and use the same underlying clocks.
+function, and use the same underlying clocks.
The specified clock is used to obtain the current time value.
Interval counting is always performed by the monotonic wall clock.
.Pp
+Currently accepted clocks are:
+.Bl -bullet -compact
+.It
+.Dv CLOCK_MONOTONIC
+.It
+.Dv CLOCK_MONOTONIC_FAST
+.It
+.Dv CLOCK_MONOTONIC_PRECISE
+.It
+.Dv CLOCK_PROCESS_CPUTIME_ID
+.It
+.Dv CLOCK_PROF
+.It
+.Dv CLOCK_REALTIME
+.It
+.Dv CLOCK_REALTIME_FAST
+.It
+.Dv CLOCK_REALTIME_PRECISE
+.It
+.Dv CLOCK_SECOND
+.It
+.Dv CLOCK_TAI
+.It
+.Dv CLOCK_UPTIME
+.It
+.Dv CLOCK_UPTIME_FAST
+.It
+.Dv CLOCK_UPTIME_PRECISE
+.It
+.Dv CLOCK_VIRTUAL
+.El
+.Pp
The
.Dv _flags
argument allows the following flags to further define the timeout behaviour:
diff --git a/lib/libthr/pthread.map b/lib/libthr/pthread.map
--- a/lib/libthr/pthread.map
+++ b/lib/libthr/pthread.map
@@ -345,7 +345,10 @@
FBSD_1.9 {
pthread_cond_clockwait;
+ pthread_mutex_clocklock;
pthread_query_np;
pthread_query_all_np;
+ pthread_rwlock_clockrdlock;
+ pthread_rwlock_clockwrlock;
pthread_tryjoin_np;
};
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
@@ -347,7 +347,7 @@
_pthread_exit(PTHREAD_CANCELED);
else /* this should not happen */
return (error2);
- } else if (error == ETIMEDOUT) {
+ } else if (error != 0 && error != EINTR) {
sq = _sleepq_lookup(cvp);
cvp->__has_user_waiters =
_sleepq_remove(sq, curthread);
@@ -442,6 +442,8 @@
if (abstime == NULL || abstime->tv_sec < 0 || abstime->tv_nsec < 0 ||
abstime->tv_nsec >= 1000000000)
return (EINVAL);
+ if (_thr_check_clockid(clockid) != 0)
+ return (EINVAL);
return (cond_wait_common(cond, mutex, clockid, abstime, true, true));
}
diff --git a/lib/libthr/thread/thr_mutex.c b/lib/libthr/thread/thr_mutex.c
--- a/lib/libthr/thread/thr_mutex.c
+++ b/lib/libthr/thread/thr_mutex.c
@@ -67,6 +67,8 @@
*/
int __pthread_mutex_timedlock(pthread_mutex_t * __restrict mutex,
const struct timespec * __restrict abstime);
+int __pthread_mutex_clocklock(pthread_mutex_t * __restrict mutex,
+ clockid_t clock, const struct timespec * __restrict abstime);
int _pthread_mutex_getspinloops_np(pthread_mutex_t *mutex, int *count);
int _pthread_mutex_setspinloops_np(pthread_mutex_t *mutex, int count);
int __pthread_mutex_setspinloops_np(pthread_mutex_t *mutex, int count);
@@ -76,10 +78,10 @@
static int mutex_self_trylock(pthread_mutex_t);
static int mutex_self_lock(pthread_mutex_t,
- const struct timespec *abstime);
+ const struct timespec *abstime, clockid_t clockid);
static int mutex_unlock_common(struct pthread_mutex *, bool, int *);
static int mutex_lock_sleep(struct pthread *, pthread_mutex_t,
- const struct timespec *);
+ const struct timespec *, clockid_t clockid);
static void mutex_init_robust(struct pthread *curthread);
static int mutex_qidx(struct pthread_mutex *m);
static bool is_robust_mutex(struct pthread_mutex *m);
@@ -93,6 +95,7 @@
__strong_reference(__Tthr_mutex_lock, _pthread_mutex_lock);
__weak_reference(__pthread_mutex_timedlock, pthread_mutex_timedlock);
__strong_reference(__pthread_mutex_timedlock, _pthread_mutex_timedlock);
+__weak_reference(__pthread_mutex_clocklock, pthread_mutex_clocklock);
__weak_reference(__Tthr_mutex_trylock, pthread_mutex_trylock);
__weak_reference(__Tthr_mutex_trylock, __pthread_mutex_trylock);
__strong_reference(__Tthr_mutex_trylock, _pthread_mutex_trylock);
@@ -656,14 +659,14 @@
static int
mutex_lock_sleep(struct pthread *curthread, struct pthread_mutex *m,
- const struct timespec *abstime)
+ const struct timespec *abstime, clockid_t clockid)
{
uint32_t id, owner;
int count, ret;
id = TID(curthread);
if (PMUTEX_OWNER_ID(m) == id)
- return (mutex_self_lock(m, abstime));
+ return (mutex_self_lock(m, abstime, clockid));
/*
* For adaptive mutexes, spin for a bit in the expectation
@@ -709,10 +712,11 @@
if (abstime == NULL)
ret = __thr_umutex_lock(&m->m_lock, id);
else if (__predict_false(abstime->tv_nsec < 0 ||
- abstime->tv_nsec >= 1000000000))
+ abstime->tv_nsec >= 1000000000) ||
+ _thr_check_clockid(clockid) != 0)
ret = EINVAL;
else
- ret = __thr_umutex_timedlock(&m->m_lock, id, abstime);
+ ret = __thr_umutex_timedlock(&m->m_lock, id, abstime, clockid);
done:
if (ret == 0 || ret == EOWNERDEAD) {
enqueue_mutex(curthread, m, ret);
@@ -724,7 +728,7 @@
static __always_inline int
mutex_lock_common(struct pthread_mutex *m, const struct timespec *abstime,
- bool cvattach, bool rb_onlist)
+ clockid_t clockid, bool cvattach, bool rb_onlist)
{
struct pthread *curthread;
int ret, robust;
@@ -741,7 +745,7 @@
if (ret == EOWNERDEAD)
m->m_lock.m_flags |= UMUTEX_NONCONSISTENT;
} else {
- ret = mutex_lock_sleep(curthread, m, abstime);
+ ret = mutex_lock_sleep(curthread, m, abstime, clockid);
}
if (!rb_onlist && robust)
_mutex_leave_robust(curthread, m);
@@ -760,12 +764,12 @@
_thr_check_init();
ret = check_and_init_mutex(mutex, &m);
if (ret == 0)
- ret = mutex_lock_common(m, NULL, false, false);
+ ret = mutex_lock_common(m, NULL, CLOCK_REALTIME, false, false);
return (ret);
}
int
-__pthread_mutex_timedlock(pthread_mutex_t * __restrict mutex,
+__pthread_mutex_clocklock(pthread_mutex_t * __restrict mutex, clockid_t clockid,
const struct timespec * __restrict abstime)
{
struct pthread_mutex *m;
@@ -774,10 +778,17 @@
_thr_check_init();
ret = check_and_init_mutex(mutex, &m);
if (ret == 0)
- ret = mutex_lock_common(m, abstime, false, false);
+ ret = mutex_lock_common(m, abstime, clockid, false, false);
return (ret);
}
+int
+__pthread_mutex_timedlock(pthread_mutex_t * __restrict mutex,
+ const struct timespec * __restrict abstime)
+{
+ return (__pthread_mutex_clocklock(mutex, CLOCK_REALTIME, abstime));
+}
+
int
_thr_mutex_unlock(pthread_mutex_t *mutex)
{
@@ -799,7 +810,7 @@
{
int error;
- error = mutex_lock_common(m, NULL, true, rb_onlist);
+ error = mutex_lock_common(m, NULL, CLOCK_REALTIME, true, rb_onlist);
if (error == 0 || error == EOWNERDEAD)
m->m_count = count;
return (error);
@@ -891,7 +902,8 @@
}
static int
-mutex_self_lock(struct pthread_mutex *m, const struct timespec *abstime)
+mutex_self_lock(struct pthread_mutex *m, const struct timespec *abstime,
+ clockid_t clockid)
{
struct timespec ts1, ts2;
int ret;
@@ -899,23 +911,11 @@
switch (PMUTEX_TYPE(m->m_flags)) {
case PTHREAD_MUTEX_ERRORCHECK:
case PTHREAD_MUTEX_ADAPTIVE_NP:
- if (abstime) {
- if (abstime->tv_sec < 0 || abstime->tv_nsec < 0 ||
- abstime->tv_nsec >= 1000000000) {
- ret = EINVAL;
- } else {
- clock_gettime(CLOCK_REALTIME, &ts1);
- TIMESPEC_SUB(&ts2, abstime, &ts1);
- __sys_nanosleep(&ts2, NULL);
- ret = ETIMEDOUT;
- }
- } else {
- /*
- * POSIX specifies that mutexes should return
- * EDEADLK if a recursive lock is detected.
- */
- ret = EDEADLK;
- }
+ /*
+ * POSIX specifies that mutexes should return EDEADLK
+ * if a recursive lock is detected.
+ */
+ ret = EDEADLK;
break;
case PTHREAD_MUTEX_NORMAL:
@@ -929,10 +929,14 @@
abstime->tv_nsec >= 1000000000) {
ret = EINVAL;
} else {
- clock_gettime(CLOCK_REALTIME, &ts1);
- TIMESPEC_SUB(&ts2, abstime, &ts1);
- __sys_nanosleep(&ts2, NULL);
- ret = ETIMEDOUT;
+ if (_thr_check_clockid(clockid) != 0 ||
+ clock_gettime(clockid, &ts1) == -1) {
+ ret = EINVAL;
+ } else {
+ TIMESPEC_SUB(&ts2, abstime, &ts1);
+ __sys_nanosleep(&ts2, NULL);
+ ret = ETIMEDOUT;
+ }
}
} else {
ts1.tv_sec = 30;
diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h
--- a/lib/libthr/thread/thr_private.h
+++ b/lib/libthr/thread/thr_private.h
@@ -996,6 +996,34 @@
return TAILQ_FIRST(&sq->sq_blocked);
}
+/*
+ * Must accept the same clocks as umtx_check_clockid() in
+ * sys/kern/kern_umtx.c.
+ */
+static inline int
+_thr_check_clockid(clockid_t clockid)
+{
+ switch (clockid) {
+ case CLOCK_REALTIME:
+ case CLOCK_REALTIME_PRECISE:
+ case CLOCK_REALTIME_FAST:
+ case CLOCK_MONOTONIC:
+ case CLOCK_MONOTONIC_PRECISE:
+ case CLOCK_MONOTONIC_FAST:
+ case CLOCK_UPTIME:
+ case CLOCK_UPTIME_PRECISE:
+ case CLOCK_UPTIME_FAST:
+ case CLOCK_SECOND:
+ case CLOCK_VIRTUAL:
+ case CLOCK_PROF:
+ case CLOCK_PROCESS_CPUTIME_ID:
+ case CLOCK_TAI:
+ return (0);
+ default:
+ return (EINVAL);
+ }
+}
+
void _sleepq_init(void) __hidden;
struct sleepqueue *_sleepq_alloc(void) __hidden;
void _sleepq_free(struct sleepqueue *) __hidden;
diff --git a/lib/libthr/thread/thr_rwlock.c b/lib/libthr/thread/thr_rwlock.c
--- a/lib/libthr/thread/thr_rwlock.c
+++ b/lib/libthr/thread/thr_rwlock.c
@@ -39,6 +39,11 @@
_Static_assert(sizeof(struct pthread_rwlock) <= THR_PAGE_SIZE_MIN,
"pthread_rwlock is too large for off-page");
+int _pthread_rwlock_clockrdlock(pthread_rwlock_t * __restrict rwlock,
+ clockid_t clockid, const struct timespec * __restrict abstime);
+int _pthread_rwlock_clockwrlock(pthread_rwlock_t * __restrict rwlock,
+ clockid_t clockid, const struct timespec * __restrict abstime);
+
__weak_reference(_thr_rwlock_destroy, pthread_rwlock_destroy);
__weak_reference(_thr_rwlock_destroy, _pthread_rwlock_destroy);
__weak_reference(_thr_rwlock_init, pthread_rwlock_init);
@@ -46,6 +51,7 @@
__weak_reference(_Tthr_rwlock_rdlock, pthread_rwlock_rdlock);
__weak_reference(_Tthr_rwlock_rdlock, _pthread_rwlock_rdlock);
__weak_reference(_pthread_rwlock_timedrdlock, pthread_rwlock_timedrdlock);
+__weak_reference(_pthread_rwlock_clockrdlock, pthread_rwlock_clockrdlock);
__weak_reference(_Tthr_rwlock_tryrdlock, pthread_rwlock_tryrdlock);
__weak_reference(_Tthr_rwlock_tryrdlock, _pthread_rwlock_tryrdlock);
__weak_reference(_Tthr_rwlock_trywrlock, pthread_rwlock_trywrlock);
@@ -55,6 +61,7 @@
__weak_reference(_Tthr_rwlock_wrlock, pthread_rwlock_wrlock);
__weak_reference(_Tthr_rwlock_wrlock, _pthread_rwlock_wrlock);
__weak_reference(_pthread_rwlock_timedwrlock, pthread_rwlock_timedwrlock);
+__weak_reference(_pthread_rwlock_clockwrlock, pthread_rwlock_clockwrlock);
static int init_static(struct pthread *thread, pthread_rwlock_t *rwlock);
static int init_rwlock(pthread_rwlock_t *rwlock, pthread_rwlock_t *rwlock_out);
@@ -194,7 +201,8 @@
}
static int
-rwlock_rdlock_common(pthread_rwlock_t *rwlock, const struct timespec *abstime)
+rwlock_rdlock_common(pthread_rwlock_t *rwlock, const struct timespec *abstime,
+ clockid_t clockid)
{
struct pthread *curthread = _get_curthread();
pthread_rwlock_t prwlock;
@@ -225,7 +233,8 @@
for (;;) {
/* goto kernel and lock it */
- ret = __thr_rwlock_rdlock(&prwlock->lock, flags, abstime);
+ ret = __thr_rwlock_rdlock(&prwlock->lock, flags, abstime,
+ clockid);
if (ret != EINTR)
break;
@@ -244,7 +253,7 @@
_Tthr_rwlock_rdlock(pthread_rwlock_t *rwlock)
{
_thr_check_init();
- return (rwlock_rdlock_common(rwlock, NULL));
+ return (rwlock_rdlock_common(rwlock, NULL, CLOCK_REALTIME));
}
int
@@ -252,7 +261,15 @@
const struct timespec * __restrict abstime)
{
_thr_check_init();
- return (rwlock_rdlock_common(rwlock, abstime));
+ return (rwlock_rdlock_common(rwlock, abstime, CLOCK_REALTIME));
+}
+
+int
+_pthread_rwlock_clockrdlock(pthread_rwlock_t * __restrict rwlock,
+ clockid_t clockid, const struct timespec * __restrict abstime)
+{
+ _thr_check_init();
+ return (rwlock_rdlock_common(rwlock, abstime, clockid));
}
int
@@ -294,7 +311,8 @@
}
static int
-rwlock_wrlock_common(pthread_rwlock_t *rwlock, const struct timespec *abstime)
+rwlock_wrlock_common(pthread_rwlock_t *rwlock, const struct timespec *abstime,
+ clockid_t clockid)
{
struct pthread *curthread = _get_curthread();
pthread_rwlock_t prwlock;
@@ -322,7 +340,7 @@
for (;;) {
/* goto kernel and lock it */
- ret = __thr_rwlock_wrlock(&prwlock->lock, abstime);
+ ret = __thr_rwlock_wrlock(&prwlock->lock, abstime, clockid);
if (ret == 0) {
prwlock->owner = TID(curthread);
break;
@@ -345,7 +363,7 @@
_Tthr_rwlock_wrlock(pthread_rwlock_t *rwlock)
{
_thr_check_init();
- return (rwlock_wrlock_common(rwlock, NULL));
+ return (rwlock_wrlock_common(rwlock, NULL, CLOCK_REALTIME));
}
int
@@ -353,7 +371,15 @@
const struct timespec * __restrict abstime)
{
_thr_check_init();
- return (rwlock_wrlock_common(rwlock, abstime));
+ return (rwlock_wrlock_common(rwlock, abstime, CLOCK_REALTIME));
+}
+
+int
+_pthread_rwlock_clockwrlock(pthread_rwlock_t * __restrict rwlock,
+ clockid_t clockid, const struct timespec * __restrict abstime)
+{
+ _thr_check_init();
+ return (rwlock_wrlock_common(rwlock, abstime, clockid));
}
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
@@ -42,7 +42,7 @@
int __thr_umutex_lock(struct umutex *mtx, uint32_t id) __hidden;
int __thr_umutex_lock_spin(struct umutex *mtx, uint32_t id) __hidden;
int __thr_umutex_timedlock(struct umutex *mtx, uint32_t id,
- const struct timespec *timeout) __hidden;
+ const struct timespec *timeout, clockid_t clockid) __hidden;
int __thr_umutex_unlock(struct umutex *mtx) __hidden;
int __thr_umutex_trylock(struct umutex *mtx) __hidden;
int __thr_umutex_set_ceiling(struct umutex *mtx, uint32_t ceiling,
@@ -66,9 +66,9 @@
int _thr_ucond_broadcast(struct ucond *cv) __hidden;
int __thr_rwlock_rdlock(struct urwlock *rwlock, int flags,
- const struct timespec *tsp) __hidden;
+ const struct timespec *tsp, clockid_t clockid) __hidden;
int __thr_rwlock_wrlock(struct urwlock *rwlock,
- const struct timespec *tsp) __hidden;
+ const struct timespec *tsp, clockid_t clockid) __hidden;
int __thr_rwlock_unlock(struct urwlock *rwlock) __hidden;
/* Internal used only */
@@ -145,7 +145,7 @@
if (_thr_umutex_trylock2(mtx, id) == 0)
return (0);
- return (__thr_umutex_timedlock(mtx, id, timeout));
+ return (__thr_umutex_timedlock(mtx, id, timeout, CLOCK_REALTIME));
}
static inline int
@@ -233,7 +233,7 @@
if (_thr_rwlock_tryrdlock(rwlock, flags) == 0)
return (0);
- return (__thr_rwlock_rdlock(rwlock, flags, tsp));
+ return (__thr_rwlock_rdlock(rwlock, flags, tsp, CLOCK_REALTIME));
}
static inline int
@@ -242,7 +242,7 @@
if (_thr_rwlock_trywrlock(rwlock) == 0)
return (0);
- return (__thr_rwlock_wrlock(rwlock, tsp));
+ return (__thr_rwlock_wrlock(rwlock, tsp, CLOCK_REALTIME));
}
static inline int
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
@@ -108,7 +108,7 @@
int
__thr_umutex_timedlock(struct umutex *mtx, uint32_t id,
- const struct timespec *abstime)
+ const struct timespec *abstime, clockid_t clockid)
{
struct _umtx_time *tm_p, timeout;
size_t tm_size;
@@ -119,7 +119,7 @@
tm_p = NULL;
tm_size = 0;
} else {
- timeout._clockid = CLOCK_REALTIME;
+ timeout._clockid = clockid;
timeout._flags = UMTX_ABSTIME;
timeout._timeout = *abstime;
tm_p = &timeout;
@@ -151,7 +151,7 @@
ret == ENOTRECOVERABLE)
break;
}
- if (ret == ETIMEDOUT)
+ if (ret == ETIMEDOUT || ret == EINVAL)
break;
}
return (ret);
@@ -292,7 +292,7 @@
int
__thr_rwlock_rdlock(struct urwlock *rwlock, int flags,
- const struct timespec *tsp)
+ const struct timespec *tsp, clockid_t clockid)
{
struct _umtx_time timeout, *tm_p;
size_t tm_size;
@@ -303,7 +303,7 @@
} else {
timeout._timeout = *tsp;
timeout._flags = UMTX_ABSTIME;
- timeout._clockid = CLOCK_REALTIME;
+ timeout._clockid = clockid;
tm_p = &timeout;
tm_size = sizeof(timeout);
}
@@ -312,7 +312,8 @@
}
int
-__thr_rwlock_wrlock(struct urwlock *rwlock, const struct timespec *tsp)
+__thr_rwlock_wrlock(struct urwlock *rwlock, const struct timespec *tsp,
+ clockid_t clockid)
{
struct _umtx_time timeout, *tm_p;
size_t tm_size;
@@ -323,7 +324,7 @@
} else {
timeout._timeout = *tsp;
timeout._flags = UMTX_ABSTIME;
- timeout._clockid = CLOCK_REALTIME;
+ timeout._clockid = clockid;
tm_p = &timeout;
tm_size = sizeof(timeout);
}
@@ -346,7 +347,8 @@
for (;;) {
if (_thr_rwlock_tryrdlock(rwlock, URWLOCK_PREFER_READER) == 0)
return;
- ret = __thr_rwlock_rdlock(rwlock, URWLOCK_PREFER_READER, NULL);
+ ret = __thr_rwlock_rdlock(rwlock, URWLOCK_PREFER_READER, NULL,
+ CLOCK_REALTIME);
if (ret == 0)
return;
if (ret != EINTR)
@@ -362,7 +364,7 @@
for (;;) {
if (_thr_rwlock_trywrlock(rwlock) == 0)
return;
- ret = __thr_rwlock_wrlock(rwlock, NULL);
+ ret = __thr_rwlock_wrlock(rwlock, NULL, CLOCK_REALTIME);
if (ret == 0)
return;
if (ret != EINTR)
diff --git a/share/man/man3/Makefile b/share/man/man3/Makefile
--- a/share/man/man3/Makefile
+++ b/share/man/man3/Makefile
@@ -514,6 +514,7 @@
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_mutex_timedlock.3 pthread_mutex_clocklock.3
PTHREAD_MLINKS+=pthread_mutexattr.3 pthread_mutexattr_destroy.3 \
pthread_mutexattr.3 pthread_mutexattr_getprioceiling.3 \
pthread_mutexattr.3 pthread_mutexattr_getprotocol.3 \
@@ -529,6 +530,8 @@
PTHREAD_MLINKS+=pthread_mutexattr_getkind_np.3 pthread_mutexattr_setkind_np.3
PTHREAD_MLINKS+=pthread_rwlock_rdlock.3 pthread_rwlock_tryrdlock.3
PTHREAD_MLINKS+=pthread_rwlock_wrlock.3 pthread_rwlock_trywrlock.3
+PTHREAD_MLINKS+=pthread_rwlock_timedwrlock.3 pthread_rwlock_clockwrlock.3
+PTHREAD_MLINKS+=pthread_rwlock_timedrdlock.3 pthread_rwlock_clockrdlock.3
PTHREAD_MLINKS+=pthread_schedparam.3 pthread_getschedparam.3 \
pthread_schedparam.3 pthread_setschedparam.3
PTHREAD_MLINKS+=pthread_set_name_np.3 pthread_get_name_np.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
@@ -29,7 +29,8 @@
.Dt PTHREAD_COND_TIMEDWAIT 3
.Os
.Sh NAME
-.Nm pthread_cond_timedwait
+.Nm pthread_cond_timedwait ,
+.Nm pthread_cond_clockwait
.Nd "wait on a condition variable for a specific amount of time"
.Sh LIBRARY
.Lb libpthread
@@ -126,6 +127,9 @@
The
.Fn pthread_cond_clockwait
function conforms to
-.St -p1003.1-2024
-and appeared in
+.St -p1003.1-2024 .
+.Sh HISTORY
+The
+.Fn pthread_cond_clockwait
+function first appeared in
.Fx 16.0 .
diff --git a/share/man/man3/pthread_mutex_timedlock.3 b/share/man/man3/pthread_mutex_timedlock.3
--- a/share/man/man3/pthread_mutex_timedlock.3
+++ b/share/man/man3/pthread_mutex_timedlock.3
@@ -26,6 +26,7 @@
.Dt PTHREAD_MUTEX_TIMEDLOCK 3
.Os
.Sh NAME
+.Nm pthread_mutex_clocklock ,
.Nm pthread_mutex_timedlock
.Nd lock a mutex without blocking indefinitely
.Sh LIBRARY
@@ -34,30 +35,58 @@
.In pthread.h
.In time.h
.Ft int
-.Fn pthread_mutex_timedlock "pthread_mutex_t *restrict mutex" "const struct timespec *restrict abs_timeout"
+.Fo pthread_mutex_clocklock
+.Fa "pthread_mutex_t *restrict mutex"
+.Fa "clockid_t clockid"
+.Fa "const struct timespec *restrict abs_timeout"
+.Fc
+.Ft int
+.Fo pthread_mutex_timedlock
+.Fa "pthread_mutex_t *restrict mutex"
+.Fa "const struct timespec *restrict abs_timeout"
+.Fc
.Sh DESCRIPTION
The
-.Fn pthread_mutex_timedlock
-function will lock
+.Fn pthread_mutex_clocklock
+function locks
.Fa mutex .
-If it is already locked the calling thread will block until
-the mutex becomes available or
-the timeout,
-specified by abs_timeout,
-expires.
-The time of the timeout is an absolute time and
-is not relative to the current time.
+If the mutex is already locked, the calling thread blocks until the
+mutex becomes available or the timeout expires.
+The timeout expires when the clock specified by
+.Fa clockid
+reaches or passes the absolute time
+.Fa abs_timeout ;
+it is not relative to the current time.
+If the mutex can be locked immediately, the call does not fail
+with a timeout, and
+.Fa abs_timeout
+and
+.Fa clockid
+are not checked for validity.
+.Pp
+The
+.Fn pthread_mutex_timedlock
+function is equivalent to
+.Fn pthread_mutex_clocklock
+with
+.Fa clockid
+set to
+.Dv CLOCK_REALTIME .
.Sh RETURN VALUES
If successful,
+.Fn pthread_mutex_clocklock
+and
.Fn pthread_mutex_timedlock
will return zero, otherwise an error number will be returned to
indicate the error.
.Sh ERRORS
The
+.Fn pthread_mutex_clocklock
+and
.Fn pthread_mutex_timedlock
-function will fail if:
+functions will fail if:
.Bl -tag -width Er
-.It Bq "Er ENOTRECOVERABLE"
+.It Bq Er ENOTRECOVERABLE
The
.Fa mutex
was created with the protocol attribute having the
@@ -73,6 +102,17 @@
The
.Fa mutex
parameter is invalid.
+.It Bq Er EINVAL
+The
+.Fa clockid
+parameter is invalid.
+The
+.Dv CLOCK_REALTIME
+and
+.Dv CLOCK_MONOTONIC
+clocks are always supported; see
+.Xr _umtx_op 2
+for the full list of accepted clocks.
.It Bq Er ETIMEDOUT
The
.Fa mutex
@@ -85,7 +125,7 @@
.Fa mutex
has been exceeded.
.It Bq Er EDEADLK
-The current thread already owns the
+The current thread already owns the error-checking
.Fa mutex .
.It Bq Er EOWNERDEAD
The argument
@@ -109,5 +149,14 @@
.Sh STANDARDS
The
.Fn pthread_mutex_timedlock
-function is expected to conform to
+function conforms to
.St -p1003.1-96 .
+The
+.Fn pthread_mutex_clocklock
+function conforms to
+.St -p1003.1-2024 .
+.Sh HISTORY
+The
+.Fn pthread_mutex_clocklock
+function first appeared in
+.Fx 16.0 .
diff --git a/share/man/man3/pthread_rwlock_timedrdlock.3 b/share/man/man3/pthread_rwlock_timedrdlock.3
--- a/share/man/man3/pthread_rwlock_timedrdlock.3
+++ b/share/man/man3/pthread_rwlock_timedrdlock.3
@@ -26,6 +26,7 @@
.Dt PTHREAD_RWLOCK_TIMEDRDLOCK 3
.Os
.Sh NAME
+.Nm pthread_rwlock_clockrdlock ,
.Nm pthread_rwlock_timedrdlock
.Nd "acquire a read-write lock for reading or give up after a specified period"
.Sh LIBRARY
@@ -33,16 +34,32 @@
.Sh SYNOPSIS
.In pthread.h
.Ft int
-.Fn pthread_rwlock_timedrdlock "pthread_rwlock_t *restrict rwlock" "const struct timespec *restrict abs_timeout"
+.Fo pthread_rwlock_clockrdlock
+.Fa "pthread_rwlock_t *restrict rwlock"
+.Fa "clockid_t clockid"
+.Fa "const struct timespec *restrict abs_timeout"
+.Fc
+.Ft int
+.Fo pthread_rwlock_timedrdlock
+.Fa "pthread_rwlock_t *restrict rwlock"
+.Fa "const struct timespec *restrict abs_timeout"
+.Fc
.Sh DESCRIPTION
-This function acquires a read lock on the read-write lock
+These functions acquire a read lock on the read-write lock
.Fa rwlock .
However, if the lock cannot be
acquired without waiting for another thread to
unlock the lock,
-this wait shall be terminated when
+this wait is terminated when
.Fa abs_timeout
expires.
+The
+.Fa abs_timeout
+value is an absolute time, measured on
+.Fa clockid
+for the clock variant and on
+.Dv CLOCK_REALTIME
+for the timed variant.
.Pp
A thread may hold multiple concurrent read locks.
The
@@ -50,38 +67,30 @@
function must be called once for each lock acquired.
.Pp
If the thread should be interrupted by a signal,
-the
-.Fn pthread_rwlock_timedrdlock
-function will be automatically restarted after the thread returns from
-the signal handler.
+the functions are automatically restarted after the thread
+returns from the signal handler.
.Pp
The calling thread may deadlock if
at the time the call is made it holds a write lock on
.Fa rwlock .
-The results are undefined if this function is called with
+The results are undefined if these functions are called with
an uninitialized read-write lock.
.Sh IMPLEMENTATION NOTES
To prevent writer starvation, writers are favored over readers.
.Sh RETURN VALUES
-If successful, the
-.Fn pthread_rwlock_timedrdlock
-function will return zero.
+If successful, the functions will return zero.
Otherwise, an error number will be returned to indicate the error.
.Pp
-This function shall not return an error code of
+These functions do not return an error code of
.Er EINTR .
.Sh ERRORS
-The
-.Fn pthread_rwlock_timedrdlock
-function will fail if:
+The functions will fail if:
.Bl -tag -width Er
.It Bq Er ETIMEDOUT
The lock could not be acquired before the specified timeout expired.
.El
.Pp
-The
-.Fn pthread_rwlock_timedrdlock
-function may fail if:
+The functions may fail if:
.Bl -tag -width Er
.It Bq Er EAGAIN
The read lock could not be
@@ -98,7 +107,17 @@
or the
.Fa abs_timeout
nanosecond value is less than zero or
-greater than or equal to 1 billion.
+greater than or equal to 1 billion, or the
+.Fa clockid
+parameter is invalid.
+.Pp
+The
+.Dv CLOCK_REALTIME
+and
+.Dv CLOCK_MONOTONIC
+clocks are always supported; see
+.Xr _umtx_op 2
+for the full list of accepted clocks.
.El
.Sh SEE ALSO
.Xr pthread_rwlock_init 3 ,
@@ -107,10 +126,18 @@
.Sh STANDARDS
The
.Fn pthread_rwlock_timedrdlock
-function is expected to conform to
+function conforms to
.St -p1003.1-96 .
+The
+.Fn pthread_rwlock_clockrdlock
+function conforms to
+.St -p1003.1-2024 .
.Sh HISTORY
The
.Fn pthread_rwlock_timedrdlock
function first appeared in
.Fx 5.2 .
+The
+.Fn pthread_rwlock_clockrdlock
+function first appeared in
+.Fx 16.0 .
diff --git a/share/man/man3/pthread_rwlock_timedwrlock.3 b/share/man/man3/pthread_rwlock_timedwrlock.3
--- a/share/man/man3/pthread_rwlock_timedwrlock.3
+++ b/share/man/man3/pthread_rwlock_timedwrlock.3
@@ -26,6 +26,7 @@
.Dt PTHREAD_RWLOCK_TIMEDWRLOCK 3
.Os
.Sh NAME
+.Nm pthread_rwlock_clockwrlock ,
.Nm pthread_rwlock_timedwrlock
.Nd "acquire a read-write lock for writing or give up after a specified period"
.Sh LIBRARY
@@ -33,50 +34,58 @@
.Sh SYNOPSIS
.In pthread.h
.Ft int
-.Fn pthread_rwlock_timedwrlock "pthread_rwlock_t *restrict rwlock" "const struct timespec *restrict abs_timeout"
+.Fo pthread_rwlock_clockwrlock
+.Fa "pthread_rwlock_t *restrict rwlock"
+.Fa "clockid_t clockid"
+.Fa "const struct timespec *restrict abs_timeout"
+.Fc
+.Ft int
+.Fo pthread_rwlock_timedwrlock
+.Fa "pthread_rwlock_t *restrict rwlock"
+.Fa "const struct timespec *restrict abs_timeout"
+.Fc
.Sh DESCRIPTION
-This function acquires a write lock on the read-write lock
+These functions acquire a write lock on the read-write lock
.Fa rwlock .
However, if the lock cannot be
acquired without waiting for another thread to
unlock the lock,
-this wait shall be terminated when
+this wait is terminated when
.Fa abs_timeout
expires.
+The
+.Fa abs_timeout
+value is an absolute time, measured on
+.Fa clockid
+for the clock variant and on
+.Dv CLOCK_REALTIME
+for the timed variant.
.Pp
If the thread should be interrupted by a signal,
-the
-.Fn pthread_rwlock_timedwrlock
-function will be automatically restarted after the thread returns from
-the signal handler.
+the functions are automatically restarted after the thread
+returns from the signal handler.
.Pp
The calling thread may deadlock if
at the time the call is made it holds
.Fa rwlock .
-The results are undefined if this function is called with
+The results are undefined if these functions are called with
an uninitialized read-write lock.
.Sh IMPLEMENTATION NOTES
To prevent writer starvation, writers are favored over readers.
.Sh RETURN VALUES
-If successful, the
-.Fn pthread_rwlock_timedwrlock
-function will return zero.
+If successful, the functions will return zero.
Otherwise, an error number will be returned to indicate the error.
.Pp
-This function shall not return an error code of
+These functions do not return an error code of
.Er EINTR .
.Sh ERRORS
-The
-.Fn pthread_rwlock_timedwrlock
-function shall fail if:
+The functions will fail if:
.Bl -tag -width Er
.It Bq Er ETIMEDOUT
The lock could not be acquired before the specified timeout expired.
.El
.Pp
-The
-.Fn pthread_rwlock_timedwrlock
-function may fail if:
+The functions may fail if:
.Bl -tag -width Er
.It Bq Er EDEADLK
The calling thread already holds
@@ -88,7 +97,17 @@
or the
.Fa abs_timeout
nanosecond value is less than zero or
-greater than or equal to 1 billion.
+greater than or equal to 1 billion, or the
+.Fa clockid
+parameter is invalid.
+.Pp
+The
+.Dv CLOCK_REALTIME
+and
+.Dv CLOCK_MONOTONIC
+clocks are always supported; see
+.Xr _umtx_op 2
+for the full list of accepted clocks.
.El
.Sh SEE ALSO
.Xr pthread_rwlock_init 3 ,
@@ -97,10 +116,18 @@
.Sh STANDARDS
The
.Fn pthread_rwlock_timedwrlock
-function is expected to conform to
+function conforms to
.St -p1003.1-96 .
+The
+.Fn pthread_rwlock_clockwrlock
+function conforms to
+.St -p1003.1-2024 .
.Sh HISTORY
The
.Fn pthread_rwlock_timedwrlock
function first appeared in
.Fx 5.2 .
+The
+.Fn pthread_rwlock_clockwrlock
+function first 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
@@ -171,7 +171,7 @@
"umtx chain stats");
#endif
-static inline void umtx_abs_timeout_init2(struct umtx_abs_timeout *timo,
+static inline int umtx_abs_timeout_init2(struct umtx_abs_timeout *timo,
const struct _umtx_time *umtxtime);
static void umtx_shm_init(void);
@@ -678,15 +678,59 @@
return tvtohz(&tv);
}
-void
+/*
+ * Clocks that umtx_abs_timeout_getsbt() can wait on.
+ *
+ * The process CPU-time clocks CLOCK_VIRTUAL, CLOCK_PROF, and
+ * CLOCK_PROCESS_CPUTIME_ID advance while other threads of the process
+ * run. CLOCK_THREAD_CPUTIME_ID is not accepted because the CPU time
+ * of the sleeping thread does not advance.
+ *
+ * The clock ids from clock_getcpuclockid(3) and
+ * pthread_getcpuclockid(3) are not accepted, at least for now.
+ * Reading the CPU time of another process takes sleepable locks,
+ * while the timeout is checked with the umtx chain lock held.
+ */
+static int
+umtx_check_clockid(clockid_t clockid)
+{
+ switch (clockid) {
+ case CLOCK_REALTIME:
+ case CLOCK_REALTIME_PRECISE:
+ case CLOCK_REALTIME_FAST:
+ case CLOCK_MONOTONIC:
+ case CLOCK_MONOTONIC_PRECISE:
+ case CLOCK_MONOTONIC_FAST:
+ case CLOCK_UPTIME:
+ case CLOCK_UPTIME_PRECISE:
+ case CLOCK_UPTIME_FAST:
+ case CLOCK_SECOND:
+ case CLOCK_VIRTUAL:
+ case CLOCK_PROF:
+ case CLOCK_PROCESS_CPUTIME_ID:
+ case CLOCK_TAI:
+ return (0);
+ default:
+ return (EINVAL);
+ }
+}
+
+int
umtx_abs_timeout_init(struct umtx_abs_timeout *timo, int clockid,
int absolute, const struct timespec *timeout)
{
+ int error;
+ error = umtx_check_clockid(clockid);
+ if (error != 0)
+ return (error);
timo->clockid = clockid;
if (!absolute) {
timo->is_abs_real = false;
- kern_clock_gettime(curthread, timo->clockid, &timo->cur);
+ error = kern_clock_gettime(curthread, timo->clockid,
+ &timo->cur);
+ if (error != 0)
+ return (error);
timespecadd(&timo->cur, timeout, &timo->end);
} else {
timo->end = *timeout;
@@ -696,15 +740,16 @@
clockid == CLOCK_TAI ||
clockid == CLOCK_SECOND;
}
+ return (0);
}
-static void
+static int
umtx_abs_timeout_init2(struct umtx_abs_timeout *timo,
const struct _umtx_time *umtxtime)
{
- umtx_abs_timeout_init(timo, umtxtime->_clockid,
- (umtxtime->_flags & UMTX_ABSTIME) != 0, &umtxtime->_timeout);
+ return (umtx_abs_timeout_init(timo, umtxtime->_clockid,
+ (umtxtime->_flags & UMTX_ABSTIME) != 0, &umtxtime->_timeout));
}
static void
@@ -727,6 +772,7 @@
struct bintime bt, bbt;
struct timespec tts;
sbintime_t rem;
+ int error;
switch (timo->clockid) {
@@ -790,7 +836,10 @@
case CLOCK_PROCESS_CPUTIME_ID:
case CLOCK_TAI: /* Boot time is not necessarily stable in TAI */
default:
- kern_clock_gettime(curthread, timo->clockid, &timo->cur);
+ error = kern_clock_gettime(curthread, timo->clockid,
+ &timo->cur);
+ if (error != 0)
+ return (error);
if (timespeccmp(&timo->end, &timo->cur, <=))
return (ETIMEDOUT);
timespecsub(&timo->end, &timo->cur, &tts);
@@ -839,6 +888,15 @@
error = umtx_abs_timeout_getsbt(timo, &sbt, &flags);
if (error != 0)
break;
+
+ /*
+ * msleep() treats zero timeout as no timeout,
+ * return ETIMEDOUT right away.
+ */
+ if ((flags & C_ABSOLUTE) != 0 && sbt == 0) {
+ error = ETIMEDOUT;
+ break;
+ }
}
error = msleep_sbt(uq, &uc->uc_lock, PCATCH | PDROP, wmesg,
sbt, 0, flags);
@@ -927,8 +985,12 @@
int error = 0;
uq = td->td_umtxq;
- if (timeout != NULL)
- umtx_abs_timeout_init(&timo, CLOCK_REALTIME, 0, timeout);
+ if (timeout != NULL) {
+ error = umtx_abs_timeout_init(&timo, CLOCK_REALTIME, 0,
+ timeout);
+ if (error != 0)
+ return (error);
+ }
/*
* Care must be exercised when dealing with umtx structure. It
@@ -1109,8 +1171,12 @@
uq = td->td_umtxq;
- if (timeout != NULL)
- umtx_abs_timeout_init(&timo, CLOCK_REALTIME, 0, timeout);
+ if (timeout != NULL) {
+ error = umtx_abs_timeout_init(&timo, CLOCK_REALTIME, 0,
+ timeout);
+ if (error != 0)
+ return (error);
+ }
/*
* Care must be exercised when dealing with umtx structure. It
@@ -1288,14 +1354,17 @@
uint32_t tmp32;
int error = 0;
+ if (timeout != NULL) {
+ error = umtx_abs_timeout_init2(&timo, timeout);
+ if (error != 0)
+ return (error);
+ }
+
uq = td->td_umtxq;
if ((error = umtx_key_get(addr, TYPE_SIMPLE_WAIT,
is_private ? THREAD_SHARE : AUTO_SHARE, &uq->uq_key)) != 0)
return (error);
- if (timeout != NULL)
- umtx_abs_timeout_init2(&timo, timeout);
-
umtxq_lock(&uq->uq_key);
umtxq_insert(uq);
umtxq_unlock(&uq->uq_key);
@@ -1363,8 +1432,11 @@
id = td->td_tid;
uq = td->td_umtxq;
error = 0;
- if (timeout != NULL)
- umtx_abs_timeout_init2(&timo, timeout);
+ if (timeout != NULL) {
+ error = umtx_abs_timeout_init2(&timo, timeout);
+ if (error != 0)
+ return (error);
+ }
/*
* Care must be exercised when dealing with umtx structure. It
@@ -2250,6 +2322,12 @@
uint32_t id, old_owner, owner, old;
int error, rv;
+ if (timeout != NULL) {
+ error = umtx_abs_timeout_init2(&timo, timeout);
+ if (error != 0)
+ return (error);
+ }
+
id = td->td_tid;
uq = td->td_umtxq;
@@ -2258,9 +2336,6 @@
&uq->uq_key)) != 0)
return (error);
- if (timeout != NULL)
- umtx_abs_timeout_init2(&timo, timeout);
-
umtxq_lock(&uq->uq_key);
pi = umtx_pi_lookup(&uq->uq_key);
if (pi == NULL) {
@@ -2547,6 +2622,12 @@
int error, pri, old_inherited_pri, new_pri, rv;
bool su;
+ if (timeout != NULL) {
+ error = umtx_abs_timeout_init2(&timo, timeout);
+ if (error != 0)
+ return (error);
+ }
+
id = td->td_tid;
uq = td->td_umtxq;
if ((error = umtx_key_get(m, (flags & UMUTEX_ROBUST) != 0 ?
@@ -2554,9 +2635,6 @@
&uq->uq_key)) != 0)
return (error);
- if (timeout != NULL)
- umtx_abs_timeout_init2(&timo, timeout);
-
su = (priv_check(td, PRIV_SCHED_RTPRIO) == 0);
for (;;) {
old_inherited_pri = uq->uq_inherited_pri;
@@ -3090,6 +3168,12 @@
int32_t blocked_readers;
int error, error1, rv;
+ if (timeout != NULL) {
+ error = umtx_abs_timeout_init2(&timo, timeout);
+ if (error != 0)
+ return (error);
+ }
+
uq = td->td_umtxq;
error = fueword32(&rwlock->rw_flags, &flags);
if (error == -1)
@@ -3098,9 +3182,6 @@
if (error != 0)
return (error);
- if (timeout != NULL)
- umtx_abs_timeout_init2(&timo, timeout);
-
wrflags = URWLOCK_WRITE_OWNER;
if (!(fflag & URWLOCK_PREFER_READER) && !(flags & URWLOCK_PREFER_READER))
wrflags |= URWLOCK_WRITE_WAITERS;
@@ -3278,6 +3359,12 @@
int32_t blocked_readers;
int error, error1, rv;
+ if (timeout != NULL) {
+ error = umtx_abs_timeout_init2(&timo, timeout);
+ if (error != 0)
+ return (error);
+ }
+
uq = td->td_umtxq;
error = fueword32(&rwlock->rw_flags, &flags);
if (error == -1)
@@ -3286,9 +3373,6 @@
if (error != 0)
return (error);
- if (timeout != NULL)
- umtx_abs_timeout_init2(&timo, timeout);
-
blocked_readers = 0;
for (;;) {
rv = fueword32(&rwlock->rw_state, &state);
@@ -3572,6 +3656,12 @@
uint32_t flags, count, count1;
int error, rv, rv1;
+ if (timeout != NULL) {
+ error = umtx_abs_timeout_init2(&timo, timeout);
+ if (error != 0)
+ return (error);
+ }
+
uq = td->td_umtxq;
error = fueword32(&sem->_flags, &flags);
if (error == -1)
@@ -3580,9 +3670,6 @@
if (error != 0)
return (error);
- if (timeout != NULL)
- umtx_abs_timeout_init2(&timo, timeout);
-
again:
umtxq_lock(&uq->uq_key);
umtxq_busy(&uq->uq_key);
@@ -3683,9 +3770,11 @@
uq = td->td_umtxq;
flags = fuword32(&sem->_flags);
- if (timeout != NULL)
- umtx_abs_timeout_init2(&timo, timeout);
-
+ if (timeout != NULL) {
+ error = umtx_abs_timeout_init2(&timo, timeout);
+ if (error != 0)
+ return (error);
+ }
again:
error = umtx_key_get(sem, TYPE_SEM, GET_SHARE(flags), &uq->uq_key);
if (error != 0)
@@ -4143,6 +4232,7 @@
(wflags & CVWAIT_UMTX_TIME) != 0))
return (EINVAL);
+ error = 0;
if ((wflags & CVWAIT_UMTX_TIME) == 0) {
/* Allow a null timespec (wait forever). */
if (uap->uaddr2 == NULL) {
@@ -4161,8 +4251,10 @@
clockid = CLOCK_REALTIME;
}
if (ts != NULL) {
- umtx_abs_timeout_init(&timo, clockid,
+ error = umtx_abs_timeout_init(&timo, clockid,
(wflags & CVWAIT_ABSTIME) != 0, ts);
+ if (error != 0)
+ return (error);
timop = &timo;
} else {
timop = NULL;
@@ -4175,13 +4267,10 @@
if (error != 0)
return (error);
timop = &timo;
- umtx_abs_timeout_init2(timop, &umtime);
+ error = umtx_abs_timeout_init2(timop, &umtime);
+ if (error != 0)
+ return (error);
}
- /* 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));
}
diff --git a/sys/sys/umtxvar.h b/sys/sys/umtxvar.h
--- a/sys/sys/umtxvar.h
+++ b/sys/sys/umtxvar.h
@@ -198,7 +198,7 @@
k1->info.both.b == k2->info.both.b);
}
-void umtx_abs_timeout_init(struct umtx_abs_timeout *, int, int,
+int umtx_abs_timeout_init(struct umtx_abs_timeout *, int, int,
const struct timespec *);
int umtx_copyin_timeout(const void *, struct timespec *);
void umtx_exec(struct proc *p);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Nov 7, 1:44 AM (8 h, 53 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41537794
Default Alt Text
D61253.1794015845.diff (39 KB)
Attached To
Mode
D61253: Implement pthread_mutex_clocklock(3) and pthread_rwlock_clock{wr,rd}lock(3) from POSIX 2024
Attached
Detach File
Event Timeline