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
setup(void ** ctx)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
do_reload_loop(void * arg)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
run(void * ctx)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
cleanup(void * ctx)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