Revert "selftests/sched_ext: Add tests for SCX_ENQ_IMMED and scx_bpf_dsq_reenq()"

This reverts commit c50dcf5331.

The tests are superficial, likely AI-generated slop, and flaky. They
don't add actual value and just churn the selftests.

Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
Tejun Heo
2026-03-26 14:45:37 -10:00
parent 1f51b42bf9
commit c6f99d0ecc
7 changed files with 0 additions and 601 deletions

View File

@@ -162,11 +162,8 @@ endef
all_test_bpfprogs := $(foreach prog,$(wildcard *.bpf.c),$(INCLUDE_DIR)/$(patsubst %.c,%.skel.h,$(prog)))
auto-test-targets := \
consume_immed \
create_dsq \
dequeue \
dsq_reenq \
enq_immed \
enq_last_no_enq_fails \
ddsp_bogus_dsq_fail \
ddsp_vtimelocal_fail \

View File

@@ -1,88 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Validate SCX_ENQ_IMMED semantics through the consume path.
*
* This is the orthogonal counterpart to enq_immed:
*
* enq_immed: SCX_ENQ_IMMED via scx_bpf_dsq_insert() to local DSQ
* with SCX_OPS_ALWAYS_ENQ_IMMED
*
* consume_immed: SCX_ENQ_IMMED via scx_bpf_dsq_move_to_local() with
* explicit SCX_ENQ_IMMED in enq_flags (requires v2 kfunc)
*
* Worker threads belonging to test_tgid are inserted into USER_DSQ.
* ops.dispatch() on CPU 0 consumes from USER_DSQ with SCX_ENQ_IMMED.
* With multiple workers competing for CPU 0, dsq->nr > 1 triggers the
* IMMED slow path (reenqueue with SCX_TASK_REENQ_IMMED).
*
* Requires scx_bpf_dsq_move_to_local___v2() (v7.1+) for enq_flags support.
*/
#include <scx/common.bpf.h>
char _license[] SEC("license") = "GPL";
UEI_DEFINE(uei);
#define USER_DSQ 0
/* Set by userspace to identify the test process group. */
const volatile u32 test_tgid;
/*
* SCX_TASK_REENQ_REASON_MASK and SCX_TASK_REENQ_IMMED are exported via
* vmlinux BTF as part of enum scx_ent_flags.
*/
u64 nr_consume_immed_reenq;
void BPF_STRUCT_OPS(consume_immed_enqueue, struct task_struct *p,
u64 enq_flags)
{
if (enq_flags & SCX_ENQ_REENQ) {
u32 reason = p->scx.flags & SCX_TASK_REENQ_REASON_MASK;
if (reason == SCX_TASK_REENQ_IMMED)
__sync_fetch_and_add(&nr_consume_immed_reenq, 1);
}
if (p->tgid == (pid_t)test_tgid)
scx_bpf_dsq_insert(p, USER_DSQ, SCX_SLICE_DFL, enq_flags);
else
scx_bpf_dsq_insert(p, SCX_DSQ_GLOBAL, SCX_SLICE_DFL,
enq_flags);
}
void BPF_STRUCT_OPS(consume_immed_dispatch, s32 cpu, struct task_struct *prev)
{
if (cpu == 0)
scx_bpf_dsq_move_to_local(USER_DSQ, SCX_ENQ_IMMED);
else
scx_bpf_dsq_move_to_local(SCX_DSQ_GLOBAL, 0);
}
s32 BPF_STRUCT_OPS_SLEEPABLE(consume_immed_init)
{
/*
* scx_bpf_dsq_move_to_local___v2() adds the enq_flags parameter.
* On older kernels the consume path cannot pass SCX_ENQ_IMMED.
*/
if (!bpf_ksym_exists(scx_bpf_dsq_move_to_local___v2)) {
scx_bpf_error("scx_bpf_dsq_move_to_local v2 not available");
return -EOPNOTSUPP;
}
return scx_bpf_create_dsq(USER_DSQ, -1);
}
void BPF_STRUCT_OPS(consume_immed_exit, struct scx_exit_info *ei)
{
UEI_RECORD(uei, ei);
}
SCX_OPS_DEFINE(consume_immed_ops,
.enqueue = (void *)consume_immed_enqueue,
.dispatch = (void *)consume_immed_dispatch,
.init = (void *)consume_immed_init,
.exit = (void *)consume_immed_exit,
.name = "consume_immed")

