110 lines
3.1 KiB
C++
110 lines
3.1 KiB
C++
//===- 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();
|
|
}
|