summaryrefslogtreecommitdiff
path: root/source/base/base_stack.cpp
diff options
context:
space:
mode:
authornasr <nsrddyn@gmail.com>2026-10-05 22:02:56 +0200
committernasr <nsrddyn@gmail.com>2026-10-05 22:02:56 +0200
commitf6d3090f7fa76eb8e0dbe060b8490cb49c001c39 (patch)
tree433c773997e51f22738acb8b04c4fd2fc6b1bdc9 /source/base/base_stack.cpp
init: base
Diffstat (limited to 'source/base/base_stack.cpp')
-rw-r--r--source/base/base_stack.cpp234
1 files changed, 234 insertions, 0 deletions
diff --git a/source/base/base_stack.cpp b/source/base/base_stack.cpp
new file mode 100644
index 0000000..bf3f045
--- /dev/null
+++ b/source/base/base_stack.cpp
@@ -0,0 +1,234 @@
1
2// TODO: the previous position of the stack header never get's set
3// TODO: renmae current_position in arena.cpp and arena.h to current_address or vice versa
4
5#if PLATFORM_LINUX
6internal MemStack *unix_stack_create(u64 capacity)
7{
8 MemStack *stack = (MemStack *)mmap(0, capacity + sizeof(MemStack), PROT_READ | PROT_WRITE,
9 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
10
11 if (stack == MAP_FAILED) {
12 return NULL;
13 }
14
15 stack->capacity = capacity;
16 stack->base_position = (u8 *)stack + sizeof(MemStack);
17 stack->current_offset = 0;
18
19 return stack;
20}
21
22internal void unix_stack_destroy(MemStack *stack)
23{
24 if (!stack) {
25 return;
26 }
27
28 munmap(stack, stack->capacity + sizeof(MemStack));
29}
30#endif // PLATFORM_LINUX
31
32#if PLATFORM_WINDOWS
33
34// request a page from the operating system
35internal MemStack *win32_stack_create(u64 capacity)
36{
37 MemStack *stack = (MemStack *)VirtualAlloc(NULL, capacity + sizeof(MemStack),
38 MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
39
40 if (!stack) {
41 Log("Failed to receive a memory address from the operating system");
42 return NULL;
43 }
44
45 stack->capacity = capacity;
46 stack->base_position = (u8 *)stack + sizeof(MemStack);
47 stack->current_offset = 0;
48 return stack;
49}
50
51internal void win32_stack_destroy(MemStack *stack)
52{
53 b32 result = VirtualFree(stack,
54 0, // stands for the byte of committed pages
55 MEM_RELEASE);
56
57 if (!result) {
58 Log("Failed to receive a memory address from the operating system");
59 }
60}
61
62#endif // PLATFORM_WINDOWS
63
64internal u8 calculate_padding(u64 pointer, u8 alignment, u64 header_size)
65{
66 u8 modulo, padding;
67
68 if (!is_pow(alignment)) {
69 return 0;
70 }
71
72 modulo = pointer & (u8)(alignment - 1);
73
74 padding = 0;
75
76 if (0 != modulo) {
77 padding = alignment - modulo;
78 }
79
80 if (padding < header_size) {
81 header_size -= padding;
82
83 if ((header_size & (alignment - 1)) != 0) {
84 padding += alignment * (1 + (u8)(header_size / alignment));
85 } else {
86 padding += alignment * ((u8)(header_size / alignment));
87 }
88 }
89
90 return padding;
91}
92
93internal MemStack *stack_push_align(MemStack *stack, u64 size, u8 alignment)
94{
95 // NOTE: satifisying static analyzer
96 AssertLog((stack != NULL), "STACK IS NULL");
97 u8 padding = 0;
98
99 // NOTE: this shouln't be possible because we have the allignment predefined
100 // so it's bassically a useless check
101
102 if (!is_pow(alignment)) {
103 breakpoint();
104 return (0);
105 }
106
107 if (alignment > 128) { // NOTE: where does the 128 come from?
108 alignment = 128;
109 }
110
111 u64 current_address;
112 current_address = (u64)stack->base_position + stack->current_offset; // NOTE: we already we're checking if the stack existed
113 padding = calculate_padding(current_address, alignment, sizeof(MemStackHeader));
114
115 if (stack->current_offset + padding + size > stack->capacity) {
116 breakpoint();
117 return 0;
118 }
119
120 stack->current_offset += padding;
121
122 u64 next_address = current_address + (u64)padding;
123 MemStackHeader *header = (MemStackHeader *)(next_address - sizeof(MemStackHeader));
124 header->padding = padding;
125
126 stack->current_offset += size;
127
128 return (MemStack *)MemSet((MemStack *)next_address, size);
129}
130
131internal void *stack_push(MemStack *stack, u64 size)
132{
133 return stack_push_align(stack, size, arena_align);
134}
135
136internal void stack_pop(MemStack *stack, void *pointer)
137{
138 if (pointer != NULL) {
139 u64 start, end, current_address;
140 MemStackHeader *header;
141 u64 prev_offset;
142
143 start = (u64)stack->base_position;
144 end = start + (u64)stack->capacity;
145 current_address = (u64)pointer;
146
147 if (!(start <= current_address && current_address < end)) {
148 if (0 && "Out of bounds memory address passed to stack allocator (free)") {
149 return;
150 }
151 return;
152 }
153
154 if (current_address >= start + (u64)stack->current_offset) {
155 return;
156 }
157
158 header = (MemStackHeader *)(current_address - sizeof(MemStackHeader));
159 prev_offset = (size_t)(current_address - (u64)header->padding - start);
160 stack->current_offset = prev_offset;
161 }
162}
163
164internal MemStack *stack_resize_align(MemStack *stack, void *pointer, u64 old_size, u64 new_size,
165 u8 alignment)
166{
167 if (pointer == NULL) {
168 return stack_push_align(stack, new_size, alignment);
169 } else if (new_size == 0) {
170 stack_pop(stack, pointer);
171 return NULL;
172 }
173
174 u64 start, end, current_address;
175 u64 min_size = old_size < new_size ? old_size : new_size;
176 void *new_pointer;
177
178 start = (u64)stack->base_position;
179 end = start + (u64)stack->capacity;
180 current_address = (u64)pointer;
181 if (!(start <= current_address && current_address < end)) {
182 return NULL;
183 }
184
185 if (current_address >= start + (u64)stack->current_offset) {
186 return NULL;
187 }
188
189 if (old_size == new_size) {
190 return (MemStack *)pointer;
191 }
192
193 new_pointer = stack_push_align(stack, new_size, alignment);
194 AssertLog((new_pointer != NULL), "stack_push_align failed in stack_resize_align");
195 memmove(new_pointer, pointer, min_size);
196 return (MemStack *)new_pointer;
197}
198
199internal MemStack *arena_to_stack(MemArena *arena, u64 requested_size)
200{
201
202 Assert(arena);
203
204 MemStack *stack = PushStruct(arena, MemStack);
205 u8 *buffer = PushArray(arena, u8, requested_size);
206
207 stack->header = 0;
208 stack->base_position = buffer;
209 stack->capacity = requested_size;
210 stack->current_offset = 0;
211
212 return stack;
213}
214
215#if 0
216#if MEM_DEBUG
217global_variable String8List *stack_log; // TODO: initialize this in the mem stack callback
218
219#endif
220
221internal void
222stack_debug_view(MemArena *global_arena, MemStack *stack)
223{
224
225 if(!stack_log)
226 {
227 stack_log = PushStruct(global_arena, String8List);
228 }
229
230
231}
232#endif
233
234internal void stack_clear(MemStack *stack) { stack->current_offset = 0; }