aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched_fair.c
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2011-07-13 07:09:25 -0400
committerIngo Molnar <mingo@elte.hu>2011-07-21 12:01:46 -0400
commit9763b67fb9f3050c6da739105888327587c30c4d (patch)
tree822e6a5243c3d872f86d9c9b980896bc4cd8a491 /kernel/sched_fair.c
parent9598c82dcacadc3b9daa8170613fd054c6124d30 (diff)
sched, cgroup: Optimize load_balance_fair()
Use for_each_leaf_cfs_rq() instead of list_for_each_entry_rcu(), this achieves that load_balance_fair() only iterates those task_groups that actually have tasks on busiest, and that we iterate bottom-up, trying to move light groups before the heavier ones. No idea if it will actually work out to be beneficial in practice, does anybody have a cgroup workload that might show a difference one way or the other? [ Also move update_h_load to sched_fair.c, loosing #ifdef-ery ] Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Reviewed-by: Paul Turner <pjt@google.com> Link: http://lkml.kernel.org/r/1310557009.2586.28.camel@twins Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/sched_fair.c')
-rw-r--r--kernel/sched_fair.c40
1 files changed, 35 insertions, 5 deletions
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
index 6cdff849fc19..180bcf1efa79 100644
--- a/kernel/sched_fair.c
+++ b/kernel/sched_fair.c
@@ -2232,11 +2232,43 @@ static void update_shares(int cpu)
2232 struct rq *rq = cpu_rq(cpu); 2232 struct rq *rq = cpu_rq(cpu);
2233 2233
2234 rcu_read_lock(); 2234 rcu_read_lock();
2235 /*
2236 * Iterates the task_group tree in a bottom up fashion, see
2237 * list_add_leaf_cfs_rq() for details.
2238 */
2235 for_each_leaf_cfs_rq(rq, cfs_rq) 2239 for_each_leaf_cfs_rq(rq, cfs_rq)
2236 update_shares_cpu(cfs_rq->tg, cpu); 2240 update_shares_cpu(cfs_rq->tg, cpu);
2237 rcu_read_unlock(); 2241 rcu_read_unlock();
2238} 2242}
2239 2243
2244/*
2245 * Compute the cpu's hierarchical load factor for each task group.
2246 * This needs to be done in a top-down fashion because the load of a child
2247 * group is a fraction of its parents load.
2248 */
2249static int tg_load_down(struct task_group *tg, void *data)
2250{
2251 unsigned long load;
2252 long cpu = (long)data;
2253
2254 if (!tg->parent) {
2255 load = cpu_rq(cpu)->load.weight;
2256 } else {
2257 load = tg->parent->cfs_rq[cpu]->h_load;
2258 load *= tg->se[cpu]->load.weight;
2259 load /= tg->parent->cfs_rq[cpu]->load.weight + 1;
2260 }
2261
2262 tg->cfs_rq[cpu]->h_load = load;
2263
2264 return 0;
2265}
2266
2267static void update_h_load(long cpu)
2268{
2269 walk_tg_tree(tg_load_down, tg_nop, (void *)cpu);
2270}
2271
2240static unsigned long 2272static unsigned long
2241load_balance_fair(struct rq *this_rq, int this_cpu, struct rq *busiest, 2273load_balance_fair(struct rq *this_rq, int this_cpu, struct rq *busiest,
2242 unsigned long max_load_move, 2274 unsigned long max_load_move,
@@ -2244,14 +2276,12 @@ load_balance_fair(struct rq *this_rq, int this_cpu, struct rq *busiest,
2244 int *all_pinned) 2276 int *all_pinned)
2245{ 2277{
2246 long rem_load_move = max_load_move; 2278 long rem_load_move = max_load_move;
2247 int busiest_cpu = cpu_of(busiest); 2279 struct cfs_rq *busiest_cfs_rq;
2248 struct task_group *tg;
2249 2280
2250 rcu_read_lock(); 2281 rcu_read_lock();
2251 update_h_load(busiest_cpu); 2282 update_h_load(cpu_of(busiest));
2252 2283
2253 list_for_each_entry_rcu(tg, &task_groups, list) { 2284 for_each_leaf_cfs_rq(busiest, busiest_cfs_rq) {
2254 struct cfs_rq *busiest_cfs_rq = tg->cfs_rq[busiest_cpu];
2255 unsigned long busiest_h_load = busiest_cfs_rq->h_load; 2285 unsigned long busiest_h_load = busiest_cfs_rq->h_load;
2256 unsigned long busiest_weight = busiest_cfs_rq->load.weight; 2286 unsigned long busiest_weight = busiest_cfs_rq->load.weight;
2257 u64 rem_load, moved_load; 2287 u64 rem_load, moved_load;