sched: fix sync wakeups
authorPeter Zijlstra <a.p.zijlstra@chello.nl>
Mon, 26 Jan 2009 16:56:17 +0000 (17:56 +0100)
committerIngo Molnar <mingo@elte.hu>
Sun, 1 Feb 2009 09:49:06 +0000 (10:49 +0100)
Pawel Dziekonski reported that the openssl benchmark and his
quantum chemistry application both show slowdowns due to the
scheduler under-parallelizing execution.

The reason are pipe wakeups still doing 'sync' wakeups which
overrides the normal buddy wakeup logic - even if waker and
wakee are loosely coupled.

Fix an inversion of logic in the buddy wakeup code.

Reported-by: Pawel Dziekonski <dzieko@gmail.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
kernel/sched.c
kernel/sched_fair.c

index 52bbf1c842a8e0baecd1cd9f53883806eaab1350..770b1f9ebe14e576186245dcc72c58588cb40c46 100644 (file)
@@ -2266,6 +2266,10 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync)
        if (!sched_feat(SYNC_WAKEUPS))
                sync = 0;
 
+       if (!sync && (current->se.avg_overlap < sysctl_sched_migration_cost &&
+                           p->se.avg_overlap < sysctl_sched_migration_cost))
+               sync = 1;
+
 #ifdef CONFIG_SMP
        if (sched_feat(LB_WAKEUP_UPDATE)) {
                struct sched_domain *sd;
index 5cc1c162044fc4f40b15c351cd170ce2c58703f7..fdc417504681af17114c9fbf79e809dad02e2e23 100644 (file)
@@ -1179,20 +1179,15 @@ wake_affine(struct sched_domain *this_sd, struct rq *this_rq,
            int idx, unsigned long load, unsigned long this_load,
            unsigned int imbalance)
 {
-       struct task_struct *curr = this_rq->curr;
-       struct task_group *tg;
        unsigned long tl = this_load;
        unsigned long tl_per_task;
+       struct task_group *tg;
        unsigned long weight;
        int balanced;
 
        if (!(this_sd->flags & SD_WAKE_AFFINE) || !sched_feat(AFFINE_WAKEUPS))
                return 0;
 
-       if (sync && (curr->se.avg_overlap > sysctl_sched_migration_cost ||
-                       p->se.avg_overlap > sysctl_sched_migration_cost))
-               sync = 0;
-
        /*
         * If sync wakeup then subtract the (maximum possible)
         * effect of the currently running task from the load
@@ -1419,9 +1414,7 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int sync)
        if (!sched_feat(WAKEUP_PREEMPT))
                return;
 
-       if (sched_feat(WAKEUP_OVERLAP) && (sync ||
-                       (se->avg_overlap < sysctl_sched_migration_cost &&
-                        pse->avg_overlap < sysctl_sched_migration_cost))) {
+       if (sched_feat(WAKEUP_OVERLAP) && sync) {
                resched_task(curr);
                return;
        }