infix
A JIT-Powered FFI Library for C
Loading...
Searching...
No Matches
arena.c
Go to the documentation of this file.
1
39#include <stdint.h>
40#include <stdlib.h>
41#include <string.h>
42
56 // Use calloc to ensure the initial struct state is zeroed.
58 if (arena == nullptr) {
60 return nullptr;
61 }
62
63 arena->buffer = infix_calloc(1, initial_size);
64 if (arena->buffer == nullptr && initial_size > 0) {
67 return nullptr;
68 }
69
70 arena->capacity = initial_size;
72 arena->error = false;
73 arena->next_block = nullptr;
74 arena->block_size = initial_size;
75
76 return arena;
77}
78
91 if (arena == nullptr)
92 return;
93
94 // Traverse the chain of blocks and free each one.
95 infix_arena_t * current = arena;
96 while (current != nullptr) {
97 infix_arena_t * next = current->next_block;
98 if (current->buffer)
99 infix_free(current->buffer);
100 infix_free(current);
101 current = next;
102 }
103}
104
126c23_nodiscard void * infix_arena_alloc(infix_arena_t * arena, size_t size, size_t alignment) {
127 if (arena == nullptr)
128 return nullptr;
129
130 // Alignment must be a power of two for the bitwise alignment trick to work.
131 if (alignment == 0 || (alignment & (alignment - 1)) != 0) {
132 arena->error = true;
134 return nullptr;
135 }
136
137 infix_arena_t * current_block = arena;
138 while (true) { // Loop until allocation succeeds or fails definitively.
139 if (current_block->error)
140 return nullptr;
141
142 if (size == 0)
143 return (void *)(current_block->buffer + current_block->current_offset);
144
145 size_t aligned_offset = _infix_align_up(current_block->current_offset, alignment);
146
147 if (aligned_offset < current_block->current_offset) {
148 current_block->error = true;
150 return nullptr;
151 }
152
153 // Attempt to allocate in the current block.
154 if (SIZE_MAX - size >= aligned_offset && aligned_offset + size <= current_block->capacity) {
155 void * ptr = current_block->buffer + aligned_offset;
156 current_block->current_offset = aligned_offset + size;
157 return ptr; // Success: Allocation complete.
158 }
159
160 // If allocation failed, find or create the next block and let the loop retry.
161 if (current_block->next_block != nullptr) {
162 current_block = current_block->next_block;
163 }
164 else {
165 // Reached the end of the chain, so create a new block.
166 size_t next_size = current_block->block_size * 2;
167 if (next_size < size + alignment)
168 next_size = size + alignment;
169
170 current_block->next_block = infix_arena_create(next_size);
171 if (current_block->next_block == nullptr) {
172 current_block->error = true; // Mark the last valid block as errored.
173 return nullptr; // Growth failed.
174 }
175 current_block = current_block->next_block;
176 }
177 }
178
179 // This line should be unreachable if the logic is correct.
180 return nullptr;
181}
182
198c23_nodiscard void * infix_arena_calloc(infix_arena_t * arena, size_t num, size_t size, size_t alignment) {
199 // Security: Check for multiplication overflow.
200 if (size > 0 && num > SIZE_MAX / size) {
201 if (arena)
202 arena->error = true;
204 return nullptr;
205 }
206
207 size_t total_size = num * size;
208 void * ptr = infix_arena_alloc(arena, total_size, alignment);
209
210 if (ptr != nullptr)
211 memset(ptr, 0, total_size);
212
213 return ptr;
214}
infix_arena_t * arena
Definition 005_layouts.c:68
#define c23_nodiscard
A compatibility macro for the C23 [[nodiscard]] attribute.
Definition compat_c23.h:113
@ INFIX_CODE_INTEGER_OVERFLOW
Definition infix.h:1339
@ INFIX_CODE_UNKNOWN
Definition infix.h:1327
@ INFIX_CODE_OUT_OF_MEMORY
Definition infix.h:1330
@ INFIX_CATEGORY_ALLOCATION
Definition infix.h:1316
@ INFIX_CATEGORY_GENERAL
Definition infix.h:1315
#define infix_free
A macro that can be defined to override the default free function.
Definition infix.h:330
void infix_arena_destroy(infix_arena_t *arena)
Destroys an arena and frees all memory allocated from it.
Definition arena.c:90
#define infix_calloc
A macro that can be defined to override the default calloc function.
Definition infix.h:320
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:198
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:126
c23_nodiscard infix_arena_t * infix_arena_create(size_t initial_size)
Creates a new memory arena.
Definition arena.c:55
Internal data structures, function prototypes, and constants.
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:155
static size_t _infix_align_up(size_t value, size_t alignment)
Aligns a value up to the next multiple of a power-of-two alignment.
Definition infix_internals.h:703
Internal definition of a memory arena.
Definition infix_internals.h:146
char * buffer
Definition infix_internals.h:147
bool error
Definition infix_internals.h:150
size_t capacity
Definition infix_internals.h:148
size_t block_size
Definition infix_internals.h:152
size_t current_offset
Definition infix_internals.h:149
struct infix_arena_t * next_block
Definition infix_internals.h:151