aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched/fair.c
diff options
context:
space:
mode:
authorJoonsoo Kim <iamjoonsoo.kim@lge.com>2013-08-06 04:36:42 -0400
committerIngo Molnar <mingo@kernel.org>2013-09-02 02:27:34 -0400
commit23f0d2093c789e612185180c468fa09063834e87 (patch)
tree63e1fb698d9e4e66d7932f7195af8f94e8f4004b /kernel/sched/fair.c
parent95a79b805b935f4a7b685aa8a117d916c638323e (diff)
sched: Factor out code to should_we_balance()
Now checking whether this cpu is appropriate to balance or not is embedded into update_sg_lb_stats() and this checking has no direct relationship to this function. There is not enough reason to place this checking at update_sg_lb_stats(), except saving one iteration for sched_group_cpus. In this patch, I factor out this checking to should_we_balance() function. And before doing actual work for load_balancing, check whether this cpu is appropriate to balance via should_we_balance(). If this cpu is not a candidate for balancing, it quit the work immediately. With this change, we can save two memset cost and can expect better compiler optimization. Below is result of this patch. * Vanilla * text data bss dec hex filename 34499 1136 116 35751 8ba7 kernel/sched/fair.o * Patched * text data bss dec hex filename 34243 1136 116 35495 8aa7 kernel/sched/fair.o In addition, rename @balance to @continue_balancing in order to represent its purpose more clearly. Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@lge.com> [ s/should_balance/continue_balancing/g ] Reviewed-by: Paul Turner <pjt@google.com> [ Made style changes and a fix in should_we_balance(). ] Signed-off-by: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/1375778203-31343-3-git-send-email-iamjoonsoo.kim@lge.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/sched/fair.c')
-rw-r--r--kernel/sched/fair.c107
1 files changed, 53 insertions, 54 deletions
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 8aa217f62a9e..9a6daf86a76a 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -4463,22 +4463,17 @@ fix_small_capacity(struct sched_domain *sd, struct sched_group *group)
4463 * @group: sched_group whose statistics are to be updated. 4463 * @group: sched_group whose statistics are to be updated.
4464 * @load_idx: Load index of sched_domain of this_cpu for load calc. 4464 * @load_idx: Load index of sched_domain of this_cpu for load calc.
4465 * @local_group: Does group contain this_cpu. 4465 * @local_group: Does group contain this_cpu.
4466 * @balance: Should we balance.
4467 * @sgs: variable to hold the statistics for this group. 4466 * @sgs: variable to hold the statistics for this group.
4468 */ 4467 */
4469static inline void update_sg_lb_stats(struct lb_env *env, 4468static inline void update_sg_lb_stats(struct lb_env *env,
4470 struct sched_group *group, int load_idx, 4469 struct sched_group *group, int load_idx,
4471 int local_group, int *balance, struct sg_lb_stats *sgs) 4470 int local_group, struct sg_lb_stats *sgs)
4472{ 4471{
4473 unsigned long nr_running, max_nr_running, min_nr_running; 4472 unsigned long nr_running, max_nr_running, min_nr_running;
4474 unsigned long load, max_cpu_load, min_cpu_load; 4473 unsigned long load, max_cpu_load, min_cpu_load;
4475 unsigned int balance_cpu = -1, first_idle_cpu = 0;
4476 unsigned long avg_load_per_task = 0; 4474 unsigned long avg_load_per_task = 0;
4477 int i; 4475 int i;
4478 4476
4479 if (local_group)
4480 balance_cpu = group_balance_cpu(group);
4481
4482 /* Tally up the load of all CPUs in the group */ 4477 /* Tally up the load of all CPUs in the group */
4483 max_cpu_load = 0; 4478 max_cpu_load = 0;
4484 min_cpu_load = ~0UL; 4479 min_cpu_load = ~0UL;
@@ -4492,12 +4487,6 @@ static inline void update_sg_lb_stats(struct lb_env *env,
4492 4487
4493 /* Bias balancing toward cpus of our domain */ 4488 /* Bias balancing toward cpus of our domain */
4494 if (local_group) { 4489 if (local_group) {
4495 if (idle_cpu(i) && !first_idle_cpu &&
4496 cpumask_test_cpu(i, sched_group_mask(group))) {
4497 first_idle_cpu = 1;
4498 balance_cpu = i;
4499 }
4500
4501 load = target_load(i, load_idx); 4490 load = target_load(i, load_idx);
4502 } else { 4491 } else {
4503 load = source_load(i, load_idx); 4492 load = source_load(i, load_idx);
@@ -4519,22 +4508,9 @@ static inline void update_sg_lb_stats(struct lb_env *env,
4519 sgs->idle_cpus++; 4508 sgs->idle_cpus++;
4520 } 4509 }
4521 4510
4522 /* 4511 if (local_group && (env->idle != CPU_NEWLY_IDLE ||
4523 * First idle cpu or the first cpu(busiest) in this sched group 4512 time_after_eq(jiffies, group->sgp->next_update)))
4524 * is eligible for doing load balancing at this and above 4513 update_group_power(env->sd, env->dst_cpu);
4525 * domains. In the newly idle case, we will allow all the cpu's
4526 * to do the newly idle load balance.
4527 */
4528 if (local_group) {
4529 if (env->idle != CPU_NEWLY_IDLE) {
4530 if (balance_cpu != env->dst_cpu) {
4531 *balance = 0;
4532 return;
4533 }
4534 update_group_power(env->sd, env->dst_cpu);
4535 } else if (time_after_eq(jiffies, group->sgp->next_update))
4536 update_group_power(env->sd, env->dst_cpu);
4537 }
4538 4514
4539 /* Adjust by relative CPU power of the group */ 4515 /* Adjust by relative CPU power of the group */
4540 sgs->avg_load = (sgs->group_load*SCHED_POWER_SCALE) / group->sgp->power; 4516 sgs->avg_load = (sgs->group_load*SCHED_POWER_SCALE) / group->sgp->power;
@@ -4613,7 +4589,7 @@ static bool update_sd_pick_busiest(struct lb_env *env,
4613 * @sds: variable to hold the statistics for this sched_domain. 4589 * @sds: variable to hold the statistics for this sched_domain.
4614 */ 4590 */
4615static inline void update_sd_lb_stats(struct lb_env *env, 4591static inline void update_sd_lb_stats(struct lb_env *env,
4616 int *balance, struct sd_lb_stats *sds) 4592 struct sd_lb_stats *sds)
4617{ 4593{
4618 struct sched_domain *child = env->sd->child; 4594 struct sched_domain *child = env->sd->child;
4619 struct sched_group *sg = env->sd->groups; 4595 struct sched_group *sg = env->sd->groups;
@@ -4630,10 +4606,7 @@ static inline void update_sd_lb_stats(struct lb_env *env,
4630 4606
4631 local_group = cpumask_test_cpu(env->dst_cpu, sched_group_cpus(sg)); 4607 local_group = cpumask_test_cpu(env->dst_cpu, sched_group_cpus(sg));
4632 memset(&sgs, 0, sizeof(sgs)); 4608 memset(&sgs, 0, sizeof(sgs));
4633 update_sg_lb_stats(env, sg, load_idx, local_group, balance, &sgs); 4609 update_sg_lb_stats(env, sg, load_idx, local_group, &sgs);
4634
4635 if (local_group && !(*balance))
4636 return;
4637 4610
4638 sds->total_load += sgs.group_load; 4611 sds->total_load += sgs.group_load;
4639 sds->total_pwr += sg->sgp->power; 4612 sds->total_pwr += sg->sgp->power;
@@ -4866,8 +4839,6 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s
4866 * to restore balance. 4839 * to restore balance.
4867 * 4840 *
4868 * @env: The load balancing environment. 4841 * @env: The load balancing environment.
4869 * @balance: Pointer to a variable indicating if this_cpu
4870 * is the appropriate cpu to perform load balancing at this_level.
4871 * 4842 *
4872 * Returns: - the busiest group if imbalance exists. 4843 * Returns: - the busiest group if imbalance exists.
4873 * - If no imbalance and user has opted for power-savings balance, 4844 * - If no imbalance and user has opted for power-savings balance,
@@ -4875,7 +4846,7 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s
4875 * put to idle by rebalancing its tasks onto our group. 4846 * put to idle by rebalancing its tasks onto our group.
4876 */ 4847 */
4877static struct sched_group * 4848static struct sched_group *
4878find_busiest_group(struct lb_env *env, int *balance) 4849find_busiest_group(struct lb_env *env)
4879{ 4850{
4880 struct sd_lb_stats sds; 4851 struct sd_lb_stats sds;
4881 4852
@@ -4885,14 +4856,7 @@ find_busiest_group(struct lb_env *env, int *balance)
4885 * Compute the various statistics relavent for load balancing at 4856 * Compute the various statistics relavent for load balancing at
4886 * this level. 4857 * this level.
4887 */ 4858 */
4888 update_sd_lb_stats(env, balance, &sds); 4859 update_sd_lb_stats(env, &sds);
4889
4890 /*
4891 * this_cpu is not the appropriate cpu to perform load balancing at
4892 * this level.
4893 */
4894 if (!(*balance))
4895 goto ret;
4896 4860
4897 if ((env->idle == CPU_IDLE || env->idle == CPU_NEWLY_IDLE) && 4861 if ((env->idle == CPU_IDLE || env->idle == CPU_NEWLY_IDLE) &&
4898 check_asym_packing(env, &sds)) 4862 check_asym_packing(env, &sds))
@@ -4956,7 +4920,6 @@ force_balance:
4956 return sds.busiest; 4920 return sds.busiest;
4957 4921
4958out_balanced: 4922out_balanced:
4959ret:
4960 env->imbalance = 0; 4923 env->imbalance = 0;
4961 return NULL; 4924 return NULL;
4962} 4925}
@@ -5043,13 +5006,47 @@ static int need_active_balance(struct lb_env *env)
5043 5006
5044static int active_load_balance_cpu_stop(void *data); 5007static int active_load_balance_cpu_stop(void *data);
5045 5008
5009static int should_we_balance(struct lb_env *env)
5010{
5011 struct sched_group *sg = env->sd->groups;
5012 struct cpumask *sg_cpus, *sg_mask;
5013 int cpu, balance_cpu = -1;
5014
5015 /*
5016 * In the newly idle case, we will allow all the cpu's
5017 * to do the newly idle load balance.
5018 */
5019 if (env->idle == CPU_NEWLY_IDLE)
5020 return 1;
5021
5022 sg_cpus = sched_group_cpus(sg);
5023 sg_mask = sched_group_mask(sg);
5024 /* Try to find first idle cpu */
5025 for_each_cpu_and(cpu, sg_cpus, env->cpus) {
5026 if (!cpumask_test_cpu(cpu, sg_mask) || !idle_cpu(cpu))
5027 continue;
5028
5029 balance_cpu = cpu;
5030 break;
5031 }
5032
5033 if (balance_cpu == -1)
5034 balance_cpu = group_balance_cpu(sg);
5035
5036 /*
5037 * First idle cpu or the first cpu(busiest) in this sched group
5038 * is eligible for doing load balancing at this and above domains.
5039 */
5040 return balance_cpu != env->dst_cpu;
5041}
5042
5046/* 5043/*
5047 * Check this_cpu to ensure it is balanced within domain. Attempt to move 5044 * Check this_cpu to ensure it is balanced within domain. Attempt to move
5048 * tasks if there is an imbalance. 5045 * tasks if there is an imbalance.
5049 */ 5046 */
5050static int load_balance(int this_cpu, struct rq *this_rq, 5047static int load_balance(int this_cpu, struct rq *this_rq,
5051 struct sched_domain *sd, enum cpu_idle_type idle, 5048 struct sched_domain *sd, enum cpu_idle_type idle,
5052 int *balance) 5049 int *continue_balancing)
5053{ 5050{
5054 int ld_moved, cur_ld_moved, active_balance = 0; 5051 int ld_moved, cur_ld_moved, active_balance = 0;
5055 struct sched_group *group; 5052 struct sched_group *group;
@@ -5079,11 +5076,12 @@ static int load_balance(int this_cpu, struct rq *this_rq,
5079 schedstat_inc(sd, lb_count[idle]); 5076 schedstat_inc(sd, lb_count[idle]);
5080 5077
5081redo: 5078redo:
5082 group = find_busiest_group(&env, balance); 5079 if (!should_we_balance(&env)) {
5083 5080 *continue_balancing = 0;
5084 if (*balance == 0)
5085 goto out_balanced; 5081 goto out_balanced;
5082 }
5086 5083
5084 group = find_busiest_group(&env);
5087 if (!group) { 5085 if (!group) {
5088 schedstat_inc(sd, lb_nobusyg[idle]); 5086 schedstat_inc(sd, lb_nobusyg[idle]);
5089 goto out_balanced; 5087 goto out_balanced;
@@ -5296,7 +5294,7 @@ void idle_balance(int this_cpu, struct rq *this_rq)
5296 rcu_read_lock(); 5294 rcu_read_lock();
5297 for_each_domain(this_cpu, sd) { 5295 for_each_domain(this_cpu, sd) {
5298 unsigned long interval; 5296 unsigned long interval;
5299 int balance = 1; 5297 int continue_balancing = 1;
5300 5298
5301 if (!(sd->flags & SD_LOAD_BALANCE)) 5299 if (!(sd->flags & SD_LOAD_BALANCE))
5302 continue; 5300 continue;
@@ -5304,7 +5302,8 @@ void idle_balance(int this_cpu, struct rq *this_rq)
5304 if (sd->flags & SD_BALANCE_NEWIDLE) { 5302 if (sd->flags & SD_BALANCE_NEWIDLE) {
5305 /* If we've pulled tasks over stop searching: */ 5303 /* If we've pulled tasks over stop searching: */
5306 pulled_task = load_balance(this_cpu, this_rq, 5304 pulled_task = load_balance(this_cpu, this_rq,
5307 sd, CPU_NEWLY_IDLE, &balance); 5305 sd, CPU_NEWLY_IDLE,
5306 &continue_balancing);
5308 } 5307 }
5309 5308
5310 interval = msecs_to_jiffies(sd->balance_interval); 5309 interval = msecs_to_jiffies(sd->balance_interval);
@@ -5542,7 +5541,7 @@ void update_max_interval(void)
5542 */ 5541 */
5543static void rebalance_domains(int cpu, enum cpu_idle_type idle) 5542static void rebalance_domains(int cpu, enum cpu_idle_type idle)
5544{ 5543{
5545 int balance = 1; 5544 int continue_balancing = 1;
5546 struct rq *rq = cpu_rq(cpu); 5545 struct rq *rq = cpu_rq(cpu);
5547 unsigned long interval; 5546 unsigned long interval;
5548 struct sched_domain *sd; 5547 struct sched_domain *sd;
@@ -5574,7 +5573,7 @@ static void rebalance_domains(int cpu, enum cpu_idle_type idle)
5574 } 5573 }
5575 5574
5576 if (time_after_eq(jiffies, sd->last_balance + interval)) { 5575 if (time_after_eq(jiffies, sd->last_balance + interval)) {
5577 if (load_balance(cpu, rq, sd, idle, &balance)) { 5576 if (load_balance(cpu, rq, sd, idle, &continue_balancing)) {
5578 /* 5577 /*
5579 * The LBF_SOME_PINNED logic could have changed 5578 * The LBF_SOME_PINNED logic could have changed
5580 * env->dst_cpu, so we can't know our idle 5579 * env->dst_cpu, so we can't know our idle
@@ -5597,7 +5596,7 @@ out:
5597 * CPU in our sched group which is doing load balancing more 5596 * CPU in our sched group which is doing load balancing more
5598 * actively. 5597 * actively.
5599 */ 5598 */
5600 if (!balance) 5599 if (!continue_balancing)
5601 break; 5600 break;
5602 } 5601 }
5603 rcu_read_unlock(); 5602 rcu_read_unlock();