From 1154cb1d3db53215e46b3c7d2476b27d52d0dfbf Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 3 May 2019 20:55:20 -0700 Subject: [PATCH] Name our threads on Windows --- src/Platform.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/src/Platform.c b/src/Platform.c index 888f8cd..71320cb 100644 --- a/src/Platform.c +++ b/src/Platform.c @@ -15,6 +15,7 @@ void cleanupPlatformSockets(void); struct thread_context { ThreadEntry entry; void* context; + const char* name; #if defined(__vita__) PLT_THREAD* thread; #endif @@ -25,6 +26,54 @@ static int activeMutexes = 0; static int activeEvents = 0; #if defined(LC_WINDOWS) + +#pragma pack(push, 8) +typedef struct tagTHREADNAME_INFO +{ + DWORD dwType; // Must be 0x1000. + LPCSTR szName; // Pointer to name (in user addr space). + DWORD dwThreadID; // Thread ID (-1=caller thread). + DWORD dwFlags; // Reserved for future use, must be zero. +} THREADNAME_INFO; +#pragma pack(pop) + +typedef HRESULT (WINAPI *SetThreadDescription_t)(HANDLE, PCWSTR); + +void setThreadNameWin32(const char* name) { + HMODULE hKernel32; + SetThreadDescription_t setThreadDescriptionFunc; + + // This function is only supported on Windows 10 RS1 and later + hKernel32 = LoadLibraryA("kernel32.dll"); + setThreadDescriptionFunc = (SetThreadDescription_t)GetProcAddress(hKernel32, "SetThreadDescription"); + if (setThreadDescriptionFunc != NULL) { + WCHAR nameW[16]; + size_t chars; + + mbstowcs_s(&chars, nameW, ARRAYSIZE(nameW), name, _TRUNCATE); + setThreadDescriptionFunc(GetCurrentThread(), nameW); + } + FreeLibrary(hKernel32); + +#ifdef _MSC_VER + // This method works on legacy OSes and older tools not updated to use SetThreadDescription yet, + // but it's only safe on MSVC with SEH + if (IsDebuggerPresent()) { + THREADNAME_INFO info; + info.dwType = 0x1000; + info.szName = name; + info.dwThreadID = (DWORD)-1; + info.dwFlags = 0; + __try { + RaiseException(0x406D1388, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info); + } + __except (EXCEPTION_EXECUTE_HANDLER) { + // Nothing + } + } +#endif +} + DWORD WINAPI ThreadProc(LPVOID lpParameter) { struct thread_context* ctx = (struct thread_context*)lpParameter; #elif defined(__vita__) @@ -35,6 +84,12 @@ void* ThreadProc(void* context) { struct thread_context* ctx = (struct thread_context*)context; #endif +#if defined(LC_WINDOWS) + setThreadNameWin32(ctx->name); +#elif defined(__linux__) + pthread_setname_np(pthread_self(), ctx->name); +#endif + ctx->entry(ctx->context); #if defined(__vita__) @@ -167,6 +222,7 @@ int PltCreateThread(const char* name, ThreadEntry entry, void* context, PLT_THRE ctx->entry = entry; ctx->context = context; + ctx->name = name; thread->cancelled = 0; @@ -197,10 +253,6 @@ int PltCreateThread(const char* name, ThreadEntry entry, void* context, PLT_THRE free(ctx); return err; } - -#ifdef __linux__ - pthread_setname_np(thread->thread, name); -#endif } #endif