From 1ead4c5f5ee703eced732a164165174b44d56f26 Mon Sep 17 00:00:00 2001 From: Roman Penyaev Date: Wed, 28 Feb 2024 15:14:08 +0100 Subject: [PATCH] sched/isolation: add 'inverse' parameter for the 'nohz_full' and 'isolcpus' By default 'nohz_full' and 'isolcpus' accept a range of those CPUs, which should be isolated from the housekeeping, with 'inverse' the logic is inverted: you specify CPUs for housekeeping tasks, others are isolated. The motivation of the patch is to generalize and simplify kernel configration, when maximum number of CPUs is not known, but it is known, that CPU0 will do the whole housekeeping, so the command line becomes: isolcpus=inverse,0 nohz_full=inverse,0 instead of isolcpus=1-N nohz_full=1-N where N is the index of the maximum CPU, which is not always known. Signed-off-by: Roman Penyaev --- kernel/sched/isolation.c | 44 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/kernel/sched/isolation.c b/kernel/sched/isolation.c index 373d42c707bc5..783cfe6213788 100644 --- a/kernel/sched/isolation.c +++ b/kernel/sched/isolation.c @@ -106,7 +106,7 @@ static void __init housekeeping_setup_type(enum hk_type type, housekeeping_staging); } -static int __init housekeeping_setup(char *str, unsigned long flags) +static int __init housekeeping_setup(char *str, unsigned long flags, bool inverse) { cpumask_var_t non_housekeeping_mask, housekeeping_staging; int err = 0; @@ -124,6 +124,8 @@ static int __init housekeeping_setup(char *str, unsigned long flags) pr_warn("Housekeeping: nohz_full= or isolcpus= incorrect CPU range\n"); goto free_non_housekeeping_mask; } + if (inverse) + cpumask_complement(non_housekeeping_mask, non_housekeeping_mask); alloc_bootmem_cpumask_var(&housekeeping_staging); cpumask_andnot(housekeeping_staging, @@ -180,11 +182,40 @@ static int __init housekeeping_setup(char *str, unsigned long flags) static int __init housekeeping_nohz_full_setup(char *str) { unsigned long flags; + bool illegal = false; + bool inverse = false; + char *par; + int len; + + while (isalpha(*str)) { + if (!strncmp(str, "inverse,", 8)) { + str += 8; + inverse = true; + continue; + } + + /* + * Skip unknown sub-parameter and validate that it is not + * containing an invalid character. + */ + for (par = str, len = 0; *str && *str != ','; str++, len++) { + if (!isalpha(*str) && *str != '_') + illegal = true; + } + + if (illegal) { + pr_warn("nohz_full: Invalid flag %.*s\n", len, par); + return 0; + } + + pr_info("nohz_full: Skipped unknown flag %.*s\n", len, par); + str++; + } flags = HK_FLAG_TICK | HK_FLAG_WQ | HK_FLAG_TIMER | HK_FLAG_RCU | HK_FLAG_MISC | HK_FLAG_KTHREAD; - return housekeeping_setup(str, flags); + return housekeeping_setup(str, flags, inverse); } __setup("nohz_full=", housekeeping_nohz_full_setup); @@ -192,6 +223,7 @@ static int __init housekeeping_isolcpus_setup(char *str) { unsigned long flags = 0; bool illegal = false; + bool inverse = false; char *par; int len; @@ -214,6 +246,12 @@ static int __init housekeeping_isolcpus_setup(char *str) continue; } + if (!strncmp(str, "inverse,", 8)) { + str += 8; + inverse = true; + continue; + } + /* * Skip unknown sub-parameter and validate that it is not * containing an invalid character. @@ -236,6 +274,6 @@ static int __init housekeeping_isolcpus_setup(char *str) if (!flags) flags |= HK_FLAG_DOMAIN; - return housekeeping_setup(str, flags); + return housekeeping_setup(str, flags, inverse); } __setup("isolcpus=", housekeeping_isolcpus_setup);