svn commit: r247898 - head/sys/kern
Alexander Motin
mav at FreeBSD.org
Wed Mar 6 19:37:39 UTC 2013
Author: mav
Date: Wed Mar 6 19:37:38 2013
New Revision: 247898
URL: http://svnweb.freebsd.org/changeset/base/247898
Log:
Fix time math overflows and improve zero intervals handling in poll(),
select(), nanosleep() and kevent() functions after calloutng changes.
Reported by: bde
Modified:
head/sys/kern/kern_event.c
head/sys/kern/kern_time.c
head/sys/kern/sys_generic.c
Modified: head/sys/kern/kern_event.c
==============================================================================
--- head/sys/kern/kern_event.c Wed Mar 6 18:45:11 2013 (r247897)
+++ head/sys/kern/kern_event.c Wed Mar 6 19:37:38 2013 (r247898)
@@ -1329,11 +1329,16 @@ kqueue_scan(struct kqueue *kq, int maxev
goto done_nl;
}
if (timespecisset(tsp)) {
- rsbt = tstosbt(*tsp);
- if (TIMESEL(&asbt, rsbt))
- asbt += tc_tick_sbt;
- asbt += rsbt;
- rsbt >>= tc_precexp;
+ if (tsp->tv_sec < INT32_MAX) {
+ rsbt = tstosbt(*tsp);
+ if (TIMESEL(&asbt, rsbt))
+ asbt += tc_tick_sbt;
+ asbt += rsbt;
+ if (asbt < rsbt)
+ asbt = 0;
+ rsbt >>= tc_precexp;
+ } else
+ asbt = 0;
} else
asbt = -1;
} else
Modified: head/sys/kern/kern_time.c
==============================================================================
--- head/sys/kern/kern_time.c Wed Mar 6 18:45:11 2013 (r247897)
+++ head/sys/kern/kern_time.c Wed Mar 6 19:37:38 2013 (r247898)
@@ -484,13 +484,20 @@ kern_nanosleep(struct thread *td, struct
{
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
TIMESEL(&sbtt, tmp);
if (rmt != NULL) {
ts = sbttots(sbt - sbtt);
+ ts.tv_sec += over;
if (ts.tv_sec < 0)
timespecclear(&ts);
*rmt = ts;
Modified: head/sys/kern/sys_generic.c
==============================================================================
--- head/sys/kern/sys_generic.c Wed Mar 6 18:45:11 2013 (r247897)
+++ head/sys/kern/sys_generic.c Wed Mar 6 19:37:38 2013 (r247898)
@@ -1051,12 +1051,19 @@ kern_select(struct thread *td, int nd, f
error = EINVAL;
goto done;
}
- rsbt = tvtosbt(rtv);
- precision = rsbt;
- precision >>= tc_precexp;
- if (TIMESEL(&asbt, rsbt))
- asbt += tc_tick_sbt;
- asbt += rsbt;
+ if (rtv.tv_sec == 0 && rtv.tv_usec == 0)
+ asbt = 0;
+ else if (rtv.tv_sec < INT32_MAX) {
+ rsbt = tvtosbt(rtv);
+ precision = rsbt;
+ precision >>= tc_precexp;
+ if (TIMESEL(&asbt, rsbt))
+ asbt += tc_tick_sbt;
+ asbt += rsbt;
+ if (asbt < rsbt)
+ asbt = -1;
+ } else
+ asbt = -1;
} else
asbt = -1;
seltdinit(td);
@@ -1295,12 +1302,16 @@ sys_poll(td, uap)
error = EINVAL;
goto done;
}
- rsbt = SBT_1MS * uap->timeout;
- precision = rsbt;
- precision >>= tc_precexp;
- if (TIMESEL(&asbt, rsbt))
- asbt += tc_tick_sbt;
- asbt += rsbt;
+ if (uap->timeout == 0)
+ asbt = 0;
+ else {
+ rsbt = SBT_1MS * uap->timeout;
+ precision = rsbt;
+ precision >>= tc_precexp;
+ if (TIMESEL(&asbt, rsbt))
+ asbt += tc_tick_sbt;
+ asbt += rsbt;
+ }
} else
asbt = -1;
seltdinit(td);
More information about the svn-src-head
mailing list