68 lines
1.5 KiB
Plaintext
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;
|
|
} |