Skip to content

Commit 9f77294

Browse files
committed
timekeeping: Update auxiliary timekeepers on clocksource change
Propagate a system clocksource change to the auxiliary timekeepers so that they can pick up the new clocksource. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: John Stultz <jstultz@google.com> Link: https://lore.kernel.org/all/20250625183757.803890875@linutronix.de
1 parent 180d8b4 commit 9f77294

1 file changed

Lines changed: 33 additions & 0 deletions

File tree

kernel/time/timekeeping.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,10 @@ static struct tk_fast tk_fast_raw ____cacheline_aligned = {
119119

120120
#ifdef CONFIG_POSIX_AUX_CLOCKS
121121
static __init void tk_aux_setup(void);
122+
static void tk_aux_update_clocksource(void);
122123
#else
123124
static inline void tk_aux_setup(void) { }
125+
static inline void tk_aux_update_clocksource(void) { }
124126
#endif
125127

126128
unsigned long timekeeper_lock_irqsave(void)
@@ -1548,6 +1550,8 @@ static int change_clocksource(void *data)
15481550
timekeeping_update_from_shadow(&tk_core, TK_UPDATE_ALL);
15491551
}
15501552

1553+
tk_aux_update_clocksource();
1554+
15511555
if (old) {
15521556
if (old->disable)
15531557
old->disable(old);
@@ -2651,6 +2655,35 @@ EXPORT_SYMBOL(hardpps);
26512655
#endif /* CONFIG_NTP_PPS */
26522656

26532657
#ifdef CONFIG_POSIX_AUX_CLOCKS
2658+
2659+
/*
2660+
* Bitmap for the activated auxiliary timekeepers to allow lockless quick
2661+
* checks in the hot paths without touching extra cache lines. If set, then
2662+
* the state of the corresponding timekeeper has to be re-checked under
2663+
* timekeeper::lock.
2664+
*/
2665+
static unsigned long aux_timekeepers;
2666+
2667+
/* Invoked from timekeeping after a clocksource change */
2668+
static void tk_aux_update_clocksource(void)
2669+
{
2670+
unsigned long active = READ_ONCE(aux_timekeepers);
2671+
unsigned int id;
2672+
2673+
for_each_set_bit(id, &active, BITS_PER_LONG) {
2674+
struct tk_data *tkd = &timekeeper_data[id + TIMEKEEPER_AUX_FIRST];
2675+
struct timekeeper *tks = &tkd->shadow_timekeeper;
2676+
2677+
guard(raw_spinlock_irqsave)(&tkd->lock);
2678+
if (!tks->clock_valid)
2679+
continue;
2680+
2681+
timekeeping_forward_now(tks);
2682+
tk_setup_internals(tks, tk_core.timekeeper.tkr_mono.clock);
2683+
timekeeping_update_from_shadow(tkd, TK_UPDATE_ALL);
2684+
}
2685+
}
2686+
26542687
static __init void tk_aux_setup(void)
26552688
{
26562689
for (int i = TIMEKEEPER_AUX_FIRST; i <= TIMEKEEPER_AUX_LAST; i++)

0 commit comments

Comments
 (0)