| 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, |