summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_umtx.c
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2012-08-11 00:06:56 +0000
committerdavidxu <davidxu@FreeBSD.org>2012-08-11 00:06:56 +0000
commit43c8a8efc2fbdafcc2aa3163f8c3efd8a863f25c (patch)
tree39220f0ec7aade78f1cc55e476bc9f08f525fee5 /sys/kern/kern_umtx.c
parent5b837de0b30c64efe81d5ee95949ecc3ce5978c9 (diff)
downloadFreeBSD-src-43c8a8efc2fbdafcc2aa3163f8c3efd8a863f25c.zip
FreeBSD-src-43c8a8efc2fbdafcc2aa3163f8c3efd8a863f25c.tar.gz
tvtohz will print out an error message if a negative value is given
to it, avoid this problem by detecting timeout earlier. Reported by: pho
Diffstat (limited to 'sys/kern/kern_umtx.c')
-rw-r--r--sys/kern/kern_umtx.c22
1 files changed, 13 insertions, 9 deletions
diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c
index 534a3c3..e5994c8 100644
--- a/sys/kern/kern_umtx.c
+++ b/sys/kern/kern_umtx.c
@@ -587,11 +587,10 @@ abs_timeout_init2(struct abs_timeout *timo, const struct _umtx_time *umtxtime)
&umtxtime->_timeout);
}
-static int
+static void
abs_timeout_update(struct abs_timeout *timo)
{
kern_clock_gettime(curthread, timo->clockid, &timo->cur);
- return (timespeccmp(&timo->cur, &timo->end, >=));
}
static int
@@ -601,6 +600,8 @@ abs_timeout_gethz(struct abs_timeout *timo)
tts = timo->end;
timespecsub(&tts, &timo->cur);
+ if (tts.tv_sec < 0 || (tts.tv_sec == 0 && tts.tv_nsec == 0))
+ return (-1);
return (tstohz(&tts));
}
@@ -613,22 +614,25 @@ umtxq_sleep(struct umtx_q *uq, const char *wmesg, struct abs_timeout *timo)
{
struct umtxq_chain *uc;
int error;
+ int pulse;
uc = umtxq_getchain(&uq->uq_key);
UMTXQ_LOCKED_ASSERT(uc);
for (;;) {
if (!(uq->uq_flags & UQF_UMTXQ))
return (0);
- error = msleep(uq, &uc->uc_lock, PCATCH, wmesg,
- timo == NULL ? 0 : abs_timeout_gethz(timo));
- if (error != EWOULDBLOCK)
- break;
- umtxq_unlock(&uq->uq_key);
- if (abs_timeout_update(timo)) {
- error = ETIMEDOUT;
+ if (timo != NULL) {
+ pulse = abs_timeout_gethz(timo);
+ if (pulse < 0)
+ return (ETIMEDOUT);
+ } else
+ pulse = 0;
+ error = msleep(uq, &uc->uc_lock, PCATCH|PDROP, wmesg, pulse);
+ if (error != EWOULDBLOCK) {
umtxq_lock(&uq->uq_key);
break;
}
+ abs_timeout_update(timo);
umtxq_lock(&uq->uq_key);
}
return (error);
OpenPOWER on IntegriCloud