1/*
2 * IXSetThreadName.cpp
3 * Author: Benjamin Sergeant
4 * Copyright (c) 2018 2020 Machine Zone, Inc. All rights reserved.
5 */
6#include "IXSetThreadName.h"
7
8// unix systems
9#if defined(__APPLE__) || defined(__linux__) || defined(BSD)
10#include <pthread.h>
11#endif
12
13// freebsd needs this header as well
14#if defined(BSD)
15#include <pthread_np.h>
16#endif
17
18// Windows
19#ifdef _WIN32
20#include <windows.h>
21#endif
22
23namespace ix
24{
25#ifdef _WIN32
26 const DWORD MS_VC_EXCEPTION = 0x406D1388;
27
28#pragma pack(push, 8)
29 typedef struct tagTHREADNAME_INFO
30 {
31 DWORD dwType; // Must be 0x1000.
32 LPCSTR szName; // Pointer to name (in user addr space).
33 DWORD dwThreadID; // Thread ID (-1=caller thread).
34 DWORD dwFlags; // Reserved for future use, must be zero.
35 } THREADNAME_INFO;
36#pragma pack(pop)
37
38 void SetThreadName(DWORD dwThreadID, const char* threadName)
39 {
40#ifndef __GNUC__
41 THREADNAME_INFO info;
42 info.dwType = 0x1000;
43 info.szName = threadName;
44 info.dwThreadID = dwThreadID;
45 info.dwFlags = 0;
46
47 __try
48 {
49 RaiseException(
50 MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*) &info);
51 }
52 __except (EXCEPTION_EXECUTE_HANDLER)
53 {
54 }
55#endif
56 }
57#endif
58
59 void setThreadName(const std::string& name)
60 {
61#if defined(__APPLE__)
62 //
63 // Apple reserves 16 bytes for its thread names
64 // Notice that the Apple version of pthread_setname_np
65 // does not take a pthread_t argument
66 //
67 pthread_setname_np(name.substr(0, 63).c_str());
68#elif defined(__linux__)
69 //
70 // Linux only reserves 16 bytes for its thread names
71 // See prctl and PR_SET_NAME property in
72 // http://man7.org/linux/man-pages/man2/prctl.2.html
73 //
74 pthread_setname_np(pthread_self(), name.substr(0, 15).c_str());
75#elif defined(_WIN32)
76 SetThreadName(-1, name.c_str());
77#elif defined(BSD)
78 pthread_set_name_np(pthread_self(), name.substr(0, 15).c_str());
79#else
80 // ... assert here ?
81#endif
82 }
83} // namespace ix
84