[llvm] r274131 - [ManagedStatic] Reimplement double-checked locking with std::atomic.
Sean Silva via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 29 11:21:04 PDT 2016
Nice! IIRC when Davide was profiling LTO these fences were actually showing
up measurably in the profile!
-- Sean Silva
On Wed, Jun 29, 2016 at 8:04 AM, Benjamin Kramer via llvm-commits <
llvm-commits at lists.llvm.org> wrote:
> Author: d0k
> Date: Wed Jun 29 10:04:07 2016
> New Revision: 274131
>
> URL: http://llvm.org/viewvc/llvm-project?rev=274131&view=rev
> Log:
> [ManagedStatic] Reimplement double-checked locking with std::atomic.
>
> This gets rid of the memory fence in the hot path (dereferencing the
> ManagedStatic), trading for an extra mutex lock in the cold path (when
> the ManagedStatic was uninitialized). Since this only happens on the
> first accesses it shouldn't matter much. On strict architectures like
> x86 this removes any atomic instructions from the hot path.
>
> Also remove the tsan annotations, tsan knows how standard atomics work
> so they should be unnecessary now.
>
> Modified:
> llvm/trunk/include/llvm/Support/ManagedStatic.h
> llvm/trunk/lib/Support/ManagedStatic.cpp
>
> Modified: llvm/trunk/include/llvm/Support/ManagedStatic.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/ManagedStatic.h?rev=274131&r1=274130&r2=274131&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/Support/ManagedStatic.h (original)
> +++ llvm/trunk/include/llvm/Support/ManagedStatic.h Wed Jun 29 10:04:07
> 2016
> @@ -14,9 +14,9 @@
> #ifndef LLVM_SUPPORT_MANAGEDSTATIC_H
> #define LLVM_SUPPORT_MANAGEDSTATIC_H
>
> -#include "llvm/Support/Atomic.h"
> #include "llvm/Support/Compiler.h"
> -#include "llvm/Support/Threading.h"
> +#include <atomic>
> +#include <cstddef>
>
> namespace llvm {
>
> @@ -41,7 +41,7 @@ class ManagedStaticBase {
> protected:
> // This should only be used as a static variable, which guarantees that
> this
> // will be zero initialized.
> - mutable void *Ptr;
> + mutable std::atomic<void *> Ptr;
> mutable void (*DeleterFn)(void*);
> mutable const ManagedStaticBase *Next;
>
> @@ -61,40 +61,26 @@ public:
> template<class C>
> class ManagedStatic : public ManagedStaticBase {
> public:
> -
> // Accessors.
> C &operator*() {
> - void* tmp = Ptr;
> - if (llvm_is_multithreaded()) sys::MemoryFence();
> - if (!tmp) RegisterManagedStatic(object_creator<C>,
> object_deleter<C>::call);
> - TsanHappensAfter(this);
> + void *Tmp = Ptr.load(std::memory_order_acquire);
> + if (!Tmp)
> + RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
>
> - return *static_cast<C*>(Ptr);
> + return *static_cast<C *>(Ptr.load(std::memory_order_relaxed));
> }
> - C *operator->() {
> - void* tmp = Ptr;
> - if (llvm_is_multithreaded()) sys::MemoryFence();
> - if (!tmp) RegisterManagedStatic(object_creator<C>,
> object_deleter<C>::call);
> - TsanHappensAfter(this);
>
> - return static_cast<C*>(Ptr);
> - }
> + C *operator->() { return &**this; }
> +
> const C &operator*() const {
> - void* tmp = Ptr;
> - if (llvm_is_multithreaded()) sys::MemoryFence();
> - if (!tmp) RegisterManagedStatic(object_creator<C>,
> object_deleter<C>::call);
> - TsanHappensAfter(this);
> + void *Tmp = Ptr.load(std::memory_order_acquire);
> + if (!Tmp)
> + RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
>
> - return *static_cast<C*>(Ptr);
> + return *static_cast<C *>(Ptr.load(std::memory_order_relaxed));
> }
> - const C *operator->() const {
> - void* tmp = Ptr;
> - if (llvm_is_multithreaded()) sys::MemoryFence();
> - if (!tmp) RegisterManagedStatic(object_creator<C>,
> object_deleter<C>::call);
> - TsanHappensAfter(this);
>
> - return static_cast<C*>(Ptr);
> - }
> + const C *operator->() const { return &**this; }
> };
>
> /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
>
> Modified: llvm/trunk/lib/Support/ManagedStatic.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/ManagedStatic.cpp?rev=274131&r1=274130&r2=274131&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Support/ManagedStatic.cpp (original)
> +++ llvm/trunk/lib/Support/ManagedStatic.cpp Wed Jun 29 10:04:07 2016
> @@ -13,7 +13,6 @@
>
> #include "llvm/Support/ManagedStatic.h"
> #include "llvm/Config/config.h"
> -#include "llvm/Support/Atomic.h"
> #include "llvm/Support/Mutex.h"
> #include "llvm/Support/MutexGuard.h"
> #include "llvm/Support/Threading.h"
> @@ -42,18 +41,10 @@ void ManagedStaticBase::RegisterManagedS
> if (llvm_is_multithreaded()) {
> MutexGuard Lock(*getManagedStaticMutex());
>
> - if (!Ptr) {
> - void* tmp = Creator();
> + if (!Ptr.load(std::memory_order_relaxed)) {
> + void *Tmp = Creator();
>
> - TsanHappensBefore(this);
> - sys::MemoryFence();
> -
> - // This write is racy against the first read in the ManagedStatic
> - // accessors. The race is benign because it does a second read
> after a
> - // memory fence, at which point it isn't possible to get a partial
> value.
> - TsanIgnoreWritesBegin();
> - Ptr = tmp;
> - TsanIgnoreWritesEnd();
> + Ptr.store(Tmp, std::memory_order_release);
> DeleterFn = Deleter;
>
> // Add to list of managed statics.
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160629/a56b04f3/attachment.html>
More information about the llvm-commits
mailing list