Files
lib_compiler/examples/sandbox/arena.lc
2024-04-13 15:29:53 +02:00

68 lines
1.5 KiB
Plaintext

import "std_types";
import libc "libc";
PAGE_SIZE :: 4096;
Arena :: struct {
data: *u8;
len: usize;
commit: usize;
reserve: usize;
alignment: usize;
}
GetAlignOffset :: proc(size: usize, align: usize): usize {
mask: usize = align - 1;
val: usize = size & mask;
if val {
val = align - val;
}
return val;
}
AlignUp :: proc(size: usize, align: usize): usize {
result := size + GetAlignOffset(size, align);
return result;
}
InitArena :: proc(arena: *Arena, reserve: usize) {
aligned_reserve := AlignUp(reserve, PAGE_SIZE);
data := VReserve(aligned_reserve);
libc.assert(data != nil);
if data {
arena.data = data;
arena.reserve = aligned_reserve;
arena.alignment = 8;
}
}
PushSize :: proc(arena: *Arena, size: usize): *void {
libc.assert(arena.data != nil);
pointer := :usize(arena.data) + arena.len + size;
align := GetAlignOffset(pointer, arena.alignment);
aligned_size := size + align;
a := arena.len + aligned_size;
if a > arena.commit {
diff := a - arena.commit;
commit_size := AlignUp(diff, PAGE_SIZE*4);
libc.assert(commit_size + arena.commit <= arena.reserve);
if VCommit(&arena.data[arena.commit], commit_size) {
arena.commit += commit_size;
} else {
libc.assert(false && "commit failed"[0]);
}
}
arena.len += align;
result: *void = &arena.data[arena.len];
arena.len += size;
return result;
}
TestArena :: proc() {
arena: Arena;
}