Similarly to the online cpus, the cpu_active_mask is actively used in the kernel. This patch adds a counter for active cpus, so that users that call num_active_cpus() would know the result immediately, instead of calling the bitmap_weight for the mask. Suggested-by: Nicholas Piggin <npiggin@xxxxxxxxx> Signed-off-by: Yury Norov <yury.norov@xxxxxxxxx> --- include/linux/cpumask.h | 26 +++++++++++++++----------- kernel/cpu.c | 15 +++++++++++++++ 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index c2a9d15e2cbd..0add872898f8 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -101,6 +101,7 @@ extern struct cpumask __cpu_dying_mask; extern atomic_t __num_online_cpus; extern atomic_t __num_possible_cpus; extern atomic_t __num_present_cpus; +extern atomic_t __num_active_cpus; extern cpumask_t cpus_booted_once_mask; @@ -875,17 +876,8 @@ void init_cpu_online(const struct cpumask *src); void set_cpu_possible(unsigned int cpu, bool possible); void reset_cpu_possible_mask(void); void set_cpu_present(unsigned int cpu, bool present); - void set_cpu_online(unsigned int cpu, bool online); - -static inline void -set_cpu_active(unsigned int cpu, bool active) -{ - if (active) - cpumask_set_cpu(cpu, &__cpu_active_mask); - else - cpumask_clear_cpu(cpu, &__cpu_active_mask); -} +void set_cpu_active(unsigned int cpu, bool active); static inline void set_cpu_dying(unsigned int cpu, bool dying) @@ -971,7 +963,19 @@ static inline unsigned int num_present_cpus(void) { return atomic_read(&__num_present_cpus); } -#define num_active_cpus() cpumask_weight(cpu_active_mask) + +/** + * num_active_cpus() - Read the number of active CPUs + * + * Despite the fact that __num_active_cpus is of type atomic_t, this + * interface gives only a momentary snapshot and is not protected against + * concurrent CPU hotplug operations unless invoked from a cpuhp_lock held + * region. + */ +static inline unsigned int num_active_cpus(void) +{ + return atomic_read(&__num_active_cpus); +} static inline bool cpu_online(unsigned int cpu) { diff --git a/kernel/cpu.c b/kernel/cpu.c index 1f7ea1bdde1a..62b411d88810 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -2603,6 +2603,9 @@ EXPORT_SYMBOL(__num_present_cpus); struct cpumask __cpu_active_mask __read_mostly; EXPORT_SYMBOL(__cpu_active_mask); +atomic_t __num_active_cpus __read_mostly; +EXPORT_SYMBOL(__num_active_cpus); + struct cpumask __cpu_dying_mask __read_mostly; EXPORT_SYMBOL(__cpu_dying_mask); @@ -2678,6 +2681,18 @@ void set_cpu_present(unsigned int cpu, bool present) } EXPORT_SYMBOL(set_cpu_present); +void set_cpu_active(unsigned int cpu, bool active) +{ + if (active) { + if (!cpumask_test_and_set_cpu(cpu, &__cpu_active_mask)) + atomic_inc(&__num_active_cpus); + } else { + if (cpumask_test_and_clear_cpu(cpu, &__cpu_active_mask)) + atomic_dec(&__num_active_cpus); + } +} +EXPORT_SYMBOL(set_cpu_active); + /* * Activate the first processor. */ -- 2.30.2