Page MenuHomeFreeBSD

D36859.id111419.diff
No OneTemporary

D36859.id111419.diff

diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c
--- a/sys/kern/kern_clock.c
+++ b/sys/kern/kern_clock.c
@@ -556,60 +556,39 @@
}
/*
- * Compute number of ticks in the specified amount of time.
+ * Compute number of ticks representing the specified amount of time.
+ * If the specified time is negative, a value of 1 is returned. This
+ * function returns a value from 1 up to and including INT_MAX.
*/
int
tvtohz(struct timeval *tv)
{
- unsigned long ticks;
- long sec, usec;
+ int64_t retval;
+
+ /* range check tv_sec so the multiplication below doesn't overflow */
+ if (__predict_false(tv->tv_sec > INT_MAX))
+ return (INT_MAX);
+ else if (__predict_false(tv->tv_sec < 0))
+ return (1);
/*
- * If the number of usecs in the whole seconds part of the time
- * difference fits in a long, then the total number of usecs will
- * fit in an unsigned long. Compute the total and convert it to
- * ticks, rounding up and adding 1 to allow for the current tick
- * to expire. Rounding also depends on unsigned long arithmetic
- * to avoid overflow.
- *
- * Otherwise, if the number of ticks in the whole seconds part of
- * the time difference fits in a long, then convert the parts to
- * ticks separately and add, using similar rounding methods and
- * overflow avoidance. This method would work in the previous
- * case but it is slightly slower and assumes that hz is integral.
- *
- * Otherwise, round the time difference down to the maximum
- * representable value.
- *
- * If ints have 32 bits, then the maximum value for any timeout in
- * 10ms ticks is 248 days.
+ * Convert to ticks. The cast to 32-bit tells the compiler on
+ * 32-bit platforms it can use a regular 32-bit multiplication
+ * with 64-bit result as an optimization, instead of a full
+ * 64-bit multiplication.
*/
- sec = tv->tv_sec;
- usec = tv->tv_usec;
- if (usec < 0) {
- sec--;
- usec += 1000000;
- }
- if (sec < 0) {
-#ifdef DIAGNOSTIC
- if (usec > 0) {
- sec++;
- usec -= 1000000;
- }
- printf("tvotohz: negative time difference %ld sec %ld usec\n",
- sec, usec);
-#endif
- ticks = 1;
- } else if (sec <= LONG_MAX / 1000000)
- ticks = howmany(sec * 1000000 + (unsigned long)usec, tick) + 1;
- else if (sec <= LONG_MAX / hz)
- ticks = sec * hz
- + howmany((unsigned long)usec, tick) + 1;
- else
- ticks = LONG_MAX;
- if (ticks > INT_MAX)
- ticks = INT_MAX;
- return ((int)ticks);
+ retval =
+ (int64_t)(int32_t)tv->tv_sec * (int64_t)hz +
+ (int64_t)(int32_t)tv->tv_usec * (int64_t)hz / 1000000;
+
+ /* range check */
+ if (__predict_false(retval > INT_MAX - 1))
+ return (INT_MAX);
+ else if (__predict_false(retval < 0))
+ return (1);
+
+ /* add one additional tick */
+ return ((int)retval + 1);
}
/*

File Metadata

Mime Type
text/plain
Expires
Sun, May 17, 2:29 AM (4 h, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33167835
Default Alt Text
D36859.id111419.diff (2 KB)

Event Timeline