Re: [PATCH v2 1/2] cpumask: introduce cpumask for hotpluggable CPUs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



See comments inline.

On 11 Aug 10, Mike Turquette wrote:
> On some platforms it is possible to have some CPUs which support CPU
> hotplug and some which do not.  Currently the prescence of an 'online'
> sysfs entry in userspace is adequate for applications to know that a CPU
> supports hotplug, but there is no convenient way to make the same
> determination in the kernel.
> 
> To better model this relationship this patch introduces a new cpumask to
> track CPUs that support CPU hotplug operations.
> 
> This new cpumask is populated at boot-time and remains static for the
> life of the machine.  Bits set in the mask indicate a CPU which supports
> hotplug, but make no guarantees about whether that CPU is currently
> online or not.  Likewise a cleared bit in the mask indicates either a
> CPU which cannot hotplug or a lack of a populated CPU.
> 
> The purpose of this new cpumask is to aid kernel code which uses CPU to
> take CPUs online and offline.  Possible uses are as a thermal event
> mitigation technique or as a power capping mechanism.
> 
> Signed-off-by: Mike Turquette <mturquette@xxxxxx>
> ---
> Change log:
> v2: fixed missing parentheses in cpumask_test_cpu and improved grammar
>     in comments
> 
>  include/linux/cpumask.h |   27 ++++++++++++++++++++++-----
>  kernel/cpu.c            |   18 ++++++++++++++++++
>  2 files changed, 40 insertions(+), 5 deletions(-)
> 
> diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
> index b24ac56..52e64a7 100644
> --- a/include/linux/cpumask.h
> +++ b/include/linux/cpumask.h
> @@ -39,10 +39,11 @@ extern int nr_cpu_ids;
>   * The following particular system cpumasks and operations manage
>   * possible, present, active and online cpus.
>   *
> - *     cpu_possible_mask- has bit 'cpu' set iff cpu is populatable
> - *     cpu_present_mask - has bit 'cpu' set iff cpu is populated
> - *     cpu_online_mask  - has bit 'cpu' set iff cpu available to scheduler
> - *     cpu_active_mask  - has bit 'cpu' set iff cpu available to migration
> + *     cpu_possible_mask     - has bit 'cpu' set iff cpu is populatable
> + *     cpu_hotpluggable_mask - has bit 'cpu' set iff cpu is hotpluggable
> + *     cpu_present_mask      - has bit 'cpu' set iff cpu is populated
> + *     cpu_online_mask       - has bit 'cpu' set iff cpu available to scheduler
> + *     cpu_active_mask       - has bit 'cpu' set iff cpu available to migration
>   *
>   *  If !CONFIG_HOTPLUG_CPU, present == possible, and active == online.
>   *
> @@ -51,7 +52,11 @@ extern int nr_cpu_ids;
>   *  life of that system boot.  The cpu_present_mask is dynamic(*),
>   *  representing which CPUs are currently plugged in.  And
>   *  cpu_online_mask is the dynamic subset of cpu_present_mask,
> - *  indicating those CPUs available for scheduling.
> + *  indicating those CPUs available for scheduling.  The
> + *  cpu_hotpluggable_mask is also fixed at boot time as the set of CPU
> + *  id's which are possible AND can hotplug.  Cleared bits in this mask
> + *  mean that either the CPU is not possible, or it is possible but does
> + *  not support CPU hotplug operations.
>   *
>   *  If HOTPLUG is enabled, then cpu_possible_mask is forced to have
>   *  all NR_CPUS bits set, otherwise it is just the set of CPUs that
> @@ -61,6 +66,9 @@ extern int nr_cpu_ids;
>   *  depending on what ACPI reports as currently plugged in, otherwise
>   *  cpu_present_mask is just a copy of cpu_possible_mask.
>   *
> + *  If HOTPLUG is not enabled then cpu_hotpluggable_mask is the empty
> + *  set.
> + *
>   *  (*) Well, cpu_present_mask is dynamic in the hotplug case.  If not
>   *      hotplug, it's a copy of cpu_possible_mask, hence fixed at boot.
>   *
> @@ -76,6 +84,7 @@ extern int nr_cpu_ids;
>   */
>  
>  extern const struct cpumask *const cpu_possible_mask;
> +extern const struct cpumask *const cpu_hotpluggable_mask;
>  extern const struct cpumask *const cpu_online_mask;
>  extern const struct cpumask *const cpu_present_mask;
>  extern const struct cpumask *const cpu_active_mask;
> @@ -85,19 +94,23 @@ extern const struct cpumask *const cpu_active_mask;
>  #define num_possible_cpus()	cpumask_weight(cpu_possible_mask)
>  #define num_present_cpus()	cpumask_weight(cpu_present_mask)
>  #define num_active_cpus()	cpumask_weight(cpu_active_mask)
> +#define num_hotpluggable_cpus()	cpumask_weight(cpu_hotpluggable_mask)
>  #define cpu_online(cpu)		cpumask_test_cpu((cpu), cpu_online_mask)
>  #define cpu_possible(cpu)	cpumask_test_cpu((cpu), cpu_possible_mask)
>  #define cpu_present(cpu)	cpumask_test_cpu((cpu), cpu_present_mask)
>  #define cpu_active(cpu)		cpumask_test_cpu((cpu), cpu_active_mask)
> +#define cpu_hotpluggable(cpu)	cpumask_test_cpu((cpu, cpu_hotpluggable_mask))

