mirror of
https://github.com/OpenVoiceOS/OpenVoiceOS
synced 2025-02-21 22:27:49 +01:00
116 lines
3.9 KiB
Diff
116 lines
3.9 KiB
Diff
From 9d79040c2c1c1f48b290b9cee53e2ad94fe595d3 Mon Sep 17 00:00:00 2001
|
|
From: Frederic Weisbecker <frederic@kernel.org>
|
|
Date: Tue, 5 Apr 2022 03:07:52 +0200
|
|
Subject: [PATCH 021/196] tick: Fix timer storm since introduction of timersd
|
|
|
|
If timers are pending while the tick is reprogrammed on nohz_mode, the
|
|
next expiry is not armed to fire now, it is delayed one jiffy forward
|
|
instead so as not to raise an inextinguishable timer storm with such
|
|
scenario:
|
|
|
|
1) IRQ triggers and queue a timer
|
|
2) ksoftirqd() is woken up
|
|
3) IRQ tail: timer is reprogrammed to fire now
|
|
4) IRQ exit
|
|
5) TIMER interrupt
|
|
6) goto 3)
|
|
|
|
...all that until we finally reach ksoftirqd.
|
|
|
|
Unfortunately we are checking the wrong softirq vector bitmask since
|
|
timersd kthread has split from ksoftirqd. Timers now have their own
|
|
vector state field that must be checked separately. As a result, the
|
|
old timer storm is back. This shows up early on boot with extremely long
|
|
initcalls:
|
|
|
|
[ 333.004807] initcall dquot_init+0x0/0x111 returned 0 after 323822879 usecs
|
|
|
|
and the cause is uncovered with the right trace events showing just
|
|
10 microseconds between ticks (~100 000 Hz):
|
|
|
|
|swapper/-1 1dn.h111 60818582us : hrtimer_expire_entry: hrtimer=00000000e0ef0f6b function=tick_sched_timer now=60415486608
|
|
|swapper/-1 1dn.h111 60818592us : hrtimer_expire_entry: hrtimer=00000000e0ef0f6b function=tick_sched_timer now=60415496082
|
|
|swapper/-1 1dn.h111 60818601us : hrtimer_expire_entry: hrtimer=00000000e0ef0f6b function=tick_sched_timer now=60415505550
|
|
|
|
Fix this by checking the right timer vector state from the nohz code.
|
|
|
|
Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
|
|
Cc: Mel Gorman <mgorman@suse.de>
|
|
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
|
Cc: Thomas Gleixner <tglx@linutronix.de>
|
|
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
|
Link: https://lkml.kernel.org/r/20220405010752.1347437-2-frederic@kernel.org
|
|
---
|
|
include/linux/interrupt.h | 12 ++++++++++++
|
|
kernel/softirq.c | 7 +------
|
|
kernel/time/tick-sched.c | 2 +-
|
|
3 files changed, 14 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
|
|
index f459b0f27c94..a5091ac97fc6 100644
|
|
--- a/include/linux/interrupt.h
|
|
+++ b/include/linux/interrupt.h
|
|
@@ -611,9 +611,16 @@ extern void raise_softirq(unsigned int nr);
|
|
|
|
#ifdef CONFIG_PREEMPT_RT
|
|
DECLARE_PER_CPU(struct task_struct *, timersd);
|
|
+DECLARE_PER_CPU(unsigned long, pending_timer_softirq);
|
|
+
|
|
extern void raise_timer_softirq(void);
|
|
extern void raise_hrtimer_softirq(void);
|
|
|
|
+static inline unsigned int local_pending_timers(void)
|
|
+{
|
|
+ return __this_cpu_read(pending_timer_softirq);
|
|
+}
|
|
+
|
|
#else
|
|
static inline void raise_timer_softirq(void)
|
|
{
|
|
@@ -624,6 +631,11 @@ static inline void raise_hrtimer_softirq(void)
|
|
{
|
|
raise_softirq_irqoff(HRTIMER_SOFTIRQ);
|
|
}
|
|
+
|
|
+static inline unsigned int local_pending_timers(void)
|
|
+{
|
|
+ return local_softirq_pending();
|
|
+}
|
|
#endif
|
|
|
|
DECLARE_PER_CPU(struct task_struct *, ksoftirqd);
|
|
diff --git a/kernel/softirq.c b/kernel/softirq.c
|
|
index 1277abc94228..a4d359e2c2b5 100644
|
|
--- a/kernel/softirq.c
|
|
+++ b/kernel/softirq.c
|
|
@@ -621,12 +621,7 @@ static inline void tick_irq_exit(void)
|
|
|
|
#ifdef CONFIG_PREEMPT_RT
|
|
DEFINE_PER_CPU(struct task_struct *, timersd);
|
|
-static DEFINE_PER_CPU(unsigned long, pending_timer_softirq);
|
|
-
|
|
-static unsigned int local_pending_timers(void)
|
|
-{
|
|
- return __this_cpu_read(pending_timer_softirq);
|
|
-}
|
|
+DEFINE_PER_CPU(unsigned long, pending_timer_softirq);
|
|
|
|
static void wake_timersd(void)
|
|
{
|
|
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
|
|
index 55cbc49f70d1..1a0ed106b192 100644
|
|
--- a/kernel/time/tick-sched.c
|
|
+++ b/kernel/time/tick-sched.c
|
|
@@ -795,7 +795,7 @@ static void tick_nohz_restart(struct tick_sched *ts, ktime_t now)
|
|
|
|
static inline bool local_timer_softirq_pending(void)
|
|
{
|
|
- return local_softirq_pending() & BIT(TIMER_SOFTIRQ);
|
|
+ return local_pending_timers() & BIT(TIMER_SOFTIRQ);
|
|
}
|
|
|
|
static ktime_t tick_nohz_next_event(struct tick_sched *ts, int cpu)
|
|
--
|
|
2.45.1
|
|
|