aboutsummaryrefslogtreecommitdiff
path: root/memstack/src
diff options
context:
space:
mode:
Diffstat (limited to 'memstack/src')
-rw-r--r--memstack/src/memstack.c39
1 files changed, 38 insertions, 1 deletions
diff --git a/memstack/src/memstack.c b/memstack/src/memstack.c
index 10d1e30..84131ef 100644
--- a/memstack/src/memstack.c
+++ b/memstack/src/memstack.c
@@ -5,6 +5,16 @@
5#include <stdlib.h> 5#include <stdlib.h>
6#include <string.h> 6#include <string.h>
7 7
8static bool is_pow2_or_0(size_t x) { return (x & (x - 1)) == 0; }
9
10/// Align the given address to the next address that is a multiple of the
11/// alignment. If the given address is already aligned, return the address.
12static uint8_t* align(uint8_t* address, size_t alignment) {
13 assert(is_pow2_or_0(alignment));
14 const size_t mask = alignment - 1;
15 return (uint8_t*)(((uintptr_t)address + mask) & ~mask);
16}
17
8bool memstack_make(memstack* stack, size_t capacity, void* memory) { 18bool memstack_make(memstack* stack, size_t capacity, void* memory) {
9 assert(stack); 19 assert(stack);
10 assert(capacity >= 1); 20 assert(capacity >= 1);
@@ -48,6 +58,21 @@ void memstack_clear(memstack* stack) {
48 memset(stack->base, 0, stack->capacity); 58 memset(stack->base, 0, stack->capacity);
49} 59}
50 60
61size_t memstack_watermark(const memstack* stack) {
62 assert(stack);
63 return stack->watermark - stack->base;
64}
65
66void memstack_set_watermark(memstack* stack, size_t watermark) {
67 assert(stack);
68 const bool fits = (watermark < stack->capacity);
69 if (stack->trap && !fits) {
70 FAIL("memstack watermark update failed, bad watermark");
71 }
72 assert(fits);
73 stack->watermark = stack->base + watermark;
74}
75
51void* memstack_alloc(memstack* stack, size_t bytes) { 76void* memstack_alloc(memstack* stack, size_t bytes) {
52 assert(stack); 77 assert(stack);
53 78
@@ -59,13 +84,25 @@ void* memstack_alloc(memstack* stack, size_t bytes) {
59 } 84 }
60 85
61 // Allocate the block. 86 // Allocate the block.
62 uint8_t* block = stack->watermark; 87 uint8_t* const block = stack->watermark;
63 stack->watermark += bytes; 88 stack->watermark += bytes;
64 assert(memstack_size(stack) <= stack->capacity); 89 assert(memstack_size(stack) <= stack->capacity);
65 90
66 return block; 91 return block;
67} 92}
68 93
94void* memstack_alloc_aligned(memstack* stack, size_t bytes, size_t alignment) {
95 assert(stack);
96
97 uint8_t* const new_watermark = align(stack->watermark, alignment);
98 assert(new_watermark >= stack->watermark);
99 assert((size_t)(new_watermark - stack->base) <= stack->capacity);
100 stack->capacity -= (new_watermark - stack->watermark);
101 stack->watermark = new_watermark;
102
103 return memstack_alloc(stack, bytes);
104}
105
69size_t memstack_size(const memstack* stack) { 106size_t memstack_size(const memstack* stack) {
70 assert(stack); 107 assert(stack);
71 return stack->watermark - stack->base; 108 return stack->watermark - stack->base;