Commit ec6317cc authored by Preeti U Murthy's avatar Preeti U Murthy Committed by Jiri Slaby

sched: Remove unnecessary iteration over sched domains to update nr_busy_cpus

commit 37dc6b50 upstream.

nr_busy_cpus parameter is used by nohz_kick_needed() to find out the
number of busy cpus in a sched domain which has SD_SHARE_PKG_RESOURCES
flag set.  Therefore instead of updating nr_busy_cpus at every level
of sched domain, since it is irrelevant, we can update this parameter
only at the parent domain of the sd which has this flag set. Introduce
a per-cpu parameter sd_busy which represents this parent domain.

In nohz_kick_needed() we directly query the nr_busy_cpus parameter
associated with the groups of sd_busy.

By associating sd_busy with the highest domain which has
SD_SHARE_PKG_RESOURCES flag set, we cover all lower level domains
which could have this flag set and trigger nohz_idle_balancing if any
of the levels have more than one busy cpu.

sd_busy is irrelevant for asymmetric load balancing. However sd_asym
has been introduced to represent the highest sched domain which has
SD_ASYM_PACKING flag set so that it can be queried directly when
required.

While we are at it, we might as well change the nohz_idle parameter to
be updated at the sd_busy domain level alone and not the base domain
level of a CPU.  This will unify the concept of busy cpus at just one
level of sched domain where it is currently used.

