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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
internal mem_arena *
arena_create(u64 capacity)
{
mem_arena *arena = (mem_arena *)mmap(
/* kernel decides where to throw the arena */
NULL,
capacity + sizeof(mem_arena),
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS,
-1,
0);
if (arena == MAP_FAILED)
{
return NULL;
}
arena->capacity = capacity;
arena->base_position = (u8 *)arena + sizeof(mem_arena);
arena->current_position = 0;
arena->previous_position = 0;
return arena;
}
internal void
arena_destroy(mem_arena *arena)
{
if (!arena)
{
return;
}
munmap(arena, arena->capacity + sizeof(mem_arena));
}
internal void *
arena_alloc(mem_arena *arena, u64 size, b32 zero)
{
if (!arena)
{
return NULL;
}
u64 aligned = Align(arena->current_position, ARENA_ALIGN);
u64 new_pos = aligned + size;
if (new_pos > arena->capacity)
{
return NULL;
}
void *out = arena->base_position + aligned;
arena->previous_position = arena->current_position;
arena->current_position = aligned + size;
if (zero) MemSet(out, size);
return out;
}
internal void
arena_pop(mem_arena *arena, u64 size)
{
size = MIN(size, arena->current_position);
arena->current_position -= size;
}
internal void
arena_pop_to(mem_arena *arena, u64 pos)
{
u64 size = pos < arena->current_position ? arena->current_position - pos : 0;
arena_pop(arena, size);
}
internal void
arena_clear(mem_arena *arena)
{
arena->current_position = 0;
}
internal mem_arena *
arena_resize_align(mem_arena *arena, void *old_memory, u64 new_size, u64 old_size, umm alignment)
{
u8 *old_mem = (u8 *)old_memory;
if (!is_pow(alignment))
{
Align(arena->current_position, alignment);
}
if (old_memory == NULL || old_size == 0)
{
return (mem_arena *)arena_alloc(arena, new_size, 0);
}
else if ((old_mem >= arena->base_position && old_mem < arena->base_position + arena->capacity))
{
if ((arena->base_position + arena->previous_position) == old_memory)
{
arena->current_position = arena->previous_position + new_size;
if (new_size > old_size)
{
MemSet(&arena->current_position, new_size - old_size);
}
return (mem_arena *)old_memory;
}
else
{
void *new_memory = arena_alloc(arena, new_size, 0);
umm copy_size = old_size < new_size ? old_size : new_size;
memmove(new_memory, old_mem, copy_size);
}
}
else
{
// warn(0);
}
return NULL;
}
internal mem_arena *
arena_resize(mem_arena *arena, void *old_memory, u64 new_size, u64 old_size)
{
return arena_resize_align(arena, old_memory, new_size, old_size, ARENA_ALIGN);
}
internal temp_arena
temp_arena_begin(mem_arena *arena)
{
temp_arena t;
t.arena = arena;
t.start_position = arena->current_position;
return t;
}
internal void
temp_arena_end(temp_arena temp)
{
temp.arena->current_position = temp.start_position;
}
|