summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/inc/utilcode.h2
-rw-r--r--src/utilcode/winfix.cpp39
-rw-r--r--src/vm/comsynchronizable.cpp15
-rw-r--r--src/vm/finalizerthread.cpp2
-rw-r--r--src/vm/gcenv.ee.cpp2
-rw-r--r--src/vm/threads.cpp3
-rw-r--r--src/vm/threads.h2
-rw-r--r--src/vm/win32threadpool.cpp4
8 files changed, 62 insertions, 7 deletions
diff --git a/src/inc/utilcode.h b/src/inc/utilcode.h
index db8465ad89..f48af70f60 100644
--- a/src/inc/utilcode.h
+++ b/src/inc/utilcode.h
@@ -4687,6 +4687,8 @@ inline void ClrFlsClearThreadType (TlsThreadTypeFlag flag)
#define CLEAR_THREAD_TYPE_STACKWALKER() ClrFlsSetValue(TlsIdx_StackWalkerWalkingThread, NULL)
#endif // DACCESS_COMPILE
+HRESULT SetThreadName(HANDLE hThread, PCWSTR lpThreadDescription);
+
inline BOOL IsStackWalkerThread()
{
STATIC_CONTRACT_NOTHROW;
diff --git a/src/utilcode/winfix.cpp b/src/utilcode/winfix.cpp
index 3a044865ec..c914fb6edd 100644
--- a/src/utilcode/winfix.cpp
+++ b/src/utilcode/winfix.cpp
@@ -426,6 +426,45 @@ lExit:
}
+typedef HRESULT(WINAPI *pfnSetThreadDescription)(HANDLE hThread, PCWSTR lpThreadDescription);
+extern pfnSetThreadDescription g_pfnSetThreadDescription;
+
+// Dummy method if windows version does not support it
+HRESULT SetThreadDescriptionDummy(HANDLE hThread, PCWSTR lpThreadDescription)
+{
+ return NOERROR;
+}
+
+HRESULT WINAPI InitializeSetThreadDescription(HANDLE hThread, PCWSTR lpThreadDescription)
+{
+ HMODULE hKernel32 = WszLoadLibrary(W("kernel32.dll"));
+
+ pfnSetThreadDescription pLocal = NULL;
+ if (hKernel32 != NULL)
+ {
+ // store to thread local variable to prevent data race
+ pLocal = (pfnSetThreadDescription)GetProcAddress(hKernel32, "SetThreadDescription");
+ }
+
+ if (pLocal == NULL) // method is only available with Windows 10 Creators Update or later
+ {
+ g_pfnSetThreadDescription = SetThreadDescriptionDummy;
+ }
+ else
+ {
+ g_pfnSetThreadDescription = pLocal;
+ }
+
+ return g_pfnSetThreadDescription(hThread, lpThreadDescription);
+}
+
+pfnSetThreadDescription g_pfnSetThreadDescription = &InitializeSetThreadDescription;
+
+// Set unmanaged thread name which will show up in ETW and Debuggers which know how to read this data.
+HRESULT SetThreadName(HANDLE hThread, PCWSTR lpThreadDescription)
+{
+ return g_pfnSetThreadDescription(hThread, lpThreadDescription);
+}
DWORD
WszGetWorkingSet()
diff --git a/src/vm/comsynchronizable.cpp b/src/vm/comsynchronizable.cpp
index 3425e2db2c..0554fe3385 100644
--- a/src/vm/comsynchronizable.cpp
+++ b/src/vm/comsynchronizable.cpp
@@ -28,6 +28,10 @@
#include "appdomain.hpp"
#include "appdomain.inl"
+#ifndef FEATURE_PAL
+#include "utilcode.h"
+#endif
+
#include "newapis.h"
// To include definition of CAPTURE_BUCKETS_AT_TRANSITION
@@ -1542,9 +1546,18 @@ void QCALLTYPE ThreadNative::InformThreadNameChange(QCall::ThreadHandle thread,
QCALL_CONTRACT;
BEGIN_QCALL;
-
+
Thread* pThread = &(*thread);
+#ifndef FEATURE_PAL
+ // Set on Windows 10 Creators Update and later machines the unmanaged thread name as well. That will show up in ETW traces and debuggers which is very helpful
+ // if more and more threads get a meaningful name
+ if (len > 0 && name != NULL)
+ {
+ SetThreadName(pThread->GetThreadHandle(), name);
+ }
+#endif
+
#ifdef PROFILING_SUPPORTED
{
BEGIN_PIN_PROFILER(CORProfilerTrackThreads());
diff --git a/src/vm/finalizerthread.cpp b/src/vm/finalizerthread.cpp
index 0a4da165a1..3ba3468407 100644
--- a/src/vm/finalizerthread.cpp
+++ b/src/vm/finalizerthread.cpp
@@ -909,7 +909,7 @@ void FinalizerThread::FinalizerThreadCreate()
// actual thread terminates.
GetFinalizerThread()->IncExternalCount();
- if (GetFinalizerThread()->CreateNewThread(0, &FinalizerThreadStart, NULL))
+ if (GetFinalizerThread()->CreateNewThread(0, &FinalizerThreadStart, NULL, W("Finalizer")) )
{
DWORD dwRet = GetFinalizerThread()->StartThread();
diff --git a/src/vm/gcenv.ee.cpp b/src/vm/gcenv.ee.cpp
index 7ab22dbcfb..b61069f5fd 100644
--- a/src/vm/gcenv.ee.cpp
+++ b/src/vm/gcenv.ee.cpp
@@ -445,7 +445,7 @@ Thread* GCToEEInterface::CreateBackgroundThread(GCBackgroundThreadFunction threa
return NULL;
}
- if (threadStubArgs.thread->CreateNewThread(0, (LPTHREAD_START_ROUTINE)BackgroundThreadStub, &threadStubArgs))
+ if (threadStubArgs.thread->CreateNewThread(0, (LPTHREAD_START_ROUTINE)BackgroundThreadStub, &threadStubArgs, W("Background GC")))
{
threadStubArgs.thread->SetBackground (TRUE, FALSE);
threadStubArgs.thread->StartThread();
diff --git a/src/vm/threads.cpp b/src/vm/threads.cpp
index a28164f857..b827140dd4 100644
--- a/src/vm/threads.cpp
+++ b/src/vm/threads.cpp
@@ -2524,7 +2524,7 @@ void UndoRevert(BOOL bReverted, HANDLE hToken)
// We don't want ::CreateThread() calls scattered throughout the source. So gather
// them all here.
-BOOL Thread::CreateNewThread(SIZE_T stackSize, LPTHREAD_START_ROUTINE start, void *args)
+BOOL Thread::CreateNewThread(SIZE_T stackSize, LPTHREAD_START_ROUTINE start, void *args, LPCWSTR pName)
{
CONTRACTL {
NOTHROW;
@@ -2551,6 +2551,7 @@ BOOL Thread::CreateNewThread(SIZE_T stackSize, LPTHREAD_START_ROUTINE start, voi
bRet = CreateNewOSThread(stackSize, start, args);
#ifndef FEATURE_PAL
UndoRevert(bReverted, token);
+ SetThreadName(m_ThreadHandle, pName);
#endif // !FEATURE_PAL
return bRet;
diff --git a/src/vm/threads.h b/src/vm/threads.h
index 9824ef1301..ad433e765b 100644
--- a/src/vm/threads.h
+++ b/src/vm/threads.h
@@ -1946,7 +1946,7 @@ public:
// Create all new threads here. The thread is created as suspended, so
// you must ::ResumeThread to kick it off. It is guaranteed to create the
// thread, or throw.
- BOOL CreateNewThread(SIZE_T stackSize, LPTHREAD_START_ROUTINE start, void *args);
+ BOOL CreateNewThread(SIZE_T stackSize, LPTHREAD_START_ROUTINE start, void *args, LPCWSTR pName=NULL);
enum StackSizeBucket
diff --git a/src/vm/win32threadpool.cpp b/src/vm/win32threadpool.cpp
index e2887c53db..eabbcb93ae 100644
--- a/src/vm/win32threadpool.cpp
+++ b/src/vm/win32threadpool.cpp
@@ -1815,8 +1815,8 @@ Thread* ThreadpoolMgr::CreateUnimpersonatedThread(LPTHREAD_START_ROUTINE lpStart
// CreateNewThread takes care of reverting any impersonation - so dont do anything here.
bOK = pThread->CreateNewThread(0, // default stack size
lpStartAddress,
- lpArgs //arguments
- );
+ lpArgs, //arguments
+ W(".NET Core ThreadPool"));
}
else {
#ifndef FEATURE_PAL