From b4d97b78dfd0d14a788fa3cb876f67a9e666b99b Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Wed, 20 May 2009 00:39:20 +0000 Subject: [PATCH] Add llvm_start_multithreaded(), which starts up the LLVM internals in thread-safe mode. Provide double-check locking initialization of ManagedStatic's when running in thread-safe mode. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@72151 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/ManagedStatic.h | 44 +++++++++++++++++------ lib/Support/ManagedStatic.cpp | 53 +++++++++++++++++++++++----- 2 files changed, 78 insertions(+), 19 deletions(-) diff --git a/include/llvm/Support/ManagedStatic.h b/include/llvm/Support/ManagedStatic.h index d0298e495d3..7eecce3241d 100644 --- a/include/llvm/Support/ManagedStatic.h +++ b/include/llvm/Support/ManagedStatic.h @@ -14,8 +14,16 @@ #ifndef LLVM_SUPPORT_MANAGED_STATIC_H #define LLVM_SUPPORT_MANAGED_STATIC_H +#include "llvm/System/Atomic.h" + namespace llvm { +/// object_creator - Helper method for ManagedStatic. +template +void* object_creator() { + return new C(); +} + /// object_deleter - Helper method for ManagedStatic. /// template @@ -32,7 +40,7 @@ protected: mutable void (*DeleterFn)(void*); mutable const ManagedStaticBase *Next; - void RegisterManagedStatic(void *ObjPtr, void (*deleter)(void*)) const; + void RegisterManagedStatic(void *(*creator)(), void (*deleter)(void*)) const; public: /// isConstructed - Return true if this object has not been created yet. bool isConstructed() const { return Ptr != 0; } @@ -51,25 +59,32 @@ public: // Accessors. C &operator*() { - if (!Ptr) LazyInit(); + void* tmp = Ptr; + sys::MemoryFence(); + if (!tmp) RegisterManagedStatic(object_creator, object_deleter); + return *static_cast(Ptr); } C *operator->() { - if (!Ptr) LazyInit(); + void* tmp = Ptr; + sys::MemoryFence(); + if (!tmp) RegisterManagedStatic(object_creator, object_deleter); + return static_cast(Ptr); } const C &operator*() const { - if (!Ptr) LazyInit(); + void* tmp = Ptr; + sys::MemoryFence(); + if (!tmp) RegisterManagedStatic(object_creator, object_deleter); + return *static_cast(Ptr); } const C *operator->() const { - if (!Ptr) LazyInit(); - return static_cast(Ptr); - } + void* tmp = Ptr; + sys::MemoryFence(); + if (!tmp) RegisterManagedStatic(object_creator, object_deleter); -public: - void LazyInit() const { - RegisterManagedStatic(new C(), object_deleter); + return static_cast(Ptr); } }; @@ -80,6 +95,10 @@ public: }; +/// llvm_start_multithreaded - Allocate and initialize structures needed to +/// make LLVM safe for multithreading. +void llvm_start_multithreaded(); + /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. void llvm_shutdown(); @@ -87,7 +106,10 @@ void llvm_shutdown(); /// llvm_shutdown_obj - This is a simple helper class that calls /// llvm_shutdown() when it is destroyed. struct llvm_shutdown_obj { - llvm_shutdown_obj() {} + llvm_shutdown_obj() { } + explicit llvm_shutdown_obj(bool multithreaded) { + if (multithreaded) llvm_start_multithreaded(); + } ~llvm_shutdown_obj() { llvm_shutdown(); } }; diff --git a/lib/Support/ManagedStatic.cpp b/lib/Support/ManagedStatic.cpp index c365e013c6f..056b6c06c1e 100644 --- a/lib/Support/ManagedStatic.cpp +++ b/lib/Support/ManagedStatic.cpp @@ -12,21 +12,44 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/ManagedStatic.h" +#include "llvm/Config/config.h" +#include "llvm/System/Atomic.h" +#include "llvm/System/Mutex.h" #include using namespace llvm; static const ManagedStaticBase *StaticList = 0; -void ManagedStaticBase::RegisterManagedStatic(void *ObjPtr, +static sys::Mutex* ManagedStaticMutex = 0; + +void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(), void (*Deleter)(void*)) const { - assert(Ptr == 0 && DeleterFn == 0 && Next == 0 && - "Partially init static?"); - Ptr = ObjPtr; - DeleterFn = Deleter; + if (ManagedStaticMutex) { + ManagedStaticMutex->acquire(); + + if (Ptr == 0) { + void* tmp = Creator ? Creator() : 0; + + sys::MemoryFence(); + Ptr = tmp; + DeleterFn = Deleter; + + // Add to list of managed statics. + Next = StaticList; + StaticList = this; + } + + ManagedStaticMutex->release(); + } else { + assert(Ptr == 0 && DeleterFn == 0 && Next == 0 && + "Partially initialized ManagedStatic!?"); + Ptr = Creator ? Creator() : 0; + DeleterFn = Deleter; - // Add to list of managed statics. - Next = StaticList; - StaticList = this; + // Add to list of managed statics. + Next = StaticList; + StaticList = this; + } } void ManagedStaticBase::destroy() const { @@ -45,9 +68,23 @@ void ManagedStaticBase::destroy() const { DeleterFn = 0; } +void llvm::llvm_start_multithreaded() { +#if LLVM_MULTITHREADED + assert(ManagedStaticMutex == 0 && "Multithreaded LLVM already initialized!"); + ManagedStaticMutex = new sys::Mutex(true); +#else + assert(0 && "LLVM built without multithreading support!"); +#endif +} + /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. void llvm::llvm_shutdown() { while (StaticList) StaticList->destroy(); + + if (ManagedStaticMutex) { + delete ManagedStaticMutex; + ManagedStaticMutex = 0; + } }