From fc418f61632d890704a2c4512f43d77ec8bb55ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Sun, 19 Apr 2026 04:23:52 +0200 Subject: [PATCH] sarena, add temp allocations --- include/ucore/sarena.h | 48 +++++++++++++++++++++++------------------- src/sarena.c | 25 +++++++++++++++++----- 2 files changed, 46 insertions(+), 27 deletions(-) diff --git a/include/ucore/sarena.h b/include/ucore/sarena.h index afffc96..29f7188 100644 --- a/include/ucore/sarena.h +++ b/include/ucore/sarena.h @@ -22,14 +22,20 @@ extern "C" { * Once allocated, a piece of memory obtained from the * allocator cannot be free'd individually, only the entire SArena can * be free'd/reset -*/ + */ typedef struct UCSArena UCSArena; struct UCSArena { - unsigned char *start; // start of user buffer - unsigned char *curr; // next alloc point - unsigned char *end; // one past end of user buffer + unsigned char *start; // start of user buffer + unsigned char *curr; // next alloc point + unsigned char *end; // one past end of user buffer + int tmp_allocs; // no of uc_sar_tmp_begin calls }; +typedef struct UCSTmpAlloc UCSTmpAlloc; +struct UCSTmpAlloc { + unsigned char *alloc_point; + UCSArena *arena; +}; /** Initialize a UCSArena with predefined backing array. * * @data must be an array type @@ -39,8 +45,7 @@ struct UCSArena { * UCSArena a = UC_BV_STATIC_INITIALIZER(v); * @endcode */ -#define UC_SAR_STATIC_INITIALIZER(data)\ - UC_SAR_INITIALIZER((data), sizeof(data)) +#define UC_SAR_STATIC_INITIALIZER(data) UC_SAR_INITIALIZER((data), sizeof(data)) /** Initializer for UCSArena with predefined memory * Use as @@ -54,12 +59,7 @@ struct UCSArena { * UCSArena a = UC_BV_INIT(m, 128); * @endcode */ -#define UC_SAR_INITIALIZER(data, sz)\ - {\ - (data),\ - (data),\ - (data) + sz\ - } +#define UC_SAR_INITIALIZER(data, sz) {(data), (data), (data) + sz} /** Initialize a UCSArena with an array as the backing memory to allocate from. * The macro can be used at local scope to allocate memory automatic on the stack, @@ -78,12 +78,12 @@ struct UCSArena { * is needed. * @param var_name Variable name for the allocator * @param size_ byte size of the backing array -*/ + */ #define UC_SAR_ALLOC_DEF(var_name, size_) \ - struct {\ - _Alignas(16) char memory[size_]; \ - } var_name ## _memory;\ - UCSArena var_name = UC_SAR_STATIC_INITIALIZER(var_name ## _memory.memory) + struct { \ + _Alignas(16) char memory[size_]; \ + } var_name##_memory; \ + UCSArena var_name = UC_SAR_STATIC_INITIALIZER(var_name##_memory.memory) /** Allocate space for @type_ , returned memory is aligned to requirements * of @type. @@ -96,16 +96,21 @@ struct UCSArena { * struct Foo *str = UC_SAR_ALLOC_ALIGNED(&my_allocator, struct Foo[32]); * @endcode */ -#define UC_SAR_ALLOC_ALIGNED(allocator, type_) \ - uc_sar_alloc_aligned((allocator), sizeof (type_), _Alignof(type_)) +#define UC_SAR_ALLOC_ALIGNED(allocator, type_) uc_sar_alloc_aligned((allocator), sizeof(type_), _Alignof(type_)) -//Initialize an UCSArena to allocate from @mem which is @sz bytes -static inline void uc_sar_init(UCSArena *a, void *mem, size_t sz) +// Initialize an UCSArena to allocate from @mem which is @sz bytes +static inline void uc_sar_init(UCSArena *a, void *mem, size_t sz) { a->start = a->curr = mem; a->end = a->start + sz; } +// begin temporary allocation. All allocations afterwards will be released in uc_sar_tmp_end +UCSTmpAlloc uc_sar_tmp_begin(UCSArena *a); + +// end temporary allocations, releaseing all allocations since the most recent uc_sar_tmp_begin +void uc_sar_tmp_end(const UCSTmpAlloc *state); + // Allocate @sz bytes from the UCSArena. Returns NULL if not enough space void *uc_sar_alloc(UCSArena *a, size_t sz); @@ -113,7 +118,6 @@ void *uc_sar_alloc(UCSArena *a, size_t sz); // Returns NULL if not enough space void *uc_sar_alloc_aligned(UCSArena *a, size_t sz, unsigned int align) [[gnu::alloc_align(2)]]; - static inline void uc_sar_reset(UCSArena *a) { a->curr = a->start; diff --git a/src/sarena.c b/src/sarena.c index d5da55a..77782a0 100644 --- a/src/sarena.c +++ b/src/sarena.c @@ -14,17 +14,32 @@ void *uc_sar_alloc(UCSArena *a, size_t sz) void *uc_sar_alloc_aligned(UCSArena *a, size_t sz, unsigned int align) { assert(align != 0); - assert((align & (align - 1)) == 0); //power of 2 + assert((align & (align - 1)) == 0); // power of 2 uintptr_t curr = (uintptr_t)a->curr; uintptr_t aligned = (curr + (align - (uintptr_t)1)) & ~(align - (uintptr_t)1); unsigned char *start = (unsigned char *)aligned; - if (start + sz > a->end) { + if (start + sz > a->end) { return NULL; - } + } - a->curr = start + sz; + a->curr = start + sz; - return start; + return start; +} + +UCSTmpAlloc uc_sar_tmp_begin(UCSArena *a) +{ + UCSTmpAlloc state = {.alloc_point = a->curr, .arena = a}; + a->tmp_allocs++; + return state; +} + +void uc_sar_tmp_end(const UCSTmpAlloc *state) +{ + UCSArena *a = state->arena; + assert(a->tmp_allocs > 0); + a->curr = state->alloc_point; + a->tmp_allocs--; }