|
@@ -3,64 +3,58 @@ package mem_virtual
|
|
import "core:mem"
|
|
import "core:mem"
|
|
|
|
|
|
Growing_Arena :: struct {
|
|
Growing_Arena :: struct {
|
|
- curr_block: ^Memory_Block,
|
|
|
|
- total_used: int,
|
|
|
|
- total_allocated: int,
|
|
|
|
|
|
+ curr_block: ^Memory_Block,
|
|
|
|
+ total_used: uint,
|
|
|
|
+ total_reserved: uint,
|
|
|
|
|
|
- minimum_block_size: int,
|
|
|
|
|
|
+ minimum_block_size: uint,
|
|
temp_count: int,
|
|
temp_count: int,
|
|
}
|
|
}
|
|
|
|
|
|
DEFAULT_MINIMUM_BLOCK_SIZE :: 1024*1024 // 1 KiB should be enough
|
|
DEFAULT_MINIMUM_BLOCK_SIZE :: 1024*1024 // 1 KiB should be enough
|
|
|
|
|
|
growing_arena_alloc :: proc(arena: ^Growing_Arena, min_size: int, alignment: int) -> (data: []byte, err: Allocator_Error) {
|
|
growing_arena_alloc :: proc(arena: ^Growing_Arena, min_size: int, alignment: int) -> (data: []byte, err: Allocator_Error) {
|
|
- align_forward_offset :: proc(arena: ^Growing_Arena, alignment: int) -> int #no_bounds_check {
|
|
|
|
- alignment_offset := 0
|
|
|
|
|
|
+ align_forward_offset :: proc "contextless" (arena: ^Growing_Arena, alignment: int) -> uint #no_bounds_check {
|
|
|
|
+ alignment_offset := uint(0)
|
|
ptr := uintptr(arena.curr_block.base[arena.curr_block.used:])
|
|
ptr := uintptr(arena.curr_block.base[arena.curr_block.used:])
|
|
mask := uintptr(alignment-1)
|
|
mask := uintptr(alignment-1)
|
|
if ptr & mask != 0 {
|
|
if ptr & mask != 0 {
|
|
- alignment_offset = alignment - int(ptr & mask)
|
|
|
|
|
|
+ alignment_offset = uint(alignment) - uint(ptr & mask)
|
|
}
|
|
}
|
|
return alignment_offset
|
|
return alignment_offset
|
|
}
|
|
}
|
|
|
|
|
|
assert(mem.is_power_of_two(uintptr(alignment)))
|
|
assert(mem.is_power_of_two(uintptr(alignment)))
|
|
-
|
|
|
|
|
|
|
|
- size := 0
|
|
|
|
|
|
+ size := uint(0)
|
|
if arena.curr_block != nil {
|
|
if arena.curr_block != nil {
|
|
- size = min_size + align_forward_offset(arena, alignment)
|
|
|
|
|
|
+ size = uint(min_size) + align_forward_offset(arena, alignment)
|
|
}
|
|
}
|
|
|
|
|
|
- if arena.curr_block == nil || arena.curr_block.used + size > arena.curr_block.size {
|
|
|
|
- size = mem.align_forward_int(min_size, alignment)
|
|
|
|
|
|
+ if arena.curr_block == nil || arena.curr_block.used + size > arena.curr_block.reserved {
|
|
|
|
+ size = uint(mem.align_forward_int(min_size, alignment))
|
|
arena.minimum_block_size = max(DEFAULT_MINIMUM_BLOCK_SIZE, arena.minimum_block_size)
|
|
arena.minimum_block_size = max(DEFAULT_MINIMUM_BLOCK_SIZE, arena.minimum_block_size)
|
|
|
|
|
|
block_size := max(size, arena.minimum_block_size)
|
|
block_size := max(size, arena.minimum_block_size)
|
|
|
|
|
|
- new_block := memory_alloc(block_size) or_return
|
|
|
|
|
|
+ new_block := memory_block_alloc(block_size, block_size, {}) or_return
|
|
new_block.prev = arena.curr_block
|
|
new_block.prev = arena.curr_block
|
|
arena.curr_block = new_block
|
|
arena.curr_block = new_block
|
|
- arena.total_allocated += new_block.size
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- curr_block := arena.curr_block
|
|
|
|
- assert(curr_block.used + size <= curr_block.size)
|
|
|
|
-
|
|
|
|
- ptr := curr_block.base[curr_block.used:]
|
|
|
|
- ptr = ptr[uintptr(align_forward_offset(arena, alignment)):]
|
|
|
|
|
|
+ arena.total_reserved += new_block.reserved
|
|
|
|
+ }
|
|
|
|
|
|
- curr_block.used += size
|
|
|
|
- assert(curr_block.used <= curr_block.size)
|
|
|
|
- arena.total_used += size
|
|
|
|
|
|
|
|
- return ptr[:min_size], nil
|
|
|
|
|
|
+ data, err = alloc_from_memory_block(arena.curr_block, int(size), alignment)
|
|
|
|
+ if err == nil {
|
|
|
|
+ arena.total_used += size
|
|
|
|
+ }
|
|
|
|
+ return
|
|
}
|
|
}
|
|
|
|
|
|
growing_arena_free_last_memory_block :: proc(arena: ^Growing_Arena) {
|
|
growing_arena_free_last_memory_block :: proc(arena: ^Growing_Arena) {
|
|
free_block := arena.curr_block
|
|
free_block := arena.curr_block
|
|
arena.curr_block = free_block.prev
|
|
arena.curr_block = free_block.prev
|
|
- memory_dealloc(free_block)
|
|
|
|
|
|
+ memory_block_dealloc(free_block)
|
|
}
|
|
}
|
|
|
|
|
|
growing_arena_free_all :: proc(arena: ^Growing_Arena) {
|
|
growing_arena_free_all :: proc(arena: ^Growing_Arena) {
|
|
@@ -68,7 +62,7 @@ growing_arena_free_all :: proc(arena: ^Growing_Arena) {
|
|
growing_arena_free_last_memory_block(arena)
|
|
growing_arena_free_last_memory_block(arena)
|
|
}
|
|
}
|
|
arena.total_used = 0
|
|
arena.total_used = 0
|
|
- arena.total_allocated = 0
|
|
|
|
|
|
+ arena.total_reserved = 0
|
|
}
|
|
}
|
|
|
|
|
|
growing_arena_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintptr, minimum_block_size := DEFAULT_MINIMUM_BLOCK_SIZE) -> (ptr: ^T, err: Allocator_Error) {
|
|
growing_arena_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintptr, minimum_block_size := DEFAULT_MINIMUM_BLOCK_SIZE) -> (ptr: ^T, err: Allocator_Error) {
|
|
@@ -101,7 +95,7 @@ growing_arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator
|
|
old_memory: rawptr, old_size: int,
|
|
old_memory: rawptr, old_size: int,
|
|
location := #caller_location) -> (data: []byte, err: Allocator_Error) {
|
|
location := #caller_location) -> (data: []byte, err: Allocator_Error) {
|
|
arena := (^Growing_Arena)(allocator_data)
|
|
arena := (^Growing_Arena)(allocator_data)
|
|
-
|
|
|
|
|
|
+
|
|
switch mode {
|
|
switch mode {
|
|
case .Alloc:
|
|
case .Alloc:
|
|
return growing_arena_alloc(arena, size, alignment)
|
|
return growing_arena_alloc(arena, size, alignment)
|
|
@@ -126,7 +120,7 @@ growing_arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator
|
|
Growing_Arena_Temp :: struct {
|
|
Growing_Arena_Temp :: struct {
|
|
arena: ^Growing_Arena,
|
|
arena: ^Growing_Arena,
|
|
block: ^Memory_Block,
|
|
block: ^Memory_Block,
|
|
- used: int,
|
|
|
|
|
|
+ used: uint,
|
|
}
|
|
}
|
|
|
|
|
|
growing_arena_temp_begin :: proc(arena: ^Growing_Arena) -> (temp: Growing_Arena_Temp) {
|
|
growing_arena_temp_begin :: proc(arena: ^Growing_Arena) -> (temp: Growing_Arena_Temp) {
|
|
@@ -149,7 +143,7 @@ growing_arena_temp_end :: proc(temp: Growing_Arena_Temp, loc := #caller_location
|
|
|
|
|
|
if block := arena.curr_block; block != nil {
|
|
if block := arena.curr_block; block != nil {
|
|
assert(block.used >= temp.used, "out of order use of growing_arena_temp_end", loc)
|
|
assert(block.used >= temp.used, "out of order use of growing_arena_temp_end", loc)
|
|
- amount_to_zero := min(block.used-temp.used, block.size-block.used)
|
|
|
|
|
|
+ amount_to_zero := min(block.used-temp.used, block.reserved-block.used)
|
|
mem.zero_slice(block.base[temp.used:][:amount_to_zero])
|
|
mem.zero_slice(block.base[temp.used:][:amount_to_zero])
|
|
block.used = temp.used
|
|
block.used = temp.used
|
|
}
|
|
}
|