Skip to content
This repository has been archived by the owner on Jun 18, 2024. It is now read-only.

Commit

Permalink
scx: Add stress-test for loading schedulers in a tight loop
Browse files Browse the repository at this point in the history
In #129, Andrea fixed a bug
where we trip over a NULL pointer deref by trying to load multiple
schedulers at a time. Let's add a stress test that tries to load
multiple schedulers in a tight loop at the same time.

Additionally, do a bit of cleanup in the build system to have testcases
take all BPF progs as dependencies. We don't really gain anything by
artificially coupling the name of testcases to the BPF progs they use.

Signed-off-by: David Vernet <void@manifault.com>
  • Loading branch information
Byte-Lab committed Jan 28, 2024
1 parent 679136f commit 26de71e
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 7 deletions.
16 changes: 9 additions & 7 deletions tools/testing/selftests/scx/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -155,22 +155,28 @@ override define CLEAN
rm -f runner
endef

# Every testcase takes all of the BPF progs are dependencies by default. This
# allows testcases to load any BPF scheduler, which is useful for testcases
# that don't need their own prog to run their test.
all_test_bpfprogs := $(foreach prog,$(wildcard *.bpf.c),$(INCLUDE_DIR)/$(patsubst %.c,%.skel.h,$(prog)))

auto-test-targets := \
enq_last_no_enq_fails \
enq_select_cpu_fails \
ddsp_bogus_dsq_fail \
ddsp_vtimelocal_fail \
init_enable_count \
maybe_null \
maximal \
maybe_null \
minimal \
reload_loop \
select_cpu_dfl \
select_cpu_dfl_nodispatch \
select_cpu_dispatch \
select_cpu_dispatch_bad_dsq \
select_cpu_dispatch_dbl_dsp \
select_cpu_vtime \
test_example
test_example \

testcase-targets := $(addsuffix .o,$(addprefix $(SCXOBJ_DIR)/,$(auto-test-targets)))

Expand All @@ -183,11 +189,7 @@ $(SCXOBJ_DIR)/runner.o: runner.c | $(SCXOBJ_DIR)
# Note that we must do double expansion here in order to support conditionally
# compiling BPF object files only if one is present, as the wildcard Make
# function doesn't support using implicit rules otherwise.
.SECONDEXPANSION:
$(testcase-targets): $(SCXOBJ_DIR)/%.o: %.c $(SCXOBJ_DIR)/runner.o \
$$(if $$(wildcard $$*.bpf.c), $(INCLUDE_DIR)/%.bpf.skel.h) \
$$(if $$(wildcard $$*_fail.bpf.c), $(INCLUDE_DIR)/%_fail.bpf.skel.h) \
| $(SCXOBJ_DIR)
$(testcase-targets): $(SCXOBJ_DIR)/%.o: %.c $(SCXOBJ_DIR)/runner.o $(all_test_bpfprogs) | $(SCXOBJ_DIR)
$(eval test=$(patsubst %.o,%.c,$(notdir $@)))
$(CC) $(CFLAGS) -c $< -o $@ $(SCXOBJ_DIR)/runner.o

Expand Down
76 changes: 76 additions & 0 deletions tools/testing/selftests/scx/reload_loop.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2023 Meta Platforms, Inc. and affiliates.
* Copyright (c) 2023 David Vernet <dvernet@meta.com>
* Copyright (c) 2023 Tejun Heo <tj@kernel.org>
*/
#include <bpf/bpf.h>
#include <pthread.h>
#include <scx/common.h>
#include <sys/wait.h>
#include <unistd.h>
#include "maximal.bpf.skel.h"
#include "scx_test.h"

static struct maximal *skel;
static pthread_t threads[2];

bool force_exit = false;

static enum scx_test_status setup(void **ctx)
{
skel = maximal__open_and_load();
if (!skel) {
SCX_ERR("Failed to open and load skel");
return SCX_TEST_FAIL;
}

return SCX_TEST_PASS;
}

static void *do_reload_loop(void *arg)
{
u32 i;

for (i = 0; i < 512 && !force_exit; i++) {
struct bpf_link *link;

link = bpf_map__attach_struct_ops(skel->maps.maximal_ops);
if (link)
bpf_link__destroy(link);
}

return NULL;
}

static enum scx_test_status run(void *ctx)
{
int err;
void *ret;

err = pthread_create(&threads[0], NULL, do_reload_loop, NULL);
SCX_FAIL_IF(err, "Failed to create thread 0");

err = pthread_create(&threads[1], NULL, do_reload_loop, NULL);
SCX_FAIL_IF(err, "Failed to create thread 1");

SCX_FAIL_IF(pthread_join(threads[0], &ret), "thread 0 failed");
SCX_FAIL_IF(pthread_join(threads[1], &ret), "thread 1 failed");

return SCX_TEST_PASS;
}

static void cleanup(void *ctx)
{
force_exit = true;
maximal__destroy(skel);
}

struct scx_test reload_loop = {
.name = "reload_loop",
.description = "Stress test loading and unloading schedulers repeatedly in a tight loop",
.setup = setup,
.run = run,
.cleanup = cleanup,
};
REGISTER_SCX_TEST(&reload_loop)

0 comments on commit 26de71e

Please sign in to comment.