1//===- Windows/Threading.inc - Win32 Threading Implementation - -*- C++ -*-===// 2// 3// 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 6// 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 16#include "WindowsSupport.h" 17#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 ¶m, 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 61uint32_t llvm::get_max_thread_name_length() { return 0; } 62 63#if defined(_MSC_VER) 64static void SetThreadName(DWORD Id, LPCSTR Name) { 65 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; 78 info.szName = Name; 79 info.dwThreadId = Id; 80 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 } 88} 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()); 97#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} 109 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} 125