aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorSuresh Siddha <suresh.b.siddha@intel.com>2011-10-03 18:09:01 -0400
committerIngo Molnar <mingo@elte.hu>2011-10-06 06:46:27 -0400
commit6eb57e0d65ebd99a71d435dc96d83e725752eef8 (patch)
tree0349de8e8478a9b39dd1c75d347c36b9ebbef24c /kernel
parentca38062e57e97791c2f62e3dbd06caf3ebb5721c (diff)
sched: Request for idle balance during nohz idle load balance
rq's idle_at_tick is set to idle/busy during the timer tick depending on the cpu was idle or not. This will be used later in the load balance that will be done in the softirq context (which is a process context in -RT kernels). For nohz kernels, for the cpu doing nohz idle load balance on behalf of all the idle cpu's, its rq->idle_at_tick might have a stale value (which is recorded when it got the timer tick presumably when it is busy). As the nohz idle load balancing is also being done at the same place as the regular load balancing, nohz idle load balancing was bailing out when it sees rq's idle_at_tick not set. Thus leading to poor system utilization. Rename rq's idle_at_tick to idle_balance and set it when someone requests for nohz idle balance on an idle cpu. Reported-by: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.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/20111003220934.892350549@sbsiddha-desk.sc.intel.com Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sched.c8
-rw-r--r--kernel/sched_fair.c4
2 files changed, 7 insertions, 5 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index 9e49af00ae3e..7bc9b0e84eb3 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -644,7 +644,7 @@ struct rq {
644 644
645 unsigned long cpu_power; 645 unsigned long cpu_power;
646 646
647 unsigned char idle_at_tick; 647 unsigned char idle_balance;
648 /* For active balancing */ 648 /* For active balancing */
649 int post_schedule; 649 int post_schedule;
650 int active_balance; 650 int active_balance;
@@ -2751,8 +2751,10 @@ void scheduler_ipi(void)
2751 /* 2751 /*
2752 * Check if someone kicked us for doing the nohz idle load balance. 2752 * Check if someone kicked us for doing the nohz idle load balance.
2753 */ 2753 */
2754 if (unlikely(got_nohz_idle_kick() && !need_resched())) 2754 if (unlikely(got_nohz_idle_kick() && !need_resched())) {
2755 this_rq()->idle_balance = 1;
2755 raise_softirq_irqoff(SCHED_SOFTIRQ); 2756 raise_softirq_irqoff(SCHED_SOFTIRQ);
2757 }
2756 irq_exit(); 2758 irq_exit();
2757} 2759}
2758 2760
@@ -4247,7 +4249,7 @@ void scheduler_tick(void)
4247 perf_event_task_tick(); 4249 perf_event_task_tick();
4248 4250
4249#ifdef CONFIG_SMP 4251#ifdef CONFIG_SMP
4250 rq->idle_at_tick = idle_cpu(cpu); 4252 rq->idle_balance = idle_cpu(cpu);
4251 trigger_load_balance(rq, cpu); 4253 trigger_load_balance(rq, cpu);
4252#endif 4254#endif
4253} 4255}
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
index 6c5fa1099229..506db0966eb8 100644
--- a/kernel/sched_fair.c
+++ b/kernel/sched_fair.c
@@ -4676,7 +4676,7 @@ static inline int nohz_kick_needed(struct rq *rq, int cpu)
4676 if (time_before(now, nohz.next_balance)) 4676 if (time_before(now, nohz.next_balance))
4677 return 0; 4677 return 0;
4678 4678
4679 if (rq->idle_at_tick) 4679 if (idle_cpu(cpu))
4680 return 0; 4680 return 0;
4681 4681
4682 first_pick_cpu = atomic_read(&nohz.first_pick_cpu); 4682 first_pick_cpu = atomic_read(&nohz.first_pick_cpu);
@@ -4712,7 +4712,7 @@ static void run_rebalance_domains(struct softirq_action *h)
4712{ 4712{
4713 int this_cpu = smp_processor_id(); 4713 int this_cpu = smp_processor_id();
4714 struct rq *this_rq = cpu_rq(this_cpu); 4714 struct rq *this_rq = cpu_rq(this_cpu);
4715 enum cpu_idle_type idle = this_rq->idle_at_tick ? 4715 enum cpu_idle_type idle = this_rq->idle_balance ?
4716 CPU_IDLE : CPU_NOT_IDLE; 4716 CPU_IDLE : CPU_NOT_IDLE;
4717 4717
4718 rebalance_domains(this_cpu, idle); 4718 rebalance_domains(this_cpu, idle);