aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched_fair.c
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2009-09-17 03:01:20 -0400
committerIngo Molnar <mingo@elte.hu>2009-09-17 04:40:30 -0400
commitde69a80be32445b0a71e8e3b757e584d7beb90f7 (patch)
tree3a8d6bf8e5aded3c371e5dc090b8874305952d1f /kernel/sched_fair.c
parentad4b78bbcbab66998b05d422ac6106b645796e54 (diff)
sched: Stop buddies from hogging the system
Clear buddies more agressively. The (theoretical, haven't actually observed any of this) problem is that when we do not select either buddy in pick_next_entity() because they are too far ahead of the left-most task, we do not clear the buddies. This means that as soon as we service the left-most task, these same buddies will be tried again on the next schedule. Now if the left-most task was a pure hog, it wouldn't have done any wakeups and it wouldn't have set buddies of its own. That leads to the old buddies dominating, which would lead to bad latencies. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/sched_fair.c')
-rw-r--r--kernel/sched_fair.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
index 3e6f78c66876..ffee827fa22f 100644
--- a/kernel/sched_fair.c
+++ b/kernel/sched_fair.c
@@ -764,10 +764,10 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int wakeup)
764 764
765static void __clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se) 765static void __clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se)
766{ 766{
767 if (cfs_rq->last == se) 767 if (!se || cfs_rq->last == se)
768 cfs_rq->last = NULL; 768 cfs_rq->last = NULL;
769 769
770 if (cfs_rq->next == se) 770 if (!se || cfs_rq->next == se)
771 cfs_rq->next = NULL; 771 cfs_rq->next = NULL;
772} 772}
773 773
@@ -1646,8 +1646,13 @@ static struct task_struct *pick_next_task_fair(struct rq *rq)
1646 /* 1646 /*
1647 * If se was a buddy, clear it so that it will have to earn 1647 * If se was a buddy, clear it so that it will have to earn
1648 * the favour again. 1648 * the favour again.
1649 *
1650 * If se was not a buddy, clear the buddies because neither
1651 * was elegible to run, let them earn it again.
1652 *
1653 * IOW. unconditionally clear buddies.
1649 */ 1654 */
1650 __clear_buddies(cfs_rq, se); 1655 __clear_buddies(cfs_rq, NULL);
1651 set_next_entity(cfs_rq, se); 1656 set_next_entity(cfs_rq, se);
1652 cfs_rq = group_cfs_rq(se); 1657 cfs_rq = group_cfs_rq(se);
1653 } while (cfs_rq); 1658 } while (cfs_rq);