From 2fc422f39ddaca25c69e8cf2092a9d66840379f3 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Sun, 30 Jun 2013 13:32:34 -0700 Subject: fixed memory leak due to implementation of LLThreadLocalSingleton removed LLThreadLocalSingleton collapsed all thread recorder classes to single type, LLTrace::ThreadRecorder moved fasttimer stack head to llthreadlocalsingletonpointer via ThreadRecorder --- indra/llcommon/lltracethreadrecorder.cpp | 117 +++++++++++++++---------------- 1 file changed, 58 insertions(+), 59 deletions(-) (limited to 'indra/llcommon/lltracethreadrecorder.cpp') diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp index d0f0328d1c..e88c5bf177 100644 --- a/indra/llcommon/lltracethreadrecorder.cpp +++ b/indra/llcommon/lltracethreadrecorder.cpp @@ -31,7 +31,7 @@ namespace LLTrace { -MasterThreadRecorder* gUIThreadRecorder = NULL; +ThreadRecorder* gUIThreadRecorder = NULL; /////////////////////////////////////////////////////////////////////// // ThreadRecorder @@ -39,11 +39,17 @@ MasterThreadRecorder* gUIThreadRecorder = NULL; ThreadRecorder::ThreadRecorder() { + init(); +} + +void ThreadRecorder::init() +{ + LLThreadLocalSingletonPointer::setInstance(&mBlockTimerStackRecord); //NB: the ordering of initialization in this function is very fragile due to a large number of implicit dependencies set_thread_recorder(this); TimeBlock& root_time_block = TimeBlock::getRootTimeBlock(); - ThreadTimerStack* timer_stack = ThreadTimerStack::getInstance(); + BlockTimerStackRecord* timer_stack = LLThreadLocalSingletonPointer::getInstance(); timer_stack->mTimeBlock = &root_time_block; timer_stack->mActiveTimer = NULL; @@ -71,8 +77,19 @@ ThreadRecorder::ThreadRecorder() TimeBlock::getRootTimeBlock().getPrimaryAccumulator()->mActiveCount = 1; } + +ThreadRecorder::ThreadRecorder(ThreadRecorder& master) +: mMasterRecorder(&master) +{ + init(); + mMasterRecorder->addChildRecorder(this); +} + + ThreadRecorder::~ThreadRecorder() { + LLThreadLocalSingletonPointer::setInstance(NULL); + deactivate(&mThreadRecordingBuffers); delete mRootTimer; @@ -85,6 +102,11 @@ ThreadRecorder::~ThreadRecorder() set_thread_recorder(NULL); delete[] mTimeBlockTreeNodes; + + if (mMasterRecorder) + { + mMasterRecorder->removeChildRecorder(this); + } } TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode( S32 index ) @@ -190,86 +212,63 @@ void ThreadRecorder::ActiveRecording::movePartialToTarget() } -/////////////////////////////////////////////////////////////////////// -// SlaveThreadRecorder -/////////////////////////////////////////////////////////////////////// - -SlaveThreadRecorder::SlaveThreadRecorder(MasterThreadRecorder& master) -: mMasterRecorder(master) -{ - mMasterRecorder.addSlaveThread(this); +// called by child thread +void ThreadRecorder::addChildRecorder( class ThreadRecorder* child ) +{ LLMutexLock lock(&mChildListMutex); + mChildThreadRecorders.push_back(child); } -SlaveThreadRecorder::~SlaveThreadRecorder() +// called by child thread +void ThreadRecorder::removeChildRecorder( class ThreadRecorder* child ) +{ LLMutexLock lock(&mChildListMutex); + +for (child_thread_recorder_list_t::iterator it = mChildThreadRecorders.begin(), end_it = mChildThreadRecorders.end(); + it != end_it; + ++it) { - mMasterRecorder.removeSlaveThread(this); + if ((*it) == child) + { + mChildThreadRecorders.erase(it); + break; + } +} } -void SlaveThreadRecorder::pushToMaster() -{ +void ThreadRecorder::pushToParent() +{ { LLMutexLock lock(&mSharedRecordingMutex); LLTrace::get_thread_recorder()->bringUpToDate(&mThreadRecordingBuffers); mSharedRecordingBuffers.append(mThreadRecordingBuffers); } } + + -/////////////////////////////////////////////////////////////////////// -// MasterThreadRecorder -/////////////////////////////////////////////////////////////////////// -static LLFastTimer::DeclareTimer FTM_PULL_TRACE_DATA_FROM_SLAVES("Pull slave trace data"); +static LLFastTimer::DeclareTimer FTM_PULL_TRACE_DATA_FROM_CHILDREN("Pull child thread trace data"); -void MasterThreadRecorder::pullFromSlaveThreads() +void ThreadRecorder::pullFromChildren() { - /*LLFastTimer _(FTM_PULL_TRACE_DATA_FROM_SLAVES); + LLFastTimer _(FTM_PULL_TRACE_DATA_FROM_CHILDREN); if (mActiveRecordings.empty()) return; - { LLMutexLock lock(&mSlaveListMutex); - - AccumulatorBufferGroup& target_recording_buffers = mActiveRecordings.back()->mPartialRecording; - target_recording_buffers.sync(); - for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end(); - it != end_it; - ++it) - { LLMutexLock lock(&(*it)->mSharedRecordingMutex); - - target_recording_buffers.merge((*it)->mSharedRecordingBuffers); - (*it)->mSharedRecordingBuffers.reset(); - } - }*/ -} + { LLMutexLock lock(&mChildListMutex); -// called by slave thread -void MasterThreadRecorder::addSlaveThread( class SlaveThreadRecorder* child ) -{ LLMutexLock lock(&mSlaveListMutex); + AccumulatorBufferGroup& target_recording_buffers = mActiveRecordings.back()->mPartialRecording; + target_recording_buffers.sync(); + for (child_thread_recorder_list_t::iterator it = mChildThreadRecorders.begin(), end_it = mChildThreadRecorders.end(); + it != end_it; + ++it) + { LLMutexLock lock(&(*it)->mSharedRecordingMutex); - mSlaveThreadRecorders.push_back(child); -} - -// called by slave thread -void MasterThreadRecorder::removeSlaveThread( class SlaveThreadRecorder* child ) -{ LLMutexLock lock(&mSlaveListMutex); - - for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end(); - it != end_it; - ++it) - { - if ((*it) == child) - { - mSlaveThreadRecorders.erase(it); - break; + target_recording_buffers.merge((*it)->mSharedRecordingBuffers); + (*it)->mSharedRecordingBuffers.reset(); } } } -void MasterThreadRecorder::pushToMaster() -{} - -MasterThreadRecorder::MasterThreadRecorder() -{} - -MasterThreadRecorder& getUIThreadRecorder() +ThreadRecorder& getUIThreadRecorder() { llassert(gUIThreadRecorder != NULL); return *gUIThreadRecorder; -- cgit v1.2.3