xref: /linux/tools/testing/selftests/sched_ext/reload_loop.c (revision a5db7817af780db6a7f290c79677eff4fd13c5fa)
1*a5db7817SDavid Vernet /* SPDX-License-Identifier: GPL-2.0 */
2*a5db7817SDavid Vernet /*
3*a5db7817SDavid Vernet  * Copyright (c) 2024 Meta Platforms, Inc. and affiliates.
4*a5db7817SDavid Vernet  * Copyright (c) 2024 David Vernet <dvernet@meta.com>
5*a5db7817SDavid Vernet  */
6*a5db7817SDavid Vernet #include <bpf/bpf.h>
7*a5db7817SDavid Vernet #include <pthread.h>
8*a5db7817SDavid Vernet #include <scx/common.h>
9*a5db7817SDavid Vernet #include <sys/wait.h>
10*a5db7817SDavid Vernet #include <unistd.h>
11*a5db7817SDavid Vernet #include "maximal.bpf.skel.h"
12*a5db7817SDavid Vernet #include "scx_test.h"
13*a5db7817SDavid Vernet 
14*a5db7817SDavid Vernet static struct maximal *skel;
15*a5db7817SDavid Vernet static pthread_t threads[2];
16*a5db7817SDavid Vernet 
17*a5db7817SDavid Vernet bool force_exit = false;
18*a5db7817SDavid Vernet 
19*a5db7817SDavid Vernet static enum scx_test_status setup(void **ctx)
20*a5db7817SDavid Vernet {
21*a5db7817SDavid Vernet 	skel = maximal__open_and_load();
22*a5db7817SDavid Vernet 	if (!skel) {
23*a5db7817SDavid Vernet 		SCX_ERR("Failed to open and load skel");
24*a5db7817SDavid Vernet 		return SCX_TEST_FAIL;
25*a5db7817SDavid Vernet 	}
26*a5db7817SDavid Vernet 
27*a5db7817SDavid Vernet 	return SCX_TEST_PASS;
28*a5db7817SDavid Vernet }
29*a5db7817SDavid Vernet 
30*a5db7817SDavid Vernet static void *do_reload_loop(void *arg)
31*a5db7817SDavid Vernet {
32*a5db7817SDavid Vernet 	u32 i;
33*a5db7817SDavid Vernet 
34*a5db7817SDavid Vernet 	for (i = 0; i < 1024 && !force_exit; i++) {
35*a5db7817SDavid Vernet 		struct bpf_link *link;
36*a5db7817SDavid Vernet 
37*a5db7817SDavid Vernet 		link = bpf_map__attach_struct_ops(skel->maps.maximal_ops);
38*a5db7817SDavid Vernet 		if (link)
39*a5db7817SDavid Vernet 			bpf_link__destroy(link);
40*a5db7817SDavid Vernet 	}
41*a5db7817SDavid Vernet 
42*a5db7817SDavid Vernet 	return NULL;
43*a5db7817SDavid Vernet }
44*a5db7817SDavid Vernet 
45*a5db7817SDavid Vernet static enum scx_test_status run(void *ctx)
46*a5db7817SDavid Vernet {
47*a5db7817SDavid Vernet 	int err;
48*a5db7817SDavid Vernet 	void *ret;
49*a5db7817SDavid Vernet 
50*a5db7817SDavid Vernet 	err = pthread_create(&threads[0], NULL, do_reload_loop, NULL);
51*a5db7817SDavid Vernet 	SCX_FAIL_IF(err, "Failed to create thread 0");
52*a5db7817SDavid Vernet 
53*a5db7817SDavid Vernet 	err = pthread_create(&threads[1], NULL, do_reload_loop, NULL);
54*a5db7817SDavid Vernet 	SCX_FAIL_IF(err, "Failed to create thread 1");
55*a5db7817SDavid Vernet 
56*a5db7817SDavid Vernet 	SCX_FAIL_IF(pthread_join(threads[0], &ret), "thread 0 failed");
57*a5db7817SDavid Vernet 	SCX_FAIL_IF(pthread_join(threads[1], &ret), "thread 1 failed");
58*a5db7817SDavid Vernet 
59*a5db7817SDavid Vernet 	return SCX_TEST_PASS;
60*a5db7817SDavid Vernet }
61*a5db7817SDavid Vernet 
62*a5db7817SDavid Vernet static void cleanup(void *ctx)
63*a5db7817SDavid Vernet {
64*a5db7817SDavid Vernet 	force_exit = true;
65*a5db7817SDavid Vernet 	maximal__destroy(skel);
66*a5db7817SDavid Vernet }
67*a5db7817SDavid Vernet 
68*a5db7817SDavid Vernet struct scx_test reload_loop = {
69*a5db7817SDavid Vernet 	.name = "reload_loop",
70*a5db7817SDavid Vernet 	.description = "Stress test loading and unloading schedulers repeatedly in a tight loop",
71*a5db7817SDavid Vernet 	.setup = setup,
72*a5db7817SDavid Vernet 	.run = run,
73*a5db7817SDavid Vernet 	.cleanup = cleanup,
74*a5db7817SDavid Vernet };
75*a5db7817SDavid Vernet REGISTER_SCX_TEST(&reload_loop)
76