From 8fa9b57f75186f641e920ac194e7c748a42d2a26 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 27 Jan 2017 20:50:30 -0500 Subject: [PATCH] windows: first shot at naming threads with SetThreadDescription(). This is a bleeding edge API, added to Windows 10 Anniversary Edition (build 1607, specifically). https://msdn.microsoft.com/en-us/library/windows/desktop/mt774976(v=vs.85).aspx Nothing supports this yet, including WinDbg, Visual Studio, minidumps, etc, so we still need to also use the RaiseException hack. But presumably tools will use this API as a more robust and universal way to get thread names sooner or later, so we'll start broadcasting to it now. --- src/thread/windows/SDL_systhread.c | 53 ++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/src/thread/windows/SDL_systhread.c b/src/thread/windows/SDL_systhread.c index 1d159db19e87e..aa73354076984 100644 --- a/src/thread/windows/SDL_systhread.c +++ b/src/thread/windows/SDL_systhread.c @@ -164,26 +164,53 @@ typedef struct tagTHREADNAME_INFO } THREADNAME_INFO; #pragma pack(pop) + +typedef HRESULT (WINAPI *pfnSetThreadDescription)(HANDLE, PCWSTR); + void SDL_SYS_SetupThread(const char *name) { - if ((name != NULL) && IsDebuggerPresent()) { - THREADNAME_INFO inf; + if (name != NULL) { + static HMODULE kernel32 = 0; + static pfnSetThreadDescription pSetThreadDescription = NULL; + + if (!kernel32) { + kernel32 = LoadLibrary(L"kernel32.dll"); + if (kernel32) { + pSetThreadDescription = (pfnSetThreadDescription) GetProcAddress(kernel32, "SetThreadDescription"); + } + } - /* C# and friends will try to catch this Exception, let's avoid it. */ - if (SDL_GetHintBoolean(SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING, SDL_FALSE)) { - return; + if (pSetThreadDescription != NULL) { + WCHAR *strw = WIN_UTF8ToString(name); + if (strw) { + pSetThreadDescription(GetCurrentThread(), strw); + SDL_free(strw); + } } - /* This magic tells the debugger to name a thread if it's listening. */ - SDL_zero(inf); - inf.dwType = 0x1000; - inf.szName = name; - inf.dwThreadID = (DWORD) -1; - inf.dwFlags = 0; + /* Presumably some version of Visual Studio will understand SetThreadDescription(), + but we still need to deal with older OSes and debuggers. Set it with the arcane + exception magic, too. */ - /* The debugger catches this, renames the thread, continues on. */ - RaiseException(0x406D1388, 0, sizeof(inf) / sizeof(ULONG), (const ULONG_PTR*) &inf); + if (IsDebuggerPresent()) { + THREADNAME_INFO inf; + + /* C# and friends will try to catch this Exception, let's avoid it. */ + if (SDL_GetHintBoolean(SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING, SDL_FALSE)) { + return; + } + + /* This magic tells the debugger to name a thread if it's listening. */ + SDL_zero(inf); + inf.dwType = 0x1000; + inf.szName = name; + inf.dwThreadID = (DWORD) -1; + inf.dwFlags = 0; + + /* The debugger catches this, renames the thread, continues on. */ + RaiseException(0x406D1388, 0, sizeof(inf) / sizeof(ULONG), (const ULONG_PTR*) &inf); + } } }