diff --git a/lib/Base/Arena.h b/lib/Base/Arena.h index 4be8ef9..213e304 100644 --- a/lib/Base/Arena.h +++ b/lib/Base/Arena.h @@ -61,7 +61,19 @@ typedef void* (*Memory_Wipe_Function)(void* memory, u64 byte_count); void* arena_allocator_proc (Allocator_Mode mode, s64 requested_size, s64 old_size, void* old_memory, void* allocator_data); // Interface API for normal use (idk how to explain - see Arena_Table.cpp) -void initialize_arena_table (); +#include // #TODO: Replace with Mutex (see OS_Win32.cpp) +struct Arena_Table { + std::mutex mutex; + s32 in_flight_count[6]; + Array free_table[6]; + +#if ARENA_DEBUG + Array in_flight[6]; +#endif + b32 initialized; +}; + +void initialize_arena_table (Allocator allocator); Arena* next_arena (Arena_Reserve reserve_size); void release_arena (Arena* arena, bool delete_extra_pages=true); @@ -75,6 +87,8 @@ void arena_clear_flags (Arena* arena); void arena_set_bootstrap_flag (Arena* arena); void arena_set_secure_flag (Arena* arena); +bool arena_is_bootstrapped (Arena* arena); + void arena_reset_keeping_memory (Arena* arena); // just sets current point to arena_start void arena_reset (Arena* arena); // frees excess pages void arena_reset_overwriting_memory (Arena* arena, Memory_Wipe_Function wipe_function); diff --git a/lib/Base/Arena_Table.cpp b/lib/Base/Arena_Table.cpp index efa50d8..da70dd4 100644 --- a/lib/Base/Arena_Table.cpp +++ b/lib/Base/Arena_Table.cpp @@ -4,64 +4,77 @@ // committed pages should be and a heuristic for maximum number of arenas waiting // API in Arena.h -#include // #TODO: Replace with Mutex (see OS_Win32.cpp) -global b64 arena_tables_initialized = false; -global std::mutex arena_table_mutex; -global s32 arenas_in_flight_count[6]; -global Array arena_free_table[6]; -#if BUILD_DEBUG -global Array arenas_in_flight[6]; -#endif +global Arena_Table* arena_table; -void initialize_arena_table () { - // debug_break(); +// global b64 arena_tables_initialized = false; +// global std::mutex arena_table_mutex; +// global s32 arenas_in_flight_count[6]; +// global Array arena_free_table[6]; +// #if BUILD_DEBUG +// global Array arenas_in_flight[6]; +// #endif + +// Only call once from main thread! +void initialize_arena_table (Allocator allocator) { + Assert(arena_table != nullptr); + if (arena_table->initialized) + return; + for (s32 i = 0; i < 6; i += 1) { - arena_free_table[i].allocator = GPAllocator(); - array_reserve(arena_free_table[i], 64); -#if BUILD_DEBUG - arenas_in_flight[i].allocator = GPAllocator(); - array_reserve(arenas_in_flight[i], 64); + arena_table->in_flight_count[i] = 0; + arena_table->free_table[i].allocator = allocator; + array_reserve(arena_table->free_table[i], 64); +#if ARENA_DEBUG + arena_table->in_flight[i].allocator = allocator; + array_reserve(arena_table->in_flight[i], 64); #endif } - arena_tables_initialized = true; + arena_table->initialized = true; } Arena* next_arena (Arena_Reserve reserve_size) { + Assert(arena_table != nullptr); Arena* arena; - std::lock_guard lock(arena_table_mutex); + std::lock_guard lock(arena_table->mutex); s64 reserve_index = (s64)reserve_size; - arenas_in_flight_count[reserve_index] += 1; - if (!arena_free_table[reserve_index].count) { + + if (!arena_table->free_table[reserve_index].count) { arena = bootstrap_arena(reserve_size, ARENA_DEFAULT_COMMIT_PAGE_COUNT); } else { - arena = pop(arena_free_table[reserve_index]); + arena = pop(arena_table->free_table[reserve_index]); } #if ARENA_DEBUG - array_add(arenas_in_flight[reserve_index], arena); + array_add(arena_table->in_flight[reserve_index], arena); #endif + arena_table->in_flight_count[reserve_index] += 1; + Assert(arena != nullptr); - return arena; } void release_arena (Arena* arena, bool delete_extra_pages) { - std::lock_guard lock(arena_table_mutex); + Assert(arena_table != nullptr); + Assert(arena != nullptr); + Assert(arena_is_bootstrapped(arena)); + // Only put into free table if arena is bootstrapped? + std::lock_guard lock(arena_table->mutex); s64 reserve_index = (s64)arena->reserve_size; + #if ARENA_DEBUG - array_unordered_remove_by_value(arenas_in_flight[reserve_index], arena, 1); + array_unordered_remove_by_value(arena_table->in_flight[reserve_index], arena, 1); // BUILD_DEBUG! #endif arena_reset_keeping_memory(arena); if (delete_extra_pages) { free_pages_down_to(arena, arena->initial_commit_page_count); } - array_add(arena_free_table[reserve_index], arena); + array_add(arena_table->free_table[reserve_index], arena); - arenas_in_flight_count[reserve_index] -= 1; - - // #garbage_collection + arena_table->in_flight_count[reserve_index] -= 1; + /* + // #TODO #garbage_collection if (arena_free_table[reserve_index].count > 64) { // s64 arenas_to_delete_count = arena_free_table[reserve_index].count - 64. // while (arenas_to_delete_count > 0) { @@ -70,4 +83,5 @@ void release_arena (Arena* arena, bool delete_extra_pages) { // arenas_to_delete_count -= 1; // } } + */ } diff --git a/lib/Base/Arena_Windows.cpp b/lib/Base/Arena_Windows.cpp index ae92b64..002312c 100644 --- a/lib/Base/Arena_Windows.cpp +++ b/lib/Base/Arena_Windows.cpp @@ -8,6 +8,8 @@ void platform_init (Arena* arena, s64 new_reserve) { void* address_start = VirtualAlloc(nullptr, (u64)page_aligned_reserve_size, MEM_RESERVE, PAGE_READWRITE); + // printf("Reserving range %p:%p (size: %llu)\n", address_start, (u8*)address_start + page_aligned_reserve_size, page_aligned_reserve_size); + if (address_start == nullptr) { s32 error_code = GetLastError(); printf("In Arena:platform_init, VirtualAlloc failed with code %d\n", error_code); @@ -24,6 +26,7 @@ void extend_committed_pages (Arena* arena, u8* end) { s64 size = Align_To_Page_Size(delta); VirtualAlloc(arena->first_uncommitted_page, (u64)size, MEM_COMMIT, PAGE_READWRITE); + // printf("Committing range %p:%p (size: %llu)\n", arena->first_uncommitted_page, (u8*)arena->first_uncommitted_page + size, size); // arena_lock_pages(arena, arena->first_uncommitted_page, size); arena->first_uncommitted_page += size; @@ -47,7 +50,10 @@ void free_pages_down_to (Arena* arena, s64 pages_to_keep) { u64 bytes_to_decommit = (u64)(arena->first_uncommitted_page - start_address); // arena_unlock_pages(arena, start_address, (s64)bytes_to_decommit); - VirtualFree(start_address, bytes_to_decommit, MEM_DECOMMIT); + if (bytes_to_decommit) { + VirtualFree(start_address, bytes_to_decommit, MEM_DECOMMIT); + // printf("Freeing pages %p:%p (size: %llu)\n", start_address, (u8*)start_address + bytes_to_decommit, bytes_to_decommit); + } arena->first_uncommitted_page = start_address; } @@ -58,6 +64,9 @@ void arena_delete (Arena* arena) { VirtualFree(arena->memory_base, 0, MEM_RELEASE); + s64 size_tmp = reserve_size(arena); + // printf("Releasing range %p:%p (size: %llu)\n", arena->memory_base, (u8*)arena->memory_base + size_tmp, size_tmp); + if (!arena_was_boostrapped) { arena->memory_base = nullptr; } diff --git a/lib/Base/Base_Thread_Context.cpp b/lib/Base/Base_Thread_Context.cpp index b183daa..1a0a03e 100644 --- a/lib/Base/Base_Thread_Context.cpp +++ b/lib/Base/Base_Thread_Context.cpp @@ -3,8 +3,12 @@ internal void Bootstrap_Main_Thread_Context () { // 0. Setup general allocator GPAllocator_Initialize_Allocation_Tracker(); + // 1. Setup arena table - initialize_arena_table(); + arena_table = (Arena_Table*)GPAllocator_New(sizeof(Arena_Table), 64, true); // permanent allocation. + memset(arena_table, 0, sizeof(Arena_Table)); + initialize_arena_table(GPAllocator()); + // 2. Setup thread local context ExpandableArena* arena_ex = expandable_arena_new(Arena_Reserve::Size_64M, 16); diff --git a/lib/Base/Expandable_Arena.cpp b/lib/Base/Expandable_Arena.cpp index 3d558ef..787d8ed 100644 --- a/lib/Base/Expandable_Arena.cpp +++ b/lib/Base/Expandable_Arena.cpp @@ -45,7 +45,7 @@ void* expandable_arena_alloc (ExpandableArena* arena_ex, s64 byte_count) { Assert(arena_ex != nullptr); Assert(arena_ex->memory_base != nullptr); // must be initialized before calling. Assert(is_valid(arena_ex)); - Assert(arena_tables_initialized); + Assert(arena_table->initialized); Arena* arena = (Arena*)arena_ex->current; diff --git a/lib/Base/General_Purpose_Allocator.cpp b/lib/Base/General_Purpose_Allocator.cpp index da378c2..d3a13cc 100644 --- a/lib/Base/General_Purpose_Allocator.cpp +++ b/lib/Base/General_Purpose_Allocator.cpp @@ -103,6 +103,9 @@ void* GPAllocator_New (s64 new_size, s64 alignment, bool initialize) { // _aligned_malloc does not zero memory, so we can zero it here if (initialize && memory) { memset(memory, ALLOCATOR_INIT_VALUE, new_size); } Add_Allocation(new_size, memory, (s32)alignment); + + // printf("[GP] Allocating memory %p of size %llu\n", memory, new_size); + return memory; } @@ -121,6 +124,9 @@ void* GPAllocator_Resize (s64 old_size, void* old_memory, s64 new_size, s64 alig } Remove_Allocation(old_memory); Add_Allocation(new_size, new_memory_address, (s32)alignment); + + // printf("[GP] Rellocating memory %p of size %llu\n", new_memory_address, new_size); + return new_memory_address; } @@ -128,6 +134,8 @@ void GPAllocator_Delete (void* memory) { if (memory == nullptr) return; Aligned_Free(memory); Remove_Allocation(memory); + + // printf("[GP] Deleting memory %p\n", memory); } Allocator GPAllocator () { diff --git a/lib/OS/OS_Win32.cpp b/lib/OS/OS_Win32.cpp index 42d91d6..761e6a6 100644 --- a/lib/OS/OS_Win32.cpp +++ b/lib/OS/OS_Win32.cpp @@ -99,8 +99,6 @@ internal void Win32_Entry_Point (int argc, WCHAR **argv) { // } // } - Bootstrap_Main_Thread_Context(); - push_arena(get_thread_context()->arena); { OS_System_Info* info = &os_state_w32.system_info; diff --git a/src/Base_Entry_Point.cpp b/src/Base_Entry_Point.cpp index d4b7a7f..95d7f9a 100644 --- a/src/Base_Entry_Point.cpp +++ b/src/Base_Entry_Point.cpp @@ -3,15 +3,16 @@ internal void Main_Entry_Point (int argc, WCHAR **argv); #if OS_WINDOWS #if BUILD_CONSOLE_INTERFACE int wmain(int argc, WCHAR **argv) { - Win32_Entry_Point(argc, argv); - // See: main_thread_base_entry_point + // debug_break(); + Bootstrap_Main_Thread_Context(); + // Win32_Entry_Point(argc, argv); // This might be the problem. Main_Entry_Point(argc, argv); return 0; } #else int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd) { + Bootstrap_Main_Thread_Context(); Win32_Entry_Point(__argc, __wargv); - // See: main_thread_base_entry_point Main_Entry_Point(__argc, __wargv); return 0; } @@ -188,6 +189,7 @@ void ImGui_Application () { string string_literal_example = "Hello, I am a string literal."; internal void Main_Entry_Point (int argc, WCHAR **argv) { + // See: main_thread_base_entry_point temp_reset(); push_allocator(get_temp_allocator()); // tip: use auto_reset or auto_release with `get_thread_context()->arena` @@ -207,7 +209,7 @@ internal void Main_Entry_Point (int argc, WCHAR **argv) { print_to_builder(sb, "the literal: %s", string_literal_example.data); // string result = string_view(sb); - auto result = builder_to_string(sb); // also frees + string result = builder_to_string(sb); // also frees // print((char*)result.data); log("Hello."); log("log() should automatically append newlines to these prints."); @@ -215,7 +217,7 @@ internal void Main_Entry_Point (int argc, WCHAR **argv) { log(result); log("Hello. There are %s things here\n", string_literal_example.data); - print("Hello, I am just a printed message to stdout"); + print("Hello, I am just a printed message to stdout\n\n"); // free_string_builder(sb);