Lots of small changes
This commit is contained in:
parent
6970a59c35
commit
619cd76ea9
@ -1,7 +1,7 @@
|
||||
#include "lib_main.cpp"
|
||||
|
||||
// Toggles:
|
||||
#define BASE_RUN_TESTS 1
|
||||
#define BASE_RUN_TESTS 0
|
||||
#define BUILD_EXPLORER_APP_WIN32 1
|
||||
#define BUILD_CUSTOM_GUI 0
|
||||
|
||||
|
||||
@ -180,17 +180,8 @@ s64 reserve_size (Arena_Reserve ar) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
constexpr s64 Arena_Sizes[6] = {
|
||||
64LL * 1024,
|
||||
2LL * 1024 * 1024,
|
||||
64LL * 1024 * 1024,
|
||||
2LL * 1024 * 1024 * 1024,
|
||||
64LL * 1024 * 1024 * 1024,
|
||||
2LL * 1024 * 1024 * 1024 * 1024,
|
||||
};
|
||||
|
||||
Arena_Reserve next_reserve_size (s64 size) {
|
||||
for (u8 i = 0; i < 6; i += 1) {
|
||||
for (u8 i = 0; i < Arena_Reserve_Count; i += 1) {
|
||||
if (size <= Arena_Sizes[i]) {
|
||||
return (Arena_Reserve)i;
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ constexpr u16 ARENA_DEFAULT_ALIGNMENT = CPU_REGISTER_WIDTH_BYTES;
|
||||
|
||||
#define ARENA_DEBUG BUILD_DEBUG
|
||||
|
||||
constexpr s32 Arena_Reserve_Count = 7;
|
||||
enum class Arena_Reserve: u8 {
|
||||
Size_64K = 0, // these are used as indices in Arena_Free_List!
|
||||
Size_2M = 1,
|
||||
@ -21,6 +22,16 @@ enum class Arena_Reserve: u8 {
|
||||
Size_64T = 6,
|
||||
};
|
||||
|
||||
constexpr s64 Arena_Sizes[Arena_Reserve_Count] = {
|
||||
64LL * 1024,
|
||||
2LL * 1024 * 1024,
|
||||
64LL * 1024 * 1024,
|
||||
2LL * 1024 * 1024 * 1024,
|
||||
64LL * 1024 * 1024 * 1024,
|
||||
2LL * 1024 * 1024 * 1024 * 1024,
|
||||
64LL * 1024 * 1024 * 1024 * 1024,
|
||||
};
|
||||
|
||||
enum class Arena_Flags: u8 {
|
||||
None = 0,
|
||||
Chained = 0x01,
|
||||
@ -61,18 +72,8 @@ 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_Free_List.cpp)
|
||||
struct Arena_Free_List {
|
||||
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);
|
||||
void initialize_arena_free_list (Allocator allocator);
|
||||
Arena* next_arena (Arena_Reserve reserve_size);
|
||||
void release_arena (Arena* arena, bool delete_extra_pages=true);
|
||||
|
||||
|
||||
@ -3,6 +3,17 @@
|
||||
// There should be some parameters regarding what the upper limit for idle
|
||||
// committed pages should be and a heuristic for maximum number of arenas waiting
|
||||
|
||||
struct Arena_Free_List {
|
||||
Mutex mutex;
|
||||
s32 in_flight_count[Arena_Reserve_Count];
|
||||
Array<Arena*> free_table[Arena_Reserve_Count];
|
||||
|
||||
#if ARENA_DEBUG
|
||||
Array<Arena*> in_flight[Arena_Reserve_Count];
|
||||
#endif
|
||||
b32 initialized;
|
||||
};
|
||||
|
||||
global Arena_Free_List* arena_free_list;
|
||||
|
||||
// Only call once from main thread!
|
||||
@ -12,7 +23,7 @@ void initialize_arena_free_list (Allocator allocator) {
|
||||
if (arena_free_list->initialized)
|
||||
return;
|
||||
|
||||
for (s32 i = 0; i < 6; i += 1) {
|
||||
for (s32 i = 0; i < Arena_Reserve_Count; i += 1) {
|
||||
arena_free_list->in_flight_count[i] = 0;
|
||||
arena_free_list->free_table[i].allocator = allocator;
|
||||
array_reserve(arena_free_list->free_table[i], 64);
|
||||
@ -75,5 +86,14 @@ void release_arena (Arena* arena, bool delete_extra_pages) {
|
||||
// arenas_to_delete_count -= 1;
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
s64 committed_bytes (ArrayView<Arena*> arenas) {
|
||||
s64 sum = 0;
|
||||
|
||||
for (s64 i = 0; i < arenas.count; i += 1) {
|
||||
sum += arena_usage_committed_bytes(arenas[i]);
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
@ -62,14 +62,14 @@ void arena_delete (Arena* arena) {
|
||||
if (!is_valid(arena)) return;
|
||||
bool arena_was_boostrapped = (arena->flags & Arena_Flags::Is_Bootstrapped) == Arena_Flags::Is_Bootstrapped;
|
||||
|
||||
VirtualFree(arena->memory_base, 0, MEM_RELEASE);
|
||||
|
||||
s64 size_tmp = reserve_size(arena);
|
||||
// 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;
|
||||
}
|
||||
|
||||
VirtualFree(arena->memory_base, 0, MEM_RELEASE);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -190,7 +190,7 @@ void array_add (Array<T>& src, T new_item) {
|
||||
|
||||
template <typename T>
|
||||
s64 array_find (Array<T>& src, T item) {
|
||||
ForArray(i, src) {
|
||||
for (s64 i = 0; i < src.count; i += 1) {
|
||||
if (src[i] == item) return i;
|
||||
}
|
||||
return -1;
|
||||
|
||||
@ -169,12 +169,6 @@ force_inline s64 Next_Power_Of_Two(s64 v) {
|
||||
#define MSVC_RUNTIME_CHECKS_RESTORE
|
||||
#endif
|
||||
|
||||
// ForExpansions. Not sure if this is a good idea...
|
||||
// ↓TODO(Low priority): Maybe remove these. I prefer verbose and clear over this.
|
||||
#define ForArray(_idx_, _array_) for (s64 _idx_ = 0; _idx_ < (_array_).count; ++_idx_)
|
||||
#define ForArrayStartingAt(_it_, _array_, _start_) for (s64 _it_ = _start_; _it_ < (_array_).count; _it_ += 1)
|
||||
#define ForUpTo(_it_, _end_) for (s64 _it_ = 0; _it_ < _end_; _it_ += 1)
|
||||
|
||||
// Scoped Macros/Functions for auto_reset and auto_release
|
||||
// usage `Auto_Reset guard(arena);` within a scope.
|
||||
#define auto_reset(x) \
|
||||
@ -324,3 +318,11 @@ struct Mutex_Lock_Guard {
|
||||
}
|
||||
};
|
||||
|
||||
// Helper macros for raw arrays:
|
||||
#define ArrayCount(array) sizeof(array) / sizeof(array[0])
|
||||
// For-loop construct macros
|
||||
#define for_each_index(_idx_, _until_) for (s64 _idx_ = 0; _idx_ < _until_; ++_idx_)
|
||||
// For-loops for ArrayView<> compatible types
|
||||
#define for_each(_idx_, _array_) for (s64 _idx_ = 0; _idx_ < (_array_).count; ++_idx_)
|
||||
// #define for_each_starting_at(_it_, _array_, _start_) for (s64 _it_ = _start_; _it_ < (_array_).count; _it_ += 1)
|
||||
|
||||
|
||||
@ -1,6 +1,30 @@
|
||||
// #NOTE: This Hash Table is borrowed from Jai's implementation! (With some tweaks)
|
||||
// I made my own version that's arena-backed, but the mechanisms are the same.
|
||||
|
||||
// s32 drive_count = 0;
|
||||
// for (s64 i = 0; i < drive_table->allocated; i += 1) {
|
||||
// Table_Entry<string, OS_Drive>* entry = &drive_table->entries[i]; // we should take ptr here if we want to modify?
|
||||
// if (entry->hash > HASH_TABLE_FIRST_VALID_HASH) {
|
||||
// // #TODO #MOVE THIS + maybe don't check this every frame!
|
||||
// // entry->value.is_present = Win32_Drive_Exists(entry->value.label);
|
||||
// if (entry->value.label.data == nullptr) continue;
|
||||
|
||||
// Text(" > [%d] drive letter: %s (is_present: %d)", drive_count + 1, entry->value.label.data, entry->value.is_present);
|
||||
// drive_count += 1;
|
||||
// SameLine();
|
||||
// push_allocator(temp());
|
||||
|
||||
// if (Button(format_cstring("Read NTFS MFT Raw##%s", entry->value.label.data))) {
|
||||
// push_arena(thread_context()->arena);
|
||||
// // auto_release(thread_context()->arena);
|
||||
// auto dfs = NTFS_MFT_read_raw(entry->value.label);
|
||||
// if (dfs == nullptr) {
|
||||
// log("[NTFS_MFT_read_raw] operation failed");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
typedef u32 hash_result;
|
||||
|
||||
constexpr hash_result HASH_TABLE_FIRST_VALID_HASH = 2;
|
||||
|
||||
@ -282,3 +282,6 @@ string to_lower_copy (string s_orig) {
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
#define format_cstring(fmt, ...) \
|
||||
(char*)format_string(fmt, ##__VA_ARGS__).data
|
||||
@ -117,7 +117,7 @@ s64 thread_group_run (Thread* thread) {
|
||||
|
||||
|
||||
// Thread_Group API:
|
||||
void init (Thread_Group* group, s32 group_thread_count, Thread_Group_Proc group_proc,
|
||||
void thread_group_init (Thread_Group* group, s32 group_thread_count, Thread_Group_Proc group_proc,
|
||||
bool enable_work_stealing = false) {
|
||||
// Set allocator if not already set:
|
||||
if (!group->allocator.proc) {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// really hacky forward declares.
|
||||
// really #hacky forward declares.
|
||||
struct Work_Entry;
|
||||
struct Worker_Info;
|
||||
struct Work_List;
|
||||
|
||||
@ -69,7 +69,7 @@ string format_cycles (u64 ticks) {
|
||||
return format_string("%1.2f %s", count_f64, units[unit_index].data);
|
||||
}
|
||||
|
||||
string format_bytes (s64 bytes) {
|
||||
string format_bytes (s64 bytes, s32 trailing_width = 3) {
|
||||
string units[6] = { "B", "KB", "MB", "GB", "TB", "PB" };
|
||||
f64 count_f64 = (f64)bytes;
|
||||
s32 unit_index = 0;
|
||||
@ -79,7 +79,16 @@ string format_bytes (s64 bytes) {
|
||||
unit_index += 1;
|
||||
}
|
||||
|
||||
return format_string("%1.3f %s", count_f64, units[unit_index].data);
|
||||
switch (trailing_width) {
|
||||
case 0: return format_string("%.0f %s", count_f64, units[unit_index].data);
|
||||
case 1: return format_string("%.1f %s", count_f64, units[unit_index].data);
|
||||
case 2: return format_string("%.2f %s", count_f64, units[unit_index].data);
|
||||
case 3: return format_string("%.3f %s", count_f64, units[unit_index].data);
|
||||
default: break;
|
||||
}
|
||||
Assert(trailing_width >= 0 && trailing_width <= 3);
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
struct timed_block_print {
|
||||
|
||||
@ -6,8 +6,7 @@ void run_pre_setup_tests() {
|
||||
|
||||
string string_literal_example = "Hello, I am a string literal.";
|
||||
void run_post_setup_tests() {
|
||||
debug_break();
|
||||
log_warning("Hello, I am a warning :), and I am a big number: %lld", (s64)293509357);
|
||||
log_warning("Hello, I am a warning :), and I am a big number: %lld", (s64)2935088889357);
|
||||
log_error("Hello, I am an error - %s", "I'm another string");
|
||||
log_error("This is an error");
|
||||
printf("Running post-setup tests...\n");
|
||||
@ -40,7 +39,6 @@ void run_post_setup_tests() {
|
||||
|
||||
print("Hello, I am just a printed message to stdout\n\n");
|
||||
|
||||
|
||||
// Testing file writes and reads:
|
||||
print("Writing some nonsense to a file.\n");
|
||||
bool success = write_entire_file("D:/TempLocal/junk.txt", to_view(result));
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
// #TODO: #OS_Win32
|
||||
// [ ] #Thread cleanup: in `thread_deinit` is there any requirement to cleanup child threads?
|
||||
// [ ] #Exception handling code in `Win32_Exception_Filter`
|
||||
// [ ] #cpuid - enumerate CPUs and Thread count (current implementation doesn't work)
|
||||
// [~] #Thread cleanup: in `thread_deinit` is there any requirement to cleanup child threads?
|
||||
// - I think no? Threads should handle their own lifetimes, and the parent threads should ensure child threads are complete
|
||||
// before terminating.
|
||||
|
||||
#if OS_WINDOWS
|
||||
constexpr s64 FILETIME_TO_UNIX = 116444736000000000i64;
|
||||
@ -26,6 +27,7 @@ s64 GetUnixTimestampNanoseconds () {
|
||||
#endif
|
||||
|
||||
struct OS_System_Info {
|
||||
// #cpuid
|
||||
s32 logical_processor_count;
|
||||
s32 physical_core_count;
|
||||
s32 primary_core_count;
|
||||
@ -40,7 +42,9 @@ struct OS_System_Info {
|
||||
Array<Monitor> monitors; // Back with GPAllocator
|
||||
|
||||
// #Drives
|
||||
Table<string, Win32_Drive> drives;
|
||||
Table<string, OS_Drive> drives; // should we just store ptrs to OS_Drive? I think so..
|
||||
// That way we can fetch the OS_Drive* and have the pointer be stable. Especially if it's b
|
||||
// backed by an arena.
|
||||
};
|
||||
|
||||
struct OS_Process_Info {
|
||||
@ -126,7 +130,7 @@ internal void Win32_Entry_Point (int argc, WCHAR **argv) {
|
||||
info->process_id = GetCurrentProcessId();
|
||||
}
|
||||
// #cpuid
|
||||
/*{ OS_System_Info* info = &global_win32_state.system_info;
|
||||
{ OS_System_Info* info = &global_win32_state.system_info;
|
||||
// [ ] Extract input args
|
||||
u32 length;
|
||||
GetLogicalProcessorInformationEx(RelationProcessorCore, nullptr, (PDWORD)&length);
|
||||
@ -136,7 +140,8 @@ internal void Win32_Entry_Point (int argc, WCHAR **argv) {
|
||||
|
||||
u32 offset = 0;
|
||||
|
||||
u32 all_cpus_count = 0;
|
||||
u32 all_cpus_count = 0; // all logical cpus
|
||||
u32 physical_cpu_count = 0;
|
||||
u32 max_performance = 0;
|
||||
u32 performance_core_count = 0;
|
||||
// u32 efficient_core_count;
|
||||
@ -159,14 +164,15 @@ internal void Win32_Entry_Point (int argc, WCHAR **argv) {
|
||||
performance_core_count += count_per_group_physical;
|
||||
}
|
||||
|
||||
physical_cpu_count += count_per_group_physical;
|
||||
all_cpus_count += count_per_group;
|
||||
}
|
||||
|
||||
info->physical_core_count = (s32)all_cpus_count;
|
||||
info->physical_core_count = (s32)physical_cpu_count;
|
||||
info->primary_core_count = (s32)performance_core_count;
|
||||
info->secondary_core_count = info->physical_core_count - info->primary_core_count;
|
||||
}
|
||||
// info->secondary_core_count = ;
|
||||
*/
|
||||
|
||||
{ OS_System_Info* info = &global_win32_state.system_info;
|
||||
info->monitors.allocator = GPAllocator();
|
||||
u8 buffer[MAX_COMPUTERNAME_LENGTH + 1] = {0};
|
||||
@ -209,6 +215,8 @@ C_LINKAGE DWORD OS_Windows_Thread_Entry_Point (void* parameter) {
|
||||
}
|
||||
|
||||
// Individual Thread API
|
||||
#define thread_task(T) (T*)thread->data;
|
||||
|
||||
internal bool thread_init (Thread* thread, Thread_Proc proc, string thread_name="") {
|
||||
Assert(thread != nullptr && proc != nullptr);
|
||||
|
||||
@ -234,6 +242,7 @@ internal bool thread_init (Thread* thread, Thread_Proc proc, string thread_name=
|
||||
thread->context->thread_name = copy_string(thread_name);
|
||||
thread->context->log_builder = new_string_builder(Arena_Reserve::Size_64M);
|
||||
thread->context->error_arena = next_arena(Arena_Reserve::Size_64M);
|
||||
thread->context->logger = {default_logger_proc, &default_logger};
|
||||
|
||||
thread->os_thread.windows_thread = windows_thread;
|
||||
thread->os_thread.windows_thread_id = windows_thread_id;
|
||||
@ -244,20 +253,24 @@ internal bool thread_init (Thread* thread, Thread_Proc proc, string thread_name=
|
||||
return true;
|
||||
}
|
||||
|
||||
internal void thread_deinit (Thread* thread) {
|
||||
internal void thread_deinit (Thread* thread, bool zero_thread=false) {
|
||||
if (thread->os_thread.windows_thread) {
|
||||
CloseHandle(thread->os_thread.windows_thread);
|
||||
}
|
||||
thread->os_thread.windows_thread = nullptr;
|
||||
|
||||
arena_delete(thread->context->temp);
|
||||
arena_delete(thread->context->arena);
|
||||
// #TODO: before releasing arena, force-delete extra pages?
|
||||
// array_reset(*thread->context->log_builder);
|
||||
free_string_builder(thread->context->log_builder);
|
||||
release_arena(thread->context->error_arena);
|
||||
arena_delete(thread->context->temp);
|
||||
arena_delete(thread->context->arena); // must come last because thread->context is allocated with this arena!
|
||||
|
||||
// memset(thread, 0xCD, sizeof(Thread);
|
||||
if (zero_thread) memset(thread, 0, sizeof(Thread));
|
||||
}
|
||||
|
||||
internal void thread_start (Thread* thread) {
|
||||
internal void thread_start (Thread* thread, void* thread_data = nullptr) {
|
||||
if (thread_data) thread->data = thread_data;
|
||||
ResumeThread(thread->os_thread.windows_thread);
|
||||
}
|
||||
|
||||
@ -899,6 +912,26 @@ bool os_main_window_is_minimized () {
|
||||
return os_window_is_minimized(get_main_window().window);
|
||||
}
|
||||
|
||||
s32 os_cpu_logical_core_count () {
|
||||
OS_System_Info* info = &global_win32_state.system_info;
|
||||
return info->logical_processor_count;
|
||||
}
|
||||
|
||||
s32 os_cpu_physical_core_count () {
|
||||
OS_System_Info* info = &global_win32_state.system_info;
|
||||
return info->physical_core_count;
|
||||
}
|
||||
|
||||
s32 os_cpu_primary_core_count () {
|
||||
OS_System_Info* info = &global_win32_state.system_info;
|
||||
return info->primary_core_count;
|
||||
}
|
||||
|
||||
s32 os_cpu_secondary_core_count () {
|
||||
OS_System_Info* info = &global_win32_state.system_info;
|
||||
return info->secondary_core_count;
|
||||
}
|
||||
|
||||
// #Drives
|
||||
constexpr u64 Win32_Max_Path_Length = 260;
|
||||
bool Win32_Discover_Drives () {
|
||||
|
||||
@ -167,6 +167,7 @@ File_System Win32_filesystem_from_string (string s) {
|
||||
}
|
||||
struct Dense_FS; // #Temp forward declare!
|
||||
struct Win32_Drive {
|
||||
// Arena* pool;
|
||||
string label;
|
||||
string volume_name;
|
||||
Win32_Drive_Type type;
|
||||
|
||||
@ -294,14 +294,24 @@ Dense_FS* NTFS_MFT_read_raw (string drive_path) {
|
||||
log("Found %lld files (bytes_accessed: %s)", mft->file_count, format_bytes(mft->bytes_accessed).data);
|
||||
|
||||
CloseHandle(file_handle);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
// Version where we transform the format so it's optimal for sorting and searching:
|
||||
// bool NTFS_MFT_read_and_convert () { // pass the structure we want to read into!
|
||||
// auto_release_temp();
|
||||
|
||||
// push_allocator(temp());
|
||||
// NTFS_MFT_Internal* mft = new_ntfs_drive();
|
||||
struct NTFS_Enumeration_Task {
|
||||
Arena* pool; // small arena just for results
|
||||
OS_Drive* drive;
|
||||
string drive_path; // The drive path we want to enumerate
|
||||
};
|
||||
|
||||
s64 ntfs_enumeration_thread_proc (Thread* thread) {
|
||||
auto task = thread_task(NTFS_Enumeration_Task);
|
||||
|
||||
// }
|
||||
log("(Thread index: %lld) Task pointer: %p", thread->index, task);
|
||||
|
||||
// NTFS_MFT_read_raw|#TODO:
|
||||
|
||||
Sleep(100); // #temp
|
||||
|
||||
return 0;
|
||||
}
|
||||
144
src/Ex1.cpp
144
src/Ex1.cpp
@ -11,9 +11,16 @@ struct Explorer {
|
||||
// Array<Image_Data> frame_textures;
|
||||
};
|
||||
|
||||
struct Ex1_NTFS_Enumeration {
|
||||
bool initialized;
|
||||
ArrayView<Thread> threads;
|
||||
Array<Thread*> threads_in_flight;
|
||||
};
|
||||
|
||||
// #Ex1_global_state
|
||||
global ExplorerUI explorer_ui;
|
||||
global Explorer explorer;
|
||||
global Ex1_NTFS_Enumeration ex1_ntfs;
|
||||
|
||||
#define HOTKEY_ID_BRING_TO_FOREGROUND 1
|
||||
#define VK_SPACE_KEY_CODE 0x20
|
||||
@ -39,19 +46,144 @@ bool Ex1_Register_Global_Hotkeys () {
|
||||
#define TRIGGER_EVERY_FRAME false
|
||||
#define KEY_UNUSED false
|
||||
|
||||
// #global_hotkeys - should rename to 'generic program hotkeys'
|
||||
global Key_Combination global_exit_hotkey { ImGuiKey_W, USE_CTRL, USE_SHIFT, KEY_UNUSED, TRIGGER_ONCE };
|
||||
global Key_Combination global_minimize_hotkey { ImGuiKey_W, USE_CTRL, KEY_UNUSED, KEY_UNUSED, TRIGGER_ONCE };
|
||||
// #program_hotkeys (Not specific to Ex1)
|
||||
global Key_Combination program_exit_hotkey { ImGuiKey_W, USE_CTRL, USE_SHIFT, KEY_UNUSED, TRIGGER_ONCE };
|
||||
global Key_Combination program_minimize_hotkey { ImGuiKey_W, USE_CTRL, KEY_UNUSED, KEY_UNUSED, TRIGGER_ONCE };
|
||||
|
||||
bool Ex1_check_key_combinations() {
|
||||
update_global_keyboard_state();
|
||||
// #global_hotkeys
|
||||
if (check_key_combination(&global_exit_hotkey)) {
|
||||
// #program_hotkeys
|
||||
if (check_key_combination(&program_exit_hotkey)) {
|
||||
return true;
|
||||
}
|
||||
if (check_key_combination(&global_minimize_hotkey)) {
|
||||
if (check_key_combination(&program_minimize_hotkey)) {
|
||||
Win32_Minimize_Window_To_Tray(get_main_window_pointer());
|
||||
}
|
||||
// #Ex1_hotkeys
|
||||
return false;
|
||||
}
|
||||
|
||||
// #define drive_table() &global_win32_state.system_info.drives
|
||||
void Ex1_Control_Panel () { using namespace ImGui;
|
||||
Table<string, OS_Drive>* drive_table = &global_win32_state.system_info.drives;
|
||||
|
||||
Begin("Control Panel");
|
||||
if (Button("Discover drives") || !table_is_valid(drive_table)) {
|
||||
Win32_Discover_Drives();
|
||||
}
|
||||
|
||||
Text("drive_table is valid: %d", table_is_valid(drive_table));
|
||||
// Basic Hash Table iterator: #hash_table_iterator
|
||||
s32 drive_count = 0;
|
||||
for (s64 i = 0; i < drive_table->allocated; i += 1) {
|
||||
Table_Entry<string, OS_Drive>* entry = &drive_table->entries[i]; // we should take ptr here if we want to modify?
|
||||
if (entry->hash > HASH_TABLE_FIRST_VALID_HASH) {
|
||||
// #TODO #MOVE THIS + maybe don't check this every frame!
|
||||
// entry->value.is_present = Win32_Drive_Exists(entry->value.label);
|
||||
if (entry->value.label.data == nullptr) continue;
|
||||
|
||||
Text(" > [%d] drive letter: %s (is_present: %d)", drive_count + 1, entry->value.label.data, entry->value.is_present);
|
||||
drive_count += 1;
|
||||
SameLine();
|
||||
push_allocator(temp());
|
||||
|
||||
if (Button(format_cstring("Read NTFS MFT Raw##%s", entry->value.label.data))) {
|
||||
push_arena(thread_context()->arena);
|
||||
// auto_release(thread_context()->arena);
|
||||
auto dfs = NTFS_MFT_read_raw(entry->value.label);
|
||||
if (dfs == nullptr) {
|
||||
log("[NTFS_MFT_read_raw] operation failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (drive_count > 0) {
|
||||
if (!ex1_ntfs.initialized) { Timed_Block_Print("Thread initialization (ntfs)");
|
||||
push_allocator(GPAllocator());
|
||||
ex1_ntfs.initialized = true;
|
||||
s32 cpu_core_count = os_cpu_physical_core_count();
|
||||
ex1_ntfs.threads = ArrayView<Thread>(cpu_core_count);
|
||||
ex1_ntfs.threads_in_flight.allocator = GPAllocator();
|
||||
for_each(t, ex1_ntfs.threads) {
|
||||
string thread_name = format_string("ntfs_enumeration_thread#%d", t);
|
||||
bool success = thread_init(&ex1_ntfs.threads[t], ntfs_enumeration_thread_proc, thread_name);
|
||||
Assert(success);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (drive_count > 0 && ex1_ntfs.initialized && Button("Enumerate all NTFS drives")) {
|
||||
// if drive count exceeds the number of threads, we need to group them so each thread
|
||||
// can enumerate multiple drives.
|
||||
// We need to distribute the drives across our available threads:
|
||||
// see: #hash_table_iterator (what part of this can we macro out?):
|
||||
|
||||
if (drive_count > ex1_ntfs.threads.count) {
|
||||
debug_break(); // #TODO: Fix this!
|
||||
}
|
||||
for (s32 t = 0; t < drive_count; t += 1) {
|
||||
Thread* thread = &ex1_ntfs.threads[t];
|
||||
Arena* thread_arena = next_arena(Arena_Reserve::Size_64K);
|
||||
push_arena(thread_arena);
|
||||
auto thread_data = New<NTFS_Enumeration_Task>();
|
||||
thread_data->pool = thread_arena;
|
||||
// #TODO: fill out
|
||||
thread_start(thread, thread_data);
|
||||
array_add(ex1_ntfs.threads_in_flight, thread);
|
||||
}
|
||||
}
|
||||
|
||||
if (ex1_ntfs.threads_in_flight.count) {
|
||||
Text("Threads in flight: %d", ex1_ntfs.threads_in_flight.count);
|
||||
// keep track of which indices to remove!
|
||||
for_each(t, ex1_ntfs.threads_in_flight) {
|
||||
if (thread_is_done(ex1_ntfs.threads_in_flight[t])) {
|
||||
Thread* thread = ex1_ntfs.threads_in_flight[t];
|
||||
auto task = thread_task(NTFS_Enumeration_Task);
|
||||
release_arena(task->pool);
|
||||
|
||||
thread_deinit(ex1_ntfs.threads_in_flight[t], true);
|
||||
array_unordered_remove_by_index(ex1_ntfs.threads_in_flight, t);
|
||||
t -= 1; // check this element index again!
|
||||
}
|
||||
}
|
||||
}
|
||||
End();
|
||||
}
|
||||
|
||||
void ImGui_Debug_Panel () { using namespace ImGui;
|
||||
push_allocator(temp());
|
||||
Begin("Debug Panel");
|
||||
SeparatorText("ex1_ntfs");
|
||||
Text("Threads in flight count: %d", ex1_ntfs.threads_in_flight.count);
|
||||
for_each(i, ex1_ntfs.threads) {
|
||||
Text(" [%d] initialized: %d, has_context: %d, has_data: %d",
|
||||
i, ex1_ntfs.threads[i].proc != nullptr, ex1_ntfs.threads[i].context != nullptr, ex1_ntfs.threads[i].data != nullptr);
|
||||
}
|
||||
// #cpuid
|
||||
// Text("[cpus] physical: %d, logical: %d, primary: %d, secondary: %d", os_cpu_physical_core_count(), os_cpu_logical_core_count(), os_cpu_primary_core_count(), os_cpu_secondary_core_count());
|
||||
SeparatorText("Arena In-Use List");
|
||||
for (u8 i = 0; i < Arena_Reserve_Count; i += 1) {
|
||||
auto t = format_cstring(
|
||||
" [%s] in_use: %d, committed_bytes: %s",
|
||||
format_bytes(Arena_Sizes[i], 0).data,
|
||||
arena_free_list->in_flight_count[i],
|
||||
format_bytes(committed_bytes(arena_free_list->in_flight[i])).data
|
||||
);
|
||||
Text(t);
|
||||
}
|
||||
SeparatorText("Arena Free List");
|
||||
for (u8 i = 0; i < Arena_Reserve_Count; i += 1) {
|
||||
auto t = format_cstring(
|
||||
" [%s] free: %d, committed_bytes: %s",
|
||||
format_bytes(Arena_Sizes[i], 0).data,
|
||||
(s32)arena_free_list->free_table[i].count,
|
||||
format_bytes(committed_bytes(arena_free_list->free_table[i])).data
|
||||
);
|
||||
Text(t);
|
||||
}
|
||||
SeparatorText("Child Threads");
|
||||
|
||||
End();
|
||||
}
|
||||
@ -339,49 +339,6 @@ struct ImGui_Font_Size {
|
||||
}
|
||||
};
|
||||
|
||||
void ImGui_Debug_Panel () {
|
||||
ImGui::Begin("Debug Panel");
|
||||
|
||||
Table<string, Win32_Drive>* drive_table = &global_win32_state.system_info.drives;
|
||||
|
||||
if (ImGui::Button("Debug_Break()")) {
|
||||
debug_break();
|
||||
}
|
||||
if (ImGui::Button("Discover drives") || !table_is_valid(drive_table)) {
|
||||
Win32_Discover_Drives();
|
||||
}
|
||||
|
||||
ImGui::Text("drive_table is valid: %d", table_is_valid(drive_table));
|
||||
// Most basic Table iterator
|
||||
s32 current_index = 0;
|
||||
for (s64 i = 0; i < drive_table->allocated; i += 1) {
|
||||
Table_Entry<string, Win32_Drive>* entry = &drive_table->entries[i]; // we should take ptr here if we want to modify?
|
||||
if (entry->hash > HASH_TABLE_FIRST_VALID_HASH) {
|
||||
// #TODO #MOVE THIS + maybe don't check this every frame!
|
||||
// entry->value.is_present = Win32_Drive_Exists(entry->value.label);
|
||||
if (entry->value.label.data == nullptr) continue;
|
||||
|
||||
ImGui::Text(" > [%d] drive letter: %s (is_present: %d)", current_index, entry->value.label.data, entry->value.is_present);
|
||||
current_index += 1;
|
||||
ImGui::SameLine();
|
||||
push_allocator(temp());
|
||||
|
||||
char* button_label = (char*)format_string("Read NTFS MFT Raw##%s", entry->value.label.data).data;
|
||||
|
||||
if (ImGui::Button(button_label)) {
|
||||
push_arena(thread_context()->arena);
|
||||
// auto_release(thread_context()->arena);
|
||||
auto dfs = NTFS_MFT_read_raw(entry->value.label);
|
||||
if (dfs == nullptr) {
|
||||
log("[NTFS_MFT_read_raw] operation failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void ImGui_Show_Font_Info () {
|
||||
ImGui::Begin("Font Settings"); // imgui_push_default_font_index(0);
|
||||
if (!ImGui_Default_Font_Loaded()){
|
||||
|
||||
@ -86,7 +86,7 @@ void Explorer_ImGui_Application_Win32 () {
|
||||
imgui_default_font.sizes.allocator = GPAllocator();
|
||||
imgui_default_font.font_name = font_file_name;
|
||||
|
||||
for (s64 i = 0; i < 6; i += 1) {
|
||||
for (s64 i = 0; i < ArrayCount(imgui_font_sizes); i += 1) {
|
||||
f32 font_size = imgui_font_sizes[i];
|
||||
ImFont* new_font = io.Fonts->AddFontFromFileTTF((char*)font_file_name.data, font_size);
|
||||
if (new_font) {
|
||||
@ -150,6 +150,7 @@ void Explorer_ImGui_Application_Win32 () {
|
||||
ImGui::DockSpaceOverViewport();
|
||||
|
||||
ImGui_Debug_Panel();
|
||||
Ex1_Control_Panel();
|
||||
ImGui_Show_Font_Info();
|
||||
|
||||
ImGui_Pop_Default_Font();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user