> I have a question about the routine below. The routine is a Pentium
> specific microtime() routine. I'm afraid it is not correct. See my
> "???" tag at the beginning of a line. If someone can tell me, if I'm
> wrong, I'd like to hear it!
i noticed another thing. The routine does 2 divisions and 1
multiplication. But last_timer_cc changes only in pentium_timer_interrupt(),
so two divisions could be taken out of do_fast_gettimeoffset, and put into
pentium_timer_interrupt. This makes gettimeofday() faster.
could the author comment on this? (sigh, couldnt find out who did this
piece of code)
> time_low -= (unsigned long) last_timer_cc;
> ??? We have two 64 bit quantities, and we are interested in the least
> ??? significant 32 bit. Currently just the "low longwords" are
> ??? subtracted, yielding a possible overflow (result in unsigned).
> ??? Usually you would need some carry processing.
yeah. thats a bug.
> if (quotient >= 1000000/HZ)
> quotient = 1000000/HZ-1;
>
> ??? Is this the correction for the missed carry?
the error is still there.
This is how the function works:
--------------------------------------------------- time -->
| | |
boot last timer tick now
init_timer_cc last_timer_cc time_high.time_low <- pentium timer
0 jiffies <- jiffies value
last_timer_cc is set each timer interrupt.
init_timer_cc is set at boot (exactly when jiffies is set to zero).
jiffies is increased each timer interrupt, and starts from zero.
to calculate the actual time in usecs, the following algorithm is used:
do_fast_gettimeofday() returns the usecs since the last timer interrupt
(jiffies tick).
usecs := usecs_per_jiffie * delta_clocks / clocks_per_jiffie
delta_clocks are the clocks since the last timer interrupt:
delta_clocks := current_clocks - last_timer_cc
clocks_per_jiffie is:
clocks_per_jiffie := last_timer_cc / jiffies
So, this is enough to calculate the return value. When the overflow
happens, the following value is calculated:
usecs := usecs_per_jiffie * (4G-delta_clocks) / clocks_per_jiffie
This is MUCH bigger than 1000000/Hz, so the return value is set to
1000000/Hz.
The check for usecs < 1000000 is still valid, because the time source is
not the timer interrupt source => problems right before the next jiffie.
IMHO, this should be corrected NOT by setting the offset to 1000000, but
by drifting the time => less dramatic changes to the derivate (f'(x)) of
the time. The current solution makes it only monotonous, which is not
enough if used for serious applications. (and it affects gettimeofday())
( sometimes you can get the same gettimeofday() if called twice ... )
-- mingo