From: Andrea Righi <arighi@nvidia.com>
To: Cheng-Yang Chou <yphbchou0911@gmail.com>
Cc: sched-ext@lists.linux.dev, Tejun Heo <tj@kernel.org>,
David Vernet <void@manifault.com>,
Changwoo Min <changwoo@igalia.com>,
Kuba Piecuch <jpiecuch@google.com>,
Ching-Chun Huang <jserv@ccns.ncku.edu.tw>,
Chia-Ping Tsai <chia7712@gmail.com>
Subject: Re: [PATCH v3 2/2] selftests/sched_ext: Add dispatch_cookie test
Date: Sat, 9 May 2026 23:43:07 +0200 [thread overview]
Message-ID: <af-qa9u5S9NJdWR1@gpd4> (raw)
In-Reply-To: <20260509191223.168648-3-yphbchou0911@gmail.com>
Hi Cheng-Yang,
On Sun, May 10, 2026 at 03:11:57AM +0800, Cheng-Yang Chou wrote:
> Test scx_bpf_dsq_insert_begin() and scx_bpf_dsq_insert_commit().
>
> The BPF scheduler enqueues tasks into a BPF queue map in ops.enqueue()
> and dispatches them via the begin/commit transaction API in ops.dispatch().
> After a successful dispatch, the token is stored. On the task's next
> dispatch (after dequeue/re-enqueue increments qseq), the stored token is
> stale and finish_dispatch() silently drops the buffered entry.
>
> Userspace forks spinning children and repeatedly flips their CPU affinity
> to trigger dequeue/re-enqueue cycles. The test verifies both nr_tx_dispatched
> and nr_tx_stale are positive, exercising both the happy path and the
> race-detection window.
>
> Suggested-by: Tejun Heo <tj@kernel.org>
> Suggested-by: Kuba Piecuch <jpiecuch@google.com>
> Signed-off-by: Cheng-Yang Chou <yphbchou0911@gmail.com>
> ---
...
> +void BPF_STRUCT_OPS(dispatch_cookie_dispatch, s32 cpu,
> + struct task_struct *prev)
> +{
> + s32 pid;
> + struct task_struct *p;
> + u64 *stored, token;
> +
> + if (bpf_map_pop_elem(&queue, &pid))
> + return;
> +
> + p = bpf_task_from_pid(pid);
> + if (!p)
> + return;
> +
> + /*
> + * After a successful fresh dispatch, store the token. On the task's
> + * next dispatch (after re-enqueue increments qseq), the stored token
> + * exercises the race-detection window in finish_dispatch().
> + *
> + * scx_bpf_dsq_insert_commit() always returns %true when the preamble
> + * passes. Stale detection fires asynchronously in finish_dispatch()
> + * with no BPF-observable signal. When using a stored token, always
> + * pair the commit() call with a fallback scx_bpf_dsq_insert(): if
> + * the token is stale, finish_dispatch() drops the first entry and
> + * the fallback dispatches the task. If the token is still fresh,
> + * finish_dispatch() dispatches it and the fallback's CAS is a no-op.
> + */
> + stored = bpf_map_lookup_elem(&last_token, &pid);
> + if (stored) {
> + token = *stored;
> + bpf_map_delete_elem(&last_token, &pid);
> + scx_bpf_dsq_insert_commit(p, SCX_DSQ_GLOBAL, SCX_SLICE_DFL, token);
I think we should pass 0 instead of SCX_SLICE_DFL here:
scx_bpf_dsq_insert_commit(p, dsq_id, enq_flags, token)
> + scx_bpf_dsq_insert(p, SCX_DSQ_GLOBAL, SCX_SLICE_DFL, 0);
> + __sync_fetch_and_add(&nr_tx_stale, 1);
> + } else {
> + token = scx_bpf_dsq_insert_begin(p);
> + if (scx_bpf_dsq_insert_commit(p, SCX_DSQ_GLOBAL, SCX_SLICE_DFL, token)) {
Ditto.
> + __sync_fetch_and_add(&nr_tx_dispatched, 1);
Also, stale detection happens asynchronously later in finish_dispatch() with no
BPF-observable signal, so commit can return true here and write the buffered
entry with stale qseq=N, but the counter is incremented before finish_dispatch()
runs. Later, when finish_dispatch() processes the entry, it detects the qseq
mismatch (task now has N+1) and silently drops the dispatch. So nr_tx_stale
counts "attempted stale commits", not "detected and rejected stale tokens".
> + bpf_map_update_elem(&last_token, &pid, &token, BPF_ANY);
> + } else {
> + scx_bpf_dsq_insert(p, SCX_DSQ_GLOBAL, SCX_SLICE_DFL, 0);
> + }
> + }
> +
> + bpf_task_release(p);
> +}
> +
> +void BPF_STRUCT_OPS(dispatch_cookie_exit, struct scx_exit_info *ei)
> +{
> + UEI_RECORD(uei, ei);
> +}
> +
> +SEC(".struct_ops.link")
> +struct sched_ext_ops dispatch_cookie_ops = {
> + .enqueue = (void *) dispatch_cookie_enqueue,
> + .dispatch = (void *) dispatch_cookie_dispatch,
> + .exit = (void *) dispatch_cookie_exit,
> + .name = "dispatch_cookie",
> + .timeout_ms = 5000U,
> +};
...
> +static enum scx_test_status run(void *ctx)
> +{
> + struct dispatch_cookie_ctx *tctx = ctx;
> + cpu_set_t cpuset_one, cpuset_all;
> + pid_t pids[NUM_CHILDREN];
> + int i, j, nforked = 0, status;
> +
> + tctx->link = bpf_map__attach_struct_ops(tctx->skel->maps.dispatch_cookie_ops);
> + SCX_FAIL_IF(!tctx->link, "Failed to attach scheduler");
> +
> + CPU_ZERO(&cpuset_one);
> + CPU_SET(0, &cpuset_one);
This is probably fine as it is, but it's worth noticing that if for any reason
CPU0 is offline the test is probably failing.
> + SCX_FAIL_IF(sched_getaffinity(0, sizeof(cpuset_all), &cpuset_all),
> + "Failed to get CPU affinity (%d)", errno);
> +
> + for (i = 0; i < NUM_CHILDREN; i++) {
> + pids[i] = fork();
> + if (pids[i] == 0) {
> + while (1)
> + sched_yield();
> + }
> + if (pids[i] > 0)
> + nforked++;
> + }
Thanks,
-Andrea
next prev parent reply other threads:[~2026-05-09 21:43 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-09 19:11 [PATCH v3 sched_ext/for-7.2 0/2] sched_ext: Add dispatch transaction API Cheng-Yang Chou
2026-05-09 19:11 ` [PATCH v3 1/2] " Cheng-Yang Chou
2026-05-09 19:49 ` sashiko-bot
2026-05-09 21:24 ` Andrea Righi
2026-05-10 14:02 ` Tejun Heo
2026-05-10 14:58 ` Andrea Righi
2026-05-15 14:50 ` Cheng-Yang Chou
2026-05-10 14:06 ` Tejun Heo
2026-05-15 14:36 ` Cheng-Yang Chou
2026-05-09 19:11 ` [PATCH v3 2/2] selftests/sched_ext: Add dispatch_cookie test Cheng-Yang Chou
2026-05-09 20:16 ` sashiko-bot
2026-05-09 21:43 ` Andrea Righi [this message]
2026-05-15 13:42 ` Cheng-Yang Chou
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=af-qa9u5S9NJdWR1@gpd4 \
--to=arighi@nvidia.com \
--cc=changwoo@igalia.com \
--cc=chia7712@gmail.com \
--cc=jpiecuch@google.com \
--cc=jserv@ccns.ncku.edu.tw \
--cc=sched-ext@lists.linux.dev \
--cc=tj@kernel.org \
--cc=void@manifault.com \
--cc=yphbchou0911@gmail.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.