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:
		
							
								
								
									
										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 | ||||
		Reference in New Issue
	
	Block a user