From 8d466dd80c156a33c508154f83e1907ef7087e5c Mon Sep 17 00:00:00 2001 From: cheloha Date: Fri, 11 Jun 2021 16:36:34 +0000 Subject: [PATCH] setitimer(2): don't round up it_value We can reduce latency for the first expiration of a timer if we don't round it_value up to the minimum interval (1 tick). While we're at it, we may as well consolidate all input validation and adjustment into a single itimerfix() call. There are no other callers in the kernel (nor should there be), so remove the prototype from sys/time.h. Discussion: https://marc.info/?l=openbsd-tech&m=162084338005502&w=2 Tested by weerd@ and claudio@. probably ok claudio@ --- sys/kern/kern_time.c | 40 ++++++++++++++++++++++++++-------------- sys/sys/time.h | 3 +-- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c index 37771cc02f0..7a6febf4fb7 100644 --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_time.c,v 1.152 2021/05/31 12:45:33 visa Exp $ */ +/* $OpenBSD: kern_time.c,v 1.153 2021/06/11 16:36:34 cheloha Exp $ */ /* $NetBSD: kern_time.c,v 1.20 1996/02/18 11:57:06 fvdl Exp $ */ /* @@ -52,6 +52,8 @@ #include +int itimerfix(struct itimerval *); + /* * Time of day and interval timer support. * @@ -628,10 +630,9 @@ sys_setitimer(struct proc *p, void *v, register_t *retval) error = copyin(SCARG(uap, itv), &aitv, sizeof(aitv)); if (error) return error; - if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval)) - return EINVAL; - if (!timerisset(&aitv.it_value)) - timerclear(&aitv.it_interval); + error = itimerfix(&aitv); + if (error) + return error; newitvp = &aitv; } if (SCARG(uap, oitv) != NULL) { @@ -701,21 +702,32 @@ out: } /* - * Check that a proposed value to load into the .it_value or - * .it_interval part of an interval timer is acceptable. + * Check if the given setitimer(2) input is valid. Clear it_interval + * if it_value is unset. Round it_interval up to the minimum interval + * if necessary. */ int -itimerfix(struct timeval *tv) +itimerfix(struct itimerval *itv) { + struct timeval min_interval = { .tv_sec = 0, .tv_usec = tick }; - if (tv->tv_sec < 0 || tv->tv_sec > 100000000 || - tv->tv_usec < 0 || tv->tv_usec >= 1000000) - return (EINVAL); + if (itv->it_value.tv_sec < 0 || !timerisvalid(&itv->it_value)) + return EINVAL; + if (itv->it_value.tv_sec > 100000000) + return EINVAL; + if (itv->it_interval.tv_sec < 0 || !timerisvalid(&itv->it_interval)) + return EINVAL; + if (itv->it_interval.tv_sec > 100000000) + return EINVAL; - if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick) - tv->tv_usec = tick; + if (!timerisset(&itv->it_value)) + timerclear(&itv->it_interval); + if (timerisset(&itv->it_interval)) { + if (timercmp(&itv->it_interval, &min_interval, <)) + itv->it_interval = min_interval; + } - return (0); + return 0; } /* diff --git a/sys/sys/time.h b/sys/sys/time.h index e5cd4eba727..019ea8153ea 100644 --- a/sys/sys/time.h +++ b/sys/sys/time.h @@ -1,4 +1,4 @@ -/* $OpenBSD: time.h,v 1.58 2021/01/13 16:28:50 cheloha Exp $ */ +/* $OpenBSD: time.h,v 1.59 2021/06/11 16:36:34 cheloha Exp $ */ /* $NetBSD: time.h,v 1.18 1996/04/23 10:29:33 mycroft Exp $ */ /* @@ -307,7 +307,6 @@ struct proc; int clock_gettime(struct proc *, clockid_t, struct timespec *); void cancel_all_itimers(void); -int itimerfix(struct timeval *); int itimerdecr(struct itimerspec *, long); int settime(const struct timespec *); int ratecheck(struct timeval *, const struct timeval *); -- 2.20.1