Skip to content

Commit

Permalink
timekeeping: Add struct tk_data as argument to timekeeping_update()
Browse files Browse the repository at this point in the history
Updates of the timekeeper are done in two ways:

 1. Updating timekeeper and afterwards memcpy()'ing the result into
    shadow_timekeeper using timekeeping_update(). Used everywhere for
    updates except in timekeeping_advance(); the sequence counter protected
    region starts before the first change to the timekeeper is done.

 2. Updating shadow_timekeeper and then memcpy()'ing the result into
    timekeeper.  Used only by in timekeeping_advance(); The seqence counter
    protected region is only around timekeeping_update() and the memcpy for
    copy from shadow to timekeeper.

The second option is fast path optimized. The sequence counter protected
region is as short as possible.

As this behaviour is mainly documented by commit messages, but not in code,
it makes the not easy timekeeping code more complicated to read.

There is no reason why updates to the timekeeper can't use the optimized
version everywhere. With this, the code will be cleaner, as code is reused
instead of duplicated.

To be able to access tk_data which contains all required information, add a
pointer to tk_data as an argument to timekeeping_update(). With that
convert the comment about holding the lock into a lockdep assert.

No functional change.

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-12-554456a44a15@linutronix.de
  • Loading branch information
anna-marialx authored and KAGA-KOKO committed Oct 25, 2024
1 parent a5f9e4e commit 1d72d7b
Showing 1 changed file with 13 additions and 12 deletions.
25 changes: 13 additions & 12 deletions kernel/time/timekeeping.c
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ EXPORT_SYMBOL_GPL(ktime_get_raw_fast_ns);
* timekeeping_inject_sleeptime64()
* __timekeeping_inject_sleeptime(tk, delta);
* timestamp();
* timekeeping_update(tk, TK_CLEAR_NTP...);
* timekeeping_update(tkd, tk, TK_CLEAR_NTP...);
*
* (2) On 32-bit systems, the 64-bit boot offset (tk->offs_boot) may be
* partially updated. Since the tk->offs_boot update is a rare event, this
Expand Down Expand Up @@ -772,9 +772,10 @@ static inline void tk_update_ktime_data(struct timekeeper *tk)
tk->tkr_raw.base = ns_to_ktime(tk->raw_sec * NSEC_PER_SEC);
}

/* must hold tk_core.lock */
static void timekeeping_update(struct timekeeper *tk, unsigned int action)
static void timekeeping_update(struct tk_data *tkd, struct timekeeper *tk, unsigned int action)
{
lockdep_assert_held(&tkd->lock);

if (action & TK_CLEAR_NTP) {
tk->ntp_error = 0;
ntp_clear();
Expand Down Expand Up @@ -1498,7 +1499,7 @@ int do_settimeofday64(const struct timespec64 *ts)

tk_set_xtime(tk, ts);
out:
timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);
timekeeping_update(&tk_core, tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);

write_seqcount_end(&tk_core.seq);
raw_spin_unlock_irqrestore(&tk_core.lock, flags);
Expand Down Expand Up @@ -1548,7 +1549,7 @@ static int timekeeping_inject_offset(const struct timespec64 *ts)
tk_set_wall_to_mono(tk, timespec64_sub(tk->wall_to_monotonic, *ts));

error: /* even if we error out, we forwarded the time, so call update */
timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);
timekeeping_update(&tk_core, tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);

write_seqcount_end(&tk_core.seq);
raw_spin_unlock_irqrestore(&tk_core.lock, flags);
Expand Down Expand Up @@ -1633,7 +1634,7 @@ static int change_clocksource(void *data)
timekeeping_forward_now(tk);
old = tk->tkr_mono.clock;
tk_setup_internals(tk, new);
timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);
timekeeping_update(&tk_core, tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);

write_seqcount_end(&tk_core.seq);
raw_spin_unlock_irqrestore(&tk_core.lock, flags);
Expand Down Expand Up @@ -1832,7 +1833,7 @@ void __init timekeeping_init(void)

tk_set_wall_to_mono(tk, wall_to_mono);

timekeeping_update(tk, TK_MIRROR | TK_CLOCK_WAS_SET);
timekeeping_update(&tk_core, tk, TK_MIRROR | TK_CLOCK_WAS_SET);

write_seqcount_end(&tk_core.seq);
}
Expand Down Expand Up @@ -1924,7 +1925,7 @@ void timekeeping_inject_sleeptime64(const struct timespec64 *delta)

__timekeeping_inject_sleeptime(tk, delta);

timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);
timekeeping_update(&tk_core, tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);

write_seqcount_end(&tk_core.seq);
raw_spin_unlock_irqrestore(&tk_core.lock, flags);
Expand Down Expand Up @@ -1987,7 +1988,7 @@ void timekeeping_resume(void)

tk->ntp_error = 0;
timekeeping_suspended = 0;
timekeeping_update(tk, TK_MIRROR | TK_CLOCK_WAS_SET);
timekeeping_update(&tk_core, tk, TK_MIRROR | TK_CLOCK_WAS_SET);
write_seqcount_end(&tk_core.seq);
raw_spin_unlock_irqrestore(&tk_core.lock, flags);

Expand Down Expand Up @@ -2056,7 +2057,7 @@ int timekeeping_suspend(void)
}
}

timekeeping_update(tk, TK_MIRROR);
timekeeping_update(&tk_core, tk, TK_MIRROR);
halt_fast_timekeeper(tk);
write_seqcount_end(&tk_core.seq);
raw_spin_unlock_irqrestore(&tk_core.lock, flags);
Expand Down Expand Up @@ -2374,7 +2375,7 @@ static bool timekeeping_advance(enum timekeeping_adv_mode mode)
* memcpy under the tk_core.seq against one before we start
* updating.
*/
timekeeping_update(tk, clock_set);
timekeeping_update(&tk_core, tk, clock_set);
memcpy(real_tk, tk, sizeof(*tk));
/* The memcpy must come last. Do not put anything here! */
write_seqcount_end(&tk_core.seq);
Expand Down Expand Up @@ -2712,7 +2713,7 @@ int do_adjtimex(struct __kernel_timex *txc)

if (tai != orig_tai) {
__timekeeping_set_tai_offset(tk, tai);
timekeeping_update(tk, TK_MIRROR | TK_CLOCK_WAS_SET);
timekeeping_update(&tk_core, tk, TK_MIRROR | TK_CLOCK_WAS_SET);
clock_set = true;
} else {
tk_update_leap_state(tk);
Expand Down

0 comments on commit 1d72d7b

Please sign in to comment.