-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patharena.c
More file actions
128 lines (102 loc) · 3.07 KB
/
Copy patharena.c
File metadata and controls
128 lines (102 loc) · 3.07 KB
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
#define MEM_PAGE_SIZE (4 * 1024)
#define MEM_ALLOCATION_GRANULARITY (64 * 1024)
#if defined(__SANITIZE_ADDRESS__)
#include "sanitizer/asan_interface.h"
#define AsanPoison __asan_poison_memory_region
#define AsanUnpoison __asan_unpoison_memory_region
// asan only work with memory alignment by 8
#define MEM_ALIGNMENT 8
#else
#define AsanPoison
#define AsanUnpoison
#define MEM_ALIGNMENT sizeof(void*)
#endif
MArena *ArenaNew(psize size)
{
psize arena_size = AlignSize(sizeof(MArena), MEM_ALIGNMENT);
psize asize = AlignSize(arena_size + size, MEM_ALLOCATION_GRANULARITY);
MArena *arena = (MArena*)OS_MemoryAlloc(asize);
AsanPoison(arena, asize);
AsanUnpoison(arena, sizeof(MArena));
Assert(arena); // TODO: handle failed allocate
arena->mem = (u8*)arena + arena_size;
arena->capacity = asize - arena_size;
SListInit(arena);
return arena;
}
void ArenaFree(MArena *arena)
{
psize arena_size = AlignSize(sizeof(MArena), MEM_ALIGNMENT);
AsanUnpoison(arena, arena_size + arena->capacity);
OS_MemoryFree(arena);
}
void ArenaFreeCurrentNode(MArena *sentinal)
{
MArena *current = sentinal->next;
SListStackPop(sentinal);
ArenaFree(current);
}
void ArenaDestroy(MArena *arena)
{
while (SListNotEmpty(arena))
{
ArenaFreeCurrentNode(arena);
}
OS_MemoryZero(arena, sizeof(*arena));
ArenaFree(arena);
}
u8 *ArenaPush(MArena *arena, psize size, bool zero)
{
u8 *result = 0;
MArena *current_arena = arena->next;
bool need_zero = true;
psize asize = AlignSize(size, MEM_ALIGNMENT);
if (current_arena->size + asize > current_arena->capacity)
{
MArena *new_arena = ArenaNew(asize);
result = new_arena->mem;
new_arena->size = asize;
SListStackPush(arena, new_arena);
need_zero = false; // OS new alloc always zero memory
}
else
{
if (current_arena->size >= current_arena->commit_size)
{
current_arena->commit_size = current_arena->size + asize;
need_zero = false; // OS untouch memory always already init with zero
}
result = current_arena->mem + current_arena->size;
current_arena->size += asize;
Assert(current_arena->size <= current_arena->capacity);
}
AsanUnpoison(result, size);
if (!need_zero)
{
// debug: just make sure memory is actually zeroed
Assert(result[0] == 0);
}
if (zero && need_zero)
{
OS_MemoryZero(result, size);
}
return result;
}
void ArenaPop(MArena *arena, psize size)
{
MArena *current_arena = arena->next;
psize asize = AlignSize(size, MEM_ALIGNMENT);
Assert(asize <= current_arena->size);
current_arena->size -= asize;
if (current_arena->size == 0 && current_arena != arena)
{
ArenaFreeCurrentNode(arena);
}
}
void EndTempArena(MTempArena *temp)
{
while (temp->arena->next != temp->current) {
ArenaFreeCurrentNode(temp->arena);
}
temp->arena->size = temp->offset;
}