summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
authorOz Linden <oz@lindenlab.com>2012-11-19 11:09:58 -0500
committerOz Linden <oz@lindenlab.com>2012-11-19 11:09:58 -0500
commitb7f8a2479249646c7fb38ead195d5197ab733c94 (patch)
treec1bf4a2b0ecac69a4705827a042ea7f0224ebc54 /indra/llcommon
parentc94756d92c7353cb91bfddb5e342f825457e1a7e (diff)
parentf8749ec9bd03072cc5b50f4cb1a61289b2989c72 (diff)
merge up to 3.4.1-release
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/llallocator.cpp2
-rw-r--r--indra/llcommon/llapp.cpp3
-rw-r--r--indra/llcommon/llmemory.cpp43
-rw-r--r--indra/llcommon/llmemory.h64
-rw-r--r--indra/llcommon/llqueuedthread.cpp4
-rw-r--r--indra/llcommon/llthread.cpp35
-rw-r--r--indra/llcommon/llthread.h31
-rw-r--r--indra/llcommon/llversionviewer.h2
8 files changed, 125 insertions, 59 deletions
diff --git a/indra/llcommon/llallocator.cpp b/indra/llcommon/llallocator.cpp
index 6f6abefc67..87654b5b97 100644
--- a/indra/llcommon/llallocator.cpp
+++ b/indra/llcommon/llallocator.cpp
@@ -27,7 +27,7 @@
#include "linden_common.h"
#include "llallocator.h"
-#if LL_USE_TCMALLOC
+#if (LL_USE_TCMALLOC && LL_USE_HEAP_PROFILER)
#include "google/heap-profiler.h"
#include "google/commandlineflags_public.h"
diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index ed192a9975..ca258900c7 100644
--- a/indra/llcommon/llapp.cpp
+++ b/indra/llcommon/llapp.cpp
@@ -289,6 +289,7 @@ void LLApp::setupErrorHandling()
// occasionally checks to see if the app is in an error state, and sees if it needs to be run.
#if LL_WINDOWS
+#if LL_SEND_CRASH_REPORTS
// This sets a callback to handle w32 signals to the console window.
// The viewer shouldn't be affected, sicne its a windowed app.
SetConsoleCtrlHandler( (PHANDLER_ROUTINE) ConsoleCtrlHandler, TRUE);
@@ -300,7 +301,7 @@ void LLApp::setupErrorHandling()
mExceptionHandler = new google_breakpad::ExceptionHandler(
L"C:\\Temp\\", 0, windows_post_minidump_callback, 0, google_breakpad::ExceptionHandler::HANDLER_ALL);
}
-
+#endif
#else
//
// Start up signal handling.
diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index 3b9758f996..70ad10ad55 100644
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -61,6 +61,18 @@ BOOL LLMemory::sEnableMemoryFailurePrevention = FALSE;
LLPrivateMemoryPoolManager::mem_allocation_info_t LLPrivateMemoryPoolManager::sMemAllocationTracker;
#endif
+void ll_assert_aligned_func(uintptr_t ptr,U32 alignment)
+{
+#ifdef SHOW_ASSERT
+ // Redundant, place to set breakpoints.
+ if (ptr%alignment!=0)
+ {
+ llwarns << "alignment check failed" << llendl;
+ }
+ llassert(ptr%alignment==0);
+#endif
+}
+
//static
void LLMemory::initClass()
{
@@ -240,21 +252,6 @@ U32 LLMemory::getAllocatedMemKB()
return sAllocatedMemInKB ;
}
-void* ll_allocate (size_t size)
-{
- if (size == 0)
- {
- llwarns << "Null allocation" << llendl;
- }
- void *p = malloc(size);
- if (p == NULL)
- {
- LLMemory::freeReserve();
- llerrs << "Out of memory Error" << llendl;
- }
- return p;
-}
-
//----------------------------------------------------------------------------
#if defined(LL_WINDOWS)
@@ -1353,7 +1350,7 @@ char* LLPrivateMemoryPool::allocate(U32 size)
//if the asked size larger than MAX_BLOCK_SIZE, fetch from heap directly, the pool does not manage it
if(size >= CHUNK_SIZE)
{
- return (char*)malloc(size) ;
+ return (char*)ll_aligned_malloc_16(size) ;
}
char* p = NULL ;
@@ -1410,7 +1407,7 @@ char* LLPrivateMemoryPool::allocate(U32 size)
to_log = false ;
}
- return (char*)malloc(size) ;
+ return (char*)ll_aligned_malloc_16(size) ;
}
return p ;
@@ -1429,7 +1426,7 @@ void LLPrivateMemoryPool::freeMem(void* addr)
if(!chunk)
{
- free(addr) ; //release from heap
+ ll_aligned_free_16(addr) ; //release from heap
}
else
{
@@ -1553,7 +1550,7 @@ LLPrivateMemoryPool::LLMemoryChunk* LLPrivateMemoryPool::addChunk(S32 chunk_inde
mReservedPoolSize += preferred_size + overhead ;
- char* buffer = (char*)malloc(preferred_size + overhead) ;
+ char* buffer = (char*)ll_aligned_malloc_16(preferred_size + overhead) ;
if(!buffer)
{
return NULL ;
@@ -1621,7 +1618,7 @@ void LLPrivateMemoryPool::removeChunk(LLMemoryChunk* chunk)
mReservedPoolSize -= chunk->getBufferSize() ;
//release memory
- free(chunk->getBuffer()) ;
+ ll_aligned_free_16(chunk->getBuffer()) ;
}
U16 LLPrivateMemoryPool::findHashKey(const char* addr)
@@ -1965,7 +1962,7 @@ char* LLPrivateMemoryPoolManager::allocate(LLPrivateMemoryPool* poolp, U32 size,
if(!poolp)
{
- p = (char*)malloc(size) ;
+ p = (char*)ll_aligned_malloc_16(size) ;
}
else
{
@@ -1994,7 +1991,7 @@ char* LLPrivateMemoryPoolManager::allocate(LLPrivateMemoryPool* poolp, U32 size)
}
else
{
- return (char*)malloc(size) ;
+ return (char*)ll_aligned_malloc_16(size) ;
}
}
#endif
@@ -2019,7 +2016,7 @@ void LLPrivateMemoryPoolManager::freeMem(LLPrivateMemoryPool* poolp, void* addr
{
if(!sPrivatePoolEnabled)
{
- free(addr) ; //private pool is disabled.
+ ll_aligned_free_16(addr) ; //private pool is disabled.
}
else if(!sInstance) //the private memory manager is destroyed, try the dangling list
{
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index bbbdaa6497..10013e0f92 100644
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -27,7 +27,13 @@
#define LLMEMORY_H
#include "llmemtype.h"
-#if LL_DEBUG
+
+#if LL_WINDOWS && LL_DEBUG
+#define LL_CHECK_MEMORY llassert(_CrtCheckMemory());
+#else
+#define LL_CHECK_MEMORY
+#endif
+
inline void* ll_aligned_malloc( size_t size, int align )
{
void* mem = malloc( size + (align - 1) + sizeof(void*) );
@@ -43,10 +49,11 @@ inline void ll_aligned_free( void* ptr )
free( ((void**)ptr)[-1] );
}
+#if !LL_USE_TCMALLOC
inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed with ll_aligned_free_16().
{
#if defined(LL_WINDOWS)
- return _mm_malloc(size, 16);
+ return _aligned_malloc(size, 16);
#elif defined(LL_DARWIN)
return malloc(size); // default osx malloc is 16 byte aligned.
#else
@@ -61,7 +68,7 @@ inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed wi
inline void ll_aligned_free_16(void *p)
{
#if defined(LL_WINDOWS)
- _mm_free(p);
+ _aligned_free(p);
#elif defined(LL_DARWIN)
return free(p);
#else
@@ -69,10 +76,39 @@ inline void ll_aligned_free_16(void *p)
#endif
}
+inline void* ll_aligned_realloc_16(void* ptr, size_t size, size_t old_size) // returned hunk MUST be freed with ll_aligned_free_16().
+{
+#if defined(LL_WINDOWS)
+ return _aligned_realloc(ptr, size, 16);
+#elif defined(LL_DARWIN)
+ return realloc(ptr,size); // default osx malloc is 16 byte aligned.
+#else
+ //FIXME: memcpy is SLOW
+ void* ret = ll_aligned_malloc_16(size);
+ if (ptr)
+ {
+ if (ret)
+ {
+ // Only copy the size of the smallest memory block to avoid memory corruption.
+ memcpy(ret, ptr, llmin(old_size, size));
+ }
+ ll_aligned_free_16(ptr);
+ }
+ return ret;
+#endif
+}
+
+#else // USE_TCMALLOC
+// ll_aligned_foo_16 are not needed with tcmalloc
+#define ll_aligned_malloc_16 malloc
+#define ll_aligned_realloc_16(a,b,c) realloc(a,b)
+#define ll_aligned_free_16 free
+#endif // USE_TCMALLOC
+
inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed with ll_aligned_free_32().
{
#if defined(LL_WINDOWS)
- return _mm_malloc(size, 32);
+ return _aligned_malloc(size, 32);
#elif defined(LL_DARWIN)
return ll_aligned_malloc( size, 32 );
#else
@@ -87,22 +123,13 @@ inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed wi
inline void ll_aligned_free_32(void *p)
{
#if defined(LL_WINDOWS)
- _mm_free(p);
+ _aligned_free(p);
#elif defined(LL_DARWIN)
ll_aligned_free( p );
#else
free(p); // posix_memalign() is compatible with heap deallocator
#endif
}
-#else // LL_DEBUG
-// ll_aligned_foo are noops now that we use tcmalloc everywhere (tcmalloc aligns automatically at appropriate intervals)
-#define ll_aligned_malloc( size, align ) malloc(size)
-#define ll_aligned_free( ptr ) free(ptr)
-#define ll_aligned_malloc_16 malloc
-#define ll_aligned_free_16 free
-#define ll_aligned_malloc_32 malloc
-#define ll_aligned_free_32 free
-#endif // LL_DEBUG
#ifndef __DEBUG_PRIVATE_MEM__
#define __DEBUG_PRIVATE_MEM__ 0
@@ -512,4 +539,13 @@ void LLPrivateMemoryPoolTester::operator delete[](void* addr)
// LLSingleton moved to llsingleton.h
+LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment);
+
+#ifdef SHOW_ASSERT
+#define ll_assert_aligned(ptr,alignment) ll_assert_aligned_func(reinterpret_cast<uintptr_t>(ptr),((U32)alignment))
+#else
+#define ll_assert_aligned(ptr,alignment)
+#endif
+
+
#endif
diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp
index 1738c16dea..abf47a0f57 100644
--- a/indra/llcommon/llqueuedthread.cpp
+++ b/indra/llcommon/llqueuedthread.cpp
@@ -134,8 +134,8 @@ S32 LLQueuedThread::updateQueue(F32 max_time_ms)
pending = getPending();
if(pending > 0)
{
- unpause();
- }
+ unpause();
+ }
}
else
{
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index a6ad6b125c..c2fbb544a8 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -114,7 +114,7 @@ LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
}
mRunCondition = new LLCondition(mAPRPoolp);
-
+ mDataLock = new LLMutex(mAPRPoolp);
mLocalAPRFilePoolp = NULL ;
}
@@ -173,7 +173,10 @@ void LLThread::shutdown()
}
delete mRunCondition;
- mRunCondition = 0;
+ mRunCondition = NULL;
+
+ delete mDataLock;
+ mDataLock = NULL;
if (mIsLocalPool && mAPRPoolp)
{
@@ -242,28 +245,30 @@ bool LLThread::runCondition(void)
// Stop thread execution if requested until unpaused.
void LLThread::checkPause()
{
- mRunCondition->lock();
+ mDataLock->lock();
// This is in a while loop because the pthread API allows for spurious wakeups.
while(shouldSleep())
{
+ mDataLock->unlock();
mRunCondition->wait(); // unlocks mRunCondition
+ mDataLock->lock();
// mRunCondition is locked when the thread wakes up
}
- mRunCondition->unlock();
+ mDataLock->unlock();
}
//============================================================================
void LLThread::setQuitting()
{
- mRunCondition->lock();
+ mDataLock->lock();
if (mStatus == RUNNING)
{
mStatus = QUITTING;
}
- mRunCondition->unlock();
+ mDataLock->unlock();
wake();
}
@@ -285,12 +290,12 @@ void LLThread::yield()
void LLThread::wake()
{
- mRunCondition->lock();
+ mDataLock->lock();
if(!shouldSleep())
{
mRunCondition->signal();
}
- mRunCondition->unlock();
+ mDataLock->unlock();
}
void LLThread::wakeLocked()
@@ -481,6 +486,19 @@ LLThreadSafeRefCount::LLThreadSafeRefCount() :
{
}
+LLThreadSafeRefCount::LLThreadSafeRefCount(const LLThreadSafeRefCount& src)
+{
+ if (sMutex)
+ {
+ sMutex->lock();
+ }
+ mRef = 0;
+ if (sMutex)
+ {
+ sMutex->unlock();
+ }
+}
+
LLThreadSafeRefCount::~LLThreadSafeRefCount()
{
if (mRef != 0)
@@ -489,6 +507,7 @@ LLThreadSafeRefCount::~LLThreadSafeRefCount()
}
}
+
//============================================================================
LLResponder::~LLResponder()
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index b52e70ab2e..115bf47553 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -97,6 +97,7 @@ private:
protected:
std::string mName;
LLCondition* mRunCondition;
+ LLMutex* mDataLock;
apr_thread_t *mAPRThreadp;
apr_pool_t *mAPRPoolp;
@@ -122,15 +123,15 @@ protected:
inline void unlockData();
// This is the predicate that decides whether the thread should sleep.
- // It should only be called with mRunCondition locked, since the virtual runCondition() function may need to access
+ // It should only be called with mDataLock locked, since the virtual runCondition() function may need to access
// data structures that are thread-unsafe.
bool shouldSleep(void) { return (mStatus == RUNNING) && (isPaused() || (!runCondition())); }
// To avoid spurious signals (and the associated context switches) when the condition may or may not have changed, you can do the following:
- // mRunCondition->lock();
+ // mDataLock->lock();
// if(!shouldSleep())
// mRunCondition->signal();
- // mRunCondition->unlock();
+ // mDataLock->unlock();
};
//============================================================================
@@ -205,12 +206,12 @@ private:
void LLThread::lockData()
{
- mRunCondition->lock();
+ mDataLock->lock();
}
void LLThread::unlockData()
{
- mRunCondition->unlock();
+ mDataLock->unlock();
}
@@ -227,15 +228,27 @@ public:
private:
static LLMutex* sMutex;
-private:
- LLThreadSafeRefCount(const LLThreadSafeRefCount&); // not implemented
- LLThreadSafeRefCount&operator=(const LLThreadSafeRefCount&); // not implemented
-
protected:
virtual ~LLThreadSafeRefCount(); // use unref()
public:
LLThreadSafeRefCount();
+ LLThreadSafeRefCount(const LLThreadSafeRefCount&);
+ LLThreadSafeRefCount& operator=(const LLThreadSafeRefCount& ref)
+ {
+ if (sMutex)
+ {
+ sMutex->lock();
+ }
+ mRef = 0;
+ if (sMutex)
+ {
+ sMutex->unlock();
+ }
+ return *this;
+ }
+
+
void ref()
{
diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index 2038681905..bcc661a920 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -29,7 +29,7 @@
const S32 LL_VERSION_MAJOR = 3;
const S32 LL_VERSION_MINOR = 4;
-const S32 LL_VERSION_PATCH = 0;
+const S32 LL_VERSION_PATCH = 1;
const S32 LL_VERSION_BUILD = 0;
const char * const LL_CHANNEL = "Second Life Developer";