From 3426af2d6cb5944d373470d10ca91f827a8f39ca Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 12 Apr 2024 12:33:25 +0100 Subject: Fix #3415 --- src/common_memory.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/common_memory.cpp') diff --git a/src/common_memory.cpp b/src/common_memory.cpp index c6ee88f03..60e570eee 100644 --- a/src/common_memory.cpp +++ b/src/common_memory.cpp @@ -163,6 +163,10 @@ gb_internal void platform_virtual_memory_protect(void *memory, isize size); GB_ASSERT(is_protected); } #else + #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) + #define MAP_ANONYMOUS MAP_ANON + #endif + gb_internal void platform_virtual_memory_init(void) { global_platform_memory_block_sentinel.prev = &global_platform_memory_block_sentinel; global_platform_memory_block_sentinel.next = &global_platform_memory_block_sentinel; -- cgit v1.2.3 From 018026d844c8ad3b625f019acee470dbb865d085 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 15 Jul 2024 00:36:00 +0100 Subject: Use `gb_zero_*` calls --- src/checker.cpp | 6 +++--- src/common_memory.cpp | 7 ------- src/gb/gb.h | 2 +- src/parser.cpp | 2 +- src/types.cpp | 2 +- 5 files changed, 6 insertions(+), 13 deletions(-) (limited to 'src/common_memory.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index 336440d32..0a671cc2d 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -658,7 +658,7 @@ gb_internal bool check_vet_shadowing(Checker *c, Entity *e, VettedEntity *ve) { } } - zero_item(ve); + gb_zero_item(ve); ve->kind = VettedEntity_Shadowed; ve->entity = e; ve->other = shadowed; @@ -677,7 +677,7 @@ gb_internal bool check_vet_unused(Checker *c, Entity *e, VettedEntity *ve) { } case Entity_ImportName: case Entity_LibraryName: - zero_item(ve); + gb_zero_item(ve); ve->kind = VettedEntity_Unused; ve->entity = e; return true; @@ -1389,7 +1389,7 @@ gb_internal void reset_checker_context(CheckerContext *ctx, AstFile *file, Untyp auto type_path = ctx->type_path; array_clear(type_path); - zero_size(&ctx->pkg, gb_size_of(CheckerContext) - gb_offset_of(CheckerContext, pkg)); + gb_zero_size(&ctx->pkg, gb_size_of(CheckerContext) - gb_offset_of(CheckerContext, pkg)); ctx->file = nullptr; ctx->scope = builtin_pkg->scope; diff --git a/src/common_memory.cpp b/src/common_memory.cpp index 60e570eee..42a2125dc 100644 --- a/src/common_memory.cpp +++ b/src/common_memory.cpp @@ -2,13 +2,6 @@ #include #endif -gb_internal gb_inline void zero_size(void *ptr, isize len) { - memset(ptr, 0, len); -} - -#define zero_item(ptr) zero_size((ptr), gb_size_of(ptr)) - - template gb_internal gb_inline U bit_cast(V &v) { return reinterpret_cast(v); } diff --git a/src/gb/gb.h b/src/gb/gb.h index 22a30a04b..38dabc9bd 100644 --- a/src/gb/gb.h +++ b/src/gb/gb.h @@ -2534,7 +2534,7 @@ gb_inline void const *gb_pointer_add_const(void const *ptr, isize bytes) { gb_inline void const *gb_pointer_sub_const(void const *ptr, isize bytes) { return cast(void const *)(cast(u8 const *)ptr - bytes); } gb_inline isize gb_pointer_diff (void const *begin, void const *end) { return cast(isize)(cast(u8 const *)end - cast(u8 const *)begin); } -gb_inline void gb_zero_size(void *ptr, isize size) { gb_memset(ptr, 0, size); } +gb_inline void gb_zero_size(void *ptr, isize size) { memset(ptr, 0, size); } #if defined(_MSC_VER) && !defined(__clang__) diff --git a/src/parser.cpp b/src/parser.cpp index 4924dd37d..02c37815b 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -5413,7 +5413,7 @@ gb_internal ParseFileError init_ast_file(AstFile *f, String const &fullpath, Tok if (!string_ends_with(f->fullpath, str_lit(".odin"))) { return ParseFile_WrongExtension; } - zero_item(&f->tokenizer); + gb_zero_item(&f->tokenizer); f->tokenizer.curr_file_id = f->id; TokenizerInitError err = init_tokenizer_from_fullpath(&f->tokenizer, f->fullpath, build_context.copy_file_contents); diff --git a/src/types.cpp b/src/types.cpp index 92b187cdb..fdc174d81 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -964,7 +964,7 @@ gb_internal Type *alloc_type(TypeKind kind) { // gbAllocator a = heap_allocator(); gbAllocator a = permanent_allocator(); Type *t = gb_alloc_item(a, Type); - zero_item(t); + gb_zero_item(t); t->kind = kind; t->cached_size = -1; t->cached_align = -1; -- cgit v1.2.3 From a8f84c87ae7b4d30cf197f54cbc05da024a17d24 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 15 Jul 2024 01:05:29 +0100 Subject: Add the permanent and temporary arenas directly on the `Thread` --- src/common_memory.cpp | 71 +++++++++++++++++++++++++++++++++++++++++++++++---- src/thread_pool.cpp | 5 +++- src/threading.cpp | 11 ++++++-- 3 files changed, 79 insertions(+), 8 deletions(-) (limited to 'src/common_memory.cpp') diff --git a/src/common_memory.cpp b/src/common_memory.cpp index 42a2125dc..95803d3c8 100644 --- a/src/common_memory.cpp +++ b/src/common_memory.cpp @@ -66,6 +66,14 @@ gb_internal isize arena_align_forward_offset(Arena *arena, isize alignment) { return alignment_offset; } +gb_internal void thread_init_arenas(Thread *t) { + t->permanent_arena = gb_alloc_item(heap_allocator(), Arena); + t->temporary_arena = gb_alloc_item(heap_allocator(), Arena); + + t->permanent_arena->minimum_block_size = DEFAULT_MINIMUM_BLOCK_SIZE; + t->temporary_arena->minimum_block_size = DEFAULT_MINIMUM_BLOCK_SIZE; +} + gb_internal void *arena_alloc(Arena *arena, isize min_size, isize alignment) { GB_ASSERT(gb_is_power_of_two(alignment)); @@ -363,14 +371,67 @@ gb_internal GB_ALLOCATOR_PROC(arena_allocator_proc) { } -gb_global gb_thread_local Arena permanent_arena = {nullptr, DEFAULT_MINIMUM_BLOCK_SIZE}; +enum ThreadArenaKind : uintptr { + ThreadArena_Permanent, + ThreadArena_Temporary, +}; + +gb_global Arena default_permanent_arena = {nullptr, DEFAULT_MINIMUM_BLOCK_SIZE}; +gb_global Arena default_temporary_arena = {nullptr, DEFAULT_MINIMUM_BLOCK_SIZE}; + + +gb_internal Thread *get_current_thread(void); + +gb_internal Arena *get_arena(ThreadArenaKind kind) { + Thread *t = get_current_thread(); + switch (kind) { + case ThreadArena_Permanent: return t ? t->permanent_arena : &default_permanent_arena; + case ThreadArena_Temporary: return t ? t->temporary_arena : &default_temporary_arena; + } + GB_PANIC("INVALID ARENA KIND"); + return nullptr; +} + + + +gb_internal GB_ALLOCATOR_PROC(thread_arena_allocator_proc) { + void *ptr = nullptr; + ThreadArenaKind kind = cast(ThreadArenaKind)cast(uintptr)allocator_data; + Arena *arena = get_arena(kind); + + switch (type) { + case gbAllocation_Alloc: + ptr = arena_alloc(arena, size, alignment); + break; + case gbAllocation_Free: + break; + case gbAllocation_Resize: + if (size == 0) { + ptr = nullptr; + } else if (size <= old_size) { + ptr = old_memory; + } else { + ptr = arena_alloc(arena, size, alignment); + gb_memmove(ptr, old_memory, old_size); + } + break; + case gbAllocation_FreeAll: + GB_PANIC("use arena_free_all directly"); + arena_free_all(arena); + break; + } + + return ptr; +} + + + gb_internal gbAllocator permanent_allocator() { - return arena_allocator(&permanent_arena); + return {thread_arena_allocator_proc, cast(void *)cast(uintptr)ThreadArena_Permanent}; } -gb_global gb_thread_local Arena temporary_arena = {nullptr, DEFAULT_MINIMUM_BLOCK_SIZE}; gb_internal gbAllocator temporary_allocator() { - return arena_allocator(&temporary_arena); + return {thread_arena_allocator_proc, cast(void *)cast(uintptr)ThreadArena_Permanent}; } @@ -378,7 +439,7 @@ gb_internal gbAllocator temporary_allocator() { // #define TEMPORARY_ALLOCATOR_GUARD() -#define TEMPORARY_ALLOCATOR_GUARD() TEMP_ARENA_GUARD(&temporary_arena) +#define TEMPORARY_ALLOCATOR_GUARD() TEMP_ARENA_GUARD(get_arena(ThreadArena_Temporary)) #define PERMANENT_ALLOCATOR_GUARD() diff --git a/src/thread_pool.cpp b/src/thread_pool.cpp index 62cca6de6..8363a4553 100644 --- a/src/thread_pool.cpp +++ b/src/thread_pool.cpp @@ -3,7 +3,10 @@ struct WorkerTask; struct ThreadPool; -gb_thread_local Thread *current_thread; +gb_global gb_thread_local Thread *current_thread; +gb_internal Thread *get_current_thread(void) { + return current_thread; +} gb_internal void thread_pool_init(ThreadPool *pool, isize worker_count, char const *worker_name); gb_internal void thread_pool_destroy(ThreadPool *pool); diff --git a/src/threading.cpp b/src/threading.cpp index ff0fdfcde..c622ac87e 100644 --- a/src/threading.cpp +++ b/src/threading.cpp @@ -70,6 +70,9 @@ struct Thread { struct TaskQueue queue; struct ThreadPool *pool; + + struct Arena *permanent_arena; + struct Arena *temporary_arena; }; typedef std::atomic Futex; @@ -560,18 +563,20 @@ gb_internal void *internal_thread_proc(void *arg) { } #endif -TaskRingBuffer *task_ring_init(isize size) { +gb_internal TaskRingBuffer *task_ring_init(isize size) { TaskRingBuffer *ring = gb_alloc_item(heap_allocator(), TaskRingBuffer); ring->size = size; ring->buffer = gb_alloc_array(heap_allocator(), WorkerTask, ring->size); return ring; } -void thread_queue_destroy(TaskQueue *q) { +gb_internal void thread_queue_destroy(TaskQueue *q) { gb_free(heap_allocator(), (*q->ring).buffer); gb_free(heap_allocator(), q->ring); } +gb_internal void thread_init_arenas(Thread *t); + gb_internal void thread_init(ThreadPool *pool, Thread *t, isize idx) { gb_zero_item(t); #if defined(GB_SYSTEM_WINDOWS) @@ -584,6 +589,8 @@ gb_internal void thread_init(ThreadPool *pool, Thread *t, isize idx) { t->queue.ring = task_ring_init(1 << 14); t->pool = pool; t->idx = idx; + + thread_init_arenas(t); } gb_internal void thread_init_and_start(ThreadPool *pool, Thread *t, isize idx) { -- cgit v1.2.3 From cae8c1e94f6e3e899706972e2cd0ac1e2c912965 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 15 Jul 2024 01:15:00 +0100 Subject: Minimize use of mutex in `Arena` --- src/common_memory.cpp | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'src/common_memory.cpp') diff --git a/src/common_memory.cpp b/src/common_memory.cpp index 95803d3c8..bfe4c2e68 100644 --- a/src/common_memory.cpp +++ b/src/common_memory.cpp @@ -32,6 +32,8 @@ gb_internal void virtual_memory_init(void) { } +gb_internal Thread *get_current_thread(void); + struct MemoryBlock { MemoryBlock *prev; @@ -45,6 +47,7 @@ struct Arena { isize minimum_block_size; BlockingMutex mutex; isize temp_count; + Thread * parent_thread; }; enum { DEFAULT_MINIMUM_BLOCK_SIZE = 8ll*1024ll*1024ll }; @@ -70,6 +73,9 @@ gb_internal void thread_init_arenas(Thread *t) { t->permanent_arena = gb_alloc_item(heap_allocator(), Arena); t->temporary_arena = gb_alloc_item(heap_allocator(), Arena); + t->permanent_arena->parent_thread = t; + t->temporary_arena->parent_thread = t; + t->permanent_arena->minimum_block_size = DEFAULT_MINIMUM_BLOCK_SIZE; t->temporary_arena->minimum_block_size = DEFAULT_MINIMUM_BLOCK_SIZE; } @@ -77,7 +83,11 @@ gb_internal void thread_init_arenas(Thread *t) { gb_internal void *arena_alloc(Arena *arena, isize min_size, isize alignment) { GB_ASSERT(gb_is_power_of_two(alignment)); - mutex_lock(&arena->mutex); + if (arena->parent_thread == nullptr) { + mutex_lock(&arena->mutex); + } else { + GB_ASSERT(arena->parent_thread == get_current_thread()); + } isize size = 0; if (arena->curr_block != nullptr) { @@ -104,7 +114,9 @@ gb_internal void *arena_alloc(Arena *arena, isize min_size, isize alignment) { curr_block->used += size; GB_ASSERT(curr_block->used <= curr_block->size); - mutex_unlock(&arena->mutex); + if (arena->parent_thread == nullptr) { + mutex_unlock(&arena->mutex); + } // NOTE(bill): memory will be zeroed by default due to virtual memory return ptr; @@ -260,7 +272,7 @@ struct ArenaTemp { ArenaTemp arena_temp_begin(Arena *arena) { GB_ASSERT(arena); - MUTEX_GUARD(&arena->mutex); + GB_ASSERT(arena->parent_thread == get_current_thread()); ArenaTemp temp = {}; temp.arena = arena; @@ -275,7 +287,7 @@ ArenaTemp arena_temp_begin(Arena *arena) { void arena_temp_end(ArenaTemp const &temp) { GB_ASSERT(temp.arena); Arena *arena = temp.arena; - MUTEX_GUARD(&arena->mutex); + GB_ASSERT(arena->parent_thread == get_current_thread()); if (temp.block) { bool memory_block_found = false; @@ -311,7 +323,7 @@ void arena_temp_end(ArenaTemp const &temp) { void arena_temp_ignore(ArenaTemp const &temp) { GB_ASSERT(temp.arena); Arena *arena = temp.arena; - MUTEX_GUARD(&arena->mutex); + GB_ASSERT(arena->parent_thread == get_current_thread()); GB_ASSERT_MSG(arena->temp_count > 0, "double-use of arena_temp_end"); arena->temp_count -= 1; @@ -380,8 +392,6 @@ gb_global Arena default_permanent_arena = {nullptr, DEFAULT_MINIMUM_BLOCK_SIZE}; gb_global Arena default_temporary_arena = {nullptr, DEFAULT_MINIMUM_BLOCK_SIZE}; -gb_internal Thread *get_current_thread(void); - gb_internal Arena *get_arena(ThreadArenaKind kind) { Thread *t = get_current_thread(); switch (kind) { -- cgit v1.2.3 From a45e05bb180ad5ac3f9bc4199ebbf0b3bcadbf25 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 15 Jul 2024 01:36:54 +0100 Subject: Remove need for `BlockingMutex` in `Arena` --- src/common_memory.cpp | 15 +++------------ src/parser.cpp | 2 +- src/parser.hpp | 4 +--- 3 files changed, 5 insertions(+), 16 deletions(-) (limited to 'src/common_memory.cpp') diff --git a/src/common_memory.cpp b/src/common_memory.cpp index bfe4c2e68..47b2796a9 100644 --- a/src/common_memory.cpp +++ b/src/common_memory.cpp @@ -45,7 +45,7 @@ struct MemoryBlock { struct Arena { MemoryBlock * curr_block; isize minimum_block_size; - BlockingMutex mutex; + // BlockingMutex mutex; isize temp_count; Thread * parent_thread; }; @@ -82,12 +82,7 @@ gb_internal void thread_init_arenas(Thread *t) { gb_internal void *arena_alloc(Arena *arena, isize min_size, isize alignment) { GB_ASSERT(gb_is_power_of_two(alignment)); - - if (arena->parent_thread == nullptr) { - mutex_lock(&arena->mutex); - } else { - GB_ASSERT(arena->parent_thread == get_current_thread()); - } + GB_ASSERT(arena->parent_thread == get_current_thread()); isize size = 0; if (arena->curr_block != nullptr) { @@ -113,11 +108,7 @@ gb_internal void *arena_alloc(Arena *arena, isize min_size, isize alignment) { curr_block->used += size; GB_ASSERT(curr_block->used <= curr_block->size); - - if (arena->parent_thread == nullptr) { - mutex_unlock(&arena->mutex); - } - + // NOTE(bill): memory will be zeroed by default due to virtual memory return ptr; } diff --git a/src/parser.cpp b/src/parser.cpp index 02c37815b..5a3fc1634 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -118,7 +118,7 @@ gb_internal isize ast_node_size(AstKind kind) { gb_internal Ast *alloc_ast_node(AstFile *f, AstKind kind) { isize size = ast_node_size(kind); - Ast *node = cast(Ast *)arena_alloc(&global_thread_local_ast_arena, size, 16); + Ast *node = cast(Ast *)arena_alloc(get_arena(ThreadArena_Permanent), size, 16); node->kind = kind; node->file_id = f ? f->id : 0; diff --git a/src/parser.hpp b/src/parser.hpp index 451cdf53d..565a8e621 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -878,10 +878,8 @@ gb_internal gb_inline bool is_ast_when_stmt(Ast *node) { return node->kind == Ast_WhenStmt; } -gb_global gb_thread_local Arena global_thread_local_ast_arena = {}; - gb_internal gb_inline gbAllocator ast_allocator(AstFile *f) { - return arena_allocator(&global_thread_local_ast_arena); + return permanent_allocator(); } gb_internal Ast *alloc_ast_node(AstFile *f, AstKind kind); -- cgit v1.2.3