sched: Provide Kconfig support for default dynamic preempt mode

Currently the boot defined preempt behaviour (aka dynamic preempt)
selects full preemption by default when the "preempt=" boot parameter
is omitted. However distros may rather want to default to either
no preemption or voluntary preemption.

To provide with this flexibility, make dynamic preemption a visible
Kconfig option and adapt the preemption behaviour selected by the user
to either static or dynamic preemption.

Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/20210914103134.11309-1-frederic@kernel.org
This commit is contained in:
Frederic Weisbecker 2021-09-14 12:31:34 +02:00 committed by Peter Zijlstra
parent 32ed980c30
commit c597bfddc9
2 changed files with 49 additions and 12 deletions

View File

@ -2,10 +2,11 @@
choice choice
prompt "Preemption Model" prompt "Preemption Model"
default PREEMPT_NONE default PREEMPT_NONE_BEHAVIOUR
config PREEMPT_NONE config PREEMPT_NONE_BEHAVIOUR
bool "No Forced Preemption (Server)" bool "No Forced Preemption (Server)"
select PREEMPT_NONE if !PREEMPT_DYNAMIC
help help
This is the traditional Linux preemption model, geared towards This is the traditional Linux preemption model, geared towards
throughput. It will still provide good latencies most of the throughput. It will still provide good latencies most of the
@ -17,9 +18,10 @@ config PREEMPT_NONE
raw processing power of the kernel, irrespective of scheduling raw processing power of the kernel, irrespective of scheduling
latencies. latencies.
config PREEMPT_VOLUNTARY config PREEMPT_VOLUNTARY_BEHAVIOUR
bool "Voluntary Kernel Preemption (Desktop)" bool "Voluntary Kernel Preemption (Desktop)"
depends on !ARCH_NO_PREEMPT depends on !ARCH_NO_PREEMPT
select PREEMPT_VOLUNTARY if !PREEMPT_DYNAMIC
help help
This option reduces the latency of the kernel by adding more This option reduces the latency of the kernel by adding more
"explicit preemption points" to the kernel code. These new "explicit preemption points" to the kernel code. These new
@ -35,12 +37,10 @@ config PREEMPT_VOLUNTARY
Select this if you are building a kernel for a desktop system. Select this if you are building a kernel for a desktop system.
config PREEMPT config PREEMPT_BEHAVIOUR
bool "Preemptible Kernel (Low-Latency Desktop)" bool "Preemptible Kernel (Low-Latency Desktop)"
depends on !ARCH_NO_PREEMPT depends on !ARCH_NO_PREEMPT
select PREEMPTION select PREEMPT
select UNINLINE_SPIN_UNLOCK if !ARCH_INLINE_SPIN_UNLOCK
select PREEMPT_DYNAMIC if HAVE_PREEMPT_DYNAMIC
help help
This option reduces the latency of the kernel by making This option reduces the latency of the kernel by making
all kernel code (that is not executing in a critical section) all kernel code (that is not executing in a critical section)
@ -58,7 +58,7 @@ config PREEMPT
config PREEMPT_RT config PREEMPT_RT
bool "Fully Preemptible Kernel (Real-Time)" bool "Fully Preemptible Kernel (Real-Time)"
depends on EXPERT && ARCH_SUPPORTS_RT depends on EXPERT && ARCH_SUPPORTS_RT && !PREEMPT_DYNAMIC
select PREEMPTION select PREEMPTION
help help
This option turns the kernel into a real-time kernel by replacing This option turns the kernel into a real-time kernel by replacing
@ -75,6 +75,17 @@ config PREEMPT_RT
endchoice endchoice
config PREEMPT_NONE
bool
config PREEMPT_VOLUNTARY
bool
config PREEMPT
bool
select PREEMPTION
select UNINLINE_SPIN_UNLOCK if !ARCH_INLINE_SPIN_UNLOCK
config PREEMPT_COUNT config PREEMPT_COUNT
bool bool
@ -83,7 +94,10 @@ config PREEMPTION
select PREEMPT_COUNT select PREEMPT_COUNT
config PREEMPT_DYNAMIC config PREEMPT_DYNAMIC
bool bool "Preemption behaviour defined on boot"
depends on HAVE_PREEMPT_DYNAMIC
select PREEMPT
default y
help help
This option allows to define the preemption model on the kernel This option allows to define the preemption model on the kernel
command line parameter and thus override the default preemption command line parameter and thus override the default preemption

View File

@ -6520,12 +6520,13 @@ EXPORT_STATIC_CALL_TRAMP(preempt_schedule_notrace);
*/ */
enum { enum {
preempt_dynamic_none = 0, preempt_dynamic_undefined = -1,
preempt_dynamic_none,
preempt_dynamic_voluntary, preempt_dynamic_voluntary,
preempt_dynamic_full, preempt_dynamic_full,
}; };
int preempt_dynamic_mode = preempt_dynamic_full; int preempt_dynamic_mode = preempt_dynamic_undefined;
int sched_dynamic_mode(const char *str) int sched_dynamic_mode(const char *str)
{ {
@ -6598,7 +6599,27 @@ static int __init setup_preempt_mode(char *str)
} }
__setup("preempt=", setup_preempt_mode); __setup("preempt=", setup_preempt_mode);
#endif /* CONFIG_PREEMPT_DYNAMIC */ static void __init preempt_dynamic_init(void)
{
if (preempt_dynamic_mode == preempt_dynamic_undefined) {
if (IS_ENABLED(CONFIG_PREEMPT_NONE_BEHAVIOUR)) {
sched_dynamic_update(preempt_dynamic_none);
} else if (IS_ENABLED(CONFIG_PREEMPT_VOLUNTARY_BEHAVIOUR)) {
sched_dynamic_update(preempt_dynamic_voluntary);
} else {
/* Default static call setting, nothing to do */
WARN_ON_ONCE(!IS_ENABLED(CONFIG_PREEMPT_BEHAVIOUR));
preempt_dynamic_mode = preempt_dynamic_full;
pr_info("Dynamic Preempt: full\n");
}
}
}
#else /* !CONFIG_PREEMPT_DYNAMIC */
static inline void preempt_dynamic_init(void) { }
#endif /* #ifdef CONFIG_PREEMPT_DYNAMIC */
/* /*
* This is the entry point to schedule() from kernel preemption * This is the entry point to schedule() from kernel preemption
@ -9398,6 +9419,8 @@ void __init sched_init(void)
init_uclamp(); init_uclamp();
preempt_dynamic_init();
scheduler_running = 1; scheduler_running = 1;
} }