diff options
Diffstat (limited to 'kernel/sched/fair.c')
| -rw-r--r-- | kernel/sched/fair.c | 34 | 
1 files changed, 29 insertions, 5 deletions
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 84adb2d66cb..7c6414fc669 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -4866,6 +4866,15 @@ static void nohz_balancer_kick(int cpu)  	return;  } +static inline void clear_nohz_tick_stopped(int cpu) +{ +	if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) { +		cpumask_clear_cpu(cpu, nohz.idle_cpus_mask); +		atomic_dec(&nohz.nr_cpus); +		clear_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)); +	} +} +  static inline void set_cpu_sd_state_busy(void)  {  	struct sched_domain *sd; @@ -4904,6 +4913,12 @@ void select_nohz_load_balancer(int stop_tick)  {  	int cpu = smp_processor_id(); +	/* +	 * If this cpu is going down, then nothing needs to be done. +	 */ +	if (!cpu_active(cpu)) +		return; +  	if (stop_tick) {  		if (test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))  			return; @@ -4914,6 +4929,18 @@ void select_nohz_load_balancer(int stop_tick)  	}  	return;  } + +static int __cpuinit sched_ilb_notifier(struct notifier_block *nfb, +					unsigned long action, void *hcpu) +{ +	switch (action & ~CPU_TASKS_FROZEN) { +	case CPU_DYING: +		clear_nohz_tick_stopped(smp_processor_id()); +		return NOTIFY_OK; +	default: +		return NOTIFY_DONE; +	} +}  #endif  static DEFINE_SPINLOCK(balancing); @@ -5070,11 +5097,7 @@ static inline int nohz_kick_needed(struct rq *rq, int cpu)  	* busy tick after returning from idle, we will update the busy stats.  	*/  	set_cpu_sd_state_busy(); -	if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) { -		clear_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)); -		cpumask_clear_cpu(cpu, nohz.idle_cpus_mask); -		atomic_dec(&nohz.nr_cpus); -	} +	clear_nohz_tick_stopped(cpu);  	/*  	 * None are in tickless mode and hence no need for NOHZ idle load @@ -5590,6 +5613,7 @@ __init void init_sched_fair_class(void)  #ifdef CONFIG_NO_HZ  	zalloc_cpumask_var(&nohz.idle_cpus_mask, GFP_NOWAIT); +	cpu_notifier(sched_ilb_notifier, 0);  #endif  #endif /* SMP */  |