aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched.c
diff options
context:
space:
mode:
authorPeter Williams <pwil3058@bigpond.net.au>2007-10-24 12:23:51 -0400
committerIngo Molnar <mingo@elte.hu>2007-10-24 12:23:51 -0400
commite1d1484f72127a5580d37c379f6a5b2c2786434c (patch)
treee3e6529c5b9079f35b2c60bbd346a3c51c2b2c13 /kernel/sched.c
parenta0f846aa76c3e03d54c1700a87cab3a46ccd71e2 (diff)
sched: reduce balance-tasks overhead
At the moment, balance_tasks() provides low level functionality for both move_tasks() and move_one_task() (indirectly) via the load_balance() function (in the sched_class interface) which also provides dual functionality. This dual functionality complicates the interfaces and internal mechanisms and makes the run time overhead of operations that are called with two run queue locks held. This patch addresses this issue and reduces the overhead of these operations. Signed-off-by: Peter Williams <pwil3058@bigpond.net.au> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/sched.c')
-rw-r--r--kernel/sched.c99
1 files changed, 67 insertions, 32 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index cc9cd5b710a6..8607795fad69 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -838,11 +838,35 @@ struct rq_iterator {
838 struct task_struct *(*next)(void *); 838 struct task_struct *(*next)(void *);
839}; 839};
840 840
841static int balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest, 841#ifdef CONFIG_SMP
842 unsigned long max_nr_move, unsigned long max_load_move, 842static unsigned long
843 struct sched_domain *sd, enum cpu_idle_type idle, 843balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
844 int *all_pinned, unsigned long *load_moved, 844 unsigned long max_load_move, struct sched_domain *sd,
845 int *this_best_prio, struct rq_iterator *iterator); 845 enum cpu_idle_type idle, int *all_pinned,
846 int *this_best_prio, struct rq_iterator *iterator);
847
848static int
849iter_move_one_task(struct rq *this_rq, int this_cpu, struct rq *busiest,
850 struct sched_domain *sd, enum cpu_idle_type idle,
851 struct rq_iterator *iterator);
852#else
853static inline unsigned long
854balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
855 unsigned long max_load_move, struct sched_domain *sd,
856 enum cpu_idle_type idle, int *all_pinned,
857 int *this_best_prio, struct rq_iterator *iterator)
858{
859 return 0;
860}
861
862static inline int
863iter_move_one_task(struct rq *this_rq, int this_cpu, struct rq *busiest,
864 struct sched_domain *sd, enum cpu_idle_type idle,
865 struct rq_iterator *iterator)
866{
867 return 0;
868}
869#endif
846 870
847#include "sched_stats.h" 871#include "sched_stats.h"
848#include "sched_idletask.c" 872#include "sched_idletask.c"
@@ -2224,17 +2248,17 @@ int can_migrate_task(struct task_struct *p, struct rq *rq, int this_cpu,
2224 return 1; 2248 return 1;
2225} 2249}
2226 2250
2227static int balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest, 2251static unsigned long
2228 unsigned long max_nr_move, unsigned long max_load_move, 2252balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
2229 struct sched_domain *sd, enum cpu_idle_type idle, 2253 unsigned long max_load_move, struct sched_domain *sd,
2230 int *all_pinned, unsigned long *load_moved, 2254 enum cpu_idle_type idle, int *all_pinned,
2231 int *this_best_prio, struct rq_iterator *iterator) 2255 int *this_best_prio, struct rq_iterator *iterator)
2232{ 2256{
2233 int pulled = 0, pinned = 0, skip_for_load; 2257 int pulled = 0, pinned = 0, skip_for_load;
2234 struct task_struct *p; 2258 struct task_struct *p;
2235 long rem_load_move = max_load_move; 2259 long rem_load_move = max_load_move;
2236 2260
2237 if (max_nr_move == 0 || max_load_move == 0) 2261 if (max_load_move == 0)
2238 goto out; 2262 goto out;
2239 2263
2240 pinned = 1; 2264 pinned = 1;
@@ -2267,7 +2291,7 @@ next:
2267 * We only want to steal up to the prescribed number of tasks 2291 * We only want to steal up to the prescribed number of tasks
2268 * and the prescribed amount of weighted load. 2292 * and the prescribed amount of weighted load.
2269 */ 2293 */
2270 if (pulled < max_nr_move && rem_load_move > 0) { 2294 if (rem_load_move > 0) {
2271 if (p->prio < *this_best_prio) 2295 if (p->prio < *this_best_prio)
2272 *this_best_prio = p->prio; 2296 *this_best_prio = p->prio;
2273 p = iterator->next(iterator->arg); 2297 p = iterator->next(iterator->arg);
@@ -2275,7 +2299,7 @@ next:
2275 } 2299 }
2276out: 2300out:
2277 /* 2301 /*
2278 * Right now, this is the only place pull_task() is called, 2302 * Right now, this is one of only two places pull_task() is called,
2279 * so we can safely collect pull_task() stats here rather than 2303 * so we can safely collect pull_task() stats here rather than
2280 * inside pull_task(). 2304 * inside pull_task().
2281 */ 2305 */
@@ -2283,8 +2307,8 @@ out:
2283 2307
2284 if (all_pinned) 2308 if (all_pinned)
2285 *all_pinned = pinned; 2309 *all_pinned = pinned;
2286 *load_moved = max_load_move - rem_load_move; 2310
2287 return pulled; 2311 return max_load_move - rem_load_move;
2288} 2312}
2289 2313
2290/* 2314/*
@@ -2306,7 +2330,7 @@ static int move_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
2306 do { 2330 do {
2307 total_load_moved += 2331 total_load_moved +=
2308 class->load_balance(this_rq, this_cpu, busiest, 2332 class->load_balance(this_rq, this_cpu, busiest,
2309 ULONG_MAX, max_load_move - total_load_moved, 2333 max_load_move - total_load_moved,
2310 sd, idle, all_pinned, &this_best_prio); 2334 sd, idle, all_pinned, &this_best_prio);
2311 class = class->next; 2335 class = class->next;
2312 } while (class && max_load_move > total_load_moved); 2336 } while (class && max_load_move > total_load_moved);
@@ -2314,6 +2338,32 @@ static int move_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
2314 return total_load_moved > 0; 2338 return total_load_moved > 0;
2315} 2339}
2316 2340
2341static int
2342iter_move_one_task(struct rq *this_rq, int this_cpu, struct rq *busiest,
2343 struct sched_domain *sd, enum cpu_idle_type idle,
2344 struct rq_iterator *iterator)
2345{
2346 struct task_struct *p = iterator->start(iterator->arg);
2347 int pinned = 0;
2348
2349 while (p) {
2350 if (can_migrate_task(p, busiest, this_cpu, sd, idle, &pinned)) {
2351 pull_task(busiest, p, this_rq, this_cpu);
2352 /*
2353 * Right now, this is only the second place pull_task()
2354 * is called, so we can safely collect pull_task()
2355 * stats here rather than inside pull_task().
2356 */
2357 schedstat_inc(sd, lb_gained[idle]);
2358
2359 return 1;
2360 }
2361 p = iterator->next(iterator->arg);
2362 }
2363
2364 return 0;
2365}
2366
2317/* 2367/*
2318 * move_one_task tries to move exactly one task from busiest to this_rq, as 2368 * move_one_task tries to move exactly one task from busiest to this_rq, as
2319 * part of active balancing operations within "domain". 2369 * part of active balancing operations within "domain".
@@ -2325,12 +2375,9 @@ static int move_one_task(struct rq *this_rq, int this_cpu, struct rq *busiest,
2325 struct sched_domain *sd, enum cpu_idle_type idle) 2375 struct sched_domain *sd, enum cpu_idle_type idle)
2326{ 2376{
2327 const struct sched_class *class; 2377 const struct sched_class *class;
2328 int this_best_prio = MAX_PRIO;
2329 2378
2330 for (class = sched_class_highest; class; class = class->next) 2379 for (class = sched_class_highest; class; class = class->next)
2331 if (class->load_balance(this_rq, this_cpu, busiest, 2380 if (class->move_one_task(this_rq, this_cpu, busiest, sd, idle))
2332 1, ULONG_MAX, sd, idle, NULL,
2333 &this_best_prio))
2334 return 1; 2381 return 1;
2335 2382
2336 return 0; 2383 return 0;
@@ -3267,18 +3314,6 @@ static inline void idle_balance(int cpu, struct rq *rq)
3267{ 3314{
3268} 3315}
3269 3316
3270/* Avoid "used but not defined" warning on UP */
3271static int balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
3272 unsigned long max_nr_move, unsigned long max_load_move,
3273 struct sched_domain *sd, enum cpu_idle_type idle,
3274 int *all_pinned, unsigned long *load_moved,
3275 int *this_best_prio, struct rq_iterator *iterator)
3276{
3277 *load_moved = 0;
3278
3279 return 0;
3280}
3281
3282#endif 3317#endif
3283 3318
3284DEFINE_PER_CPU(struct kernel_stat, kstat); 3319DEFINE_PER_CPU(struct kernel_stat, kstat);