Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Commit

Permalink
Implement SetThreadName in PAL for Linux. (#27182)
Browse files Browse the repository at this point in the history
* Implement SetThreadName in PAL for Linux.

This means thread names will now show up in gdb, htop, etc... on Linux.

I did not implement this for any other platforms:
I did not have anything to test them with,
and pthread_setname_np's API varies wildly.
  • Loading branch information
PJB3005 authored and janvorli committed Nov 11, 2019
1 parent a5e90c9 commit 5f5f960
Show file tree
Hide file tree
Showing 9 changed files with 197 additions and 60 deletions.
1 change: 1 addition & 0 deletions src/dlls/mscordac/mscordac_unixexports.src
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ nativeStringResourceTable_mscorrc_debug
#SetFilePointer
#SetLastError
#SetErrorMode
#SetThreadDescription
#Sleep
#SleepEx
#SwitchToThread
Expand Down
61 changes: 61 additions & 0 deletions src/pal/inc/pal.h
Original file line number Diff line number Diff line change
Expand Up @@ -2400,6 +2400,14 @@ GetThreadTimes(
OUT LPFILETIME lpKernelTime,
OUT LPFILETIME lpUserTime);

PALIMPORT
HRESULT
PALAPI
SetThreadDescription(
IN HANDLE hThread,
IN PCWSTR lpThreadDescription
);

#define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)

PALIMPORT
Expand Down Expand Up @@ -5086,6 +5094,59 @@ class NativeExceptionHolderFactory
#define _O_TEXT 0x4000
#define _O_BINARY 0x8000

/******************* HRESULT types ****************************************/

#define FACILITY_WINDOWS 8
#define FACILITY_URT 19
#define FACILITY_UMI 22
#define FACILITY_SXS 23
#define FACILITY_STORAGE 3
#define FACILITY_SSPI 9
#define FACILITY_SCARD 16
#define FACILITY_SETUPAPI 15
#define FACILITY_SECURITY 9
#define FACILITY_RPC 1
#define FACILITY_WIN32 7
#define FACILITY_CONTROL 10
#define FACILITY_NULL 0
#define FACILITY_MSMQ 14
#define FACILITY_MEDIASERVER 13
#define FACILITY_INTERNET 12
#define FACILITY_ITF 4
#define FACILITY_DPLAY 21
#define FACILITY_DISPATCH 2
#define FACILITY_COMPLUS 17
#define FACILITY_CERT 11
#define FACILITY_ACS 20
#define FACILITY_AAF 18

#define NO_ERROR 0L

#define SEVERITY_SUCCESS 0
#define SEVERITY_ERROR 1

#define SUCCEEDED(Status) ((HRESULT)(Status) >= 0)
#define FAILED(Status) ((HRESULT)(Status)<0)
#define IS_ERROR(Status) ((ULONG)(Status) >> 31 == SEVERITY_ERROR) // diff from win32
#define HRESULT_CODE(hr) ((hr) & 0xFFFF)
#define SCODE_CODE(sc) ((sc) & 0xFFFF)
#define HRESULT_FACILITY(hr) (((hr) >> 16) & 0x1fff)
#define SCODE_FACILITY(sc) (((sc) >> 16) & 0x1fff)
#define HRESULT_SEVERITY(hr) (((hr) >> 31) & 0x1)
#define SCODE_SEVERITY(sc) (((sc) >> 31) & 0x1)

// both macros diff from Win32
#define MAKE_HRESULT(sev,fac,code) \
((HRESULT) (((ULONG)(sev)<<31) | ((ULONG)(fac)<<16) | ((ULONG)(code))) )
#define MAKE_SCODE(sev,fac,code) \
((SCODE) (((ULONG)(sev)<<31) | ((ULONG)(fac)<<16) | ((LONG)(code))) )

#define FACILITY_NT_BIT 0x10000000
#define HRESULT_FROM_WIN32(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000)))
#define __HRESULT_FROM_WIN32(x) HRESULT_FROM_WIN32(x)

#define HRESULT_FROM_NT(x) ((HRESULT) ((x) | FACILITY_NT_BIT))

#ifdef __cplusplus
}
#endif
Expand Down
53 changes: 0 additions & 53 deletions src/pal/inc/rt/palrt.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,59 +302,6 @@ typedef union _ULARGE_INTEGER {
ULONGLONG QuadPart;
} ULARGE_INTEGER, *PULARGE_INTEGER;

