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