diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 1812e39b36460f89baf0d1c37f149808b3068716..eec2695dde92bcac161fe7d4c7748e04565f42b2 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -74,6 +74,7 @@ set(llcommon_SOURCE_FILES
     llmetrics.cpp
     llmetricperformancetester.cpp
     llmortician.cpp
+    llmutex.cpp
     lloptioninterface.cpp
     llptrto.cpp 
     llprocess.cpp
@@ -99,6 +100,7 @@ set(llcommon_SOURCE_FILES
     llthread.cpp
     llthreadsafequeue.cpp
     lltimer.cpp
+    lltrace.cpp
     lluri.cpp
     lluuid.cpp
     llworkerthread.cpp
@@ -197,6 +199,7 @@ set(llcommon_HEADER_FILES
     llmetrics.h
     llmetricperformancetester.h
     llmortician.h
+    llmutex.h
     llnametable.h
     lloptioninterface.h
     llpointer.h
@@ -237,6 +240,7 @@ set(llcommon_HEADER_FILES
     llstringtable.h
     llsys.h
     llthread.h
+    llthreadlocalptr.h
     llthreadsafequeue.h
     lltimer.h
     lltrace.h
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index 6a2323e7d87af6ba61ec143b25a34d52d943615f..4480e381e8b2730342cfd5d457c3223204a86352 100644
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -30,6 +30,11 @@
 
 class LLMutex ;
 
+#ifdef LL_WINDOWS
+#define LL_ALIGNED(x) __declspec(align(x))
+#else
+#define LL_ALIGNED(x) __attribute__ ((aligned (16)))
+#endif
 inline void* ll_aligned_malloc( size_t size, int align )
 {
 	void* mem = malloc( size + (align - 1) + sizeof(void*) );
diff --git a/indra/llcommon/llmutex.cpp b/indra/llcommon/llmutex.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2ce14b3a2e757629b9193bdcdefd903f80d5bea8
--- /dev/null
+++ b/indra/llcommon/llmutex.cpp
@@ -0,0 +1,229 @@
+/** 
+ * @file llmutex.cpp
+ *
+ * $LicenseInfo:firstyear=2004&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 "llapr.h"
+
+#include "apr_portable.h"
+
+#include "llmutex.h"
+#include "llthread.h"
+
+//============================================================================
+
+LLMutex::LLMutex(apr_pool_t *poolp) :
+	mAPRMutexp(NULL), mCount(0), mLockingThread(NO_THREAD)
+{
+	//if (poolp)
+	//{
+	//	mIsLocalPool = FALSE;
+	//	mAPRPoolp = poolp;
+	//}
+	//else
+	{
+		mIsLocalPool = TRUE;
+		apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
+	}
+	apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp);
+}
+
+
+LLMutex::~LLMutex()
+{
+#if MUTEX_DEBUG
+	//bad assertion, the subclass LLSignal might be "locked", and that's OK
+	//llassert_always(!isLocked()); // better not be locked!
+#endif
+	apr_thread_mutex_destroy(mAPRMutexp);
+	mAPRMutexp = NULL;
+	if (mIsLocalPool)
+	{
+		apr_pool_destroy(mAPRPoolp);
+	}
+}
+
+
+void LLMutex::lock()
+{
+	if(isSelfLocked())
+	{ //redundant lock
+		mCount++;
+		return;
+	}
+	
+	apr_thread_mutex_lock(mAPRMutexp);
+	
+#if MUTEX_DEBUG
+	// Have to have the lock before we can access the debug info
+	U32 id = LLThread::currentID();
+	if (mIsLocked[id] != FALSE)
+		llerrs << "Already locked in Thread: " << id << llendl;
+	mIsLocked[id] = TRUE;
+#endif
+
+#if LL_DARWIN
+	mLockingThread = LLThread::currentID();
+#else
+	mLockingThread = LLThread::sThreadIndex;
+#endif
+}
+
+void LLMutex::unlock()
+{
+	if (mCount > 0)
+	{ //not the root unlock
+		mCount--;
+		return;
+	}
+	
+#if MUTEX_DEBUG
+	// Access the debug info while we have the lock
+	U32 id = LLThread::currentID();
+	if (mIsLocked[id] != TRUE)
+		llerrs << "Not locked in Thread: " << id << llendl;	
+	mIsLocked[id] = FALSE;
+#endif
+
+	mLockingThread = NO_THREAD;
+	apr_thread_mutex_unlock(mAPRMutexp);
+}
+
+bool LLMutex::isLocked()
+{
+	apr_status_t status = apr_thread_mutex_trylock(mAPRMutexp);
+	if (APR_STATUS_IS_EBUSY(status))
+	{
+		return true;
+	}
+	else
+	{
+		apr_thread_mutex_unlock(mAPRMutexp);
+		return false;
+	}
+}
+
+bool LLMutex::isSelfLocked()
+{
+#if LL_DARWIN
+	return mLockingThread == LLThread::currentID();
+#else
+	return mLockingThread == LLThread::sThreadIndex;
+#endif
+}
+
+U32 LLMutex::lockingThread() const
+{
+	return mLockingThread;
+}
+
+//============================================================================
+
+LLCondition::LLCondition(apr_pool_t *poolp) :
+	LLMutex(poolp)
+{
+	// base class (LLMutex) has already ensured that mAPRPoolp is set up.
+
+	apr_thread_cond_create(&mAPRCondp, mAPRPoolp);
+}
+
+
+LLCondition::~LLCondition()
+{
+	apr_thread_cond_destroy(mAPRCondp);
+	mAPRCondp = NULL;
+}
+
+
+void LLCondition::wait()
+{
+	if (!isLocked())
+	{ //mAPRMutexp MUST be locked before calling apr_thread_cond_wait
+		apr_thread_mutex_lock(mAPRMutexp);
+#if MUTEX_DEBUG
+		// avoid asserts on destruction in non-release builds
+		U32 id = LLThread::currentID();
+		mIsLocked[id] = TRUE;
+#endif
+	}
+	apr_thread_cond_wait(mAPRCondp, mAPRMutexp);
+}
+
+void LLCondition::signal()
+{
+	apr_thread_cond_signal(mAPRCondp);
+}
+
+void LLCondition::broadcast()
+{
+	apr_thread_cond_broadcast(mAPRCondp);
+}
+
+
+//============================================================================
+
+//----------------------------------------------------------------------------
+
+//static
+LLMutex* LLThreadSafeRefCount::sMutex = 0;
+
+//static
+void LLThreadSafeRefCount::initThreadSafeRefCount()
+{
+	if (!sMutex)
+	{
+		sMutex = new LLMutex(0);
+	}
+}
+
+//static
+void LLThreadSafeRefCount::cleanupThreadSafeRefCount()
+{
+	delete sMutex;
+	sMutex = NULL;
+}
+
+
+//----------------------------------------------------------------------------
+
+LLThreadSafeRefCount::LLThreadSafeRefCount() :
+mRef(0)
+{
+}
+
+LLThreadSafeRefCount::~LLThreadSafeRefCount()
+{ 
+	if (mRef != 0)
+	{
+		llerrs << "deleting non-zero reference" << llendl;
+	}
+}
+
+//============================================================================
+
+LLResponder::~LLResponder()
+{
+}
+
+//============================================================================
diff --git a/indra/llcommon/llmutex.h b/indra/llcommon/llmutex.h
new file mode 100644
index 0000000000000000000000000000000000000000..bd0a59b577a5cd8ca7933e39ceccd38dae0dd8cb
--- /dev/null
+++ b/indra/llcommon/llmutex.h
@@ -0,0 +1,168 @@
+/** 
+ * @file llmutex.h
+ * @brief Base classes for mutex and condition handling.
+ *
+ * $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_LLMUTEX_H
+#define LL_LLMUTEX_H
+
+#include "llapr.h"
+#include "apr_thread_cond.h"
+
+//============================================================================
+
+#define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO)
+
+class LL_COMMON_API LLMutex
+{
+public:
+	typedef enum
+	{
+		NO_THREAD = 0xFFFFFFFF
+	} e_locking_thread;
+
+	LLMutex(apr_pool_t *apr_poolp = NULL); // NULL pool constructs a new pool for the mutex
+	virtual ~LLMutex();
+	
+	void lock();		// blocks
+	void unlock();
+	bool isLocked(); 	// non-blocking, but does do a lock/unlock so not free
+	bool isSelfLocked(); //return true if locked in a same thread
+	U32 lockingThread() const; //get ID of locking thread
+	
+protected:
+	apr_thread_mutex_t *mAPRMutexp;
+	mutable U32			mCount;
+	mutable U32			mLockingThread;
+	
+	apr_pool_t			*mAPRPoolp;
+	BOOL				mIsLocalPool;
+	
+#if MUTEX_DEBUG
+	std::map<U32, BOOL> mIsLocked;
+#endif
+};
+
+// Actually a condition/mutex pair (since each condition needs to be associated with a mutex).
+class LL_COMMON_API LLCondition : public LLMutex
+{
+public:
+	LLCondition(apr_pool_t *apr_poolp); // Defaults to global pool, could use the thread pool as well.
+	~LLCondition();
+	
+	void wait();		// blocks
+	void signal();
+	void broadcast();
+	
+protected:
+	apr_thread_cond_t *mAPRCondp;
+};
+
+class LLMutexLock
+{
+public:
+	LLMutexLock(LLMutex* mutex)
+	{
+		mMutex = mutex;
+		
+		if(mMutex)
+			mMutex->lock();
+	}
+	~LLMutexLock()
+	{
+		if(mMutex)
+			mMutex->unlock();
+	}
+private:
+	LLMutex* mMutex;
+};
+
+
+//============================================================================
+
+// see llmemory.h for LLPointer<> definition
+
+class LL_COMMON_API LLThreadSafeRefCount
+{
+public:
+	static void initThreadSafeRefCount(); // creates sMutex
+	static void cleanupThreadSafeRefCount(); // destroys sMutex
+
+private:
+	static LLMutex* sMutex;
+
+private:
+	LLThreadSafeRefCount(const LLThreadSafeRefCount&); // not implemented
+	LLThreadSafeRefCount&operator=(const LLThreadSafeRefCount&); // not implemented
+
+protected:
+	virtual ~LLThreadSafeRefCount(); // use unref()
+
+public:
+	LLThreadSafeRefCount();
+
+	void ref()
+	{
+		if (sMutex) sMutex->lock();
+		mRef++; 
+		if (sMutex) sMutex->unlock();
+	} 
+
+	S32 unref()
+	{
+		llassert(mRef >= 1);
+		if (sMutex) sMutex->lock();
+		S32 res = --mRef;
+		if (sMutex) sMutex->unlock();
+		if (0 == res) 
+		{
+			delete this; 
+			return 0;
+		}
+		return res;
+	}	
+	S32 getNumRefs() const
+	{
+		return mRef;
+	}
+
+private: 
+	S32	mRef; 
+};
+
+
+//============================================================================
+
+// Simple responder for self destructing callbacks
+// Pure virtual class
+class LL_COMMON_API LLResponder : public LLThreadSafeRefCount
+{
+protected:
+	virtual ~LLResponder();
+public:
+	virtual void completed(bool success) = 0;
+};
+
+
+#endif // LL_LLTHREAD_H
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index a6ad6b125c1ad14cd1a9370f0713ed2159be655c..f3ab8aa40cbd8f2b7b272e87842a58879076eefb 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -29,6 +29,7 @@
 #include "apr_portable.h"
 
 #include "llthread.h"
+#include "llmutex.h"
 
 #include "lltimer.h"
 
@@ -56,12 +57,20 @@
 // 
 //----------------------------------------------------------------------------
 
-#if !LL_DARWIN
-U32 ll_thread_local sThreadID = 0;
-#endif 
+#if LL_DARWIN
+// statically allocated thread local storage not supported in Darwin executable formats
+#elif LL_WINDOWS
+U32 __declspec(thread) LLThread::sThreadIndex = 0;
+#elif LL_LINUX
+U32 __thread LLThread::sThreadID = 0;
+#endif
 
 U32 LLThread::sIDIter = 0;
 
+LLTrace::MasterThreadTrace gMasterThreadTrace;
+LLThreadLocalPtr<LLTrace::ThreadTraceData> LLThread::sTraceData(&gMasterThreadTrace);
+
+
 LL_COMMON_API void assert_main_thread()
 {
 	static U32 s_thread_id = LLThread::currentID();
@@ -78,8 +87,10 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 {
 	LLThread *threadp = (LLThread *)datap;
 
+	sTraceData = new LLTrace::SlaveThreadTrace(gMasterThreadTrace);
+
 #if !LL_DARWIN
-	sThreadID = threadp->mID;
+	sThreadIndex = threadp->mID;
 #endif
 
 	// Run the user supplied function
@@ -93,7 +104,6 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 	return NULL;
 }
 
-
 LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
 	mPaused(FALSE),
 	mName(name),
@@ -301,198 +311,12 @@ void LLThread::wakeLocked()
 	}
 }
 
-//============================================================================
-
-LLMutex::LLMutex(apr_pool_t *poolp) :
-	mAPRMutexp(NULL), mCount(0), mLockingThread(NO_THREAD)
-{
-	//if (poolp)
-	//{
-	//	mIsLocalPool = FALSE;
-	//	mAPRPoolp = poolp;
-	//}
-	//else
-	{
-		mIsLocalPool = TRUE;
-		apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
-	}
-	apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp);
-}
-
-
-LLMutex::~LLMutex()
-{
-#if MUTEX_DEBUG
-	//bad assertion, the subclass LLSignal might be "locked", and that's OK
-	//llassert_always(!isLocked()); // better not be locked!
-#endif
-	apr_thread_mutex_destroy(mAPRMutexp);
-	mAPRMutexp = NULL;
-	if (mIsLocalPool)
-	{
-		apr_pool_destroy(mAPRPoolp);
-	}
-}
-
-
-void LLMutex::lock()
-{
-	if(isSelfLocked())
-	{ //redundant lock
-		mCount++;
-		return;
-	}
-	
-	apr_thread_mutex_lock(mAPRMutexp);
-	
-#if MUTEX_DEBUG
-	// Have to have the lock before we can access the debug info
-	U32 id = LLThread::currentID();
-	if (mIsLocked[id] != FALSE)
-		llerrs << "Already locked in Thread: " << id << llendl;
-	mIsLocked[id] = TRUE;
-#endif
-
-#if LL_DARWIN
-	mLockingThread = LLThread::currentID();
-#else
-	mLockingThread = sThreadID;
-#endif
-}
-
-void LLMutex::unlock()
-{
-	if (mCount > 0)
-	{ //not the root unlock
-		mCount--;
-		return;
-	}
-	
-#if MUTEX_DEBUG
-	// Access the debug info while we have the lock
-	U32 id = LLThread::currentID();
-	if (mIsLocked[id] != TRUE)
-		llerrs << "Not locked in Thread: " << id << llendl;	
-	mIsLocked[id] = FALSE;
-#endif
-
-	mLockingThread = NO_THREAD;
-	apr_thread_mutex_unlock(mAPRMutexp);
-}
-
-bool LLMutex::isLocked()
-{
-	apr_status_t status = apr_thread_mutex_trylock(mAPRMutexp);
-	if (APR_STATUS_IS_EBUSY(status))
-	{
-		return true;
-	}
-	else
-	{
-		apr_thread_mutex_unlock(mAPRMutexp);
-		return false;
-	}
-}
-
-bool LLMutex::isSelfLocked()
-{
-#if LL_DARWIN
-	return mLockingThread == LLThread::currentID();
-#else
-	return mLockingThread == sThreadID;
-#endif
-}
-
-U32 LLMutex::lockingThread() const
-{
-	return mLockingThread;
-}
-
-//============================================================================
-
-LLCondition::LLCondition(apr_pool_t *poolp) :
-	LLMutex(poolp)
-{
-	// base class (LLMutex) has already ensured that mAPRPoolp is set up.
-
-	apr_thread_cond_create(&mAPRCondp, mAPRPoolp);
-}
-
-
-LLCondition::~LLCondition()
-{
-	apr_thread_cond_destroy(mAPRCondp);
-	mAPRCondp = NULL;
-}
-
-
-void LLCondition::wait()
-{
-	if (!isLocked())
-	{ //mAPRMutexp MUST be locked before calling apr_thread_cond_wait
-		apr_thread_mutex_lock(mAPRMutexp);
-#if MUTEX_DEBUG
-		// avoid asserts on destruction in non-release builds
-		U32 id = LLThread::currentID();
-		mIsLocked[id] = TRUE;
-#endif
-	}
-	apr_thread_cond_wait(mAPRCondp, mAPRMutexp);
-}
-
-void LLCondition::signal()
-{
-	apr_thread_cond_signal(mAPRCondp);
-}
-
-void LLCondition::broadcast()
-{
-	apr_thread_cond_broadcast(mAPRCondp);
-}
-
-//============================================================================
-
-//----------------------------------------------------------------------------
-
-//static
-LLMutex* LLThreadSafeRefCount::sMutex = 0;
-
-//static
-void LLThreadSafeRefCount::initThreadSafeRefCount()
-{
-	if (!sMutex)
-	{
-		sMutex = new LLMutex(0);
-	}
-}
-
-//static
-void LLThreadSafeRefCount::cleanupThreadSafeRefCount()
+void LLThread::lockData()
 {
-	delete sMutex;
-	sMutex = NULL;
-}
-	
-
-//----------------------------------------------------------------------------
-
-LLThreadSafeRefCount::LLThreadSafeRefCount() :
-	mRef(0)
-{
-}
-
-LLThreadSafeRefCount::~LLThreadSafeRefCount()
-{ 
-	if (mRef != 0)
-	{
-		llerrs << "deleting non-zero reference" << llendl;
-	}
+	mRunCondition->lock();
 }
 
-//============================================================================
-
-LLResponder::~LLResponder()
+void LLThread::unlockData()
 {
+	mRunCondition->unlock();
 }
-
-//============================================================================
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index b52e70ab2ebcb637ac5fed388ba3b9ef285abb0e..e2de4c8b85a99d9963b71ea33f8059a2869286f3 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -30,21 +30,21 @@
 #include "llapp.h"
 #include "llapr.h"
 #include "apr_thread_cond.h"
-
-class LLThread;
-class LLMutex;
-class LLCondition;
-
-#if LL_WINDOWS
-#define ll_thread_local __declspec(thread)
-#else
-#define ll_thread_local __thread
-#endif
+#include "lltrace.h"
+#include "llthreadlocalptr.h"
 
 class LL_COMMON_API LLThread
 {
 private:
+	friend class LLMutex;
 	static U32 sIDIter;
+#if LL_DARWIN
+	// statically allocated thread local storage not supported in Darwin executable formats
+#elif LL_WINDOWS
+	static U32 __declspec(thread) LLThread::sThreadIndex;
+#elif LL_LINUX
+	static U32 __thread LLThread::sThreadID ;
+#endif
 
 public:
 	typedef enum e_thread_status
@@ -88,6 +88,8 @@ class LL_COMMON_API LLThread
 
 	U32 getID() const { return mID; }
 
+	static LLTrace::ThreadTraceData* getTraceData() { return sTraceData.get(); }
+
 private:
 	BOOL				mPaused;
 	
@@ -96,7 +98,7 @@ class LL_COMMON_API LLThread
 
 protected:
 	std::string			mName;
-	LLCondition*		mRunCondition;
+	class LLCondition*	mRunCondition;
 
 	apr_thread_t		*mAPRThreadp;
 	apr_pool_t			*mAPRPoolp;
@@ -104,6 +106,8 @@ class LL_COMMON_API LLThread
 	EThreadStatus		mStatus;
 	U32					mID;
 
+	static LLThreadLocalPtr<LLTrace::ThreadTraceData> sTraceData;
+
 	//a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used.
 	//Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes.
 	//      otherwise it will cause severe memory leaking!!! --bao
@@ -135,149 +139,4 @@ class LL_COMMON_API LLThread
 
 //============================================================================
 
-#define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO)
-
-class LL_COMMON_API LLMutex
-{
-public:
-	typedef enum
-	{
-		NO_THREAD = 0xFFFFFFFF
-	} e_locking_thread;
-
-	LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex
-	virtual ~LLMutex();
-	
-	void lock();		// blocks
-	void unlock();
-	bool isLocked(); 	// non-blocking, but does do a lock/unlock so not free
-	bool isSelfLocked(); //return true if locked in a same thread
-	U32 lockingThread() const; //get ID of locking thread
-	
-protected:
-	apr_thread_mutex_t *mAPRMutexp;
-	mutable U32			mCount;
-	mutable U32			mLockingThread;
-	
-	apr_pool_t			*mAPRPoolp;
-	BOOL				mIsLocalPool;
-	
-#if MUTEX_DEBUG
-	std::map<U32, BOOL> mIsLocked;
-#endif
-};
-
-// Actually a condition/mutex pair (since each condition needs to be associated with a mutex).
-class LL_COMMON_API LLCondition : public LLMutex
-{
-public:
-	LLCondition(apr_pool_t *apr_poolp); // Defaults to global pool, could use the thread pool as well.
-	~LLCondition();
-	
-	void wait();		// blocks
-	void signal();
-	void broadcast();
-	
-protected:
-	apr_thread_cond_t *mAPRCondp;
-};
-
-class LLMutexLock
-{
-public:
-	LLMutexLock(LLMutex* mutex)
-	{
-		mMutex = mutex;
-		
-		if(mMutex)
-			mMutex->lock();
-	}
-	~LLMutexLock()
-	{
-		if(mMutex)
-			mMutex->unlock();
-	}
-private:
-	LLMutex* mMutex;
-};
-
-//============================================================================
-
-void LLThread::lockData()
-{
-	mRunCondition->lock();
-}
-
-void LLThread::unlockData()
-{
-	mRunCondition->unlock();
-}
-
-
-//============================================================================
-
-// see llmemory.h for LLPointer<> definition
-
-class LL_COMMON_API LLThreadSafeRefCount
-{
-public:
-	static void initThreadSafeRefCount(); // creates sMutex
-	static void cleanupThreadSafeRefCount(); // destroys sMutex
-	
-private:
-	static LLMutex* sMutex;
-
-private:
-	LLThreadSafeRefCount(const LLThreadSafeRefCount&); // not implemented
-	LLThreadSafeRefCount&operator=(const LLThreadSafeRefCount&); // not implemented
-
-protected:
-	virtual ~LLThreadSafeRefCount(); // use unref()
-	
-public:
-	LLThreadSafeRefCount();
-	
-	void ref()
-	{
-		if (sMutex) sMutex->lock();
-		mRef++; 
-		if (sMutex) sMutex->unlock();
-	} 
-
-	S32 unref()
-	{
-		llassert(mRef >= 1);
-		if (sMutex) sMutex->lock();
-		S32 res = --mRef;
-		if (sMutex) sMutex->unlock();
-		if (0 == res) 
-		{
-			delete this; 
-			return 0;
-		}
-		return res;
-	}	
-	S32 getNumRefs() const
-	{
-		return mRef;
-	}
-
-private: 
-	S32	mRef; 
-};
-
-//============================================================================
-
-// Simple responder for self destructing callbacks
-// Pure virtual class
-class LL_COMMON_API LLResponder : public LLThreadSafeRefCount
-{
-protected:
-	virtual ~LLResponder();
-public:
-	virtual void completed(bool success) = 0;
-};
-
-//============================================================================
-
 #endif // LL_LLTHREAD_H
diff --git a/indra/llcommon/llthreadlocalptr.h b/indra/llcommon/llthreadlocalptr.h
new file mode 100644
index 0000000000000000000000000000000000000000..f02f4849ca425455735e1b621f57e13e15caeb7d
--- /dev/null
+++ b/indra/llcommon/llthreadlocalptr.h
@@ -0,0 +1,141 @@
+/** 
+ * @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
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..037c52f8c19f1dc4c662b759b5d1baaf5123ca7d
--- /dev/null
+++ b/indra/llcommon/lltrace.cpp
@@ -0,0 +1,95 @@
+/** 
+ * @file lltrace.cpp
+ *
+ * $LicenseInfo:firstyear=2001&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$
+ */
+
+#include "linden_common.h"
+
+#include "lltrace.h"
+#include "llthread.h"
+
+namespace LLTrace
+{
+
+BlockTimer::Recorder::StackEntry BlockTimer::sCurRecorder;
+LLThreadLocalPtr<ThreadTraceData> ThreadTraceData::sCurThreadTrace;
+
+///////////////////////////////////////////////////////////////////////
+// Sampler
+///////////////////////////////////////////////////////////////////////
+
+void Sampler::stop()
+{
+	getThreadTrace()->deactivate(this);
+}
+
+void Sampler::resume()
+{
+	getThreadTrace()->activate(this);
+}
+
+class ThreadTraceData* Sampler::getThreadTrace()
+{
+	return LLThread::getTraceData();
+}
+
+///////////////////////////////////////////////////////////////////////
+// MasterThreadTrace
+///////////////////////////////////////////////////////////////////////
+
+void MasterThreadTrace::pullFromWorkerThreads()
+{
+	LLMutexLock lock(&mSlaveListMutex);
+
+	for (worker_thread_trace_list_t::iterator it = mSlaveThreadTraces.begin(), end_it = mSlaveThreadTraces.end();
+		it != end_it;
+		++it)
+	{
+		it->mWorkerTrace->mSharedData.copyTo(it->mSamplerStorage);
+	}
+}
+
+void MasterThreadTrace::addSlaveThread( class SlaveThreadTrace* child )
+{
+	LLMutexLock lock(&mSlaveListMutex);
+
+	mSlaveThreadTraces.push_back(WorkerThreadTraceProxy(child));
+}
+
+void MasterThreadTrace::removeSlaveThread( class SlaveThreadTrace* child )
+{
+	LLMutexLock lock(&mSlaveListMutex);
+
+	for (worker_thread_trace_list_t::iterator it = mSlaveThreadTraces.begin(), end_it = mSlaveThreadTraces.end();
+		it != end_it;
+		++it)
+	{
+		if (it->mWorkerTrace == child)
+		{
+			mSlaveThreadTraces.erase(it);
+			break;
+		}
+	}
+}
+
+}
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 7da182df1e11c64320ed4f5c106759eff0a3a189..401ddfd6f34b830be91dfe05aab6329d0af0dcbb 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -30,25 +30,27 @@
 #include "stdtypes.h"
 #include "llpreprocessor.h"
 
-#include "llthread.h"
+#include "llmutex.h"
+#include "llmemory.h"
+#include "llthreadlocalptr.h"
 
 #include <list>
 
+#define TOKEN_PASTE_ACTUAL(x, y) x##y
+#define TOKEN_PASTE(x, y) TOKEN_PASTE_ACTUAL(x, y)
+#define RECORD_BLOCK_TIME(block_timer) LLTrace::BlockTimer::Recorder TOKEN_PASTE(block_time_recorder, __COUNTER__)(block_timer);
+
 namespace LLTrace
 {
-
 	// one per thread per type
 	template<typename ACCUMULATOR>
-	struct AccumulatorBuffer : public AccumulatorBufferBase
+	class AccumulatorBuffer
 	{
-		ACCUMULATOR*				mStorage;
-		size_t						mStorageSize;
-		size_t						mNextStorageSlot;
-		static S32					sStorageKey; // key used to access thread local storage pointer to accumulator values
-		
+		static const U32 DEFAULT_ACCUMULATOR_BUFFER_SIZE = 64;
+	public:
 		AccumulatorBuffer()
 		:	mStorageSize(64),
-			mStorage(new ACCUMULATOR[64]),
+			mStorage(new ACCUMULATOR[DEFAULT_ACCUMULATOR_BUFFER_SIZE]),
 			mNextStorageSlot(0)
 		{}
 
@@ -56,12 +58,13 @@ namespace LLTrace
 		:	mStorageSize(other.mStorageSize),
 			mStorage(new ACCUMULATOR[other.mStorageSize]),
 			mNextStorageSlot(other.mNextStorageSlot)
-		{
+		{}
 
+		LL_FORCE_INLINE ACCUMULATOR& operator[](size_t index) 
+		{ 
+			return mStorage[index]; 
 		}
 
-		LL_FORCE_INLINE ACCUMULATOR& operator[](size_t index) { return (*mStorage)[index]; }
-
 		void mergeFrom(const AccumulatorBuffer<ACCUMULATOR>& other)
 		{
 			llassert(mNextStorageSlot == other.mNextStorageSlot);
@@ -72,7 +75,7 @@ namespace LLTrace
 			}
 		}
 
-		void copyFrom(const AccumulatorBuffer<Accumulator>& other)
+		void copyFrom(const AccumulatorBuffer<ACCUMULATOR>& other)
 		{
 			for (size_t i = 0; i < mNextStorageSlot; i++)
 			{
@@ -90,7 +93,12 @@ namespace LLTrace
 
 		void makePrimary()
 		{
-			//TODO: use sStorageKey to set mStorage as active buffer
+			sPrimaryStorage = mStorage;
+		}
+
+		LL_FORCE_INLINE static ACCUMULATOR* getPrimaryStorage() 
+		{ 
+			return sPrimaryStorage.get(); 
 		}
 
 		// NOTE: this is not thread-safe.  We assume that slots are reserved in the main thread before any child threads are spawned
@@ -101,14 +109,29 @@ namespace LLTrace
 			{
 				size_t new_size = mStorageSize + (mStorageSize >> 2);
 				delete [] mStorage;
-				mStorage = new mStorage(new_size);
+				mStorage = new ACCUMULATOR[new_size];
 				mStorageSize = new_size;
 			}
 			llassert(next_slot < mStorageSize);
 			return next_slot;
 		}
+
+	private:
+		ACCUMULATOR*							mStorage;
+		size_t									mStorageSize;
+		size_t									mNextStorageSlot;
+		static LLThreadLocalPtr<ACCUMULATOR>	sPrimaryStorage;
+	};
+	template<typename ACCUMULATOR> LLThreadLocalPtr<ACCUMULATOR> AccumulatorBuffer<ACCUMULATOR>::sPrimaryStorage;
+
+	template<typename ACCUMULATOR>
+	class PrimaryAccumulatorBuffer : public AccumulatorBuffer<ACCUMULATOR
+	{
+		PrimaryAccumulatorBuffer()
+		{
+			makePrimary();
+		}
 	};
-	template<typename ACCUMULATOR> S32 AccumulatorBuffer<ACCUMULATOR>::sStorageKey;
 
 	template<typename ACCUMULATOR>
 	class Trace
@@ -117,32 +140,34 @@ namespace LLTrace
 		Trace(const std::string& name)
 		:	mName(name)
 		{
-			mAccumulatorIndex = sAccumulatorBuffer.reserveSlot();
+			mAccumulatorIndex = getPrimaryBuffer().reserveSlot();
 		}
 
 		LL_FORCE_INLINE ACCUMULATOR& getAccumulator()
 		{
-			return sAccumulatorBuffer[mAccumulatorIndex];
+			return AccumulatorBuffer<ACCUMULATOR>::getPrimaryStorage()[mAccumulatorIndex];
+		}
+
+		static PrimaryAccumulatorBuffer& getPrimaryBuffer()
+		{
+			static PrimaryAccumulatorBuffer sBuffer;
+			return sBuffer;
 		}
 
 	private:
 		std::string	mName;
 		size_t		mAccumulatorIndex;
-
-		// this needs to be thread local
-		static AccumulatorBuffer<ACCUMULATOR>	sAccumulatorBuffer;
 	};
 
-	template<typename ACCUMULATOR> std::vector<ACCUMULATOR> Trace<ACCUMULATOR>::sAccumulatorBuffer;
 
 	template<typename T>
 	class StatAccumulator
 	{
 	public:
 		StatAccumulator()
-		:	mSum(),
-			mMin(),
-			mMax(),
+		:	mSum(0),
+			mMin(0),
+			mMax(0),
 			mNumSamples(0)
 		{}
 
@@ -160,7 +185,7 @@ namespace LLTrace
 			}
 		}
 
-		void mergeFrom(const Stat<T>& other)
+		void mergeFrom(const StatAccumulator<T>& other)
 		{
 			mSum += other.mSum;
 			if (other.mMin < mMin)
@@ -318,21 +343,13 @@ namespace LLTrace
 		static Recorder::StackEntry sCurRecorder;
 	};
 
-	BlockTimer::Recorder::StackEntry BlockTimer::sCurRecorder;
-
 	class Sampler
 	{
 	public:
-		Sampler(const Sampler& other)
-		:	mF32Stats(other.mF32Stats),
-			mS32Stats(other.mS32Stats),
-			mTimers(other.mTimers)
-		{}
+		Sampler() {}
+		Sampler(const Sampler& other);
 
-		~Sampler()
-		{
-			stop();
-		}
+		~Sampler();
 
 		void makePrimary()
 		{
@@ -347,17 +364,8 @@ namespace LLTrace
 			resume();
 		}
 
-		void stop()
-		{
-			getThreadTracer()->deactivate(this);
-		}
-
-		void resume()
-		{
-			ThreadTracer* thread_data = getThreadTracer();
-			thread_data->flushData();
-			thread_data->activate(this);
-		}
+		void stop();
+		void resume();
 
 		void mergeFrom(const Sampler& other)
 		{
@@ -375,7 +383,7 @@ namespace LLTrace
 
 	private:
 		// returns data for current thread
-		struct ThreadTracer* getThreadTracer() { return NULL; } 
+		class ThreadTraceData* getThreadTrace(); 
 
 		AccumulatorBuffer<StatAccumulator<F32> >	mF32Stats;
 		AccumulatorBuffer<StatAccumulator<S32> >	mS32Stats;
@@ -383,39 +391,39 @@ namespace LLTrace
 		AccumulatorBuffer<TimerAccumulator>			mTimers;
 	};
 
-	struct ThreadTracer
+	class ThreadTraceData
 	{
-		ThreadTracer(LLThread& this_thread, ThreadTracer& parent_data)
-		:	mPrimarySampler(parent_data.mPrimarySampler),
-			mSharedSampler(parent_data.mSharedSampler),
-			mSharedSamplerMutex(this_thread.getAPRPool()),
-			mParent(parent_data)
+	public:
+		ThreadTraceData()
 		{
 			mPrimarySampler.makePrimary();
-			parent_data.addChildThread(this);
 		}
 
-		~ThreadTracer()
+		ThreadTraceData(const ThreadTraceData& other)
+		:	mPrimarySampler(other.mPrimarySampler)
 		{
-			mParent.removeChildThread(this);
+			mPrimarySampler.makePrimary();
 		}
 
-		void addChildThread(ThreadTracer* child)
+		void activate(Sampler* sampler)
 		{
-			mChildThreadTracers.push_back(child);
+			flushPrimary();
+			mActiveSamplers.push_back(sampler);
 		}
 
-		void removeChildThread(ThreadTracer* child)
+		void deactivate(Sampler* sampler)
 		{
+			sampler->mergeFrom(mPrimarySampler);
+
 			// TODO: replace with intrusive list
-			std::list<ThreadTracer*>::iterator found_it = std::find(mChildThreadTracers.begin(), mChildThreadTracers.end(), child);
-			if (found_it != mChildThreadTracers.end())
+			std::list<Sampler*>::iterator found_it = std::find(mActiveSamplers.begin(), mActiveSamplers.end(), sampler);
+			if (found_it != mActiveSamplers.end())
 			{
-				mChildThreadTracers.erase(found_it);
+				mActiveSamplers.erase(found_it);
 			}
 		}
 
-		void flushData()
+		void flushPrimary()
 		{
 			for (std::list<Sampler*>::iterator it = mActiveSamplers.begin(), end_it = mActiveSamplers.end();
 				it != end_it;
@@ -426,56 +434,96 @@ namespace LLTrace
 			mPrimarySampler.reset();
 		}
 
-		void activate(Sampler* sampler)
+		Sampler* getPrimarySampler() { return &mPrimarySampler; }
+	protected:
+		Sampler					mPrimarySampler;
+		std::list<Sampler*>		mActiveSamplers;
+		static LLThreadLocalPtr<ThreadTraceData> sCurThreadTrace;
+	};
+
+	class MasterThreadTrace : public ThreadTraceData
+	{
+	public:
+		MasterThreadTrace()
+		{}
+
+		void addSlaveThread(class SlaveThreadTrace* child);
+		void removeSlaveThread(class SlaveThreadTrace* child);
+
+		// call this periodically to gather stats data from worker threads
+		void pullFromWorkerThreads();
+
+	private:
+		struct WorkerThreadTraceProxy
 		{
-			mActiveSamplers.push_back(sampler);
+			WorkerThreadTraceProxy(class SlaveThreadTrace* trace)
+				:	mWorkerTrace(trace)
+			{}
+			class SlaveThreadTrace*	mWorkerTrace;
+			Sampler				mSamplerStorage;
+		};
+		typedef std::list<WorkerThreadTraceProxy> worker_thread_trace_list_t;
+
+		worker_thread_trace_list_t		mSlaveThreadTraces;
+		LLMutex							mSlaveListMutex;
+	};
+
+	class SlaveThreadTrace : public ThreadTraceData
+	{
+	public:
+		explicit 
+		SlaveThreadTrace(MasterThreadTrace& master_trace)
+		:	mMaster(master_trace),
+			ThreadTraceData(master_trace),
+			mSharedData(mPrimarySampler)
+		{
+			master_trace.addSlaveThread(this);
 		}
 
-		void deactivate(Sampler* sampler)
+		~SlaveThreadTrace()
 		{
-			// TODO: replace with intrusive list
-			std::list<Sampler*>::iterator found_it = std::find(mActiveSamplers.begin(), mActiveSamplers.end(), sampler);
-			if (found_it != mActiveSamplers.end())
-			{
-				mActiveSamplers.erase(found_it);
-			}
+			mMaster.removeSlaveThread(this);
 		}
-		
-		// call this periodically to gather stats data in parent thread
-		void publishToParent()
+
+		// call this periodically to gather stats data for master thread to consume
+		void pushToParent()
 		{
-			mSharedSamplerMutex.lock();
-			{	
-				mSharedSampler.mergeFrom(mPrimarySampler);
-			}
-			mSharedSamplerMutex.unlock();
+			mSharedData.copyFrom(mPrimarySampler);
 		}
 
-		// call this periodically to gather stats data from children
-		void gatherChildData()
+		MasterThreadTrace& 	mMaster;
+
+		// this data is accessed by other threads, so give it a 64 byte alignment
+		// to avoid false sharing on most x86 processors
+		LL_ALIGNED(64) class SharedData
 		{
-			for (std::list<ThreadTracer*>::iterator child_it = mChildThreadTracers.begin(), end_it = mChildThreadTracers.end();
-				child_it != end_it;
-				++child_it)
+		public:
+			explicit 
+			SharedData(const Sampler& other_sampler) 
+			:	mSampler(other_sampler)
+			{}
+
+			void copyFrom(Sampler& source)
 			{
-				(*child_it)->mSharedSamplerMutex.lock();
-				{
-					//TODO for now, just aggregate, later keep track of thread data independently
-					mPrimarySampler.mergeFrom((*child_it)->mSharedSampler);
+				LLMutexLock lock(&mSamplerMutex);
+				{	
+					mSampler.mergeFrom(source);
 				}
-				(*child_it)->mSharedSamplerMutex.unlock();
 			}
-		}
 
-		Sampler	mPrimarySampler;
-
-		ThreadTracer&				mParent;
-		std::list<Sampler*>			mActiveSamplers;
-		std::list<ThreadTracer*>	mChildThreadTracers;
-
-		// TODO:  add unused space here to avoid false sharing?
-		LLMutex	mSharedSamplerMutex;
-		Sampler mSharedSampler;
+			void copyTo(Sampler& sink)
+			{
+				LLMutexLock lock(&mSamplerMutex);
+				{
+					sink.mergeFrom(mSampler);
+				}
+			}
+		private:
+			// add a cache line's worth of unused space to avoid any potential of false sharing
+			LLMutex					mSamplerMutex;
+			Sampler					mSampler;
+		};
+		SharedData					mSharedData;
 	};
 
 
@@ -486,19 +534,6 @@ namespace LLTrace
 		void stop() {}
 		void resume() {}
 	};
-
-	class Sampler
-	{
-	public:
-		void start() {}
-		void stop() {}
-		void resume() {}
-	};
-
 }
 
-#define TOKEN_PASTE_ACTUAL(x, y) x##y
-#define TOKEN_PASTE(x, y) TOKEN_PASTE_ACTUAL(x, y)
-#define RECORD_BLOCK_TIME(block_timer) LLTrace::BlockTimer::Recorder TOKEN_PASTE(block_time_recorder, __COUNTER__)(block_timer);
-
 #endif // LL_LLTRACE_H