Commit 1b267793 authored by Thomas Gleixner's avatar Thomas Gleixner

time/timekeeping: Avoid invoking clock_was_set() twice

do_adjtimex() might end up scheduling a delayed clock_was_set() via
timekeeping_advance() and then invoke clock_was_set() directly which is
pointless.

Make timekeeping_advance() return whether an invocation of clock_was_set()
is required and handle it at the call sites which allows do_adjtimex() to
issue a single direct call if required.
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/20210713135158.580966888@linutronix.de
parent a761a67f
...@@ -2127,7 +2127,7 @@ static u64 logarithmic_accumulation(struct timekeeper *tk, u64 offset, ...@@ -2127,7 +2127,7 @@ static u64 logarithmic_accumulation(struct timekeeper *tk, u64 offset,
* timekeeping_advance - Updates the timekeeper to the current time and * timekeeping_advance - Updates the timekeeper to the current time and
* current NTP tick length * current NTP tick length
*/ */
static void timekeeping_advance(enum timekeeping_adv_mode mode) static bool timekeeping_advance(enum timekeeping_adv_mode mode)
{ {
struct timekeeper *real_tk = &tk_core.timekeeper; struct timekeeper *real_tk = &tk_core.timekeeper;
struct timekeeper *tk = &shadow_timekeeper; struct timekeeper *tk = &shadow_timekeeper;
...@@ -2198,9 +2198,8 @@ static void timekeeping_advance(enum timekeeping_adv_mode mode) ...@@ -2198,9 +2198,8 @@ static void timekeeping_advance(enum timekeeping_adv_mode mode)
write_seqcount_end(&tk_core.seq); write_seqcount_end(&tk_core.seq);
out: out:
raw_spin_unlock_irqrestore(&timekeeper_lock, flags); raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
if (clock_set)
/* Have to call _delayed version, since in irq context*/ return !!clock_set;
clock_was_set_delayed();
} }
/** /**
...@@ -2209,7 +2208,8 @@ static void timekeeping_advance(enum timekeeping_adv_mode mode) ...@@ -2209,7 +2208,8 @@ static void timekeeping_advance(enum timekeeping_adv_mode mode)
*/ */
void update_wall_time(void) void update_wall_time(void)
{ {
timekeeping_advance(TK_ADV_TICK); if (timekeeping_advance(TK_ADV_TICK))
clock_was_set_delayed();
} }
/** /**
...@@ -2389,8 +2389,9 @@ int do_adjtimex(struct __kernel_timex *txc) ...@@ -2389,8 +2389,9 @@ int do_adjtimex(struct __kernel_timex *txc)
{ {
struct timekeeper *tk = &tk_core.timekeeper; struct timekeeper *tk = &tk_core.timekeeper;
struct audit_ntp_data ad; struct audit_ntp_data ad;
unsigned long flags; bool clock_set = false;
struct timespec64 ts; struct timespec64 ts;
unsigned long flags;
s32 orig_tai, tai; s32 orig_tai, tai;
int ret; int ret;
...@@ -2425,6 +2426,7 @@ int do_adjtimex(struct __kernel_timex *txc) ...@@ -2425,6 +2426,7 @@ int do_adjtimex(struct __kernel_timex *txc)
if (tai != orig_tai) { if (tai != orig_tai) {
__timekeeping_set_tai_offset(tk, tai); __timekeeping_set_tai_offset(tk, tai);
timekeeping_update(tk, TK_MIRROR | TK_CLOCK_WAS_SET); timekeeping_update(tk, TK_MIRROR | TK_CLOCK_WAS_SET);
clock_set = true;
} }
tk_update_leap_state(tk); tk_update_leap_state(tk);
...@@ -2435,9 +2437,9 @@ int do_adjtimex(struct __kernel_timex *txc) ...@@ -2435,9 +2437,9 @@ int do_adjtimex(struct __kernel_timex *txc)
/* Update the multiplier immediately if frequency was set directly */ /* Update the multiplier immediately if frequency was set directly */
if (txc->modes & (ADJ_FREQUENCY | ADJ_TICK)) if (txc->modes & (ADJ_FREQUENCY | ADJ_TICK))
timekeeping_advance(TK_ADV_FREQ); clock_set |= timekeeping_advance(TK_ADV_FREQ);
if (tai != orig_tai) if (clock_set)
clock_was_set(); clock_was_set();
ntp_notify_cmos_timer(); ntp_notify_cmos_timer();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment