[PATCH 8/9] tools/sched_ext: scx_userland: Check dispatch buffer slots before inserting

From: Tao Cui

Date: Tue Nov 10 2026 - 08:00:55 EST


From: Tao Cui <cuitao@xxxxxxxxxx>

userland_dispatch() pops up to MAX_ENQUEUED_TASKS pids from the
dispatched map and inserts each task into the global DSQ without
consulting scx_bpf_dispatch_nr_slots(). The kernel's dispatch buffer
holds 32 slots against MAX_ENQUEUED_TASKS (4096), so a single
full dispatch round overflows it long before that many tasks
pile up between dispatch rounds the insert past the buffer limit aborts
the whole scheduler. Every other tools scheduler that loops on
scx_bpf_dsq_insert() (scx_central, scx_qmap) checks the remaining slot
count; scx_userland is the odd one out.

Break out when the buffer is exhausted and leave the remaining tasks
queued for the next dispatch round.

Fixes: cc4448d0856d ("tools/sched_ext: add scx_userland scheduler")
Signed-off-by: Tao Cui <cuitao@xxxxxxxxxx>
---
tools/sched_ext/scx_userland.bpf.c | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/tools/sched_ext/scx_userland.bpf.c b/tools/sched_ext/scx_userland.bpf.c
index f29862b89386..0a6daad84528 100644
--- a/tools/sched_ext/scx_userland.bpf.c
+++ b/tools/sched_ext/scx_userland.bpf.c
@@ -233,6 +233,14 @@ void BPF_STRUCT_OPS(userland_dispatch, s32 cpu, struct task_struct *prev)
s32 pid;
struct task_struct *p;

+ /*
+ * The dispatch buffer is limited. When it runs out, leave the
+ * remaining tasks queued for the next dispatch round instead
+ * of inserting past the limit and aborting the scheduler.
+ */
+ if (!scx_bpf_dispatch_nr_slots())
+ break;
+
if (bpf_map_pop_elem(&dispatched, &pid))
break;

--
2.53.0

base-commit: 5b740a72b55c4267ba4d8010f17dde26b26f52d3