Skip to content

Commit

Permalink
New hzto() function from FreeBSD and Artur Grabowski <[email protected]
Browse files Browse the repository at this point in the history
….se>.

Stops sleeps from returning early (by up to a clock tick), and return 0
ticks for timeouts that should happen now or in the past.

Returning 0 is different from the legacy hzto() interface, and callers
need to check for it.
  • Loading branch information
thorpej committed Jul 13, 2000
1 parent 7033f77 commit 11feecc
Showing 1 changed file with 47 additions and 21 deletions.
68 changes: 47 additions & 21 deletions sys/kern/kern_clock.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $NetBSD: kern_clock.c,v 1.61 2000/06/27 17:41:15 mrg Exp $ */
/* $NetBSD: kern_clock.c,v 1.62 2000/07/13 17:06:15 thorpej Exp $ */

/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
Expand Down Expand Up @@ -1110,34 +1110,60 @@ int
hzto(tv)
struct timeval *tv;
{
long ticks, sec;
unsigned long ticks;
long sec, usec;
int s;

/*
* If number of microseconds will fit in 32 bit arithmetic,
* then compute number of microseconds to time and scale to
* ticks. Otherwise just compute number of hz in time, rounding
* times greater than representible to maximum value. (We must
* compute in microseconds, because hz can be greater than 1000,
* and thus tick can be less than one millisecond).
* 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 14 hours can be computed ``exactly''.
* (Note that if hz would yeild a non-integral number of us per
* tick, i.e. tickfix is nonzero, timouts can be a tick longer
* than they should be.) 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 assume that hz is integral.
*
* Otherwise, round the time difference down to the maximum
* representable value.
*
* If ints are 32-bit, then the maximum value for any timeout in
* 10ms ticks is 248 days.
*/
s = splclock();
sec = tv->tv_sec - time.tv_sec;
if (sec <= 0x7fffffff / 1000000 - 1)
ticks = ((tv->tv_sec - time.tv_sec) * 1000000 +
(tv->tv_usec - time.tv_usec)) / tick;
else if (sec <= 0x7fffffff / hz)
ticks = sec * hz;
else
ticks = 0x7fffffff;
usec = tv->tv_usec - time.tv_usec;
splx(s);
return (ticks);

if (usec < 0) {
sec--;
usec += 1000000;
}

if (sec < 0 || (sec == 0 && usec <= 0)) {
/*
* Would expire now or in the past. Return 0 ticks.
* This is different from the legacy hzto() interface,
* and callers need to check for it.
*/
ticks = 0;
} 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 ((int)ticks);
}

/*
Expand Down

0 comments on commit 11feecc

Please sign in to comment.