summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_timeout.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/kern_timeout.c')
-rw-r--r--sys/kern/kern_timeout.c58
1 files changed, 42 insertions, 16 deletions
diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c
index 35e119b..c1ff1bd 100644
--- a/sys/kern/kern_timeout.c
+++ b/sys/kern/kern_timeout.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)kern_clock.c 8.5 (Berkeley) 1/21/94
- * $Id: kern_clock.c,v 1.9 1994/10/02 17:35:10 phk Exp $
+ * $Id: kern_clock.c,v 1.10 1994/10/16 03:52:12 wollman Exp $
*/
/* Portions of this software are covered by the following: */
@@ -748,28 +748,54 @@ int
hzto(tv)
struct timeval *tv;
{
- register long ticks, sec;
+ register unsigned long ticks;
+ register long sec, usec;
int s;
/*
- * If number of milliseconds will fit in 32 bit arithmetic,
- * then compute number of milliseconds to time and scale to
- * ticks. Otherwise just compute number of hz in time, rounding
- * times greater than representible to maximum value.
+ * 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.
*
- * Delta times less than 25 days can be computed ``exactly''.
- * Maximum value for any timeout in 10ms ticks is 250 days.
+ * 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.
*/
- s = splhigh();
+ s = splclock();
sec = tv->tv_sec - time.tv_sec;
- if (sec <= 0x7fffffff / 1000 - 1000)
- ticks = ((tv->tv_sec - time.tv_sec) * 1000 +
- (tv->tv_usec - time.tv_usec) / 1000) / (tick / 1000);
- else if (sec <= 0x7fffffff / hz)
- ticks = sec * hz;
- else
- ticks = 0x7fffffff;
+ usec = tv->tv_usec - time.tv_usec;
splx(s);
+ if (usec < 0) {
+ sec--;
+ usec += 1000000;
+ }
+ if (sec < 0) {
+#ifdef DIAGNOSTIC
+ printf("hzto: negative time difference %ld sec %ld usec\n",
+ sec, usec);
+#endif
+ ticks = 1;
+ } else if (sec <= LONG_MAX / 1000000)
+ ticks = (sec * 1000000 + (unsigned long)usec + (tick - 1))
+ / tick + 1;
+ else if (sec <= LONG_MAX / hz)
+ ticks = sec * hz
+ + ((unsigned long)usec + (tick - 1)) / tick + 1;
+ else
+ ticks = LONG_MAX;
+ if (ticks > INT_MAX)
+ ticks = INT_MAX;
return (ticks);
}
OpenPOWER on IntegriCloud