diff options
author | Chandler Carruth <chandlerc@gmail.com> | 2016-06-02 18:22:12 +0000 |
---|---|---|
committer | Chandler Carruth <chandlerc@gmail.com> | 2016-06-02 18:22:12 +0000 |
commit | dd1463823a0c79bb7a1382839bdedb28c5541b41 (patch) | |
tree | 61f489816f61f5fbe08858b3a49c3ff4a0190696 /llvm/lib/Support/Threading.cpp | |
parent | 90db78816b9cc285254b8a4d8fcf5c0499dc2dad (diff) | |
download | bcm5719-llvm-dd1463823a0c79bb7a1382839bdedb28c5541b41.tar.gz bcm5719-llvm-dd1463823a0c79bb7a1382839bdedb28c5541b41.zip |
This is yet another attempt to re-instate r220932 as discussed in
D19271.
Previous attempt was broken by NetBSD, so in this version I've made the
fallback path generic rather than Windows specific and sent both Windows
and NetBSD to it.
I've also re-formatted the code some, and used an exact clone of the
code in PassSupport.h for doing manual call-once using our atomics
rather than rolling a new one.
If this sticks, we can replace the fallback path for Windows with
a Windows-specific implementation that is more reliable.
Original commit message:
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.
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.
Differential Revision: http://reviews.llvm.org/D5922
llvm-svn: 271558
Diffstat (limited to 'llvm/lib/Support/Threading.cpp')
-rw-r--r-- | llvm/lib/Support/Threading.cpp | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/llvm/lib/Support/Threading.cpp b/llvm/lib/Support/Threading.cpp index ca7f3f64aa3..a4e1e44261b 100644 --- a/llvm/lib/Support/Threading.cpp +++ b/llvm/lib/Support/Threading.cpp @@ -16,6 +16,7 @@ #include "llvm/Config/config.h" #include "llvm/Support/Atomic.h" #include "llvm/Support/Mutex.h" +#include "llvm/Support/thread.h" #include <cassert> using namespace llvm; @@ -110,3 +111,30 @@ void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData, } #endif + +void llvm::call_once(once_flag &flag, void (*fptr)(void)) { +#if LLVM_THREADING_USE_STD_CALL_ONCE + std::call_once(flag, fptr); +#else + // For other platforms we use a generic (if brittle) version based on our + // atomics. + sys::cas_flag old_val = sys::CompareAndSwap(&flag, Wait, Uninitialized); + if (old_val == Uninitialized) { + fptr(); + sys::MemoryFence(); + TsanIgnoreWritesBegin(); + TsanHappensBefore(&flag); + flag = Done; + TsanIgnoreWritesEnd(); + } else { + // Wait until any thread doing the call has finished. + sys::cas_flag tmp = flag; + sys::MemoryFence(); + while (tmp != Done) { + tmp = flag; + sys::MemoryFence(); + } + } + TsanHappensAfter(&flag); +#endif +} |