1 // SPDX-License-Identifier: GPL-2.0
3 #include <bpf/bpf_tracing.h>
4 #include <bpf/bpf_helpers.h>
5 #include <bpf/bpf_core_read.h>
6 #include "bpf_experimental.h"
9 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
12 #include "linked_list.h"
14 static __always_inline
15 int list_push_pop(struct bpf_spin_lock *lock, struct bpf_list_head *head, bool leave_in_map)
17 struct bpf_list_node *n;
20 f = bpf_obj_new(typeof(*f));
25 n = bpf_list_pop_front(head);
26 bpf_spin_unlock(lock);
28 bpf_obj_drop(container_of(n, struct foo, node2));
34 n = bpf_list_pop_back(head);
35 bpf_spin_unlock(lock);
37 bpf_obj_drop(container_of(n, struct foo, node2));
45 bpf_list_push_front(head, &f->node2);
46 bpf_spin_unlock(lock);
50 n = bpf_list_pop_back(head);
51 bpf_spin_unlock(lock);
54 f = container_of(n, struct foo, node2);
62 bpf_list_push_front(head, &f->node2);
63 bpf_spin_unlock(lock);
65 n = bpf_list_pop_front(head);
66 bpf_spin_unlock(lock);
69 f = container_of(n, struct foo, node2);
77 n = bpf_list_pop_front(head);
78 bpf_spin_unlock(lock);
80 bpf_obj_drop(container_of(n, struct foo, node2));
85 n = bpf_list_pop_back(head);
86 bpf_spin_unlock(lock);
88 bpf_obj_drop(container_of(n, struct foo, node2));
95 static __always_inline
96 int list_push_pop_multiple(struct bpf_spin_lock *lock, struct bpf_list_head *head, bool leave_in_map)
98 struct bpf_list_node *n;
99 struct foo *f[200], *pf;
102 /* Loop following this check adds nodes 2-at-a-time in order to
103 * validate multiple release_on_unlock release logic
105 if (ARRAY_SIZE(f) % 2)
108 for (i = 0; i < ARRAY_SIZE(f); i += 2) {
109 f[i] = bpf_obj_new(typeof(**f));
114 f[i + 1] = bpf_obj_new(typeof(**f));
119 f[i + 1]->data = i + 1;
122 bpf_list_push_front(head, &f[i]->node2);
123 bpf_list_push_front(head, &f[i + 1]->node2);
124 bpf_spin_unlock(lock);
127 for (i = 0; i < ARRAY_SIZE(f); i++) {
129 n = bpf_list_pop_front(head);
130 bpf_spin_unlock(lock);
133 pf = container_of(n, struct foo, node2);
134 if (pf->data != (ARRAY_SIZE(f) - i - 1)) {
139 bpf_list_push_back(head, &pf->node2);
140 bpf_spin_unlock(lock);
146 for (i = 0; i < ARRAY_SIZE(f); i++) {
148 n = bpf_list_pop_back(head);
149 bpf_spin_unlock(lock);
152 pf = container_of(n, struct foo, node2);
160 n = bpf_list_pop_back(head);
161 bpf_spin_unlock(lock);
163 bpf_obj_drop(container_of(n, struct foo, node2));
168 n = bpf_list_pop_front(head);
169 bpf_spin_unlock(lock);
171 bpf_obj_drop(container_of(n, struct foo, node2));
177 static __always_inline
178 int list_in_list(struct bpf_spin_lock *lock, struct bpf_list_head *head, bool leave_in_map)
180 struct bpf_list_node *n;
181 struct bar *ba[8], *b;
185 f = bpf_obj_new(typeof(*f));
188 for (i = 0; i < ARRAY_SIZE(ba); i++) {
189 b = bpf_obj_new(typeof(*b));
195 bpf_spin_lock(&f->lock);
196 bpf_list_push_back(&f->head, &b->node);
197 bpf_spin_unlock(&f->lock);
202 bpf_list_push_front(head, &f->node2);
203 bpf_spin_unlock(lock);
209 n = bpf_list_pop_front(head);
210 bpf_spin_unlock(lock);
213 f = container_of(n, struct foo, node2);
219 for (i = 0; i < ARRAY_SIZE(ba); i++) {
220 bpf_spin_lock(&f->lock);
221 n = bpf_list_pop_front(&f->head);
222 bpf_spin_unlock(&f->lock);
227 b = container_of(n, struct bar, node);
235 bpf_spin_lock(&f->lock);
236 n = bpf_list_pop_front(&f->head);
237 bpf_spin_unlock(&f->lock);
240 bpf_obj_drop(container_of(n, struct bar, node));
247 static __always_inline
248 int test_list_push_pop(struct bpf_spin_lock *lock, struct bpf_list_head *head)
252 ret = list_push_pop(lock, head, false);
255 return list_push_pop(lock, head, true);
258 static __always_inline
259 int test_list_push_pop_multiple(struct bpf_spin_lock *lock, struct bpf_list_head *head)
263 ret = list_push_pop_multiple(lock, head, false);
266 return list_push_pop_multiple(lock, head, true);
269 static __always_inline
270 int test_list_in_list(struct bpf_spin_lock *lock, struct bpf_list_head *head)
274 ret = list_in_list(lock, head, false);
277 return list_in_list(lock, head, true);
281 int map_list_push_pop(void *ctx)
285 v = bpf_map_lookup_elem(&array_map, &(int){0});
288 return test_list_push_pop(&v->lock, &v->head);
292 int inner_map_list_push_pop(void *ctx)
297 map = bpf_map_lookup_elem(&map_of_maps, &(int){0});
300 v = bpf_map_lookup_elem(map, &(int){0});
303 return test_list_push_pop(&v->lock, &v->head);
307 int global_list_push_pop(void *ctx)
309 return test_list_push_pop(&glock, &ghead);
313 int map_list_push_pop_multiple(void *ctx)
317 v = bpf_map_lookup_elem(&array_map, &(int){0});
320 return test_list_push_pop_multiple(&v->lock, &v->head);
324 int inner_map_list_push_pop_multiple(void *ctx)
329 map = bpf_map_lookup_elem(&map_of_maps, &(int){0});
332 v = bpf_map_lookup_elem(map, &(int){0});
335 return test_list_push_pop_multiple(&v->lock, &v->head);
339 int global_list_push_pop_multiple(void *ctx)
343 ret = list_push_pop_multiple(&glock, &ghead, false);
346 return list_push_pop_multiple(&glock, &ghead, true);
350 int map_list_in_list(void *ctx)
354 v = bpf_map_lookup_elem(&array_map, &(int){0});
357 return test_list_in_list(&v->lock, &v->head);
361 int inner_map_list_in_list(void *ctx)
366 map = bpf_map_lookup_elem(&map_of_maps, &(int){0});
369 v = bpf_map_lookup_elem(map, &(int){0});
372 return test_list_in_list(&v->lock, &v->head);
376 int global_list_in_list(void *ctx)
378 return test_list_in_list(&glock, &ghead);
381 char _license[] SEC("license") = "GPL";