From 63ce00b72f2420852a9d5dcb5b025d3320b7b989 Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Tue, 10 Jun 2014 23:15:43 +0000 Subject: [PATCH] Revert "Remove support for runtime multi-threading." This reverts revision r210600. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@210603 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm-c/Core.h | 13 +++++--- include/llvm/Support/ManagedStatic.h | 3 ++ include/llvm/Support/Threading.h | 46 ++++++++++++++-------------- lib/IR/Core.cpp | 3 +- lib/Support/ErrorHandling.cpp | 8 ++--- lib/Support/ManagedStatic.cpp | 6 ++-- lib/Support/Threading.cpp | 41 ++++++++++++++++++++++--- lib/Support/Timer.cpp | 3 +- 8 files changed, 80 insertions(+), 43 deletions(-) diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index 8693a3020ab..0e78ed71fa9 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -2848,13 +2848,16 @@ void LLVMDisposePassManager(LLVMPassManagerRef PM); * @{ */ -/** Deprecated: Multi-threading can only be enabled/disabled with the compile - time define LLVM_ENABLE_THREADS. This function always returns - LLVMIsMultithreaded(). */ +/** Allocate and initialize structures needed to make LLVM safe for + multithreading. The return value indicates whether multithreaded + initialization succeeded. Must be executed in isolation from all + other LLVM api calls. + @see llvm::llvm_start_multithreaded */ LLVMBool LLVMStartMultithreaded(void); -/** Deprecated: Multi-threading can only be enabled/disabled with the compile - time define LLVM_ENABLE_THREADS. */ +/** Deallocate structures necessary to make LLVM safe for multithreading. + Must be executed in isolation from all other LLVM api calls. + @see llvm::llvm_stop_multithreaded */ void LLVMStopMultithreaded(void); /** Check whether LLVM is executing in thread-safe mode or not. diff --git a/include/llvm/Support/ManagedStatic.h b/include/llvm/Support/ManagedStatic.h index d8fbfeb8e20..1bb8cea092f 100644 --- a/include/llvm/Support/ManagedStatic.h +++ b/include/llvm/Support/ManagedStatic.h @@ -103,6 +103,9 @@ void llvm_shutdown(); /// llvm_shutdown() when it is destroyed. struct llvm_shutdown_obj { llvm_shutdown_obj() { } + explicit llvm_shutdown_obj(bool multithreaded) { + if (multithreaded) llvm_start_multithreaded(); + } ~llvm_shutdown_obj() { llvm_shutdown(); } }; diff --git a/include/llvm/Support/Threading.h b/include/llvm/Support/Threading.h index 75b6ddbfda2..a7e8774558d 100644 --- a/include/llvm/Support/Threading.h +++ b/include/llvm/Support/Threading.h @@ -14,32 +14,32 @@ #ifndef LLVM_SUPPORT_THREADING_H #define LLVM_SUPPORT_THREADING_H -#include "llvm/Config/llvm-config.h" -#include "llvm/Support/Compiler.h" -#include - namespace llvm { + /// llvm_start_multithreaded - Allocate and initialize structures needed to + /// make LLVM safe for multithreading. The return value indicates whether + /// multithreaded initialization succeeded. LLVM will still be operational + /// on "failed" return, and will still be safe for hosting threading + /// applications in the JIT, but will not be safe for concurrent calls to the + /// LLVM APIs. + /// THIS MUST EXECUTE IN ISOLATION FROM ALL OTHER LLVM API CALLS. + bool llvm_start_multithreaded(); + + /// llvm_stop_multithreaded - Deallocate structures necessary to make LLVM + /// safe for multithreading. + /// THIS MUST EXECUTE IN ISOLATION FROM ALL OTHER LLVM API CALLS. + void llvm_stop_multithreaded(); + + /// llvm_is_multithreaded - Check whether LLVM is executing in thread-safe + /// mode or not. + bool llvm_is_multithreaded(); -#if LLVM_ENABLE_THREADS != 0 - typedef std::mutex mutex; - typedef std::recursive_mutex recursive_mutex; -#else - class null_mutex { - public: - void lock() { } - void unlock() { } - bool try_lock() { return true; } - }; - typedef null_mutex mutex; - typedef null_mutex recursive_mutex; -#endif - - /// llvm_get_global_lock() - returns the llvm global lock object. - llvm::recursive_mutex &llvm_get_global_lock(); + /// acquire_global_lock - Acquire the global lock. This is a no-op if called + /// before llvm_start_multithreaded(). + void llvm_acquire_global_lock(); - /// llvm_is_multithreaded() - returns true if LLVM is compiled with support - /// for multiple threads, and false otherwise. - bool llvm_is_multithreaded(); + /// release_global_lock - Release the global lock. This is a no-op if called + /// before llvm_start_multithreaded(). + void llvm_release_global_lock(); /// llvm_execute_on_thread - Execute the given \p UserFn on a separate /// thread, passing it the provided \p UserData. diff --git a/lib/IR/Core.cpp b/lib/IR/Core.cpp index 2bdc92da8fc..f24704c61cd 100644 --- a/lib/IR/Core.cpp +++ b/lib/IR/Core.cpp @@ -2702,10 +2702,11 @@ void LLVMDisposePassManager(LLVMPassManagerRef PM) { /*===-- Threading ------------------------------------------------------===*/ LLVMBool LLVMStartMultithreaded() { - return LLVMIsMultithreaded(); + return llvm_start_multithreaded(); } void LLVMStopMultithreaded() { + llvm_stop_multithreaded(); } LLVMBool LLVMIsMultithreaded() { diff --git a/lib/Support/ErrorHandling.cpp b/lib/Support/ErrorHandling.cpp index b9e4eabe926..342c4f05cc9 100644 --- a/lib/Support/ErrorHandling.cpp +++ b/lib/Support/ErrorHandling.cpp @@ -23,7 +23,6 @@ #include "llvm/Support/raw_ostream.h" #include #include -#include #if defined(HAVE_UNISTD_H) # include @@ -38,18 +37,16 @@ using namespace llvm; static fatal_error_handler_t ErrorHandler = nullptr; static void *ErrorHandlerUserData = nullptr; -static llvm::recursive_mutex ErrorHandlerMutex; - void llvm::install_fatal_error_handler(fatal_error_handler_t handler, void *user_data) { - std::lock_guard Lock(ErrorHandlerMutex); + assert(!llvm_is_multithreaded() && + "Cannot register error handlers after starting multithreaded mode!\n"); assert(!ErrorHandler && "Error handler already registered!\n"); ErrorHandler = handler; ErrorHandlerUserData = user_data; } void llvm::remove_fatal_error_handler() { - std::lock_guard Lock(ErrorHandlerMutex); ErrorHandler = nullptr; } @@ -66,7 +63,6 @@ void llvm::report_fatal_error(StringRef Reason, bool GenCrashDiag) { } void llvm::report_fatal_error(const Twine &Reason, bool GenCrashDiag) { - std::lock_guard Lock(ErrorHandlerMutex); if (ErrorHandler) { ErrorHandler(ErrorHandlerUserData, Reason.str(), GenCrashDiag); } else { diff --git a/lib/Support/ManagedStatic.cpp b/lib/Support/ManagedStatic.cpp index 74884d93304..6a1c2a545a8 100644 --- a/lib/Support/ManagedStatic.cpp +++ b/lib/Support/ManagedStatic.cpp @@ -15,7 +15,6 @@ #include "llvm/Config/config.h" #include "llvm/Support/Atomic.h" #include -#include using namespace llvm; static const ManagedStaticBase *StaticList = nullptr; @@ -24,7 +23,7 @@ void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(), void (*Deleter)(void*)) const { assert(Creator); if (llvm_is_multithreaded()) { - std::lock_guard Lock(llvm_get_global_lock()); + llvm_acquire_global_lock(); if (!Ptr) { void* tmp = Creator(); @@ -45,6 +44,7 @@ void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(), StaticList = this; } + llvm_release_global_lock(); } else { assert(!Ptr && !DeleterFn && !Next && "Partially initialized ManagedStatic!?"); @@ -77,4 +77,6 @@ void ManagedStaticBase::destroy() const { void llvm::llvm_shutdown() { while (StaticList) StaticList->destroy(); + + if (llvm_is_multithreaded()) llvm_stop_multithreaded(); } diff --git a/lib/Support/Threading.cpp b/lib/Support/Threading.cpp index c9f0f2c2e5a..1acfa79b11d 100644 --- a/lib/Support/Threading.cpp +++ b/lib/Support/Threading.cpp @@ -19,19 +19,50 @@ using namespace llvm; -llvm::recursive_mutex& llvm::llvm_get_global_lock() { - static llvm::recursive_mutex global_lock; - return global_lock; -} +static bool multithreaded_mode = false; -bool llvm::llvm_is_multithreaded() { +static sys::Mutex* global_lock = nullptr; + +bool llvm::llvm_start_multithreaded() { #if LLVM_ENABLE_THREADS != 0 + assert(!multithreaded_mode && "Already multithreaded!"); + multithreaded_mode = true; + global_lock = new sys::Mutex(true); + + // We fence here to ensure that all initialization is complete BEFORE we + // return from llvm_start_multithreaded(). + sys::MemoryFence(); return true; #else return false; #endif } +void llvm::llvm_stop_multithreaded() { +#if LLVM_ENABLE_THREADS != 0 + assert(multithreaded_mode && "Not currently multithreaded!"); + + // We fence here to insure that all threaded operations are complete BEFORE we + // return from llvm_stop_multithreaded(). + sys::MemoryFence(); + + multithreaded_mode = false; + delete global_lock; +#endif +} + +bool llvm::llvm_is_multithreaded() { + return multithreaded_mode; +} + +void llvm::llvm_acquire_global_lock() { + if (multithreaded_mode) global_lock->acquire(); +} + +void llvm::llvm_release_global_lock() { + if (multithreaded_mode) global_lock->release(); +} + #if LLVM_ENABLE_THREADS != 0 && defined(HAVE_PTHREAD_H) #include diff --git a/lib/Support/Timer.cpp b/lib/Support/Timer.cpp index cdab02b2fb7..61465ae5e8b 100644 --- a/lib/Support/Timer.cpp +++ b/lib/Support/Timer.cpp @@ -84,13 +84,14 @@ static TimerGroup *getDefaultTimerGroup() { sys::MemoryFence(); if (tmp) return tmp; - std::lock_guard Lock(llvm::llvm_get_global_lock()); + llvm_acquire_global_lock(); tmp = DefaultTimerGroup; if (!tmp) { tmp = new TimerGroup("Miscellaneous Ungrouped Timers"); sys::MemoryFence(); DefaultTimerGroup = tmp; } + llvm_release_global_lock(); return tmp; } -- 2.34.1