blob: 3782b79f6e66503b159fa8b862a05c54ad78e865 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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);
}
|