From 6cc98f03adbf517986a90c43af0cbc9a732b8435 Mon Sep 17 00:00:00 2001 From: Olav Haugan Date: Fri, 8 Jul 2016 10:59:08 -0700 Subject: [PATCH] timer: Ensure timers are not running before migrating This is needed to support migration of timers during cpu isolation. A timer might be running on the CPU that we want to isolate so we are unable to migrate the timers at this point. We are adding a spin-loop to wait for the timer to finish before migrating the timers. Change-Id: I24d6e91b6dff468c640c2fe3a37a7f31b6f0c79a Signed-off-by: Olav Haugan --- kernel/time/timer.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/kernel/time/timer.c b/kernel/time/timer.c index 51896272fcde..be750f6b2a68 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -1635,7 +1635,7 @@ static void migrate_timer_list(struct tvec_base *new_base, struct hlist_head *he } } -static void migrate_timers(int cpu) +static void migrate_timers(int cpu, bool wait) { struct tvec_base *old_base; struct tvec_base *new_base; @@ -1651,7 +1651,18 @@ static void migrate_timers(int cpu) spin_lock_irq(&new_base->lock); spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING); - BUG_ON(old_base->running_timer); + if (wait) { + /* Ensure timers are done running before continuing */ + while (old_base->running_timer) { + spin_unlock(&old_base->lock); + spin_unlock_irq(&new_base->lock); + cpu_relax(); + spin_lock_irq(&new_base->lock); + spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING); + } + } else { + BUG_ON(old_base->running_timer); + } for (i = 0; i < TVR_SIZE; i++) migrate_timer_list(new_base, old_base->tv1.vec + i); @@ -1676,7 +1687,7 @@ static int timer_cpu_notify(struct notifier_block *self, switch (action) { case CPU_DEAD: case CPU_DEAD_FROZEN: - migrate_timers((long)hcpu); + migrate_timers((long)hcpu, false); break; default: break;