// SPDX-License-Identifier: LGPL-2.1 OR BSD-2-Clause /* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */ #include #include #include #include struct buddy __arena buddy; volatile u32 zero = 0; /* * Storage for the queue nodes declared by bpf_arena_spin_lock.h. Each program * linking the arena spinlock provides exactly one definition, so that the array * is emitted once rather than once per translation unit. */ struct arena_qnode __arena __hidden qnodes[_Q_MAX_CPUS][_Q_MAX_NODES]; int arena_fls(__u64 word) { if (!word) return 0; return 64 - __builtin_clzll(word); } SEC("syscall") __weak int arena_get_info(struct arena_get_info_args *args) { args->arena_base = arena_base(&arena); return 0; } SEC("syscall") __weak int arena_alloc_reserve(struct arena_alloc_reserve_args *args) { return bpf_arena_reserve_pages(&arena, NULL, args->nr_pages); } SEC("syscall") __weak int arena_buddy_reset(void) { buddy_destroy(&buddy); return buddy_init(&buddy); } SEC("syscall") __weak int arena_buddy_destroy(void) { return buddy_destroy(&buddy); } __weak void __arena *arena_malloc(size_t size) { return buddy_alloc(&buddy, size); } __weak void __arena *arena_calloc(size_t ncount, size_t size) { void __arena *mem; size_t total; /* * Ideally we'd be using __builtin_mul_overflow here, * but the BPF compiler backend doesn't implement __multi3. * There are ways to optimize the division away from the * overflow check, but any costs are dwarfed by the * buddy_alloc() call. Keep it simple for now. */ if (unlikely(ncount && size >= ULLONG_MAX / ncount)) return NULL; total = ncount * size; mem = buddy_alloc(&buddy, total); if (likely(mem)) arena_memset(mem, 0, total); return mem; } __weak void arena_free(void __arena *ptr) { buddy_free(&buddy, ptr); } char _license[] SEC("license") = "GPL";