205 lines
5.5 KiB
C
205 lines
5.5 KiB
C
typedef HRESULT W32_SetThreadDescription_Type(HANDLE hThread, PCWSTR lpThreadDescription);
|
|
|
|
#define W32_KERNEL32_EXT_X_LIST X(SetThreadDescription)
|
|
|
|
#define X(x) global W32_##x##_Type* w32_##x##_func;
|
|
W32_KERNEL32_EXT_X_LIST
|
|
#undef X
|
|
|
|
// =============================================================================
|
|
// Time functions
|
|
|
|
internal uint64 now_time_us()
|
|
{
|
|
uint64 result = 0;
|
|
LARGE_INTEGER large_int_counter;
|
|
if (QueryPerformanceCounter(&large_int_counter))
|
|
{
|
|
result = (large_int_counter.QuadPart * Million(1)) / w32_state.microsecond_resolution;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// =============================================================================
|
|
// System
|
|
|
|
internal SystemInfo* get_system_info()
|
|
{
|
|
return &w32_state.system_info;
|
|
}
|
|
|
|
// =============================================================================
|
|
// Thread Info
|
|
|
|
internal uint32 tid()
|
|
{
|
|
DWORD id = GetCurrentThreadId();
|
|
return (uint32)id;
|
|
}
|
|
|
|
internal void set_platform_thread_name(String8 name)
|
|
{
|
|
TempArena scratch = scratch_begin(0, 0);
|
|
|
|
// Win10 and +
|
|
if (w32_SetThreadDescription_func)
|
|
{
|
|
String16 name16 = str16_from_8(scratch.arena, name);
|
|
HRESULT hr = w32_SetThreadDescription_func(GetCurrentThread(), (WCHAR*)name16.str);
|
|
}
|
|
|
|
// Old way by raising exception
|
|
{
|
|
String8 name_copy = str8_copy(scratch.arena, name);
|
|
#pragma pack(push, 8)
|
|
typedef struct THREADNAME_INFO THREADNAME_INFO;
|
|
struct THREADNAME_INFO
|
|
{
|
|
uint32 dwType; // Must be 0x1000.
|
|
char* szName; // Pointer to name (in user addr space).
|
|
uint32 dwThreadID; // Thread ID (-1=caller thread).
|
|
uint32 dwFlags; // Reserved for future use, must be zero.
|
|
};
|
|
#pragma pack(pop)
|
|
THREADNAME_INFO info;
|
|
info.dwType = 0x1000;
|
|
info.szName = (char*)name_copy.str;
|
|
info.dwThreadID = tid();
|
|
info.dwFlags = 0;
|
|
#pragma warning(push)
|
|
#pragma warning(disable : 6320 6322)
|
|
__try
|
|
{
|
|
RaiseException(0x406D1388, 0, sizeof(info) / sizeof(void*), (const ULONG_PTR*)&info);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
}
|
|
#pragma warning(pop)
|
|
}
|
|
scratch_end(scratch);
|
|
}
|
|
|
|
// =============================================================================
|
|
// Memory
|
|
|
|
internal void* reserve_memory(uint64 size)
|
|
{
|
|
void* result = VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE);
|
|
return result;
|
|
}
|
|
|
|
internal bool32 commit_memory(void* ptr, uint64 size)
|
|
{
|
|
bool32 result = (VirtualAlloc(ptr, size, MEM_COMMIT, PAGE_READWRITE) != 0);
|
|
return result;
|
|
}
|
|
|
|
internal void* reserve_memory_large(uint64 size)
|
|
{
|
|
// Windows do not allow commiting large pages
|
|
void* result = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
|
|
return result;
|
|
}
|
|
|
|
internal bool32 commit_memory_large(void* ptr, uint64 size)
|
|
{
|
|
(void)ptr;
|
|
(void)size;
|
|
return 1;
|
|
}
|
|
|
|
internal void decommit_memory(void* ptr, uint64 size)
|
|
{
|
|
VirtualFree(ptr, size, MEM_DECOMMIT);
|
|
}
|
|
|
|
internal void release_memory(void* ptr, uint64 size)
|
|
{
|
|
(void)size; // Unused on windows
|
|
VirtualFree(ptr, 0, MEM_RELEASE);
|
|
}
|
|
|
|
// =============================================================================
|
|
// Aborting
|
|
|
|
internal void abort_self(uint64 exit_code)
|
|
{
|
|
ExitProcess((int)exit_code);
|
|
}
|
|
|
|
// =============================================================================
|
|
// Entry points
|
|
|
|
internal void w32_entry_point(int argc, WCHAR** wargv)
|
|
{
|
|
// Dynamically load some windows function that are not guaranteed in all sdk
|
|
{
|
|
#define X(x) w32_##x##_func = (void*)GetProcAddress(module, Stringify(x));
|
|
HMODULE module;
|
|
|
|
module = LoadLibraryA("kernek32.dll");
|
|
W32_KERNEL32_EXT_X_LIST
|
|
FreeLibrary(module);
|
|
#undef X
|
|
}
|
|
|
|
SYSTEM_INFO sys_info = { 0 };
|
|
GetSystemInfo(&sys_info);
|
|
|
|
{
|
|
w32_state.microsecond_resolution = 1;
|
|
LARGE_INTEGER large_int_resolution;
|
|
if (QueryPerformanceCounter(&large_int_resolution))
|
|
{
|
|
w32_state.microsecond_resolution = large_int_resolution.QuadPart;
|
|
}
|
|
}
|
|
|
|
SystemInfo* info = &w32_state.system_info;
|
|
info->page_size = sys_info.dwPageSize;
|
|
info->large_page_size = GetLargePageMinimum();
|
|
|
|
Arena* args_arena = arena_alloc(.reserve_size = MB(1), .commit_size = KB(32));
|
|
char** argv = push_array(args_arena, char*, argc);
|
|
for (int i = 0; i < argc; ++i)
|
|
{
|
|
String16 arg16 = str16_cstring((uint16*)wargv[i]);
|
|
String8 arg8 = str8_from_16(args_arena, arg16);
|
|
argv[i] = (char*)arg8.str;
|
|
}
|
|
|
|
// Thread context
|
|
TCTX* tctx = tctx_alloc();
|
|
tctx_select(tctx);
|
|
|
|
// setup w32 state
|
|
Arena* arena = arena_alloc();
|
|
{
|
|
w32_state.arena = arena;
|
|
{
|
|
SystemInfo* info = &w32_state.system_info;
|
|
DWORD size = MAX_COMPUTERNAME_LENGTH + 1;
|
|
uint8 buffer[MAX_COMPUTERNAME_LENGTH + 1] = { 0 };
|
|
if (GetComputerNameA((char*)buffer, &size))
|
|
{
|
|
info->machine_name = str8_copy(arena, str8(buffer, size));
|
|
}
|
|
}
|
|
}
|
|
|
|
main_thread_core_entry_point(argc, argv);
|
|
|
|
tctx_release(tctx);
|
|
}
|
|
|
|
int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
|
|
{
|
|
(void)hInstance;
|
|
(void)hPrevInstance;
|
|
(void)lpCmdLine;
|
|
(void)nShowCmd;
|
|
w32_entry_point(__argc, __wargv);
|
|
return 0;
|
|
}
|