Index: MM-2.6.17-rc1-mm3/kernel/sched.c =================================================================== --- MM-2.6.17-rc1-mm3.orig/kernel/sched.c 2006-04-21 12:19:30.000000000 +1000 +++ MM-2.6.17-rc1-mm3/kernel/sched.c 2006-04-21 12:26:54.000000000 +1000 @@ -2029,6 +2029,7 @@ int can_migrate_task(task_t *p, runqueue return 1; } +#define rq_best_prio(rq) min((rq)->curr->prio, (rq)->best_expired_prio) /* * move_tasks tries to move up to max_nr_move tasks and max_load_move weighted * load from busiest to this_rq, as part of a balancing operation within @@ -2043,7 +2044,9 @@ static int move_tasks(runqueue_t *this_r { prio_array_t *array, *dst_array; struct list_head *head, *curr; - int idx, pulled = 0, pinned = 0, this_min_prio; + int idx, pulled = 0, pinned = 0, this_best_prio, busiest_best_prio; + int busiest_best_prio_seen; + int skip_for_load; /* skip the task based on weighted load issues */ long rem_load_move; task_t *tmp; @@ -2052,7 +2055,13 @@ static int move_tasks(runqueue_t *this_r rem_load_move = max_load_move; pinned = 1; - this_min_prio = this_rq->curr->prio; + this_best_prio = rq_best_prio(this_rq); + busiest_best_prio = rq_best_prio(busiest); + /* + * Enable handling of the case where there is more than one task + * with the best priority. + */ + busiest_best_prio_seen = busiest_best_prio == busiest->curr->prio; /* * We first consider expired tasks. Those will likely not be @@ -2097,7 +2106,10 @@ skip_queue: * skip a task if it will be the highest priority task (i.e. smallest * prio value) on its new queue regardless of its load weight */ - if ((idx >= this_min_prio && tmp->load_weight > rem_load_move) || + skip_for_load = tmp->load_weight > rem_load_move; + if (skip_for_load && idx < this_best_prio) + skip_for_load = busiest_best_prio_seen || idx != busiest_best_prio; + if (skip_for_load || !can_migrate_task(tmp, busiest, this_cpu, sd, idle, &pinned)) { if (curr != head) goto skip_queue; @@ -2119,8 +2131,10 @@ skip_queue: * and the prescribed amount of weighted load. */ if (pulled < max_nr_move && rem_load_move > 0) { - if (idx < this_min_prio) - this_min_prio = idx; + if (idx < this_best_prio) + this_best_prio = idx; + if (idx == busiest_best_prio) + busiest_best_prio_seen = 1; if (curr != head) goto skip_queue; idx++;