summaryrefslogtreecommitdiff
path: root/kernel/timer.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-07-03 08:30:32 -0500
committerThomas Gleixner <tglx@linutronix.de>2009-07-29 23:30:38 +0200
commite5e57bd60fce5d9e674f8fb3a1eaeb0dee114337 (patch)
tree2d9c851bb1ad2d4c24b9170221a470c31642609b /kernel/timer.c
parentc90fc5b4462b0291bfce50ddf31e142471dc4803 (diff)
downloadlwn-e5e57bd60fce5d9e674f8fb3a1eaeb0dee114337.tar.gz
lwn-e5e57bd60fce5d9e674f8fb3a1eaeb0dee114337.zip
timers: fix timer hotplug on -rt
Here we are in the CPU_DEAD notifier, and we must not sleep nor enable interrupts. Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/timer.c')
-rw-r--r--kernel/timer.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/kernel/timer.c b/kernel/timer.c
index 09026a957eef..e7b2deb54893 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -1610,6 +1610,7 @@ static void __cpuinit migrate_timers(int cpu)
{
struct tvec_base *old_base;
struct tvec_base *new_base;
+ unsigned long flags;
int i;
BUG_ON(cpu_online(cpu));
@@ -1619,8 +1620,11 @@ static void __cpuinit migrate_timers(int cpu)
* The caller is globally serialized and nobody else
* takes two locks at once, deadlock is not possible.
*/
- spin_lock_irq(&new_base->lock);
- spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING);
+ local_irq_save(flags);
+ while (!spin_trylock(&new_base->lock))
+ cpu_relax();
+ while (!spin_trylock(&old_base->lock))
+ cpu_relax();
BUG_ON(old_base->running_timer);
@@ -1634,7 +1638,9 @@ static void __cpuinit migrate_timers(int cpu)
}
spin_unlock(&old_base->lock);
- spin_unlock_irq(&new_base->lock);
+ spin_unlock(&new_base->lock);
+ local_irq_restore(flags);
+
put_cpu_var(tvec_bases);
}
#endif /* CONFIG_HOTPLUG_CPU */