Messages in this thread Patch in this message | | | Subject | Re: [PATCH] correct inconsistent ntp interval/tick_length usage | From | john stultz <> | Date | Tue, 29 Jan 2008 18:14:23 -0800 |
| |
On Tue, 2008-01-29 at 05:02 +0100, Roman Zippel wrote: > Hi, > > On Mon, 28 Jan 2008, john stultz wrote: > > > Regardless, current_tick_length() really is the base interval we're > > using in the error accumulation loop, so it seems the cleanest interface > > to use (just to avoid redundancy at least) when establishing the > > clocksource's interval length. Or do you not agree? > > I see, what you need to use in timex.h for !CONFIG_NO_HZ is: > > #define NTP_INTERVAL_LENGTH ((s64)LATCH * NSEC_PER_SEC) / (s64)CLOCK_TICK_RATE) > > this calculates the base length of a clock tick in nsec. > > current_tick_length() would only work during boot. If you switch clocks > later, it would include random adjustments specific to the old clock.
Ah. Good point. How about the following, tested on x86_64 both with and without CONFIG_NO_HZ?
Thanks for the review and feedback! -john
Correct NTP drift caused by using inconsistent NTP_INTERVAL_LENGTHs in clocksource initialization and error accumulation. This corrects a 280ppm drift seen on some systems using acpi_pm, and affects other clocksources as well (likely to a lesser degree).
Signed-off-by: John Stultz <johnstul@us.ibm.com>
Index: linux/include/linux/timex.h =================================================================== --- linux.orig/include/linux/timex.h +++ linux/include/linux/timex.h @@ -231,7 +231,13 @@ static inline int ntp_synced(void) #else #define NTP_INTERVAL_FREQ (HZ) #endif -#define NTP_INTERVAL_LENGTH (NSEC_PER_SEC/NTP_INTERVAL_FREQ) + +#define CLOCK_TICK_OVERFLOW (LATCH * HZ - CLOCK_TICK_RATE) +#define CLOCK_TICK_ADJUST (((s64)CLOCK_TICK_OVERFLOW * NSEC_PER_SEC) / \ + (s64)CLOCK_TICK_RATE) + +/* Because using NSEC_PER_SEC would be too easy */ +#define NTP_INTERVAL_LENGTH ((((s64)TICK_USEC*NSEC_PER_USEC*USER_HZ)+CLOCK_TICK_ADJUST)/NTP_INTERVAL_FREQ) /* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */ extern u64 current_tick_length(void); Index: linux/kernel/time/ntp.c =================================================================== --- linux.orig/kernel/time/ntp.c +++ linux/kernel/time/ntp.c @@ -43,10 +43,6 @@ long time_freq; /* frequency offset ( static long time_reftime; /* time at last adjustment (s) */ long time_adjust; -#define CLOCK_TICK_OVERFLOW (LATCH * HZ - CLOCK_TICK_RATE) -#define CLOCK_TICK_ADJUST (((s64)CLOCK_TICK_OVERFLOW * NSEC_PER_SEC) / \ - (s64)CLOCK_TICK_RATE) - static void ntp_update_frequency(void) { u64 second_length = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ)
| |