diff options
author | Peter Zijlstra <peterz@infradead.org> | 2011-11-10 07:01:10 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-11-16 02:43:43 -0500 |
commit | 4dcfe1025b513c2c1da5bf5586adb0e80148f612 (patch) | |
tree | 1c0bf8ad4c09a3a618c471b6468873d8d8ed2117 | |
parent | f1c6f1a7eed963ed233ba4c8b6fa8addb86c6ddc (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>
-rw-r--r-- | kernel/sched_fair.c | 42 |
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(); |
2350 | again: | ||
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; | ||
2377 | next: | ||
2378 | sg = sg->next; | ||
2379 | } while (sg != sd->groups); | ||
2367 | } | 2380 | } |
2381 | done: | ||
2368 | rcu_read_unlock(); | 2382 | rcu_read_unlock(); |
2369 | 2383 | ||
2370 | return target; | 2384 | return target; |