15#define STATIC_BUFFER_SIZE (1024 * 1024)
17static alignas(64) THREAD_LOCAL
char static_buffer[STATIC_BUFFER_SIZE];
18static THREAD_LOCAL
bool static_buffer_in_use =
false;
20static ARENA_INLINE
size_t get_page_size(
void) {
26 return (
size_t)sysconf(_SC_PAGESIZE);
30void arena_init(Arena* restrict a,
void* restrict buf,
size_t size) {
31 memset(a, 0,
sizeof(Arena));
32 a->page_size = get_page_size();
33 a->heap_allocated =
false;
35 a->first_block.base = (
char*)buf;
36 a->first_block.end = (
char*)buf + size;
37 a->first_block.is_static =
true;
38 a->first_block.next = NULL;
40 a->head = &a->first_block;
41 a->current_block = a->head;
42 a->curr = a->head->base;
43 a->end = a->head->end;
44 a->total_committed = size;
47Arena* arena_create(
size_t reserve_size) {
48 Arena* a = (Arena*)aligned_alloc_xp(64,
sizeof(Arena));
51 if (!static_buffer_in_use && reserve_size <= STATIC_BUFFER_SIZE) {
52 arena_init(a, static_buffer, STATIC_BUFFER_SIZE);
53 static_buffer_in_use =
true;
55 size_t initial_size = reserve_size > 0 ? reserve_size : ARENA_MIN_BLOCK_SIZE;
56 initial_size = (initial_size + get_page_size() - 1) & ~(get_page_size() - 1);
58 char* buf = (
char*)aligned_alloc_xp(64, initial_size);
63 arena_init(a, buf, initial_size);
64 a->first_block.is_static =
false;
67 a->heap_allocated =
true;
71void* _arena_alloc_slow(Arena* restrict a,
size_t size,
size_t alignment) {
75 uintptr_t aligned = ((uintptr_t)next->base + alignment - 1) & ~(alignment - 1);
76 if (aligned + size <= (uintptr_t)next->
end) {
77 a->current_block = next;
78 a->curr = (
char*)(aligned + size);
80 return (
void*)aligned;
86 size_t current_size = (size_t)(a->current_block->end - a->current_block->base);
87 size_t needed =
sizeof(
ArenaBlock) + alignment + size;
88 size_t next_size = current_size * 2;
90 if (next_size < needed) next_size = needed;
91 if (next_size < ARENA_MIN_BLOCK_SIZE) next_size = ARENA_MIN_BLOCK_SIZE;
92 next_size = (next_size + a->page_size - 1) & ~(a->page_size - 1);
95 char* ptr = (
char*)aligned_alloc_xp(64, next_size);
96 if (!ptr)
return NULL;
99 block->base = (
char*)(((uintptr_t)(ptr +
sizeof(
ArenaBlock)) + alignment - 1) & ~(alignment - 1));
100 block->
end = ptr + next_size;
102 block->next = a->current_block->next;
104 a->current_block->next = block;
105 a->current_block = block;
106 a->total_committed += next_size;
108 uintptr_t aligned = ((uintptr_t)block->base + alignment - 1) & ~(alignment - 1);
109 a->curr = (
char*)(aligned + size);
112 return (
void*)aligned;
115void arena_destroy(Arena* restrict a) {
121 if (block && !block->
is_static) aligned_free_xp(block->base);
126 block = block ? block->next : NULL;
130 aligned_free_xp(temp);
133 if (a->heap_allocated) aligned_free_xp(a);
Aligned memory allocation functions for cross-platform support.
Portable utility macros for assertions, memory, math, iteration, timing, and platform compatibility.