diff --git a/indra/cwdebug/debug.cc b/indra/cwdebug/debug.cc index 18b51aad0..92ffc0d13 100644 --- a/indra/cwdebug/debug.cc +++ b/indra/cwdebug/debug.cc @@ -416,12 +416,23 @@ void cwdebug_backtrace(int n) #elif defined(DEBUG_CURLIO) #include "debug.h" +#include "aithreadid.h" namespace debug { libcwd_do_type const libcw_do; -CWD_TLS int Indent::S_indentation; +ll_thread_local int Indent::S_indentation; + +Indent::Indent(int indent) : M_indent(indent) +{ + S_indentation += M_indent; +} + +Indent::~Indent() +{ + S_indentation -= M_indent; +} std::ostream& operator<<(std::ostream& os, Indent::print_nt) { @@ -430,6 +441,19 @@ std::ostream& operator<<(std::ostream& os, Indent::print_nt) return os; } +std::ostream& operator<<(std::ostream& os, print_thread_id_t) +{ + if (!AIThreadID::in_main_thread_inline()) + { +#ifdef LL_DARWIN + os << std::hex << (size_t)apr_os_thread_current() << std::dec << ' '; +#else + os << std::hex << (size_t)AIThreadID::getCurrentThread_inline() << std::dec << ' '; +#endif + } + return os; +} + std::ostream& operator<<(std::ostream& os, libcwd::buf2str const& b2s) { static char const c2s_tab[7] = { 'a', 'b', 't', 'n', 'v', 'f', 'r' }; diff --git a/indra/cwdebug/debug.h b/indra/cwdebug/debug.h index 9e832a44c..c8f15cfb9 100644 --- a/indra/cwdebug/debug.h +++ b/indra/cwdebug/debug.h @@ -29,14 +29,13 @@ #ifdef DEBUG_CURLIO -#include "aithreadid.h" - // If CWDEBUG is not defined, but DEBUG_CURLIO is, then replace // some of the cwd macro's with something that generates viewer // specific debug output. Note that this generates a LOT of // output and should not normally be defined. #include +#include "llpreprocessor.h" namespace debug { namespace libcwd { @@ -49,6 +48,7 @@ struct buf2str { } // namespace libcwd +enum print_thread_id_t { print_thread_id }; inline void init() { } struct libcwd_do_type { void on() const { } @@ -56,14 +56,15 @@ struct libcwd_do_type { extern LL_COMMON_API libcwd_do_type const libcw_do; struct Indent { int M_indent; - static LL_COMMON_API_TLS int S_indentation; + static ll_thread_local int S_indentation; enum LL_COMMON_API print_nt { print }; - LL_COMMON_API Indent(int indent) : M_indent(indent) { S_indentation += M_indent; } - LL_COMMON_API ~Indent() { S_indentation -= M_indent; } + LL_COMMON_API Indent(int indent); + LL_COMMON_API ~Indent(); }; extern LL_COMMON_API std::ostream& operator<<(std::ostream& os, libcwd::buf2str const& b2s); extern LL_COMMON_API std::ostream& operator<<(std::ostream& os, Indent::print_nt); +extern LL_COMMON_API std::ostream& operator<<(std::ostream& os, print_thread_id_t); namespace dc { @@ -87,13 +88,13 @@ extern LL_COMMON_API fake_channel const notice; } // namespace debug #define Debug(x) do { using namespace debug; x; } while(0) -#define Dout(a, b) do { using namespace debug; if ((a).mOn) { llinfos_nf << AIThreadID::DoutPrint << (a).mLabel << ": " << Indent::print << b << llendl; } } while(0) +#define Dout(a, b) do { using namespace debug; if ((a).mOn) { llinfos_nf << print_thread_id << (a).mLabel << ": " << Indent::print << b << llendl; } } while(0) #define DoutEntering(a, b) \ int __slviewer_debug_indentation = 2; \ { \ using namespace debug; \ if ((a).mOn) \ - llinfos_nf << AIThreadID::DoutPrint << (a).mLabel << ": " << Indent::print << "Entering " << b << llendl; \ + llinfos_nf << print_thread_id << (a).mLabel << ": " << Indent::print << "Entering " << b << llendl; \ else \ __slviewer_debug_indentation = 0; \ } \ diff --git a/indra/llcommon/aithreadid.cpp b/indra/llcommon/aithreadid.cpp index 4eea7d37d..64a8dd21a 100644 --- a/indra/llcommon/aithreadid.cpp +++ b/indra/llcommon/aithreadid.cpp @@ -27,7 +27,6 @@ * - Initial version, written by Aleric Inglewood @ SL */ -#include "sys.h" #include #include #include "aithreadid.h" @@ -36,7 +35,7 @@ AIThreadID const AIThreadID::sNone(AIThreadID::none); apr_os_thread_t AIThreadID::sMainThreadID; apr_os_thread_t const AIThreadID::undefinedID = (apr_os_thread_t)-1; #ifndef LL_DARWIN -apr_os_thread_t CWD_TLS AIThreadID::lCurrentThread; +apr_os_thread_t ll_thread_local AIThreadID::lCurrentThread; #endif void AIThreadID::set_main_thread_id(void) @@ -51,21 +50,27 @@ void AIThreadID::set_current_thread_id(void) #endif } +void AIThreadID::reset(void) +{ + mID = lCurrentThread; +} + +bool AIThreadID::equals_current_thread(void) const +{ + return apr_os_thread_equal(mID, lCurrentThread); +} + +bool AIThreadID::in_main_thread(void) +{ + return apr_os_thread_equal(lCurrentThread, sMainThreadID); +} + +apr_os_thread_t AIThreadID::getCurrentThread(void) +{ + return lCurrentThread; +} + std::ostream& operator<<(std::ostream& os, AIThreadID const& id) { return os << id.mID; } - -std::ostream& operator<<(std::ostream& os, AIThreadID::dout_print_t) -{ - if (!AIThreadID::in_main_thread()) - { -#ifdef LL_DARWIN - os << std::hex << (size_t)apr_os_thread_current() << std::dec << ' '; -#else - os << std::hex << (size_t)AIThreadID::lCurrentThread << std::dec << ' '; -#endif - } - return os; -} - diff --git a/indra/llcommon/aithreadid.h b/indra/llcommon/aithreadid.h index 9f7893c66..2bb3f1dac 100644 --- a/indra/llcommon/aithreadid.h +++ b/indra/llcommon/aithreadid.h @@ -34,7 +34,6 @@ #include // apr_os_thread_t, apr_os_thread_current(), apr_os_thread_equal(). #include // std::ostream. #include "llpreprocessor.h" // LL_COMMON_API, LL_COMMON_API_TLS -#include "llerror.h" // Lightweight wrapper around apr_os_thread_t. // This class introduces no extra assembly code after optimization; it's only intend is to provide type-safety. @@ -45,12 +44,11 @@ private: static LL_COMMON_API apr_os_thread_t sMainThreadID; static LL_COMMON_API apr_os_thread_t const undefinedID; #ifndef LL_DARWIN - static LL_COMMON_API_TLS apr_os_thread_t lCurrentThread; + static ll_thread_local apr_os_thread_t lCurrentThread; #endif public: static LL_COMMON_API AIThreadID const sNone; enum undefined_thread_t { none }; - enum dout_print_t { DoutPrint }; public: AIThreadID(void) : mID(apr_os_thread_current()) { } @@ -62,7 +60,6 @@ public: friend LL_COMMON_API bool operator==(AIThreadID const& id1, AIThreadID const& id2) { return apr_os_thread_equal(id1.mID, id2.mID); } friend LL_COMMON_API bool operator!=(AIThreadID const& id1, AIThreadID const& id2) { return !apr_os_thread_equal(id1.mID, id2.mID); } friend LL_COMMON_API std::ostream& operator<<(std::ostream& os, AIThreadID const& id); - friend LL_COMMON_API std::ostream& operator<<(std::ostream& os, dout_print_t); static void set_main_thread_id(void); // Called once to set sMainThreadID. static void set_current_thread_id(void); // Called once for every thread to set lCurrentThread. #ifdef LL_DARWIN @@ -70,9 +67,15 @@ public: bool equals_current_thread(void) const { return apr_os_thread_equal(mID, apr_os_thread_current()); } static bool in_main_thread(void) { return apr_os_thread_equal(apr_os_thread_current(), sMainThreadID); } #else - void reset(void) { mID = lCurrentThread; } - bool equals_current_thread(void) const { return apr_os_thread_equal(mID, lCurrentThread); } - static bool in_main_thread(void) { return apr_os_thread_equal(lCurrentThread, sMainThreadID); } + LL_COMMON_API void reset(void); + LL_COMMON_API bool equals_current_thread(void) const; + LL_COMMON_API static bool in_main_thread(void); + LL_COMMON_API static apr_os_thread_t getCurrentThread(void); + // The *_inline variants cannot be exported because they access a thread-local member. + void reset_inline(void) { mID = lCurrentThread; } + bool equals_current_thread_inline(void) const { return apr_os_thread_equal(mID, lCurrentThread); } + static bool in_main_thread_inline(void) { return apr_os_thread_equal(lCurrentThread, sMainThreadID); } + static apr_os_thread_t getCurrentThread_inline(void) { return lCurrentThread; } #endif }; diff --git a/indra/llcommon/llaprpool.cpp b/indra/llcommon/llaprpool.cpp index de5761157..3dffa8300 100644 --- a/indra/llcommon/llaprpool.cpp +++ b/indra/llcommon/llaprpool.cpp @@ -60,10 +60,10 @@ void LLAPRPool::create(LLAPRPool& parent) // // In other words, it's safe for any thread to create a (sub)pool, independent of who // owns the parent pool. - mOwner.reset(); + mOwner.reset_inline(); #else mOwner = mParent->mOwner; - llassert(mOwner.equals_current_thread()); + llassert(mOwner.equals_current_thread_inline()); #endif apr_status_t const apr_pool_create_status = apr_pool_create(&mPool, mParent->mPool); llassert_always(apr_pool_create_status == APR_SUCCESS); @@ -83,7 +83,7 @@ void LLAPRPool::destroy(void) // of course. Otherwise, if we are a subpool, only the thread that owns // the parent may destruct us, since that is the pool that is still alive, // possibly being used by others and being altered here. - llassert(!mParent || mParent->mOwner.equals_current_thread()); + llassert(!mParent || mParent->mOwner.equals_current_thread_inline()); #endif apr_pool_t* pool = mPool; mPool = NULL; // Mark that we are BEING destructed. diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index be0ec94a3..a1f598d4a 100644 --- a/indra/llcommon/llpreprocessor.h +++ b/indra/llcommon/llpreprocessor.h @@ -198,12 +198,9 @@ // Darwin does not support thread-local data. #ifndef LL_DARWIN #if LL_WINDOWS -// On windows, thread-local data is automatically exported. -#define LL_COMMON_API_TLS __declspec(thread) -#define CWD_TLS __declspec(thread) +#define ll_thread_local __declspec(thread) #else // Linux -#define LL_COMMON_API_TLS LL_COMMON_API __thread -#define CWD_TLS __thread +#define ll_thread_local __thread #endif #endif diff --git a/indra/llcommon/llrefcount.cpp b/indra/llcommon/llrefcount.cpp index d92735aac..0956e1628 100644 --- a/indra/llcommon/llrefcount.cpp +++ b/indra/llcommon/llrefcount.cpp @@ -75,7 +75,7 @@ void LLRefCount::ref() const } mMutex.lock() ; - mLockedThreadID.reset(); + mLockedThreadID.reset_inline(); mRef++; @@ -96,7 +96,7 @@ S32 LLRefCount::unref() const } mMutex.lock() ; - mLockedThreadID.reset(); + mLockedThreadID.reset_inline(); llassert(mRef >= 1); if (0 == --mRef) diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index c8d0be2f4..5c1a29f24 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -72,7 +72,7 @@ LLAtomicS32 LLThread::sRunning = 0; LL_COMMON_API void assert_main_thread() { - if (!AIThreadID::in_main_thread()) + if (!AIThreadID::in_main_thread_inline()) { llerrs << "Illegal execution outside main thread." << llendl; } @@ -407,12 +407,12 @@ LLMutexBase::LLMutexBase() : bool LLMutexBase::isSelfLocked() const { - return mLockingThread.equals_current_thread(); + return mLockingThread.equals_current_thread_inline(); } void LLMutexBase::lock() { - if (mLockingThread.equals_current_thread()) + if (mLockingThread.equals_current_thread_inline()) { //redundant lock mCount++; return; @@ -420,12 +420,12 @@ void LLMutexBase::lock() apr_thread_mutex_lock(mAPRMutexp); - mLockingThread.reset(); + mLockingThread.reset_inline(); } bool LLMutexBase::tryLock() { - if (mLockingThread.equals_current_thread()) + if (mLockingThread.equals_current_thread_inline()) { //redundant lock mCount++; return true; @@ -433,7 +433,7 @@ bool LLMutexBase::tryLock() bool success = !APR_STATUS_IS_EBUSY(apr_thread_mutex_trylock(mAPRMutexp)); if (success) { - mLockingThread.reset(); + mLockingThread.reset_inline(); } return success; } @@ -441,7 +441,7 @@ bool LLMutexBase::tryLock() // non-blocking, but does do a lock/unlock so not free bool LLMutexBase::isLocked() const { - if (mLockingThread.equals_current_thread()) + if (mLockingThread.equals_current_thread_inline()) return false; // A call to lock() won't block. if (APR_STATUS_IS_EBUSY(apr_thread_mutex_trylock(mAPRMutexp))) return true;