diff options
author | Alexander Motin <mav@FreeBSD.org> | 2013-03-06 19:37:38 +0000 |
---|---|---|
committer | Alexander Motin <mav@FreeBSD.org> | 2013-03-06 19:37:38 +0000 |
commit | 980c545d7662978813155da54c0c267e3371f4e3 (patch) | |
tree | e0014e3ceb1c3b632a8085f56d508783b74abf8c /sys/kern/kern_time.c | |
parent | 9461964cc921d1f1f8de9251ac061c1669e21258 (diff) | |
download | src-980c545d7662978813155da54c0c267e3371f4e3.tar.gz src-980c545d7662978813155da54c0c267e3371f4e3.zip |
Fix time math overflows and improve zero intervals handling in poll(),
select(), nanosleep() and kevent() functions after calloutng changes.
Reported by: bde
Notes
Notes:
svn path=/head/; revision=247898
Diffstat (limited to 'sys/kern/kern_time.c')
-rw-r--r-- | sys/kern/kern_time.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c index da511069c18e..9eb22c89bfd7 100644 --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -484,13 +484,20 @@ kern_nanosleep(struct thread *td, struct timespec *rqt, struct timespec *rmt) { struct timespec ts; sbintime_t sbt, sbtt, prec, tmp; + time_t over; int error; if (rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000) return (EINVAL); if (rqt->tv_sec < 0 || (rqt->tv_sec == 0 && rqt->tv_nsec == 0)) return (0); - tmp = tstosbt(*rqt); + ts = *rqt; + if (ts.tv_sec > INT32_MAX / 2) { + over = ts.tv_sec - INT32_MAX / 2; + ts.tv_sec -= over; + } else + over = 0; + tmp = tstosbt(ts); prec = tmp; prec >>= tc_precexp; if (TIMESEL(&sbt, tmp)) @@ -504,6 +511,7 @@ kern_nanosleep(struct thread *td, struct timespec *rqt, struct timespec *rmt) TIMESEL(&sbtt, tmp); if (rmt != NULL) { ts = sbttots(sbt - sbtt); + ts.tv_sec += over; if (ts.tv_sec < 0) timespecclear(&ts); *rmt = ts; |