]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Support/Windows/Threading.inc
MFV r316893:
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Support / Windows / Threading.inc
1 //===- Windows/Threading.inc - Win32 Threading Implementation - -*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file provides the Win32 specific implementation of Threading functions.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/ADT/SmallString.h"
15 #include "llvm/ADT/Twine.h"
16
17 #include "Windows/WindowsSupport.h"
18 #include <process.h>
19
20 // Windows will at times define MemoryFence.
21 #ifdef MemoryFence
22 #undef MemoryFence
23 #endif
24
25 namespace {
26   struct ThreadInfo {
27     void(*func)(void*);
28     void *param;
29   };
30 }
31
32 static unsigned __stdcall ThreadCallback(void *param) {
33   struct ThreadInfo *info = reinterpret_cast<struct ThreadInfo *>(param);
34   info->func(info->param);
35
36   return 0;
37 }
38
39 void llvm::llvm_execute_on_thread(void(*Fn)(void*), void *UserData,
40   unsigned RequestedStackSize) {
41   struct ThreadInfo param = { Fn, UserData };
42
43   HANDLE hThread = (HANDLE)::_beginthreadex(NULL,
44     RequestedStackSize, ThreadCallback,
45     &param, 0, NULL);
46
47   if (hThread) {
48     // We actually don't care whether the wait succeeds or fails, in
49     // the same way we don't care whether the pthread_join call succeeds
50     // or fails.  There's not much we could do if this were to fail. But
51     // on success, this call will wait until the thread finishes executing
52     // before returning.
53     (void)::WaitForSingleObject(hThread, INFINITE);
54     ::CloseHandle(hThread);
55   }
56 }
57
58 uint64_t llvm::get_threadid() {
59   return uint64_t(::GetCurrentThreadId());
60 }
61
62 uint32_t llvm::get_max_thread_name_length() { return 0; }
63
64 #if defined(_MSC_VER)
65 static void SetThreadName(DWORD Id, LPCSTR Name) {
66   constexpr DWORD MS_VC_EXCEPTION = 0x406D1388;
67
68 #pragma pack(push, 8)
69   struct THREADNAME_INFO {
70     DWORD dwType;     // Must be 0x1000.
71     LPCSTR szName;    // Pointer to thread name
72     DWORD dwThreadId; // Thread ID (-1 == current thread)
73     DWORD dwFlags;    // Reserved.  Do not use.
74   };
75 #pragma pack(pop)
76
77   THREADNAME_INFO info;
78   info.dwType = 0x1000;
79   info.szName = Name;
80   info.dwThreadId = Id;
81   info.dwFlags = 0;
82
83   __try {
84     ::RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR),
85       (ULONG_PTR *)&info);
86   }
87   __except (EXCEPTION_EXECUTE_HANDLER) {
88   }
89 }
90 #endif
91
92 void llvm::set_thread_name(const Twine &Name) {
93 #if defined(_MSC_VER)
94   // Make sure the input is null terminated.
95   SmallString<64> Storage;
96   StringRef NameStr = Name.toNullTerminatedStringRef(Storage);
97   SetThreadName(::GetCurrentThreadId(), NameStr.data());
98 #endif
99 }
100
101 void llvm::get_thread_name(SmallVectorImpl<char> &Name) {
102   // "Name" is not an inherent property of a thread on Windows.  In fact, when
103   // you "set" the name, you are only firing a one-time message to a debugger
104   // which it interprets as a program setting its threads' name.  We may be
105   // able to get fancy by creating a TLS entry when someone calls
106   // set_thread_name so that subsequent calls to get_thread_name return this
107   // value.
108   Name.clear();
109 }