summaryrefslogtreecommitdiffstats
path: root/debian/patches-rt/0102-hrtimer-Move-schedule_work-call-to-helper-thread.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches-rt/0102-hrtimer-Move-schedule_work-call-to-helper-thread.patch')
-rw-r--r--debian/patches-rt/0102-hrtimer-Move-schedule_work-call-to-helper-thread.patch98
1 files changed, 98 insertions, 0 deletions
diff --git a/debian/patches-rt/0102-hrtimer-Move-schedule_work-call-to-helper-thread.patch b/debian/patches-rt/0102-hrtimer-Move-schedule_work-call-to-helper-thread.patch
new file mode 100644
index 000000000..59bec99cb
--- /dev/null
+++ b/debian/patches-rt/0102-hrtimer-Move-schedule_work-call-to-helper-thread.patch
@@ -0,0 +1,98 @@
+From da39809d4f91a8c4a41fdf3f17fc892dc71dd9ae Mon Sep 17 00:00:00 2001
+From: Yang Shi <yang.shi@windriver.com>
+Date: Mon, 16 Sep 2013 14:09:19 -0700
+Subject: [PATCH 102/347] hrtimer: Move schedule_work call to helper thread
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.19/older/patches-4.19.246-rt110.tar.xz
+
+When run ltp leapsec_timer test, the following call trace is caught:
+
+BUG: sleeping function called from invalid context at kernel/rtmutex.c:659
+in_atomic(): 1, irqs_disabled(): 1, pid: 0, name: swapper/1
+Preemption disabled at:[<ffffffff810857f3>] cpu_startup_entry+0x133/0x310
+
+CPU: 1 PID: 0 Comm: swapper/1 Not tainted 3.10.10-rt3 #2
+Hardware name: Intel Corporation Calpella platform/MATXM-CORE-411-B, BIOS 4.6.3 08/18/2010
+ffffffff81c2f800 ffff880076843e40 ffffffff8169918d ffff880076843e58
+ffffffff8106db31 ffff88007684b4a0 ffff880076843e70 ffffffff8169d9c0
+ffff88007684b4a0 ffff880076843eb0 ffffffff81059da1 0000001876851200
+Call Trace:
+<IRQ> [<ffffffff8169918d>] dump_stack+0x19/0x1b
+[<ffffffff8106db31>] __might_sleep+0xf1/0x170
+[<ffffffff8169d9c0>] rt_spin_lock+0x20/0x50
+[<ffffffff81059da1>] queue_work_on+0x61/0x100
+[<ffffffff81065aa1>] clock_was_set_delayed+0x21/0x30
+[<ffffffff810883be>] do_timer+0x40e/0x660
+[<ffffffff8108f487>] tick_do_update_jiffies64+0xf7/0x140
+[<ffffffff8108fe42>] tick_check_idle+0x92/0xc0
+[<ffffffff81044327>] irq_enter+0x57/0x70
+[<ffffffff816a040e>] smp_apic_timer_interrupt+0x3e/0x9b
+[<ffffffff8169f80a>] apic_timer_interrupt+0x6a/0x70
+<EOI> [<ffffffff8155ea1c>] ? cpuidle_enter_state+0x4c/0xc0
+[<ffffffff8155eb68>] cpuidle_idle_call+0xd8/0x2d0
+[<ffffffff8100b59e>] arch_cpu_idle+0xe/0x30
+[<ffffffff8108585e>] cpu_startup_entry+0x19e/0x310
+[<ffffffff8168efa2>] start_secondary+0x1ad/0x1b0
+
+The clock_was_set_delayed is called in hard IRQ handler (timer interrupt), which
+calls schedule_work.
+
+Under PREEMPT_RT_FULL, schedule_work calls spinlocks which could sleep, so it's
+not safe to call schedule_work in interrupt context.
+
+Reference upstream commit b68d61c705ef02384c0538b8d9374545097899ca
+(rt,ntp: Move call to schedule_delayed_work() to helper thread)
+from git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-stable-rt.git, which
+makes a similar change.
+
+Signed-off-by: Yang Shi <yang.shi@windriver.com>
+[bigeasy: use swork_queue() instead a helper thread]
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/time/hrtimer.c | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
+index e947f3b344ac..0833e5cf224d 100644
+--- a/kernel/time/hrtimer.c
++++ b/kernel/time/hrtimer.c
+@@ -748,6 +748,29 @@ static void hrtimer_switch_to_hres(void)
+ retrigger_next_event(NULL);
+ }
+
++#ifdef CONFIG_PREEMPT_RT_FULL
++
++static struct swork_event clock_set_delay_work;
++
++static void run_clock_set_delay(struct swork_event *event)
++{
++ clock_was_set();
++}
++
++void clock_was_set_delayed(void)
++{
++ swork_queue(&clock_set_delay_work);
++}
++
++static __init int create_clock_set_delay_thread(void)
++{
++ WARN_ON(swork_get());
++ INIT_SWORK(&clock_set_delay_work, run_clock_set_delay);
++ return 0;
++}
++early_initcall(create_clock_set_delay_thread);
++#else /* PREEMPT_RT_FULL */
++
+ static void clock_was_set_work(struct work_struct *work)
+ {
+ clock_was_set();
+@@ -763,6 +786,7 @@ void clock_was_set_delayed(void)
+ {
+ schedule_work(&hrtimer_work);
+ }
++#endif
+
+ #else
+
+--
+2.36.1
+