summaryrefslogtreecommitdiff
path: root/arena.h
diff options
context:
space:
mode:
Diffstat (limited to 'arena.h')
-rw-r--r--arena.h81
1 files changed, 81 insertions, 0 deletions
diff --git a/arena.h b/arena.h
new file mode 100644
index 0000000..58c9d38
--- /dev/null
+++ b/arena.h
@@ -0,0 +1,81 @@
+#ifndef ARENA_H
+#define ARENA_H
+
+#include "wrmr.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+typedef struct {
+ char *start; /* need to release memory */
+ char *beg, *end;
+} Arena;
+
+#define ARENA(name, sz)\
+ static char name##_buf[sz];\
+ Arena name = { name##_buf, name##_buf + (sz) };
+
+void *vmem_alloc(size_t sz);
+void vmem_free(void *ptr, size_t sz);
+
+Arena arena_init(size_t sz);
+void arena_free(Arena *a);
+void *arena_alloc(Arena *a, size_t n, size_t align);
+void *arena_realloc(Arena *a, void *old, size_t oldsz, size_t newsz, size_t align);
+
+#define new(a, t)\
+ arena_alloc(a, sizeof(t), _Alignof(__typeof__(t)))
+
+#define new_arr(a, t, n)\
+ arena_alloc(a, sizeof(t) * (n), _Alignof(__typeof__(t)))
+
+#define resize(a, x, osz, nsz)\
+ arena_realloc(a, x, sizeof(*(x)) * (osz),\
+ sizeof(*(x)) * (nsz), _Alignof(__typeof__(*(x))))
+
+#ifdef ARENA_IMPL
+
+/* virtual memory */
+
+#include <stdio.h>
+#include <sys/mman.h>
+
+void *vmem_alloc(size_t sz) {
+ void *ptr = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (!ptr) FAIL_WITH_MSG("mmap failed");
+ return ptr;
+}
+
+void vmem_free(void *ptr, size_t sz) {
+ munmap(ptr, sz);
+}
+
+/* arenas */
+
+#include <string.h>
+
+Arena arena_init(size_t sz) {
+ char *p = vmem_alloc(sz);
+ return (Arena) { p, p, p + sz };
+}
+
+void arena_free(Arena *a) {
+ vmem_free(a->start, a->end - a->start);
+}
+
+void *arena_alloc(Arena *a, size_t sz, size_t align) {
+ char *p = a->beg + (-(uintptr_t)a->beg & (align - 1));
+ if (p >= a->end) FAIL_WITH_MSG("arena out-of-memory");
+ a->beg = p + sz;
+ memset(p, 0, sz);
+ return p;
+}
+
+void *arena_realloc(Arena *a, void *old, size_t oldsz, size_t newsz, size_t align) {
+ if (old == a->beg - oldsz) a->beg = old;
+ else if (old) memcpy(a->beg, old, oldsz);
+ return arena_alloc(a, newsz, align);
+}
+
+#endif
+#endif