Sched_ext development
 help / color / mirror / Atom feed
From: Tao Cui <cui.tao@linux.dev>
To: Tejun Heo <tj@kernel.org>
Cc: David Vernet <void@manifault.com>,
	Andrea Righi <arighi@nvidia.com>,
	Changwoo Min <changwoo@igalia.com>,
	sched-ext@lists.linux.dev, cui.tao@linux.dev,
	Tao Cui <cuitao@kylinos.cn>
Subject: [PATCH 4/5] selftests/sched_ext: Add SCX_ASSERT_ALIVE and adopt it
Date: Fri,  9 Oct 2026 21:41:03 +0800	[thread overview]
Message-ID: <20261009134104.296891-5-cui.tao@linux.dev> (raw)
In-Reply-To: <20261009134104.296891-1-cui.tao@linux.dev>

From: Tao Cui <cuitao@kylinos.cn>

A scheduler that dies mid-test freezes the state that the test is
about to assert on, so the assertions can pass vacuously. Add
SCX_ASSERT_ALIVE(), which fails the test with the recorded exit kind
and code, and use it in maximal, create_dsq and init_enable_count.
Existing open-coded checks keep their goto-based cleanup and are not
converted. init_enable_count also clears the uei between its two
attach cycles, since the clean unregister of the first cycle would
otherwise trip the check of the second.

Signed-off-by: Tao Cui <cuitao@kylinos.cn>
---
 tools/testing/selftests/sched_ext/create_dsq.bpf.c |  8 ++++++++
 tools/testing/selftests/sched_ext/create_dsq.c     |  2 ++
 .../selftests/sched_ext/init_enable_count.bpf.c    |  8 ++++++++
 .../selftests/sched_ext/init_enable_count.c        | 13 +++++++++++++
 tools/testing/selftests/sched_ext/maximal.bpf.c    |  6 +++++-
 tools/testing/selftests/sched_ext/maximal.c        |  2 ++
 tools/testing/selftests/sched_ext/scx_test.h       | 14 ++++++++++++++
 7 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/sched_ext/create_dsq.bpf.c b/tools/testing/selftests/sched_ext/create_dsq.bpf.c
index 680cc4b6d8c7..24dacd1aab0c 100644
--- a/tools/testing/selftests/sched_ext/create_dsq.bpf.c
+++ b/tools/testing/selftests/sched_ext/create_dsq.bpf.c
@@ -12,6 +12,8 @@ char _license[] SEC("license") = "GPL";
 
 u32 nr_lifecycle_tests;
 
+UEI_DEFINE(uei);
+
 void BPF_STRUCT_OPS(create_dsq_exit_task, struct task_struct *p,
 		    struct scx_exit_task_args *args)
 {
@@ -84,10 +86,16 @@ s32 BPF_STRUCT_OPS_SLEEPABLE(create_dsq_init)
 	return 0;
 }
 
+void BPF_STRUCT_OPS(create_dsq_exit, struct scx_exit_info *ei)
+{
+	UEI_RECORD(uei, ei);
+}
+
 SEC(".struct_ops.link")
 struct sched_ext_ops create_dsq_ops = {
 	.init_task		= (void *) create_dsq_init_task,
 	.exit_task		= (void *) create_dsq_exit_task,
 	.init			= (void *) create_dsq_init,
+	.exit			= (void *) create_dsq_exit,
 	.name			= "create_dsq",
 };
diff --git a/tools/testing/selftests/sched_ext/create_dsq.c b/tools/testing/selftests/sched_ext/create_dsq.c
index 422e6532ee71..84143d5710f4 100644
--- a/tools/testing/selftests/sched_ext/create_dsq.c
+++ b/tools/testing/selftests/sched_ext/create_dsq.c
@@ -35,6 +35,8 @@ static enum scx_test_status run(void *ctx)
 		return SCX_TEST_FAIL;
 	}
 
