diff options
Diffstat (limited to 'arena.c')
-rw-r--r-- | arena.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/arena.c b/arena.c new file mode 100644 index 0000000..3e1a57c --- /dev/null +++ b/arena.c @@ -0,0 +1,56 @@ +#include "arena.h" +#include <stdlib.h> +#define PAGE_SIZE 4096 +enum { + ARENA_SUCCESS = 0, + ARENA_EXPAND, + ARENA_FAILURE, +} +int arena_errno; +arena_t* arena_create_sized(size_t size){ + arena_t* arena = (arena_t*) calloc(1, sizeof(arena_t*)); + if (!arena) { + arena_errno = ARENA_FAILURE; + return 0; + } + arena->memory = (uint8_t*) calloc(1, size); + arena->size = size; + if (!arena->memory) { + free(arena); + arena_errno = ARENA_FAILURE; + return 0; + } + arena_errno = ARENA_SUCCESS; + return arena; +} +arena_t* arena_create() { + return arena_create_sized(PAGE_SIZE); +} +void* arena_malloc(arena_t* arena, size_t size) { + arena_t* head = arena; + arena_t* tail; + do { + if ((arena->size - arena->fill) > size) { + arena->fill += size; + // NOTE: do not overwrite ARENA_EXPAND code + if (arena_errno != ARENA_EXPAND) arena_errno = ARENA_SUCCESS; + return arena->memory + (arena->fill - size); + } + } while ((arena = arena->next) != 0); + tail = arena_create(); + if (tail == 0) { + // NOTE: `arena_errno` is already set from `arena_create` + return 0; + } + arena_errno = ARENA_EXPAND; + return arena_malloc(tail, size); +} +void arena_destroy(arena_t* arena) { + arena_t* tail = arena; + do { + free(tail->memory); + free(tail); + tail = tail->next; + } while (tail != 0); + arena_errno = ARENA_SUCCESS; +} |