aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-10-04 16:43:52 +0100
committergingerBill <bill@gingerbill.org>2021-10-04 16:43:52 +0100
commitf2e78dcc0baa5abce71e3aba492406617c3a7bc4 (patch)
tree32a8e1326fabf024e8005df80f997c12542dc7ed
parenta463609e4c6753f520d11a6d9180cb720c4eeb38 (diff)
Separate out the virtual memory allocation procedures
`reserve`, `commit`, `reserve_and_commit`, `decommit`, `release`, `protect`
-rw-r--r--core/mem/virtual/arena.odin11
-rw-r--r--core/mem/virtual/virtual.odin83
-rw-r--r--core/mem/virtual/virtual_windows.odin48
3 files changed, 95 insertions, 47 deletions
diff --git a/core/mem/virtual/arena.odin b/core/mem/virtual/arena.odin
index d4d84e5b3..d8949cb10 100644
--- a/core/mem/virtual/arena.odin
+++ b/core/mem/virtual/arena.odin
@@ -12,9 +12,8 @@ Growing_Arena :: struct {
}
DEFAULT_MINIMUM_BLOCK_SIZE :: 1024*1024 // 1 KiB should be enough
-DEFAULT_PAGE_SIZE := 4096
-growing_arena_alloc :: proc(arena: ^Growing_Arena, min_size: int, alignment: int) -> (data: []byte, err: mem.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
ptr := uintptr(arena.curr_block.base[arena.curr_block.used:])
@@ -71,7 +70,7 @@ growing_arena_free_all :: proc(arena: ^Growing_Arena) {
arena.total_used = 0
}
-growing_arena_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintptr, minimum_block_size := DEFAULT_MINIMUM_BLOCK_SIZE) -> (ptr: ^T, err: mem.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) {
bootstrap: Growing_Arena
bootstrap.minimum_block_size = minimum_block_size
@@ -84,7 +83,7 @@ growing_arena_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintp
return
}
-growing_arena_bootstrap_new_by_name :: proc($T: typeid, $field_name: string, minimum_block_size := DEFAULT_MINIMUM_BLOCK_SIZE) -> (ptr: ^T, err: mem.Allocator_Error) {
+growing_arena_bootstrap_new_by_name :: proc($T: typeid, $field_name: string, minimum_block_size := DEFAULT_MINIMUM_BLOCK_SIZE) -> (ptr: ^T, err: Allocator_Error) {
return growing_arena_bootstrap_new_by_offset(T, offset_of_by_string(T, field_name), minimum_block_size)
}
growing_arena_bootstrap_new :: proc{
@@ -99,7 +98,7 @@ growing_arena_allocator :: proc(arena: ^Growing_Arena) -> mem.Allocator {
growing_arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
size, alignment: int,
old_memory: rawptr, old_size: int,
- location := #caller_location) -> (data: []byte, err: mem.Allocator_Error) {
+ location := #caller_location) -> (data: []byte, err: Allocator_Error) {
arena := (^Growing_Arena)(allocator_data)
switch mode {
@@ -160,4 +159,4 @@ growing_arena_temp_end :: proc(temp: Growing_Arena_Temp, loc := #caller_location
growing_arena_check_temp :: proc(arena: ^Growing_Arena, loc := #caller_location) {
assert(arena.temp_count == 0, "Growing_Arena_Temp not been ended", loc)
-} \ No newline at end of file
+}
diff --git a/core/mem/virtual/virtual.odin b/core/mem/virtual/virtual.odin
index 83a4e8783..a78917ae1 100644
--- a/core/mem/virtual/virtual.odin
+++ b/core/mem/virtual/virtual.odin
@@ -3,6 +3,39 @@ package mem_virtual
import "core:mem"
import sync "core:sync/sync2"
+DEFAULT_PAGE_SIZE := uint(4096)
+
+Allocator_Error :: mem.Allocator_Error
+
+reserve :: proc(size: uint) -> (data: []byte, err: Allocator_Error) {
+ return _reserve(size)
+}
+
+commit :: proc(data: rawptr, size: uint) {
+ _commit(data, size)
+}
+
+reserve_and_commit :: proc(size: uint) -> (data: []byte, err: Allocator_Error) {
+ data = _reserve(size) or_return
+ commit(raw_data(data), size)
+ return
+}
+
+
+decommit :: proc(data: rawptr, size: uint) {
+ _decommit(data, size)
+}
+
+release :: proc(data: rawptr, size: uint) {
+ _release(data, size)
+}
+
+protect :: proc(data: rawptr, size: uint) -> bool {
+ return _protect(data, size)
+}
+
+
+
Memory_Block :: struct {
prev: ^Memory_Block,
base: [^]byte,
@@ -11,18 +44,23 @@ Memory_Block :: struct {
}
-memory_alloc :: proc(size: int) -> (block: ^Memory_Block, err: mem.Allocator_Error) {
+memory_alloc :: proc(size: int) -> (block: ^Memory_Block, err: Allocator_Error) {
+ align_formula :: proc "contextless" (size, align: uint) -> uint {
+ result := size + align-1
+ return result - result%align
+ }
+
page_size := DEFAULT_PAGE_SIZE
- total_size := size + size_of(Platform_Memory_Block)
+ total_size := uint(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)
+ rounded_size := align_formula(uint(size), page_size)
+ total_size = uint(rounded_size + 2*page_size)
+ base_offset = uintptr(page_size + rounded_size - uint(size))
protect_offset = uintptr(page_size + rounded_size)
do_protection = true
}
@@ -35,7 +73,7 @@ memory_alloc :: proc(size: int) -> (block: ^Memory_Block, err: mem.Allocator_Err
assert(pmblock.block.prev == nil)
if (do_protection) {
- platform_memory_protect(rawptr(uintptr(pmblock) + protect_offset), page_size)
+ protect(rawptr(uintptr(pmblock) + protect_offset), page_size)
}
pmblock.block.size = size
@@ -67,10 +105,26 @@ memory_dealloc :: proc(block_to_free: ^Memory_Block) {
Platform_Memory_Block :: struct {
block: Memory_Block,
- total_size: int,
+ total_size: uint,
prev, next: ^Platform_Memory_Block,
}
+platform_memory_alloc :: proc(total_size: uint) -> (block: ^Platform_Memory_Block, err: Allocator_Error) {
+ total_size := total_size
+ total_size = max(total_size, size_of(Platform_Memory_Block))
+ data := reserve_and_commit(total_size) or_return
+ block = (^Platform_Memory_Block)(raw_data(data))
+ block.total_size = total_size
+ return
+}
+
+
+platform_memory_free :: proc(block: ^Platform_Memory_Block) {
+ if block != nil {
+ release(block, block.total_size)
+ }
+}
+
@(private)
global_memory_block_mutex: sync.Mutex
@(private)
@@ -78,7 +132,7 @@ global_platform_memory_block_sentinel: Platform_Memory_Block
@(private)
global_platform_memory_block_sentinel_set: bool
-@(init)
+@(private, init)
platform_memory_init :: proc() {
if !global_platform_memory_block_sentinel_set {
_platform_memory_init()
@@ -87,16 +141,3 @@ platform_memory_init :: proc() {
global_platform_memory_block_sentinel_set = true
}
}
-
-platform_memory_alloc :: proc(block_size: int) -> (^Platform_Memory_Block, mem.Allocator_Error) {
- return _platform_memory_alloc(block_size)
-}
-
-
-platform_memory_free :: proc(block: ^Platform_Memory_Block) {
- _platform_memory_free(block)
-}
-
-platform_memory_protect :: proc(memory: rawptr, size: int) {
- _platform_memory_protect(memory, size)
-}
diff --git a/core/mem/virtual/virtual_windows.odin b/core/mem/virtual/virtual_windows.odin
index 58dff6d3c..fb28eb117 100644
--- a/core/mem/virtual/virtual_windows.odin
+++ b/core/mem/virtual/virtual_windows.odin
@@ -2,8 +2,6 @@
//+private
package mem_virtual
-import "core:mem"
-
foreign import Kernel32 "system:Kernel32.lib"
LPSYSTEM_INFO :: ^SYSTEM_INFO
@@ -60,28 +58,38 @@ foreign Kernel32 {
}
-_platform_memory_init :: proc() {
- sys_info: SYSTEM_INFO
- GetSystemInfo(&sys_info)
- DEFAULT_PAGE_SIZE = max(DEFAULT_PAGE_SIZE, int(sys_info.dwPageSize))
- assert(mem.is_power_of_two(uintptr(DEFAULT_PAGE_SIZE)))
-}
-
-_platform_memory_alloc :: proc(total_size: int) -> (pmblock: ^Platform_Memory_Block, err: mem.Allocator_Error) {
- pmblock = (^Platform_Memory_Block)(VirtualAlloc(nil, uint(total_size), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE))
- if pmblock == nil {
+_reserve :: proc(size: uint) -> (data: []byte, err: Allocator_Error) {
+ result := VirtualAlloc(nil, size, MEM_RELEASE, PAGE_READWRITE)
+ if result == nil {
err = .Out_Of_Memory
+ return
}
- return
+ data = ([^]byte)(result)[:size]
+ return
}
-
-_platform_memory_free :: proc(block: ^Platform_Memory_Block) {
- VirtualFree(block, 0, MEM_RELEASE)
+_commit :: proc(data: rawptr, size: uint) {
+ VirtualAlloc(data, size, MEM_COMMIT, PAGE_READWRITE)
}
-
-_platform_memory_protect :: proc(memory: rawptr, size: int) -> bool {
+_decommit :: proc(data: rawptr, size: uint) {
+ VirtualFree(data, size, MEM_DECOMMIT)
+}
+_release :: proc(data: rawptr, size: uint) {
+ VirtualFree(data, 0, MEM_RELEASE)
+}
+_protect :: proc(data: rawptr, size: uint) -> bool {
old_protect: u32
- ok := VirtualProtect(memory, uint(size), PAGE_NOACCESS, &old_protect)
+ ok := VirtualProtect(data, size, PAGE_NOACCESS, &old_protect)
return bool(ok)
-} \ No newline at end of file
+}
+
+
+
+_platform_memory_init :: proc() {
+ sys_info: SYSTEM_INFO
+ GetSystemInfo(&sys_info)
+ DEFAULT_PAGE_SIZE = max(DEFAULT_PAGE_SIZE, uint(sys_info.dwPageSize))
+
+ // is power of two
+ assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0)
+}