GetThreadDescription (win 10+ thread name) API support

This commit is contained in:
Ryan Fleury
2024-01-11 16:02:27 -08:00
parent 1318aad83b
commit e7243a2c28
6 changed files with 121 additions and 143 deletions
+74
View File
@@ -4,6 +4,8 @@
////////////////////////////////
//~ rjf: Globals
global GetThreadDescriptionFunctionType *demon_w32_GetThreadDescription = 0;
global B32 demon_w32_resume_needed = 0;
global DWORD demon_w32_resume_pid = 0;
global DWORD demon_w32_resume_tid = 0;
@@ -26,6 +28,17 @@ global String8List demon_w32_environment = {0};
////////////////////////////////
//~ rjf: Helpers
internal U64
demon_w32_hash_from_string(String8 string)
{
U64 result = 5381;
for(U64 i = 0; i < string.size; i += 1)
{
result = ((result << 5) + result) + string.str[i];
}
return result;
}
internal DEMON_W32_Ext*
demon_w32_ext_alloc(void){
DEMON_W32_Ext *result = demon_w32_proc_ext_free;
@@ -351,6 +364,11 @@ demon_os_init(void){
demon_w32_ext_arena = arena_alloc();
demon_w32_detach_proc_arena = arena_alloc();
// rjf: load Windows 10+ GetThreadDescription API
{
demon_w32_GetThreadDescription = (GetThreadDescriptionFunctionType *)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "GetThreadDescription");
}
// rjf: setup environment variables
{
CHAR *this_proc_env = GetEnvironmentStrings();
@@ -771,6 +789,19 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *ctrls){
DWORD sus_result = SuspendThread(thread_ext->thread.handle);
(void)sus_result;
// rjf: unpack thread name
String8 thread_name = {0};
if(demon_w32_GetThreadDescription != 0)
{
WCHAR *thread_name_w = 0;
HRESULT hr = demon_w32_GetThreadDescription(evt.u.CreateThread.hThread, &thread_name_w);
if(SUCCEEDED(hr))
{
thread_name = str8_from_16(arena, str16_cstring((U16 *)thread_name_w));
LocalFree(thread_name_w);
}
}
// rjf: determine if this is the halter thread
B32 is_halter = (evt.dwThreadId == demon_w32_halter_thread_id);
@@ -780,6 +811,7 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *ctrls){
e->process = demon_ent_handle_from_ptr(process);
e->thread = demon_ent_handle_from_ptr(thread);
e->code = evt.dwThreadId;
e->string = thread_name;
}
}
}break;
@@ -1140,6 +1172,48 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *ctrls){
}
}
//- rjf: gather new thread-names
if(demon_w32_GetThreadDescription != 0)
{
for(DEMON_Entity *process = demon_ent_root->first;
process != 0;
process = process->next)
{
if(process->kind != DEMON_EntityKind_Process) { continue; }
for(DEMON_Entity *thread = process->first;
thread != 0;
thread = thread->next)
{
if(thread->kind != DEMON_EntityKind_Thread) { continue; }
DEMON_W32_Ext *thread_ext = demon_w32_ext(thread);
if(thread_ext->thread.last_name_hash == 0 ||
thread_ext->thread.name_gather_time_us+1000000 <= os_now_microseconds())
{
String8 name = {0};
{
WCHAR *thread_name_w = 0;
HRESULT hr = demon_w32_GetThreadDescription(thread_ext->thread.handle, &thread_name_w);
if(SUCCEEDED(hr))
{
name = str8_from_16(scratch.arena, str16_cstring((U16 *)thread_name_w));
LocalFree(thread_name_w);
}
}
U64 name_hash = demon_w32_hash_from_string(name);
if(name.size != 0 && name_hash != thread_ext->thread.last_name_hash)
{
DEMON_Event *e = demon_push_event(arena, &result, DEMON_EventKind_SetThreadName);
e->process = demon_ent_handle_from_ptr(process);
e->thread = demon_ent_handle_from_ptr(thread);
e->string = push_str8_copy(arena, name);
}
thread_ext->thread.name_gather_time_us = os_now_microseconds();
thread_ext->thread.last_name_hash = name_hash;
}
}
}
}
// TODO(allen): handle errors? if (!got_new_event) ? if (!good_state) ?
// TODO(allen): per-Architecture
+4
View File
@@ -35,6 +35,8 @@ union DEMON_W32_Ext
struct{
HANDLE handle;
U64 thread_local_base;
U64 last_name_hash;
U64 name_gather_time_us;
} thread;
struct{
HANDLE handle;
@@ -68,6 +70,7 @@ struct DEMON_W32_EntityNode
DEMON_Entity *entity;
};
typedef HRESULT GetThreadDescriptionFunctionType(HANDLE hThread, WCHAR **ppszThreadDescription);
////////////////////////////////
//~ NOTE(allen): Win32 Demon Exceptions
@@ -352,6 +355,7 @@ struct DEMON_PeOptionalHeader32Plus
////////////////////////////////
//~ rjf: Helpers
internal U64 demon_w32_hash_from_string(String8 string);
internal DEMON_W32_Ext* demon_w32_ext_alloc(void);
internal DEMON_W32_Ext* demon_w32_ext(DEMON_Entity *entity);