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 ¶m, 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