infix
A JIT-Powered FFI Library for C
Loading...
Searching...
No Matches
arena.c
Go to the documentation of this file.
1
37#include <stdint.h>
38#include <stdlib.h>
39#include <string.h>
53 // Use calloc to ensure the initial struct state is zeroed.
55 if (arena == nullptr) {
57 return nullptr;
58 }
59 arena->buffer = infix_calloc(1, initial_size);
60 if (arena->buffer == nullptr && initial_size > 0) {
63 return nullptr;
64 }
65 arena->capacity = initial_size;
67 arena->error = false;
68 arena->next_block = nullptr;
69 arena->block_size = initial_size;
70 return arena;
71}
84 if (arena == nullptr)
85 return;
86 // Traverse the chain of blocks and free each one.
87 infix_arena_t * current = arena;
88 while (current != nullptr) {
89 infix_arena_t * next = current->next_block;
90 if (current->buffer)
91 infix_free(current->buffer);
92 infix_free(current);
93 current = next;
94 }
95}
117INFIX_API c23_nodiscard void * infix_arena_alloc(infix_arena_t * arena, size_t size, size_t alignment) {
118 if (arena == nullptr)
119 return nullptr;
120
121 // Ensure alignment is power of 2
122 if (alignment == 0 || (alignment & (alignment - 1)) != 0) {
123 arena->error = true;
125 return nullptr;
126 }
127
128 infix_arena_t * block = arena;
129 while (true) {
130 if (block->error)
131 return nullptr;
132
133 // Calculate current absolute address
134 uintptr_t current_ptr = (uintptr_t)(block->buffer + block->current_offset);
135
136 // Calculate aligned address
137 // (x + align - 1) & ~(align - 1)
138 uintptr_t aligned_ptr = (current_ptr + (alignment - 1)) & ~(alignment - 1);
139
140 // Calculate padding needed
141 size_t padding = (size_t)(aligned_ptr - current_ptr);
142
143 // Calculate total space required in this block
144 size_t total_needed = size + padding;
145
146 // Check if fits in current block
147 if (block->current_offset + total_needed <= block->capacity) {
148 void * ret = (void *)aligned_ptr;
149 block->current_offset += total_needed;
150 return ret;
151 }
152
153 // Allocation failed in current block. Check next or create new.
154 if (block->next_block) {
155 block = block->next_block;
156 continue;
157 }
158
159 // Create new block. Ensure it's large enough for alignment + size.
160 size_t next_cap = block->block_size * 2;
161 if (next_cap < size + alignment)
162 next_cap = size + alignment;
163
164 block->next_block = infix_arena_create(next_cap);
165 if (!block->next_block) {
166 block->error = true;
167 return nullptr;
168 }
169
170 block = block->next_block;
171 }
172}
188INFIX_API c23_nodiscard void * infix_arena_calloc(infix_arena_t * arena, size_t num, size_t size, size_t alignment) {
189 // Security: Check for multiplication overflow.
190 if (size > 0 && num > SIZE_MAX / size) {
191 if (arena)
192 arena->error = true;
194 return nullptr;
195 }
196 size_t total_size = num * size;
197 void * ptr = infix_arena_alloc(arena, total_size, alignment);
198 if (ptr != nullptr)
199 memset(ptr, 0, total_size);
200 return ptr;
201}
202
207 infix_arena_mark_t mark = {nullptr, 0};
208 if (arena == nullptr)
209 return mark;
210
211 infix_arena_t * current = arena;
212 while (current->next_block != nullptr && current->next_block->current_offset > 0)
213 current = current->next_block;
214 mark.block = current;
215 mark.offset = current->current_offset;
216 return mark;
217}
218
224 if (arena == nullptr || mark.block == nullptr)
225 return;
226
227 // Reset offset in the marked block
228 mark.block->current_offset = mark.offset;
229 mark.block->error = false;
230
231 // Reset offsets in all subsequent blocks so they can be reused
232 infix_arena_t * current = mark.block->next_block;
233 while (current != nullptr) {
234 current->current_offset = 0;
235 current->error = false;
236 current = current->next_block;
237 }
238}
infix_arena_t * arena
Definition 005_layouts.c:62
#define c23_nodiscard
Internal alias for the public INFIX_NODISCARD macro.
Definition compat_c23.h:92
INFIX_API void infix_arena_rewind(infix_arena_t *arena, infix_arena_mark_t mark)
Rewinds an arena chain back to a previously captured mark, resetting all secondary blocks for immedia...
Definition arena.c:223
INFIX_API c23_nodiscard infix_arena_mark_t infix_arena_get_mark(infix_arena_t *arena)
Captures the current allocation state of an arena chain.
Definition arena.c:206
@ INFIX_CODE_INVALID_ALIGNMENT
Definition infix.h:1424
@ INFIX_CODE_INTEGER_OVERFLOW
Definition infix.h:1431
@ INFIX_CODE_OUT_OF_MEMORY
Definition infix.h:1421
@ INFIX_CATEGORY_ALLOCATION
Definition infix.h:1405
@ INFIX_CATEGORY_GENERAL
Definition infix.h:1404
size_t offset
Definition infix.h:1563
infix_arena_t * block
Definition infix.h:1562
INFIX_API c23_nodiscard void * infix_arena_alloc(infix_arena_t *arena, size_t size, size_t alignment)
Allocates a block of memory from an arena.
Definition arena.c:117
#define infix_calloc(nelem, size)
A macro that can be defined to override infix's allocator at compile time.
Definition infix.h:427
#define infix_free(ptr)
A macro that can be defined to override infix's allocator at compile time.
Definition infix.h:435
INFIX_API c23_nodiscard infix_arena_t * infix_arena_create(size_t initial_size)
Creates a new memory arena.
Definition arena.c:52
INFIX_API c23_nodiscard void * infix_arena_calloc(infix_arena_t *arena, size_t num, size_t size, size_t alignment)
Allocates and zero-initializes a block of memory from an arena.
Definition arena.c:188
INFIX_API void infix_arena_destroy(infix_arena_t *arena)
Destroys an arena and frees all memory allocated from it.
Definition arena.c:83
#define INFIX_API
Symbol visibility macro.
Definition infix.h:114
Internal data structures, function prototypes, and constants.
INFIX_INTERNAL void _infix_set_error(infix_error_category_t category, infix_error_code_t code, size_t position)
Sets the thread-local error state with detailed information.
Definition error.c:175
Definition infix.h:1561
Internal definition of a memory arena.
Definition infix_internals.h:143
char * buffer
Definition infix_internals.h:144
bool error
Definition infix_internals.h:147
size_t capacity
Definition infix_internals.h:145
size_t block_size
Definition infix_internals.h:149
size_t current_offset
Definition infix_internals.h:146
struct infix_arena_t * next_block
Definition infix_internals.h:148