Signed-off-by: Preeti U Murthy<preeti@linux.vnet.ibm.com>
Signed-off-by: default avatarPeter Zijlstra <peterz@infradead.org>
Cc: svaidy@linux.vnet.ibm.com
Cc: vincent.guittot@linaro.org
Cc: bitbucket@online.de
Cc: benh@kernel.crashing.org
Cc: anton@samba.org
Cc: Morten.Rasmussen@arm.com
Cc: pjt@google.com
Cc: peterz@infradead.org
Cc: mikey@neuling.org
Link: http://lkml.kernel.org/r/20131030031252.23426.4417.stgit@preeti.in.ibm.comSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
Signed-off-by: default avatarJiri Slaby <jslaby@suse.cz>
parent 66802dc6
...@@ -5119,6 +5119,8 @@ static void destroy_sched_domains(struct sched_domain *sd, int cpu) ...@@ -5119,6 +5119,8 @@ static void destroy_sched_domains(struct sched_domain *sd, int cpu)
DEFINE_PER_CPU(struct sched_domain *, sd_llc); DEFINE_PER_CPU(struct sched_domain *, sd_llc);
DEFINE_PER_CPU(int, sd_llc_size); DEFINE_PER_CPU(int, sd_llc_size);
DEFINE_PER_CPU(int, sd_llc_id); DEFINE_PER_CPU(int, sd_llc_id);
DEFINE_PER_CPU(struct sched_domain *, sd_busy);
DEFINE_PER_CPU(struct sched_domain *, sd_asym);
static void update_top_cache_domain(int cpu) static void update_top_cache_domain(int cpu)
{ {
...@@ -5130,11 +5132,15 @@ static void update_top_cache_domain(int cpu) ...@@ -5130,11 +5132,15 @@ static void update_top_cache_domain(int cpu)
if (sd) { if (sd) {
id = cpumask_first(sched_domain_span(sd)); id = cpumask_first(sched_domain_span(sd));
size = cpumask_weight(sched_domain_span(sd)); size = cpumask_weight(sched_domain_span(sd));
rcu_assign_pointer(per_cpu(sd_busy, cpu), sd->parent);
} }
rcu_assign_pointer(per_cpu(sd_llc, cpu), sd); rcu_assign_pointer(per_cpu(sd_llc, cpu), sd);
per_cpu(sd_llc_size, cpu) = size; per_cpu(sd_llc_size, cpu) = size;
per_cpu(sd_llc_id, cpu) = id; per_cpu(sd_llc_id, cpu) = id;
sd = highest_flag_domain(cpu, SD_ASYM_PACKING);
rcu_assign_pointer(per_cpu(sd_asym, cpu), sd);
} }
/* /*
......
...@@ -5598,15 +5598,15 @@ static inline void nohz_balance_exit_idle(int cpu) ...@@ -5598,15 +5598,15 @@ static inline void nohz_balance_exit_idle(int cpu)
static inline void set_cpu_sd_state_busy(void) static inline void set_cpu_sd_state_busy(void)
{ {
struct sched_domain *sd; struct sched_domain *sd;
int cpu = smp_processor_id();
rcu_read_lock(); rcu_read_lock();
sd = rcu_dereference_check_sched_domain(this_rq()->sd); sd = rcu_dereference(per_cpu(sd_busy, cpu));
if (!sd || !sd->nohz_idle) if (!sd || !sd->nohz_idle)
goto unlock; goto unlock;
sd->nohz_idle = 0; sd->nohz_idle = 0;
for (; sd; sd = sd->parent)
atomic_inc(&sd->groups->sgp->nr_busy_cpus); atomic_inc(&sd->groups->sgp->nr_busy_cpus);
unlock: unlock:
rcu_read_unlock(); rcu_read_unlock();
...@@ -5615,15 +5615,15 @@ static inline void set_cpu_sd_state_busy(void) ...@@ -5615,15 +5615,15 @@ static inline void set_cpu_sd_state_busy(void)
void set_cpu_sd_state_idle(void) void set_cpu_sd_state_idle(void)
{ {
struct sched_domain *sd; struct sched_domain *sd;
int cpu = smp_processor_id();
rcu_read_lock(); rcu_read_lock();
sd = rcu_dereference_check_sched_domain(this_rq()->sd); sd = rcu_dereference(per_cpu(sd_busy, cpu));
if (!sd || sd->nohz_idle) if (!sd || sd->nohz_idle)
goto unlock; goto unlock;
sd->nohz_idle = 1; sd->nohz_idle = 1;
for (; sd; sd = sd->parent)
atomic_dec(&sd->groups->sgp->nr_busy_cpus); atomic_dec(&sd->groups->sgp->nr_busy_cpus);
unlock: unlock:
rcu_read_unlock(); rcu_read_unlock();
...@@ -5807,6 +5807,8 @@ static inline int nohz_kick_needed(struct rq *rq, int cpu) ...@@ -5807,6 +5807,8 @@ static inline int nohz_kick_needed(struct rq *rq, int cpu)
{ {
unsigned long now = jiffies; unsigned long now = jiffies;
struct sched_domain *sd; struct sched_domain *sd;
struct sched_group_power *sgp;
int nr_busy;
if (unlikely(idle_cpu(cpu))) if (unlikely(idle_cpu(cpu)))
return 0; return 0;
...@@ -5832,22 +5834,22 @@ static inline int nohz_kick_needed(struct rq *rq, int cpu) ...@@ -5832,22 +5834,22 @@ static inline int nohz_kick_needed(struct rq *rq, int cpu)
goto need_kick; goto need_kick;
rcu_read_lock(); rcu_read_lock();
for_each_domain(cpu, sd) { sd = rcu_dereference(per_cpu(sd_busy, cpu));
struct sched_group *sg = sd->groups;
struct sched_group_power *sgp = sg->sgp; if (sd) {
int nr_busy = atomic_read(&sgp->nr_busy_cpus); sgp = sd->groups->sgp;
nr_busy = atomic_read(&sgp->nr_busy_cpus);
if (sd->flags & SD_SHARE_PKG_RESOURCES && nr_busy > 1) if (nr_busy > 1)
goto need_kick_unlock; goto need_kick_unlock;
}
sd = rcu_dereference(per_cpu(sd_asym, cpu));
if (sd->flags & SD_ASYM_PACKING if (sd && (cpumask_first_and(nohz.idle_cpus_mask,
&& (cpumask_first_and(nohz.idle_cpus_mask,
sched_domain_span(sd)) < cpu)) sched_domain_span(sd)) < cpu))
goto need_kick_unlock; goto need_kick_unlock;
if (!(sd->flags & (SD_SHARE_PKG_RESOURCES | SD_ASYM_PACKING)))
break;
}
rcu_read_unlock(); rcu_read_unlock();
return 0; return 0;
......
...@@ -596,6 +596,8 @@ static inline struct sched_domain *highest_flag_domain(int cpu, int flag) ...@@ -596,6 +596,8 @@ static inline struct sched_domain *highest_flag_domain(int cpu, int flag)
DECLARE_PER_CPU(struct sched_domain *, sd_llc); DECLARE_PER_CPU(struct sched_domain *, sd_llc);
DECLARE_PER_CPU(int, sd_llc_size); DECLARE_PER_CPU(int, sd_llc_size);
DECLARE_PER_CPU(int, sd_llc_id); DECLARE_PER_CPU(int, sd_llc_id);
DECLARE_PER_CPU(struct sched_domain *, sd_busy);
DECLARE_PER_CPU(struct sched_domain *, sd_asym);
struct sched_group_power { struct sched_group_power {
atomic_t ref; atomic_t ref;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment