Index: MM-2.6.X/kernel/sched.c =================================================================== --- MM-2.6.X.orig/kernel/sched.c 2006-02-13 10:23:12.000000000 +1100 +++ MM-2.6.X/kernel/sched.c 2006-02-13 11:46:41.000000000 +1100 @@ -2033,9 +2033,11 @@ find_busiest_group(struct sched_domain * struct sched_group *busiest = NULL, *this = NULL, *group = sd->groups; unsigned long max_load, avg_load, total_load, this_load, total_pwr; unsigned long max_pull; + unsigned long avg_bias_prio, busiest_prio_bias, busiest_nr_running; int load_idx; max_load = this_load = total_load = total_pwr = 0; + busiest_prio_bias = busiest_nr_running = 0; if (idle == NOT_IDLE) load_idx = sd->busy_idx; else if (idle == NEWLY_IDLE) @@ -2047,13 +2049,16 @@ find_busiest_group(struct sched_domain * unsigned long load; int local_group; int i; + unsigned long sum_prio_bias, sum_nr_running; local_group = cpu_isset(this_cpu, group->cpumask); /* Tally up the load of all CPUs in the group */ - avg_load = 0; + sum_prio_bias = sum_nr_running = avg_load = 0; for_each_cpu_mask(i, group->cpumask) { + runqueue_t *rq = cpu_rq(i); + if (*sd_idle && !idle_cpu(i)) *sd_idle = 0; @@ -2064,6 +2069,8 @@ find_busiest_group(struct sched_domain * load = source_load(i, load_idx); avg_load += load; + sum_prio_bias += rq->prio_bias; + sum_nr_running += rq->nr_running; } total_load += avg_load; @@ -2078,6 +2085,8 @@ find_busiest_group(struct sched_domain * } else if (avg_load > max_load) { max_load = avg_load; busiest = group; + busiest_prio_bias = sum_prio_bias; + busiest_nr_running = sum_nr_running; } group = group->next; } while (group != sd->groups); @@ -2111,12 +2120,25 @@ find_busiest_group(struct sched_domain * (avg_load - this_load) * this->cpu_power) / SCHED_LOAD_SCALE; - if (*imbalance < SCHED_LOAD_SCALE) { + /* assume that busiest_nr_running > 0 */ + avg_bias_prio = busiest_prio_bias / busiest_nr_running; + /* + * Get rid of the scaling factor, rounding down as we divide and + * converting to biased load for use by move_tasks() + */ + *imbalance = biased_load(*imbalance); + /* + * if *imbalance is less than the average runnable task biased prio + * there is no gaurantee that any tasks will be moved so we'll have + * a think about bumping its value to force at least one task to be + * moved + */ + if (*imbalance < avg_bias_prio) { unsigned long pwr_now = 0, pwr_move = 0; unsigned long tmp; - if (max_load - this_load >= SCHED_LOAD_SCALE*2) { - *imbalance = NICE_TO_BIAS_PRIO(0); + if (biased_load(max_load - this_load) >= avg_bias_prio*2) { + *imbalance = avg_bias_prio; return busiest; } @@ -2146,18 +2168,19 @@ find_busiest_group(struct sched_domain * pwr_move /= SCHED_LOAD_SCALE; /* Move if we gain throughput */ - if (pwr_move <= pwr_now) - goto out_balanced; + if (pwr_move <= pwr_now) { + /* or if there's a reasonable chance that *imbalance + * is big enough to cause a move + */ + if (*imbalance <= avg_bias_prio / 2) + goto out_balanced; + else + return busiest; + } - *imbalance = NICE_TO_BIAS_PRIO(0); - return busiest; + *imbalance = avg_bias_prio; } - /* - * Get rid of the scaling factor, rounding down as we divide and - * converting to biased load for use by move_tasks() - */ - *imbalance = biased_load(*imbalance); return busiest; out_balanced: