Introduce nr_busy_cpus in the struct sched_group_power [Not in sched_group because sched groups are duplicated for the SD_OVERLAP scheduler domain] and for each cpu that enters and exits tickless, this parameter will be updated in each scheduler group of the scheduler domain that this cpu belongs to. To avoid the frequent update of this state as the cpu enters and exits tickless idle, the update of the stat during tickless exit is delayed to the first timer tick that happens after the cpu becomes busy. Signed-off-by: Suresh Siddha --- include/linux/sched.h | 4 ++++ kernel/sched/core.c | 1 + kernel/sched/fair.c | 18 +++++++++++++++++- 3 files changed, 22 insertions(+), 1 deletion(-) Index: tip/include/linux/sched.h =================================================================== --- tip.orig/include/linux/sched.h +++ tip/include/linux/sched.h @@ -901,6 +901,10 @@ struct sched_group_power { * single CPU. */ unsigned int power, power_orig; + /* + * Number of busy cpus in this group. + */ + atomic_t nr_busy_cpus; }; struct sched_group { Index: tip/kernel/sched/core.c =================================================================== --- tip.orig/kernel/sched/core.c +++ tip/kernel/sched/core.c @@ -6017,6 +6017,7 @@ static void init_sched_groups_power(int return; update_group_power(sd, cpu); + atomic_set(&sg->sgp->nr_busy_cpus, sg->group_weight); } int __weak arch_sd_sibling_asym_packing(void) Index: tip/kernel/sched/fair.c =================================================================== --- tip.orig/kernel/sched/fair.c +++ tip/kernel/sched/fair.c @@ -4894,6 +4894,7 @@ static void nohz_balancer_kick(int cpu) void select_nohz_load_balancer(int stop_tick) { int cpu = smp_processor_id(); + struct sched_domain *sd; if (stop_tick) { if (!cpu_active(cpu)) { @@ -4940,6 +4941,12 @@ void select_nohz_load_balancer(int stop_ } set_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)); + /* + * Indicate the idle state to all the scheduler groups that + * this cpu is part of. + */ + for_each_domain(cpu, sd) + atomic_dec(&sd->groups->sgp->nr_busy_cpus); } else { if (!cpumask_test_cpu(cpu, nohz.idle_cpus_mask)) return; @@ -5104,10 +5111,19 @@ static inline int nohz_kick_needed(struc unsigned long now = jiffies; int ret; int first_pick_cpu, second_pick_cpu; + struct sched_domain *sd; - if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) + /* + * We were recently in tickless idle mode. At the first busy tick + * after returning from idle, we will update the busy stats. + */ + if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) { clear_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)); + for_each_domain(cpu, sd) + atomic_inc(&sd->groups->sgp->nr_busy_cpus); + } + if (time_before(now, nohz.next_balance)) return 0; -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/