Threading.inc revision 344779
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 "WindowsSupport.h"
18#include <process.h>
19
20// Windows will at times define MemoryFence.
21#ifdef MemoryFence
22#undef MemoryFence
23#endif
24
25namespace {
26  struct ThreadInfo {
27    void(*func)(void*);
28    void *param;
29  };
30}
31
32static 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
39void 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
58uint64_t llvm::get_threadid() {
59  return uint64_t(::GetCurrentThreadId());
60}
61
62uint32_t llvm::get_max_thread_name_length() { return 0; }
63
64#if defined(_MSC_VER)
65static 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
92void 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
101void 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}
110