summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2005-01-14 13:38:15 +0000
committerdavidxu <davidxu@FreeBSD.org>2005-01-14 13:38:15 +0000
commit8a30514f66e00de862d52c04d71d53f87a59918c (patch)
tree7028b9225a923222e937dc7134e4bb1089304c34 /sys
parentd7e35203c706dd9dfd06d90bf19ca74e0f9d1dda (diff)
downloadFreeBSD-src-8a30514f66e00de862d52c04d71d53f87a59918c.zip
FreeBSD-src-8a30514f66e00de862d52c04d71d53f87a59918c.tar.gz
make umtx timeout relative so userland can select different clock type,
e.g, CLOCK_REALTIME or CLOCK_MONOTONIC. merge umtx_wait and umtx_timedwait into single function.
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_umtx.c97
-rw-r--r--sys/sys/umtx.h14
2 files changed, 55 insertions, 56 deletions
diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c
index 007b3a8..1e93a66 100644
--- a/sys/kern/kern_umtx.c
+++ b/sys/kern/kern_umtx.c
@@ -525,28 +525,30 @@ _do_lock(struct thread *td, struct umtx *umtx, long id, int timo)
static int
do_lock(struct thread *td, struct umtx *umtx, long id,
- struct timespec *abstime)
+ struct timespec *timeout)
{
- struct timespec ts1, ts2;
+ struct timespec ts, ts2, ts3;
struct timeval tv;
- int timo, error;
+ int error;
- if (abstime == NULL) {
+ if (timeout == NULL) {
error = _do_lock(td, umtx, id, 0);
} else {
+ getnanouptime(&ts);
+ timespecadd(&ts, timeout);
+ TIMESPEC_TO_TIMEVAL(&tv, timeout);
for (;;) {
- ts1 = *abstime;
- getnanotime(&ts2);
- timespecsub(&ts1, &ts2);
- TIMESPEC_TO_TIMEVAL(&tv, &ts1);
- if (tv.tv_sec < 0) {
+ error = _do_lock(td, umtx, id, tvtohz(&tv));
+ if (error != ETIMEDOUT)
+ break;
+ getnanouptime(&ts2);
+ if (timespeccmp(&ts2, &ts, >=)) {
error = ETIMEDOUT;
break;
}
- timo = tvtohz(&tv);
- error = _do_lock(td, umtx, id, timo);
- if (error != ETIMEDOUT)
- break;
+ ts3 = ts;
+ timespecsub(&ts3, &ts2);
+ TIMESPEC_TO_TIMEVAL(&tv, &ts3);
}
}
/*
@@ -610,13 +612,13 @@ do_unlock(struct thread *td, struct umtx *umtx, long id)
}
static int
-do_wait(struct thread *td, struct umtx *umtx, long id, struct timespec *abstime)
+do_wait(struct thread *td, struct umtx *umtx, long id, struct timespec *timeout)
{
struct umtx_q uq;
- struct timespec ts1, ts2;
+ struct timespec ts, ts2, ts3;
struct timeval tv;
long tmp;
- int timo, error = 0;
+ int error = 0;
if ((error = umtxq_queue_me(td, umtx, &uq)) != 0)
return (error);
@@ -625,7 +627,7 @@ do_wait(struct thread *td, struct umtx *umtx, long id, struct timespec *abstime)
umtxq_lock(&uq.uq_key);
umtxq_remove(&uq);
umtxq_unlock(&uq.uq_key);
- } else if (abstime == NULL) {
+ } else if (timeout == NULL) {
umtxq_lock(&uq.uq_key);
if (td->td_flags & TDF_UMTXQ)
error = umtxq_sleep(td, &uq.uq_key,
@@ -636,31 +638,37 @@ do_wait(struct thread *td, struct umtx *umtx, long id, struct timespec *abstime)
umtxq_remove(&uq);
umtxq_unlock(&uq.uq_key);
} else {
+ getnanouptime(&ts);
+ timespecadd(&ts, timeout);
+ TIMESPEC_TO_TIMEVAL(&tv, timeout);
for (;;) {
- ts1 = *abstime;
- getnanotime(&ts2);
- timespecsub(&ts1, &ts2);
- TIMESPEC_TO_TIMEVAL(&tv, &ts1);
umtxq_lock(&uq.uq_key);
- if (tv.tv_sec < 0) {
- error = ETIMEDOUT;
- break;
- }
- timo = tvtohz(&tv);
- if (td->td_flags & TDF_UMTXQ)
+ if (td->td_flags & TDF_UMTXQ) {
error = umtxq_sleep(td, &uq.uq_key,
td->td_priority | PCATCH,
- "ucond", timo);
- if (error != ETIMEDOUT || !(td->td_flags & TDF_UMTXQ))
- break;
+ "ucond", tvtohz(&tv));
+ }
+ if (!(td->td_flags & TDF_UMTXQ)) {
+ umtxq_unlock(&uq.uq_key);
+ goto out;
+ }
umtxq_unlock(&uq.uq_key);
+ if (error != ETIMEDOUT)
+ break;
+ getnanouptime(&ts2);
+ if (timespeccmp(&ts2, &ts, >=)) {
+ error = ETIMEDOUT;
+ break;
+ }
+ ts3 = ts;
+ timespecsub(&ts3, &ts2);
+ TIMESPEC_TO_TIMEVAL(&tv, &ts3);
}
- if (!(td->td_flags & TDF_UMTXQ))
- error = 0;
- else
- umtxq_remove(&uq);
+ umtxq_lock(&uq.uq_key);
+ umtxq_remove(&uq);
umtxq_unlock(&uq.uq_key);
}
+out:
umtx_key_release(&uq.uq_key);
if (error == ERESTART)
error = EINTR;
@@ -699,7 +707,7 @@ _umtx_unlock(struct thread *td, struct _umtx_unlock_args *uap)
int
_umtx_op(struct thread *td, struct _umtx_op_args *uap)
{
- struct timespec abstime;
+ struct timespec timeout;
struct timespec *ts;
int error;
@@ -709,18 +717,15 @@ _umtx_op(struct thread *td, struct _umtx_op_args *uap)
if (uap->uaddr2 == NULL)
ts = NULL;
else {
- error = copyin(uap->uaddr2, &abstime, sizeof(abstime));
+ error = copyin(uap->uaddr2, &timeout, sizeof(timeout));
if (error != 0)
break;
-#if 0
- printf("uap->abstime: %d.%ld\n", abstime.tv_sec, abstime.tv_nsec);
-#endif
- if (abstime.tv_nsec >= 1000000000 ||
- abstime.tv_nsec < 0) {
+ if (timeout.tv_nsec >= 1000000000 ||
+ timeout.tv_nsec < 0) {
error = EINVAL;
break;
}
- ts = &abstime;
+ ts = &timeout;
}
error = do_lock(td, uap->umtx, uap->id, ts);
break;
@@ -732,15 +737,15 @@ _umtx_op(struct thread *td, struct _umtx_op_args *uap)
if (uap->uaddr2 == NULL)
ts = NULL;
else {
- error = copyin(uap->uaddr2, &abstime, sizeof(abstime));
+ error = copyin(uap->uaddr2, &timeout, sizeof(timeout));
if (error != 0)
break;
- if (abstime.tv_nsec >= 1000000000 ||
- abstime.tv_nsec < 0) {
+ if (timeout.tv_nsec >= 1000000000 ||
+ timeout.tv_nsec < 0) {
error = EINVAL;
break;
}
- ts = &abstime;
+ ts = &timeout;
}
error = do_wait(td, uap->umtx, uap->id, ts);
break;
diff --git a/sys/sys/umtx.h b/sys/sys/umtx.h
index 383829c..4664c4e 100644
--- a/sys/sys/umtx.h
+++ b/sys/sys/umtx.h
@@ -95,11 +95,11 @@ umtx_trylock(struct umtx *umtx, long id)
}
static __inline int
-umtx_timedlock(struct umtx *umtx, long id, const struct timespec *abstime)
+umtx_timedlock(struct umtx *umtx, long id, const struct timespec *timeout)
{
if (atomic_cmpset_acq_ptr(&umtx->u_owner, (void *)UMTX_UNOWNED,
(void *)id) == 0)
- return (- _umtx_op(umtx, UMTX_OP_LOCK, id, 0, (void *)abstime));
+ return (- _umtx_op(umtx, UMTX_OP_LOCK, id, 0, (void *)timeout));
return (0);
}
@@ -113,15 +113,9 @@ umtx_unlock(struct umtx *umtx, long id)
}
static __inline int
-umtx_wait(struct umtx *umtx, long id)
+umtx_wait(struct umtx *umtx, long id, const struct timespec *timeout)
{
- return (- _umtx_op(umtx, UMTX_OP_WAIT, id, 0, 0));
-}
-
-static __inline int
-umtx_timedwait(struct umtx *umtx, long id, const struct timespec *abstime)
-{
- return (- _umtx_op(umtx, UMTX_OP_WAIT, id, 0, (void *)abstime));
+ return (- _umtx_op(umtx, UMTX_OP_WAIT, id, 0, timeout));
}
/* Wake threads waiting on a user address. */
OpenPOWER on IntegriCloud