blob: 264c375d35617d7b5443a0746ad25af0e6a42165 [file] [log] [blame]
From: Ingo Molnar <mingo@elte.hu>
Date: Fri, 3 Jul 2009 08:30:20 -0500
Subject: timers: Preempt-rt support
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,