Messages in this thread | | | Subject | Re: Problem with kernel-pll in 2.0.3x (at least) | Date | Fri, 01 May 1998 07:33:07 +0100 | From | Jon Peatfield <> |
| |
> I have no alpha, but isn't the tick changed once per second, or > something like that (no source here...)?
Well looking though various files in linux/kernel/ I don't really understand all that is going on, sched.c for example has code #ifdef'd on HZ being 100 to perform some clever fix.
However, taking a trivial belief in the workings (that the clock is updated by tick uS every timer interrupt (i.e. HZ times per sec)) I estimate the following:
tick = 1000000 / 1024 = 976.56250 -> tick is actually set to 977, so in 1 second time is updated by 977 * 1024 uS which is 1000448 which is 448ppm too fast.
Running xntpd3-5.93 modified to use the kernel-pll with the MAXFREQ set to 2048 (rather than the default 200ppm) the system stabelised after a few hours with freq set to -438.308 ppm which is close enough for me to believe this is really what is happening in the kernel.
Now being fast by 448ppm would mean that unchecked the clock would drift by ~30seconds per day which doesn't seem to happen (though I've probably not left one up without some ntp daemon for long enough to be sure), so the code may be different when the kernel-pll is in use.
A bit more digging shows the following definitions in sched.c:
long tick = (1000000 + HZ/2) / HZ; /* timer interrupt period */ int tickadj = 500/HZ; /* microsecs */ long time_freq = ((1000000 + HZ/2) % HZ - HZ/2) << SHIFT_USEC; /* frequency offset (scaled ppm) */
when HZ is 100 tickadj is 5, but once HZ is over 500 this is zero (is that right?) The time_freq is very interesting, at HZ=100 it is 0, and at HZ=1024 this sets time_freq to -448 just as I would (though I'd bracket it up a bit to make it clear that the % binds more tightly than the - since I misread it the first few times (it is early here, and I'm not wide awake yet).
Looking at another of our machines which is running an xntpd not using kernel-pll and asking adjtimex() what freq is gives me -448ppm (though xntpd thinks it has set it to 17.052 ppm, in fact the clock is drifting slowly on this machine ~1 seconds a day).
Aha, but when using the kernel-pll xntpd starts by setting the pll freq to the value from ntp.drift which will probably be 0 (or close to it) unless ntp has already been running. This means that the value for drift is different when the kernel-pll is used .vs. an external pll xntpd if 1000000 is not divisible by HZ!
In any case clearly freq needs to be able to reach at least the value it is set to by default by the kernel which is of order HZ/2, you also need a little slack in case the clock is jittering between 2 values on either side of changing tick, hence the original 200ppm for a 100hz clock.
I'm now very happy with why MAXFREQ needs to be able to span more than HZ, if you know a cleaner way to change the headers to allow this I'd be happy to use it...
Perhaps HZ + 100 is actually enough for all cases, so the code would be:
#define MAXFREQ ((HZ + 100L) << SHIFT_USEC) /* max frequency error (ppm) */
(or HZ + HZ which at least doesn't have the dreaded multiplication in it).
[ Ian, I'll put this modified kernel on thor lather this morning if no-one is running big code on it. I'll also finish up my mods to xntpd3-5.93 and put the RPM up somewhere useful. ]
-- Jon
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu
| |