/******************* HRESULT types ****************************************/

#define FACILITY_WINDOWS 8
#define FACILITY_URT 19
#define FACILITY_UMI 22
#define FACILITY_SXS 23
#define FACILITY_STORAGE 3
#define FACILITY_SSPI 9
#define FACILITY_SCARD 16
#define FACILITY_SETUPAPI 15
#define FACILITY_SECURITY 9
#define FACILITY_RPC 1
#define FACILITY_WIN32 7
#define FACILITY_CONTROL 10
#define FACILITY_NULL 0
#define FACILITY_MSMQ 14
#define FACILITY_MEDIASERVER 13
#define FACILITY_INTERNET 12
#define FACILITY_ITF 4
#define FACILITY_DPLAY 21
#define FACILITY_DISPATCH 2
#define FACILITY_COMPLUS 17
#define FACILITY_CERT 11
#define FACILITY_ACS 20
#define FACILITY_AAF 18

#define NO_ERROR 0L

#define SEVERITY_SUCCESS 0
#define SEVERITY_ERROR 1

#define SUCCEEDED(Status) ((HRESULT)(Status) >= 0)
#define FAILED(Status) ((HRESULT)(Status)<0)
#define IS_ERROR(Status) ((ULONG)(Status) >> 31 == SEVERITY_ERROR) // diff from win32
#define HRESULT_CODE(hr) ((hr) & 0xFFFF)
#define SCODE_CODE(sc) ((sc) & 0xFFFF)
#define HRESULT_FACILITY(hr) (((hr) >> 16) & 0x1fff)
#define SCODE_FACILITY(sc) (((sc) >> 16) & 0x1fff)
#define HRESULT_SEVERITY(hr) (((hr) >> 31) & 0x1)
#define SCODE_SEVERITY(sc) (((sc) >> 31) & 0x1)

// both macros diff from Win32
#define MAKE_HRESULT(sev,fac,code) \
((HRESULT) (((ULONG)(sev)<<31) | ((ULONG)(fac)<<16) | ((ULONG)(code))) )
#define MAKE_SCODE(sev,fac,code) \
((SCODE) (((ULONG)(sev)<<31) | ((ULONG)(fac)<<16) | ((LONG)(code))) )

#define FACILITY_NT_BIT 0x10000000
#define HRESULT_FROM_WIN32(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000)))
#define __HRESULT_FROM_WIN32(x) HRESULT_FROM_WIN32(x)

#define HRESULT_FROM_NT(x) ((HRESULT) ((x) | FACILITY_NT_BIT))

/******************* OLE, BSTR, VARIANT *************************/

STDAPI_VIS(DLLEXPORT, LPVOID) CoTaskMemAlloc(SIZE_T cb);
Expand Down
8 changes: 8 additions & 0 deletions src/pal/src/include/pal/thread.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,14 @@ namespace CorUnix
int
);

friend
PAL_ERROR
InternalSetThreadDescription(
CPalThread *,
HANDLE,
PCWSTR
);

