From: Ingo Molnar 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 Signed-off-by: Thomas Gleixner --- 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,