On 12/07/2013 09:56 AM, Richard Cochran wrote: > On Fri, Dec 06, 2013 at 05:43:45PM -0800, John Stultz wrote: >> Anyway, let me know what you think and I'll run some tests on it this >> weekend. >> >> thanks >> -john >> >> >> diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c >> index 3abf534..bfb36fd 100644 >> --- a/kernel/time/timekeeping.c >> +++ b/kernel/time/timekeeping.c >> @@ -1056,42 +1056,24 @@ static __always_inline int >> timekeeping_bigadjust(struct timekeeper *tk, >> s64 *offset) > John, > > Any chance of posting this against a normal kernel? I am preparing > "real" tests comparing the three different patches in this thread on > v3.12.3, but this one does not apply.
Sorry about that. :( About half the time I try pasting in a patch, thunderbird seems to decide to ignore the preformat setting and corrupts whitespace in the patch. Anyway, patch is attached. Many thanks for the additional testing and review! thanks -john
>From 3fbbd9ade38419245af22902a98ea221e7b36c94 Mon Sep 17 00:00:00 2001 From: John Stultz <john.stu...@linaro.org> Date: Fri, 6 Dec 2013 17:25:21 -0800 Subject: [PATCH] my first attempt at reworking bigadjust for nohz Takes a similar approach as Miroslav's but using the bigadjust method. Signed-off-by: John Stultz <john.stu...@linaro.org> --- kernel/time/timekeeping.c | 80 +++++++++++++---------------------------------- 1 file changed, 22 insertions(+), 58 deletions(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 947ba25..46f4bd2 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -1056,42 +1056,24 @@ static __always_inline int timekeeping_bigadjust(struct timekeeper *tk, s64 *offset) { s64 tick_error, i; - u32 look_ahead, adj; - s32 error2, mult; + u32 adj; + s32 mult = 1; - /* - * Use the current error value to determine how much to look ahead. - * The larger the error the slower we adjust for it to avoid problems - * with losing too many ticks, otherwise we would overadjust and - * produce an even larger error. The smaller the adjustment the - * faster we try to adjust for it, as lost ticks can do less harm - * here. This is tuned so that an error of about 1 msec is adjusted - * within about 1 sec (or 2^20 nsec in 2^SHIFT_HZ ticks). - */ - error2 = tk->ntp_error >> (NTP_SCALE_SHIFT + 22 - 2 * SHIFT_HZ); - error2 = abs(error2); - for (look_ahead = 0; error2 > 0; look_ahead++) - error2 >>= 2; + /* Calculate current tick error */ + tick_error = ntp_tick_length() >> (tk->ntp_error_shift ); + tick_error -= tk->xtime_interval; - /* - * Now calculate the error in (1 << look_ahead) ticks, but first - * remove the single look ahead already included in the error. - */ - tick_error = ntp_tick_length() >> (tk->ntp_error_shift + 1); - tick_error -= tk->xtime_interval >> 1; - error = ((error - tick_error) >> look_ahead) + tick_error; - - /* Finally calculate the adjustment shift value. */ - i = *interval; - mult = 1; - if (error < 0) { - error = -error; + if (tick_error < 0) { *interval = -*interval; *offset = -*offset; - mult = -1; + mult = -mult; } - for (adj = 0; error > i; adj++) - error >>= 1; + + /* Sort out the magnitude of the correction */ + tick_error = abs(tick_error); + i = abs(*interval); + for (adj = 0; tick_error > i; adj++) + tick_error >>= 1; *interval <<= adj; *offset <<= adj; @@ -1114,41 +1096,23 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset) * * First we shift it down from NTP_SHIFT to clocksource->shifted nsecs. * - * Note we subtract one in the shift, so that error is really error*2. - * This "saves" dividing(shifting) interval twice, but keeps the - * (error > interval) comparison as still measuring if error is - * larger than half an interval. - * - * Note: It does not "save" on aggravation when reading the code. + * Then we meausre if error is larger than half an interval. */ - error = tk->ntp_error >> (tk->ntp_error_shift - 1); - if (error > interval) { - /* - * We now divide error by 4(via shift), which checks if - * the error is greater than twice the interval. - * If it is greater, we need a bigadjust, if its smaller, - * we can adjust by 1. - */ - error >>= 2; + error = tk->ntp_error >> (tk->ntp_error_shift); + if (error > interval/2) { /* - * XXX - In update_wall_time, we round up to the next - * nanosecond, and store the amount rounded up into - * the error. This causes the likely below to be unlikely. - * - * The proper fix is to avoid rounding up by using - * the high precision tk->xtime_nsec instead of - * xtime.tv_nsec everywhere. Fixing this will take some - * time. + * We now checks if the error is greater than twice the + * interval. If it is greater, we need a bigadjust, if its + * smaller, we can adjust by 1. */ - if (likely(error <= interval)) + if (likely(error <= interval*2)) adj = 1; else adj = timekeeping_bigadjust(tk, error, &interval, &offset); } else { - if (error < -interval) { + if (error < -interval/2) { /* See comment above, this is just switched for the negative */ - error >>= 2; - if (likely(error >= -interval)) { + if (likely(error >= -interval*2)) { adj = -1; interval = -interval; offset = -offset; -- 1.8.3.2