mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: zhidao su <soolaugust@gmail.com>
To: sched-ext@lists.linux.dev
Cc: linux-kernel@vger.kernel.org, tj@kernel.org, void@manifault.com,
	arighi@nvidia.com, changwoo@igalia.com, peterz@infradead.org,
	mingo@redhat.com, zhidao su <suzhidao@xiaomi.com>
Subject: [PATCH 3/4] selftests/sched_ext: dsq_reenq: fix reliability with two-DSQ design
Date: Fri, 27 Mar 2026 04:42:37 +0800	[thread overview]
Message-ID: <20260326204238.3755737-4-suzhidao@xiaomi.com> (raw)
In-Reply-To: <20260326204238.3755737-1-suzhidao@xiaomi.com>

The original test used a single USER_DSQ for both holding tasks and
triggering scx_bpf_dsq_reenq().  ops.dispatch() consumed directly from
USER_DSQ, which raced with the 5 ms BPF timer: by the time the timer
fired, dispatch had already drained USER_DSQ, so scx_bpf_dsq_reenq()
found no tasks to reenqueue and nr_reenq_kfunc remained zero.

Fix with a two-DSQ design:
- USER_DSQ: tasks land here on initial enqueue; ops.dispatch() never
  consumes from it, so tasks accumulate and the timer always finds them.
- RUN_DSQ: reenqueued tasks (SCX_ENQ_REENQ path) land here; dispatch
  consumes from RUN_DSQ so tasks can run.

This guarantees scx_bpf_dsq_reenq() always observes tasks in USER_DSQ
and nr_reenq_kfunc is reliably incremented every timer tick.

Fixes: c50dcf533149 ("selftests/sched_ext: Add tests for SCX_ENQ_IMMED and scx_bpf_dsq_reenq()")
Signed-off-by: zhidao su <suzhidao@xiaomi.com>
---
 .../selftests/sched_ext/dsq_reenq.bpf.c       | 45 ++++++++++++++-----
 1 file changed, 35 insertions(+), 10 deletions(-)

diff --git a/tools/testing/selftests/sched_ext/dsq_reenq.bpf.c b/tools/testing/selftests/sched_ext/dsq_reenq.bpf.c
index 750bb10508df..ccce75a99d8a 100644
--- a/tools/testing/selftests/sched_ext/dsq_reenq.bpf.c
+++ b/tools/testing/selftests/sched_ext/dsq_reenq.bpf.c
@@ -2,9 +2,15 @@
 /*
  * Validate scx_bpf_dsq_reenq() semantics on user DSQs.
  *
- * A BPF timer periodically calls scx_bpf_dsq_reenq() on a user DSQ,
- * causing tasks to be re-enqueued through ops.enqueue() with SCX_ENQ_REENQ
- * set and SCX_TASK_REENQ_KFUNC recorded in p->scx.flags.
+ * Worker tasks are placed into USER_DSQ.  ops.dispatch() does NOT consume
+ * from USER_DSQ directly, so tasks accumulate there between timer ticks.
+ * A BPF timer fires every 5 ms and calls scx_bpf_dsq_reenq(USER_DSQ, 0),
+ * which re-enqueues every task in USER_DSQ through ops.enqueue() with
+ * SCX_ENQ_REENQ set and SCX_TASK_REENQ_KFUNC in p->scx.flags.
+ *
+ * Reenqueued tasks are placed into RUN_DSQ so ops.dispatch() can pick them
+ * up and run them.  This two-queue design guarantees tasks remain in
+ * USER_DSQ long enough for the timer to observe them.
  *
  * The test verifies:
  *  - scx_bpf_dsq_reenq() triggers ops.enqueue() with SCX_ENQ_REENQ
@@ -18,7 +24,13 @@ char _license[] SEC("license") = "GPL";
 
 UEI_DEFINE(uei);
 
+/*
+ * USER_DSQ: tasks sit here between timer ticks so scx_bpf_dsq_reenq()
+ *           can observe and re-enqueue them.
+ * RUN_DSQ:  tasks land here after reenqueue and are consumed by dispatch.
+ */
 #define USER_DSQ	0
