summaryrefslogtreecommitdiff
path: root/llvm/lib/Support/Windows/Threading.inc
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Support/Windows/Threading.inc')
-rw-r--r--llvm/lib/Support/Windows/Threading.inc124
1 files changed, 124 insertions, 0 deletions
diff --git a/llvm/lib/Support/Windows/Threading.inc b/llvm/lib/Support/Windows/Threading.inc
new file mode 100644
index 000000000000..96649472cc90
--- /dev/null
+++ b/llvm/lib/Support/Windows/Threading.inc
@@ -0,0 +1,124 @@
+//===- Windows/Threading.inc - Win32 Threading Implementation - -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides the Win32 specific implementation of Threading functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Twine.h"
+
+#include "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,
+ &param, 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();
+}
+
+SetThreadPriorityResult llvm::set_thread_priority(ThreadPriority Priority) {
+ // https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-setthreadpriority
+ // Begin background processing mode. The system lowers the resource scheduling
+ // priorities of the thread so that it can perform background work without
+ // significantly affecting activity in the foreground.
+ // End background processing mode. The system restores the resource scheduling
+ // priorities of the thread as they were before the thread entered background
+ // processing mode.
+ return SetThreadPriority(GetCurrentThread(),
+ Priority == ThreadPriority::Background
+ ? THREAD_MODE_BACKGROUND_BEGIN
+ : THREAD_MODE_BACKGROUND_END)
+ ? SetThreadPriorityResult::SUCCESS
+ : SetThreadPriorityResult::FAILURE;
+}