Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

timekeeping: Rework timekeeping_suspend() to use shadow_timekeeper

Updates of the timekeeper can be done by operating on the shadow timekeeper
and afterwards copying the result into the real timekeeper. This has the
advantage, that the sequence count write protected region is kept as small
as possible.

While the sequence count held time is not relevant for the resume path as
there is no concurrency, there is no reason to have this function
different than all the other update sites.

Convert timekeeping_inject_offset() to use this scheme and cleanup the
variable declarations while at it.

As halt_fast_timekeeper() does not need protection sequence counter, it is
no problem to move it with this change outside of the sequence counter
protected area. But it still needs to be executed while holding the lock.

Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: John Stultz <jstultz@google.com>
Link: https://lore.kernel.org/all/20241009-devel-anna-maria-b4-timers-ptp-timekeeping-v2-22-554456a44a15@linutronix.de

authored by

Anna-Maria Behnsen and committed by
Thomas Gleixner
d05eae87 b2350d95

+10 -12
+10 -12
kernel/time/timekeeping.c
··· 2003 2003 2004 2004 int timekeeping_suspend(void) 2005 2005 { 2006 - struct timekeeper *tk = &tk_core.timekeeper; 2007 - unsigned long flags; 2008 - struct timespec64 delta, delta_delta; 2009 - static struct timespec64 old_delta; 2006 + struct timekeeper *tks = &tk_core.shadow_timekeeper; 2007 + struct timespec64 delta, delta_delta; 2008 + static struct timespec64 old_delta; 2010 2009 struct clocksource *curr_clock; 2010 + unsigned long flags; 2011 2011 u64 cycle_now; 2012 2012 2013 2013 read_persistent_clock64(&timekeeping_suspend_time); ··· 2023 2023 suspend_timing_needed = true; 2024 2024 2025 2025 raw_spin_lock_irqsave(&tk_core.lock, flags); 2026 - write_seqcount_begin(&tk_core.seq); 2027 - timekeeping_forward_now(tk); 2026 + timekeeping_forward_now(tks); 2028 2027 timekeeping_suspended = 1; 2029 2028 2030 2029 /* ··· 2031 2032 * just read from the current clocksource. Save this to potentially 2032 2033 * use in suspend timing. 2033 2034 */ 2034 - curr_clock = tk->tkr_mono.clock; 2035 - cycle_now = tk->tkr_mono.cycle_last; 2035 + curr_clock = tks->tkr_mono.clock; 2036 + cycle_now = tks->tkr_mono.cycle_last; 2036 2037 clocksource_start_suspend_timing(curr_clock, cycle_now); 2037 2038 2038 2039 if (persistent_clock_exists) { ··· 2042 2043 * try to compensate so the difference in system time 2043 2044 * and persistent_clock time stays close to constant. 2044 2045 */ 2045 - delta = timespec64_sub(tk_xtime(tk), timekeeping_suspend_time); 2046 + delta = timespec64_sub(tk_xtime(tks), timekeeping_suspend_time); 2046 2047 delta_delta = timespec64_sub(delta, old_delta); 2047 2048 if (abs(delta_delta.tv_sec) >= 2) { 2048 2049 /* ··· 2057 2058 } 2058 2059 } 2059 2060 2060 - timekeeping_update(&tk_core, tk, TK_MIRROR); 2061 - halt_fast_timekeeper(tk); 2062 - write_seqcount_end(&tk_core.seq); 2061 + timekeeping_update_from_shadow(&tk_core, 0); 2062 + halt_fast_timekeeper(tks); 2063 2063 raw_spin_unlock_irqrestore(&tk_core.lock, flags); 2064 2064 2065 2065 tick_suspend();