Kill the LLVM global lock.
authorZachary Turner <zturner@google.com>
Thu, 19 Jun 2014 16:17:42 +0000 (16:17 +0000)
committerZachary Turner <zturner@google.com>
Thu, 19 Jun 2014 16:17:42 +0000 (16:17 +0000)
This patch removes the LLVM global lock, and updates all existing
users of the global lock to use their own mutex.    None of the
existing users of the global lock were protecting code that was
mutually exclusive with any of the other users of the global
lock, so its purpose was not being met.

Reviewed by: rnk

Differential Revision: http://reviews.llvm.org/D4142

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211277 91177308-0d34-0410-b5e6-96231b3b80d8

docs/ProgrammersManual.rst
include/llvm/Support/Threading.h
lib/Support/ManagedStatic.cpp
lib/Support/Threading.cpp
lib/Support/Timer.cpp

index 4973e5c66719161d6e6883d58250e9b29b90e98d..df3795a34d33ff66267656793153d46a38ab6192 100644 (file)
@@ -2226,11 +2226,6 @@ Note that, because no other threads are allowed to issue LLVM API calls before
 ``llvm_start_multithreaded()`` returns, it is possible to have
 ``ManagedStatic``\ s of ``llvm::sys::Mutex``\ s.
 
-The ``llvm_acquire_global_lock()`` and ``llvm_release_global_lock`` APIs provide
-access to the global lock used to implement the double-checked locking for lazy
-initialization.  These should only be used internally to LLVM, and only if you
-know what you're doing!
-
 .. _llvmcontext:
 
 Achieving Isolation with ``LLVMContext``
index a7e8774558d5886e4462e74e014a569baf7481bb..d84d1186795854e91a1e460dac7edfd98f27da1a 100644 (file)
@@ -33,14 +33,6 @@ namespace llvm {
   /// mode or not.
   bool llvm_is_multithreaded();
 
-  /// acquire_global_lock - Acquire the global lock.  This is a no-op if called
-  /// before llvm_start_multithreaded().
-  void llvm_acquire_global_lock();
-
-  /// 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.
   ///
index 6a1c2a545a8d87f2a59ffed59c0542aa30caf32b..9d7e99f97fb5637c7f837abc834c0f238c174031 100644 (file)
 #include "llvm/Config/config.h"
 #include "llvm/Support/Atomic.h"
 #include <cassert>
+#include <mutex>
 using namespace llvm;
 
 static const ManagedStaticBase *StaticList = nullptr;
 
+// ManagedStatics can get created during execution of static constructors.  As a
+// result, we cannot use a global static std::mutex object for the lock since it
+// may not have been constructed.  Instead, we do a call-once initialization of
+// a pointer to a mutex.
+static std::once_flag MutexInitializationFlag;
+static std::recursive_mutex* ManagedStaticMutex = nullptr;
+
+// Not all supported platforms (in particular VS2012) have thread-safe function
+// static initialization, so roll our own.
+static std::recursive_mutex& GetManagedStaticMutex() {
+  std::call_once(MutexInitializationFlag,
+      []() { ManagedStaticMutex = new std::recursive_mutex(); } );
+
+  return *ManagedStaticMutex;
+}
+
 void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
                                               void (*Deleter)(void*)) const {
   assert(Creator);
   if (llvm_is_multithreaded()) {
-    llvm_acquire_global_lock();
+    std::lock_guard<std::recursive_mutex> Lock(GetManagedStaticMutex());
 
     if (!Ptr) {
       void* tmp = Creator();
@@ -43,8 +60,6 @@ void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
       Next = StaticList;
       StaticList = this;
     }
-
-    llvm_release_global_lock();
   } else {
     assert(!Ptr && !DeleterFn && !Next &&
            "Partially initialized ManagedStatic!?");
@@ -75,6 +90,8 @@ void ManagedStaticBase::destroy() const {
 
 /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
 void llvm::llvm_shutdown() {
+  std::lock_guard<std::recursive_mutex> Lock(GetManagedStaticMutex());
+
   while (StaticList)
     StaticList->destroy();
 
index 1acfa79b11d5835f60103057e16f4b5f377d6f39..2358dde0e6c5e3c703334dbc1a83ff8b2ac360f3 100644 (file)
@@ -21,13 +21,10 @@ using namespace llvm;
 
 static bool multithreaded_mode = false;
 
-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().
@@ -47,7 +44,6 @@ void llvm::llvm_stop_multithreaded() {
   sys::MemoryFence();
 
   multithreaded_mode = false;
-  delete global_lock;
 #endif
 }
 
@@ -55,14 +51,6 @@ 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 <pthread.h>
 
index 61465ae5e8be861a33d12058c38fa9c11cf50b9d..210bda754e74957db524630e2b1c18830702a707 100644 (file)
@@ -19,6 +19,7 @@
 #include "llvm/Support/Format.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/Mutex.h"
+#include "llvm/Support/MutexGuard.h"
 #include "llvm/Support/Process.h"
 #include "llvm/Support/raw_ostream.h"
 using namespace llvm;
@@ -84,14 +85,13 @@ static TimerGroup *getDefaultTimerGroup() {
   sys::MemoryFence();
   if (tmp) return tmp;
   
-  llvm_acquire_global_lock();
+  sys::SmartScopedLock<true> Lock(*TimerLock);
   tmp = DefaultTimerGroup;
   if (!tmp) {
     tmp = new TimerGroup("Miscellaneous Ungrouped Timers");
     sys::MemoryFence();
     DefaultTimerGroup = tmp;
   }
-  llvm_release_global_lock();
 
   return tmp;
 }