Currently we don't support migration of currently running timers. Current code flow in __mod_timer() is: - Find a cpu where we should migrate the timer - Check if timer is currently running - If yes, don't migrate.
In this process, the first step is a unnecessary activiy, if the timer is currently running. This patch tries to avoid it in such cases.
Signed-off-by: Viresh Kumar viresh.kumar@linaro.org --- kernel/timer.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/kernel/timer.c b/kernel/timer.c index 8c5e7b9..6e5bf98 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -755,23 +755,23 @@ __mod_timer(struct timer_list *timer, unsigned long expires,
debug_activate(timer, expires);
- cpu = smp_processor_id(); + /* + * Should we try to migrate timer? + * However we can't change timer's base while it is running, otherwise + * del_timer_sync() can't detect that the timer's handler yet has not + * finished. This also guarantees that the timer is serialized wrt + * itself. + */ + if (likely(base->running_timer != timer)) { + cpu = smp_processor_id();
#if defined(CONFIG_NO_HZ) && defined(CONFIG_SMP) - if (!pinned && get_sysctl_timer_migration() && idle_cpu(cpu)) - cpu = get_nohz_timer_target(); + if (!pinned && get_sysctl_timer_migration() && idle_cpu(cpu)) + cpu = get_nohz_timer_target(); #endif - new_base = per_cpu(tvec_bases, cpu); + new_base = per_cpu(tvec_bases, cpu);
- if (base != new_base) { - /* - * We are trying to schedule the timer on the local CPU. - * However we can't change timer's base while it is running, - * otherwise del_timer_sync() can't detect that the timer's - * handler yet has not finished. This also guarantees that - * the timer is serialized wrt itself. - */ - if (likely(base->running_timer != timer)) { + if (base != new_base) { /* See the comment in lock_timer_base() */ timer_set_base(timer, NULL); spin_unlock(&base->lock);