mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-17 19:32:23 -07:00
106 lines
2.7 KiB
Odin
106 lines
2.7 KiB
Odin
package mem_virtual
|
|
|
|
import "core:mem"
|
|
import sync "core:sync/sync2"
|
|
|
|
Memory_Block :: struct {
|
|
prev: ^Memory_Block,
|
|
base: [^]byte,
|
|
size: int,
|
|
used: int,
|
|
}
|
|
|
|
|
|
memory_alloc :: proc(size: int) -> (block: ^Memory_Block, err: mem.Allocator_Error) {
|
|
page_size := DEFAULT_PAGE_SIZE
|
|
|
|
total_size := size + size_of(Platform_Memory_Block)
|
|
base_offset := uintptr(size_of(Platform_Memory_Block))
|
|
protect_offset := uintptr(0)
|
|
|
|
do_protection := false
|
|
{ // overflow protection
|
|
rounded_size := mem.align_formula(size, page_size)
|
|
total_size = rounded_size + 2*page_size
|
|
base_offset = uintptr(page_size + rounded_size - size)
|
|
protect_offset = uintptr(page_size + rounded_size)
|
|
do_protection = true
|
|
}
|
|
|
|
pmblock := platform_memory_alloc(total_size) or_return
|
|
|
|
pmblock.block.base = ([^]byte)(uintptr(pmblock) + base_offset)
|
|
// Should be zeroed
|
|
assert(pmblock.block.used == 0)
|
|
assert(pmblock.block.prev == nil)
|
|
|
|
if (do_protection) {
|
|
platform_memory_protect(rawptr(uintptr(pmblock) + protect_offset), page_size)
|
|
}
|
|
|
|
pmblock.block.size = size
|
|
pmblock.total_size = total_size
|
|
|
|
sentinel := &global_platform_memory_block_sentinel
|
|
sync.mutex_lock(&global_memory_block_mutex)
|
|
pmblock.next = sentinel
|
|
pmblock.prev = sentinel.prev
|
|
pmblock.prev.next = pmblock
|
|
pmblock.next.prev = pmblock
|
|
sync.mutex_unlock(&global_memory_block_mutex)
|
|
|
|
return &pmblock.block, nil
|
|
}
|
|
|
|
|
|
memory_dealloc :: proc(block_to_free: ^Memory_Block) {
|
|
block := (^Platform_Memory_Block)(block_to_free)
|
|
if block != nil {
|
|
sync.mutex_lock(&global_memory_block_mutex)
|
|
block.prev.next = block.next
|
|
block.next.prev = block.prev
|
|
sync.mutex_unlock(&global_memory_block_mutex)
|
|
|
|
platform_memory_free(block)
|
|
}
|
|
}
|
|
|
|
Platform_Memory_Block :: struct {
|
|
block: Memory_Block,
|
|
total_size: int,
|
|
prev, next: ^Platform_Memory_Block,
|
|
}
|
|
|
|
@(private)
|
|
global_memory_block_mutex: sync.Mutex
|
|
@(private)
|
|
global_platform_memory_block_sentinel: Platform_Memory_Block
|
|
@(private)
|
|
global_platform_memory_block_sentinel_set: bool
|
|
|
|
@(private)
|
|
platform_memory_init :: proc() {
|
|
if !global_platform_memory_block_sentinel_set {
|
|
_platform_memory_init()
|
|
global_platform_memory_block_sentinel.prev = &global_platform_memory_block_sentinel
|
|
global_platform_memory_block_sentinel.next = &global_platform_memory_block_sentinel
|
|
global_platform_memory_block_sentinel_set = true
|
|
}
|
|
}
|
|
|
|
platform_memory_alloc :: proc(block_size: int) -> (^Platform_Memory_Block, mem.Allocator_Error) {
|
|
platform_memory_init()
|
|
return _platform_memory_alloc(block_size)
|
|
}
|
|
|
|
|
|
platform_memory_free :: proc(block: ^Platform_Memory_Block) {
|
|
platform_memory_init()
|
|
_platform_memory_free(block)
|
|
}
|
|
|
|
platform_memory_protect :: proc(memory: rawptr, size: int) {
|
|
platform_memory_init()
|
|
_platform_memory_protect(memory, size)
|
|
}
|