View File

@@ -1,115 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Userspace test for SCX_ENQ_IMMED via the consume path.
*
* Validates that scx_bpf_dsq_move_to_local(USER_DSQ, SCX_ENQ_IMMED) on
* a busy CPU triggers the IMMED slow path, re-enqueuing tasks through
* ops.enqueue() with SCX_TASK_REENQ_IMMED.
*
* Skipped on single-CPU systems where local DSQ contention cannot occur.
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <bpf/bpf.h>
#include <scx/common.h>
#include "consume_immed.bpf.skel.h"
#include "scx_test.h"
#define NUM_WORKERS 4
#define TEST_DURATION_SEC 3
static volatile bool stop_workers;
static void *worker_fn(void *arg)
{
while (!stop_workers) {
volatile unsigned long i;
for (i = 0; i < 100000UL; i++)
;
usleep(100);
}
return NULL;
}
static enum scx_test_status setup(void **ctx)
{
struct consume_immed *skel;
if (!__COMPAT_has_ksym("scx_bpf_dsq_move_to_local___v2")) {
fprintf(stderr,
"SKIP: scx_bpf_dsq_move_to_local v2 not available\n");
return SCX_TEST_SKIP;
}
skel = consume_immed__open();
SCX_FAIL_IF(!skel, "Failed to open");
SCX_ENUM_INIT(skel);
skel->rodata->test_tgid = (u32)getpid();
SCX_FAIL_IF(consume_immed__load(skel), "Failed to load skel");
*ctx = skel;
return SCX_TEST_PASS;
}
static enum scx_test_status run(void *ctx)
{
struct consume_immed *skel = ctx;
struct bpf_link *link;
pthread_t workers[NUM_WORKERS];
long nproc;
int i;
u64 reenq;
nproc = sysconf(_SC_NPROCESSORS_ONLN);
if (nproc <= 1) {
fprintf(stderr,
"SKIP: single CPU, consume IMMED slow path may not trigger\n");
return SCX_TEST_SKIP;
}
link = bpf_map__attach_struct_ops(skel->maps.consume_immed_ops);
SCX_FAIL_IF(!link, "Failed to attach scheduler");
stop_workers = false;
for (i = 0; i < NUM_WORKERS; i++) {
SCX_FAIL_IF(pthread_create(&workers[i], NULL, worker_fn, NULL),
"Failed to create worker %d", i);
}
sleep(TEST_DURATION_SEC);
reenq = skel->bss->nr_consume_immed_reenq;
stop_workers = true;
for (i = 0; i < NUM_WORKERS; i++)
pthread_join(workers[i], NULL);
bpf_link__destroy(link);
SCX_EQ(skel->data->uei.kind, EXIT_KIND(SCX_EXIT_UNREG));
SCX_GT(reenq, 0);
return SCX_TEST_PASS;
}
static void cleanup(void *ctx)
{
struct consume_immed *skel = ctx;
consume_immed__destroy(skel);
}
struct scx_test consume_immed = {
.name = "consume_immed",
.description = "Verify SCX_ENQ_IMMED slow path via "
"scx_bpf_dsq_move_to_local() consume path",
.setup = setup,
.run = run,
.cleanup = cleanup,
};
REGISTER_SCX_TEST(&consume_immed)

View File

