blob: 83b47ea1e3df5e1a031704e8f843ae2ddfa60a4b [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
Sam McCalla9c3c172019-10-23 15:34:48 +020024static unsigned __stdcall threadFuncSync(void *Arg) {
25 SyncThreadInfo *TI = static_cast<SyncThreadInfo *>(Arg);
26 TI->UserFn(TI->UserData);
Zachary Turner757dbc92017-03-03 17:15:17 +000027 return 0;
28}
29
Sam McCalla9c3c172019-10-23 15:34:48 +020030static unsigned __stdcall threadFuncAsync(void *Arg) {
31 std::unique_ptr<AsyncThreadInfo> Info(static_cast<AsyncThreadInfo *>(Arg));
32 (*Info)();
33 return 0;
34}
Zachary Turner757dbc92017-03-03 17:15:17 +000035
Sam McCalla9c3c172019-10-23 15:34:48 +020036static void
37llvm_execute_on_thread_impl(_beginthreadex_proc_type ThreadFunc, void *Arg,
38 llvm::Optional<unsigned> StackSizeInBytes,
39 JoiningPolicy JP) {
40 HANDLE hThread = (HANDLE)::_beginthreadex(
41 NULL, StackSizeInBytes.getValueOr(0), ThreadFunc, Arg, 0, NULL);
Zachary Turner757dbc92017-03-03 17:15:17 +000042
Sam McCalla9c3c172019-10-23 15:34:48 +020043 if (!hThread) {
44 ReportLastErrorFatal("_beginthreadex failed");
45 }
46
47 if (JP == JoiningPolicy::Join) {
48 if (::WaitForSingleObject(hThread, INFINITE) == WAIT_FAILED) {
49 ReportLastErrorFatal("WaitForSingleObject failed");
50 }
51 }
52 if (::CloseHandle(hThread) == FALSE) {
53 ReportLastErrorFatal("CloseHandle failed");
Zachary Turner757dbc92017-03-03 17:15:17 +000054 }
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}
Kadir Cetinkaya8fdc5ab2019-04-16 14:32:43 +0000109
110SetThreadPriorityResult llvm::set_thread_priority(ThreadPriority Priority) {
111 // https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-setthreadpriority
112 // Begin background processing mode. The system lowers the resource scheduling
113 // priorities of the thread so that it can perform background work without
114 // significantly affecting activity in the foreground.
115 // End background processing mode. The system restores the resource scheduling
116 // priorities of the thread as they were before the thread entered background
117 // processing mode.
118 return SetThreadPriority(GetCurrentThread(),
119 Priority == ThreadPriority::Background
120 ? THREAD_MODE_BACKGROUND_BEGIN
121 : THREAD_MODE_BACKGROUND_END)
122 ? SetThreadPriorityResult::SUCCESS
123 : SetThreadPriorityResult::FAILURE;
124}