Make ManagedStatic registration thread-safe

As part of chromium:944811, LLVM_ENABLE_THREADS was turned off, but
since https://swiftshader-review.googlesource.com/c/SwiftShader/+/33484
we may invoke Reactor JIT-compilation on multiple threads. Instead of
re-enabling LLVM_ENABLE_THREADS wholesale, just make ManagedStatic
thread-safe.

Since sys::Mutex usage is not thread-safe without LLVM_ENABLE_THREADS,
use standard C++ synchronization primitives instead.

Note this change only affects the Subzero JIT backend, not the LLVM JIT.

Bug: chromium:950343
Change-Id: Ie70be4adb2c395459cb9bbd4f6699e0b04969c74
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/45328
Presubmit-Ready: Nicolas Capens <nicolascapens@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
diff --git a/third_party/llvm-subzero/lib/Support/ManagedStatic.cpp b/third_party/llvm-subzero/lib/Support/ManagedStatic.cpp
index 7dd3131..97e7470 100644
--- a/third_party/llvm-subzero/lib/Support/ManagedStatic.cpp
+++ b/third_party/llvm-subzero/lib/Support/ManagedStatic.cpp
@@ -12,22 +12,20 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Support/ManagedStatic.h"
-#include "llvm/Config/config.h"
-#include "llvm/Support/Mutex.h"
-#include "llvm/Support/MutexGuard.h"
 #include "llvm/Support/Threading.h"
 #include <cassert>
+#include <mutex>
 using namespace llvm;
 
 static const ManagedStaticBase *StaticList = nullptr;
-static sys::Mutex *ManagedStaticMutex = nullptr;
+static std::recursive_mutex *ManagedStaticMutex = nullptr;
 LLVM_DEFINE_ONCE_FLAG(mutex_init_flag);
 
 static void initializeMutex() {
-  ManagedStaticMutex = new sys::Mutex();
+  ManagedStaticMutex = new std::recursive_mutex();
 }
 
-static sys::Mutex* getManagedStaticMutex() {
+static std::recursive_mutex* getManagedStaticMutex() {
   // We need to use a function local static here, since this can get called
   // during a static constructor and we need to guarantee that it's initialized
   // correctly.
@@ -38,25 +36,14 @@
 void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
                                               void (*Deleter)(void*)) const {
   assert(Creator);
-  if (llvm_is_multithreaded()) {
-    MutexGuard Lock(*getManagedStaticMutex());
+  std::lock_guard<std::recursive_mutex> Lock(*getManagedStaticMutex());
 
-    if (!Ptr.load(std::memory_order_relaxed)) {
-      void *Tmp = Creator();
+  if (!Ptr.load(std::memory_order_relaxed)) {
+    void *Tmp = Creator();
 
-      Ptr.store(Tmp, std::memory_order_release);
-      DeleterFn = Deleter;
-      
-      // Add to list of managed statics.
-      Next = StaticList;
-      StaticList = this;
-    }
-  } else {
-    assert(!Ptr && !DeleterFn && !Next &&
-           "Partially initialized ManagedStatic!?");
-    Ptr = Creator();
+    Ptr.store(Tmp, std::memory_order_release);
     DeleterFn = Deleter;
-  
+
     // Add to list of managed statics.
     Next = StaticList;
     StaticList = this;
@@ -81,7 +68,7 @@
 
 /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
 void llvm::llvm_shutdown() {
-  MutexGuard Lock(*getManagedStaticMutex());
+  std::lock_guard<std::recursive_mutex> Lock(*getManagedStaticMutex());
 
   while (StaticList)
     StaticList->destroy();