+	SCX_ASSERT_ALIVE(skel, uei);
+
 	bpf_link__destroy(link);
 
 	SCX_EQ(skel->bss->nr_lifecycle_tests, 1024);
diff --git a/tools/testing/selftests/sched_ext/init_enable_count.bpf.c b/tools/testing/selftests/sched_ext/init_enable_count.bpf.c
index 5eb9edb1837d..c0a5dd8fe183 100644
--- a/tools/testing/selftests/sched_ext/init_enable_count.bpf.c
+++ b/tools/testing/selftests/sched_ext/init_enable_count.bpf.c
@@ -15,6 +15,8 @@ char _license[] SEC("license") = "GPL";
 u64 init_task_cnt, exit_task_cnt, enable_cnt, disable_cnt;
 u64 init_fork_cnt, init_transition_cnt;
 
+UEI_DEFINE(uei);
+
 s32 BPF_STRUCT_OPS_SLEEPABLE(cnt_init_task, struct task_struct *p,
 			     struct scx_init_task_args *args)
 {
@@ -43,11 +45,17 @@ void BPF_STRUCT_OPS(cnt_disable, struct task_struct *p)
 	__sync_fetch_and_add(&disable_cnt, 1);
 }
 
+void BPF_STRUCT_OPS(cnt_exit, struct scx_exit_info *ei)
+{
+	UEI_RECORD(uei, ei);
+}
+
 SEC(".struct_ops.link")
 struct sched_ext_ops init_enable_count_ops = {
 	.init_task	= (void *) cnt_init_task,
 	.exit_task	= (void *) cnt_exit_task,
 	.enable		= (void *) cnt_enable,
 	.disable	= (void *) cnt_disable,
+	.exit		= (void *) cnt_exit,
 	.name		= "init_enable_count",
 };
diff --git a/tools/testing/selftests/sched_ext/init_enable_count.c b/tools/testing/selftests/sched_ext/init_enable_count.c
index 44577e30e764..c4a57038a1d6 100644
--- a/tools/testing/selftests/sched_ext/init_enable_count.c
+++ b/tools/testing/selftests/sched_ext/init_enable_count.c
@@ -5,6 +5,7 @@
  * Copyright (c) 2023 Tejun Heo <tj@kernel.org>
  */
 #include <signal.h>
+#include <string.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <sched.h>
@@ -72,7 +73,17 @@ static enum scx_test_status run_test(bool global)
 	close(pipe_fds[1]);
 	signal(SIGCHLD, SIG_DFL);
 
+	SCX_ASSERT_ALIVE(skel, uei);
+
 	bpf_link__destroy(link);
+
+	/*
+	 * The clean unregister above is recorded in uei and would
+	 * otherwise trip the liveness check of the second cycle, which
+	 * reuses this skeleton.
+	 */
+	memset(&skel->data->uei, 0, sizeof(skel->data->uei));
+
 	SCX_GE(skel->bss->init_task_cnt, num_pre_forks);
 	SCX_GE(skel->bss->exit_task_cnt, num_pre_forks);
 
@@ -124,6 +135,8 @@ static enum scx_test_status run_test(bool global)
 			    status);
 	}
 
+	SCX_ASSERT_ALIVE(skel, uei);
+
 	bpf_link__destroy(link);
 
 	SCX_GE(skel->bss->init_task_cnt, 2 * num_children);
diff --git a/tools/testing/selftests/sched_ext/maximal.bpf.c b/tools/testing/selftests/sched_ext/maximal.bpf.c
index 04a369078aac..9ea664e2ff70 100644
--- a/tools/testing/selftests/sched_ext/maximal.bpf.c
+++ b/tools/testing/selftests/sched_ext/maximal.bpf.c
@@ -14,6 +14,8 @@ char _license[] SEC("license") = "GPL";
 
 #define DSQ_ID 0
 
