diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index 82db54e17b7a..3c8826c9a7ab 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -1329,11 +1329,16 @@ kqueue_scan(struct kqueue *kq, int maxevents, struct kevent_copyops *k_ops, 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 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; diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index 3893515d3e53..2d149b5f6944 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -1051,12 +1051,19 @@ kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou, 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);