@@ -1,120 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* 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.
*
* The test verifies:
* - scx_bpf_dsq_reenq() triggers ops.enqueue() with SCX_ENQ_REENQ
* - The reenqueue reason is SCX_TASK_REENQ_KFUNC (bit 12 set)
* - Tasks are correctly re-dispatched after reenqueue
*/
#include <scx/common.bpf.h>
char _license[] SEC("license") = "GPL";
UEI_DEFINE(uei);
#define USER_DSQ 0
/*
* SCX_TASK_REENQ_REASON_MASK and SCX_TASK_REENQ_KFUNC are exported via
* vmlinux BTF as part of enum scx_ent_flags.
*/
/* 5ms timer interval */
#define REENQ_TIMER_NS (5 * 1000 * 1000ULL)
/*
* Number of times ops.enqueue() was called with SCX_ENQ_REENQ set and
* SCX_TASK_REENQ_KFUNC recorded in p->scx.flags.
*/
u64 nr_reenq_kfunc;
struct reenq_timer_val {
struct bpf_timer timer;
};
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 1);
__type(key, u32);
__type(value, struct reenq_timer_val);
} reenq_timer SEC(".maps");
/*
* Timer callback: reenqueue all tasks currently sitting on USER_DSQ back
* through ops.enqueue() with SCX_ENQ_REENQ | SCX_TASK_REENQ_KFUNC.
*/
static int reenq_timerfn(void *map, int *key, struct bpf_timer *timer)
{
scx_bpf_dsq_reenq(USER_DSQ, 0);
bpf_timer_start(timer, REENQ_TIMER_NS, 0);
return 0;
}
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);
}
/*
* Always dispatch to USER_DSQ so the timer can reenqueue tasks again
* on the next tick.
*/
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);
}
s32 BPF_STRUCT_OPS_SLEEPABLE(dsq_reenq_init)
{
struct reenq_timer_val *tval;
u32 key = 0;
s32 ret;
ret = scx_bpf_create_dsq(USER_DSQ, -1);
if (ret)
return ret;
if (!__COMPAT_has_generic_reenq()) {
scx_bpf_error("scx_bpf_dsq_reenq() not available");
return -EOPNOTSUPP;
}
tval = bpf_map_lookup_elem(&reenq_timer, &key);
if (!tval)
return -ESRCH;
bpf_timer_init(&tval->timer, &reenq_timer, CLOCK_MONOTONIC);
bpf_timer_set_callback(&tval->timer, reenq_timerfn);
return bpf_timer_start(&tval->timer, REENQ_TIMER_NS, 0);
}
void BPF_STRUCT_OPS(dsq_reenq_exit, struct scx_exit_info *ei)
{
UEI_RECORD(uei, ei);
}
SCX_OPS_DEFINE(dsq_reenq_ops,
.enqueue = (void *)dsq_reenq_enqueue,
.dispatch = (void *)dsq_reenq_dispatch,
.init = (void *)dsq_reenq_init,
.exit = (void *)dsq_reenq_exit,
.timeout_ms = 10000,
.name = "dsq_reenq")

View File

