| //===- Windows/Threading.inc - Win32 Threading Implementation - -*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file provides the Win32 specific implementation of Threading functions. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm/ADT/SmallString.h" |
| #include "llvm/ADT/Twine.h" |
| |
| #include "Windows/WindowsSupport.h" |
| #include <process.h> |
| |
| // Windows will at times define MemoryFence. |
| #ifdef MemoryFence |
| #undef MemoryFence |
| #endif |
| |
| namespace { |
| struct ThreadInfo { |
| void(*func)(void*); |
| void *param; |
| }; |
| } |
| |
| static unsigned __stdcall ThreadCallback(void *param) { |
| struct ThreadInfo *info = reinterpret_cast<struct ThreadInfo *>(param); |
| info->func(info->param); |
| |
| return 0; |
| } |
| |
| void llvm::llvm_execute_on_thread(void(*Fn)(void*), void *UserData, |
| unsigned RequestedStackSize) { |
| struct ThreadInfo param = { Fn, UserData }; |
| |
| HANDLE hThread = (HANDLE)::_beginthreadex(NULL, |
| RequestedStackSize, ThreadCallback, |
| ¶m, 0, NULL); |
| |
| if (hThread) { |
| // We actually don't care whether the wait succeeds or fails, in |
| // the same way we don't care whether the pthread_join call succeeds |
| // or fails. There's not much we could do if this were to fail. But |
| // on success, this call will wait until the thread finishes executing |
| // before returning. |
| (void)::WaitForSingleObject(hThread, INFINITE); |
| ::CloseHandle(hThread); |
| } |
| } |
| |
| uint64_t llvm::get_threadid() { |
| return uint64_t(::GetCurrentThreadId()); |
| } |
| |
| uint32_t llvm::get_max_thread_name_length() { return 0; } |
| |
| #if defined(_MSC_VER) |
| static void SetThreadName(DWORD Id, LPCSTR Name) { |
| constexpr DWORD MS_VC_EXCEPTION = 0x406D1388; |
| |
| #pragma pack(push, 8) |
| struct THREADNAME_INFO { |
| DWORD dwType; // Must be 0x1000. |
| LPCSTR szName; // Pointer to thread name |
| DWORD dwThreadId; // Thread ID (-1 == current thread) |
| DWORD dwFlags; // Reserved. Do not use. |
| }; |
| #pragma pack(pop) |
| |
| THREADNAME_INFO info; |
| info.dwType = 0x1000; |
| info.szName = Name; |
| info.dwThreadId = Id; |
| info.dwFlags = 0; |
| |
| __try { |
| ::RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), |
| (ULONG_PTR *)&info); |
| } |
| __except (EXCEPTION_EXECUTE_HANDLER) { |
| } |
| } |
| #endif |
| |
| void llvm::set_thread_name(const Twine &Name) { |
| #if defined(_MSC_VER) |
| // Make sure the input is null terminated. |
| SmallString<64> Storage; |
| StringRef NameStr = Name.toNullTerminatedStringRef(Storage); |
| SetThreadName(::GetCurrentThreadId(), NameStr.data()); |
| #endif |
| } |
| |
| void llvm::get_thread_name(SmallVectorImpl<char> &Name) { |
| // "Name" is not an inherent property of a thread on Windows. In fact, when |
| // you "set" the name, you are only firing a one-time message to a debugger |
| // which it interprets as a program setting its threads' name. We may be |
| // able to get fancy by creating a TLS entry when someone calls |
| // set_thread_name so that subsequent calls to get_thread_name return this |
| // value. |
| Name.clear(); |
| } |