Threading.inc revision 317017
1317017Sdim//===- Windows/Threading.inc - Win32 Threading Implementation - -*- C++ -*-===//
2317017Sdim//
3317017Sdim//                     The LLVM Compiler Infrastructure
4317017Sdim//
5317017Sdim// This file is distributed under the University of Illinois Open Source
6317017Sdim// License. See LICENSE.TXT for details.
7317017Sdim//
8317017Sdim//===----------------------------------------------------------------------===//
9317017Sdim//
10317017Sdim// This file provides the Win32 specific implementation of Threading functions.
11317017Sdim//
12317017Sdim//===----------------------------------------------------------------------===//
13317017Sdim
14317017Sdim#include "llvm/ADT/SmallString.h"
15317017Sdim#include "llvm/ADT/Twine.h"
16317017Sdim
17317017Sdim#include "Windows/WindowsSupport.h"
18317017Sdim#include <process.h>
19317017Sdim
20317017Sdim// Windows will at times define MemoryFence.
21317017Sdim#ifdef MemoryFence
22317017Sdim#undef MemoryFence
23317017Sdim#endif
24317017Sdim
25317017Sdimnamespace {
26317017Sdim  struct ThreadInfo {
27317017Sdim    void(*func)(void*);
28317017Sdim    void *param;
29317017Sdim  };
30317017Sdim}
31317017Sdim
32317017Sdimstatic unsigned __stdcall ThreadCallback(void *param) {
33317017Sdim  struct ThreadInfo *info = reinterpret_cast<struct ThreadInfo *>(param);
34317017Sdim  info->func(info->param);
35317017Sdim
36317017Sdim  return 0;
37317017Sdim}
38317017Sdim
39317017Sdimvoid llvm::llvm_execute_on_thread(void(*Fn)(void*), void *UserData,
40317017Sdim  unsigned RequestedStackSize) {
41317017Sdim  struct ThreadInfo param = { Fn, UserData };
42317017Sdim
43317017Sdim  HANDLE hThread = (HANDLE)::_beginthreadex(NULL,
44317017Sdim    RequestedStackSize, ThreadCallback,
45317017Sdim    &param, 0, NULL);
46317017Sdim
47317017Sdim  if (hThread) {
48317017Sdim    // We actually don't care whether the wait succeeds or fails, in
49317017Sdim    // the same way we don't care whether the pthread_join call succeeds
50317017Sdim    // or fails.  There's not much we could do if this were to fail. But
51317017Sdim    // on success, this call will wait until the thread finishes executing
52317017Sdim    // before returning.
53317017Sdim    (void)::WaitForSingleObject(hThread, INFINITE);
54317017Sdim    ::CloseHandle(hThread);
55317017Sdim  }
56317017Sdim}
57317017Sdim
58317017Sdimuint64_t llvm::get_threadid() {
59317017Sdim  return uint64_t(::GetCurrentThreadId());
60317017Sdim}
61317017Sdim
62317017Sdimuint32_t llvm::get_max_thread_name_length() { return 0; }
63317017Sdim
64317017Sdim#if defined(_MSC_VER)
65317017Sdimstatic void SetThreadName(DWORD Id, LPCSTR Name) {
66317017Sdim  constexpr DWORD MS_VC_EXCEPTION = 0x406D1388;
67317017Sdim
68317017Sdim#pragma pack(push, 8)
69317017Sdim  struct THREADNAME_INFO {
70317017Sdim    DWORD dwType;     // Must be 0x1000.
71317017Sdim    LPCSTR szName;    // Pointer to thread name
72317017Sdim    DWORD dwThreadId; // Thread ID (-1 == current thread)
73317017Sdim    DWORD dwFlags;    // Reserved.  Do not use.
74317017Sdim  };
75317017Sdim#pragma pack(pop)
76317017Sdim
77317017Sdim  THREADNAME_INFO info;
78317017Sdim  info.dwType = 0x1000;
79317017Sdim  info.szName = Name;
80317017Sdim  info.dwThreadId = Id;
81317017Sdim  info.dwFlags = 0;
82317017Sdim
83317017Sdim  __try {
84317017Sdim    ::RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR),
85317017Sdim      (ULONG_PTR *)&info);
86317017Sdim  }
87317017Sdim  __except (EXCEPTION_EXECUTE_HANDLER) {
88317017Sdim  }
89317017Sdim}
90317017Sdim#endif
91317017Sdim
92317017Sdimvoid llvm::set_thread_name(const Twine &Name) {
93317017Sdim#if defined(_MSC_VER)
94317017Sdim  // Make sure the input is null terminated.
95317017Sdim  SmallString<64> Storage;
96317017Sdim  StringRef NameStr = Name.toNullTerminatedStringRef(Storage);
97317017Sdim  SetThreadName(::GetCurrentThreadId(), NameStr.data());
98317017Sdim#endif
99317017Sdim}
100317017Sdim
101317017Sdimvoid llvm::get_thread_name(SmallVectorImpl<char> &Name) {
102317017Sdim  // "Name" is not an inherent property of a thread on Windows.  In fact, when
103317017Sdim  // you "set" the name, you are only firing a one-time message to a debugger
104317017Sdim  // which it interprets as a program setting its threads' name.  We may be
105317017Sdim  // able to get fancy by creating a TLS entry when someone calls
106317017Sdim  // set_thread_name so that subsequent calls to get_thread_name return this
107317017Sdim  // value.
108317017Sdim  Name.clear();
109317017Sdim}
110