diff options
-rw-r--r-- | src/inc/utilcode.h | 2 | ||||
-rw-r--r-- | src/utilcode/winfix.cpp | 39 | ||||
-rw-r--r-- | src/vm/comsynchronizable.cpp | 15 | ||||
-rw-r--r-- | src/vm/finalizerthread.cpp | 2 | ||||
-rw-r--r-- | src/vm/gcenv.ee.cpp | 2 | ||||
-rw-r--r-- | src/vm/threads.cpp | 3 | ||||
-rw-r--r-- | src/vm/threads.h | 2 | ||||
-rw-r--r-- | src/vm/win32threadpool.cpp | 4 |
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 |