summaryrefslogtreecommitdiff
path: root/source/base/base_arena.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/base/base_arena.c')
-rwxr-xr-xsource/base/base_arena.c142
1 files changed, 142 insertions, 0 deletions
diff --git a/source/base/base_arena.c b/source/base/base_arena.c
new file mode 100755
index 0000000..76938bd
--- /dev/null
+++ b/source/base/base_arena.c
@@ -0,0 +1,142 @@
1internal mem_arena *
2arena_create(u64 capacity)
3{
4 mem_arena *arena = (mem_arena *)mmap(
5 /* kernel decides where to throw the arena */
6 NULL,
7 capacity + sizeof(mem_arena),
8 PROT_READ | PROT_WRITE,
9 MAP_SHARED | MAP_ANONYMOUS,
10 -1,
11 0);
12
13 if (arena == MAP_FAILED)
14 {
15 return NULL;
16 }
17
18 arena->capacity = capacity;
19 arena->base_position = (u8 *)arena + sizeof(mem_arena);
20 arena->current_position = 0;
21 arena->previous_position = 0;
22
23 return arena;
24}
25
26internal void
27arena_destroy(mem_arena *arena)
28{
29 if (!arena)
30 {
31 return;
32 }
33
34 int code = munmap(arena, arena->capacity + sizeof(mem_arena));
35}
36
37internal void *
38arena_alloc(mem_arena *arena, u64 size)
39{
40 if (!arena)
41 {
42 return NULL;
43 }
44
45 u64 aligned = Align(arena->current_position, ARENA_ALIGN);
46 u64 new_pos = aligned + size;
47
48 if (new_pos > arena->capacity)
49 {
50 return NULL;
51 }
52
53 void *out = arena->base_position + aligned;
54
55 arena->previous_position = arena->current_position;
56 arena->current_position = aligned + size;
57
58 MemSet(out, size);
59
60 return out;
61}
62
63internal void
64arena_pop(mem_arena *arena, u64 size)
65{
66 size = MIN(size, arena->current_position);
67 arena->current_position -= size;
68}
69
70internal void
71arena_pop_to(mem_arena *arena, u64 pos)
72{
73 u64 size = pos < arena->current_position ? arena->current_position - pos : 0;
74 arena_pop(arena, size);
75}
76
77internal void
78arena_clear(mem_arena *arena)
79{
80 arena->current_position = 0;
81}
82
83internal mem_arena *
84arena_resize_align(mem_arena *arena, void *old_memory, u64 new_size, u64 old_size, umm alignment)
85{
86 u8 *old_mem = (u8 *)old_memory;
87
88 if (!is_pow(alignment))
89 {
90 Align(arena->current_position, alignment);
91 }
92
93 if (old_memory == NULL || old_size == 0)
94 {
95 return (mem_arena *)arena_alloc(arena, new_size);
96 }
97 else if ((old_mem >= arena->base_position && old_mem < arena->base_position + arena->capacity))
98 {
99 if ((arena->base_position + arena->previous_position) == old_memory)
100 {
101 arena->current_position = arena->previous_position + new_size;
102 if (new_size > old_size)
103 {
104 MemSet(&arena->current_position, new_size - old_size);
105 }
106 return (mem_arena *)old_memory;
107 }
108 else
109 {
110 void *new_memory = arena_alloc(arena, new_size);
111 umm copy_size = old_size < new_size ? old_size : new_size;
112 memmove(new_memory, old_mem, copy_size);
113 }
114 }
115 else
116 {
117 check(0);
118 }
119 return NULL;
120}
121
122internal mem_arena *
123arena_resize(mem_arena *arena, void *old_memory, u64 new_size, u64 old_size)
124{
125 return arena_resize_align(arena, old_memory, new_size, old_size, ARENA_ALIGN);
126}
127
128internal temp_arena
129temp_arena_begin(mem_arena *arena)
130{
131 temp_arena t;
132 t.arena = arena;
133 t.start_position = arena->current_position;
134
135 return t;
136}
137
138internal void
139temp_arena_end(temp_arena temp)
140{
141 temp.arena->current_position = temp.start_position;
142}