diff options
author | Linnnus <[email protected]> | 2024-02-01 22:59:38 +0100 |
---|---|---|
committer | Linnnus <[email protected]> | 2024-02-04 09:58:06 +0100 |
commit | d38f82f6462af4e5aad6a2c776f5c00ce5b13c87 (patch) | |
tree | 01a222792dfb10473ae4370b4fc90f3a48e1a499 /src/arena.c |
feat: initial commit
Here is a small overview of the state of the project at this first
commit.
I have basic Git Repo -> HTML working, and a plan for how setting up an
actual server would work (mainly, NGINX + a git hook to rebuild).
The main thing I'm working on right now is parsing WikiCreole, though I
am starting to wonder if this is the right langauge. WikiCreole is
pretty irregular and has a lot of edge cases (e.g. around emphasis).
Diffstat (limited to 'src/arena.c')
-rw-r--r-- | src/arena.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/src/arena.c b/src/arena.c new file mode 100644 index 0000000..3782b79 --- /dev/null +++ b/src/arena.c @@ -0,0 +1,56 @@ +#include "arena.h" + +#include <assert.h> // assert +#include <stdint.h> // uintptr_t +#include <stdio.h> // fprintf +#include <stdlib.h> // abort, malloc +#include <stdnoreturn.h> // noreturn +#include <string.h> // memset + +static noreturn void arena_panic(const char *reason) { + fprintf(stderr, "Memory allocation failed: %s", reason); + abort(); +} + +struct arena arena_create(size_t capacity) { + struct arena arena = { + .root = malloc(capacity), + .capacity = capacity, + .used = 0, + }; + if (arena.root == NULL) { + arena_panic("cannot allocate system memory"); + } + return arena; +} + +void *arena_alloc(struct arena *arena, size_t size, size_t alignment, unsigned flags) { + // Alignment must be a power of two. + // See: https://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2 + assert(alignment != 0 && (alignment & (alignment - 1)) == 0); + size_t padding = -(uintptr_t)(arena->root + arena->used) & (alignment - 1); + + // If no more memory is available, we fall back to our error strategy. + assert(arena->capacity >= arena->used); + if (arena->used + padding + size > arena->capacity) { + if (flags & ARENA_NO_PANIC) { + return NULL; + } else { + arena_panic("out of preallocated memory"); + } + } + + // Reserve memory from arena. + void *ptr = arena->root + arena->used + padding; + arena->used += padding + size; + + if (~flags & ARENA_NO_ZERO) { + memset(ptr, 0, size); + } + + return ptr; +} + +void arena_destroy(struct arena *arena) { + free(arena->root); +} |