+#define RUN_DSQ		1
 
 /*
  * SCX_TASK_REENQ_REASON_MASK and SCX_TASK_REENQ_KFUNC are exported via
@@ -58,27 +70,36 @@ static int reenq_timerfn(void *map, int *key, struct bpf_timer *timer)
 
 void BPF_STRUCT_OPS(dsq_reenq_enqueue, struct task_struct *p, u64 enq_flags)
 {
-	/*
-	 * If this is a kfunc-triggered reenqueue, verify that
-	 * SCX_TASK_REENQ_KFUNC is recorded in p->scx.flags.
-	 */
 	if (enq_flags & SCX_ENQ_REENQ) {
 		u32 reason = p->scx.flags & SCX_TASK_REENQ_REASON_MASK;
 
 		if (reason == SCX_TASK_REENQ_KFUNC)
 			__sync_fetch_and_add(&nr_reenq_kfunc, 1);
+
+		/*
+		 * Reenqueued tasks go to RUN_DSQ so dispatch() can run them.
+		 * Keeping them in USER_DSQ would cause the timer to reenqueue
+		 * them again endlessly without ever running.
+		 */
+		scx_bpf_dsq_insert(p, RUN_DSQ, SCX_SLICE_DFL, enq_flags);
+		return;
 	}
 
 	/*
-	 * Always dispatch to USER_DSQ so the timer can reenqueue tasks again
-	 * on the next tick.
+	 * Non-reenqueue path: place the task in USER_DSQ.  ops.dispatch()
+	 * does not consume USER_DSQ directly, so tasks sit here until the
+	 * timer fires and calls scx_bpf_dsq_reenq(USER_DSQ, 0).
 	 */
 	scx_bpf_dsq_insert(p, USER_DSQ, SCX_SLICE_DFL, enq_flags);
 }
 
 void BPF_STRUCT_OPS(dsq_reenq_dispatch, s32 cpu, struct task_struct *prev)
 {
-	scx_bpf_dsq_move_to_local(USER_DSQ, 0);
+	/*
+	 * Only consume from RUN_DSQ (tasks that have been through the
+	 * reenqueue path).  USER_DSQ is deliberately left for the timer.
+	 */
+	scx_bpf_dsq_move_to_local(RUN_DSQ, 0);
 }
 
 s32 BPF_STRUCT_OPS_SLEEPABLE(dsq_reenq_init)
@@ -91,6 +112,10 @@ s32 BPF_STRUCT_OPS_SLEEPABLE(dsq_reenq_init)
 	if (ret)
 		return ret;
 
+	ret = scx_bpf_create_dsq(RUN_DSQ, -1);
+	if (ret)
+		return ret;
+
 	if (!__COMPAT_has_generic_reenq()) {
 		scx_bpf_error("scx_bpf_dsq_reenq() not available");
 		return -EOPNOTSUPP;
-- 
2.43.0


  parent reply	other threads:[~2026-03-26 20:42 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-26 20:42 [PATCH 0/4] sched_ext: fix three unreliable selftests and compat kfunc signature zhidao su
2026-03-26 20:42 ` [PATCH 1/4] tools/sched_ext: compat.bpf.h: fix scx_bpf_dsq_reenq___compat signature zhidao su
2026-03-27  0:42   ` Tejun Heo
2026-03-26 20:42 ` [PATCH 2/4] selftests/sched_ext: enq_immed: fix IMMED reenqueue livelock zhidao su
2026-03-26 20:42 ` zhidao su [this message]
2026-03-26 20:42 ` [PATCH 4/4] selftests/sched_ext: consume_immed: fix reliability with CPU affinity zhidao su

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260326204238.3755737-4-suzhidao@xiaomi.com \
    --to=soolaugust@gmail.com \
    --cc=arighi@nvidia.com \
    --cc=changwoo@igalia.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=sched-ext@lists.linux.dev \
    --cc=suzhidao@xiaomi.com \
    --cc=tj@kernel.org \
    --cc=void@manifault.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®