On Mon, 8 Jun 2015, Thomas Gleixner wrote: > On Mon, 8 Jun 2015, John Stultz wrote: > > Now, It could be possible to do a lighter weight version of my patch, > > which just does the adjustment only for the hrtimer_interrupt code > > (leaving the rest of the read paths alone). > > Yes, that should work. As long as I can keep the cached values in the > hrtimer cpu bases and the whole thing keeps the clock_was_set_seq > logic intact. > > If we do not do the conditional version, then on every hrtimer > interrupt we write THREE cachelines for nothing. > > And if we cannot cache the offsets, then we end up calling into the > timekeeping code for every timer which is not CLOCK_MONOTONIC based > and retrieve the offset. That hurts especially on 32bit machines, > because we need to protect the readout with the timekeeper sequence > counter.
Below is a patch which just has the required data in the right place and the changes to ktime_get_update_offsets_now(). It's simpler than your version as: - there is no requirement to do the add in the first place as we know the monotonic time at which the leap second happens. - we can precalculate the leap adjusted offset and just replace the non adjusted offset for the window. When the whole thing is over you just need to increment the clock_was_set_seq counter so the next timer interrupt will cache the normal values again. Thanks, tglx diff --git a/include/linux/timekeeper_internal.h b/include/linux/timekeeper_internal.h index e1f5a1136554..ecd193c23676 100644 --- a/include/linux/timekeeper_internal.h +++ b/include/linux/timekeeper_internal.h @@ -90,6 +90,9 @@ struct timekeeper { ktime_t offs_tai; s32 tai_offset; unsigned int clock_was_set_seq; + ktime_t next_leap_ktime; + ktime_t offs_real_leap_adjusted; + struct timespec64 raw_time; /* The following members are for timekeeping internal use */ diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 90ed5db67c1d..0de85bf9e331 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -1952,15 +1952,21 @@ ktime_t ktime_get_update_offsets_now(unsigned int *cwsseq, ktime_t *offs_real, base = tk->tkr_mono.base; nsecs = timekeeping_get_ns(&tk->tkr_mono); + base = ktime_add_ns(base, nsecs); + if (*cwsseq != tk->clock_was_set_seq) { *cwsseq = tk->clock_was_set_seq; *offs_real = tk->offs_real; *offs_boot = tk->offs_boot; *offs_tai = tk->offs_tai; } + + if (base.tv64 >= tk->next_leap_ktime.tv64) + *offs_real = tk->offs_real_leap_adjusted; + } while (read_seqcount_retry(&tk_core.seq, seq)); - return ktime_add_ns(base, nsecs); + return base; } /** -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/