diff options
Diffstat (limited to 'indra/llcommon')
-rw-r--r-- | indra/llcommon/CMakeLists.txt | 1 | ||||
-rw-r--r-- | indra/llcommon/llapr.cpp | 71 | ||||
-rw-r--r-- | indra/llcommon/llfasttimer.cpp | 28 | ||||
-rw-r--r-- | indra/llcommon/llfasttimer.h | 19 | ||||
-rw-r--r-- | indra/llcommon/llmemory.h | 14 | ||||
-rw-r--r-- | indra/llcommon/llthreadlocalstorage.cpp | 101 | ||||
-rw-r--r-- | indra/llcommon/llthreadlocalstorage.h | 109 | ||||
-rw-r--r-- | indra/llcommon/lltrace.h | 91 | ||||
-rw-r--r-- | indra/llcommon/lltracerecording.cpp | 46 | ||||
-rw-r--r-- | indra/llcommon/lltracerecording.h | 21 | ||||
-rw-r--r-- | indra/llcommon/lltracethreadrecorder.cpp | 6 | ||||
-rw-r--r-- | indra/llcommon/llunit.h | 8 |
12 files changed, 350 insertions, 165 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 7ed1671ca8..f8f1c010f7 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -98,6 +98,7 @@ set(llcommon_SOURCE_FILES llstringtable.cpp llsys.cpp llthread.cpp + llthreadlocalstorage.cpp llthreadsafequeue.cpp lltimer.cpp lltrace.cpp diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index 0556fadb26..47fa70614f 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -494,77 +494,6 @@ S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset) } // -//LLThreadLocalPointerBase -// -bool LLThreadLocalPointerBase::sInitialized = false; - -void LLThreadLocalPointerBase::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 LLThreadLocalPointerBase::initStorage( ) -{ - apr_status_t result = apr_threadkey_private_create(&mThreadKey, NULL, gAPRPoolp); - if (result != APR_SUCCESS) - { - ll_apr_warn_status(result); - llerrs << "Failed to allocate thread local data" << llendl; - } -} - -void LLThreadLocalPointerBase::destroyStorage() -{ - if (sInitialized) - { - 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 LLThreadLocalPointerBase::initAllThreadLocalStorage() -{ - if (!sInitialized) - { - for (LLInstanceTracker<LLThreadLocalPointerBase>::instance_iter it = beginInstances(), end_it = endInstances(); - it != end_it; - ++it) - { - (*it).initStorage(); - } - sInitialized = true; - } -} - -void LLThreadLocalPointerBase::destroyAllThreadLocalStorage() -{ - if (sInitialized) - { - //for (LLInstanceTracker<LLThreadLocalPointerBase>::instance_iter it = beginInstances(), end_it = endInstances(); - // it != end_it; - // ++it) - //{ - // (*it).destroyStorage(); - //} - sInitialized = false; - } -} - -// //******************************************************************************************************************************* //static components of LLAPRFile // diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp index e6233a094e..37332da31c 100644 --- a/indra/llcommon/llfasttimer.cpp +++ b/indra/llcommon/llfasttimer.cpp @@ -199,10 +199,11 @@ void TimeBlock::processTimes() { TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator(); - if (accumulator->mLastCaller) + if (accumulator->mLastAccumulator) { - timer.setParent(accumulator->mLastCaller); - accumulator->mParent = accumulator->mLastCaller; + TimeBlock* parent = accumulator->mLastAccumulator->mBlock; + timer.setParent(parent); + accumulator->mParent = parent; } // no need to push up tree on first use, flag can be set spuriously accumulator->mMoveUpTree = false; @@ -250,23 +251,22 @@ void TimeBlock::processTimes() // walk up stack of active timers and accumulate current time while leaving timing structures active BlockTimer* cur_timer = stack_record->mActiveTimer; - TimeBlockAccumulator* accumulator = stack_record->mTimeBlock->getPrimaryAccumulator(); + TimeBlockAccumulator* accumulator = stack_record->mAccumulator; // root defined by parent pointing to self while(cur_timer && cur_timer->mLastTimerData.mActiveTimer != cur_timer) { U64 cumulative_time_delta = cur_time - cur_timer->mStartTime; - U64 self_time_delta = cumulative_time_delta - stack_record->mChildTime; + accumulator->mChildTimeCounter += stack_record->mChildTime; stack_record->mChildTime = 0; - accumulator->mSelfTimeCounter += self_time_delta; accumulator->mTotalTimeCounter += cumulative_time_delta; cur_timer->mStartTime = cur_time; stack_record = &cur_timer->mLastTimerData; stack_record->mChildTime += cumulative_time_delta; - if (stack_record->mTimeBlock) + if (stack_record->mAccumulator) { - accumulator = stack_record->mTimeBlock->getPrimaryAccumulator(); + accumulator = stack_record->mAccumulator; } cur_timer = cur_timer->mLastTimerData.mActiveTimer; @@ -282,7 +282,7 @@ void TimeBlock::processTimes() TimeBlock& timer = *it; TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator(); - accumulator->mLastCaller = NULL; + accumulator->mLastAccumulator = NULL; accumulator->mMoveUpTree = false; } @@ -417,10 +417,10 @@ void TimeBlock::writeLog(std::ostream& os) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TimeBlockAccumulator::TimeBlockAccumulator() -: mSelfTimeCounter(0), +: mChildTimeCounter(0), mTotalTimeCounter(0), mCalls(0), - mLastCaller(NULL), + mLastAccumulator(NULL), mActiveCount(0), mMoveUpTree(false), mParent(NULL) @@ -428,10 +428,10 @@ TimeBlockAccumulator::TimeBlockAccumulator() void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other ) { - mSelfTimeCounter += other.mSelfTimeCounter; + mChildTimeCounter += other.mChildTimeCounter; mTotalTimeCounter += other.mTotalTimeCounter; mCalls += other.mCalls; - mLastCaller = other.mLastCaller; + mLastAccumulator = other.mLastAccumulator; mActiveCount = other.mActiveCount; mMoveUpTree = other.mMoveUpTree; mParent = other.mParent; @@ -440,7 +440,7 @@ void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other ) void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other ) { mTotalTimeCounter = 0; - mSelfTimeCounter = 0; + mChildTimeCounter = 0; mCalls = 0; } diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index fb2868ff98..2d87629561 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -40,9 +40,9 @@ namespace LLTrace struct BlockTimerStackRecord { - class BlockTimer* mActiveTimer; - class TimeBlock* mTimeBlock; - U64 mChildTime; + class BlockTimer* mActiveTimer; + class TimeBlockAccumulator* mAccumulator; + U64 mChildTime; }; class ThreadTimerStack @@ -277,7 +277,7 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer) mStartTime = TimeBlock::getCPUClockCount64(); BlockTimerStackRecord* cur_timer_data = ThreadTimerStack::getIfExists(); - TimeBlockAccumulator* accumulator = cur_timer_data->mTimeBlock->getPrimaryAccumulator(); + TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator(); accumulator->mActiveCount++; // keep current parent as long as it is active when we are accumulator->mMoveUpTree |= (accumulator->mParent->getPrimaryAccumulator()->mActiveCount == 0); @@ -286,7 +286,7 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer) mLastTimerData = *cur_timer_data; // push new information cur_timer_data->mActiveTimer = this; - cur_timer_data->mTimeBlock = &timer; + cur_timer_data->mAccumulator = accumulator; cur_timer_data->mChildTime = 0; #endif } @@ -296,21 +296,22 @@ LL_FORCE_INLINE BlockTimer::~BlockTimer() #if FAST_TIMER_ON U64 total_time = TimeBlock::getCPUClockCount64() - mStartTime; BlockTimerStackRecord* cur_timer_data = ThreadTimerStack::getIfExists(); - TimeBlockAccumulator* accumulator = cur_timer_data->mTimeBlock->getPrimaryAccumulator(); + TimeBlockAccumulator* accumulator = cur_timer_data->mAccumulator; accumulator->mCalls++; - accumulator->mSelfTimeCounter += total_time - cur_timer_data->mChildTime; + accumulator->mChildTimeCounter += cur_timer_data->mChildTime; accumulator->mTotalTimeCounter += total_time; accumulator->mActiveCount--; // store last caller to bootstrap tree creation // do this in the destructor in case of recursion to get topmost caller - accumulator->mLastCaller = mLastTimerData.mTimeBlock; + accumulator->mLastAccumulator = mLastTimerData.mAccumulator; // we are only tracking self time, so subtract our total time delta from parents mLastTimerData.mChildTime += total_time; - *ThreadTimerStack::getIfExists() = mLastTimerData; + //pop stack + *cur_timer_data = mLastTimerData; #endif } diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index 4ead45679f..95500753e4 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -39,6 +39,20 @@ class LLMutex ; #define LL_CHECK_MEMORY #endif +#if LL_WINDOWS +#define LL_ALIGN_OF __alignof +#else +#define LL_ALIGN_OF __align_of__ +#endif + +#if LL_WINDOWS +#define LL_DEFAULT_HEAP_ALIGN 8 +#elif LL_DARWIN +#define LL_DEFAULT_HEAP_ALIGN 16 +#elif LL_LINUX +#define LL_DEFAULT_HEAP_ALIGN 8 +#endif + inline void* ll_aligned_malloc( size_t size, int align ) { void* mem = malloc( size + (align - 1) + sizeof(void*) ); diff --git a/indra/llcommon/llthreadlocalstorage.cpp b/indra/llcommon/llthreadlocalstorage.cpp new file mode 100644 index 0000000000..7858ee5429 --- /dev/null +++ b/indra/llcommon/llthreadlocalstorage.cpp @@ -0,0 +1,101 @@ +/** + * @file llthreadlocalstorage.cpp + * @author Richard + * @date 2013-1-11 + * @brief implementation of thread local storage utility classes + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, 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$ + */ + +#include "linden_common.h" +#include "llthreadlocalstorage.h" + +// +//LLThreadLocalPointerBase +// +bool LLThreadLocalPointerBase::sInitialized = false; + +void LLThreadLocalPointerBase::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 LLThreadLocalPointerBase::initStorage( ) +{ + apr_status_t result = apr_threadkey_private_create(&mThreadKey, NULL, gAPRPoolp); + if (result != APR_SUCCESS) + { + ll_apr_warn_status(result); + llerrs << "Failed to allocate thread local data" << llendl; + } +} + +void LLThreadLocalPointerBase::destroyStorage() +{ + if (sInitialized) + { + 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 LLThreadLocalPointerBase::initAllThreadLocalStorage() +{ + if (!sInitialized) + { + for (LLInstanceTracker<LLThreadLocalPointerBase>::instance_iter it = beginInstances(), end_it = endInstances(); + it != end_it; + ++it) + { + (*it).initStorage(); + } + sInitialized = true; + } +} + +void LLThreadLocalPointerBase::destroyAllThreadLocalStorage() +{ + if (sInitialized) + { + //for (LLInstanceTracker<LLThreadLocalPointerBase>::instance_iter it = beginInstances(), end_it = endInstances(); + // it != end_it; + // ++it) + //{ + // (*it).destroyStorage(); + //} + sInitialized = false; + } +} diff --git a/indra/llcommon/llthreadlocalstorage.h b/indra/llcommon/llthreadlocalstorage.h index 5a38d54eea..c8b7c5e229 100644 --- a/indra/llcommon/llthreadlocalstorage.h +++ b/indra/llcommon/llthreadlocalstorage.h @@ -151,44 +151,66 @@ public: virtual ~LLThreadLocalSingleton() { - sInstance = NULL; - sInitState = DELETED; +#if LL_DARWIN + //pthread_setspecific(sInstanceKey, NULL); +#else + sInstance = NULL; +#endif + setInitState(DELETED); } static void deleteSingleton() { - delete sInstance; - sInstance = NULL; - sInitState = DELETED; + delete getIfExists(); } static DERIVED_TYPE* getInstance() { - if (sInitState == CONSTRUCTING) + EInitState init_state = getInitState(); + if (init_state == CONSTRUCTING) { llerrs << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << llendl; } - if (sInitState == DELETED) + if (init_state == DELETED) { llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl; } - if (!sInstance) + if (!getIfExists()) { - sInitState = CONSTRUCTING; - sInstance = new DERIVED_TYPE(); - sInitState = INITIALIZING; - sInstance->initSingleton(); - sInitState = INITIALIZED; + setInitState(CONSTRUCTING); + DERIVED_TYPE* instancep = new DERIVED_TYPE(); +#if LL_DARWIN + /*static S32 sKeyCreated = pthread_key_create(&sInstanceKey, NULL); + if (sKeyCreated != 0) + { + llerrs << "Could not create thread local storage" << llendl; + } + + S32 result = pthread_setspecific(sInstanceKey, (void*)instancep); + if (result != 0) + { + llerrs << "Could not set thread local storage" << llendl; + }*/ +#else + sInstance = instancep; +#endif + setInitState(INITIALIZING); + instancep->initSingleton(); + setInitState(INITIALIZED); } - return sInstance; + return getIfExists(); } static DERIVED_TYPE* getIfExists() { +#if LL_DARWIN + return NULL;//(DERIVED_TYPE*)pthread_getspecific(sInstanceKey); +#else return sInstance; +#endif } // Reference version of getInstance() @@ -202,16 +224,46 @@ public: // Use this to avoid accessing singletons before the can safely be constructed static bool instanceExists() { - return sInitState == INITIALIZED; + return getInitState() == INITIALIZED; } // Has this singleton already been deleted? // Use this to avoid accessing singletons from a static object's destructor static bool destroyed() { - return sInitState == DELETED; + return getInitState() == DELETED; } private: +#if LL_DARWIN + static EInitState& threadLocalInitState() + { + /*static S32 sKeyCreated = pthread_key_create(&sInitStateKey, NULL); + if (sKeyCreated != 0) + { + llerrs << "Could not create thread local storage" << llendl; + } + return *(EInitState*)pthread_getspecific(sInitStateKey);*/ + static EInitState state; + return state; + } +#endif + static EInitState getInitState() + { +#if LL_DARWIN + return threadLocalInitState(); +#else + return sInitState; +#endif + } + + static void setInitState(EInitState state) + { +#if LL_DARWIN + threadLocalInitState() = state; +#else + sInitState = state; +#endif + } LLThreadLocalSingleton(const LLThreadLocalSingleton& other); virtual void initSingleton() {} @@ -221,10 +273,13 @@ private: #elif LL_LINUX static __thread DERIVED_TYPE* sInstance; static __thread EInitState sInitState; +#elif LL_DARWIN + //static pthread_key_t sInstanceKey; + //static pthread_key_t sInitStateKey; #endif }; -#ifdef LL_WINDOWS +#if LL_WINDOWS template<typename DERIVED_TYPE> __declspec(thread) DERIVED_TYPE* LLThreadLocalSingleton<DERIVED_TYPE>::sInstance = NULL; @@ -236,6 +291,12 @@ __thread DERIVED_TYPE* LLThreadLocalSingleton<DERIVED_TYPE>::sInstance = NULL; template<typename DERIVED_TYPE> __thread typename LLThreadLocalSingleton<DERIVED_TYPE>::EInitState LLThreadLocalSingleton<DERIVED_TYPE>::sInitState = LLThreadLocalSingleton<DERIVED_TYPE>::UNINITIALIZED; +#elif LL_DARWIN +/*template<typename DERIVED_TYPE> +pthread_key_t LLThreadLocalSingleton<DERIVED_TYPE>::sInstanceKey; + +template<typename DERIVED_TYPE> +pthread_key_t LLThreadLocalSingleton<DERIVED_TYPE>::sInitStateKey;*/ #endif template<typename DERIVED_TYPE> @@ -249,7 +310,11 @@ public: LL_FORCE_INLINE static DERIVED_TYPE* getInstance() { +#if LL_DARWIN + return sInstance.get(); +#else return sInstance; +#endif } LL_FORCE_INLINE static void setInstance(DERIVED_TYPE* instance) @@ -258,18 +323,24 @@ public: } private: -#ifdef LL_WINDOWS +#if LL_WINDOWS static __declspec(thread) DERIVED_TYPE* sInstance; #elif LL_LINUX static __thread DERIVED_TYPE* sInstance; +#elif LL_DARWIN + static LLThreadLocalPointer<DERIVED_TYPE> sInstance; #endif }; +#if LL_WINDOWS template<typename DERIVED_TYPE> -#ifdef LL_WINDOWS __declspec(thread) DERIVED_TYPE* LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstance = NULL; #elif LL_LINUX +template<typename DERIVED_TYPE> __thread DERIVED_TYPE* LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstance = NULL; +#elif LL_DARWIN +template<typename DERIVED_TYPE> +LLThreadLocalPointer<DERIVED_TYPE> LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstance; #endif #endif // LL_LLTHREADLOCALSTORAGE_H diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h index 1a156e583e..1d3c376a58 100644 --- a/indra/llcommon/lltrace.h +++ b/indra/llcommon/lltrace.h @@ -446,11 +446,12 @@ namespace LLTrace // // members // - U64 mSelfTimeCounter, + U64 mChildTimeCounter, mTotalTimeCounter; U32 mCalls; + class TimeBlock* mBlock; // block associated with this accumulator class TimeBlock* mParent; // last acknowledged parent of this time block - class TimeBlock* mLastCaller; // used to bootstrap tree construction + TimeBlockAccumulator* mLastAccumulator; // used to bootstrap tree construction U16 mActiveCount; // number of timers with this ID active on stack bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame @@ -660,7 +661,58 @@ struct MemFootprint<std::list<T> > } }; -template<typename DERIVED> +template <size_t ALIGNMENT, size_t RESERVE> +void* allocAligned(size_t size) +{ + llstatic_assert((ALIGNMENT > 0) && (ALIGNMENT & (ALIGNMENT - 1)) == 0, "Alignment must be a power of 2"); + + void* padded_allocation; + const size_t aligned_reserve = (RESERVE / ALIGNMENT) + + ((RESERVE % ALIGNMENT) ? ALIGNMENT : 0); + const size_t size_with_reserve = size + aligned_reserve; + if (ALIGNMENT <= LL_DEFAULT_HEAP_ALIGN) + { + padded_allocation = malloc(size_with_reserve); + } + else + { +#if LL_WINDOWS + padded_allocation = _aligned_malloc(size_with_reserve, ALIGNMENT); +#elif LL_DARWIN + padded_allocation = ll_aligned_malloc(size_with_reserve, ALIGNMENT); +#else + if (LL_UNLIKELY(0 != posix_memalign(&padded_allocation, 16, size))) + padded_allocation = NULL; +#endif + } + return (char*)padded_allocation + aligned_reserve; +} + +template<size_t ALIGNMENT, size_t RESERVE> +void deallocAligned(void* ptr) +{ + const size_t aligned_reserve = (RESERVE / ALIGNMENT) + + ((RESERVE % ALIGNMENT) ? ALIGNMENT : 0); + + void* original_allocation = (char*)ptr - aligned_reserve; + + if (ALIGNMENT <= LL_DEFAULT_HEAP_ALIGN) + { + free(original_allocation); + } + else + { +#if LL_WINDOWS + _aligned_free(original_allocation); +#elif LL_DARWIN + ll_aligned_free(original_allocation); +#else + free(original_allocation); +#endif + } +} + +template<typename DERIVED, size_t ALIGNMENT = LL_DEFAULT_HEAP_ALIGN> class MemTrackable { template<typename TRACKED, typename TRACKED_IS_TRACKER> @@ -676,44 +728,49 @@ public: memDisclaim(mMemFootprint); } - void* operator new(size_t allocation_size) + void* operator new(size_t size) { - // reserve 8 bytes for allocation size (and preserving 8 byte alignment of structs) - void* allocation = ::operator new(allocation_size + 8); - *(size_t*)allocation = allocation_size; MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator(); if (accumulator) { - accumulator->mSize += allocation_size; + accumulator->mSize += size; accumulator->mAllocatedCount++; } - return (void*)((char*)allocation + 8); + + // reserve 4 bytes for allocation size (and preserving requested alignment) + void* allocation = allocAligned<ALIGNMENT, sizeof(size_t)>(size); + ((size_t*)allocation)[-1] = size; + + return allocation; } void operator delete(void* ptr) { - size_t* allocation_size = (size_t*)((char*)ptr - 8); + size_t allocation_size = ((size_t*)ptr)[-1]; MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator(); if (accumulator) { - accumulator->mSize -= *allocation_size; + accumulator->mSize -= allocation_size; accumulator->mAllocatedCount--; accumulator->mDeallocatedCount++; } - ::delete((char*)ptr - 8); + deallocAligned<ALIGNMENT, sizeof(size_t)>(ptr); } void *operator new [](size_t size) { - size_t* result = (size_t*)malloc(size + 8); - *result = size; MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator(); if (accumulator) { accumulator->mSize += size; accumulator->mAllocatedCount++; } - return (void*)((char*)result + 8); + + // reserve 4 bytes for allocation size (and preserving requested alignment) + void* allocation = allocAligned<ALIGNMENT, sizeof(size_t)>(size); + ((size_t*)allocation)[-1] = size; + + return allocation; } void operator delete[](void* ptr) @@ -726,7 +783,7 @@ public: accumulator->mAllocatedCount--; accumulator->mDeallocatedCount++; } - ::delete[]((char*)ptr - 8); + deallocAligned<ALIGNMENT, sizeof(size_t)>(ptr); } // claim memory associated with other objects/data as our own, adding to our calculated footprint @@ -783,6 +840,8 @@ public: private: size_t mMemFootprint; + + template<typename TRACKED, typename TRACKED_IS_TRACKER = void> struct TrackMemImpl { diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp index c110e64380..f45226eb9a 100644 --- a/indra/llcommon/lltracerecording.cpp +++ b/indra/llcommon/lltracerecording.cpp @@ -60,7 +60,7 @@ Recording::Recording( const Recording& other ) mStackTimers = other.mStackTimers; mMemStats = other.mMemStats; - LLStopWatchControlsMixin<Recording>::initTo(other.getPlayState()); + LLStopWatchControlsMixin<Recording>::setPlayState(other.getPlayState()); } @@ -179,7 +179,7 @@ LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumul LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const { - return (F64)(*mStackTimers)[stat.getIndex()].mSelfTimeCounter / (F64)LLTrace::TimeBlock::countsPerSecond(); + return ((F64)(*mStackTimers)[stat.getIndex()].mTotalTimeCounter - (F64)(*mStackTimers)[stat.getIndex()].mChildTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond(); } @@ -195,7 +195,7 @@ LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccu LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const { - return (F64)(*mStackTimers)[stat.getIndex()].mSelfTimeCounter / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds); + return ((F64)(*mStackTimers)[stat.getIndex()].mTotalTimeCounter - (F64)(*mStackTimers)[stat.getIndex()].mChildTimeCounter) / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds); } F32 Recording::getPerSec(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat) const @@ -345,14 +345,14 @@ U32 Recording::getSampleCount( const TraceType<MeasurementAccumulator<S64> >& st // PeriodicRecording /////////////////////////////////////////////////////////////////////// -PeriodicRecording::PeriodicRecording( S32 num_periods, EStopWatchState state) +PeriodicRecording::PeriodicRecording( S32 num_periods, EPlayState state) : mNumPeriods(num_periods), mCurPeriod(0), mTotalValid(false), mRecordingPeriods( new Recording[num_periods]) { llassert(mNumPeriods > 0); - initTo(state); + setPlayState(state); } PeriodicRecording::PeriodicRecording(PeriodicRecording& other) @@ -377,7 +377,7 @@ PeriodicRecording::~PeriodicRecording() void PeriodicRecording::nextPeriod() { - EStopWatchState play_state = getPlayState(); + EPlayState play_state = getPlayState(); Recording& old_recording = getCurRecordingPeriod(); mCurPeriod = (mCurPeriod + 1) % mNumPeriods; old_recording.splitTo(getCurRecordingPeriod()); @@ -458,8 +458,14 @@ void PeriodicRecording::splitFrom(PeriodicRecording& other) void ExtendableRecording::extend() { + // stop recording to get latest data + mPotentialRecording.stop(); + // push the data back to accepted recording mAcceptedRecording.appendRecording(mPotentialRecording); + // flush data, so we can start from scratch mPotentialRecording.reset(); + // go back to play state we were in initially + mPotentialRecording.setPlayState(getPlayState()); } void ExtendableRecording::start() @@ -514,7 +520,7 @@ PeriodicRecording& get_frame_recording() void LLStopWatchControlsMixinCommon::start() { - switch (mState) + switch (mPlayState) { case STOPPED: handleReset(); @@ -530,12 +536,12 @@ void LLStopWatchControlsMixinCommon::start() llassert(false); break; } - mState = STARTED; + mPlayState = STARTED; } void LLStopWatchControlsMixinCommon::stop() { - switch (mState) + switch (mPlayState) { case STOPPED: break; @@ -549,12 +555,12 @@ void LLStopWatchControlsMixinCommon::stop() llassert(false); break; } - mState = STOPPED; + mPlayState = STOPPED; } void LLStopWatchControlsMixinCommon::pause() { - switch (mState) + switch (mPlayState) { case STOPPED: break; @@ -567,12 +573,12 @@ void LLStopWatchControlsMixinCommon::pause() llassert(false); break; } - mState = PAUSED; + mPlayState = PAUSED; } void LLStopWatchControlsMixinCommon::resume() { - switch (mState) + switch (mPlayState) { case STOPPED: handleStart(); @@ -586,12 +592,12 @@ void LLStopWatchControlsMixinCommon::resume() llassert(false); break; } - mState = STARTED; + mPlayState = STARTED; } void LLStopWatchControlsMixinCommon::restart() { - switch (mState) + switch (mPlayState) { case STOPPED: handleReset(); @@ -608,7 +614,7 @@ void LLStopWatchControlsMixinCommon::restart() llassert(false); break; } - mState = STARTED; + mPlayState = STARTED; } void LLStopWatchControlsMixinCommon::reset() @@ -616,21 +622,23 @@ void LLStopWatchControlsMixinCommon::reset() handleReset(); } -void LLStopWatchControlsMixinCommon::initTo( EStopWatchState state ) +void LLStopWatchControlsMixinCommon::setPlayState( EPlayState state ) { switch(state) { case STOPPED: + stop(); break; case PAUSED: + pause(); break; case STARTED: - handleStart(); + start(); break; default: llassert(false); break; } - mState = state; + mPlayState = state; } diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h index 5105874ba1..a773c9ad91 100644 --- a/indra/llcommon/lltracerecording.h +++ b/indra/llcommon/lltracerecording.h @@ -39,7 +39,7 @@ class LLStopWatchControlsMixinCommon public: virtual ~LLStopWatchControlsMixinCommon() {} - enum EStopWatchState + enum EPlayState { STOPPED, PAUSED, @@ -53,19 +53,18 @@ public: virtual void restart(); virtual void reset(); - bool isStarted() const { return mState == STARTED; } - bool isPaused() const { return mState == PAUSED; } - bool isStopped() const { return mState == STOPPED; } - EStopWatchState getPlayState() const { return mState; } + bool isStarted() const { return mPlayState == STARTED; } + bool isPaused() const { return mPlayState == PAUSED; } + bool isStopped() const { return mPlayState == STOPPED; } + EPlayState getPlayState() const { return mPlayState; } + // force play state to specific value by calling appropriate handle* methods + void setPlayState(EPlayState state); protected: LLStopWatchControlsMixinCommon() - : mState(STOPPED) + : mPlayState(STOPPED) {} - // derived classes can call this from their copy constructor in order - // to duplicate play state of source - void initTo(EStopWatchState state); private: // trigger active behavior (without reset) virtual void handleStart(){}; @@ -74,7 +73,7 @@ private: // clear accumulated state, can be called while started virtual void handleReset(){}; - EStopWatchState mState; + EPlayState mPlayState; }; template<typename DERIVED> @@ -245,7 +244,7 @@ namespace LLTrace : public LLStopWatchControlsMixin<PeriodicRecording> { public: - PeriodicRecording(S32 num_periods, EStopWatchState state = STOPPED); + PeriodicRecording(S32 num_periods, EPlayState state = STOPPED); PeriodicRecording(PeriodicRecording& recording); ~PeriodicRecording(); diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp index 7b493a651e..bc1d19e72c 100644 --- a/indra/llcommon/lltracethreadrecorder.cpp +++ b/indra/llcommon/lltracethreadrecorder.cpp @@ -43,7 +43,7 @@ ThreadRecorder::ThreadRecorder() TimeBlock& root_time_block = TimeBlock::getRootTimeBlock(); ThreadTimerStack* timer_stack = ThreadTimerStack::getInstance(); - timer_stack->mTimeBlock = &root_time_block; + timer_stack->mAccumulator = root_time_block.getPrimaryAccumulator(); timer_stack->mActiveTimer = NULL; mNumTimeBlockTreeNodes = AccumulatorBuffer<TimeBlockAccumulator>::getDefaultBuffer()->size(); @@ -61,7 +61,9 @@ ThreadRecorder::ThreadRecorder() tree_node.mBlock = &time_block; tree_node.mParent = &root_time_block; - it->getPrimaryAccumulator()->mParent = &root_time_block; + TimeBlockAccumulator* accumulator = it->getPrimaryAccumulator(); + accumulator->mParent = &root_time_block; + accumulator->mBlock = &time_block; } mRootTimer = new BlockTimer(root_time_block); diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h index c600883607..c2a31b7604 100644 --- a/indra/llcommon/llunit.h +++ b/indra/llcommon/llunit.h @@ -301,13 +301,13 @@ LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator - (SCALAR_TYPE first, LLUnitImp template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> LLUnit<UNIT_TYPE, STORAGE_TYPE> operator * (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> second) { - return LLUnit<UNIT_TYPE, STORAGE_TYPE>(first * second.value()); + return LLUnit<UNIT_TYPE, STORAGE_TYPE>((STORAGE_TYPE)(first * second.value())); } template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> LLUnit<UNIT_TYPE, STORAGE_TYPE> operator * (LLUnit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) { - return LLUnit<UNIT_TYPE, STORAGE_TYPE>(first.value() * second); + return LLUnit<UNIT_TYPE, STORAGE_TYPE>((STORAGE_TYPE)(first.value() * second)); } template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> @@ -350,7 +350,7 @@ SCALAR_TYPE operator / (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> secon template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> LLUnit<UNIT_TYPE, STORAGE_TYPE> operator / (LLUnit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) { - return LLUnit<UNIT_TYPE, STORAGE_TYPE>(first.value() / second); + return LLUnit<UNIT_TYPE, STORAGE_TYPE>((STORAGE_TYPE)(first.value() / second)); } template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> @@ -363,7 +363,7 @@ STORAGE_TYPE1 operator / (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_T template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator / (LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) { - return LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE>(first.value() / second); + return LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE>((STORAGE_TYPE)(first.value() / second)); } template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> |