11#include "prism/util/pm_arena.h"
22
3+ #include <assert.h>
4+
35/**
46 * Compute the block allocation size using offsetof so it is correct regardless
57 * of PM_FLEX_ARY_LEN.
@@ -29,6 +31,42 @@ pm_arena_next_block_size(const pm_arena_t *arena, size_t min_size) {
2931 return size > min_size ? size : min_size ;
3032}
3133
34+ /**
35+ * Allocate a new block with the given data capacity and initial usage, link it
36+ * into the arena, and return it. Aborts on allocation failure.
37+ */
38+ static pm_arena_block_t *
39+ pm_arena_new_block (pm_arena_t * arena , size_t data_size , size_t initial_used ) {
40+ assert (initial_used <= data_size );
41+ pm_arena_block_t * block = (pm_arena_block_t * ) xmalloc (PM_ARENA_BLOCK_SIZE (data_size ));
42+
43+ if (block == NULL ) {
44+ fprintf (stderr , "prism: out of memory; aborting\n" );
45+ abort ();
46+ }
47+
48+ block -> capacity = data_size ;
49+ block -> used = initial_used ;
50+ block -> prev = arena -> current ;
51+ arena -> current = block ;
52+ arena -> block_count ++ ;
53+
54+ return block ;
55+ }
56+
57+ /**
58+ * Ensure the arena has at least `capacity` bytes available in its current
59+ * block, allocating a new block if necessary. This allows callers to
60+ * pre-size the arena to avoid repeated small block allocations.
61+ */
62+ void
63+ pm_arena_reserve (pm_arena_t * arena , size_t capacity ) {
64+ if (capacity <= PM_ARENA_INITIAL_SIZE ) return ;
65+ if (arena -> current != NULL && (arena -> current -> capacity - arena -> current -> used ) >= capacity ) return ;
66+
67+ pm_arena_new_block (arena , capacity , 0 );
68+ }
69+
3270/**
3371 * Allocate memory from the arena. The returned memory is NOT zeroed. This
3472 * function is infallible — it aborts on allocation failure.
@@ -51,18 +89,7 @@ pm_arena_alloc(pm_arena_t *arena, size_t size, size_t alignment) {
5189 // New blocks from xmalloc are max-aligned, so data[] starts aligned for
5290 // any C type. No padding needed at the start.
5391 size_t block_data_size = pm_arena_next_block_size (arena , size );
54- pm_arena_block_t * block = (pm_arena_block_t * ) xmalloc (PM_ARENA_BLOCK_SIZE (block_data_size ));
55-
56- if (block == NULL ) {
57- fprintf (stderr , "prism: out of memory; aborting\n" );
58- abort ();
59- }
60-
61- block -> capacity = block_data_size ;
62- block -> used = size ;
63- block -> prev = arena -> current ;
64- arena -> current = block ;
65- arena -> block_count ++ ;
92+ pm_arena_block_t * block = pm_arena_new_block (arena , block_data_size , size );
6693
6794 return block -> data ;
6895}
0 commit comments