@@ -1,95 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Userspace test for scx_bpf_dsq_reenq() semantics.
*
* Attaches the dsq_reenq BPF scheduler, runs workload threads that
* sleep and yield to keep tasks on USER_DSQ, waits for the BPF timer
* to fire several times, then verifies that at least one kfunc-triggered
* reenqueue was observed (ops.enqueue() called with SCX_ENQ_REENQ and
* SCX_TASK_REENQ_KFUNC in p->scx.flags).
*/
#include <bpf/bpf.h>
#include <scx/common.h>
#include <unistd.h>
#include <pthread.h>
#include "dsq_reenq.bpf.skel.h"
#include "scx_test.h"
#define NUM_WORKERS 4
#define TEST_DURATION_SEC 3
static volatile bool stop_workers;
static pthread_t workers[NUM_WORKERS];
static void *worker_fn(void *arg)
{
while (!stop_workers) {
usleep(500);
sched_yield();
}
return NULL;
}
static enum scx_test_status setup(void **ctx)
{
struct dsq_reenq *skel;
if (!__COMPAT_has_ksym("scx_bpf_dsq_reenq")) {
fprintf(stderr, "SKIP: scx_bpf_dsq_reenq() not available\n");
return SCX_TEST_SKIP;
}
skel = dsq_reenq__open();
SCX_FAIL_IF(!skel, "Failed to open");
SCX_ENUM_INIT(skel);
SCX_FAIL_IF(dsq_reenq__load(skel), "Failed to load skel");
*ctx = skel;
return SCX_TEST_PASS;
}
static enum scx_test_status run(void *ctx)
{
struct dsq_reenq *skel = ctx;
struct bpf_link *link;
int i;
link = bpf_map__attach_struct_ops(skel->maps.dsq_reenq_ops);
SCX_FAIL_IF(!link, "Failed to attach scheduler");
stop_workers = false;
for (i = 0; i < NUM_WORKERS; i++) {
SCX_FAIL_IF(pthread_create(&workers[i], NULL, worker_fn, NULL),
"Failed to create worker %d", i);
}
sleep(TEST_DURATION_SEC);
stop_workers = true;
for (i = 0; i < NUM_WORKERS; i++)
pthread_join(workers[i], NULL);
bpf_link__destroy(link);
SCX_EQ(skel->data->uei.kind, EXIT_KIND(SCX_EXIT_UNREG));
SCX_GT(skel->bss->nr_reenq_kfunc, 0);
return SCX_TEST_PASS;
}
static void cleanup(void *ctx)
{
struct dsq_reenq *skel = ctx;
dsq_reenq__destroy(skel);
}
struct scx_test dsq_reenq = {
.name = "dsq_reenq",
.description = "Verify scx_bpf_dsq_reenq() triggers enqueue with "
"SCX_ENQ_REENQ and SCX_TASK_REENQ_KFUNC reason",
.setup = setup,
.run = run,
.cleanup = cleanup,
};
REGISTER_SCX_TEST(&dsq_reenq)

View File

@@ -1,63 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Validate SCX_ENQ_IMMED fast/slow path semantics via the direct insert path.
*
* With SCX_OPS_ALWAYS_ENQ_IMMED set, the kernel automatically adds
* SCX_ENQ_IMMED to every local DSQ dispatch. When the target CPU's local
* DSQ already has tasks queued (dsq->nr > 1), the kernel re-enqueues the
* task through ops.enqueue() with SCX_ENQ_REENQ and SCX_TASK_REENQ_IMMED
* recorded in p->scx.flags (the "slow path").
*
* Worker threads are pinned to CPU 0 via SCX_DSQ_LOCAL_ON to guarantee
* local DSQ contention.
*/
#include <scx/common.bpf.h>
char _license[] SEC("license") = "GPL";
UEI_DEFINE(uei);
/* Set by userspace to identify the test process group. */
const volatile u32 test_tgid;
/*
* SCX_TASK_REENQ_REASON_MASK and SCX_TASK_REENQ_IMMED are exported via
* vmlinux BTF as part of enum scx_ent_flags.
*/
u64 nr_immed_reenq;
void BPF_STRUCT_OPS(enq_immed_enqueue, struct task_struct *p, u64 enq_flags)
{
if (enq_flags & SCX_ENQ_REENQ) {
u32 reason = p->scx.flags & SCX_TASK_REENQ_REASON_MASK;
if (reason == SCX_TASK_REENQ_IMMED)
__sync_fetch_and_add(&nr_immed_reenq, 1);
}
if (p->tgid == (pid_t)test_tgid)
scx_bpf_dsq_insert(p, SCX_DSQ_LOCAL_ON | 0, SCX_SLICE_DFL,
enq_flags);
else
scx_bpf_dsq_insert(p, SCX_DSQ_GLOBAL, SCX_SLICE_DFL,
enq_flags);
}
void BPF_STRUCT_OPS(enq_immed_dispatch, s32 cpu, struct task_struct *prev)
{
scx_bpf_dsq_move_to_local(SCX_DSQ_GLOBAL, 0);
}
void BPF_STRUCT_OPS(enq_immed_exit, struct scx_exit_info *ei)
{
UEI_RECORD(uei, ei);
}
SCX_OPS_DEFINE(enq_immed_ops,
.enqueue = (void *)enq_immed_enqueue,
.dispatch = (void *)enq_immed_dispatch,
.exit = (void *)enq_immed_exit,
.flags = SCX_OPS_ALWAYS_ENQ_IMMED,
.name = "enq_immed")

