aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched_fair.c
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2011-11-10 07:01:10 -0500
committerIngo Molnar <mingo@elte.hu>2011-11-16 02:43:43 -0500
commit4dcfe1025b513c2c1da5bf5586adb0e80148f612 (patch)
tree1c0bf8ad4c09a3a618c471b6468873d8d8ed2117 /kernel/sched_fair.c
parentf1c6f1a7eed963ed233ba4c8b6fa8addb86c6ddc (diff)
sched: Avoid SMT siblings in select_idle_sibling() if possible
Avoid select_idle_sibling() from picking a sibling thread if there's an idle core that shares cache. This fixes SMT balancing in the increasingly common case where there's a shared cache core available to balance to. Tested-by: Mike Galbraith <efault@gmx.de> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Suresh Siddha <suresh.b.siddha@intel.com> Link: http://lkml.kernel.org/r/1321350377.1421.55.camel@twins Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/sched_fair.c')
-rw-r--r--kernel/sched_fair.c42
1 files changed, 28 insertions, 14 deletions
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
index 7e51b5bb27cc..ba0e1f49a22f 100644
--- a/kernel/sched_fair.c
+++ b/kernel/sched_fair.c
@@ -2326,7 +2326,8 @@ static int select_idle_sibling(struct task_struct *p, int target)
2326 int cpu = smp_processor_id(); 2326 int cpu = smp_processor_id();
2327 int prev_cpu = task_cpu(p); 2327 int prev_cpu = task_cpu(p);
2328 struct sched_domain *sd; 2328 struct sched_domain *sd;
2329 int i; 2329 struct sched_group *sg;
2330 int i, smt = 0;
2330 2331
2331 /* 2332 /*
2332 * If the task is going to be woken-up on this cpu and if it is 2333 * If the task is going to be woken-up on this cpu and if it is
@@ -2346,25 +2347,38 @@ static int select_idle_sibling(struct task_struct *p, int target)
2346 * Otherwise, iterate the domains and find an elegible idle cpu. 2347 * Otherwise, iterate the domains and find an elegible idle cpu.
2347 */ 2348 */
2348 rcu_read_lock(); 2349 rcu_read_lock();
2350again:
2349 for_each_domain(target, sd) { 2351 for_each_domain(target, sd) {
2350 if (!(sd->flags & SD_SHARE_PKG_RESOURCES)) 2352 if (!smt && (sd->flags & SD_SHARE_CPUPOWER))
2351 break; 2353 continue;
2352 2354
2353 for_each_cpu_and(i, sched_domain_span(sd), tsk_cpus_allowed(p)) { 2355 if (!(sd->flags & SD_SHARE_PKG_RESOURCES)) {
2354 if (idle_cpu(i)) { 2356 if (!smt) {
2355 target = i; 2357 smt = 1;
2356 break; 2358 goto again;
2357 } 2359 }
2360 break;
2358 } 2361 }
2359 2362
2360 /* 2363 sg = sd->groups;
2361 * Lets stop looking for an idle sibling when we reached 2364 do {
2362 * the domain that spans the current cpu and prev_cpu. 2365 if (!cpumask_intersects(sched_group_cpus(sg),
2363 */ 2366 tsk_cpus_allowed(p)))
2364 if (cpumask_test_cpu(cpu, sched_domain_span(sd)) && 2367 goto next;
2365 cpumask_test_cpu(prev_cpu, sched_domain_span(sd))) 2368
2366 break; 2369 for_each_cpu(i, sched_group_cpus(sg)) {
2370 if (!idle_cpu(i))
2371 goto next;
2372 }
2373
2374 target = cpumask_first_and(sched_group_cpus(sg),
2375 tsk_cpus_allowed(p));
2376 goto done;
2377next:
2378 sg = sg->next;
2379 } while (sg != sd->groups);
2367 } 2380 }
2381done:
2368 rcu_read_unlock(); 2382 rcu_read_unlock();
2369 2383
2370 return target; 2384 return target;