Skip to content

Commit

Permalink
sched: Fix select_idle_sibling() bouncing cow syndrome
Browse files Browse the repository at this point in the history
If the previous CPU is cache affine and idle, select it.

The current implementation simply traverses the sd_llc domain,
taking the first idle CPU encountered, which walks buddy pairs
hand in hand over the package, inflicting excruciating pain.

1 tbench pair (worst case) in a 10 core + SMT package:

  pre   15.22 MB/sec 1 procs
  post 252.01 MB/sec 1 procs

Signed-off-by: Mike Galbraith <bitbucket@online.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1359371965.5783.127.camel@marge.simpson.net
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Mike Galbraith authored and Ingo Molnar committed Feb 4, 2013
1 parent 60334ca commit e0a79f5
Showing 1 changed file with 7 additions and 14 deletions.
21 changes: 7 additions & 14 deletions kernel/sched/fair.c
Original file line number Diff line number Diff line change
Expand Up @@ -3252,25 +3252,18 @@ find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu)
*/
static int select_idle_sibling(struct task_struct *p, int target)
{
int cpu = smp_processor_id();
int prev_cpu = task_cpu(p);
struct sched_domain *sd;
struct sched_group *sg;
int i;
int i = task_cpu(p);

/*
* If the task is going to be woken-up on this cpu and if it is
* already idle, then it is the right target.
*/
if (target == cpu && idle_cpu(cpu))
return cpu;
if (idle_cpu(target))
return target;

/*
* If the task is going to be woken-up on the cpu where it previously
* ran and if it is currently idle, then it the right target.
* If the prevous cpu is cache affine and idle, don't be stupid.
*/
if (target == prev_cpu && idle_cpu(prev_cpu))
return prev_cpu;
if (i != target && cpus_share_cache(i, target) && idle_cpu(i))
return i;

/*
* Otherwise, iterate the domains and find an elegible idle cpu.
Expand All @@ -3284,7 +3277,7 @@ static int select_idle_sibling(struct task_struct *p, int target)
goto next;

for_each_cpu(i, sched_group_cpus(sg)) {
if (!idle_cpu(i))
if (i == target || !idle_cpu(i))
goto next;
}

Expand Down

0 comments on commit e0a79f5

Please sign in to comment.