View File

@@ -1,117 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Userspace test for SCX_ENQ_IMMED via the direct insert path.
*
* Validates that dispatching tasks to a busy CPU's local DSQ with
* SCX_OPS_ALWAYS_ENQ_IMMED triggers the IMMED slow path: the kernel
* re-enqueues the task through ops.enqueue() with SCX_TASK_REENQ_IMMED.
*
* Skipped on single-CPU systems where local DSQ contention cannot occur.
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <bpf/bpf.h>
#include <scx/common.h>
#include "enq_immed.bpf.skel.h"
#include "scx_test.h"
#define NUM_WORKERS 4
#define TEST_DURATION_SEC 3
static volatile bool stop_workers;
static void *worker_fn(void *arg)
{
while (!stop_workers) {
volatile unsigned long i;
for (i = 0; i < 100000UL; i++)
;
usleep(100);
}
return NULL;
}
static enum scx_test_status setup(void **ctx)
{
struct enq_immed *skel;
u64 v;
if (!__COMPAT_read_enum("scx_ops_flags",
"SCX_OPS_ALWAYS_ENQ_IMMED", &v)) {
fprintf(stderr,
"SKIP: SCX_OPS_ALWAYS_ENQ_IMMED not available\n");
return SCX_TEST_SKIP;
}
skel = enq_immed__open();
SCX_FAIL_IF(!skel, "Failed to open");
SCX_ENUM_INIT(skel);
skel->rodata->test_tgid = (u32)getpid();
SCX_FAIL_IF(enq_immed__load(skel), "Failed to load skel");
*ctx = skel;
return SCX_TEST_PASS;
}
static enum scx_test_status run(void *ctx)
{
struct enq_immed *skel = ctx;
struct bpf_link *link;
pthread_t workers[NUM_WORKERS];
long nproc;
int i;
u64 reenq;
nproc = sysconf(_SC_NPROCESSORS_ONLN);
if (nproc <= 1) {
fprintf(stderr,
"SKIP: single CPU, IMMED slow path may not trigger\n");
return SCX_TEST_SKIP;
}
link = bpf_map__attach_struct_ops(skel->maps.enq_immed_ops);
SCX_FAIL_IF(!link, "Failed to attach scheduler");
stop_workers = false;
for (i = 0; i < NUM_WORKERS; i++) {
SCX_FAIL_IF(pthread_create(&workers[i], NULL, worker_fn, NULL),
"Failed to create worker %d", i);
}
sleep(TEST_DURATION_SEC);
reenq = skel->bss->nr_immed_reenq;
stop_workers = true;
for (i = 0; i < NUM_WORKERS; i++)
pthread_join(workers[i], NULL);
bpf_link__destroy(link);
SCX_EQ(skel->data->uei.kind, EXIT_KIND(SCX_EXIT_UNREG));
SCX_GT(reenq, 0);
return SCX_TEST_PASS;
}
static void cleanup(void *ctx)
{
struct enq_immed *skel = ctx;
enq_immed__destroy(skel);
}
struct scx_test enq_immed = {
.name = "enq_immed",
.description = "Verify SCX_ENQ_IMMED slow path via direct insert "
"with SCX_OPS_ALWAYS_ENQ_IMMED",
.setup = setup,
.run = run,
.cleanup = cleanup,
};
REGISTER_SCX_TEST(&enq_immed)