1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2024-2025 Meta Platforms, Inc. and affiliates. */
3 #include <test_progs.h>
4 #include <network_helpers.h>
5 #include <sys/sysinfo.h>
6
7 #include "res_spin_lock.skel.h"
8 #include "res_spin_lock_fail.skel.h"
9
test_res_spin_lock_failure(void)10 void test_res_spin_lock_failure(void)
11 {
12 RUN_TESTS(res_spin_lock_fail);
13 }
14
15 static volatile int skip;
16
spin_lock_thread(void * arg)17 static void *spin_lock_thread(void *arg)
18 {
19 int err, prog_fd = *(u32 *) arg;
20 LIBBPF_OPTS(bpf_test_run_opts, topts,
21 .data_in = &pkt_v4,
22 .data_size_in = sizeof(pkt_v4),
23 .repeat = 10000,
24 );
25
26 while (!READ_ONCE(skip)) {
27 err = bpf_prog_test_run_opts(prog_fd, &topts);
28 if (err || topts.retval) {
29 ASSERT_OK(err, "test_run");
30 ASSERT_OK(topts.retval, "test_run retval");
31 break;
32 }
33 }
34 pthread_exit(arg);
35 }
36
test_res_spin_lock_success(void)37 void test_res_spin_lock_success(void)
38 {
39 LIBBPF_OPTS(bpf_test_run_opts, topts,
40 .data_in = &pkt_v4,
41 .data_size_in = sizeof(pkt_v4),
42 .repeat = 1,
43 );
44 struct res_spin_lock *skel;
45 pthread_t thread_id[16];
46 int prog_fd, i, err;
47 void *ret;
48
49 if (get_nprocs() < 2) {
50 test__skip();
51 return;
52 }
53
54 skel = res_spin_lock__open_and_load();
55 if (!ASSERT_OK_PTR(skel, "res_spin_lock__open_and_load"))
56 return;
57 /* AA deadlock */
58 prog_fd = bpf_program__fd(skel->progs.res_spin_lock_test);
59 err = bpf_prog_test_run_opts(prog_fd, &topts);
60 ASSERT_OK(err, "error");
61 ASSERT_OK(topts.retval, "retval");
62
63 prog_fd = bpf_program__fd(skel->progs.res_spin_lock_test_held_lock_max);
64 err = bpf_prog_test_run_opts(prog_fd, &topts);
65 ASSERT_OK(err, "error");
66 ASSERT_OK(topts.retval, "retval");
67
68 /* Multi-threaded ABBA deadlock. */
69
70 prog_fd = bpf_program__fd(skel->progs.res_spin_lock_test_AB);
71 for (i = 0; i < 16; i++) {
72 int err;
73
74 err = pthread_create(&thread_id[i], NULL, &spin_lock_thread, &prog_fd);
75 if (!ASSERT_OK(err, "pthread_create"))
76 goto end;
77 }
78
79 topts.retval = 0;
80 topts.repeat = 1000;
81 int fd = bpf_program__fd(skel->progs.res_spin_lock_test_BA);
82 while (!topts.retval && !err && !READ_ONCE(skel->bss->err)) {
83 err = bpf_prog_test_run_opts(fd, &topts);
84 }
85
86 WRITE_ONCE(skip, true);
87
88 for (i = 0; i < 16; i++) {
89 if (!ASSERT_OK(pthread_join(thread_id[i], &ret), "pthread_join"))
90 goto end;
91 if (!ASSERT_EQ(ret, &prog_fd, "ret == prog_fd"))
92 goto end;
93 }
94
95 ASSERT_EQ(READ_ONCE(skel->bss->err), -EDEADLK, "timeout err");
96 ASSERT_OK(err, "err");
97 ASSERT_EQ(topts.retval, -EDEADLK, "timeout");
98 end:
99 res_spin_lock__destroy(skel);
100 return;
101 }
102