aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/sched.c76
1 files changed, 31 insertions, 45 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index 03d737791c1a..41e69b5ee652 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -1995,7 +1995,7 @@ static int load_balance(int this_cpu, runqueue_t *this_rq,
1995 * We've kicked active balancing, reset the failure 1995 * We've kicked active balancing, reset the failure
1996 * counter. 1996 * counter.
1997 */ 1997 */
1998 sd->nr_balance_failed = sd->cache_nice_tries; 1998 sd->nr_balance_failed = sd->cache_nice_tries+1;
1999 } 1999 }
2000 } else 2000 } else
2001 sd->nr_balance_failed = 0; 2001 sd->nr_balance_failed = 0;
@@ -2106,56 +2106,42 @@ static inline void idle_balance(int this_cpu, runqueue_t *this_rq)
2106static void active_load_balance(runqueue_t *busiest_rq, int busiest_cpu) 2106static void active_load_balance(runqueue_t *busiest_rq, int busiest_cpu)
2107{ 2107{
2108 struct sched_domain *sd; 2108 struct sched_domain *sd;
2109 struct sched_group *cpu_group;
2110 runqueue_t *target_rq; 2109 runqueue_t *target_rq;
2111 cpumask_t visited_cpus; 2110 int target_cpu = busiest_rq->push_cpu;
2112 int cpu; 2111
2112 if (busiest_rq->nr_running <= 1)
2113 /* no task to move */
2114 return;
2115
2116 target_rq = cpu_rq(target_cpu);
2113 2117
2114 /* 2118 /*
2115 * Search for suitable CPUs to push tasks to in successively higher 2119 * This condition is "impossible", if it occurs
2116 * domains with SD_LOAD_BALANCE set. 2120 * we need to fix it. Originally reported by
2121 * Bjorn Helgaas on a 128-cpu setup.
2117 */ 2122 */
2118 visited_cpus = CPU_MASK_NONE; 2123 BUG_ON(busiest_rq == target_rq);
2119 for_each_domain(busiest_cpu, sd) {
2120 if (!(sd->flags & SD_LOAD_BALANCE))
2121 /* no more domains to search */
2122 break;
2123 2124
2124 schedstat_inc(sd, alb_cnt); 2125 /* move a task from busiest_rq to target_rq */
2126 double_lock_balance(busiest_rq, target_rq);
2125 2127
2126 cpu_group = sd->groups; 2128 /* Search for an sd spanning us and the target CPU. */
2127 do { 2129 for_each_domain(target_cpu, sd)
2128 for_each_cpu_mask(cpu, cpu_group->cpumask) { 2130 if ((sd->flags & SD_LOAD_BALANCE) &&
2129 if (busiest_rq->nr_running <= 1) 2131 cpu_isset(busiest_cpu, sd->span))
2130 /* no more tasks left to move */ 2132 break;
2131 return; 2133
2132 if (cpu_isset(cpu, visited_cpus)) 2134 if (unlikely(sd == NULL))
2133 continue; 2135 goto out;
2134 cpu_set(cpu, visited_cpus); 2136
2135 if (!cpu_and_siblings_are_idle(cpu) || cpu == busiest_cpu) 2137 schedstat_inc(sd, alb_cnt);
2136 continue; 2138
2137 2139 if (move_tasks(target_rq, target_cpu, busiest_rq, 1, sd, SCHED_IDLE, NULL))
2138 target_rq = cpu_rq(cpu); 2140 schedstat_inc(sd, alb_pushed);
2139 /* 2141 else
2140 * This condition is "impossible", if it occurs 2142 schedstat_inc(sd, alb_failed);
2141 * we need to fix it. Originally reported by 2143out:
2142 * Bjorn Helgaas on a 128-cpu setup. 2144 spin_unlock(&target_rq->lock);
2143 */
2144 BUG_ON(busiest_rq == target_rq);
2145
2146 /* move a task from busiest_rq to target_rq */
2147 double_lock_balance(busiest_rq, target_rq);
2148 if (move_tasks(target_rq, cpu, busiest_rq,
2149 1, sd, SCHED_IDLE, NULL)) {
2150 schedstat_inc(sd, alb_pushed);
2151 } else {
2152 schedstat_inc(sd, alb_failed);
2153 }
2154 spin_unlock(&target_rq->lock);
2155 }
2156 cpu_group = cpu_group->next;
2157 } while (cpu_group != sd->groups);
2158 }
2159} 2145}
2160 2146
2161/* 2147/*