friend
PAL_ERROR
CreateThreadData(
Expand Down
116 changes: 116 additions & 0 deletions src/pal/src/thread/thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1578,7 +1578,123 @@ GetThreadTimes(
return (retval);
}

HRESULT
PALAPI
SetThreadDescription(
IN HANDLE hThread,
IN PCWSTR lpThreadDescription)
{
CPalThread *pThread;
PAL_ERROR palError;

PERF_ENTRY(SetThreadDescription);
ENTRY("SetThreadDescription(hThread=%p,lpThreadDescription=%p)\n", hThread, lpThreadDescription);

pThread = InternalGetCurrentThread();

palError = InternalSetThreadDescription(
pThread,
hThread,
lpThreadDescription
);

if (NO_ERROR != palError)
{
pThread->SetLastError(palError);
}

LOGEXIT("SetThreadDescription");
PERF_EXIT(SetThreadDescription);

return HRESULT_FROM_WIN32(palError);
}

PAL_ERROR
CorUnix::InternalSetThreadDescription(
CPalThread *pThread,
HANDLE hTargetThread,
PCWSTR lpThreadDescription
)
{
PAL_ERROR palError = NO_ERROR;
CPalThread *pTargetThread = NULL;
IPalObject *pobjThread = NULL;
int error;
int nameSize;
char *nameBuf = NULL;

// The exact API of pthread_setname_np varies very wildly depending on OS.
// For now, only Linux is implemented.
#if defined(__linux__)

palError = InternalGetThreadDataFromHandle(
pThread,
hTargetThread,
&pTargetThread,
&pobjThread
);

if (NO_ERROR != palError)
{
goto InternalSetThreadDescriptionExit;
}

pTargetThread->Lock(pThread);

/* translate the wide char lpThreadDescription string to multibyte string */
nameSize = WideCharToMultiByte(CP_ACP, 0, lpThreadDescription, -1, NULL, 0, NULL, NULL);

if (0 == nameSize)
{
palError = ERROR_INTERNAL_ERROR;
goto InternalSetThreadDescriptionExit;
}

nameBuf = (char *)PAL_malloc(nameSize);
if (nameBuf == NULL)
{
palError = ERROR_OUTOFMEMORY;
goto InternalSetThreadDescriptionExit;
}

if (WideCharToMultiByte(CP_ACP, 0, lpThreadDescription, -1, nameBuf, nameSize, NULL,
NULL) != nameSize)
{
palError = ERROR_INTERNAL_ERROR;
goto InternalSetThreadDescriptionExit;
}

// Null terminate early.
// pthread_setname_np only accepts up to 16 chars.
nameBuf[15] = '\0';

error = pthread_setname_np(pTargetThread->GetPThreadSelf(), nameBuf);

if (error != 0)
{
palError = ERROR_INTERNAL_ERROR;
}

InternalSetThreadDescriptionExit:

if (NULL != pTargetThread)
{
pTargetThread->Unlock(pThread);
}

if (NULL != pobjThread)
{
pobjThread->ReleaseReference(pThread);
}

if (NULL != nameBuf) {
PAL_free(nameBuf);
}

#endif // defined(__linux__)

return palError;
}

void *
CPalThread::ThreadEntry(
Expand Down
7 changes: 7 additions & 0 deletions src/utilcode/winfix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,4 +292,11 @@ HRESULT SetThreadName(HANDLE hThread, PCWSTR lpThreadDescription)
return g_pfnSetThreadDescription(hThread, lpThreadDescription);
}

#else //!FEATURE_PAL

HRESULT SetThreadName(HANDLE hThread, PCWSTR lpThreadDescription)
{
return SetThreadDescription(hThread, lpThreadDescription);
}

#endif //!FEATURE_PAL
3 changes: 1 addition & 2 deletions src/vm/comsynchronizable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1283,14 +1283,13 @@ void QCALLTYPE ThreadNative::InformThreadNameChange(QCall::ThreadHandle thread,

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
// Will also show up in Linux in gdb and such.
if (len > 0 && name != NULL && pThread->GetThreadHandle() != INVALID_HANDLE_VALUE)
{
SetThreadName(pThread->GetThreadHandle(), name);
}
#endif

#ifdef PROFILING_SUPPORTED
{
Expand Down
5 changes: 2 additions & 3 deletions src/vm/threads.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2064,9 +2064,9 @@ BOOL Thread::CreateNewThread(SIZE_T stackSize, LPTHREAD_START_ROUTINE start, voi
bRet = CreateNewOSThread(stackSize, start, args);
#ifndef FEATURE_PAL
UndoRevert(bReverted, token);
#endif // !FEATURE_PAL
if (pName != NULL)
SetThreadName(m_ThreadHandle, pName);
#endif // !FEATURE_PAL

return bRet;
}
Expand Down Expand Up @@ -2123,9 +2123,8 @@ HANDLE Thread::CreateUtilityThread(Thread::StackSizeBucket stackSizeBucket, LPTH

DWORD threadId;
HANDLE hThread = CreateThread(NULL, stackSize, start, args, flags, &threadId);
#ifndef FEATURE_PAL

SetThreadName(hThread, pName);
#endif // !FEATURE_PAL


if (pThreadId)
Expand Down
3 changes: 1 addition & 2 deletions src/vm/win32threadpool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1824,9 +1824,8 @@ Thread* ThreadpoolMgr::CreateUnimpersonatedThread(LPTHREAD_START_ROUTINE lpStart
lpThreadArgs, // arguments
CREATE_SUSPENDED,
&threadId);
#ifndef FEATURE_PAL

SetThreadName(threadHandle, W(".NET ThreadPool Worker"));
#endif // !FEATURE_PAL
if (threadHandle != NULL)
lpThreadArgs.SuppressRelease();
}
Expand Down

0 comments on commit 5f5f960

Please sign in to comment.