summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Support
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Support')
-rw-r--r--llvm/lib/Support/CrashRecoveryContext.cpp5
-rw-r--r--llvm/lib/Support/Threading.cpp51
-rw-r--r--llvm/lib/Support/Unix/Threading.inc63
-rw-r--r--llvm/lib/Support/Unix/Unix.h9
-rw-r--r--llvm/lib/Support/Windows/Process.inc7
-rw-r--r--llvm/lib/Support/Windows/Threading.inc50
-rw-r--r--llvm/lib/Support/Windows/WindowsSupport.h8
7 files changed, 132 insertions, 61 deletions
diff --git a/llvm/lib/Support/CrashRecoveryContext.cpp b/llvm/lib/Support/CrashRecoveryContext.cpp
index 9d13fce9cc5..8d8529b474f 100644
--- a/llvm/lib/Support/CrashRecoveryContext.cpp
+++ b/llvm/lib/Support/CrashRecoveryContext.cpp
@@ -404,7 +404,10 @@ bool CrashRecoveryContext::RunSafelyOnThread(function_ref<void()> Fn,
unsigned RequestedStackSize) {
bool UseBackgroundPriority = hasThreadBackgroundPriority();
RunSafelyOnThreadInfo Info = { Fn, this, UseBackgroundPriority, false };
- llvm_execute_on_thread(RunSafelyOnThread_Dispatch, &Info, RequestedStackSize);
+ llvm_execute_on_thread(RunSafelyOnThread_Dispatch, &Info,
+ RequestedStackSize == 0
+ ? llvm::None
+ : llvm::Optional<unsigned>(RequestedStackSize));
if (CrashRecoveryContextImpl *CRC = (CrashRecoveryContextImpl *)Impl)
CRC->setSwitchedThread();
return Info.Result;
diff --git a/llvm/lib/Support/Threading.cpp b/llvm/lib/Support/Threading.cpp
index e5899a60f4d..48750cef5ec 100644
--- a/llvm/lib/Support/Threading.cpp
+++ b/llvm/lib/Support/Threading.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/Threading.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/Config/config.h"
#include "llvm/Support/Host.h"
@@ -39,8 +40,8 @@ bool llvm::llvm_is_multithreaded() {
(!defined(_WIN32) && !defined(HAVE_PTHREAD_H))
// Support for non-Win32, non-pthread implementation.
void llvm::llvm_execute_on_thread(void (*Fn)(void *), void *UserData,
- unsigned RequestedStackSize) {
- (void)RequestedStackSize;
+ llvm::Optional<unsigned> StackSizeInBytes) {
+ (void)StackSizeInBytes;
Fn(UserData);
}
@@ -56,6 +57,25 @@ void llvm::set_thread_name(const Twine &Name) {}
void llvm::get_thread_name(SmallVectorImpl<char> &Name) { Name.clear(); }
+#if LLVM_ENABLE_THREADS == 0
+void llvm::llvm_execute_on_thread_async(
+ llvm::unique_function<void()> Func,
+ llvm::Optional<unsigned> StackSizeInBytes) {
+ (void)Func;
+ (void)StackSizeInBytes;
+ report_fatal_error("Spawning a detached thread doesn't make sense with no "
+ "threading support");
+}
+#else
+// Support for non-Win32, non-pthread implementation.
+void llvm::llvm_execute_on_thread_async(
+ llvm::unique_function<void()> Func,
+ llvm::Optional<unsigned> StackSizeInBytes) {
+ (void)StackSizeInBytes;
+ std::thread(std::move(Func)).detach();
+}
+#endif
+
#else
#include <thread>
@@ -84,6 +104,17 @@ unsigned llvm::hardware_concurrency() {
return 1;
}
+namespace {
+struct SyncThreadInfo {
+ void (*UserFn)(void *);
+ void *UserData;
+};
+
+using AsyncThreadInfo = llvm::unique_function<void()>;
+
+enum class JoiningPolicy { Join, Detach };
+} // namespace
+
// Include the platform-specific parts of this class.
#ifdef LLVM_ON_UNIX
#include "Unix/Threading.inc"
@@ -92,4 +123,20 @@ unsigned llvm::hardware_concurrency() {
#include "Windows/Threading.inc"
#endif
+void llvm::llvm_execute_on_thread(void (*Fn)(void *), void *UserData,
+ llvm::Optional<unsigned> StackSizeInBytes) {
+
+ SyncThreadInfo Info = {Fn, UserData};
+ llvm_execute_on_thread_impl(threadFuncSync, &Info, StackSizeInBytes,
+ JoiningPolicy::Join);
+}
+
+void llvm::llvm_execute_on_thread_async(
+ llvm::unique_function<void()> Func,
+ llvm::Optional<unsigned> StackSizeInBytes) {
+ llvm_execute_on_thread_impl(&threadFuncAsync,
+ new AsyncThreadInfo(std::move(Func)),
+ StackSizeInBytes, JoiningPolicy::Detach);
+}
+
#endif
diff --git a/llvm/lib/Support/Unix/Threading.inc b/llvm/lib/Support/Unix/Threading.inc
index ed9a9656305..afb887fc109 100644
--- a/llvm/lib/Support/Unix/Threading.inc
+++ b/llvm/lib/Support/Unix/Threading.inc
@@ -10,6 +10,8 @@
//
//===----------------------------------------------------------------------===//
+#include "Unix.h"
+#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
@@ -40,47 +42,56 @@
#include <unistd.h> // For syscall()
#endif
-namespace {
- struct ThreadInfo {
- void(*UserFn)(void *);
- void *UserData;
- };
+static void *threadFuncSync(void *Arg) {
+ SyncThreadInfo *TI = static_cast<SyncThreadInfo *>(Arg);
+ TI->UserFn(TI->UserData);
+ return nullptr;
}
-static void *ExecuteOnThread_Dispatch(void *Arg) {
- ThreadInfo *TI = reinterpret_cast<ThreadInfo*>(Arg);
- TI->UserFn(TI->UserData);
+static void *threadFuncAsync(void *Arg) {
+ std::unique_ptr<AsyncThreadInfo> Info(static_cast<AsyncThreadInfo *>(Arg));
+ (*Info)();
return nullptr;
}
-void llvm::llvm_execute_on_thread(void(*Fn)(void*), void *UserData,
- unsigned RequestedStackSize) {
- ThreadInfo Info = { Fn, UserData };
- pthread_attr_t Attr;
- pthread_t Thread;
+static void
+llvm_execute_on_thread_impl(void *(*ThreadFunc)(void *), void *Arg,
+ llvm::Optional<unsigned> StackSizeInBytes,
+ JoiningPolicy JP) {
+ int errnum;
// Construct the attributes object.
- if (::pthread_attr_init(&Attr) != 0)
- return;
+ pthread_attr_t Attr;
+ if ((errnum = ::pthread_attr_init(&Attr)) != 0) {
+ ReportErrnumFatal("pthread_attr_init failed", errnum);
+ }
+
+ auto AttrGuard = llvm::make_scope_exit([&] {
+ if ((errnum = ::pthread_attr_destroy(&Attr)) != 0) {
+ ReportErrnumFatal("pthread_attr_destroy failed", errnum);
+ }
+ });
// Set the requested stack size, if given.
- if (RequestedStackSize != 0) {
- if (::pthread_attr_setstacksize(&Attr, RequestedStackSize) != 0)
- goto error;
+ if (StackSizeInBytes) {
+ if ((errnum = ::pthread_attr_setstacksize(&Attr, *StackSizeInBytes)) != 0) {
+ ReportErrnumFatal("pthread_attr_setstacksize failed", errnum);
+ }
}
// Construct and execute the thread.
- if (::pthread_create(&Thread, &Attr, ExecuteOnThread_Dispatch, &Info) != 0)
- goto error;
-
- // Wait for the thread and clean up.
- ::pthread_join(Thread, nullptr);
+ pthread_t Thread;
+ if ((errnum = ::pthread_create(&Thread, &Attr, ThreadFunc, Arg)) != 0)
+ ReportErrnumFatal("pthread_create failed", errnum);
-error:
- ::pthread_attr_destroy(&Attr);
+ if (JP == JoiningPolicy::Join) {
+ // Wait for the thread
+ if ((errnum = ::pthread_join(Thread, nullptr)) != 0) {
+ ReportErrnumFatal("pthread_join failed", errnum);
+ }
+ }
}
-
uint64_t llvm::get_threadid() {
#if defined(__APPLE__)
// Calling "mach_thread_self()" bumps the reference count on the thread
diff --git a/llvm/lib/Support/Unix/Unix.h b/llvm/lib/Support/Unix/Unix.h
index 86309b0567f..1fc9a414f74 100644
--- a/llvm/lib/Support/Unix/Unix.h
+++ b/llvm/lib/Support/Unix/Unix.h
@@ -21,6 +21,7 @@
#include "llvm/Config/config.h"
#include "llvm/Support/Chrono.h"
#include "llvm/Support/Errno.h"
+#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
#include <assert.h>
#include <cerrno>
@@ -69,6 +70,14 @@ static inline bool MakeErrMsg(
return true;
}
+// Include StrError(errnum) in a fatal error message.
+LLVM_ATTRIBUTE_NORETURN static inline void ReportErrnumFatal(const char *Msg,
+ int errnum) {
+ std::string ErrMsg;
+ MakeErrMsg(&ErrMsg, Msg, errnum);
+ llvm::report_fatal_error(ErrMsg);
+}
+
namespace llvm {
namespace sys {
diff --git a/llvm/lib/Support/Windows/Process.inc b/llvm/lib/Support/Windows/Process.inc
index 4b91f9f7fc6..3526e3dee6f 100644
--- a/llvm/lib/Support/Windows/Process.inc
+++ b/llvm/lib/Support/Windows/Process.inc
@@ -439,13 +439,6 @@ const char *Process::ResetColor() {
return 0;
}
-// Include GetLastError() in a fatal error message.
-static void ReportLastErrorFatal(const char *Msg) {
- std::string ErrMsg;
- MakeErrMsg(&ErrMsg, Msg);
- report_fatal_error(ErrMsg);
-}
-
unsigned Process::GetRandomNumber() {
HCRYPTPROV HCPC;
if (!::CryptAcquireContextW(&HCPC, NULL, NULL, PROV_RSA_FULL,
diff --git a/llvm/lib/Support/Windows/Threading.inc b/llvm/lib/Support/Windows/Threading.inc
index 96649472cc9..83b47ea1e3d 100644
--- a/llvm/lib/Support/Windows/Threading.inc
+++ b/llvm/lib/Support/Windows/Threading.inc
@@ -21,36 +21,36 @@
#undef MemoryFence
#endif
-namespace {
- struct ThreadInfo {
- void(*func)(void*);
- void *param;
- };
+static unsigned __stdcall threadFuncSync(void *Arg) {
+ SyncThreadInfo *TI = static_cast<SyncThreadInfo *>(Arg);
+ TI->UserFn(TI->UserData);
+ return 0;
}
-static unsigned __stdcall ThreadCallback(void *param) {
- struct ThreadInfo *info = reinterpret_cast<struct ThreadInfo *>(param);
- info->func(info->param);
-
+static unsigned __stdcall threadFuncAsync(void *Arg) {
+ std::unique_ptr<AsyncThreadInfo> Info(static_cast<AsyncThreadInfo *>(Arg));
+ (*Info)();
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);
+static void
+llvm_execute_on_thread_impl(_beginthreadex_proc_type ThreadFunc, void *Arg,
+ llvm::Optional<unsigned> StackSizeInBytes,
+ JoiningPolicy JP) {
+ HANDLE hThread = (HANDLE)::_beginthreadex(
+ NULL, StackSizeInBytes.getValueOr(0), ThreadFunc, Arg, 0, NULL);
+
+ if (!hThread) {
+ ReportLastErrorFatal("_beginthreadex failed");
+ }
+
+ if (JP == JoiningPolicy::Join) {
+ if (::WaitForSingleObject(hThread, INFINITE) == WAIT_FAILED) {
+ ReportLastErrorFatal("WaitForSingleObject failed");
+ }
+ }
+ if (::CloseHandle(hThread) == FALSE) {
+ ReportLastErrorFatal("CloseHandle failed");
}
}
diff --git a/llvm/lib/Support/Windows/WindowsSupport.h b/llvm/lib/Support/Windows/WindowsSupport.h
index 2e2e97430b7..bb7e79b8601 100644
--- a/llvm/lib/Support/Windows/WindowsSupport.h
+++ b/llvm/lib/Support/Windows/WindowsSupport.h
@@ -41,6 +41,7 @@
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Chrono.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/VersionTuple.h"
#include <cassert>
#include <string>
@@ -66,6 +67,13 @@ llvm::VersionTuple GetWindowsOSVersion();
bool MakeErrMsg(std::string *ErrMsg, const std::string &prefix);
+// Include GetLastError() in a fatal error message.
+LLVM_ATTRIBUTE_NORETURN inline void ReportLastErrorFatal(const char *Msg) {
+ std::string ErrMsg;
+ MakeErrMsg(&ErrMsg, Msg);
+ llvm::report_fatal_error(ErrMsg);
+}
+
template <typename HandleTraits>
class ScopedHandle {
typedef typename HandleTraits::handle_type handle_type;
OpenPOWER on IntegriCloud