+UEI_DEFINE(uei);
+
 s32 BPF_STRUCT_OPS(maximal_select_cpu, struct task_struct *p, s32 prev_cpu,
 		   u64 wake_flags)
 {
@@ -132,7 +134,9 @@ s32 BPF_STRUCT_OPS_SLEEPABLE(maximal_init)
 }
 
 void BPF_STRUCT_OPS(maximal_exit, struct scx_exit_info *info)
-{}
+{
+	UEI_RECORD(uei, info);
+}
 
 SEC(".struct_ops.link")
 struct sched_ext_ops maximal_ops = {
diff --git a/tools/testing/selftests/sched_ext/maximal.c b/tools/testing/selftests/sched_ext/maximal.c
index 1dc369224670..6c6b80e0446e 100644
--- a/tools/testing/selftests/sched_ext/maximal.c
+++ b/tools/testing/selftests/sched_ext/maximal.c
@@ -35,6 +35,8 @@ static enum scx_test_status run(void *ctx)
 	link = bpf_map__attach_struct_ops(skel->maps.maximal_ops);
 	SCX_FAIL_IF(!link, "Failed to attach scheduler");
 
+	SCX_ASSERT_ALIVE(skel, uei);
+
 	bpf_link__destroy(link);
 
 	return SCX_TEST_PASS;
diff --git a/tools/testing/selftests/sched_ext/scx_test.h b/tools/testing/selftests/sched_ext/scx_test.h
index fe0e6dabe7a4..aa676cd5bb8d 100644
--- a/tools/testing/selftests/sched_ext/scx_test.h
+++ b/tools/testing/selftests/sched_ext/scx_test.h
@@ -125,6 +125,20 @@ void scx_test_register(struct scx_test *test);
 #define SCX_ASSERT(_x) SCX_FAIL_IF(!(_x), "Expected %s to be true (%lu)",		\
 				   #_x, (u64)(_x))
 
+/*
+ * SCX_ASSERT_ALIVE - Fail the test if the scheduler under test exited
+ * on its own between attach and this check, e.g. from a runtime error.
+ * A scheduler that dies mid-test freezes whatever state the test is
+ * about to assert on, which can make the assertions pass vacuously.
+ */
+#define SCX_ASSERT_ALIVE(__skel, __uei)						\
+	do {									\
+		if (UEI_EXITED(__skel, __uei))					\
+			SCX_FAIL("Scheduler exited unexpectedly (kind=%llu code=%lld)", \
+				 (unsigned long long)(__skel)->data->__uei.kind, \
+				 (long long)(__skel)->data->__uei.exit_code);	\
+	} while (0)
+
 #define SCX_ECODE_VAL(__ecode) ({						\
         u64 __val = 0;								\
 	bool __found = false;							\
-- 
2.53.0


  parent reply	other threads:[~2026-10-09 13:41 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-09 13:40 [PATCH 0/5] sched_ext: selftest infrastructure fixes Tao Cui
2026-10-09 13:41 ` [PATCH 1/5] selftests/sched_ext: Fix reload_loop error-path use-after-free Tao Cui
2026-10-09 13:41 ` [PATCH 2/5] sched_ext: Add SCX_ECODE_RSN_CGROUP_OFFLINE to user_exit_info.h Tao Cui
2026-10-09 13:41 ` [PATCH 3/5] selftests/sched_ext: Fail loudly when EXIT_KIND is missing from BTF Tao Cui
2026-10-09 13:54   ` sashiko-bot
2026-10-09 13:41 ` Tao Cui [this message]
2026-10-09 13:41 ` [PATCH 5/5] selftests/sched_ext: Bound exit waits and report reload_loop failures Tao Cui
2026-10-09 13:48   ` sashiko-bot

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=20261009134104.296891-5-cui.tao@linux.dev \
    --to=cui.tao@linux.dev \
    --cc=arighi@nvidia.com \
    --cc=changwoo@igalia.com \
    --cc=cuitao@kylinos.cn \
    --cc=sched-ext@lists.linux.dev \
    --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