bpf_spin_lock(lock);
n = bpf_list_pop_front(head);
bpf_spin_unlock(lock); if (n) {
bpf_obj_drop(container_of(n, struct foo, node2));
bpf_obj_drop(f); return 3;
}
bpf_spin_lock(lock);
n = bpf_list_pop_back(head);
bpf_spin_unlock(lock); if (n) {
bpf_obj_drop(container_of(n, struct foo, node2));
bpf_obj_drop(f); return 4;
}
bpf_spin_lock(lock);
f->data = 42;
bpf_list_push_front(head, &f->node2);
bpf_spin_unlock(lock); if (leave_in_map) return 0;
bpf_spin_lock(lock);
n = bpf_list_pop_back(head);
bpf_spin_unlock(lock); if (!n) return 5;
f = container_of(n, struct foo, node2); if (f->data != 42) {
bpf_obj_drop(f); return 6;
}
bpf_spin_lock(lock);
f->data = 13;
bpf_list_push_front(head, &f->node2);
bpf_spin_unlock(lock);
bpf_spin_lock(lock);
n = bpf_list_pop_front(head);
bpf_spin_unlock(lock); if (!n) return 7;
f = container_of(n, struct foo, node2); if (f->data != 13) {
bpf_obj_drop(f); return 8;
}
bpf_obj_drop(f);
bpf_spin_lock(lock);
n = bpf_list_pop_front(head);
bpf_spin_unlock(lock); if (n) {
bpf_obj_drop(container_of(n, struct foo, node2)); return 9;
}
bpf_spin_lock(lock);
n = bpf_list_pop_back(head);
bpf_spin_unlock(lock); if (n) {
bpf_obj_drop(container_of(n, struct foo, node2)); return 10;
} return 0;
}
static __always_inline int list_push_pop_multiple(struct bpf_spin_lock *lock, struct bpf_list_head *head, boolleave_in_map)
{ struct bpf_list_node *n; struct foo *f[200], *pf; int i;
/* Loop following this check adds nodes 2-at-a-time in order to * validate multiple release_on_unlock release logic
*/ if (ARRAY_SIZE(f) % 2) return 10;
for (i = 0; i < ARRAY_SIZE(f); i += 2) {
f[i] = bpf_obj_new(typeof(**f)); if (!f[i]) return 2;
f[i]->data = i;
for (i = 0; i < ARRAY_SIZE(f); i++) {
bpf_spin_lock(lock);
n = bpf_list_pop_front(head);
bpf_spin_unlock(lock); if (!n) return 3;
pf = container_of(n, struct foo, node2); if (pf->data != (ARRAY_SIZE(f) - i - 1)) {
bpf_obj_drop(pf); return 4;
}
bpf_spin_lock(lock);
bpf_list_push_back(head, &pf->node2);
bpf_spin_unlock(lock);
}
if (leave_in_map) return 0;
for (i = 0; i < ARRAY_SIZE(f); i++) {
bpf_spin_lock(lock);
n = bpf_list_pop_back(head);
bpf_spin_unlock(lock); if (!n) return 5;
pf = container_of(n, struct foo, node2); if (pf->data != i) {
bpf_obj_drop(pf); return 6;
}
bpf_obj_drop(pf);
}
bpf_spin_lock(lock);
n = bpf_list_pop_back(head);
bpf_spin_unlock(lock); if (n) {
bpf_obj_drop(container_of(n, struct foo, node2)); return 7;
}
bpf_spin_lock(lock);
n = bpf_list_pop_front(head);
bpf_spin_unlock(lock); if (n) {
bpf_obj_drop(container_of(n, struct foo, node2)); return 8;
} return 0;
}
static __always_inline int list_in_list(struct bpf_spin_lock *lock, struct bpf_list_head *head, bool leave_in_map)
{ struct bpf_list_node *n; struct bar *ba[8], *b; struct foo *f; int i;
f = bpf_obj_new(typeof(*f)); if (!f) return 2; for (i = 0; i < ARRAY_SIZE(ba); i++) {
b = bpf_obj_new(typeof(*b)); if (!b) {
bpf_obj_drop(f); return 3;
}
b->data = i;
bpf_spin_lock(&f->lock);
bpf_list_push_back(&f->head, &b->node);
bpf_spin_unlock(&f->lock);
}
bpf_spin_lock(lock);
n = bpf_list_pop_front(head);
bpf_spin_unlock(lock); if (!n) return 4;
f = container_of(n, struct foo, node2); if (f->data != 42) {
bpf_obj_drop(f); return 5;
}
for (i = 0; i < ARRAY_SIZE(ba); i++) {
bpf_spin_lock(&f->lock);
n = bpf_list_pop_front(&f->head);
bpf_spin_unlock(&f->lock); if (!n) {
bpf_obj_drop(f); return 6;
}
b = container_of(n, struct bar, node); if (b->data != i) {
bpf_obj_drop(f);
bpf_obj_drop(b); return 7;
}
bpf_obj_drop(b);
}
bpf_spin_lock(&f->lock);
n = bpf_list_pop_front(&f->head);
bpf_spin_unlock(&f->lock); if (n) {
bpf_obj_drop(f);
bpf_obj_drop(container_of(n, struct bar, node)); return 8;
}
bpf_obj_drop(f); return 0;
}
static __always_inline int test_list_push_pop(struct bpf_spin_lock *lock, struct bpf_list_head *head)
{ int ret;
ret = list_push_pop(lock, head, false); if (ret) return ret; return list_push_pop(lock, head, true);
}
static __always_inline int test_list_push_pop_multiple(struct bpf_spin_lock *lock, struct bpf_list_head *head)
{ int ret;
ret = list_push_pop_multiple(lock, head, false); if (ret) return ret; return list_push_pop_multiple(lock, head, true);
}
static __always_inline int test_list_in_list(struct bpf_spin_lock *lock, struct bpf_list_head *head)
{ int ret;
ret = list_in_list(lock, head, false); if (ret) return ret; return list_in_list(lock, head, true);
}
SEC("tc") int map_list_push_pop(void *ctx)
{ struct map_value *v;
v = bpf_map_lookup_elem(&array_map, &(int){0}); if (!v) return 1; return test_list_push_pop(&v->lock, &v->head);
}
SEC("tc") int inner_map_list_push_pop(void *ctx)
{ struct map_value *v; void *map;
map = bpf_map_lookup_elem(&map_of_maps, &(int){0}); if (!map) return 1;
v = bpf_map_lookup_elem(map, &(int){0}); if (!v) return 1; return test_list_push_pop(&v->lock, &v->head);
}
SEC("tc") int global_list_push_pop(void *ctx)
{ return test_list_push_pop(&glock, &ghead);
}
SEC("tc") int global_list_push_pop_nested(void *ctx)
{ return test_list_push_pop(&ghead_nested.inner.lock, &ghead_nested.inner.head);
}
SEC("tc") int global_list_array_push_pop(void *ctx)
{ int r;
r = test_list_push_pop(&glock_c, &ghead_array[0]); if (r) return r;
r = test_list_push_pop(&glock_c, &ghead_array[1]); if (r) return r;
/* Arrays with only one element is a special case, being treated * just like a bpf_list_head variable by the verifier, not an * array.
*/ return test_list_push_pop(&glock_c, &ghead_array_one[0]);
}
SEC("tc") int map_list_push_pop_multiple(void *ctx)
{ struct map_value *v;
v = bpf_map_lookup_elem(&array_map, &(int){0}); if (!v) return 1; return test_list_push_pop_multiple(&v->lock, &v->head);
}
SEC("tc") int inner_map_list_push_pop_multiple(void *ctx)
{ struct map_value *v; void *map;
map = bpf_map_lookup_elem(&map_of_maps, &(int){0}); if (!map) return 1;
v = bpf_map_lookup_elem(map, &(int){0}); if (!v) return 1; return test_list_push_pop_multiple(&v->lock, &v->head);
}
SEC("tc") int global_list_push_pop_multiple(void *ctx)
{ int ret;
ret = list_push_pop_multiple(&glock, &ghead, false); if (ret) return ret; return list_push_pop_multiple(&glock, &ghead, true);
}
SEC("tc") int map_list_in_list(void *ctx)
{ struct map_value *v;
v = bpf_map_lookup_elem(&array_map, &(int){0}); if (!v) return 1; return test_list_in_list(&v->lock, &v->head);
}
SEC("tc") int inner_map_list_in_list(void *ctx)
{ struct map_value *v; void *map;
map = bpf_map_lookup_elem(&map_of_maps, &(int){0}); if (!map) return 1;
v = bpf_map_lookup_elem(map, &(int){0}); if (!v) return 1; return test_list_in_list(&v->lock, &v->head);
}
SEC("tc") int global_list_in_list(void *ctx)
{ return test_list_in_list(&glock, &ghead);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.