tools/testing/selftests/bpf/libarena/src/buddy.bpf.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/bpf/libarena/src/buddy.bpf.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/bpf/libarena/src/buddy.bpf.c
Extension
.c
Size
24144 bytes
Lines
904
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

if (unlikely(!header)) {
			arena_stderr("idx %u has no header", idx);
			return -EINVAL;
		}

		asan_unpoison(header, sizeof(*header));

		header_add_freelist(chunk, header, idx, ord);
	}

	return 0;
}

static struct buddy_chunk __arena *buddy_chunk_get(struct buddy __arena *buddy)
{
	u64 order, ord, min_order, max_order;
	struct buddy_chunk __arena  *chunk;
	size_t left;
	int power2;
	u64 vaddr;
	u32 idx;
	int ret;

	/*
	 * Step 1:  Allocate a properly aligned chunk, and
	 * prep it for insertion into the buddy allocator.
	 * We don't need the allocator lock until step 2.
	 */

	ret = buddy_alloc_arena_vaddr(buddy, &vaddr);
	if (ret)
		return NULL;

	/* Addresses must be aligned to the chunk boundary. */
	if (vaddr % BUDDY_CHUNK_BYTES)
		return NULL;

	/* Unreserve the address space. */
	bpf_arena_free_pages(&arena, (void __arena *)vaddr,
			     BUDDY_CHUNK_PAGES);

	chunk = bpf_arena_alloc_pages(&arena, (void __arena *)vaddr,
				      BUDDY_CHUNK_PAGES, NUMA_NO_NODE, 0);
	if (!chunk) {
		arena_stderr("[ALLOC FAILED]");
		return NULL;
	}

	if (buddy_lock(buddy)) {
		/*
		 * We cannot reclaim the vaddr space, but that is ok - this
		 * operation should always succeed. The error path is to catch
		 * accidental deadlocks that will cause -ENOMEMs to the program as
		 * the allocator fails to refill itself, in which case vaddr usage
		 * is the least of our worries.
		 */
		bpf_arena_free_pages(&arena, (void __arena *)vaddr, BUDDY_CHUNK_PAGES);
		return NULL;
	}

	asan_poison(chunk, BUDDY_POISONED, BUDDY_CHUNK_PAGES * __PAGE_SIZE);

	/* Unpoison the chunk itself. */
	asan_unpoison(chunk, sizeof(*chunk));

	/* Mark all freelists as empty. */
	for (ord = zero; ord < BUDDY_CHUNK_NUM_ORDERS && can_loop; ord++)
		chunk->freelists[ord] = BUDDY_CHUNK_ITEMS;

	/*
	 * Initialize the chunk by carving out a page range to hold the metadata
	 * struct above, then dumping the rest of the pages into the allocator.
	 */

	_Static_assert(BUDDY_CHUNK_PAGES * __PAGE_SIZE >=
			       BUDDY_MIN_ALLOC_BYTES *
				       BUDDY_CHUNK_ITEMS,
		       "chunk must fit within the allocation");

	/*
	 * Step 2: Reserve a chunk for the chunk metadata, then breaks
	 * the rest of the full allocation into the different buckets.
	 * We allocating the memory by grabbing blocks of progressively
	 * smaller sizes from the allocator, which are guaranteed to be
	 * continuous.
	 *
	 * This operation also populates the allocator.
	 *
	 * Algorithm:
	 *

Annotation

Implementation Notes