Messages in this thread | | | Date | Sun, 28 Apr 1996 23:08:10 -0400 (EDT) | From | Molnar Ingo <> | Subject | Re: do_fast_gettimeoffset(void) buggy? (YES) |
| |
On Fri, 26 Apr 1996, Ulrich Windl wrote:
> 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
| |