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 /kernel | |
| 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>
Diffstat (limited to 'kernel')
| -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; |
