I think it's fixed now

This commit is contained in:
Musa Mahmood 2025-11-27 13:31:08 -05:00
parent a29b67e524
commit e2f0e71003
8 changed files with 88 additions and 39 deletions

View File

@ -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 <mutex> // #TODO: Replace with Mutex (see OS_Win32.cpp)
struct Arena_Table {
std::mutex mutex;
s32 in_flight_count[6];
Array<Arena*> free_table[6];
#if ARENA_DEBUG
Array<Arena*> 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);

View File

@ -4,64 +4,77 @@
// committed pages should be and a heuristic for maximum number of arenas waiting
// API in Arena.h
#include <mutex> // #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*> arena_free_table[6];
#if BUILD_DEBUG
global Array<Arena*> 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*> arena_free_table[6];
// #if BUILD_DEBUG
// global Array<Arena*> 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<std::mutex> lock(arena_table_mutex);
std::lock_guard<std::mutex> 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<std::mutex> 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<std::mutex> 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;
// }
}
*/
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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 () {

View File

@ -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;

View File

@ -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);