summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2012-02-22 03:22:49 +0000
committerdavidxu <davidxu@FreeBSD.org>2012-02-22 03:22:49 +0000
commitd177303078ee8f6069218009d6c3c2b6d9d9ca97 (patch)
tree243668cadaadb4cb39ffc1650b45f200ef00ac6c
parent1ec5baaef2e3798db4f06efbac2ca27d4d5506a5 (diff)
downloadFreeBSD-src-d177303078ee8f6069218009d6c3c2b6d9d9ca97.zip
FreeBSD-src-d177303078ee8f6069218009d6c3c2b6d9d9ca97.tar.gz
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.
-rw-r--r--lib/libthr/thread/thr_umtx.c16
-rw-r--r--sys/kern/kern_umtx.c63
-rw-r--r--sys/sys/umtx.h2
3 files changed, 47 insertions, 34 deletions
diff --git a/lib/libthr/thread/thr_umtx.c b/lib/libthr/thread/thr_umtx.c
index 0a8f861..f7acac3 100644
--- a/lib/libthr/thread/thr_umtx.c
+++ b/lib/libthr/thread/thr_umtx.c
@@ -200,20 +200,10 @@ int
_thr_umtx_timedwait_uint(volatile u_int *mtx, u_int id, int clockid,
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),
- shared ? UMTX_OP_WAIT_UINT : UMTX_OP_WAIT_UINT_PRIVATE, id, NULL,
- tsp);
+ shared ? UMTX_OP_WAIT_UINT : UMTX_OP_WAIT_UINT_PRIVATE, id,
+ abstime != NULL ? (void *)(uintptr_t)((clockid << 16) | UMTX_WAIT_ABSTIME) : 0,
+ __DECONST(void *, abstime));
}
int
diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c
index 896f77c..6e924d1 100644
--- a/sys/kern/kern_umtx.c
+++ b/sys/kern/kern_umtx.c
@@ -970,17 +970,26 @@ do_unlock_umtx32(struct thread *td, uint32_t *m, uint32_t id)
}
#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.
*/
static int
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 timespec ts, ts2, ts3;
- struct timeval tv;
+ struct timespec ets, cts, tts;
u_long tmp;
+ int clockid = (flags >> 16) & 0xFFFF;
int error = 0;
uq = td->td_umtxq;
@@ -1005,12 +1014,22 @@ do_wait(struct thread *td, void *addr, u_long id,
umtxq_remove(uq);
umtxq_unlock(&uq->uq_key);
} else {
- getnanouptime(&ts);
- timespecadd(&ts, timeout);
- TIMESPEC_TO_TIMEVAL(&tv, timeout);
+ kern_clock_gettime(td, clockid, &cts);
+ if ((flags & UMTX_WAIT_ABSTIME) == 0) {
+ ets = cts;
+ timespecadd(&ets, timeout);
+ } else {
+ ets = *timeout;
+ }
umtxq_lock(&uq->uq_key);
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)) {
error = 0;
break;
@@ -1018,15 +1037,7 @@ do_wait(struct thread *td, void *addr, u_long id,
if (error != ETIMEDOUT)
break;
umtxq_unlock(&uq->uq_key);
- getnanouptime(&ts2);
- if (timespeccmp(&ts2, &ts, >=)) {
- error = ETIMEDOUT;
- umtxq_lock(&uq->uq_key);
- break;
- }
- ts3 = ts;
- timespecsub(&ts3, &ts2);
- TIMESPEC_TO_TIMEVAL(&tv, &ts3);
+ kern_clock_gettime(td, clockid, &cts);
umtxq_lock(&uq->uq_key);
}
umtxq_remove(uq);
@@ -2941,6 +2952,7 @@ __umtx_op_wait(struct thread *td, struct _umtx_op_args *uap)
{
struct timespec *ts, timeout;
int error;
+ uint32_t flags;
if (uap->uaddr2 == NULL)
ts = NULL;
@@ -2950,7 +2962,8 @@ __umtx_op_wait(struct thread *td, struct _umtx_op_args *uap)
return (error);
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
@@ -2958,6 +2971,7 @@ __umtx_op_wait_uint(struct thread *td, struct _umtx_op_args *uap)
{
struct timespec *ts, timeout;
int error;
+ uint32_t flags;
if (uap->uaddr2 == NULL)
ts = NULL;
@@ -2967,7 +2981,8 @@ __umtx_op_wait_uint(struct thread *td, struct _umtx_op_args *uap)
return (error);
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
@@ -2975,6 +2990,7 @@ __umtx_op_wait_uint_private(struct thread *td, struct _umtx_op_args *uap)
{
struct timespec *ts, timeout;
int error;
+ uint32_t flags;
if (uap->uaddr2 == NULL)
ts = NULL;
@@ -2984,7 +3000,8 @@ __umtx_op_wait_uint_private(struct thread *td, struct _umtx_op_args *uap)
return (error);
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
@@ -3286,6 +3303,7 @@ __umtx_op_wait_compat32(struct thread *td, struct _umtx_op_args *uap)
{
struct timespec *ts, timeout;
int error;
+ uint32_ flags;
if (uap->uaddr2 == NULL)
ts = NULL;
@@ -3295,7 +3313,8 @@ __umtx_op_wait_compat32(struct thread *td, struct _umtx_op_args *uap)
return (error);
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
@@ -3394,6 +3413,7 @@ __umtx_op_wait_uint_private_compat32(struct thread *td, struct _umtx_op_args *ua
{
struct timespec *ts, timeout;
int error;
+ uint32_t flags;
if (uap->uaddr2 == NULL)
ts = NULL;
@@ -3403,7 +3423,8 @@ __umtx_op_wait_uint_private_compat32(struct thread *td, struct _umtx_op_args *ua
return (error);
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
diff --git a/sys/sys/umtx.h b/sys/sys/umtx.h
index 8d8950d..cfdb565 100644
--- a/sys/sys/umtx.h
+++ b/sys/sys/umtx.h
@@ -87,6 +87,8 @@
#define CVWAIT_ABSTIME 0x02
#define CVWAIT_CLOCKID 0x04
+#define UMTX_WAIT_ABSTIME 0x01
+
#define UMTX_CHECK_UNPARKING CVWAIT_CHECK_UNPARKING
#ifndef _KERNEL
OpenPOWER on IntegriCloud