From ff565e8d422c5e58558d1f7682ba0c9756e5be27 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Mon, 14 Jul 2025 09:30:08 -0700 Subject: Add function to allocate aligned blocks on the memstack --- memstack/src/memstack.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'memstack/src/memstack.c') diff --git a/memstack/src/memstack.c b/memstack/src/memstack.c index 10d1e30..0848afb 100644 --- a/memstack/src/memstack.c +++ b/memstack/src/memstack.c @@ -5,6 +5,16 @@ #include #include +static bool is_pow2_or_0(size_t x) { return (x & (x - 1)) == 0; } + +/// Align the given address to the next address that is a multiple of the +/// alignment. If the given address is already aligned, return the address. +static uint8_t* align(uint8_t* address, size_t alignment) { + assert(is_pow2_or_0(alignment)); + const size_t mask = alignment - 1; + return (uint8_t*)(((uintptr_t)address + mask) & ~mask); +} + bool memstack_make(memstack* stack, size_t capacity, void* memory) { assert(stack); assert(capacity >= 1); @@ -59,13 +69,24 @@ void* memstack_alloc(memstack* stack, size_t bytes) { } // Allocate the block. - uint8_t* block = stack->watermark; + uint8_t* const block = stack->watermark; stack->watermark += bytes; assert(memstack_size(stack) <= stack->capacity); return block; } +void* memstack_alloc_aligned(memstack* stack, size_t bytes, size_t alignment) { + assert(stack); + + uint8_t* const new_watermark = align(stack->watermark, alignment); + assert(new_watermark >= stack->watermark); + assert((size_t)(new_watermark - stack->base) <= stack->capacity); + stack->watermark = new_watermark; + + return memstack_alloc(stack, bytes); +} + size_t memstack_size(const memstack* stack) { assert(stack); return stack->watermark - stack->base; -- cgit v1.2.3