summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSuresh Siddha <suresh.b.siddha@intel.com>2011-10-03 15:09:01 -0700
committerVincent Guittot <vincent.guittot@linaro.org>2011-11-14 10:17:14 +0100
commite10d3fe8389c3fd1037d4ac4c34b01186477c1af (patch)
tree5ca706bf925b1bfe1f1e7ff1b3904dc57fc486a9
parentb820cdb85eb3ba38404f09c4a89b0607aabf5e71 (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>
-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 b57cf9e09b5..036311afeed 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -510,7 +510,7 @@ struct rq {
unsigned long cpu_power;
- unsigned char idle_at_tick;
+ unsigned char idle_balance;
/* For active balancing */
int post_schedule;
int active_balance;
@@ -2625,8 +2625,10 @@ void scheduler_ipi(void)
/*
* Check if someone kicked us for doing the nohz idle load balance.
*/
- if (unlikely(got_nohz_idle_kick() && !need_resched()))
+ if (unlikely(got_nohz_idle_kick() && !need_resched())) {
+ this_rq()->idle_balance = 1;
raise_softirq_irqoff(SCHED_SOFTIRQ);
+ }
irq_exit();
}
@@ -4134,7 +4136,7 @@ void scheduler_tick(void)
perf_event_task_tick();
#ifdef CONFIG_SMP
- rq->idle_at_tick = idle_cpu(cpu);
+ rq->idle_balance = idle_cpu(cpu);
trigger_load_balance(rq, cpu);
#endif
}
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
index 22cbad091ba..e476a5abca0 100644
--- a/kernel/sched_fair.c
+++ b/kernel/sched_fair.c
@@ -4019,7 +4019,7 @@ static inline int nohz_kick_needed(struct rq *rq, int cpu)
if (time_before(now, nohz.next_balance))
return 0;
- if (rq->idle_at_tick)
+ if (idle_cpu(cpu))
return 0;
first_pick_cpu = atomic_read(&nohz.first_pick_cpu);
@@ -4055,7 +4055,7 @@ static void run_rebalance_domains(struct softirq_action *h)
{
int this_cpu = smp_processor_id();
struct rq *this_rq = cpu_rq(this_cpu);
- enum cpu_idle_type idle = this_rq->idle_at_tick ?
+ enum cpu_idle_type idle = this_rq->idle_balance ?
CPU_IDLE : CPU_NOT_IDLE;
rebalance_domains(this_cpu, idle);