56 lines
2.0 KiB
Diff
56 lines
2.0 KiB
Diff
From: Ingo Molnar <mingo@elte.hu>
|
|
Date: Fri, 3 Jul 2009 08:30:20 -0500
|
|
Subject: timers: Preempt-rt support
|
|
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.4/patches-4.4-rt3.tar.xz
|
|
|
|
The base->lock is a sleeping lock. Try not to workaround with a
|
|
spin_trylock(). The rt-mutex lock is not irq save even the try-lock
|
|
due to way how the inner lock accessed. Even with this fixed have the
|
|
problem that the owner is not the current process on the CPU but his
|
|
pid is used while taking the lock. Therefore we go with ext jiffy for
|
|
the wakeup. Also drop preempt_disable() usage since we need just to
|
|
ensure not to switch CPUs (the data structures have own locks).
|
|
|
|
[bigeasy: dropped that spin try lock]
|
|
Signed-off-by: Ingo Molnar <mingo@elte.hu>
|
|
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
|
---
|
|
kernel/time/timer.c | 12 ++++++++++--
|
|
1 file changed, 10 insertions(+), 2 deletions(-)
|
|
|
|
--- a/kernel/time/timer.c
|
|
+++ b/kernel/time/timer.c
|
|
@@ -1422,6 +1422,14 @@ u64 get_next_timer_interrupt(unsigned lo
|
|
if (cpu_is_offline(smp_processor_id()))
|
|
return expires;
|
|
|
|
+#ifdef CONFIG_PREEMPT_RT_FULL
|
|
+ /*
|
|
+ * On PREEMPT_RT we cannot sleep here. As a result we can't take
|
|
+ * the base lock to check when the next timer is pending and so
|
|
+ * we assume the next jiffy.
|
|
+ */
|
|
+ return basem + TICK_NSEC;
|
|
+#endif
|
|
spin_lock(&base->lock);
|
|
if (base->active_timers) {
|
|
if (time_before_eq(base->next_timer, base->timer_jiffies))
|
|
@@ -1621,7 +1629,7 @@ static void migrate_timers(int cpu)
|
|
|
|
BUG_ON(cpu_online(cpu));
|
|
old_base = per_cpu_ptr(&tvec_bases, cpu);
|
|
- new_base = get_cpu_ptr(&tvec_bases);
|
|
+ new_base = get_local_ptr(&tvec_bases);
|
|
/*
|
|
* The caller is globally serialized and nobody else
|
|
* takes two locks at once, deadlock is not possible.
|
|
@@ -1645,7 +1653,7 @@ static void migrate_timers(int cpu)
|
|
|
|
spin_unlock(&old_base->lock);
|
|
spin_unlock_irq(&new_base->lock);
|
|
- put_cpu_ptr(&tvec_bases);
|
|
+ put_local_ptr(&tvec_bases);
|
|
}
|
|
|
|
static int timer_cpu_notify(struct notifier_block *self,
|