Messages in this thread Patch in this message |  | | From | Andrea Righi <> | | Subject | [PATCH 09/10] sched/core: Disable proxy-exec context switch under sched_ext by default | | Date | Wed, 6 May 2026 19:45:49 +0200 |
| |
Proxy execution switches a donor's execution context to the mutex owner, so the owner can make progress while the donor remains on the runqueue.
This logic might be incompatible with some sched_ext schedulers: the BPF scheduler picks tasks through its own dispatch interface, and a proxy-exec switch may end up running a task the BPF scheduler never dispatched. This mismatch can break BPF context: sched_ext callbacks fire against a task that isn't the one the BPF scheduler tracks as running, so any kfunc they invoke operates on an inconsistent view of the current task.
Therefore, when sched_ext is enabled, disable proxy-exec context donation by default:
- Force try_to_block_task() to actually block a mutex-blocked prev instead of keeping it on the rq as a donor.
- Skip find_proxy_task() in the pick path. Clear any leftover PROXY_WAKING marker set by the mutex handoff, since find_proxy_task() is no longer there to do it; otherwise the task trips the blocked_on mismatch WARN in __set_task_blocked_on() when it resumes the mutex_lock() retry loop.
However, some schedulers may not consider proxy execution as a real "task switch" and more like a "function call": the donor effectively executes the lock owner's critical section, so the switch does not represent a true change in scheduling ownership.
To handle both semantics, add a boot-time knob to enable proxy execution under sched_ext when explicitly desired:
sched_proxy_exec_scx=0|1
The default is 0, keeping proxy-exec disabled for the reasons described above. Setting it to 1 allows donor->owner context switch even with sched_ext enabled.
Signed-off-by: Andrea Righi <arighi@nvidia.com> --- .../admin-guide/kernel-parameters.txt | 6 +++ kernel/sched/core.c | 47 ++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 4510b4b3c4165..f73c12e9645de 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -6821,6 +6821,12 @@ Kernel parameters solution to mutex-based priority inversion. Format: <bool> + sched_proxy_exec_scx= [KNL] + Enables or disables proxy execution when sched_ext is + enabled. The default is disabled, meaning proxy-exec + context donation is suppressed while sched_ext is active. + Format: <bool> + sched_verbose [KNL,EARLY] Enables verbose scheduler debug messages. schedstats= [KNL,X86] Enable or disable scheduled statistics. diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 1c161dd9d7440..0f714c6613771 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -151,14 +151,52 @@ static int __init setup_proxy_exec(char *str) } return 1; } + +DEFINE_STATIC_KEY_FALSE(__sched_proxy_exec_scx); +static __always_inline bool sched_proxy_exec_scx(void) +{ + return static_branch_unlikely(&__sched_proxy_exec_scx); +} + +static int __init setup_proxy_exec_scx(char *str) +{ + bool proxy_scx_enable = false; + + if (*str && kstrtobool(str + 1, &proxy_scx_enable)) { + pr_warn("Unable to parse sched_proxy_exec_scx=\n"); + return 0; + } + + if (proxy_scx_enable) { + pr_info("sched_proxy_exec_scx enabled via boot arg\n"); + static_branch_enable(&__sched_proxy_exec_scx); + } else { + pr_info("sched_proxy_exec_scx disabled via boot arg\n"); + static_branch_disable(&__sched_proxy_exec_scx); + } + + return 1; +} #else static int __init setup_proxy_exec(char *str) { pr_warn("CONFIG_SCHED_PROXY_EXEC=n, so it cannot be enabled or disabled at boot time\n"); return 0; } + +static __always_inline bool sched_proxy_exec_scx(void) +{ + return false; +} + +static int __init setup_proxy_exec_scx(char *str) +{ + pr_warn("CONFIG_SCHED_PROXY_EXEC=n, so sched_proxy_exec_scx= is ignored\n"); + return 0; +} #endif __setup("sched_proxy_exec", setup_proxy_exec); +__setup("sched_proxy_exec_scx", setup_proxy_exec_scx); /* * Debugging: various feature bits @@ -7111,7 +7149,8 @@ static void __sched notrace __schedule(int sched_mode) * task_is_blocked() will always be false). */ try_to_block_task(rq, prev, &prev_state, - !task_is_blocked(prev)); + !task_is_blocked(prev) || + (scx_enabled() && !sched_proxy_exec_scx())); switch_count = &prev->nvcsw; } @@ -7123,6 +7162,12 @@ static void __sched notrace __schedule(int sched_mode) struct task_struct *prev_donor = rq->donor; rq_set_donor(rq, next); + if (scx_enabled() && !sched_proxy_exec_scx()) { + if (unlikely(next->blocked_on)) + clear_task_blocked_on(next, PROXY_WAKING); + goto picked; + } + if (unlikely(next->blocked_on)) { next = find_proxy_task(rq, next, &rf); if (!next) { -- 2.54.0
|  |