From 655402192f9ef58650e6b6f9a01f5748747aa263 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Wed, 12 Aug 2026 19:49:13 +0300 Subject: #6119 Mutex deadlock on LLGridManager singleton LLGridManager is performance critical and low level enough that it should just be turned into LLSimpleton. Without capture_dependency there won't be a 'deadlock'. --- indra/newview/llappviewer.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'indra/newview/llappviewer.cpp') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 2d8e94fdda..d3df15a642 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2175,6 +2175,7 @@ bool LLAppViewer::cleanup() LLWorld::deleteSingleton(); LLVoiceClient::deleteSingleton(); LLUI::deleteSingleton(); + LLGridManager::deleteSingleton(); LLWatchdog::deleteSingleton(); // It's not at first obvious where, in this long sequence, a generic cleanup @@ -3009,6 +3010,8 @@ bool LLAppViewer::initConfiguration() } } + LLGridManager::createInstance(); + LLSLURL start_slurl; if (!starting_location.empty()) { @@ -3057,6 +3060,7 @@ bool LLAppViewer::initConfiguration() // Do not save settings. // Might be smarter to have an exit code for a more reliable // "early exit, needs cleanup" case. + LLGridManager::deleteSingleton(); LLSingletonBase::deleteAll(); cleanupConsole(); delete mSettingsLocationList; @@ -3117,6 +3121,7 @@ bool LLAppViewer::initConfiguration() // Since returning 'false' is basically an error without cleanup, // do cleanup here. No need to worry about marker files here. + LLGridManager::deleteSingleton(); LLSingletonBase::deleteAll(); cleanupConsole(); return false; -- cgit v1.3 From b72dc959c3b949fac35fba7f76436553e23f0320 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Thu, 13 Aug 2026 20:39:18 +0300 Subject: p#692 Update system data with simd --- indra/llcommon/llprocessor.cpp | 89 ++++++++++++++++++++++++++++++++++++++++++ indra/llcommon/llprocessor.h | 3 ++ indra/llcommon/llsys.cpp | 35 +++++++++++++++++ indra/llcommon/llsys.h | 8 ++++ indra/newview/llappviewer.cpp | 8 +++- 5 files changed, 141 insertions(+), 2 deletions(-) (limited to 'indra/newview/llappviewer.cpp') diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index 0778b123ea..180538eeb9 100644 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -123,6 +123,9 @@ namespace eSSE4_1_Features = 38, eSSE4_2_Features = 39, eSSE4a_Features = 40, + eAVX_Features = 41, + eAVX2_Features = 42, + eAVX512F_Features = 43, }; const char* cpu_feature_names[] = @@ -170,6 +173,9 @@ namespace "SSE4.1 Instructions", "SSE4.2 Instructions", "SSE4a Instructions", + "AVX Instructions", // 41 + "AVX2 Instructions", // 42 + "AVX-512F Instructions", // 43 }; std::string intel_CPUFamilyName(int composed_family) @@ -283,6 +289,21 @@ public: return hasExtension(cpu_feature_names[eSSE4a_Features]); } + bool hasAVX() const + { + return hasExtension(cpu_feature_names[eAVX_Features]); + } + + bool hasAVX2() const + { + return hasExtension(cpu_feature_names[eAVX2_Features]); + } + + bool hasAVX512F() const + { + return hasExtension(cpu_feature_names[eAVX512F_Features]); + } + bool hasAltivec() const { return hasExtension("Altivec"); @@ -572,6 +593,12 @@ private: setExtension(cpu_feature_names[eSSE4_2_Features]); } + // AVX: CPUID leaf 1, ECX bit 28, OSXSAVE + XCR0[1:2] enabled + if ((cpu_info[2] & 0x18000000) == 0x18000000 && ((_xgetbv(0) & 0x6) == 0x6)) + { + setExtension(cpu_feature_names[eAVX_Features]); + } + unsigned int feature_info = (unsigned int) cpu_info[3]; for(unsigned int index = 0, bit = 1; index < eSSE3_Features; ++index, bit <<= 1) { @@ -581,6 +608,27 @@ private: } } } + else if (i == 7) + { + // AVX2/AVX-512* require AVX to be usable (OSXSAVE + XCR0 state) + if (hasExtension(cpu_feature_names[eAVX_Features])) + { + int cpu_info7[4] = { -1 }; + __cpuidex(cpu_info7, 7, 0); + // AVX2: EBX bit 5 + if (cpu_info7[1] & 0x20) + { + setExtension(cpu_feature_names[eAVX2_Features]); + } + + // AVX-512F: EBX bit 16; ZMM state in XCR0 (bits 5-7) + const unsigned long long xcr0 = _xgetbv(0); + if ((cpu_info7[1] & 0x10000) && ((xcr0 & 0xE6) == 0xE6)) + { + setExtension(cpu_feature_names[eAVX512F_Features]); + } + } + } } // Calling __cpuid with 0x80000000 as the InfoType argument @@ -779,6 +827,29 @@ private: // Not supposed to happen? setExtension(cpu_feature_names[eSSE4a_Features]); } + if (cpu_features_str.find(" AVX1.0 ") != std::string::npos) + { + setExtension(cpu_feature_names[eAVX_Features]); + } + + // AVX2 and AVX-512F are reported in machdep.cpu.leaf7_features on macOS + char cpu_leaf7_features[1024]; + len = sizeof(cpu_leaf7_features); + memset(cpu_leaf7_features, 0, len); + sysctlbyname("machdep.cpu.leaf7_features", (void*)cpu_leaf7_features, &len, NULL, 0); + + std::string cpu_leaf7_str(cpu_leaf7_features); + cpu_leaf7_str = " " + cpu_leaf7_str + " "; + + if (cpu_leaf7_str.find(" AVX2 ") != std::string::npos) + { + setExtension(cpu_feature_names[eAVX2_Features]); + } + + if (cpu_leaf7_str.find(" AVX512F ") != std::string::npos) + { + setExtension(cpu_feature_names[eAVX512F_Features]); + } } }; @@ -915,6 +986,21 @@ private: setExtension(cpu_feature_names[eSSE4a_Features]); } + if (flags.find(" avx ") != std::string::npos) + { + setExtension(cpu_feature_names[eAVX_Features]); + } + + if (flags.find(" avx2 ") != std::string::npos) + { + setExtension(cpu_feature_names[eAVX2_Features]); + } + + if (flags.find(" avx512f ") != std::string::npos) + { + setExtension(cpu_feature_names[eAVX512F_Features]); + } + # endif // LL_X86 } @@ -979,6 +1065,9 @@ 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::hasAVX() const { return mImpl->hasAVX(); } +bool LLProcessorInfo::hasAVX2() const { return mImpl->hasAVX2(); } +bool LLProcessorInfo::hasAVX512F() const { return mImpl->hasAVX512F(); } 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 b955f7f55c..da93a531f4 100644 --- a/indra/llcommon/llprocessor.h +++ b/indra/llcommon/llprocessor.h @@ -46,6 +46,9 @@ public: bool hasSSE41() const; bool hasSSE42() const; bool hasSSE4a() const; + bool hasAVX() const; + bool hasAVX2() const; + bool hasAVX512F() 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 803bab393c..051f24fcb5 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -590,6 +590,9 @@ LLCPUInfo::LLCPUInfo() mHasSSE41 = proc.hasSSE41(); mHasSSE42 = proc.hasSSE42(); mHasSSE4a = proc.hasSSE4a(); + mHasAVX = proc.hasAVX(); + mHasAVX2 = proc.hasAVX2(); + mHasAVX512F = proc.hasAVX512F(); mHasAltivec = proc.hasAltivec(); mCPUMHz = (F64)proc.getCPUFrequency(); mFamily = proc.getCPUFamilyName(); @@ -631,6 +634,18 @@ LLCPUInfo::LLCPUInfo() { mSSEVersions.append("4a"); } + if (mHasAVX) + { + mSIMDVersions.append("AVX"); + } + if (mHasAVX2) + { + mSIMDVersions.append("AVX2"); + } + if (mHasAVX512F) + { + mSIMDVersions.append("AVX-512F"); + } } bool LLCPUInfo::hasAltivec() const @@ -673,6 +688,21 @@ bool LLCPUInfo::hasSSE4a() const return mHasSSE4a; } +bool LLCPUInfo::hasAVX() const +{ + return mHasAVX; +} + +bool LLCPUInfo::hasAVX2() const +{ + return mHasAVX2; +} + +bool LLCPUInfo::hasAVX512F() const +{ + return mHasAVX512F; +} + F64 LLCPUInfo::getMHz() const { return mCPUMHz; @@ -688,6 +718,11 @@ const LLSD& LLCPUInfo::getSSEVersions() const return mSSEVersions; } +const LLSD& LLCPUInfo::getSIMDVersions() const +{ + return mSIMDVersions; +} + void LLCPUInfo::stream(std::ostream& s) const { // gather machine information. diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h index 827b0dc048..e19f6922f3 100644 --- a/indra/llcommon/llsys.h +++ b/indra/llcommon/llsys.h @@ -81,6 +81,7 @@ public: std::string getCPUString() const; const LLSD& getSSEVersions() const; + const LLSD& getSIMDVersions() const; bool hasAltivec() const; bool hasSSE() const; @@ -90,6 +91,9 @@ public: bool hasSSE41() const; bool hasSSE42() const; bool hasSSE4a() const; + bool hasAVX() const; + bool hasAVX2() const; + bool hasAVX512F() const; F64 getMHz() const; // Family is "AMD Duron" or "Intel Pentium Pro" @@ -103,11 +107,15 @@ private: bool mHasSSE41; bool mHasSSE42; bool mHasSSE4a; + bool mHasAVX; + bool mHasAVX2; + bool mHasAVX512F; bool mHasAltivec; F64 mCPUMHz; std::string mFamily; std::string mCPUString; LLSD mSSEVersions; + LLSD mSIMDVersions; }; //============================================================================= diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index d3df15a642..67b84c324c 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -3890,8 +3890,12 @@ void LLAppViewer::writeSystemInfo() gDebugInfo["CPUInfo"]["CPUFamily"] = gSysCPU.getFamily(); gDebugInfo["CPUInfo"]["CPUMhz"] = (S32)gSysCPU.getMHz(); gDebugInfo["CPUInfo"]["CPUAltivec"] = gSysCPU.hasAltivec(); - gDebugInfo["CPUInfo"]["CPUSSE"] = gSysCPU.hasSSE(); - gDebugInfo["CPUInfo"]["CPUSSE2"] = gSysCPU.hasSSE2(); + gDebugInfo["CPUInfo"]["CPUSSE42"] = gSysCPU.hasSSE42(); + gDebugInfo["CPUInfo"]["CPUSSE4a"] = gSysCPU.hasSSE4a(); + gDebugInfo["CPUInfo"]["CPUAVX"] = gSysCPU.hasAVX(); + gDebugInfo["CPUInfo"]["CPUAVX2"] = gSysCPU.hasAVX2(); + gDebugInfo["CPUInfo"]["CPUAVX512F"] = gSysCPU.hasAVX512F(); + gDebugInfo["RAMInfo"]["Physical"] = LLSD::Integer(gSysMemory.getPhysicalMemoryKB().value()); gDebugInfo["RAMInfo"]["Allocated"] = LLSD::Integer(gMemoryAllocated.valueInUnits()); -- cgit v1.3