From 8d6ce0b693b12b392a370e96f2bb9394efacd01e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 28 Jan 2023 11:51:58 +0000 Subject: [PATCH] Add mutex to `virtual.Arena`; add `virtual.arena_temp_ignore` --- core/mem/virtual/arena.odin | 21 +++++++++++++++++++++ core/mem/virtual/virtual.odin | 6 +++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/core/mem/virtual/arena.odin b/core/mem/virtual/arena.odin index 0ddb116fd..411407c70 100644 --- a/core/mem/virtual/arena.odin +++ b/core/mem/virtual/arena.odin @@ -1,6 +1,7 @@ package mem_virtual import "core:mem" +import "core:sync" Arena_Kind :: enum uint { Growing = 0, // Chained memory blocks (singly linked list). @@ -15,6 +16,7 @@ Arena :: struct { total_reserved: uint, minimum_block_size: uint, temp_count: uint, + mutex: sync.Mutex, } @@ -78,6 +80,8 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l return nil, nil } + sync.mutex_guard(&arena.mutex) + switch arena.kind { case .Growing: if arena.curr_block == nil || (safe_add(arena.curr_block.used, size) or_else 0) > arena.curr_block.reserved { @@ -116,6 +120,8 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l } arena_static_reset_to :: proc(arena: ^Arena, pos: uint, loc := #caller_location) -> bool { + sync.mutex_guard(&arena.mutex) + if arena.curr_block != nil { assert(arena.kind != .Growing, "expected a non .Growing arena", loc) @@ -135,6 +141,7 @@ arena_static_reset_to :: proc(arena: ^Arena, pos: uint, loc := #caller_location) } arena_growing_free_last_memory_block :: proc(arena: ^Arena, loc := #caller_location) { + sync.mutex_guard(&arena.mutex) if free_block := arena.curr_block; free_block != nil { assert(arena.kind == .Growing, "expected a .Growing arena", loc) arena.curr_block = free_block.prev @@ -145,6 +152,7 @@ arena_growing_free_last_memory_block :: proc(arena: ^Arena, loc := #caller_locat arena_free_all :: proc(arena: ^Arena) { switch arena.kind { case .Growing: + sync.mutex_guard(&arena.mutex) for arena.curr_block != nil { arena_growing_free_last_memory_block(arena) } @@ -287,6 +295,8 @@ Arena_Temp :: struct { @(require_results) arena_temp_begin :: proc(arena: ^Arena, loc := #caller_location) -> (temp: Arena_Temp) { assert(arena != nil, "nil arena", loc) + sync.mutex_guard(&arena.mutex) + temp.arena = arena temp.block = arena.curr_block if arena.curr_block != nil { @@ -299,6 +309,7 @@ arena_temp_begin :: proc(arena: ^Arena, loc := #caller_location) -> (temp: Arena arena_temp_end :: proc(temp: Arena_Temp, loc := #caller_location) { assert(temp.arena != nil, "nil arena", loc) arena := temp.arena + sync.mutex_guard(&arena.mutex) memory_block_found := false for block := arena.curr_block; block != nil; block = block.prev { @@ -326,6 +337,16 @@ arena_temp_end :: proc(temp: Arena_Temp, loc := #caller_location) { arena.temp_count -= 1 } +// Ignore the use of a `arena_temp_begin` entirely +arena_temp_ignore :: proc(temp: Arena_Temp, loc := #caller_location) { + assert(temp.arena != nil, "nil arena", loc) + arena := temp.arena + sync.mutex_guard(&arena.mutex) + + assert(arena.temp_count > 0, "double-use of arena_temp_end", loc) + arena.temp_count -= 1 +} + arena_check_temp :: proc(arena: ^Arena, loc := #caller_location) { assert(arena.temp_count == 0, "Arena_Temp not been ended", loc) } diff --git a/core/mem/virtual/virtual.odin b/core/mem/virtual/virtual.odin index 5e831a0c3..12815b7f1 100644 --- a/core/mem/virtual/virtual.odin +++ b/core/mem/virtual/virtual.odin @@ -7,6 +7,7 @@ DEFAULT_PAGE_SIZE := uint(4096) Allocator_Error :: mem.Allocator_Error +@(require_results) reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) { return _reserve(size) } @@ -15,6 +16,7 @@ commit :: proc "contextless" (data: rawptr, size: uint) -> Allocator_Error { return _commit(data, size) } +@(require_results) reserve_and_commit :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) { data = reserve(size) or_return commit(raw_data(data), size) or_return @@ -57,6 +59,7 @@ Memory_Block_Flag :: enum u32 { Memory_Block_Flags :: distinct bit_set[Memory_Block_Flag; u32] +@(require_results) memory_block_alloc :: proc(committed, reserved: uint, flags: Memory_Block_Flags) -> (block: ^Memory_Block, err: Allocator_Error) { align_formula :: proc "contextless" (size, align: uint) -> uint { result := size + align-1 @@ -100,6 +103,7 @@ memory_block_alloc :: proc(committed, reserved: uint, flags: Memory_Block_Flags) return &pmblock.block, nil } +@(require_results) alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint) -> (data: []byte, err: Allocator_Error) { calc_alignment_offset :: proc "contextless" (block: ^Memory_Block, alignment: uintptr) -> uint { alignment_offset := uint(0) @@ -160,7 +164,7 @@ memory_block_dealloc :: proc(block_to_free: ^Memory_Block) { -@(private) +@(private, require_results) safe_add :: #force_inline proc "contextless" (x, y: uint) -> (uint, bool) { z, did_overflow := intrinsics.overflow_add(x, y) return z, !did_overflow