X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/b1ab9ed8d0e0f1c3b66d7daa8fd5564444c56195..e3d3b979fd185d8303f28a937baa53a187fb8c7d:/libsecurity_utilities/lib/globalizer.h?ds=inline diff --git a/libsecurity_utilities/lib/globalizer.h b/libsecurity_utilities/lib/globalizer.h index 4fe8e56a..8a7e91a1 100644 --- a/libsecurity_utilities/lib/globalizer.h +++ b/libsecurity_utilities/lib/globalizer.h @@ -31,6 +31,8 @@ #include #include #include +#include +#include namespace Security { @@ -52,51 +54,68 @@ public: }; -// -// A module-scope nexus is tied to the linker Nexus object itself. -// Its scope is all code accessing that particular Nexus object -// from within a process. Any number of ModuleNexus objects can -// exist, and each implements a different scope. -// -// IMPORTANT notes on this class can be found in globalizer.cpp. -// DO NOT change anything here before carefully reading them. -// class ModuleNexusCommon : public GlobalNexus { +private: + void do_create(void *(*make)()); + protected: void *create(void *(*make)()); - + void lock() {OSSpinLockLock(&access);} + void unlock() {OSSpinLockUnlock(&access);} + protected: - // both of these will be statically initialized to zero + // all of these will be statically initialized to zero void *pointer; - StaticAtomicCounter sync; + dispatch_once_t once; + OSSpinLock access; }; template class ModuleNexus : public ModuleNexusCommon { public: - Type &operator () () + Type &operator () () { - void *p = Atomic::load(pointer); // latch pointer - if (!p || (uintptr_t(p) & 0x1)) { - p = create(make); - secdebug("nexus", "module %s 0x%p", Debug::typeName().c_str(), pointer); - } - return *reinterpret_cast(p); + lock(); + + try + { + if (pointer == NULL) + { + pointer = create(make); + } + + unlock(); + } + catch (...) + { + unlock(); + throw; + } + + return *reinterpret_cast(pointer); } // does the object DEFINITELY exist already? bool exists() const { - return Atomic::load(pointer) != NULL; + bool result; + lock(); + result = pointer != NULL; + unlock(); + return result; } // destroy the object (if any) and start over - not really thread-safe void reset() { - if (pointer && !(uintptr_t(pointer) & 0x1)) { + lock(); + if (pointer != NULL) + { delete reinterpret_cast(pointer); - Atomic::store(0, pointer); + pointer = NULL; + once = 0; } + unlock(); } private: @@ -116,14 +135,6 @@ public: typedef std::set RetentionSet; -class ThreadNexusBase { -protected: - static ModuleNexus mInstanceLock; - static ModuleNexus mInstances; -}; - - - // // A thread-scope nexus is tied to a particular native thread AND // a particular nexus object. Its scope is all code in any one thread @@ -133,7 +144,7 @@ protected: // zero-initialization ThreadNexi, put them inside a ModuleNexus. // template -class ThreadNexus : public GlobalNexus, private ThreadNexusBase { +class ThreadNexus : public GlobalNexus { public: ThreadNexus() : mSlot(true) { } @@ -143,10 +154,6 @@ public: if (Type *p = mSlot) return *p; mSlot = new Type; - { - StLock _(mInstanceLock ()); - mInstances ().insert(mSlot); - } return *mSlot; }