Skip to content

Commit

Permalink
sched: Do less agressive buddy clearing
Browse files Browse the repository at this point in the history
Yanmin reported a hackbench regression due to:

 > commit de69a80
 > Author: Peter Zijlstra <a.p.zijlstra@chello.nl>
 > Date:   Thu Sep 17 09:01:20 2009 +0200
 >
 >     sched: Stop buddies from hogging the system

I really liked de69a80, and it affecting hackbench shows I wasn't
crazy ;-)

So hackbench is a multi-cast, with one sender spraying multiple
receivers, who in their turn don't spray back.

This would be exactly the scenario that patch 'cures'. Previously
we would not clear the last buddy after running the next task,
allowing the sender to get back to work sooner than it otherwise
ought to have been, increasing latencies for other tasks.

Now, since those receivers don't poke back, they don't enforce the
buddy relation, which means there's nothing to re-elect the sender.

Cure this by less agressively clearing the buddy stats. Only clear
buddies when they were not chosen. It should still avoid a buddy
sticking around long after its served its time.

Reported-by: "Zhang, Yanmin" <yanmin_zhang@linux.intel.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
CC: Mike Galbraith <efault@gmx.de>
LKML-Reference: <1255084986.8802.46.camel@laptop>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
Peter Zijlstra authored and Ingo Molnar committed Oct 14, 2009
1 parent 799e220 commit 92f6a5e
Showing 1 changed file with 13 additions and 14 deletions.
27 changes: 13 additions & 14 deletions kernel/sched_fair.c
Original file line number Diff line number Diff line change
Expand Up @@ -861,12 +861,21 @@ wakeup_preempt_entity(struct sched_entity *curr, struct sched_entity *se);
static struct sched_entity *pick_next_entity(struct cfs_rq *cfs_rq)
{
struct sched_entity *se = __pick_next_entity(cfs_rq);
struct sched_entity *buddy;

if (cfs_rq->next && wakeup_preempt_entity(cfs_rq->next, se) < 1)
return cfs_rq->next;
if (cfs_rq->next) {
buddy = cfs_rq->next;
cfs_rq->next = NULL;
if (wakeup_preempt_entity(buddy, se) < 1)
return buddy;
}

if (cfs_rq->last && wakeup_preempt_entity(cfs_rq->last, se) < 1)
return cfs_rq->last;
if (cfs_rq->last) {
buddy = cfs_rq->last;
cfs_rq->last = NULL;
if (wakeup_preempt_entity(buddy, se) < 1)
return buddy;
}

return se;
}
Expand Down Expand Up @@ -1654,16 +1663,6 @@ static struct task_struct *pick_next_task_fair(struct rq *rq)

do {
se = pick_next_entity(cfs_rq);
/*
* If se was a buddy, clear it so that it will have to earn
* the favour again.
*
* If se was not a buddy, clear the buddies because neither
* was elegible to run, let them earn it again.
*
* IOW. unconditionally clear buddies.
*/
__clear_buddies(cfs_rq, NULL);
set_next_entity(cfs_rq, se);
cfs_rq = group_cfs_rq(se);
} while (cfs_rq);
Expand Down

0 comments on commit 92f6a5e

Please sign in to comment.