summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llcommon/CMakeLists.txt1
-rw-r--r--indra/llcommon/llapr.cpp82
-rw-r--r--indra/llcommon/llapr.h117
-rw-r--r--indra/llcommon/llcommon.cpp2
-rw-r--r--indra/llcommon/llthread.cpp8
-rw-r--r--indra/llcommon/llthread.h1
-rw-r--r--indra/llcommon/llthreadlocalptr.h141
-rw-r--r--indra/llcommon/lltrace.cpp16
-rw-r--r--indra/llcommon/lltrace.h57
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)