Rolled my own virtual memory baseline interface
Mostly use the core library's functionality but wanted a nicer wrap for my use case
This commit is contained in:
parent
0656a41cf7
commit
3ab6bb8616
112
code/grime_virtual_memory.odin
Normal file
112
code/grime_virtual_memory.odin
Normal file
@ -0,0 +1,112 @@
|
||||
/* Virtual Memory OS Interface
|
||||
This is an alternative to the virtual core library provided by odin, suppport setting the base address among other things.
|
||||
*/
|
||||
package sectr
|
||||
|
||||
import core_virtual "core:mem/virtual"
|
||||
import "core:os"
|
||||
|
||||
VirtualMemoryRegionHeader :: struct {
|
||||
committed : uint,
|
||||
reserved : uint,
|
||||
reserve_start : [^]byte,
|
||||
}
|
||||
|
||||
VirtualMemoryRegion :: struct {
|
||||
using base_address : ^VirtualMemoryRegionHeader
|
||||
}
|
||||
|
||||
virtual_get_page_size :: proc "contextless" () -> int {
|
||||
@static page_size := 0
|
||||
if page_size == 0 {
|
||||
page_size = os.get_page_size()
|
||||
}
|
||||
return page_size
|
||||
}
|
||||
|
||||
virtual_reserve_remaining :: proc "contextless" ( using vmem : VirtualMemoryRegion ) -> uint {
|
||||
header_offset := cast(uint) (uintptr(reserve_start) - uintptr(vmem.base_address))
|
||||
return reserved - header_offset
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
virtual_commit :: proc "contextless" ( using vmem : VirtualMemoryRegion, size : uint ) -> ( alloc_error : AllocatorError )
|
||||
{
|
||||
if size < committed {
|
||||
return .None
|
||||
}
|
||||
|
||||
page_size := uint(virtual_get_page_size())
|
||||
to_commit := memory_align_formula( size, page_size )
|
||||
|
||||
alloc_error = core_virtual.commit( base_address, to_commit )
|
||||
if alloc_error != .None {
|
||||
return alloc_error
|
||||
}
|
||||
|
||||
base_address.committed = size
|
||||
return alloc_error
|
||||
}
|
||||
|
||||
virtual_decommit :: proc "contextless" ( vmem : VirtualMemoryRegion, size : uint ) {
|
||||
core_virtual.decommit( vmem.base_address, size )
|
||||
}
|
||||
|
||||
virtual_protect :: proc "contextless" ( vmem : VirtualMemoryRegion, region : []byte, flags : VirtualProtectFlags ) -> b32
|
||||
{
|
||||
page_size := virtual_get_page_size()
|
||||
|
||||
if len(region) % page_size != 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
return cast(b32) core_virtual.protect( raw_data(region), len(region), flags )
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
virtual_reserve :: proc "contextless" ( base_address : uintptr, size : uint ) -> ( VirtualMemoryRegion, AllocatorError ) {
|
||||
page_size := uint(virtual_get_page_size())
|
||||
to_reserve := memory_align_formula( size, page_size )
|
||||
return virtual__reserve( base_address, to_reserve )
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
virtual_reserve_and_commit :: proc "contextless" (
|
||||
base_address : uintptr, reserve_size, commit_size : uint
|
||||
) -> ( vmem : VirtualMemoryRegion, alloc_error : AllocatorError )
|
||||
{
|
||||
if reserve_size < commit_size {
|
||||
alloc_error = .Invalid_Argument
|
||||
return
|
||||
}
|
||||
|
||||
vmem, alloc_error = virtual_reserve( base_address, reserve_size )
|
||||
if alloc_error != .None {
|
||||
return
|
||||
}
|
||||
|
||||
alloc_error = virtual_commit( vmem, commit_size )
|
||||
return
|
||||
}
|
||||
|
||||
virtual_release :: proc "contextless" ( vmem : VirtualMemoryRegion ) {
|
||||
core_virtual.release( vmem.base_address, vmem.reserved )
|
||||
}
|
||||
|
||||
// If the OS is not windows, we just use the library's interface which does not support base_address.
|
||||
when ODIN_OS != OS_Type.Windows {
|
||||
|
||||
virtual__reserve :: proc "contextless" ( base_address : uintptr, size : uint ) -> ( vmem : VirtualMemoryRegion, alloc_error : AllocatorError )
|
||||
{
|
||||
// Ignoring the base address, add an os specific impl if you want it.
|
||||
data : []byte
|
||||
data, alloc_error := core_virtual.reserve( size ) or_return
|
||||
|
||||
vmem.base_address := cast( ^VirtualMemoryRegionHeader ) raw_data(data)
|
||||
vmem.reserve_start = memory_after_header(vmem.base_address)
|
||||
vmem.reserved = len(data)
|
||||
vmem.committed = 0
|
||||
return
|
||||
}
|
||||
|
||||
} // END: ODIN_OS != runtime.Odin_OS_Type.Windows
|
32
code/grime_vmem_windows.odin
Normal file
32
code/grime_vmem_windows.odin
Normal file
@ -0,0 +1,32 @@
|
||||
/* Windows Virtual Memory
|
||||
Windows is the only os getting special vmem definitions
|
||||
since I want full control of it for debug purposes.
|
||||
*/
|
||||
package sectr
|
||||
|
||||
import "core:mem/virtual"
|
||||
import win32 "core:sys/windows"
|
||||
|
||||
when ODIN_OS == OS_Type.Windows {
|
||||
|
||||
@(require_results)
|
||||
virtual__reserve ::
|
||||
proc "contextless" ( base_address : uintptr, size : uint ) -> ( vmem : VirtualMemoryRegion, alloc_error : AllocatorError )
|
||||
{
|
||||
header_size :: cast(uint) size_of(VirtualMemoryRegion)
|
||||
|
||||
result := win32.VirtualAlloc( rawptr(base_address), header_size + size, win32.MEM_RESERVE, win32.PAGE_READWRITE )
|
||||
if result == nil {
|
||||
alloc_error = .Out_Of_Memory
|
||||
return
|
||||
}
|
||||
|
||||
vmem.base_address = cast(^VirtualMemoryRegionHeader) result
|
||||
vmem.reserve_start = memory_after_header(vmem.base_address)
|
||||
vmem.reserved = size
|
||||
vmem.committed = 0
|
||||
alloc_error = .None
|
||||
return
|
||||
}
|
||||
|
||||
} // END: ODIN_OS == runtime.Odin_OS_Type.Windows
|
Loading…
Reference in New Issue
Block a user