SH-3275 WIP Run viewer metrics for object update messages
moved LLThreadLocalPtr to llapr fixed various startup race conditions for LLThreadLocalPtrmaster
parent
735fde8c74
commit
adeeabfc13
|
|
@ -240,7 +240,6 @@ set(llcommon_HEADER_FILES
|
|||
llstringtable.h
|
||||
llsys.h
|
||||
llthread.h
|
||||
llthreadlocalptr.h
|
||||
llthreadsafequeue.h
|
||||
lltimer.h
|
||||
lltrace.h
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
#include "llapr.h"
|
||||
#include "apr_thread_cond.h"
|
||||
#include "lltrace.h"
|
||||
#include "llthreadlocalptr.h"
|
||||
|
||||
class LL_COMMON_API LLThread
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue