lkml.org 
[lkml]   [2006]   [Oct]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch 01/21] GTOD: exponential update_wall_time
    From: John Stultz <johnstul@us.ibm.com>

    Accumulate time in update_wall_time() exponentially. This avoids long
    running loops seen with the dynticks patch as well as the problematic
    hang seen on systems with broken clocksources.

    NOTE: this only has relevance on dyntick kernels, so the quality of
    NTP updates on jiffies-tick systems is unaffected. (non-dyntick
    kernels call update_wall_time() in every timer tick)

    Signed-off-by: John Stultz <johnstul@us.ibm.com>
    Signed-off-by: Ingo Molnar <mingo@elte.hu>
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
    --

    kernel/timer.c | 28 ++++++++++++++++++++--------
    1 file changed, 20 insertions(+), 8 deletions(-)
    Index: linux-2.6.18-mm2/kernel/timer.c
    ===================================================================
    --- linux-2.6.18-mm2.orig/kernel/timer.c 2006-10-02 00:55:50.000000000 +0200
    +++ linux-2.6.18-mm2/kernel/timer.c 2006-10-02 00:55:50.000000000 +0200
    @@ -907,6 +907,7 @@ static void clocksource_adjust(struct cl
    static void update_wall_time(void)
    {
    cycle_t offset;
    + int shift = 0;

    /* Make sure we're fully resumed: */
    if (unlikely(timekeeping_suspended))
    @@ -919,28 +920,39 @@ static void update_wall_time(void)
    #endif
    clock->xtime_nsec += (s64)xtime.tv_nsec << clock->shift;

    + while (offset > clock->cycle_interval << (shift + 1))
    + shift++;
    +
    /* normally this loop will run just once, however in the
    * case of lost or late ticks, it will accumulate correctly.
    */
    while (offset >= clock->cycle_interval) {
    + if (offset < (clock->cycle_interval << shift)) {
    + shift--;
    + continue;
    + }
    +
    /* accumulate one interval */
    - clock->xtime_nsec += clock->xtime_interval;
    - clock->cycle_last += clock->cycle_interval;
    - offset -= clock->cycle_interval;
    + clock->xtime_nsec += clock->xtime_interval << shift;
    + clock->cycle_last += clock->cycle_interval << shift;
    + offset -= clock->cycle_interval << shift;

    - if (clock->xtime_nsec >= (u64)NSEC_PER_SEC << clock->shift) {
    + while (clock->xtime_nsec >= (u64)NSEC_PER_SEC << clock->shift) {
    clock->xtime_nsec -= (u64)NSEC_PER_SEC << clock->shift;
    xtime.tv_sec++;
    second_overflow();
    }

    /* interpolator bits */
    - time_interpolator_update(clock->xtime_interval
    - >> clock->shift);
    + time_interpolator_update((clock->xtime_interval
    + >> clock->shift)<<shift);

    /* accumulate error between NTP and clock interval */
    - clock->error += current_tick_length();
    - clock->error -= clock->xtime_interval << (TICK_LENGTH_SHIFT - clock->shift);
    + clock->error += current_tick_length() << shift;
    + clock->error -= (clock->xtime_interval
    + << (TICK_LENGTH_SHIFT - clock->shift))<<shift;
    +
    + shift--;
    }

    /* correct the clock when NTP error is too big */
    --

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2006-10-02 01:09    [from the cache]
    ©2003-2011 Jasper Spaans