diff options
| author | Andrey Lihatskiy <alihatskiy@productengine.com> | 2022-09-15 20:44:04 +0300 | 
|---|---|---|
| committer | Andrey Lihatskiy <alihatskiy@productengine.com> | 2022-09-15 20:44:04 +0300 | 
| commit | 329268c5f7520a288e76e253f9bffea9dc212488 (patch) | |
| tree | dffda1aca4433b5acd7cd759714b03a6e85feb67 /indra/llcommon | |
| parent | c50dd63ca38ce44f6c6997a052a114989db8c942 (diff) | |
| parent | c2a27c474dc11dff4f93b0bd319cfec7de27bb22 (diff) | |
Merge branch 'master' into DRTVWR-548-maint-N
# Conflicts:
#	indra/newview/llmodelpreview.h
Diffstat (limited to 'indra/llcommon')
| -rw-r--r-- | indra/llcommon/llalignedarray.h | 10 | ||||
| -rw-r--r-- | indra/llcommon/llcoros.cpp | 37 | ||||
| -rw-r--r-- | indra/llcommon/llcoros.h | 35 | ||||
| -rw-r--r-- | indra/llcommon/llprocessor.cpp | 139 | ||||
| -rw-r--r-- | indra/llcommon/llprocessor.h | 5 | ||||
| -rw-r--r-- | indra/llcommon/llsys.cpp | 69 | ||||
| -rw-r--r-- | indra/llcommon/llsys.h | 12 | 
7 files changed, 291 insertions, 16 deletions
diff --git a/indra/llcommon/llalignedarray.h b/indra/llcommon/llalignedarray.h index b68e9e0f82..da9d98c16c 100644 --- a/indra/llcommon/llalignedarray.h +++ b/indra/llcommon/llalignedarray.h @@ -116,14 +116,20 @@ void LLAlignedArray<T, alignment>::resize(U32 size)  template <class T, U32 alignment>  T& LLAlignedArray<T, alignment>::operator[](int idx)  { -	llassert(idx < mElementCount); +	if(idx >= mElementCount || idx < 0) +    { +        LL_ERRS() << "Out of bounds LLAlignedArray, requested: " << (S32)idx << " size: " << mElementCount << LL_ENDL; +    }  	return mArray[idx];  }  template <class T, U32 alignment>  const T& LLAlignedArray<T, alignment>::operator[](int idx) const  { -	llassert(idx < mElementCount); +    if (idx >= mElementCount || idx < 0) +    { +        LL_ERRS() << "Out of bounds LLAlignedArray, requested: " << (S32)idx << " size: " << mElementCount << LL_ENDL; +    }  	return mArray[idx];  } diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index c2d353b0fc..14bfb98629 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -35,6 +35,7 @@  // STL headers  // std headers  #include <atomic> +#include <stdexcept>  // external library headers  #include <boost/bind.hpp>  #include <boost/fiber/fiber.hpp> @@ -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; @@ -302,11 +319,11 @@ U32 cpp_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop,      }  } -void LLCoros::winlevel(const std::string& name, const callable_t& callable) +void LLCoros::sehHandle(const std::string& name, const LLCoros::callable_t& callable)  {      __try      { -        toplevelTryWrapper(name, callable); +        LLCoros::toplevelTryWrapper(name, callable);      }      __except (cpp_exception_filter(GetExceptionCode(), GetExceptionInformation(), name))      { @@ -321,7 +338,6 @@ void LLCoros::winlevel(const std::string& name, const callable_t& callable)          throw std::exception(integer_string);      }  } -  #endif  void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& callable) @@ -350,11 +366,19 @@ void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& call      }      catch (...)      { +#if LL_WINDOWS          // Any OTHER kind of uncaught exception will cause the viewer to -        // crash, hopefully informatively. +        // 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      }  } @@ -364,8 +388,9 @@ void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& call  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); +    // 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 diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index a94cfca19f..dbff921f16 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -38,6 +38,8 @@  #include "llinstancetracker.h"  #include <boost/function.hpp>  #include <string> +#include <exception> +#include <queue>  // e.g. #include LLCOROS_MUTEX_HEADER  #define LLCOROS_MUTEX_HEADER   <boost/fiber/mutex.hpp> @@ -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 @@ -292,13 +307,27 @@ public:  private:      std::string generateDistinctName(const std::string& prefix) const; +    void toplevelTryWrapper(const std::string& name, const callable_t& callable);  #if LL_WINDOWS -    void winlevel(const std::string& name, const callable_t& callable); +    void sehHandle(const std::string& name, const callable_t& callable); // calls toplevelTryWrapper  #endif -    void toplevelTryWrapper(const std::string& name, const callable_t& callable); -    void toplevel(std::string name, callable_t callable); +    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); + +    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<ExceptionData> mExceptionQueue;      S32 mStackSize; diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index 818df07bb2..4a1a81f083 100644 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -118,7 +118,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[] = @@ -161,7 +165,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)  @@ -250,6 +258,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");  @@ -473,6 +506,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) @@ -504,6 +543,7 @@ private:  				if(cpu_info[2] & 0x8)  				{ +                    // intel specific SSE3 suplements  					setExtension(cpu_feature_names[eMONTIOR_MWAIT]);  				} @@ -516,7 +556,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)  				{ @@ -543,8 +598,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) @@ -690,6 +754,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]); +        }  	}  }; @@ -800,6 +899,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  	} @@ -860,6 +984,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 b77eb22c3a..1a473ddc97 100644 --- a/indra/llcommon/llprocessor.h +++ b/indra/llcommon/llprocessor.h @@ -54,6 +54,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 154c4a28c9..a8b5c7b3a8 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -589,6 +589,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(); @@ -601,6 +606,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 @@ -618,6 +652,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; @@ -628,6 +687,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. @@ -637,6 +701,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 cb92cb0ac6..5ffbf5a732 100644 --- a/indra/llcommon/llsys.h +++ b/indra/llcommon/llsys.h @@ -80,10 +80,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" @@ -92,10 +98,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;  };  //=============================================================================  | 
