diff options
-rw-r--r-- | indra/llcommon/CMakeLists.txt | 1 | ||||
-rw-r--r-- | indra/llcommon/llapr.cpp | 82 | ||||
-rw-r--r-- | indra/llcommon/llapr.h | 117 | ||||
-rw-r--r-- | indra/llcommon/llcommon.cpp | 2 | ||||
-rw-r--r-- | indra/llcommon/llthread.cpp | 8 | ||||
-rw-r--r-- | indra/llcommon/llthread.h | 1 | ||||
-rw-r--r-- | indra/llcommon/llthreadlocalptr.h | 141 | ||||
-rw-r--r-- | indra/llcommon/lltrace.cpp | 16 | ||||
-rw-r--r-- | indra/llcommon/lltrace.h | 57 |
9 files changed, 249 insertions, 176 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index eec2695dde..f78751601c 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -240,7 +240,6 @@ set(llcommon_HEADER_FILES llstringtable.h llsys.h llthread.h - llthreadlocalptr.h llthreadsafequeue.h lltimer.h lltrace.h diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index d1c44c9403..76749f8a91 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -54,6 +54,8 @@ void ll_init_apr() { LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE) ; } + + LLThreadLocalPtrBase::initAllThreadLocalStorage(); } @@ -477,6 +479,86 @@ S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset) } // +//LLThreadLocalPtrBase +// +bool LLThreadLocalPtrBase::sInitialized = false; + +LLThreadLocalPtrBase::LLThreadLocalPtrBase(void (*cleanup_func)(void*)) +: mCleanupFunc(cleanup_func), + mThreadKey(NULL) +{ + if (sInitialized) + { + initStorage(); + } +} + +LLThreadLocalPtrBase::LLThreadLocalPtrBase( const LLThreadLocalPtrBase& other) +: mCleanupFunc(other.mCleanupFunc), + mThreadKey(NULL) +{ + if (sInitialized) + { + initStorage(); + } +} + +LLThreadLocalPtrBase::~LLThreadLocalPtrBase() +{ + destroyStorage(); +} + +void LLThreadLocalPtrBase::set( void* value ) +{ + llassert(sInitialized && mThreadKey); + + apr_status_t result = apr_threadkey_private_set((void*)value, mThreadKey); + if (result != APR_SUCCESS) + { + ll_apr_warn_status(result); + llerrs << "Failed to set thread local data" << llendl; + } +} + +void LLThreadLocalPtrBase::initStorage( ) +{ + apr_status_t result = apr_threadkey_private_create(&mThreadKey, mCleanupFunc, gAPRPoolp); + if (result != APR_SUCCESS) + { + ll_apr_warn_status(result); + llerrs << "Failed to allocate thread local data" << llendl; + } +} + +void LLThreadLocalPtrBase::destroyStorage() +{ + if (mThreadKey) + { + apr_status_t result = apr_threadkey_private_delete(mThreadKey); + if (result != APR_SUCCESS) + { + ll_apr_warn_status(result); + llerrs << "Failed to delete thread local data" << llendl; + } + } +} + +void LLThreadLocalPtrBase::initAllThreadLocalStorage() +{ + if (!sInitialized) + { + sInitialized = true; + for (LLInstanceTracker<LLThreadLocalPtrBase>::instance_iter it = beginInstances(), end_it = endInstances(); + it != end_it; + ++it) + { + (*it).initStorage(); + } + } +} + + +// //******************************************************************************************************************************* //static components of LLAPRFile // diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h index af33ce666f..eb0bf627a0 100644 --- a/indra/llcommon/llapr.h +++ b/indra/llcommon/llapr.h @@ -49,6 +49,7 @@ #include "apr_signal.h" #include "apr_atomic.h" #include "llstring.h" +#include "llinstancetracker.h" extern LL_COMMON_API apr_thread_mutex_t* gLogMutexp; extern apr_thread_mutex_t* gCallStacksLogMutexp; @@ -255,6 +256,122 @@ public: //******************************************************************************************************************************* }; +class LLThreadLocalPtrBase : LLInstanceTracker<LLThreadLocalPtrBase> +{ +public: + LLThreadLocalPtrBase(void (*cleanup_func)(void*) ); + LLThreadLocalPtrBase(const LLThreadLocalPtrBase& other); + ~LLThreadLocalPtrBase(); + +protected: + friend void LL_COMMON_API ll_init_apr(); + void set(void* value); + + LL_FORCE_INLINE void* get() + { + void* ptr; + //apr_status_t result = + apr_threadkey_private_get(&ptr, mThreadKey); + //if (result != APR_SUCCESS) + //{ + // ll_apr_warn_status(s); + // llerrs << "Failed to get thread local data" << llendl; + //} + return ptr; + } + + LL_FORCE_INLINE const void* get() const + { + void* ptr; + //apr_status_t result = + apr_threadkey_private_get(&ptr, mThreadKey); + //if (result != APR_SUCCESS) + //{ + // ll_apr_warn_status(s); + // llerrs << "Failed to get thread local data" << llendl; + //} + return ptr; + } + + void initStorage(); + + void destroyStorage(); + + static void initAllThreadLocalStorage(); + +private: + void (*mCleanupFunc)(void*); + apr_threadkey_t* mThreadKey; + static bool sInitialized; +}; + +template <typename T> +class LLThreadLocalPtr : public LLThreadLocalPtrBase +{ +public: + + LLThreadLocalPtr() + : LLThreadLocalPtrBase(&cleanup) + {} + + LLThreadLocalPtr(T* value) + : LLThreadLocalPtrBase(&cleanup) + { + set(value); + } + + + LLThreadLocalPtr(const LLThreadLocalPtr<T>& other) + : LLThreadLocalPtrBase(other, &cleanup) + { + set(other.get()); + } + + T* get() + { + return (T*)LLThreadLocalPtrBase::get(); + } + + const T* get() const + { + return (const T*)LLThreadLocalPtrBase::get(); + } + + T* operator -> () + { + return (T*)get(); + } + + const T* operator -> () const + { + return (T*)get(); + } + + T& operator*() + { + return *(T*)get(); + } + + const T& operator*() const + { + return *(T*)get(); + } + + LLThreadLocalPtr<T>& operator = (T* value) + { + set((void*)value); + return *this; + } + +private: + + static void cleanup(void* ptr) + { + delete reinterpret_cast<T*>(ptr); + } + +}; + /** * @brief Function which appropriately logs error or remains quiet on * APR_SUCCESS. diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp index 8be9e4f4de..512e7da840 100644 --- a/indra/llcommon/llcommon.cpp +++ b/indra/llcommon/llcommon.cpp @@ -44,6 +44,7 @@ void LLCommon::initClass() } LLTimer::initClass(); LLThreadSafeRefCount::initThreadSafeRefCount(); + LLTrace::init(); // LLWorkerThread::initClass(); // LLFrameCallbackManager::initClass(); } @@ -61,4 +62,5 @@ void LLCommon::cleanupClass() sAprInitialized = FALSE; } LLMemory::cleanupClass(); + LLTrace::cleanup(); } diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index f3ab8aa40c..023004eedd 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -66,9 +66,7 @@ U32 __thread LLThread::sThreadID = 0; #endif U32 LLThread::sIDIter = 0; - -LLTrace::MasterThreadTrace gMasterThreadTrace; -LLThreadLocalPtr<LLTrace::ThreadTraceData> LLThread::sTraceData(&gMasterThreadTrace); +LLThreadLocalPtr<LLTrace::ThreadTraceData> LLThread::sTraceData; LL_COMMON_API void assert_main_thread() @@ -87,7 +85,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap { LLThread *threadp = (LLThread *)datap; - sTraceData = new LLTrace::SlaveThreadTrace(gMasterThreadTrace); + sTraceData = new LLTrace::SlaveThreadTrace(); #if !LL_DARWIN sThreadIndex = threadp->mID; @@ -155,7 +153,7 @@ void LLThread::shutdown() //llinfos << "LLThread::~LLThread() Killing thread " << mName << " Status: " << mStatus << llendl; // Now wait a bit for the thread to exit // It's unclear whether I should even bother doing this - this destructor - // should netver get called unless we're already stopped, really... + // should never get called unless we're already stopped, really... S32 counter = 0; const S32 MAX_WAIT = 600; while (counter < MAX_WAIT) diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index e2de4c8b85..e50fa7653d 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -31,7 +31,6 @@ #include "llapr.h" #include "apr_thread_cond.h" #include "lltrace.h" -#include "llthreadlocalptr.h" class LL_COMMON_API LLThread { diff --git a/indra/llcommon/llthreadlocalptr.h b/indra/llcommon/llthreadlocalptr.h deleted file mode 100644 index f02f4849ca..0000000000 --- a/indra/llcommon/llthreadlocalptr.h +++ /dev/null @@ -1,141 +0,0 @@ -/** - * @file llthreadlocalptr.h - * @brief manage thread local storage through non-copyable pointer - * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2012, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLTHREAD_LOCAL_PTR_H -#define LL_LLTHREAD_LOCAL_PTR_H - -#include "llapr.h" - -template <typename T> -class LLThreadLocalPtr -{ -public: - LLThreadLocalPtr(T* value = NULL, apr_pool_t* pool = NULL) - { - apr_status_t result = apr_threadkey_private_create(&mThreadKey, cleanup, pool); - if (result != APR_SUCCESS) - { - ll_apr_warn_status(result); - llerrs << "Failed to allocate thread local data" << llendl; - } - set(value); - } - - - ~LLThreadLocalPtr() - { - apr_status_t result = apr_threadkey_private_delete(mThreadKey); - if (result != APR_SUCCESS) - { - ll_apr_warn_status(result); - llerrs << "Failed to delete thread local data" << llendl; - } - } - - T* operator -> () - { - return get(); - } - - const T* operator -> () const - { - return get(); - } - - T& operator*() - { - return *get(); - } - - const T& operator*() const - { - return *get(); - } - - LLThreadLocalPtr<T>& operator = (T* value) - { - set(value); - return *this; - } - - void copyFrom(const LLThreadLocalPtr<T>& other) - { - set(other.get()); - } - - LL_FORCE_INLINE void set(T* value) - { - apr_status_t result = apr_threadkey_private_set((void*)value, mThreadKey); - if (result != APR_SUCCESS) - { - ll_apr_warn_status(result); - llerrs << "Failed to set thread local data" << llendl; - } - } - - LL_FORCE_INLINE T* get() - { - T* ptr; - //apr_status_t result = - apr_threadkey_private_get((void**)&ptr, mThreadKey); - //if (result != APR_SUCCESS) - //{ - // ll_apr_warn_status(s); - // llerrs << "Failed to get thread local data" << llendl; - //} - return ptr; - } - - LL_FORCE_INLINE const T* get() const - { - T* ptr; - //apr_status_t result = - apr_threadkey_private_get((void**)&ptr, mThreadKey); - //if (result != APR_SUCCESS) - //{ - // ll_apr_warn_status(s); - // llerrs << "Failed to get thread local data" << llendl; - //} - return ptr; - } - - -private: - static void cleanup(void* ptr) - { - delete reinterpret_cast<T*>(ptr); - } - - LLThreadLocalPtr(const LLThreadLocalPtr<T>& other) - { - // do not copy construct - llassert(false); - } - - apr_threadkey_t* mThreadKey; -}; - -#endif // LL_LLTHREAD_LOCAL_PTR_H diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp index 037c52f8c1..501414ebf3 100644 --- a/indra/llcommon/lltrace.cpp +++ b/indra/llcommon/lltrace.cpp @@ -32,7 +32,21 @@ namespace LLTrace { BlockTimer::Recorder::StackEntry BlockTimer::sCurRecorder; -LLThreadLocalPtr<ThreadTraceData> ThreadTraceData::sCurThreadTrace; + +MasterThreadTrace *gMasterThreadTrace = NULL; +LLThreadLocalPtr<ThreadTraceData> gCurThreadTrace; + +void init() +{ + gMasterThreadTrace = new MasterThreadTrace(); + gCurThreadTrace = gMasterThreadTrace; +} + +void cleanup() +{ + delete gMasterThreadTrace; +} + /////////////////////////////////////////////////////////////////////// // Sampler diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h index 401ddfd6f3..3af05d67f9 100644 --- a/indra/llcommon/lltrace.h +++ b/indra/llcommon/lltrace.h @@ -32,7 +32,6 @@ #include "llmutex.h" #include "llmemory.h" -#include "llthreadlocalptr.h" #include <list> @@ -42,19 +41,29 @@ namespace LLTrace { + void init(); + void cleanup(); + + extern class MasterThreadTrace *gMasterThreadTrace; + extern LLThreadLocalPtr<class ThreadTraceData> gCurThreadTrace; + // one per thread per type template<typename ACCUMULATOR> class AccumulatorBuffer { static const U32 DEFAULT_ACCUMULATOR_BUFFER_SIZE = 64; - public: - AccumulatorBuffer() + private: + enum StaticAllocationMarker { STATIC_ALLOC }; + + AccumulatorBuffer(StaticAllocationMarker m) : mStorageSize(64), - mStorage(new ACCUMULATOR[DEFAULT_ACCUMULATOR_BUFFER_SIZE]), - mNextStorageSlot(0) - {} + mNextStorageSlot(0), + mStorage(new ACCUMULATOR[DEFAULT_ACCUMULATOR_BUFFER_SIZE]) + { + } + public: - AccumulatorBuffer(const AccumulatorBuffer& other) + AccumulatorBuffer(const AccumulatorBuffer& other = getDefaultBuffer()) : mStorageSize(other.mStorageSize), mStorage(new ACCUMULATOR[other.mStorageSize]), mNextStorageSlot(other.mNextStorageSlot) @@ -116,6 +125,12 @@ namespace LLTrace return next_slot; } + static AccumulatorBuffer<ACCUMULATOR>& getDefaultBuffer() + { + static AccumulatorBuffer sBuffer; + return sBuffer; + } + private: ACCUMULATOR* mStorage; size_t mStorageSize; @@ -125,22 +140,13 @@ namespace LLTrace template<typename ACCUMULATOR> LLThreadLocalPtr<ACCUMULATOR> AccumulatorBuffer<ACCUMULATOR>::sPrimaryStorage; template<typename ACCUMULATOR> - class PrimaryAccumulatorBuffer : public AccumulatorBuffer<ACCUMULATOR - { - PrimaryAccumulatorBuffer() - { - makePrimary(); - } - }; - - template<typename ACCUMULATOR> class Trace { public: Trace(const std::string& name) : mName(name) { - mAccumulatorIndex = getPrimaryBuffer().reserveSlot(); + mAccumulatorIndex = AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer().reserveSlot(); } LL_FORCE_INLINE ACCUMULATOR& getAccumulator() @@ -148,12 +154,6 @@ namespace LLTrace return AccumulatorBuffer<ACCUMULATOR>::getPrimaryStorage()[mAccumulatorIndex]; } - static PrimaryAccumulatorBuffer& getPrimaryBuffer() - { - static PrimaryAccumulatorBuffer sBuffer; - return sBuffer; - } - private: std::string mName; size_t mAccumulatorIndex; @@ -347,9 +347,13 @@ namespace LLTrace { public: Sampler() {} - Sampler(const Sampler& other); + Sampler(const Sampler& other) + : mF32Stats(other.mF32Stats), + mS32Stats(other.mS32Stats), + mTimers(other.mTimers) + {} - ~Sampler(); + ~Sampler() {} void makePrimary() { @@ -438,7 +442,6 @@ namespace LLTrace protected: Sampler mPrimarySampler; std::list<Sampler*> mActiveSamplers; - static LLThreadLocalPtr<ThreadTraceData> sCurThreadTrace; }; class MasterThreadTrace : public ThreadTraceData @@ -472,7 +475,7 @@ namespace LLTrace { public: explicit - SlaveThreadTrace(MasterThreadTrace& master_trace) + SlaveThreadTrace(MasterThreadTrace& master_trace = *gMasterThreadTrace) : mMaster(master_trace), ThreadTraceData(master_trace), mSharedData(mPrimarySampler) |