swr/rast: name threads to aid debugging
authorTim Rowley <timothy.o.rowley@intel.com>
Thu, 13 Apr 2017 21:01:12 +0000 (16:01 -0500)
committerTim Rowley <timothy.o.rowley@intel.com>
Sat, 29 Apr 2017 00:55:40 +0000 (19:55 -0500)
Reviewed-by: Bruce Cherniak <bruce.cherniak@intel.com>
src/gallium/drivers/swr/Makefile.sources
src/gallium/drivers/swr/rasterizer/common/os.cpp [new file with mode: 0644]
src/gallium/drivers/swr/rasterizer/common/os.h
src/gallium/drivers/swr/rasterizer/core/threads.cpp

index 1afb532434c9ae7d8e35c2f04bc1a59fe5388543..056449c2745799e481249479ba04bf6ff72cff29 100644 (file)
@@ -56,6 +56,7 @@ COMMON_CXX_SOURCES := \
        rasterizer/common/formats.cpp \
        rasterizer/common/formats.h \
        rasterizer/common/isa.hpp \
+       rasterizer/common/os.cpp \
        rasterizer/common/os.h \
        rasterizer/common/rdtsc_buckets.cpp \
        rasterizer/common/rdtsc_buckets.h \
diff --git a/src/gallium/drivers/swr/rasterizer/common/os.cpp b/src/gallium/drivers/swr/rasterizer/common/os.cpp
new file mode 100644 (file)
index 0000000..295556a
--- /dev/null
@@ -0,0 +1,107 @@
+/****************************************************************************
+* Copyright (C) 2017 Intel Corporation.   All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice (including the next
+* paragraph) shall be included in all copies or substantial portions of the
+* Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+* IN THE SOFTWARE.
+****************************************************************************/
+
+#include "common/os.h"
+
+#if defined(FORCE_LINUX) || defined(__linux__) || defined(__gnu_linux__)
+#include <pthread.h>
+#endif // Linux
+
+
+
+#if defined(_WIN32)
+static const DWORD MS_VC_EXCEPTION = 0x406D1388;
+
+#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)
+
+void LegacySetThreadName(const char* pThreadName)
+{
+    THREADNAME_INFO info;
+    info.dwType = 0x1000;
+    info.szName = pThreadName;
+    info.dwThreadID = GetCurrentThreadId();
+    info.dwFlags = 0;
+
+    if (!IsDebuggerPresent())
+    {
+        // No debugger attached to interpret exception, no need to actually do it
+        return;
+    }
+
+#pragma warning(push)  
+#pragma warning(disable: 6320 6322)  
+    __try {
+        RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
+    }
+    __except (EXCEPTION_EXECUTE_HANDLER) {
+    }
+#pragma warning(pop)  
+}
+#endif // _WIN32
+
+void SWR_API SetCurrentThreadName(const char* pThreadName)
+{
+#if defined(_WIN32)
+    // The SetThreadDescription API was brought in version 1607 of Windows 10.
+    typedef HRESULT(WINAPI* PFNSetThreadDescription)(HANDLE hThread, PCWSTR lpThreadDescription);
+    // The SetThreadDescription API works even if no debugger is attached.
+    auto pfnSetThreadDescription =
+        reinterpret_cast<PFNSetThreadDescription>(
+            GetProcAddress(GetModuleHandleA("Kernel32.dll"), "SetThreadDescription"));
+
+    if (!pfnSetThreadDescription)
+    {
+        // try KernelBase.dll
+        pfnSetThreadDescription =
+            reinterpret_cast<PFNSetThreadDescription>(
+                GetProcAddress(GetModuleHandleA("KernelBase.dll"), "SetThreadDescription"));
+    }
+
+    if (pfnSetThreadDescription)
+    {
+        std::string utf8Name = pThreadName;
+        std::wstring wideName;
+        wideName.resize(utf8Name.size() + 1);
+        swprintf_s(&(wideName.front()), wideName.size(), L"%S", utf8Name.c_str());
+        HRESULT hr = pfnSetThreadDescription(GetCurrentThread(), wideName.c_str());
+        SWR_ASSERT(SUCCEEDED(hr), "Failed to set thread name to %s", pThreadName);
+
+        // Fall through - it seems like some debuggers only recognize the exception
+    }
+
+    // Fall back to exception based hack
+    LegacySetThreadName(pThreadName);
+#endif // _WIN32
+
+#if defined(FORCE_LINUX) || defined(__linux__) || defined(__gnu_linux__)
+    pthread_setname_np(pthread_self(), pThreadName);
+#endif // Linux
+}
index ef00a255d316c8a1dec7e8924a13aac37ad25c9a..38553df508b23b53a7c651345afe1ba4e928fd45 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
-* Copyright (C) 2014-2015 Intel Corporation.   All Rights Reserved.
+* Copyright (C) 2014-2017 Intel Corporation.   All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -273,4 +273,7 @@ typedef MEGABYTE    GIGABYTE[1024];
 #define ATTR_UNUSED
 #endif
 
+// Defined in os.cpp
+void SWR_API SetCurrentThreadName(const char* pThreadName);
+
 #endif//__SWR_OS_H__
index e3ad2585c018227dc97c639bafbf67fdf41ef3ed..295014d1a7ec11b2e491c11753900506e251585b 100644 (file)
@@ -747,7 +747,20 @@ DWORD workerThreadMain(LPVOID pData)
     uint32_t threadId = pThreadData->threadId;
     uint32_t workerId = pThreadData->workerId;
 
-    bindThread(pContext, threadId, pThreadData->procGroupId, pThreadData->forceBindProcGroup); 
+    bindThread(pContext, threadId, pThreadData->procGroupId, pThreadData->forceBindProcGroup);
+
+    {
+        char threadName[64];
+        sprintf_s(threadName,
+#if defined(_WIN32)
+                  "SWRWorker_%02d_NUMA%d_Core%02d_T%d",
+#else
+                  // linux pthread name limited to 16 chars (including \0)
+                  "w%03d-n%d-c%03d-t%d",
+#endif
+            workerId, pThreadData->numaId, pThreadData->coreId, pThreadData->htId);
+        SetCurrentThreadName(threadName);
+    }
 
     RDTSC_INIT(threadId);