Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=bbe4d18ac2e058c56adb0cd71f49d9ed3216a405
Commit:     bbe4d18ac2e058c56adb0cd71f49d9ed3216a405
Parent:     37a47db8d7f0f38dac5acf5a13abbc8f401707fa
Author:     john stultz <[EMAIL PROTECTED]>
AuthorDate: Wed Jan 30 13:30:03 2008 +0100
Committer:  Ingo Molnar <[EMAIL PROTECTED]>
CommitDate: Wed Jan 30 13:30:03 2008 +0100

    NTP: correct inconsistent ntp interval/tick_length usage
    
    I recently noticed on one of my boxes that when synched with an NTP
    server, the drift value reported for the system was ~283ppm. While in
    some cases, clock hardware can be that bad, it struck me as unusual as
    the system was using the acpi_pm clocksource, which is one of the more
    trustworthy and accurate clocksources on x86 hardware.
    
    I brought up another system and let it sync to the same NTP server, and
    I noticed a similar 280some ppm drift.
    
    In looking at the code, I found that the acpi_pm's constant frequency
    was being computed correctly at boot-up, however once the system was up,
    even without the ntp daemon running, the clocksource's frequency was
    being modified by the clocksource_adjust() function.
    
    Digging deeper, I realized that in the code that keeps track of how much
    the clocksource is skewing from the ntp desired time, we were using
    different lengths to establish how long an time interval was.
    
    The clocksource was being setup with the following interval:
        NTP_INTERVAL_LENGTH = NSEC_PER_SEC/NTP_INTERVAL_FREQ
    
    While the ntp code was using the tick_length_base value:
        tick_length_base ~= (tick_usec * NSEC_PER_USEC * USER_HZ)
                                        /NTP_INTERVAL_FREQ
    
    The subtle difference is:
        (tick_usec * NSEC_PER_USEC * USER_HZ) != NSEC_PER_SEC
    
    This difference in calculation was causing the clocksource correction
    code to apply a correction factor to the clocksource so the two
    intervals were the same, however this results in the actual frequency of
    the clocksource to be made incorrect. I believe this difference would
    affect all clocksources, although to differing degrees depending on the
    clocksource resolution.
    
    The issue was introduced when my HZ free ntp patch landed in 2.6.21-rc1,
    so my apologies for the mistake, and for not noticing it until now.
    
    The following patch, corrects the clocksource's initialization code so
    it uses the same interval length as the code in ntp.c. After applying
    this patch, the drift value for the same system went from ~283ppm to
    only 2.635ppm.
    
    I believe this patch to be good, however it does affect all arches and
    I've only tested on x86, so some caution is advised. I do think it would
    be a likely candidate for a stable 2.6.24.x release.
    
    Any thoughts or feedback would be appreciated.
    
    Signed-off-by: John Stultz <[EMAIL PROTECTED]>
    Signed-off-by: Ingo Molnar <[EMAIL PROTECTED]>
    Signed-off-by: Thomas Gleixner <[EMAIL PROTECTED]>
---
 kernel/time/timekeeping.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 7768019..092a236 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -186,7 +186,8 @@ static void change_clocksource(void)
 
        clock->error = 0;
        clock->xtime_nsec = 0;
-       clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
+       clocksource_calculate_interval(clock,
+               (unsigned long)(current_tick_length()>>TICK_LENGTH_SHIFT));
 
        tick_clock_notify();
 
@@ -243,7 +244,8 @@ void __init timekeeping_init(void)
        ntp_clear();
 
        clock = clocksource_get_next();
-       clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
+       clocksource_calculate_interval(clock,
+               (unsigned long)(current_tick_length()>>TICK_LENGTH_SHIFT));
        clock->cycle_last = clocksource_read(clock);
 
        xtime.tv_sec = sec;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to