From efd41b35acaae88f49a2f9167bf76cbbede1a950 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 26 Jan 2022 02:26:19 +0200 Subject: OPEN-358 Readable error --- indra/llcommon/llalignedarray.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llalignedarray.h b/indra/llcommon/llalignedarray.h index b68e9e0f82..5f52bc0b15 100644 --- a/indra/llcommon/llalignedarray.h +++ b/indra/llcommon/llalignedarray.h @@ -116,14 +116,20 @@ void LLAlignedArray::resize(U32 size) template T& LLAlignedArray::operator[](int idx) { - llassert(idx < mElementCount); + if(idx >= mElementCount) + { + LL_ERRS() << "Out of bounds LLAlignedArray, requested: " << (S32)idx << " size: " << mElementCount << LL_ENDL; + } return mArray[idx]; } template const T& LLAlignedArray::operator[](int idx) const { - llassert(idx < mElementCount); + if (idx >= mElementCount) + { + LL_ERRS() << "Out of bounds LLAlignedArray, requested: " << (S32)idx << " size: " << mElementCount << LL_ENDL; + } return mArray[idx]; } -- cgit v1.2.3 From 855f53901a2265400797f33f3fb8b53ddc6cc07f Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sat, 5 Feb 2022 02:52:56 +0200 Subject: SL-16799 Clean up use of hardcoded folder names --- indra/llcommon/llalignedarray.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llalignedarray.h b/indra/llcommon/llalignedarray.h index 5f52bc0b15..da9d98c16c 100644 --- a/indra/llcommon/llalignedarray.h +++ b/indra/llcommon/llalignedarray.h @@ -116,7 +116,7 @@ void LLAlignedArray::resize(U32 size) template T& LLAlignedArray::operator[](int idx) { - if(idx >= mElementCount) + if(idx >= mElementCount || idx < 0) { LL_ERRS() << "Out of bounds LLAlignedArray, requested: " << (S32)idx << " size: " << mElementCount << LL_ENDL; } @@ -126,7 +126,7 @@ T& LLAlignedArray::operator[](int idx) template const T& LLAlignedArray::operator[](int idx) const { - if (idx >= mElementCount) + if (idx >= mElementCount || idx < 0) { LL_ERRS() << "Out of bounds LLAlignedArray, requested: " << (S32)idx << " size: " << mElementCount << LL_ENDL; } -- cgit v1.2.3 From 236593e997e931580d3bd3192b12e450c8054b07 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 11 Feb 2022 20:26:00 +0200 Subject: Revert "SL-14961 Coroutine crash was not reported to bugsplat" Will be replaced with retrow from nat --- indra/llcommon/llapp.h | 4 ---- indra/llcommon/llcoros.cpp | 56 +++++++++++++--------------------------------- indra/llcommon/llcoros.h | 7 +++--- 3 files changed, 19 insertions(+), 48 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index c65fe21c9c..b9ae49aa44 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -286,10 +286,6 @@ public: */ LLRunner& getRunner() { return mRunner; } -#ifdef LL_WINDOWS - virtual void reportCrashToBugsplat(void* pExcepInfo /*EXCEPTION_POINTERS*/) { } -#endif - public: typedef std::map string_map; string_map mOptionMap; // Contains all command-line options and arguments in a map diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index 75fc0fec99..6a534951ff 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -264,21 +264,8 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific -U32 cpp_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop, const std::string& name) +U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop) { - // C++ exceptions were logged in toplevelTryWrapper, but not SEH - // log SEH exceptions here, to make sure it gets into bugsplat's - // report and because __try won't allow std::string operations - if (code != STATUS_MSC_EXCEPTION) - { - LL_WARNS() << "SEH crash in " << name << ", code: " << code << LL_ENDL; - } - // Handle bugsplat here, since GetExceptionInformation() can only be - // called from within filter for __except(filter), not from __except's {} - // Bugsplat should get all exceptions, C++ and SEH - LLApp::instance()->reportCrashToBugsplat(exception_infop); - - // Only convert non C++ exceptions. if (code == STATUS_MSC_EXCEPTION) { // C++ exception, go on @@ -291,29 +278,29 @@ U32 cpp_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop, } } -void LLCoros::winlevel(const std::string& name, const callable_t& callable) +void LLCoros::winlevel(const callable_t& callable) { __try { - toplevelTryWrapper(name, callable); + callable(); } - __except (cpp_exception_filter(GetExceptionCode(), GetExceptionInformation(), name)) + __except (exception_filter(GetExceptionCode(), GetExceptionInformation())) { - // convert to C++ styled exception for handlers other than bugsplat + // convert to C++ styled exception // Note: it might be better to use _se_set_translator // if you want exception to inherit full callstack - // - // in case of bugsplat this will get to exceptionTerminateHandler and - // looks like fiber will terminate application after that char integer_string[512]; - sprintf(integer_string, "SEH crash in %s, code: %lu\n", name.c_str(), GetExceptionCode()); + sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode()); throw std::exception(integer_string); } } #endif -void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& callable) +// Top-level wrapper around caller's coroutine callable. +// Normally we like to pass strings and such by const reference -- but in this +// case, we WANT to copy both the name and the callable to our local stack! +void LLCoros::toplevel(std::string name, callable_t callable) { // keep the CoroData on this top-level function's stack frame CoroData corodata(name); @@ -323,12 +310,16 @@ void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& call // run the code the caller actually wants in the coroutine try { +#if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD + winlevel(callable); +#else callable(); +#endif } catch (const Stop& exc) { LL_INFOS("LLCoros") << "coroutine " << name << " terminating because " - << exc.what() << LL_ENDL; + << exc.what() << LL_ENDL; } catch (const LLContinueError&) { @@ -341,25 +332,10 @@ void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& call { // Any OTHER kind of uncaught exception will cause the viewer to // crash, hopefully informatively. - LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name)); - // to not modify callstack - throw; + CRASH_ON_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name)); } } -// Top-level wrapper around caller's coroutine callable. -// Normally we like to pass strings and such by const reference -- but in this -// case, we WANT to copy both the name and the callable to our local stack! -void LLCoros::toplevel(std::string name, callable_t callable) -{ -#if LL_WINDOWS - // Can not use __try in functions that require unwinding, so use one more wrapper - winlevel(name, callable); -#else - toplevelTryWrapper(name, callable); -#endif -} - //static void LLCoros::checkStop() { diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index a94cfca19f..51f7380def 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -292,12 +292,11 @@ public: private: std::string generateDistinctName(const std::string& prefix) const; -#if LL_WINDOWS - void winlevel(const std::string& name, const callable_t& callable); -#endif - void toplevelTryWrapper(const std::string& name, const callable_t& callable); void toplevel(std::string name, callable_t callable); struct CoroData; +#if LL_WINDOWS + static void winlevel(const callable_t& callable); +#endif static CoroData& get_CoroData(const std::string& caller); S32 mStackSize; -- cgit v1.2.3 From 6c3507d6d358485c2a8e2fc4d915847cbeda3ee3 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sun, 16 Dec 2018 14:31:32 -0500 Subject: SL-10190: Introduce LLCoros::saveException() and rethrow(). This mechanism uses a queue of std::exception_ptrs to transport an (otherwise) uncaught exception from a terminated coroutine to the thread's main fiber. The main loop calls LLCoros::rethrow() just after giving some cycles to ready coroutines that frame. # Conflicts: # indra/llcommon/llcoros.cpp # indra/llcommon/llcoros.h # indra/newview/llappviewer.cpp --- indra/llcommon/llcoros.cpp | 25 ++++++++++++++++++++++--- indra/llcommon/llcoros.h | 29 +++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 3 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index 6a534951ff..a182d305e8 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -35,6 +35,7 @@ // STL headers // std headers #include +#include // external library headers #include #include @@ -214,6 +215,22 @@ std::string LLCoros::logname() return data.mName.empty()? data.getKey() : data.mName; } +void LLCoros::saveException(const std::string& name, std::exception_ptr exc) +{ + mExceptionQueue.emplace(name, exc); +} + +void LLCoros::rethrow() +{ + if (! mExceptionQueue.empty()) + { + ExceptionData front = mExceptionQueue.front(); + mExceptionQueue.pop(); + LL_WARNS("LLCoros") << "Rethrowing exception from coroutine " << front.name << LL_ENDL; + std::rethrow_exception(front.exception); + } +} + void LLCoros::setStackSize(S32 stacksize) { LL_DEBUGS("LLCoros") << "Setting coroutine stack size to " << stacksize << LL_ENDL; @@ -330,9 +347,11 @@ void LLCoros::toplevel(std::string name, callable_t callable) } catch (...) { - // Any OTHER kind of uncaught exception will cause the viewer to - // crash, hopefully informatively. - CRASH_ON_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name)); + // Stash any OTHER kind of uncaught exception in the rethrow() queue + // to be rethrown by the main fiber. + LL_WARNS("LLCoros") << "Capturing uncaught exception in coroutine " + << name << LL_ENDL; + LLCoros::instance().saveException(name, std::current_exception()); } } diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index 51f7380def..59b2b91f96 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -38,6 +38,8 @@ #include "llinstancetracker.h" #include #include +#include +#include // e.g. #include LLCOROS_MUTEX_HEADER #define LLCOROS_MUTEX_HEADER @@ -156,6 +158,19 @@ public: * LLCoros::launch()). */ static std::string getName(); + + /** + * rethrow() is called by the thread's main fiber to propagate an + * exception from any coroutine into the main fiber, where it can engage + * the normal unhandled-exception machinery, up to and including crash + * reporting. + * + * LLCoros maintains a queue of otherwise-uncaught exceptions from + * terminated coroutines. Each call to rethrow() pops the first of those + * and rethrows it. When the queue is empty (normal case), rethrow() is a + * no-op. + */ + void rethrow(); /** * This variation returns a name suitable for log messages: the explicit @@ -298,6 +313,20 @@ private: static void winlevel(const callable_t& callable); #endif static CoroData& get_CoroData(const std::string& caller); + void saveException(const std::string& name, std::exception_ptr exc); + + struct ExceptionData + { + ExceptionData(const std::string& nm, std::exception_ptr exc): + name(nm), + exception(exc) + {} + // name of coroutine that originally threw this exception + std::string name; + // the thrown exception + std::exception_ptr exception; + }; + std::queue mExceptionQueue; S32 mStackSize; -- cgit v1.2.3 From 913bddf18fa33b54cdb6e30ebd290363e33e7f47 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sun, 16 Dec 2018 14:51:39 -0500 Subject: SL-10190: Slightly reduce conditional clutter in llcoros.{h,cpp}. Rename 'winlevel()' to 'sehandle()'; change it from a static member function to a free function, thus eliminating the conditional in llcoros.h. Elsewhere than Windows, provide a zero-cost pass-through sehandle() implementation, eliminating the conditional in toplevel(). # Conflicts: # indra/llcommon/llcoros.cpp # indra/llcommon/llcoros.h --- indra/llcommon/llcoros.cpp | 22 +++++++++++++++------- indra/llcommon/llcoros.h | 3 --- 2 files changed, 15 insertions(+), 10 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index a182d305e8..51cf2138cb 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -277,6 +277,9 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl return name; } +namespace +{ + #if LL_WINDOWS static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific @@ -295,7 +298,7 @@ U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop) } } -void LLCoros::winlevel(const callable_t& callable) +void sehandle(const LLCoros::callable_t& callable) { __try { @@ -312,7 +315,16 @@ void LLCoros::winlevel(const callable_t& callable) } } -#endif +#else // ! LL_WINDOWS + +inline void sehandle(const LLCoros::callable_t& callable) +{ + callable(); +} + +#endif // ! LL_WINDOWS + +} // anonymous namespace // Top-level wrapper around caller's coroutine callable. // Normally we like to pass strings and such by const reference -- but in this @@ -327,11 +339,7 @@ void LLCoros::toplevel(std::string name, callable_t callable) // run the code the caller actually wants in the coroutine try { -#if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD - winlevel(callable); -#else - callable(); -#endif + sehandle(callable); } catch (const Stop& exc) { diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index 59b2b91f96..966ce03296 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -309,9 +309,6 @@ private: std::string generateDistinctName(const std::string& prefix) const; void toplevel(std::string name, callable_t callable); struct CoroData; -#if LL_WINDOWS - static void winlevel(const callable_t& callable); -#endif static CoroData& get_CoroData(const std::string& caller); void saveException(const std::string& name, std::exception_ptr exc); -- cgit v1.2.3 From 935c1362a222f192bf913270d01f6c31c16e175b Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Mon, 14 Feb 2022 22:26:43 +0200 Subject: Restored SL-14961 SL-14961 works better for windows than rethrow --- indra/llcommon/llapp.h | 4 +++ indra/llcommon/llcoros.cpp | 74 ++++++++++++++++++++++++++++++---------------- indra/llcommon/llcoros.h | 6 +++- 3 files changed, 57 insertions(+), 27 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index b9ae49aa44..c65fe21c9c 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -286,6 +286,10 @@ public: */ LLRunner& getRunner() { return mRunner; } +#ifdef LL_WINDOWS + virtual void reportCrashToBugsplat(void* pExcepInfo /*EXCEPTION_POINTERS*/) { } +#endif + public: typedef std::map string_map; string_map mOptionMap; // Contains all command-line options and arguments in a map diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index 51cf2138cb..ca2e7b38d7 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -277,15 +277,25 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl return name; } -namespace -{ - #if LL_WINDOWS static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific -U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop) +U32 cpp_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop, const std::string& name) { + // C++ exceptions were logged in toplevelTryWrapper, but not SEH + // log SEH exceptions here, to make sure it gets into bugsplat's + // report and because __try won't allow std::string operations + if (code != STATUS_MSC_EXCEPTION) + { + LL_WARNS() << "SEH crash in " << name << ", code: " << code << LL_ENDL; + } + // Handle bugsplat here, since GetExceptionInformation() can only be + // called from within filter for __except(filter), not from __except's {} + // Bugsplat should get all exceptions, C++ and SEH + LLApp::instance()->reportCrashToBugsplat(exception_infop); + + // Only convert non C++ exceptions. if (code == STATUS_MSC_EXCEPTION) { // C++ exception, go on @@ -298,38 +308,28 @@ U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop) } } -void sehandle(const LLCoros::callable_t& callable) +void LLCoros::sehHandle(const std::string& name, const LLCoros::callable_t& callable) { __try { - callable(); + LLCoros::toplevelTryWrapper(name, callable); } - __except (exception_filter(GetExceptionCode(), GetExceptionInformation())) + __except (cpp_exception_filter(GetExceptionCode(), GetExceptionInformation(), name)) { - // convert to C++ styled exception + // convert to C++ styled exception for handlers other than bugsplat // Note: it might be better to use _se_set_translator // if you want exception to inherit full callstack + // + // in case of bugsplat this will get to exceptionTerminateHandler and + // looks like fiber will terminate application after that char integer_string[512]; - sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode()); + sprintf(integer_string, "SEH crash in %s, code: %lu\n", name.c_str(), GetExceptionCode()); throw std::exception(integer_string); } } +#endif -#else // ! LL_WINDOWS - -inline void sehandle(const LLCoros::callable_t& callable) -{ - callable(); -} - -#endif // ! LL_WINDOWS - -} // anonymous namespace - -// Top-level wrapper around caller's coroutine callable. -// Normally we like to pass strings and such by const reference -- but in this -// case, we WANT to copy both the name and the callable to our local stack! -void LLCoros::toplevel(std::string name, callable_t callable) +void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& callable) { // keep the CoroData on this top-level function's stack frame CoroData corodata(name); @@ -339,12 +339,12 @@ void LLCoros::toplevel(std::string name, callable_t callable) // run the code the caller actually wants in the coroutine try { - sehandle(callable); + callable(); } catch (const Stop& exc) { LL_INFOS("LLCoros") << "coroutine " << name << " terminating because " - << exc.what() << LL_ENDL; + << exc.what() << LL_ENDL; } catch (const LLContinueError&) { @@ -355,14 +355,36 @@ void LLCoros::toplevel(std::string name, callable_t callable) } catch (...) { +#if LL_WINDOWS + // Any OTHER kind of uncaught exception will cause the viewer to + // crash, SEH handling should catch it and report to bugsplat. + LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name)); + // to not modify callstack + throw; +#else // Stash any OTHER kind of uncaught exception in the rethrow() queue // to be rethrown by the main fiber. LL_WARNS("LLCoros") << "Capturing uncaught exception in coroutine " << name << LL_ENDL; LLCoros::instance().saveException(name, std::current_exception()); +#endif } } +// Top-level wrapper around caller's coroutine callable. +// Normally we like to pass strings and such by const reference -- but in this +// case, we WANT to copy both the name and the callable to our local stack! +void LLCoros::toplevel(std::string name, callable_t callable) +{ +#if LL_WINDOWS + // Because SEH can's have unwinding, need to call a wrapper + // 'try' is inside SEH handling to not catch LLContinue + sehHandle(name, callable); +#else + toplevelTryWrapper(name, callable); +#endif +} + //static void LLCoros::checkStop() { diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index 966ce03296..dbff921f16 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -307,7 +307,11 @@ public: private: std::string generateDistinctName(const std::string& prefix) const; - void toplevel(std::string name, callable_t callable); + void toplevelTryWrapper(const std::string& name, const callable_t& callable); +#if LL_WINDOWS + void sehHandle(const std::string& name, const callable_t& callable); // calls toplevelTryWrapper +#endif + void toplevel(std::string name, callable_t callable); // calls sehHandle or toplevelTryWrapper struct CoroData; static CoroData& get_CoroData(const std::string& caller); void saveException(const std::string& name, std::exception_ptr exc); -- cgit v1.2.3 From ed74d15246ded84ded3a096046d79e95352b444e Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 18 May 2022 00:41:26 +0300 Subject: SL-17388 Add SSE version info to ViewerStats --- indra/llcommon/llprocessor.cpp | 139 +++++++++++++++++++++++++++++++++++++++-- indra/llcommon/llprocessor.h | 5 ++ indra/llcommon/llsys.cpp | 69 ++++++++++++++++++++ indra/llcommon/llsys.h | 12 ++++ 4 files changed, 220 insertions(+), 5 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index 5d16a4b74d..fe97cf8108 100644 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -132,7 +132,11 @@ namespace eMONTIOR_MWAIT=33, eCPLDebugStore=34, eThermalMonitor2=35, - eAltivec=36 + eAltivec=36, + eSSE3S_Features = 37, + eSSE4_1_Features = 38, + eSSE4_2_Features = 39, + eSSE4a_Features = 40, }; const char* cpu_feature_names[] = @@ -175,7 +179,11 @@ namespace "CPL Qualified Debug Store", "Thermal Monitor 2", - "Altivec" + "Altivec", + "SSE3S Instructions", + "SSE4.1 Instructions", + "SSE4.2 Instructions", + "SSE4a Instructions", }; std::string intel_CPUFamilyName(int composed_family) @@ -264,6 +272,31 @@ public: return hasExtension(cpu_feature_names[eSSE2_Ext]); } + bool hasSSE3() const + { + return hasExtension(cpu_feature_names[eSSE3_Features]); + } + + bool hasSSE3S() const + { + return hasExtension(cpu_feature_names[eSSE3S_Features]); + } + + bool hasSSE41() const + { + return hasExtension(cpu_feature_names[eSSE4_1_Features]); + } + + bool hasSSE42() const + { + return hasExtension(cpu_feature_names[eSSE4_2_Features]); + } + + bool hasSSE4a() const + { + return hasExtension(cpu_feature_names[eSSE4a_Features]); + } + bool hasAltivec() const { return hasExtension("Altivec"); @@ -487,6 +520,12 @@ private: *((int*)(cpu_vendor+4)) = cpu_info[3]; *((int*)(cpu_vendor+8)) = cpu_info[2]; setInfo(eVendor, cpu_vendor); + std::string cmp_vendor(cpu_vendor); + bool is_amd = false; + if (cmp_vendor == "AuthenticAMD") + { + is_amd = true; + } // Get the information associated with each valid Id for(unsigned int i=0; i<=ids; ++i) @@ -518,6 +557,7 @@ private: if(cpu_info[2] & 0x8) { + // intel specific SSE3 suplements setExtension(cpu_feature_names[eMONTIOR_MWAIT]); } @@ -530,7 +570,22 @@ private: { setExtension(cpu_feature_names[eThermalMonitor2]); } - + + if (cpu_info[2] & 0x200) + { + setExtension(cpu_feature_names[eSSE3S_Features]); + } + + if (cpu_info[2] & 0x80000) + { + setExtension(cpu_feature_names[eSSE4_1_Features]); + } + + if (cpu_info[2] & 0x100000) + { + setExtension(cpu_feature_names[eSSE4_2_Features]); + } + unsigned int feature_info = (unsigned int) cpu_info[3]; for(unsigned int index = 0, bit = 1; index < eSSE3_Features; ++index, bit <<= 1) { @@ -557,8 +612,17 @@ private: __cpuid(cpu_info, i); // Interpret CPU brand string and cache information. - if (i == 0x80000002) - memcpy(cpu_brand_string, cpu_info, sizeof(cpu_info)); + if (i == 0x80000001) + { + if (is_amd) + { + setExtension(cpu_feature_names[eSSE4a_Features]); + } + } + else if (i == 0x80000002) + { + memcpy(cpu_brand_string, cpu_info, sizeof(cpu_info)); + } else if (i == 0x80000003) memcpy(cpu_brand_string + 16, cpu_info, sizeof(cpu_info)); else if (i == 0x80000004) @@ -704,6 +768,41 @@ private: uint64_t ext_feature_info = getSysctlInt64("machdep.cpu.extfeature_bits"); S32 *ext_feature_infos = (S32*)(&ext_feature_info); setConfig(eExtFeatureBits, ext_feature_infos[0]); + + + char cpu_features[1024]; + len = sizeof(cpu_features); + memset(cpu_features, 0, len); + sysctlbyname("machdep.cpu.features", (void*)cpu_features, &len, NULL, 0); + + std::string cpu_features_str(cpu_features); + cpu_features_str = " " + cpu_features_str + " "; + + if (cpu_features_str.find(" SSE3 ") != std::string::npos) + { + setExtension(cpu_feature_names[eSSE3_Features]); + } + + if (cpu_features_str.find(" SSSE3 ") != std::string::npos) + { + setExtension(cpu_feature_names[eSSE3S_Features]); + } + + if (cpu_features_str.find(" SSE4.1 ") != std::string::npos) + { + setExtension(cpu_feature_names[eSSE4_1_Features]); + } + + if (cpu_features_str.find(" SSE4.2 ") != std::string::npos) + { + setExtension(cpu_feature_names[eSSE4_2_Features]); + } + + if (cpu_features_str.find(" SSE4A ") != std::string::npos) + { + // Not supposed to happen? + setExtension(cpu_feature_names[eSSE4a_Features]); + } } }; @@ -814,6 +913,31 @@ private: { setExtension(cpu_feature_names[eSSE2_Ext]); } + + if (flags.find(" pni ") != std::string::npos) + { + setExtension(cpu_feature_names[eSSE3_Features]); + } + + if (flags.find(" ssse3 ") != std::string::npos) + { + setExtension(cpu_feature_names[eSSE3S_Features]); + } + + if (flags.find(" sse4_1 ") != std::string::npos) + { + setExtension(cpu_feature_names[eSSE4_1_Features]); + } + + if (flags.find(" sse4_2 ") != std::string::npos) + { + setExtension(cpu_feature_names[eSSE4_2_Features]); + } + + if (flags.find(" sse4a ") != std::string::npos) + { + setExtension(cpu_feature_names[eSSE4a_Features]); + } # endif // LL_X86 } @@ -874,6 +998,11 @@ LLProcessorInfo::~LLProcessorInfo() {} F64MegahertzImplicit LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); } bool LLProcessorInfo::hasSSE() const { return mImpl->hasSSE(); } bool LLProcessorInfo::hasSSE2() const { return mImpl->hasSSE2(); } +bool LLProcessorInfo::hasSSE3() const { return mImpl->hasSSE3(); } +bool LLProcessorInfo::hasSSE3S() const { return mImpl->hasSSE3S(); } +bool LLProcessorInfo::hasSSE41() const { return mImpl->hasSSE41(); } +bool LLProcessorInfo::hasSSE42() const { return mImpl->hasSSE42(); } +bool LLProcessorInfo::hasSSE4a() const { return mImpl->hasSSE4a(); } bool LLProcessorInfo::hasAltivec() const { return mImpl->hasAltivec(); } std::string LLProcessorInfo::getCPUFamilyName() const { return mImpl->getCPUFamilyName(); } std::string LLProcessorInfo::getCPUBrandName() const { return mImpl->getCPUBrandName(); } diff --git a/indra/llcommon/llprocessor.h b/indra/llcommon/llprocessor.h index 90e5bc59ee..8156dd12e6 100644 --- a/indra/llcommon/llprocessor.h +++ b/indra/llcommon/llprocessor.h @@ -40,6 +40,11 @@ public: F64MegahertzImplicit getCPUFrequency() const; bool hasSSE() const; bool hasSSE2() const; + bool hasSSE3() const; + bool hasSSE3S() const; + bool hasSSE41() const; + bool hasSSE42() const; + bool hasSSE4a() const; bool hasAltivec() const; std::string getCPUFamilyName() const; std::string getCPUBrandName() const; diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index cdc1d83b59..a6c4d81472 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -571,6 +571,11 @@ LLCPUInfo::LLCPUInfo() // proc.WriteInfoTextFile("procInfo.txt"); mHasSSE = proc.hasSSE(); mHasSSE2 = proc.hasSSE2(); + mHasSSE3 = proc.hasSSE3(); + mHasSSE3S = proc.hasSSE3S(); + mHasSSE41 = proc.hasSSE41(); + mHasSSE42 = proc.hasSSE42(); + mHasSSE4a = proc.hasSSE4a(); mHasAltivec = proc.hasAltivec(); mCPUMHz = (F64)proc.getCPUFrequency(); mFamily = proc.getCPUFamilyName(); @@ -583,6 +588,35 @@ LLCPUInfo::LLCPUInfo() } mCPUString = out.str(); LLStringUtil::trim(mCPUString); + + if (mHasSSE) + { + mSSEVersions.append("1"); + } + if (mHasSSE2) + { + mSSEVersions.append("2"); + } + if (mHasSSE3) + { + mSSEVersions.append("3"); + } + if (mHasSSE3S) + { + mSSEVersions.append("3S"); + } + if (mHasSSE41) + { + mSSEVersions.append("4.1"); + } + if (mHasSSE42) + { + mSSEVersions.append("4.2"); + } + if (mHasSSE4a) + { + mSSEVersions.append("4a"); + } } bool LLCPUInfo::hasAltivec() const @@ -600,6 +634,31 @@ bool LLCPUInfo::hasSSE2() const return mHasSSE2; } +bool LLCPUInfo::hasSSE3() const +{ + return mHasSSE3; +} + +bool LLCPUInfo::hasSSE3S() const +{ + return mHasSSE3S; +} + +bool LLCPUInfo::hasSSE41() const +{ + return mHasSSE41; +} + +bool LLCPUInfo::hasSSE42() const +{ + return mHasSSE42; +} + +bool LLCPUInfo::hasSSE4a() const +{ + return mHasSSE4a; +} + F64 LLCPUInfo::getMHz() const { return mCPUMHz; @@ -610,6 +669,11 @@ std::string LLCPUInfo::getCPUString() const return mCPUString; } +const LLSD& LLCPUInfo::getSSEVersions() const +{ + return mSSEVersions; +} + void LLCPUInfo::stream(std::ostream& s) const { // gather machine information. @@ -619,6 +683,11 @@ void LLCPUInfo::stream(std::ostream& s) const // CPU's attributes regardless of platform s << "->mHasSSE: " << (U32)mHasSSE << std::endl; s << "->mHasSSE2: " << (U32)mHasSSE2 << std::endl; + s << "->mHasSSE3: " << (U32)mHasSSE3 << std::endl; + s << "->mHasSSE3S: " << (U32)mHasSSE3S << std::endl; + s << "->mHasSSE41: " << (U32)mHasSSE41 << std::endl; + s << "->mHasSSE42: " << (U32)mHasSSE42 << std::endl; + s << "->mHasSSE4a: " << (U32)mHasSSE4a << std::endl; s << "->mHasAltivec: " << (U32)mHasAltivec << std::endl; s << "->mCPUMHz: " << mCPUMHz << std::endl; s << "->mCPUString: " << mCPUString << std::endl; diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h index 5ab97939b9..6882cd9533 100644 --- a/indra/llcommon/llsys.h +++ b/indra/llcommon/llsys.h @@ -76,10 +76,16 @@ public: void stream(std::ostream& s) const; std::string getCPUString() const; + const LLSD& getSSEVersions() const; bool hasAltivec() const; bool hasSSE() const; bool hasSSE2() const; + bool hasSSE3() const; + bool hasSSE3S() const; + bool hasSSE41() const; + bool hasSSE42() const; + bool hasSSE4a() const; F64 getMHz() const; // Family is "AMD Duron" or "Intel Pentium Pro" @@ -88,10 +94,16 @@ public: private: bool mHasSSE; bool mHasSSE2; + bool mHasSSE3; + bool mHasSSE3S; + bool mHasSSE41; + bool mHasSSE42; + bool mHasSSE4a; bool mHasAltivec; F64 mCPUMHz; std::string mFamily; std::string mCPUString; + LLSD mSSEVersions; }; //============================================================================= -- cgit v1.2.3 From 8ef25a63bd1e84e02fe2c08ce439aa26c0f3d5f1 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Mon, 23 May 2022 19:49:18 -0700 Subject: SL-15937 - adjust memory limit / cache code --- indra/llcommon/llmemory.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index ea84e4c1ea..afd476096e 100644 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -210,11 +210,9 @@ U64 LLMemory::getCurrentRSS() mach_msg_type_number_t basicInfoCount = MACH_TASK_BASIC_INFO_COUNT; if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&basicInfo, &basicInfoCount) == KERN_SUCCESS) { -// residentSize = basicInfo.resident_size; - // Although this method is defined to return the "resident set size," - // in fact what callers want from it is the total virtual memory - // consumed by the application. - residentSize = basicInfo.virtual_size; + residentSize = basicInfo.resident_size; + // 64-bit macos apps allocate 32 GB or more at startup, and this is reflected in virtual_size. + // basicInfo.virtual_size is not what we want. } else { -- cgit v1.2.3 From 14ea73033ab64321d4034714ece6ad999093a9a8 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Tue, 31 May 2022 12:49:53 -0700 Subject: SL-17483: Make ThreadPool inherit LLInstanceTracker (cherry picked from commit 41d6a0e222241606c317281e2f0b211e16813dd5) --- indra/llcommon/threadpool.cpp | 1 + indra/llcommon/threadpool.h | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/threadpool.cpp b/indra/llcommon/threadpool.cpp index ba914035e2..d5adf11264 100644 --- a/indra/llcommon/threadpool.cpp +++ b/indra/llcommon/threadpool.cpp @@ -22,6 +22,7 @@ #include "stringize.h" LL::ThreadPool::ThreadPool(const std::string& name, size_t threads, size_t capacity): + super(name), mQueue(name, capacity), mName("ThreadPool:" + name), mThreadCount(threads) diff --git a/indra/llcommon/threadpool.h b/indra/llcommon/threadpool.h index b79c9b9090..f8eec3b457 100644 --- a/indra/llcommon/threadpool.h +++ b/indra/llcommon/threadpool.h @@ -22,8 +22,10 @@ namespace LL { - class ThreadPool + class ThreadPool: public LLInstanceTracker { + private: + using super = LLInstanceTracker; public: /** * Pass ThreadPool a string name. This can be used to look up the -- cgit v1.2.3 From 3e60b53d52d09e3f1412a9476743a77e555104d9 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 6 May 2022 14:46:49 -0700 Subject: SL-16182: Offload audio decoding from the main thread to the general work queue. The work queue callback binds "this". This is deemed safe due to current dependencies, but see the associated comment in the return callback. There was some trial and error to get a this-binded lambda to compile. Due to LLVorbisDecodeState writing to disk off-thread, limit audio decodes proportional to general worker thread count. Guess the thread count for now. --- indra/llcommon/workqueue.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h index 96574a18b9..70fd65bd0c 100644 --- a/indra/llcommon/workqueue.h +++ b/indra/llcommon/workqueue.h @@ -403,7 +403,7 @@ namespace LL [result = std::forward(callable)(), callback = std::move(callback)] () - { callback(std::move(result)); }; + mutable { callback(std::move(result)); }; } }; @@ -449,7 +449,7 @@ namespace LL callable = std::move(callable), callback = std::move(callback)] () - { + mutable { // Use postMaybe() below in case this originating WorkQueue // has been closed or destroyed. Remember, the outer lambda is // now running on a thread servicing the target WorkQueue, and @@ -513,7 +513,7 @@ namespace LL // We dare to bind a reference to Promise because it's // specifically designed for cross-thread communication. [&promise, callable = std::move(callable)]() - { + mutable { try { // call the caller's callable and trigger promise with result @@ -542,7 +542,7 @@ namespace LL time, // &promise is designed for cross-thread access [&promise, callable = std::move(callable)]() - { + mutable { try { callable(); -- cgit v1.2.3 From 1167ea994c44a2c45f68109325ae1862b0ca09c3 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Wed, 22 Jun 2022 18:00:49 +0300 Subject: SL-17634 Replace deprecated carbon Gestalt calls --- indra/llcommon/CMakeLists.txt | 11 ++++---- indra/llcommon/llsys.cpp | 21 ++------------ indra/llcommon/llsys_objc.h | 33 ++++++++++++++++++++++ indra/llcommon/llsys_objc.mm | 64 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+), 24 deletions(-) create mode 100644 indra/llcommon/llsys_objc.h create mode 100644 indra/llcommon/llsys_objc.mm (limited to 'indra/llcommon') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index ca8b5e946f..fd8fbf70c8 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -265,6 +265,11 @@ set(llcommon_HEADER_FILES workqueue.h StackWalker.h ) + +if (DARWIN) + list(APPEND llcommon_HEADER_FILES llsys_objc.h) + list(APPEND llcommon_SOURCE_FILES llsys_objc.mm) +endif (DARWIN) set_source_files_properties(${llcommon_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE) @@ -312,12 +317,6 @@ target_link_libraries( ${TRACY_LIBRARY} ) -if (DARWIN) - include(CMakeFindFrameworks) - find_library(CARBON_LIBRARY Carbon) - target_link_libraries(llcommon ${CARBON_LIBRARY}) -endif (DARWIN) - add_dependencies(llcommon stage_third_party_libs) if (LL_TESTS) diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index f717b2cf34..6d0483903b 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -64,6 +64,7 @@ using namespace llsd; # include // GetPerformanceInfo() et al. # include #elif LL_DARWIN +# include "llsys_objc.h" # include # include # include @@ -74,12 +75,6 @@ using namespace llsd; # include # include # include - -// disable warnings about Gestalt calls being deprecated -// until Apple get's on the ball and provides an alternative -// -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - #elif LL_LINUX # include # include @@ -278,12 +273,9 @@ LLOSInfo::LLOSInfo() : { const char * DARWIN_PRODUCT_NAME = "Mac OS X"; - SInt32 major_version, minor_version, bugfix_version; - OSErr r1 = Gestalt(gestaltSystemVersionMajor, &major_version); - OSErr r2 = Gestalt(gestaltSystemVersionMinor, &minor_version); - OSErr r3 = Gestalt(gestaltSystemVersionBugFix, &bugfix_version); + S32 major_version, minor_version, bugfix_version = 0; - if((r1 == noErr) && (r2 == noErr) && (r3 == noErr)) + if (LLGetDarwinOSInfo(major_version, minor_version, bugfix_version)) { mMajorVer = major_version; mMinorVer = minor_version; @@ -1315,10 +1307,3 @@ BOOL gzip_file(const std::string& srcfile, const std::string& dstfile) if (dst != NULL) gzclose(dst); return retval; } - -#if LL_DARWIN -// disable warnings about Gestalt calls being deprecated -// until Apple get's on the ball and provides an alternative -// -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif diff --git a/indra/llcommon/llsys_objc.h b/indra/llcommon/llsys_objc.h new file mode 100644 index 0000000000..35599a574b --- /dev/null +++ b/indra/llcommon/llsys_objc.h @@ -0,0 +1,33 @@ +/** + * @file llsys_objc.h + * @brief Header file for llsys_objc.mm + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, 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_LLSYS_OBJC_H +#define LL_LLSYS_OBJC_H + +bool LLGetDarwinOSInfo(int &major, int &minor, int &patch); + + +#endif // LL_LLSYS_OBJC_H diff --git a/indra/llcommon/llsys_objc.mm b/indra/llcommon/llsys_objc.mm new file mode 100644 index 0000000000..cdb1e320d5 --- /dev/null +++ b/indra/llcommon/llsys_objc.mm @@ -0,0 +1,64 @@ +/** + * @file llsys_objc.mm + * @brief obj-c implementation of the system information functions + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, 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$ + */ + +#import "llsys_objc.h" +#import + +static int intAtStringIndex(NSArray *array, int index) +{ + return [(NSString *)[array objectAtIndex:index] integerValue]; +} + +bool LLGetDarwinOSInfo(int &major, int &minor, int &patch) +{ + if (NSAppKitVersionNumber > NSAppKitVersionNumber10_8) + { + NSOperatingSystemVersion osVersion = [[NSProcessInfo processInfo] operatingSystemVersion]; + major = osVersion.majorVersion; + minor = osVersion.minorVersion; + patch = osVersion.patchVersion; + } + else + { + NSString* versionString = [[NSDictionary dictionaryWithContentsOfFile: + @"/System/Library/CoreServices/SystemVersion.plist"] objectForKey:@"ProductVersion"]; + NSArray* versions = [versionString componentsSeparatedByString:@"."]; + NSUInteger count = [versions count]; + if (count > 0) + { + major = intAtStringIndex(versions, 0); + if (count > 1) + { + minor = intAtStringIndex(versions, 1); + if (count > 2) + { + patch = intAtStringIndex(versions, 2); + } + } + } + } + return true; +} -- cgit v1.2.3 From 56e1db9c15f9521296e5565dcc5d4d828ffeb3b4 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 16 Sep 2022 17:09:55 +0100 Subject: SL-18119 - UIUsage logs for some common operations --- indra/llcommon/llrefcount.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llrefcount.cpp b/indra/llcommon/llrefcount.cpp index 5cbd346411..6852b5536a 100644 --- a/indra/llcommon/llrefcount.cpp +++ b/indra/llcommon/llrefcount.cpp @@ -30,7 +30,7 @@ #include "llerror.h" // maximum reference count before sounding memory leak alarm -const S32 gMaxRefCount = 65536; +const S32 gMaxRefCount = S32_MAX; LLRefCount::LLRefCount(const LLRefCount& other) : mRef(0) -- cgit v1.2.3