mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 11:25:21 +01:00
libthr: implement pthread_cond_clockwait(3)
Reviewed by: markj Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D58463
This commit is contained in:
1 parent
149d3e5fcb
commit
e1136fbcab
6 files changed
+82
-25
No files matched your search
@@ -199,6 +199,11 @@ int pthread_condattr_init(pthread_condattr_t *);
|
||||
int pthread_condattr_setclock(pthread_condattr_t *, clockid_t);
|
||||
int pthread_condattr_setpshared(pthread_condattr_t *, int);
|
||||
int pthread_cond_broadcast(pthread_cond_t *);
|
||||
#if __POSIX_VISIBLE >= 202405
|
||||
int pthread_cond_clockwait(pthread_cond_t * __restrict,
|
||||
pthread_mutex_t * __restrict, clockid_t,
|
||||
const struct timespec * __restrict);
|
||||
#endif
|
||||
int pthread_cond_destroy(pthread_cond_t *);
|
||||
int pthread_cond_init(pthread_cond_t * __restrict,
|
||||
const pthread_condattr_t * __restrict);
|
||||
|
||||
@@ -344,5 +344,6 @@ FBSD_1.8 {
|
||||
};
|
||||
|
||||
FBSD_1.9 {
|
||||
pthread_cond_clockwait;
|
||||
pthread_tryjoin_np;
|
||||
};
|
||||
@@ -76,7 +76,8 @@ _pthread_barrier_destroy(pthread_barrier_t *barrier)
|
||||
return (EBUSY);
|
||||
}
|
||||
if (bar->b_refcount != 0) {
|
||||
_thr_ucond_wait(&bar->b_cv, &bar->b_lock, NULL, 0);
|
||||
_thr_ucond_wait(&bar->b_cv, &bar->b_lock, NULL,
|
||||
NULL, 0);
|
||||
THR_UMUTEX_LOCK(curthread, &bar->b_lock);
|
||||
} else
|
||||
break;
|
||||
@@ -158,7 +159,8 @@ _pthread_barrier_wait(pthread_barrier_t *barrier)
|
||||
cycle = bar->b_cycle;
|
||||
bar->b_refcount++;
|
||||
do {
|
||||
_thr_ucond_wait(&bar->b_cv, &bar->b_lock, NULL, 0);
|
||||
_thr_ucond_wait(&bar->b_cv, &bar->b_lock, NULL,
|
||||
NULL, 0);
|
||||
THR_UMUTEX_LOCK(curthread, &bar->b_lock);
|
||||
/* test cycle to avoid bogus wakeup */
|
||||
} while (cycle == bar->b_cycle);
|
||||
|
||||
@@ -46,11 +46,14 @@ _Static_assert(sizeof(struct pthread_cond) <= THR_PAGE_SIZE_MIN,
|
||||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
int __pthread_cond_clockwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
clockid_t clockid, const struct timespec *abstime);
|
||||
int __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
const struct timespec * abstime);
|
||||
static int cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
|
||||
static int cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
const struct timespec *abstime, bool cancel);
|
||||
clockid_t clockid, const struct timespec *abstime, bool cancel,
|
||||
bool clockwait);
|
||||
static int cond_signal_common(pthread_cond_t *cond);
|
||||
static int cond_broadcast_common(pthread_cond_t *cond);
|
||||
|
||||
@@ -64,6 +67,7 @@ __weak_reference(__thr_cond_wait, __pthread_cond_wait);
|
||||
__weak_reference(_thr_cond_wait, _pthread_cond_wait);
|
||||
__weak_reference(__pthread_cond_timedwait, pthread_cond_timedwait);
|
||||
__weak_reference(_thr_cond_timedwait, _pthread_cond_timedwait);
|
||||
__weak_reference(__pthread_cond_clockwait, pthread_cond_clockwait);
|
||||
__weak_reference(_thr_cond_init, pthread_cond_init);
|
||||
__weak_reference(_thr_cond_init, _pthread_cond_init);
|
||||
__weak_reference(_thr_cond_destroy, pthread_cond_destroy);
|
||||
@@ -202,9 +206,11 @@ _thr_cond_destroy(pthread_cond_t *cond)
|
||||
*/
|
||||
static int
|
||||
cond_wait_kernel(struct pthread_cond *cvp, struct pthread_mutex *mp,
|
||||
const struct timespec *abstime, bool cancel)
|
||||
clockid_t clockid, const struct timespec *abstime, bool cancel,
|
||||
bool clockwait)
|
||||
{
|
||||
struct pthread *curthread;
|
||||
struct _umtx_time utime;
|
||||
int error, error2, recurse, robust;
|
||||
|
||||
curthread = _get_curthread();
|
||||
@@ -219,8 +225,16 @@ cond_wait_kernel(struct pthread_cond *cvp, struct pthread_mutex *mp,
|
||||
|
||||
if (cancel)
|
||||
_thr_cancel_enter2(curthread, 0);
|
||||
error = _thr_ucond_wait(&cvp->kcond, &mp->m_lock, abstime,
|
||||
CVWAIT_ABSTIME | CVWAIT_CLOCKID);
|
||||
if (clockwait) {
|
||||
utime._timeout = *abstime;
|
||||
utime._flags = UMTX_ABSTIME;
|
||||
utime._clockid = clockid;
|
||||
error = _thr_ucond_wait(&cvp->kcond, &mp->m_lock, NULL,
|
||||
&utime, CVWAIT_UMTX_TIME);
|
||||
} else {
|
||||
error = _thr_ucond_wait(&cvp->kcond, &mp->m_lock, abstime,
|
||||
NULL, CVWAIT_ABSTIME | CVWAIT_CLOCKID);
|
||||
}
|
||||
if (cancel)
|
||||
_thr_cancel_leave(curthread, 0);
|
||||
|
||||
@@ -274,7 +288,7 @@ cond_wait_kernel(struct pthread_cond *cvp, struct pthread_mutex *mp,
|
||||
|
||||
static int
|
||||
cond_wait_user(struct pthread_cond *cvp, struct pthread_mutex *mp,
|
||||
const struct timespec *abstime, bool cancel)
|
||||
clockid_t clockid, const struct timespec *abstime, bool cancel)
|
||||
{
|
||||
struct pthread *curthread;
|
||||
struct sleepqueue *sq;
|
||||
@@ -315,7 +329,7 @@ cond_wait_user(struct pthread_cond *cvp, struct pthread_mutex *mp,
|
||||
|
||||
if (cancel)
|
||||
_thr_cancel_enter2(curthread, 0);
|
||||
error = _thr_sleep(curthread, cvp->kcond.c_clockid, abstime);
|
||||
error = _thr_sleep(curthread, clockid, abstime);
|
||||
if (cancel)
|
||||
_thr_cancel_leave(curthread, 0);
|
||||
|
||||
@@ -350,7 +364,8 @@ cond_wait_user(struct pthread_cond *cvp, struct pthread_mutex *mp,
|
||||
|
||||
static int
|
||||
cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
const struct timespec *abstime, bool cancel)
|
||||
clockid_t clockid, const struct timespec *abstime, bool cancel,
|
||||
bool clockwait)
|
||||
{
|
||||
struct pthread *curthread = _get_curthread();
|
||||
struct pthread_cond *cvp;
|
||||
@@ -359,6 +374,9 @@ cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
|
||||
CHECK_AND_INIT_COND
|
||||
|
||||
if (!clockwait)
|
||||
clockid = cvp->kcond.c_clockid;
|
||||
|
||||
if (*mutex == THR_PSHARED_PTR) {
|
||||
mp = __thr_pshared_offpage(mutex, 0);
|
||||
if (mp == NULL)
|
||||
@@ -372,23 +390,25 @@ cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
|
||||
if (curthread->attr.sched_policy != SCHED_OTHER ||
|
||||
(mp->m_lock.m_flags & (UMUTEX_PRIO_PROTECT | UMUTEX_PRIO_INHERIT |
|
||||
USYNC_PROCESS_SHARED)) != 0 || CV_PSHARED(cvp))
|
||||
return (cond_wait_kernel(cvp, mp, abstime, cancel));
|
||||
else
|
||||
return (cond_wait_user(cvp, mp, abstime, cancel));
|
||||
USYNC_PROCESS_SHARED)) != 0 || CV_PSHARED(cvp)) {
|
||||
return (cond_wait_kernel(cvp, mp, clockid, abstime, cancel,
|
||||
clockwait));
|
||||
} else {
|
||||
return (cond_wait_user(cvp, mp, clockid, abstime, cancel));
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
_thr_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
|
||||
{
|
||||
return (cond_wait_common(cond, mutex, NULL, false));
|
||||
return (cond_wait_common(cond, mutex, 0, NULL, false, false));
|
||||
}
|
||||
|
||||
int
|
||||
__thr_cond_wait(pthread_cond_t * __restrict cond,
|
||||
pthread_mutex_t * __restrict mutex)
|
||||
{
|
||||
return (cond_wait_common(cond, mutex, NULL, true));
|
||||
return (cond_wait_common(cond, mutex, 0, NULL, true, false));
|
||||
}
|
||||
|
||||
int
|
||||
@@ -400,18 +420,30 @@ _thr_cond_timedwait(pthread_cond_t * __restrict cond,
|
||||
abstime->tv_nsec >= 1000000000)
|
||||
return (EINVAL);
|
||||
|
||||
return (cond_wait_common(cond, mutex, abstime, false));
|
||||
return (cond_wait_common(cond, mutex, 0, abstime, false, false));
|
||||
}
|
||||
|
||||
int
|
||||
__pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
const struct timespec *abstime)
|
||||
const struct timespec *abstime)
|
||||
{
|
||||
if (abstime == NULL || abstime->tv_sec < 0 || abstime->tv_nsec < 0 ||
|
||||
abstime->tv_nsec >= 1000000000)
|
||||
return (EINVAL);
|
||||
|
||||
return (cond_wait_common(cond, mutex, abstime, true));
|
||||
return (cond_wait_common(cond, mutex, 0, abstime, true, false));
|
||||
}
|
||||
|
||||
int
|
||||
__pthread_cond_clockwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
clockid_t clockid, const struct timespec *abstime)
|
||||
{
|
||||
|
||||
if (abstime == NULL || abstime->tv_sec < 0 || abstime->tv_nsec < 0 ||
|
||||
abstime->tv_nsec >= 1000000000)
|
||||
return (EINVAL);
|
||||
|
||||
return (cond_wait_common(cond, mutex, clockid, abstime, true, true));
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
@@ -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 @@ _thr_ucond_init(struct ucond *cv)
|
||||
|
||||
int
|
||||
_thr_ucond_wait(struct ucond *cv, struct umutex *m,
|
||||
const struct timespec *timeout, int flags)
|
||||
const struct timespec *timeout, const struct _umtx_time *utimep, int flags)
|
||||
{
|
||||
struct pthread *curthread;
|
||||
const struct timespec *ts;
|
||||
void *arg2;
|
||||
|
||||
if (timeout != NULL && (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)
|
||||
{
|
||||
|
||||
@@ -59,7 +59,8 @@ int _thr_umtx_timedwait_uint(volatile u_int *mtx, u_int exp, int clockid,
|
||||
const struct timespec *timeout, int shared) __hidden;
|
||||
int _thr_umtx_wake(volatile void *mtx, int count, int shared) __hidden;
|
||||
int _thr_ucond_wait(struct ucond *cv, struct umutex *m,
|
||||
const struct timespec *timeout, int flags) __hidden;
|
||||
const struct timespec *timeout, const struct _umtx_time *utimep,
|
||||
int flags) __hidden;
|
||||
void _thr_ucond_init(struct ucond *cv) __hidden;
|
||||
int _thr_ucond_signal(struct ucond *cv) __hidden;
|
||||
int _thr_ucond_broadcast(struct ucond *cv) __hidden;
|
||||
|
||||
Reference in new issue
Block a user