/* * Get the preferred target CPU for NOHZ */ static int hrtimer_get_target(int this_cpu, int pinned) { #ifdef CONFIG_NO_HZ if (!pinned && get_sysctl_timer_migration() && idle_cpu(this_cpu)) return get_nohz_timer_target(); #endif return this_cpu; }
static inline struct hrtimer_cpu_base *get_target_base(struct hrtimer_cpu_base *base, int pinned) { if (pinned || !base->migration_enabled) return base; return &per_cpu(hrtimer_bases, get_nohz_timer_target()); }
/* * Switch the timer base to the current CPU when possible. */ static inline struct hrtimer_clock_base * switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base, int pinned) { struct hrtimer_clock_base *new_base; struct hrtimer_cpu_base *new_cpu_base; int this_cpu = smp_processor_id(); int cpu = get_nohz_timer_target(pinned); int basenum = base->index; again: new_cpu_base = &per_cpu(hrtimer_bases, cpu); new_base = &new_cpu_base->clock_base[basenum]; if (base != new_base) { /* * We are trying to move timer to new_base. * However we can't change timer's base while it is running, * so we keep it on the same CPU. No hassle vs. reprogramming * the event source in the high resolution case. The softirq * code will take care of this when the timer function has * completed. There is no conflict as we hold the lock until * the timer is enqueued. */ if (unlikely(hrtimer_callback_running(timer))) return base; /* See the comment in lock_timer_base() */ timer->base = NULL; raw_spin_unlock(&base->cpu_base->lock); raw_spin_lock(&new_base->cpu_base->lock); if (cpu != this_cpu && hrtimer_check_target(timer, new_base)) { cpu = this_cpu; raw_spin_unlock(&new_base->cpu_base->lock); raw_spin_lock(&base->cpu_base->lock); timer->base = base; goto again; } timer->base = new_base; } else { if (cpu != this_cpu && hrtimer_check_target(timer, new_base)) { cpu = this_cpu; goto again; } } return new_base; }
/* * Get the preferred target CPU for NOHZ */ static int hrtimer_get_target(int this_cpu, int pinned) { #ifdef CONFIG_NO_HZ #ifdef CONFIG_SCHED_BFS if (!pinned && get_sysctl_timer_migration() && idle_cpu(this_cpu)) { int preferred_cpu = get_nohz_load_balancer(); if (preferred_cpu >= 0) return preferred_cpu; } #else if (!pinned && get_sysctl_timer_migration() && idle_cpu(this_cpu)) return get_nohz_timer_target(); #endif #endif return this_cpu; }