Page MenuHomeFreeBSD

D61253.1794015845.diff
No OneTemporary

Authored By
Unknown
Size
39 KB
Referenced Files
None
Subscribers
None

D61253.1794015845.diff

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

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)

Event Timeline