Skip to content

Commit 6f9c07b

Browse files
committed
lib/cpumask: add FORCE_NR_CPUS config option
The size of cpumasks is hard-limited by compile-time parameter NR_CPUS, but defined at boot-time when kernel parses ACPI/DT tables, and stored in nr_cpu_ids. In many practical cases, number of CPUs for a target is known at compile time, and can be provided with NR_CPUS. In that case, compiler may be instructed to rely on NR_CPUS as on actual number of CPUs, not an upper limit. It allows to optimize many cpumask routines and significantly shrink size of the kernel image. This patch adds FORCE_NR_CPUS option to teach the compiler to rely on NR_CPUS and enable corresponding optimizations. If FORCE_NR_CPUS=y, kernel will not set nr_cpu_ids at boot, but only check that the actual number of possible CPUs is equal to NR_CPUS, and WARN if that doesn't hold. The new option is especially useful in embedded applications because kernel configurations are unique for each SoC, the number of CPUs is constant and known well, and memory limitations are typically harder. For my 4-CPU ARM64 build with NR_CPUS=4, FORCE_NR_CPUS=y saves 46KB: add/remove: 3/4 grow/shrink: 46/729 up/down: 652/-46952 (-46300) Signed-off-by: Yury Norov <[email protected]>
1 parent 546a073 commit 6f9c07b

File tree

3 files changed

+17
-4
lines changed

3 files changed

+17
-4
lines changed

include/linux/cpumask.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,20 @@ typedef struct cpumask { DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t;
3535
*/
3636
#define cpumask_pr_args(maskp) nr_cpu_ids, cpumask_bits(maskp)
3737

38-
#if NR_CPUS == 1
39-
#define nr_cpu_ids 1U
38+
#if (NR_CPUS == 1) || defined(CONFIG_FORCE_NR_CPUS)
39+
#define nr_cpu_ids ((unsigned int)NR_CPUS)
4040
#else
4141
extern unsigned int nr_cpu_ids;
42+
#endif
4243

4344
static inline void set_nr_cpu_ids(unsigned int nr)
4445
{
46+
#if (NR_CPUS == 1) || defined(CONFIG_FORCE_NR_CPUS)
47+
WARN_ON(nr != nr_cpu_ids);
48+
#else
4549
nr_cpu_ids = nr;
46-
}
4750
#endif
51+
}
4852

4953
/* Deprecated. Always use nr_cpu_ids. */
5054
#define nr_cpumask_bits nr_cpu_ids

kernel/smp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1088,7 +1088,7 @@ static int __init maxcpus(char *str)
10881088

10891089
early_param("maxcpus", maxcpus);
10901090

1091-
#if (NR_CPUS > 1)
1091+
#if (NR_CPUS > 1) && !defined(CONFIG_FORCE_NR_CPUS)
10921092
/* Setup number of possible processor ids */
10931093
unsigned int nr_cpu_ids __read_mostly = NR_CPUS;
10941094
EXPORT_SYMBOL(nr_cpu_ids);

lib/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,15 @@ config CPUMASK_OFFSTACK
527527
them on the stack. This is a bit more expensive, but avoids
528528
stack overflow.
529529

530+
config FORCE_NR_CPUS
531+
bool "NR_CPUS is set to an actual number of CPUs"
532+
depends on SMP
533+
help
534+
Say Yes if you have NR_CPUS set to an actual number of possible
535+
CPUs in your system, not to a default value. This forces the core
536+
code to rely on compile-time value and optimize kernel routines
537+
better.
538+
530539
config CPU_RMAP
531540
bool
532541
depends on SMP

0 commit comments

Comments
 (0)