mirror of
https://github.com/torvalds/linux.git
synced 2026-05-12 16:18:45 +02:00
sched/clock: Avoid false sharing for sched_clock_irqtime
Read-mostly sched_clock_irqtime may share the same cacheline with
frequently updated nohz struct. Make it as static_key to avoid
false sharing issue.
The only user of disable_sched_clock_irqtime()
is tsc_.*mark_unstable() which may be invoked under atomic context
and require a workqueue to disable static_key. But both of them
calls clear_sched_clock_stable() just before doing
disable_sched_clock_irqtime(). We can reuse
"sched_clock_work" to also disable sched_clock_irqtime().
One additional case need to handle is if the tsc is marked unstable
before late_initcall() phase, sched_clock_work will not be invoked
and sched_clock_irqtime will stay enabled although clock is unstable:
tsc_init()
enable_sched_clock_irqtime() # irqtime accounting is enabled here
...
if (unsynchronized_tsc()) # true
mark_tsc_unstable()
clear_sched_clock_stable()
__sched_clock_stable_early = 0;
...
if (static_key_count(&sched_clock_running.key) == 2)
# Only happens at sched_clock_init_late()
__clear_sched_clock_stable(); # Never executed
...
# late_initcall() phase
sched_clock_init_late()
if (__sched_clock_stable_early) # Already false
__set_sched_clock_stable(); # sched_clock is never marked stable
# TSC unstable, but sched_clock_work won't run to disable irqtime
So we need to disable_sched_clock_irqtime() in sched_clock_init_late()
if clock is unstable.
Reported-by: Benjamin Lei <benjamin.lei@intel.com>
Suggested-by: K Prateek Nayak <kprateek.nayak@amd.com>
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Suggested-by: Shrikanth Hegde <sshegde@linux.ibm.com>
Signed-off-by: Wangyang Guo <wangyang.guo@intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: K Prateek Nayak <kprateek.nayak@amd.com>
Reviewed-by: Tim Chen <tim.c.chen@linux.intel.com>
Reviewed-by: Tianyou Li <tianyou.li@intel.com>
Reviewed-by: Shrikanth Hegde <sshegde@linux.ibm.com>
Tested-by: K Prateek Nayak <kprateek.nayak@amd.com>
Link: https://patch.msgid.link/20260127072509.2627346-1-wangyang.guo@intel.com
This commit is contained in:
parent
dd6a37e8fa
commit
505da66893
|
|
@ -1143,7 +1143,6 @@ static void tsc_cs_mark_unstable(struct clocksource *cs)
|
||||||
tsc_unstable = 1;
|
tsc_unstable = 1;
|
||||||
if (using_native_sched_clock())
|
if (using_native_sched_clock())
|
||||||
clear_sched_clock_stable();
|
clear_sched_clock_stable();
|
||||||
disable_sched_clock_irqtime();
|
|
||||||
pr_info("Marking TSC unstable due to clocksource watchdog\n");
|
pr_info("Marking TSC unstable due to clocksource watchdog\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1213,7 +1212,6 @@ void mark_tsc_unstable(char *reason)
|
||||||
tsc_unstable = 1;
|
tsc_unstable = 1;
|
||||||
if (using_native_sched_clock())
|
if (using_native_sched_clock())
|
||||||
clear_sched_clock_stable();
|
clear_sched_clock_stable();
|
||||||
disable_sched_clock_irqtime();
|
|
||||||
pr_info("Marking TSC unstable due to %s\n", reason);
|
pr_info("Marking TSC unstable due to %s\n", reason);
|
||||||
|
|
||||||
clocksource_mark_unstable(&clocksource_tsc_early);
|
clocksource_mark_unstable(&clocksource_tsc_early);
|
||||||
|
|
|
||||||
|
|
@ -173,6 +173,7 @@ notrace static void __sched_clock_work(struct work_struct *work)
|
||||||
scd->tick_gtod, __gtod_offset,
|
scd->tick_gtod, __gtod_offset,
|
||||||
scd->tick_raw, __sched_clock_offset);
|
scd->tick_raw, __sched_clock_offset);
|
||||||
|
|
||||||
|
disable_sched_clock_irqtime();
|
||||||
static_branch_disable(&__sched_clock_stable);
|
static_branch_disable(&__sched_clock_stable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -238,6 +239,8 @@ static int __init sched_clock_init_late(void)
|
||||||
|
|
||||||
if (__sched_clock_stable_early)
|
if (__sched_clock_stable_early)
|
||||||
__set_sched_clock_stable();
|
__set_sched_clock_stable();
|
||||||
|
else
|
||||||
|
disable_sched_clock_irqtime(); /* disable if clock unstable. */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
#ifdef CONFIG_IRQ_TIME_ACCOUNTING
|
#ifdef CONFIG_IRQ_TIME_ACCOUNTING
|
||||||
|
|
||||||
|
DEFINE_STATIC_KEY_FALSE(sched_clock_irqtime);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There are no locks covering percpu hardirq/softirq time.
|
* There are no locks covering percpu hardirq/softirq time.
|
||||||
* They are only modified in vtime_account, on corresponding CPU
|
* They are only modified in vtime_account, on corresponding CPU
|
||||||
|
|
@ -25,16 +27,15 @@
|
||||||
*/
|
*/
|
||||||
DEFINE_PER_CPU(struct irqtime, cpu_irqtime);
|
DEFINE_PER_CPU(struct irqtime, cpu_irqtime);
|
||||||
|
|
||||||
int sched_clock_irqtime;
|
|
||||||
|
|
||||||
void enable_sched_clock_irqtime(void)
|
void enable_sched_clock_irqtime(void)
|
||||||
{
|
{
|
||||||
sched_clock_irqtime = 1;
|
static_branch_enable(&sched_clock_irqtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void disable_sched_clock_irqtime(void)
|
void disable_sched_clock_irqtime(void)
|
||||||
{
|
{
|
||||||
sched_clock_irqtime = 0;
|
if (irqtime_enabled())
|
||||||
|
static_branch_disable(&sched_clock_irqtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void irqtime_account_delta(struct irqtime *irqtime, u64 delta,
|
static void irqtime_account_delta(struct irqtime *irqtime, u64 delta,
|
||||||
|
|
|
||||||
|
|
@ -3333,11 +3333,11 @@ struct irqtime {
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_PER_CPU(struct irqtime, cpu_irqtime);
|
DECLARE_PER_CPU(struct irqtime, cpu_irqtime);
|
||||||
extern int sched_clock_irqtime;
|
DECLARE_STATIC_KEY_FALSE(sched_clock_irqtime);
|
||||||
|
|
||||||
static inline int irqtime_enabled(void)
|
static inline int irqtime_enabled(void)
|
||||||
{
|
{
|
||||||
return sched_clock_irqtime;
|
return static_branch_likely(&sched_clock_irqtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user