aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/kern_time.c
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2013-03-06 19:37:38 +0000
committerAlexander Motin <mav@FreeBSD.org>2013-03-06 19:37:38 +0000
commit980c545d7662978813155da54c0c267e3371f4e3 (patch)
treee0014e3ceb1c3b632a8085f56d508783b74abf8c /sys/kern/kern_time.c
parent9461964cc921d1f1f8de9251ac061c1669e21258 (diff)
downloadsrc-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.c10
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;