aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorSuresh Siddha <suresh.b.siddha@intel.com>2012-01-19 21:28:57 -0500
committerIngo Molnar <mingo@elte.hu>2012-01-26 13:38:13 -0500
commit71325960d16cd68ea0e22a8da15b2495b0f363f7 (patch)
tree38be96d9232b302780476899f8536e690c693ffb /kernel
parentdb7e527da41560f597ccdc4417cefa6b7657c0c0 (diff)
sched/nohz: Fix nohz cpu idle load balancing state with cpu hotplug
With the recent nohz scheduler changes, rq's nohz flag 'NOHZ_TICK_STOPPED' and its associated state doesn't get cleared immediately after the cpu exits idle. This gets cleared as part of the next tick seen on that cpu. For the cpu offline support, we need to clear this state manually. Fix it by registering a cpu notifier, which clears the nohz idle load balance state for this rq explicitly during the CPU_DYING notification. There won't be any nohz updates for that cpu, after the CPU_DYING notification. But lets be extra paranoid and skip updating the nohz state in the select_nohz_load_balancer() if the cpu is not in active state anymore. Reported-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com> Reviewed-and-tested-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com> Tested-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com> Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/1327026538.16150.40.camel@sbsiddha-desk.sc.intel.com Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sched/fair.c34
1 files changed, 29 insertions, 5 deletions
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 84adb2d66cbd..7c6414fc669d 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -4866,6 +4866,15 @@ static void nohz_balancer_kick(int cpu)
4866 return; 4866 return;
4867} 4867}
4868 4868
4869static inline void clear_nohz_tick_stopped(int cpu)
4870{
4871 if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) {
4872 cpumask_clear_cpu(cpu, nohz.idle_cpus_mask);
4873 atomic_dec(&nohz.nr_cpus);
4874 clear_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu));
4875 }
4876}
4877
4869static inline void set_cpu_sd_state_busy(void) 4878static inline void set_cpu_sd_state_busy(void)
4870{ 4879{
4871 struct sched_domain *sd; 4880 struct sched_domain *sd;
@@ -4904,6 +4913,12 @@ void select_nohz_load_balancer(int stop_tick)
4904{ 4913{
4905 int cpu = smp_processor_id(); 4914 int cpu = smp_processor_id();
4906 4915
4916 /*
4917 * If this cpu is going down, then nothing needs to be done.
4918 */
4919 if (!cpu_active(cpu))
4920 return;
4921
4907 if (stop_tick) { 4922 if (stop_tick) {
4908 if (test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu))) 4923 if (test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))
4909 return; 4924 return;
@@ -4914,6 +4929,18 @@ void select_nohz_load_balancer(int stop_tick)
4914 } 4929 }
4915 return; 4930 return;
4916} 4931}
4932
4933static int __cpuinit sched_ilb_notifier(struct notifier_block *nfb,
4934 unsigned long action, void *hcpu)
4935{
4936 switch (action & ~CPU_TASKS_FROZEN) {
4937 case CPU_DYING:
4938 clear_nohz_tick_stopped(smp_processor_id());
4939 return NOTIFY_OK;
4940 default:
4941 return NOTIFY_DONE;
4942 }
4943}
4917#endif 4944#endif
4918 4945
4919static DEFINE_SPINLOCK(balancing); 4946static DEFINE_SPINLOCK(balancing);
@@ -5070,11 +5097,7 @@ static inline int nohz_kick_needed(struct rq *rq, int cpu)
5070 * busy tick after returning from idle, we will update the busy stats. 5097 * busy tick after returning from idle, we will update the busy stats.
5071 */ 5098 */
5072 set_cpu_sd_state_busy(); 5099 set_cpu_sd_state_busy();
5073 if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) { 5100 clear_nohz_tick_stopped(cpu);
5074 clear_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu));
5075 cpumask_clear_cpu(cpu, nohz.idle_cpus_mask);
5076 atomic_dec(&nohz.nr_cpus);
5077 }
5078 5101
5079 /* 5102 /*
5080 * None are in tickless mode and hence no need for NOHZ idle load 5103 * None are in tickless mode and hence no need for NOHZ idle load
@@ -5590,6 +5613,7 @@ __init void init_sched_fair_class(void)
5590 5613
5591#ifdef CONFIG_NO_HZ 5614#ifdef CONFIG_NO_HZ
5592 zalloc_cpumask_var(&nohz.idle_cpus_mask, GFP_NOWAIT); 5615 zalloc_cpumask_var(&nohz.idle_cpus_mask, GFP_NOWAIT);
5616 cpu_notifier(sched_ilb_notifier, 0);
5593#endif 5617#endif
5594#endif /* SMP */ 5618#endif /* SMP */
5595 5619