summaryrefslogtreecommitdiff
path: root/arena.h
blob: e9637527f62015609022e8391dfa8817926b0f4d (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
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#ifndef ARENA_H
#define ARENA_H

#include "wrmr.h"

#include <stddef.h>
#include <stdint.h>
#include <string.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_reset(Arena *a);
void *arena_alloc(Arena *a, size_t n, size_t align);
void *arena_realloc(Arena *a, const void *old, size_t oldsz, size_t newsz, size_t align);
void *arena_concat(Arena *m, const void *a, size_t asz, const void *b, size_t bsz, size_t align);

#define new(a, t)\
    memset(arena_alloc(a, sizeof(t), _Alignof(__typeof__(t))), 0, sizeof(t))

#define new_arr(a, t, n)\
    memset(arena_alloc(a, sizeof(t) * (n), _Alignof(__typeof__(t))), 0, sizeof(t) * (n))

#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_reset(Arena *a) {
	a->beg = a->start;
}

#include <stdlib.h>

void *arena_alloc(Arena *a, size_t sz, size_t align) {
	char *p = a->beg + (-(uintptr_t)a->beg & (align - 1));
	if (p + sz > a->end) FAIL_WITH_MSG("arena out-of-memory");
	a->beg = p + sz;
	return p;
}

void *arena_realloc(Arena *a, const void *old, size_t oldsz, size_t newsz, size_t align) {
	if (old == a->beg - oldsz) {
		a->beg = (char*)old + newsz;
		return (void*)old;
	} else {
		void *p = arena_alloc(a, newsz, align);
		if (old) memcpy(p, old, oldsz);
		return p;
	}
}

void *arena_concat(Arena *m, const void *a, size_t asz, const void *b, size_t bsz, size_t align) {
	if (!asz)
		return (void*)b;
	if (!bsz || (char*)a + asz == b)
		return (void*)a;
	void *p = arena_realloc(m, a, asz, asz + bsz, align);
	memcpy((char*)p + asz, b, bsz);
	return p;
}

#endif
#endif