blob: bf78edc857c29e5e8530a51ad79c4a206f231c26 (
plain) (
blame)
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
#include "arena.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
/*
* Alignment for largest scalar type. Before max_align_t was added in C11, code
* like this usually declared a union of several long-ish types, resulting in a
* suitable sizeof result. Hopefully anyway. This is cleaner.
*/
#define ALIGN (sizeof(max_align_t))
/*
* We need this property below to round up to multiples of `ALIGN`. (Of course
* it's almost certainly true anyway.)
*/
static_assert(ALIGN && !(ALIGN & (ALIGN - 1)), "ALIGN not a power of two");
static unsigned char *arena; /* memory allocated for the arena */
static size_t capacity; /* capacity of the arena in bytes */
static size_t used; /* bytes used so far (from beginning) */
/*
* Round up `minimum` to nearest multiple of ALIGN.
*/
static inline size_t
round_up(size_t minimum)
{
return (minimum + ALIGN - 1) & ~(ALIGN - 1);
}
int
ar_setup(size_t arena_size)
{
assert(!arena);
size_t adjusted = round_up(arena_size);
void *p = calloc(1, adjusted);
if (p == NULL) {
return -1;
}
arena = p;
capacity = adjusted;
return 0;
}
void *
ar_alloc(size_t object_size)
{
assert(arena);
size_t adjusted = round_up(object_size); /* keep `used` aligned */
if (used + adjusted > capacity) {
return NULL; /* out of space */
}
void *p = arena + used;
used += adjusted;
return p;
}
void
ar_free(void)
{
assert(arena);
memset(arena, 0, capacity);
used = 0;
}
void
ar_cleanup(void)
{
assert(arena);
free(arena);
arena = NULL;
capacity = 0;
used = 0;
}
|