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; }