blob: c53624c0dc9d09cb2d65e3d1bb70c33b571a4738 [file] [log] [blame]
Zachary Turner757dbc92017-03-03 17:15:17 +00001//===- Windows/Threading.inc - Win32 Threading Implementation - -*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Zachary Turner757dbc92017-03-03 17:15:17 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file provides the Win32 specific implementation of Threading functions.
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm/ADT/SmallString.h"
14#include "llvm/ADT/Twine.h"
15
Zachary Turner4e839232019-01-08 21:05:34 +000016#include "WindowsSupport.h"
Zachary Turner757dbc92017-03-03 17:15:17 +000017#include <process.h>
18
19// Windows will at times define MemoryFence.
20#ifdef MemoryFence
21#undef MemoryFence
22#endif
23
24namespace {
25 struct ThreadInfo {
26 void(*func)(void*);
27 void *param;
28 };
29}
30
31static unsigned __stdcall ThreadCallback(void *param) {
32 struct ThreadInfo *info = reinterpret_cast<struct ThreadInfo *>(param);
33 info->func(info->param);
34
35 return 0;
36}
37
38void llvm::llvm_execute_on_thread(void(*Fn)(void*), void *UserData,
39 unsigned RequestedStackSize) {
40 struct ThreadInfo param = { Fn, UserData };
41
42 HANDLE hThread = (HANDLE)::_beginthreadex(NULL,
43 RequestedStackSize, ThreadCallback,
44 &param, 0, NULL);
45
46 if (hThread) {
47 // We actually don't care whether the wait succeeds or fails, in
48 // the same way we don't care whether the pthread_join call succeeds
49 // or fails. There's not much we could do if this were to fail. But
50 // on success, this call will wait until the thread finishes executing
51 // before returning.
52 (void)::WaitForSingleObject(hThread, INFINITE);
53 ::CloseHandle(hThread);
54 }
55}
56
57uint64_t llvm::get_threadid() {
58 return uint64_t(::GetCurrentThreadId());
59}
60
Zachary Turner1f004c42017-03-04 18:53:09 +000061uint32_t llvm::get_max_thread_name_length() { return 0; }
Zachary Turner777de772017-03-04 16:42:25 +000062
Zachary Turner757dbc92017-03-03 17:15:17 +000063#if defined(_MSC_VER)
Konstantin Zhuravlyov4203ea32017-03-07 20:09:46 +000064static void SetThreadName(DWORD Id, LPCSTR Name) {
Zachary Turner757dbc92017-03-03 17:15:17 +000065 constexpr DWORD MS_VC_EXCEPTION = 0x406D1388;
66
67#pragma pack(push, 8)
68 struct THREADNAME_INFO {
69 DWORD dwType; // Must be 0x1000.
70 LPCSTR szName; // Pointer to thread name
71 DWORD dwThreadId; // Thread ID (-1 == current thread)
72 DWORD dwFlags; // Reserved. Do not use.
73 };
74#pragma pack(pop)
75
76 THREADNAME_INFO info;
77 info.dwType = 0x1000;
Konstantin Zhuravlyov4203ea32017-03-07 20:09:46 +000078 info.szName = Name;
79 info.dwThreadId = Id;
Zachary Turner757dbc92017-03-03 17:15:17 +000080 info.dwFlags = 0;
81
82 __try {
83 ::RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR),
84 (ULONG_PTR *)&info);
85 }
86 __except (EXCEPTION_EXECUTE_HANDLER) {
87 }
Konstantin Zhuravlyov4203ea32017-03-07 20:09:46 +000088}
89#endif
90
91void llvm::set_thread_name(const Twine &Name) {
92#if defined(_MSC_VER)
93 // Make sure the input is null terminated.
94 SmallString<64> Storage;
95 StringRef NameStr = Name.toNullTerminatedStringRef(Storage);
96 SetThreadName(::GetCurrentThreadId(), NameStr.data());
Zachary Turner757dbc92017-03-03 17:15:17 +000097#endif
98}
99
100void llvm::get_thread_name(SmallVectorImpl<char> &Name) {
101 // "Name" is not an inherent property of a thread on Windows. In fact, when
102 // you "set" the name, you are only firing a one-time message to a debugger
103 // which it interprets as a program setting its threads' name. We may be
104 // able to get fancy by creating a TLS entry when someone calls
105 // set_thread_name so that subsequent calls to get_thread_name return this
106 // value.
107 Name.clear();
108}