[parisc-linux] [PATCH] timer_interrupt and gettimeoffset.
Grant Grundler
grundler at parisc-linux.org
Thu Aug 31 15:46:50 MDT 2006
On Thu, Aug 31, 2006 at 02:52:44PM -0400, Carlos O'Donell wrote:
...
> >> 2. No attempt is made to handle cr16 wrapping.
> >
> >The signed math was supposed to handle it.
> >I believe it did but forgot details since looking at
> >it a few years ago.
>
> That is *even* worse, signed arithmetic overflow is compiler
> implementation dependant. It's also therefore not very nice C code.
> The overflow case is in the middle of the 32-bit range now, where you
> had a very large positive number which wraps to a very large negative
> number. The gap is almost the entire 32-bit range, or 27 seconds on a
> 160Mhz box as we have shown already.
I think it's arbitrary where the overflow occurs.
Maybe unsigned math overflow is easier to visualize/understand.
At least it is for me.
> >I personally prefer to NOT use signed math in this case.
> >But that's honestly not a great reason to change this code.
> >I'd really prefer some evidence the kernel code is wrong.
>
> I agree, this patch was an attempt to provide an alternate
> implementation that made sense and was maintainer friendly. I believe
> we should be able to get this working better and handle the failures
> seen on the slower boxes.
Yes. I'm now pretty sure the fix for that will be in gettimeoffset()
and not in timer_interrupt(). But I agree the two functions are very
similar but have to handle slightly different corner cases.
> >13.065388 sec
> >30 Aug 23:52:04 ntpdate[14055]: step time server 195.234.188.26 offset
> >11.578574 sec
> >30 Aug 23:52:31 ntpdate[14058]: step time server 203.217.30.156 offset
> >13.954358 sec
> >...
>
> Technically it is implementation dependant, and can be as low as 1/2
> the peak instruction rate. In correcting timer_interrupt, I remember
> removing what I thought was a spurious 'clocktick' addition in the
> implementation.
I was thinking the opposite: I'm missing a "tick_elapsed" count
on each timer interrupt.
> Does cr16 *actuall* count at the instruction rate, or
> does it count at 1/2 rate?
I _believe_ all implementations count at the actual rate.
At least I'm not aware of any implementations that don't
count at the advertized clock speed.
...
> I think the detection of Scenario 3 is wrong in your patch, I'll
> epxlain further down in the code.
...
>
> >...
> >> I assert that 'gettimeoffset' should never return a negative value. It
> >> represents the postive adjustment accounting for the fact that we are
> >> *part* of the way through a tick.
> >
> >I have to think about this more. But I wonder if how "halftick" is
> >handled in timer_interrupt does not play well with this concept.
>
> There is a bug here because of this, you are right to be warry of the
> halftick adjustment. It is also needed in gettimeoffset, or "now" will
> appear before "next_tick" without wrapping.
Sorry - this didn't make sense. Can you provide an example?
For simplicity assume a 5 bit counter and pick the values
that illustrate your case.
> >Please review and see if I added any new bugs.
>
> There is 1 addtional bug.
...
> >+ /* Determine how much time elapsed. */
> >+ if (now > next_tick) {
> >+ /* Scenario 1: "now" is late. A bit late is normal. */
> >+ ticks_elapsed = (now - next_tick) / clocktick;
> >+ remainder = now - (ticks_elapsed * clocktick);
>
> What have you got against modulo?
Modulo is a division.
Division is much more expensive than integer multiplication.
Is there a way to do the division once _and_ get the remainder?
My assumption that integer multiplication is "cheaper"
could be wrong.
> The correct math is as follows.
>
> remainder = now - next_tick - ticks_elapsed * clocktick;
Erm, no. ticks_elapsed was calculated here:
ticks_elapsed = (now - next_tick) / clocktick;
(the line above.)
I'm taking advantage of truncation since this is integer division.
That make more sense?
> >+ /* "now" is either early or cr16 wrapped. */
> >+ if (~next_tick < clocktick) {
>
> Too clever for me :)
Now I'm worried. :)
I've already removed this code in the version I'm working on now.
...
> >+ } else {
> >+ /* "now" is either early or cr16 wrapped. */
> >+ if (next_next_tick < last_tick) {
>
> This could also use your clever "~next_tick < clocktick" trick.
> Remember this is only a heuristic to catch wrapping.
Yup - I'll post a new version that boots 64-bit correctly in a bit.
I've still not got the "wrapping" rules correct.
...
> Somwhere in thie function we need to makeup for the halftick...
Hrm. I need to think more about that. You might be right.
> Joel has already seen a BUG, which IMO is caused by gettimeoffset not
> taking into account the halftick.
ok. I was just looking at that.
thanks,
grant
More information about the parisc-linux
mailing list