Add program base layer #1
@ -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);
|
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)
|
// 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);
|
Arena* next_arena (Arena_Reserve reserve_size);
|
||||||
void release_arena (Arena* arena, bool delete_extra_pages=true);
|
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_bootstrap_flag (Arena* arena);
|
||||||
void arena_set_secure_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_keeping_memory (Arena* arena); // just sets current point to arena_start
|
||||||
void arena_reset (Arena* arena); // frees excess pages
|
void arena_reset (Arena* arena); // frees excess pages
|
||||||
void arena_reset_overwriting_memory (Arena* arena, Memory_Wipe_Function wipe_function);
|
void arena_reset_overwriting_memory (Arena* arena, Memory_Wipe_Function wipe_function);
|
||||||
|
|||||||
@ -4,64 +4,77 @@
|
|||||||
// committed pages should be and a heuristic for maximum number of arenas waiting
|
// committed pages should be and a heuristic for maximum number of arenas waiting
|
||||||
|
|
||||||
// API in Arena.h
|
// API in Arena.h
|
||||||
#include <mutex> // #TODO: Replace with Mutex (see OS_Win32.cpp)
|
|
||||||
|
|
||||||
global b64 arena_tables_initialized = false;
|
global Arena_Table* arena_table;
|
||||||
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
|
|
||||||
|
|
||||||
void initialize_arena_table () {
|
// global b64 arena_tables_initialized = false;
|
||||||
// debug_break();
|
// 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) {
|
for (s32 i = 0; i < 6; i += 1) {
|
||||||
arena_free_table[i].allocator = GPAllocator();
|
arena_table->in_flight_count[i] = 0;
|
||||||
array_reserve(arena_free_table[i], 64);
|
arena_table->free_table[i].allocator = allocator;
|
||||||
#if BUILD_DEBUG
|
array_reserve(arena_table->free_table[i], 64);
|
||||||
arenas_in_flight[i].allocator = GPAllocator();
|
#if ARENA_DEBUG
|
||||||
array_reserve(arenas_in_flight[i], 64);
|
arena_table->in_flight[i].allocator = allocator;
|
||||||
|
array_reserve(arena_table->in_flight[i], 64);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
arena_tables_initialized = true;
|
arena_table->initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Arena* next_arena (Arena_Reserve reserve_size) {
|
Arena* next_arena (Arena_Reserve reserve_size) {
|
||||||
|
Assert(arena_table != nullptr);
|
||||||
Arena* arena;
|
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;
|
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);
|
arena = bootstrap_arena(reserve_size, ARENA_DEFAULT_COMMIT_PAGE_COUNT);
|
||||||
} else {
|
} else {
|
||||||
arena = pop(arena_free_table[reserve_index]);
|
arena = pop(arena_table->free_table[reserve_index]);
|
||||||
}
|
}
|
||||||
#if ARENA_DEBUG
|
#if ARENA_DEBUG
|
||||||
array_add(arenas_in_flight[reserve_index], arena);
|
array_add(arena_table->in_flight[reserve_index], arena);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
arena_table->in_flight_count[reserve_index] += 1;
|
||||||
|
|
||||||
Assert(arena != nullptr);
|
Assert(arena != nullptr);
|
||||||
|
|
||||||
return arena;
|
return arena;
|
||||||
}
|
}
|
||||||
|
|
||||||
void release_arena (Arena* arena, bool delete_extra_pages) {
|
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;
|
s64 reserve_index = (s64)arena->reserve_size;
|
||||||
|
|
||||||
#if ARENA_DEBUG
|
#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
|
#endif
|
||||||
arena_reset_keeping_memory(arena);
|
arena_reset_keeping_memory(arena);
|
||||||
if (delete_extra_pages) {
|
if (delete_extra_pages) {
|
||||||
free_pages_down_to(arena, arena->initial_commit_page_count);
|
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;
|
arena_table->in_flight_count[reserve_index] -= 1;
|
||||||
|
/*
|
||||||
// #garbage_collection
|
// #TODO #garbage_collection
|
||||||
if (arena_free_table[reserve_index].count > 64) {
|
if (arena_free_table[reserve_index].count > 64) {
|
||||||
// s64 arenas_to_delete_count = 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) {
|
// while (arenas_to_delete_count > 0) {
|
||||||
@ -70,4 +83,5 @@ void release_arena (Arena* arena, bool delete_extra_pages) {
|
|||||||
// arenas_to_delete_count -= 1;
|
// arenas_to_delete_count -= 1;
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,8 @@ void platform_init (Arena* arena, s64 new_reserve) {
|
|||||||
void* address_start =
|
void* address_start =
|
||||||
VirtualAlloc(nullptr, (u64)page_aligned_reserve_size, MEM_RESERVE, PAGE_READWRITE);
|
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) {
|
if (address_start == nullptr) {
|
||||||
s32 error_code = GetLastError();
|
s32 error_code = GetLastError();
|
||||||
printf("In Arena:platform_init, VirtualAlloc failed with code %d\n", error_code);
|
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);
|
s64 size = Align_To_Page_Size(delta);
|
||||||
|
|
||||||
VirtualAlloc(arena->first_uncommitted_page, (u64)size, MEM_COMMIT, PAGE_READWRITE);
|
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_lock_pages(arena, arena->first_uncommitted_page, size);
|
||||||
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);
|
u64 bytes_to_decommit = (u64)(arena->first_uncommitted_page - start_address);
|
||||||
// arena_unlock_pages(arena, start_address, (s64)bytes_to_decommit);
|
// 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;
|
arena->first_uncommitted_page = start_address;
|
||||||
}
|
}
|
||||||
@ -58,6 +64,9 @@ void arena_delete (Arena* arena) {
|
|||||||
|
|
||||||
VirtualFree(arena->memory_base, 0, MEM_RELEASE);
|
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) {
|
if (!arena_was_boostrapped) {
|
||||||
arena->memory_base = nullptr;
|
arena->memory_base = nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,8 +3,12 @@
|
|||||||
internal void Bootstrap_Main_Thread_Context () {
|
internal void Bootstrap_Main_Thread_Context () {
|
||||||
// 0. Setup general allocator
|
// 0. Setup general allocator
|
||||||
GPAllocator_Initialize_Allocation_Tracker();
|
GPAllocator_Initialize_Allocation_Tracker();
|
||||||
|
|
||||||
// 1. Setup arena table
|
// 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
|
// 2. Setup thread local context
|
||||||
ExpandableArena* arena_ex = expandable_arena_new(Arena_Reserve::Size_64M, 16);
|
ExpandableArena* arena_ex = expandable_arena_new(Arena_Reserve::Size_64M, 16);
|
||||||
|
|
||||||
|
|||||||
@ -45,7 +45,7 @@ void* expandable_arena_alloc (ExpandableArena* arena_ex, s64 byte_count) {
|
|||||||
Assert(arena_ex != nullptr);
|
Assert(arena_ex != nullptr);
|
||||||
Assert(arena_ex->memory_base != nullptr); // must be initialized before calling.
|
Assert(arena_ex->memory_base != nullptr); // must be initialized before calling.
|
||||||
Assert(is_valid(arena_ex));
|
Assert(is_valid(arena_ex));
|
||||||
Assert(arena_tables_initialized);
|
Assert(arena_table->initialized);
|
||||||
|
|
||||||
Arena* arena = (Arena*)arena_ex->current;
|
Arena* arena = (Arena*)arena_ex->current;
|
||||||
|
|
||||||
|
|||||||
@ -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
|
// _aligned_malloc does not zero memory, so we can zero it here
|
||||||
if (initialize && memory) { memset(memory, ALLOCATOR_INIT_VALUE, new_size); }
|
if (initialize && memory) { memset(memory, ALLOCATOR_INIT_VALUE, new_size); }
|
||||||
Add_Allocation(new_size, memory, (s32)alignment);
|
Add_Allocation(new_size, memory, (s32)alignment);
|
||||||
|
|
||||||
|
// printf("[GP] Allocating memory %p of size %llu\n", memory, new_size);
|
||||||
|
|
||||||
return memory;
|
return memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,6 +124,9 @@ void* GPAllocator_Resize (s64 old_size, void* old_memory, s64 new_size, s64 alig
|
|||||||
}
|
}
|
||||||
Remove_Allocation(old_memory);
|
Remove_Allocation(old_memory);
|
||||||
Add_Allocation(new_size, new_memory_address, (s32)alignment);
|
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;
|
return new_memory_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,6 +134,8 @@ void GPAllocator_Delete (void* memory) {
|
|||||||
if (memory == nullptr) return;
|
if (memory == nullptr) return;
|
||||||
Aligned_Free(memory);
|
Aligned_Free(memory);
|
||||||
Remove_Allocation(memory);
|
Remove_Allocation(memory);
|
||||||
|
|
||||||
|
// printf("[GP] Deleting memory %p\n", memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
Allocator GPAllocator () {
|
Allocator GPAllocator () {
|
||||||
|
|||||||
@ -99,8 +99,6 @@ internal void Win32_Entry_Point (int argc, WCHAR **argv) {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
Bootstrap_Main_Thread_Context();
|
|
||||||
|
|
||||||
push_arena(get_thread_context()->arena);
|
push_arena(get_thread_context()->arena);
|
||||||
|
|
||||||
{ OS_System_Info* info = &os_state_w32.system_info;
|
{ OS_System_Info* info = &os_state_w32.system_info;
|
||||||
|
|||||||
@ -3,15 +3,16 @@ internal void Main_Entry_Point (int argc, WCHAR **argv);
|
|||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
#if BUILD_CONSOLE_INTERFACE
|
#if BUILD_CONSOLE_INTERFACE
|
||||||
int wmain(int argc, WCHAR **argv) {
|
int wmain(int argc, WCHAR **argv) {
|
||||||
Win32_Entry_Point(argc, argv);
|
// debug_break();
|
||||||
// See: main_thread_base_entry_point
|
Bootstrap_Main_Thread_Context();
|
||||||
|
// Win32_Entry_Point(argc, argv); // This might be the problem.
|
||||||
Main_Entry_Point(argc, argv);
|
Main_Entry_Point(argc, argv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd) {
|
int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd) {
|
||||||
|
Bootstrap_Main_Thread_Context();
|
||||||
Win32_Entry_Point(__argc, __wargv);
|
Win32_Entry_Point(__argc, __wargv);
|
||||||
// See: main_thread_base_entry_point
|
|
||||||
Main_Entry_Point(__argc, __wargv);
|
Main_Entry_Point(__argc, __wargv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -188,6 +189,7 @@ void ImGui_Application () {
|
|||||||
string string_literal_example = "Hello, I am a string literal.";
|
string string_literal_example = "Hello, I am a string literal.";
|
||||||
|
|
||||||
internal void Main_Entry_Point (int argc, WCHAR **argv) {
|
internal void Main_Entry_Point (int argc, WCHAR **argv) {
|
||||||
|
// See: main_thread_base_entry_point
|
||||||
temp_reset();
|
temp_reset();
|
||||||
push_allocator(get_temp_allocator());
|
push_allocator(get_temp_allocator());
|
||||||
// tip: use auto_reset or auto_release with `get_thread_context()->arena`
|
// 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);
|
print_to_builder(sb, "the literal: %s", string_literal_example.data);
|
||||||
|
|
||||||
// string result = string_view(sb);
|
// 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);
|
// print((char*)result.data);
|
||||||
log("Hello.");
|
log("Hello.");
|
||||||
log("log() should automatically append newlines to these prints.");
|
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(result);
|
||||||
log("Hello. There are %s things here\n", string_literal_example.data);
|
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);
|
// free_string_builder(sb);
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user