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