The bracket should be around cpu, like this (cpu) so that there are no
side-effects when passing anything to the macro. See the other #defines above.

>  #else
>  #define num_online_cpus()	1U
>  #define num_possible_cpus()	1U
>  #define num_present_cpus()	1U
>  #define num_active_cpus()	1U
> +#define num_hotpluggable_cpus()	0
>  #define cpu_online(cpu)		((cpu) == 0)
>  #define cpu_possible(cpu)	((cpu) == 0)
>  #define cpu_present(cpu)	((cpu) == 0)
>  #define cpu_active(cpu)		((cpu) == 0)
> +#define cpu_hotpluggable(cpu)	0
>  #endif
>  
>  /* verify cpu argument to cpumask_* operators */
> @@ -678,16 +691,20 @@ extern const DECLARE_BITMAP(cpu_all_bits, NR_CPUS);
>  #define cpu_none_mask to_cpumask(cpu_bit_bitmap[0])
>  
>  #define for_each_possible_cpu(cpu) for_each_cpu((cpu), cpu_possible_mask)
> +#define for_each_hotpluggable_cpu(cpu) \
> +				   for_each_cpu((cpu), cpu_hotpluggable_mask)
>  #define for_each_online_cpu(cpu)   for_each_cpu((cpu), cpu_online_mask)
>  #define for_each_present_cpu(cpu)  for_each_cpu((cpu), cpu_present_mask)
>  
>  /* Wrappers for arch boot code to manipulate normally-constant masks */
>  void set_cpu_possible(unsigned int cpu, bool possible);
> +void set_cpu_hotpluggable(unsigned int cpu, bool hotpluggable);
>  void set_cpu_present(unsigned int cpu, bool present);
>  void set_cpu_online(unsigned int cpu, bool online);
>  void set_cpu_active(unsigned int cpu, bool active);
>  void init_cpu_present(const struct cpumask *src);
>  void init_cpu_possible(const struct cpumask *src);
> +void init_cpu_hotpluggable(const struct cpumask *src);
>  void init_cpu_online(const struct cpumask *src);
>  
>  /**
> diff --git a/kernel/cpu.c b/kernel/cpu.c
> index 12b7458..8c397c9 100644
> --- a/kernel/cpu.c
> +++ b/kernel/cpu.c
> @@ -536,6 +536,11 @@ static DECLARE_BITMAP(cpu_possible_bits, CONFIG_NR_CPUS) __read_mostly;
>  const struct cpumask *const cpu_possible_mask = to_cpumask(cpu_possible_bits);
>  EXPORT_SYMBOL(cpu_possible_mask);
>  
> +static DECLARE_BITMAP(cpu_hotpluggable_bits, CONFIG_NR_CPUS) __read_mostly;
> +const struct cpumask *const cpu_hotpluggable_mask =
> +					to_cpumask(cpu_hotpluggable_bits);
> +EXPORT_SYMBOL(cpu_hotpluggable_mask);
> +
>  static DECLARE_BITMAP(cpu_online_bits, CONFIG_NR_CPUS) __read_mostly;
>  const struct cpumask *const cpu_online_mask = to_cpumask(cpu_online_bits);
>  EXPORT_SYMBOL(cpu_online_mask);
> @@ -556,6 +561,14 @@ void set_cpu_possible(unsigned int cpu, bool possible)
>  		cpumask_clear_cpu(cpu, to_cpumask(cpu_possible_bits));
>  }
>  
> +void set_cpu_hotpluggable(unsigned int cpu, bool hotpluggable)
> +{
> +	if (hotpluggable)
> +		cpumask_set_cpu(cpu, to_cpumask(cpu_hotpluggable_bits));
> +	else
> +		cpumask_clear_cpu(cpu, to_cpumask(cpu_hotpluggable_bits));
> +}
> +
>  void set_cpu_present(unsigned int cpu, bool present)
>  {
>  	if (present)
> @@ -590,6 +603,11 @@ void init_cpu_possible(const struct cpumask *src)
>  	cpumask_copy(to_cpumask(cpu_possible_bits), src);
>  }
>  
> +void init_cpu_hotpluggable(const struct cpumask *src)
> +{
> +	cpumask_copy(to_cpumask(cpu_hotpluggable_bits), src);
> +}
> +

Just to be clear I understand this code, init_cpu_hotpluggable will be called
in arch code, right? e.g. arch/arm/kernel/smp.c or do you intend for it to be
called in platform-specific code?

>  void init_cpu_online(const struct cpumask *src)
>  {
>  	cpumask_copy(to_cpumask(cpu_online_bits), src);
> -- 
> 1.7.4.1
_______________________________________________
linux-pm mailing list
linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx
https://lists.linux-foundation.org/mailman/listinfo/linux-pm


[Index of Archives]     [Linux ACPI]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [CPU Freq]     [Kernel Newbies]     [Fedora Kernel]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux