<div dir="ltr">Hi Chris,<br><br>This commit triggered a llvm/clang build failure on aarch64 host machine. The error message is like,<br><br>/bin/sh: line 1: 16677 Segmentation fault ../../../../bin/clang-tblgen -gen-arm-neon -I /work/slave/performance-daily/build/tools/clang/lib/Headers -I /work/slave/performance-daily/build/lib/Target -I /work/slave/performance-daily/build/include /work/slave/performance-daily/build/tools/clang/include/clang/Basic/<a href="http://arm_neon.td" target="_blank">arm_neon.td</a> -o /work/slave/performance-daily/build/build/tools/clang/lib/Headers/arm_neon.h.tmp<br><br>It seems pthread doesn't work well on aarch64 target, so the following code doesn't work.<br><br>+void llvm::call_once(once_flag& flag, void (*fptr)(void)) {<br>+  std::call_once(flag, fptr);<br>+}<br><br>Can we use the same solution as windows rather than call std::call_once directly?<br><br>Thanks,<br>-Jiangning<div><div><span style="color:red;font-family:'Courier New',courier,monotype,monospace;white-space:pre-wrap"><br></span></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">2014-10-31 6:07 GMT+08:00 Chris Bieneman <span dir="ltr"><<a href="mailto:beanz@apple.com" target="_blank">beanz@apple.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: cbieneman<br>
Date: Thu Oct 30 17:07:09 2014<br>
New Revision: 220932<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=220932&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=220932&view=rev</a><br>
Log:<br>
Removing the static initializer in ManagedStatic.cpp by using llvm_call_once to initialize the ManagedStatic mutex.<br>
<br>
Summary:<br>
This patch adds an llvm_call_once which is a wrapper around std::call_once on platforms where it is available and devoid of bugs. The patch also migrates the ManagedStatic mutex to be allocated using llvm_call_once.<br>
<br>
These changes are philosophically equivalent to the changes added in r219638, which were reverted due to a hang on Win32 which was the result of a bug in the Windows implementation of std::call_once.<br>
<br>
Reviewers: aaron.ballman, chapuni, chandlerc, rnk<br>
<br>
Reviewed By: rnk<br>
<br>
Subscribers: majnemer, llvm-commits<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D5922" target="_blank">http://reviews.llvm.org/D5922</a><br>
<br>
Added:<br>
    llvm/trunk/lib/Support/Unix/Threading.inc<br>
    llvm/trunk/lib/Support/Windows/Threading.inc<br>
Modified:<br>
    llvm/trunk/include/llvm/Support/Threading.h<br>
    llvm/trunk/lib/Support/CMakeLists.txt<br>
    llvm/trunk/lib/Support/ManagedStatic.cpp<br>
    llvm/trunk/lib/Support/Threading.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/Support/Threading.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/Threading.h?rev=220932&r1=220931&r2=220932&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/Threading.h?rev=220932&r1=220931&r2=220932&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Support/Threading.h (original)<br>
+++ llvm/trunk/include/llvm/Support/Threading.h Thu Oct 30 17:07:09 2014<br>
@@ -15,6 +15,14 @@<br>
 #ifndef LLVM_SUPPORT_THREADING_H<br>
 #define LLVM_SUPPORT_THREADING_H<br>
<br>
+#include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX<br>
+<br>
+#if defined(LLVM_ON_UNIX)<br>
+#include <mutex><br>
+#else<br>
+#include "llvm/Support/Atomic.h"<br>
+#endif<br>
+<br>
 namespace llvm {<br>
   /// Returns true if LLVM is compiled with support for multi-threading, and<br>
   /// false otherwise.<br>
@@ -33,6 +41,35 @@ namespace llvm {<br>
   /// the thread stack.<br>
   void llvm_execute_on_thread(void (*UserFn)(void*), void *UserData,<br>
                               unsigned RequestedStackSize = 0);<br>
+<br>
+#if defined(LLVM_ON_UNIX)<br>
+typedef std::once_flag once_flag;<br>
+#define LLVM_DEFINE_ONCE_FLAG(flag) static once_flag flag<br>
+#else<br>
+enum InitStatus {<br>
+  Done = -1,<br>
+  Uninitialized = 0,<br>
+  Wait = 1<br>
+};<br>
+typedef volatile sys::cas_flag once_flag;<br>
+<br>
+#define LLVM_DEFINE_ONCE_FLAG(flag) static once_flag flag = Uninitialized<br>
+#endif<br>
+<br>
+/// \brief Execute the function specified as a parameter once.<br>
+///<br>
+/// Typical usage:<br>
+/// \code<br>
+///   void foo() {...};<br>
+///   ...<br>
+///   LLVM_DEFINE_ONCE_FLAG(flag);<br>
+///   call_once(flag, foo);<br>
+/// \endcode<br>
+///<br>
+/// \param flag Flag used for tracking whether or not this has run.<br>
+/// \param UserFn Function to call once.<br>
+void call_once(once_flag&, void (*)(void));<br>
+<br>
 }<br>
<br>
 #endif<br>
<br>
Modified: llvm/trunk/lib/Support/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/CMakeLists.txt?rev=220932&r1=220931&r2=220932&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/CMakeLists.txt?rev=220932&r1=220931&r2=220932&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Support/CMakeLists.txt (original)<br>
+++ llvm/trunk/lib/Support/CMakeLists.txt Thu Oct 30 17:07:09 2014<br>
@@ -102,6 +102,7 @@ add_llvm_library(LLVMSupport<br>
   Unix/Program.inc<br>
   Unix/RWMutex.inc<br>
   Unix/Signals.inc<br>
+  Unix/Threading.inc<br>
   Unix/ThreadLocal.inc<br>
   Unix/TimeValue.inc<br>
   Unix/Watchdog.inc<br>
@@ -114,6 +115,7 @@ add_llvm_library(LLVMSupport<br>
   Windows/Program.inc<br>
   Windows/RWMutex.inc<br>
   Windows/Signals.inc<br>
+  Windows/Threading.inc<br>
   Windows/ThreadLocal.inc<br>
   Windows/TimeValue.inc<br>
   Windows/Watchdog.inc<br>
<br>
Modified: llvm/trunk/lib/Support/ManagedStatic.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/ManagedStatic.cpp?rev=220932&r1=220931&r2=220932&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/ManagedStatic.cpp?rev=220932&r1=220931&r2=220932&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Support/ManagedStatic.cpp (original)<br>
+++ llvm/trunk/lib/Support/ManagedStatic.cpp Thu Oct 30 17:07:09 2014<br>
@@ -16,16 +16,23 @@<br>
 #include "llvm/Support/Atomic.h"<br>
 #include "llvm/Support/Mutex.h"<br>
 #include "llvm/Support/MutexGuard.h"<br>
+#include "llvm/Support/Threading.h"<br>
 #include <cassert><br>
 using namespace llvm;<br>
<br>
 static const ManagedStaticBase *StaticList = nullptr;<br>
+static sys::Mutex *ManagedStaticMutex = nullptr;<br>
+LLVM_DEFINE_ONCE_FLAG(mutex_init_flag);<br>
<br>
-static sys::Mutex& getManagedStaticMutex() {<br>
+static void initializeMutex() {<br>
+  ManagedStaticMutex = new sys::Mutex();<br>
+}<br>
+<br>
+static sys::Mutex* getManagedStaticMutex() {<br>
   // We need to use a function local static here, since this can get called<br>
   // during a static constructor and we need to guarantee that it's initialized<br>
   // correctly.<br>
-  static sys::Mutex ManagedStaticMutex;<br>
+  call_once(mutex_init_flag, initializeMutex);<br>
   return ManagedStaticMutex;<br>
 }<br>
<br>
@@ -33,7 +40,7 @@ void ManagedStaticBase::RegisterManagedS<br>
                                               void (*Deleter)(void*)) const {<br>
   assert(Creator);<br>
   if (llvm_is_multithreaded()) {<br>
-    MutexGuard Lock(getManagedStaticMutex());<br>
+    MutexGuard Lock(*getManagedStaticMutex());<br>
<br>
     if (!Ptr) {<br>
       void* tmp = Creator();<br>
@@ -83,7 +90,7 @@ void ManagedStaticBase::destroy() const<br>
<br>
 /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.<br>
 void llvm::llvm_shutdown() {<br>
-  MutexGuard Lock(getManagedStaticMutex());<br>
+  MutexGuard Lock(*getManagedStaticMutex());<br>
<br>
   while (StaticList)<br>
     StaticList->destroy();<br>
<br>
Modified: llvm/trunk/lib/Support/Threading.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Threading.cpp?rev=220932&r1=220931&r2=220932&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Threading.cpp?rev=220932&r1=220931&r2=220932&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Support/Threading.cpp (original)<br>
+++ llvm/trunk/lib/Support/Threading.cpp Thu Oct 30 17:07:09 2014<br>
@@ -110,3 +110,10 @@ void llvm::llvm_execute_on_thread(void (<br>
 }<br>
<br>
 #endif<br>
+<br>
+#if defined(LLVM_ON_UNIX)<br>
+#include "Unix/Threading.inc"<br>
+#else<br>
+#include "Windows/Threading.inc"<br>
+#endif<br>
+<br>
<br>
Added: llvm/trunk/lib/Support/Unix/Threading.inc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Unix/Threading.inc?rev=220932&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Unix/Threading.inc?rev=220932&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Support/Unix/Threading.inc (added)<br>
+++ llvm/trunk/lib/Support/Unix/Threading.inc Thu Oct 30 17:07:09 2014<br>
@@ -0,0 +1,5 @@<br>
+#include <thread><br>
+<br>
+void llvm::call_once(once_flag& flag, void (*fptr)(void)) {<br>
+  std::call_once(flag, fptr);<br>
+}<br>
<br>
Added: llvm/trunk/lib/Support/Windows/Threading.inc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Windows/Threading.inc?rev=220932&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Windows/Threading.inc?rev=220932&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Support/Windows/Threading.inc (added)<br>
+++ llvm/trunk/lib/Support/Windows/Threading.inc Thu Oct 30 17:07:09 2014<br>
@@ -0,0 +1,19 @@<br>
+#include <winbase.h><br>
+<br>
+void llvm::call_once(once_flag &flag, void (*fptr)(void)) {<br>
+  while (flag != Done) {<br>
+    if (flag == Wait) {<br>
+      ::Sleep(1);<br>
+      continue;<br>
+    }<br>
+<br>
+    sys::cas_flag old_val = sys::CompareAndSwap(&flag, Wait, Uninitialized);<br>
+    if (old_val == Uninitialized) {<br>
+      fptr();<br>
+      sys::MemoryFence();<br>
+      flag = Done;<br>
+      return;<br>
+    }<br>
+  }<br>
+  sys::MemoryFence();<br>
+}<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>