diff options
author | davidxu <davidxu@FreeBSD.org> | 2012-08-11 00:06:56 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2012-08-11 00:06:56 +0000 |
commit | 43c8a8efc2fbdafcc2aa3163f8c3efd8a863f25c (patch) | |
tree | 39220f0ec7aade78f1cc55e476bc9f08f525fee5 /sys/kern/kern_umtx.c | |
parent | 5b837de0b30c64efe81d5ee95949ecc3ce5978c9 (diff) | |
download | FreeBSD-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.c | 22 |
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); |