Use unused fourth argument of umtx_op to pass flags to kernel for operation
UMTX_OP_WAIT. Upper 16bits is enough to hold a clock id, and lower 16bits is used to pass flags. The change saves a clock_gettime() syscall from libthr.
This commit is contained in:
parent
57fa7d3101
commit
b13a8fa78f
@ -200,20 +200,10 @@ int
|
|||||||
_thr_umtx_timedwait_uint(volatile u_int *mtx, u_int id, int clockid,
|
_thr_umtx_timedwait_uint(volatile u_int *mtx, u_int id, int clockid,
|
||||||
const struct timespec *abstime, int shared)
|
const struct timespec *abstime, int shared)
|
||||||
{
|
{
|
||||||
struct timespec ts, ts2, *tsp;
|
|
||||||
|
|
||||||
if (abstime != NULL) {
|
|
||||||
clock_gettime(clockid, &ts);
|
|
||||||
TIMESPEC_SUB(&ts2, abstime, &ts);
|
|
||||||
if (ts2.tv_sec < 0 || (ts2.tv_sec == 0 && ts2.tv_nsec <= 0))
|
|
||||||
return (ETIMEDOUT);
|
|
||||||
tsp = &ts2;
|
|
||||||
} else {
|
|
||||||
tsp = NULL;
|
|
||||||
}
|
|
||||||
return _umtx_op_err(__DEVOLATILE(void *, mtx),
|
return _umtx_op_err(__DEVOLATILE(void *, mtx),
|
||||||
shared ? UMTX_OP_WAIT_UINT : UMTX_OP_WAIT_UINT_PRIVATE, id, NULL,
|
shared ? UMTX_OP_WAIT_UINT : UMTX_OP_WAIT_UINT_PRIVATE, id,
|
||||||
tsp);
|
abstime != NULL ? (void *)(uintptr_t)((clockid << 16) | UMTX_WAIT_ABSTIME) : 0,
|
||||||
|
__DECONST(void *, abstime));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -970,17 +970,26 @@ do_unlock_umtx32(struct thread *td, uint32_t *m, uint32_t id)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
tstohz(const struct timespec *tsp)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
TIMESPEC_TO_TIMEVAL(&tv, tsp);
|
||||||
|
return tvtohz(&tv);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fetch and compare value, sleep on the address if value is not changed.
|
* Fetch and compare value, sleep on the address if value is not changed.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
do_wait(struct thread *td, void *addr, u_long id,
|
do_wait(struct thread *td, void *addr, u_long id,
|
||||||
struct timespec *timeout, int compat32, int is_private)
|
struct timespec *timeout, int compat32, int is_private, uint32_t flags)
|
||||||
{
|
{
|
||||||
struct umtx_q *uq;
|
struct umtx_q *uq;
|
||||||
struct timespec ts, ts2, ts3;
|
struct timespec ets, cts, tts;
|
||||||
struct timeval tv;
|
|
||||||
u_long tmp;
|
u_long tmp;
|
||||||
|
int clockid = (flags >> 16) & 0xFFFF;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
uq = td->td_umtxq;
|
uq = td->td_umtxq;
|
||||||
@ -1005,12 +1014,22 @@ do_wait(struct thread *td, void *addr, u_long id,
|
|||||||
umtxq_remove(uq);
|
umtxq_remove(uq);
|
||||||
umtxq_unlock(&uq->uq_key);
|
umtxq_unlock(&uq->uq_key);
|
||||||
} else {
|
} else {
|
||||||
getnanouptime(&ts);
|
kern_clock_gettime(td, clockid, &cts);
|
||||||
timespecadd(&ts, timeout);
|
if ((flags & UMTX_WAIT_ABSTIME) == 0) {
|
||||||
TIMESPEC_TO_TIMEVAL(&tv, timeout);
|
ets = cts;
|
||||||
|
timespecadd(&ets, timeout);
|
||||||
|
} else {
|
||||||
|
ets = *timeout;
|
||||||
|
}
|
||||||
umtxq_lock(&uq->uq_key);
|
umtxq_lock(&uq->uq_key);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
error = umtxq_sleep(uq, "uwait", tvtohz(&tv));
|
if (timespeccmp(&cts, &ets, >=)) {
|
||||||
|
error = ETIMEDOUT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tts = ets;
|
||||||
|
timespecsub(&tts, &cts);
|
||||||
|
error = umtxq_sleep(uq, "uwait", tstohz(&tts));
|
||||||
if (!(uq->uq_flags & UQF_UMTXQ)) {
|
if (!(uq->uq_flags & UQF_UMTXQ)) {
|
||||||
error = 0;
|
error = 0;
|
||||||
break;
|
break;
|
||||||
@ -1018,15 +1037,7 @@ do_wait(struct thread *td, void *addr, u_long id,
|
|||||||
if (error != ETIMEDOUT)
|
if (error != ETIMEDOUT)
|
||||||
break;
|
break;
|
||||||
umtxq_unlock(&uq->uq_key);
|
umtxq_unlock(&uq->uq_key);
|
||||||
getnanouptime(&ts2);
|
kern_clock_gettime(td, clockid, &cts);
|
||||||
if (timespeccmp(&ts2, &ts, >=)) {
|
|
||||||
error = ETIMEDOUT;
|
|
||||||
umtxq_lock(&uq->uq_key);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ts3 = ts;
|
|
||||||
timespecsub(&ts3, &ts2);
|
|
||||||
TIMESPEC_TO_TIMEVAL(&tv, &ts3);
|
|
||||||
umtxq_lock(&uq->uq_key);
|
umtxq_lock(&uq->uq_key);
|
||||||
}
|
}
|
||||||
umtxq_remove(uq);
|
umtxq_remove(uq);
|
||||||
@ -2941,6 +2952,7 @@ __umtx_op_wait(struct thread *td, struct _umtx_op_args *uap)
|
|||||||
{
|
{
|
||||||
struct timespec *ts, timeout;
|
struct timespec *ts, timeout;
|
||||||
int error;
|
int error;
|
||||||
|
uint32_t flags;
|
||||||
|
|
||||||
if (uap->uaddr2 == NULL)
|
if (uap->uaddr2 == NULL)
|
||||||
ts = NULL;
|
ts = NULL;
|
||||||
@ -2950,7 +2962,8 @@ __umtx_op_wait(struct thread *td, struct _umtx_op_args *uap)
|
|||||||
return (error);
|
return (error);
|
||||||
ts = &timeout;
|
ts = &timeout;
|
||||||
}
|
}
|
||||||
return do_wait(td, uap->obj, uap->val, ts, 0, 0);
|
flags = (uint32_t)(uintptr_t)uap->uaddr1;
|
||||||
|
return do_wait(td, uap->obj, uap->val, ts, 0, 0, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -2958,6 +2971,7 @@ __umtx_op_wait_uint(struct thread *td, struct _umtx_op_args *uap)
|
|||||||
{
|
{
|
||||||
struct timespec *ts, timeout;
|
struct timespec *ts, timeout;
|
||||||
int error;
|
int error;
|
||||||
|
uint32_t flags;
|
||||||
|
|
||||||
if (uap->uaddr2 == NULL)
|
if (uap->uaddr2 == NULL)
|
||||||
ts = NULL;
|
ts = NULL;
|
||||||
@ -2967,7 +2981,8 @@ __umtx_op_wait_uint(struct thread *td, struct _umtx_op_args *uap)
|
|||||||
return (error);
|
return (error);
|
||||||
ts = &timeout;
|
ts = &timeout;
|
||||||
}
|
}
|
||||||
return do_wait(td, uap->obj, uap->val, ts, 1, 0);
|
flags = (uint32_t)(uintptr_t)uap->uaddr1;
|
||||||
|
return do_wait(td, uap->obj, uap->val, ts, 1, 0, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -2975,6 +2990,7 @@ __umtx_op_wait_uint_private(struct thread *td, struct _umtx_op_args *uap)
|
|||||||
{
|
{
|
||||||
struct timespec *ts, timeout;
|
struct timespec *ts, timeout;
|
||||||
int error;
|
int error;
|
||||||
|
uint32_t flags;
|
||||||
|
|
||||||
if (uap->uaddr2 == NULL)
|
if (uap->uaddr2 == NULL)
|
||||||
ts = NULL;
|
ts = NULL;
|
||||||
@ -2984,7 +3000,8 @@ __umtx_op_wait_uint_private(struct thread *td, struct _umtx_op_args *uap)
|
|||||||
return (error);
|
return (error);
|
||||||
ts = &timeout;
|
ts = &timeout;
|
||||||
}
|
}
|
||||||
return do_wait(td, uap->obj, uap->val, ts, 1, 1);
|
flags = (uint32_t)(uintptr_t)uap->uaddr1;
|
||||||
|
return do_wait(td, uap->obj, uap->val, ts, 1, 1, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -3286,6 +3303,7 @@ __umtx_op_wait_compat32(struct thread *td, struct _umtx_op_args *uap)
|
|||||||
{
|
{
|
||||||
struct timespec *ts, timeout;
|
struct timespec *ts, timeout;
|
||||||
int error;
|
int error;
|
||||||
|
uint32_ flags;
|
||||||
|
|
||||||
if (uap->uaddr2 == NULL)
|
if (uap->uaddr2 == NULL)
|
||||||
ts = NULL;
|
ts = NULL;
|
||||||
@ -3295,7 +3313,8 @@ __umtx_op_wait_compat32(struct thread *td, struct _umtx_op_args *uap)
|
|||||||
return (error);
|
return (error);
|
||||||
ts = &timeout;
|
ts = &timeout;
|
||||||
}
|
}
|
||||||
return do_wait(td, uap->obj, uap->val, ts, 1, 0);
|
flags = (uint32_t)(uintptr_t)uap->uaddr1;
|
||||||
|
return do_wait(td, uap->obj, uap->val, ts, 1, 0, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -3394,6 +3413,7 @@ __umtx_op_wait_uint_private_compat32(struct thread *td, struct _umtx_op_args *ua
|
|||||||
{
|
{
|
||||||
struct timespec *ts, timeout;
|
struct timespec *ts, timeout;
|
||||||
int error;
|
int error;
|
||||||
|
uint32_t flags;
|
||||||
|
|
||||||
if (uap->uaddr2 == NULL)
|
if (uap->uaddr2 == NULL)
|
||||||
ts = NULL;
|
ts = NULL;
|
||||||
@ -3403,7 +3423,8 @@ __umtx_op_wait_uint_private_compat32(struct thread *td, struct _umtx_op_args *ua
|
|||||||
return (error);
|
return (error);
|
||||||
ts = &timeout;
|
ts = &timeout;
|
||||||
}
|
}
|
||||||
return do_wait(td, uap->obj, uap->val, ts, 1, 1);
|
flags = (uint32_t)(uintptr_t)uap->uaddr1;
|
||||||
|
return do_wait(td, uap->obj, uap->val, ts, 1, 1, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -87,6 +87,8 @@
|
|||||||
#define CVWAIT_ABSTIME 0x02
|
#define CVWAIT_ABSTIME 0x02
|
||||||
#define CVWAIT_CLOCKID 0x04
|
#define CVWAIT_CLOCKID 0x04
|
||||||
|
|
||||||
|
#define UMTX_WAIT_ABSTIME 0x01
|
||||||
|
|
||||||
#define UMTX_CHECK_UNPARKING CVWAIT_CHECK_UNPARKING
|
#define UMTX_CHECK_UNPARKING CVWAIT_CHECK_UNPARKING
|
||||||
|
|
||||||
#ifndef _KERNEL
|
#ifndef _KERNEL
|
||||||
|
Loading…
Reference in New Issue
Block a user