SH-3275 WIP Run viewer metrics for object update messages

moved LLThreadLocalPtr to llapr
fixed various startup race conditions for LLThreadLocalPtr
master
Richard Linden 2012-09-24 18:56:01 -07:00
parent 735fde8c74
commit adeeabfc13
9 changed files with 250 additions and 177 deletions

View File

@ -240,7 +240,6 @@ set(llcommon_HEADER_FILES
llstringtable.h
llsys.h
llthread.h
llthreadlocalptr.h
llthreadsafequeue.h
lltimer.h
lltrace.h

View File

@ -54,6 +54,8 @@ void ll_init_apr()
{
LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE) ;
}
LLThreadLocalPtrBase::initAllThreadLocalStorage();
}
@ -476,6 +478,86 @@ S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset)
return LLAPRFile::seek(mFile, where, 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

View File

@ -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.

View File

@ -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();
}

View File

@ -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)

View File

@ -31,7 +31,6 @@
#include "llapr.h"
#include "apr_thread_cond.h"
#include "lltrace.h"
#include "llthreadlocalptr.h"
class LL_COMMON_API LLThread
{

View File

@ -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

View File

@ -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

View File

@ -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()
: mStorageSize(64),
mStorage(new ACCUMULATOR[DEFAULT_ACCUMULATOR_BUFFER_SIZE]),
mNextStorageSlot(0)
{}
private:
enum StaticAllocationMarker { STATIC_ALLOC };
AccumulatorBuffer(const AccumulatorBuffer& other)
AccumulatorBuffer(StaticAllocationMarker m)
: mStorageSize(64),
mNextStorageSlot(0),
mStorage(new ACCUMULATOR[DEFAULT_ACCUMULATOR_BUFFER_SIZE])
{
}
public:
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;
@ -124,15 +139,6 @@ 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
{
@ -140,7 +146,7 @@ namespace LLTrace
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)