From dd500fb1fdafac0c93efe0e26a553faf150d53a9 Mon Sep 17 00:00:00 2001 From: "Mark Palange (Mani)" Date: Thu, 7 Jan 2010 16:15:51 -0800 Subject: EXT-3780 Rewrote windows processor detection to support cpuid brandstring, and x64. Refactored the CProcessor class into LLProcessorInfo. Reviewed by brad --- indra/llcommon/llprocessor.h | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'indra/llcommon/llprocessor.h') diff --git a/indra/llcommon/llprocessor.h b/indra/llcommon/llprocessor.h index 746d007a7f..1cea6245a3 100644 --- a/indra/llcommon/llprocessor.h +++ b/indra/llcommon/llprocessor.h @@ -30,14 +30,30 @@ * $/LicenseInfo$ */ -// Author: Benjamin Jurke -// File history: 27.02.2002 File created. -/////////////////////////////////////////// - #ifndef LLPROCESSOR_H #define LLPROCESSOR_H +class LLProcessorInfo +{ +public: + LLProcessorInfo(); + ~LLProcessorInfo(); + + F64 getCPUFrequency() const; + bool hasSSE() const; + bool hasSSE2() const; + bool hasAltivec() const; + std::string getCPUFamilyName() const; + std::string getCPUBrandName() const; + std::string getCPUFeatureDescription() const; +}; + +# if 0 +// Author: Benjamin Jurke +// File history: 27.02.2002 File created. +/////////////////////////////////////////// + // Options: /////////// #if LL_WINDOWS @@ -166,7 +182,7 @@ public: // Private vars: //////////////// -public: +private: F64 uqwFrequency; char strCPUName[128]; /* Flawfinder: ignore */ ProcessorInfo CPUInfo; @@ -192,5 +208,6 @@ public: bool WriteInfoTextFile(const std::string& strFilename); }; +#endif // 0 -#endif +#endif // LLPROCESSOR_H -- cgit v1.3 From 6abecf1228010d83c2df8d14057950fb51e37320 Mon Sep 17 00:00:00 2001 From: palange Date: Mon, 1 Feb 2010 11:23:30 -0800 Subject: pushing to private repo to move to windows development. --- indra/llcommon/llprocessor.cpp | 544 +++++++++++++++++++++++++++++------------ indra/llcommon/llprocessor.h | 3 + indra/newview/llappviewer.cpp | 4 - 3 files changed, 388 insertions(+), 163 deletions(-) (limited to 'indra/llcommon/llprocessor.h') diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index 8ac0cdf4e3..09a7004913 100644 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -33,6 +33,8 @@ #include "linden_common.h" #include "llprocessor.h" +#include "llerror.h" + //#include #if LL_WINDOWS @@ -42,28 +44,86 @@ # include #endif -#include #include "llsd.h" -#if LL_MSVC && _M_X64 -# define LL_X86_64 1 -# define LL_X86 1 -#elif LL_MSVC && _M_IX86 -# define LL_X86 1 -#elif LL_GNUC && ( defined(__amd64__) || defined(__x86_64__) ) -# define LL_X86_64 1 -# define LL_X86 1 -#elif LL_GNUC && ( defined(__i386__) ) -# define LL_X86 1 -#elif LL_GNUC && ( defined(__powerpc__) || defined(__ppc__) ) -# define LL_PPC 1 -#endif - -class LLProcessorInfoImpl; // foward declaration for the gImpl; +class LLProcessorInfoImpl; // foward declaration for the mImpl; namespace { - static const char* cpu_feature_names[] = + enum cpu_info + { + eBrandName = 0, + eFrequency, + eVendor, + eStepping, + eFamily, + eExtendedFamily, + eModel, + eExtendedModel, + eType, + eBrandID, + eFamilyName + }; + + + const char* cpu_info_names[] = + { + "Processor Name", + "Frequency", + "Vendor", + "Stepping", + "Family", + "Extended Family", + "Model", + "Extended Model", + "Type", + "Brand ID", + "Family Name" + }; + + enum cpu_config + { + eMaxID, + eMaxExtID, + eCLFLUSHCacheLineSize, + eAPICPhysicalID, + eCacheLineSize, + eL2Associativity, + eCacheSizeK, + eFeatureBits, + eExtFeatureBits + }; + + const char* cpu_config_names[] = + { + "Max Supported CPUID level", + "Max Supported Ext. CPUID level", + "CLFLUSH cache line size", + "APIC Physical ID", + "Cache Line Size", + "L2 Associativity", + "Cache Size", + "Feature Bits", + "Ext. Feature Bits" + }; + + + + // *NOTE:Mani - this contains the elements we reference directly and extensions beyond the first 32. + // The rest of the names are referenced by bit maks returned from cpuid. + enum cpu_features + { + eSSE_Ext=25, + eSSE2_Ext=26, + + eSSE3_Features=32, + eMONTIOR_MWAIT=33, + eCPLDebugStore=34, + eThermalMonitor2=35, + eAltivec=36 + }; + + const char* cpu_feature_names[] = { "x87 FPU On Chip", "Virtual-8086 Mode Enhancement", @@ -96,39 +156,70 @@ namespace "Hyper-threading Technology", "Thermal Monitor", "Unknown4", - "Pend. Brk. EN.", // End of FeatureInfo bits + "Pend. Brk. EN.", // 31 End of FeatureInfo bits "SSE3 New Instructions", // 32 "MONITOR/MWAIT", "CPL Qualified Debug Store", - "Thermal Monitor 2" - }; + "Thermal Monitor 2", - enum cpu_features - { - eSSE_Ext=25, - eSSE2_Ext=26, - eSSE3_Features=32, - eMONTIOR_MWAIT=33, - eCPLDebugStore=34, - eThermalMonitor2=35 + "Altivec" }; - // Pointer to the active impl. - boost::scoped_ptr gImpl; -} + std::string compute_CPUFamilyName(const char* cpu_vendor, int family, int ext_family) + { + const char* intel_string = "GenuineIntel"; + const char* amd_string = "AuthenticAMD"; + if(!strncmp(cpu_vendor, intel_string, strlen(intel_string))) + { + U32 composed_family = family + ext_family; + switch(composed_family) + { + case 3: return "Intel i386"; + case 4: return "Intel i486"; + case 5: return "Intel Pentium"; + case 6: return "Intel Pentium Pro/2/3, Core"; + case 7: return "Intel Itanium (IA-64)"; + case 0xF: return "Intel Pentium 4"; + case 0x10: return "Intel Itanium 2 (IA-64)"; + default: return "Unknown"; + } + } + else if(!strncmp(cpu_vendor, amd_string, strlen(amd_string))) + { + U32 composed_family = (family == 0xF) + ? family + ext_family + : family; + switch(composed_family) + { + case 4: return "AMD 80486/5x86"; + case 5: return "AMD K5/K6"; + case 6: return "AMD K7"; + case 0xF: return "AMD K8"; + case 0x10: return "AMD K8L"; + default: return "Unknown"; + } + } + return "Unknown"; + } +} // end unnamed namespace // The base class for implementations. // Each platform should override this class. class LLProcessorInfoImpl { public: - LLProcessorInfoImpl() {} + LLProcessorInfoImpl() + { + mProcessorInfo["info"] = LLSD::emptyMap(); + mProcessorInfo["config"] = LLSD::emptyMap(); + mProcessorInfo["extension"] = LLSD::emptyMap(); + } virtual ~LLProcessorInfoImpl() {} F64 getCPUFrequency() const { - return getInfo("Frequency", 0).asReal(); + return getInfo(eFrequency, 0).asReal(); } bool hasSSE() const @@ -146,8 +237,9 @@ public: return hasExtension("Altivec"); } - std::string getCPUFamilyName() const { return getInfo("FamilyName", "Unknown").asString(); } - std::string getCPUBrandName() const { return getInfo("BrandName", "Unknown").asString(); } + std::string getCPUFamilyName() const { return getInfo(eFamilyName, "Unknown").asString(); } + std::string getCPUBrandName() const { return getInfo(eBrandName, "Unknown").asString(); } + std::string getCPUFeatureDescription() const { std::ostringstream out; @@ -156,28 +248,29 @@ public: out << "//////////////////////////" << std::endl; out << "Processor Name: " << getCPUBrandName() << std::endl; out << "Frequency: " << getCPUFrequency() / (F64)1000000 << " MHz" << std::endl; - out << "Vendor: " << getInfo("Vendor", "Unknown").asString() << std::endl; - out << "Family: " << getCPUFamilyName() << " (" << getInfo("Family", 0) << ")" << std::endl; - out << "Extended family: " << getInfo("ExtendedFamily", 0) << std::endl; - out << "Model: " << getInfo("Model", 0) << std::endl; - out << "Extended model: " << getInfo("ExtendedModel", 0) << std::endl; - out << "Type: " << getInfo("Type", 0) << std::endl; - out << "Brand ID: " << getInfo("BrandID", 0) << std::endl; + out << "Vendor: " << getInfo(eVendor, "Unknown").asString() << std::endl; + out << "Family: " << getCPUFamilyName() << " (" << getInfo(eFamily, 0) << ")" << std::endl; + out << "Extended family: " << getInfo(eExtendedFamily, 0) << std::endl; + out << "Model: " << getInfo(eModel, 0) << std::endl; + out << "Extended model: " << getInfo(eExtendedModel, 0) << std::endl; + out << "Type: " << getInfo(eType, 0) << std::endl; + out << "Brand ID: " << getInfo(eBrandID, 0) << std::endl; out << std::endl; out << "// CPU Configuration" << std::endl; out << "//////////////////////////" << std::endl; - out << "Max Supported CPUID level = " << getConfig("MaxID", 0) << std::endl; - out << "Max Supported Ext. CPUID level = " << std::hex << getConfig("MaxExtID", 0) << std::dec << std::endl; - out << "CLFLUSH cache line size = " << getConfig("CLFLUSHCacheLineSize", 0) << std::endl; - out << "APIC Physical ID = " << getConfig("APICPhysicalID", 0) << std::endl; - out << "Cache Line Size = " << getConfig("CacheLineSize", 0) << std::endl; - out << "L2 Associativity = " << getConfig("L2Associativity", 0) << std::endl; - out << "Cache Size = " << getConfig("CacheSizeK", 0) << "K" << std::endl; + + // Iterate through the dictionary of configuration options. + LLSD configs = mProcessorInfo["config"]; + for(LLSD::map_const_iterator cfgItr = configs.beginMap(); cfgItr != configs.endMap(); ++cfgItr) + { + out << cfgItr->first << " = " << cfgItr->second << std::endl; + } out << std::endl; + out << "// CPU Extensions" << std::endl; out << "//////////////////////////" << std::endl; - for(LLSD::map_const_iterator itr = mProcessorInfo.beginMap(); itr != mProcessorInfo.endMap(); ++itr) + for(LLSD::map_const_iterator itr = mProcessorInfo["extension"].beginMap(); itr != mProcessorInfo["extension"].endMap(); ++itr) { out << " " << itr->first << std::endl; } @@ -185,28 +278,46 @@ public: } protected: - void setInfo(const std::string& name, const LLSD& value) { mProcessorInfo["info"][name]=value; } - void setConfig(const std::string& name, const LLSD& value) { mProcessorInfo["config"][name]=value; } + void setInfo(cpu_info info_type, const LLSD& value) + { + setInfo(cpu_info_names[info_type], value); + } + LLSD getInfo(cpu_info info_type, const LLSD& defaultVal) const + { + return getInfo(cpu_info_names[info_type], defaultVal); + } + + void setConfig(cpu_config config_type, const LLSD& value) + { + setConfig(cpu_config_names[config_type], value); + } + LLSD getConfig(cpu_config config_type, const LLSD& defaultVal) const + { + return getConfig(cpu_config_names[config_type], defaultVal); + } + void setExtension(const std::string& name) { mProcessorInfo["extension"][name] = "true"; } + bool hasExtension(const std::string& name) const + { + return mProcessorInfo["extension"].has(name); + } +private: + void setInfo(const std::string& name, const LLSD& value) { mProcessorInfo["info"][name]=value; } LLSD getInfo(const std::string& name, const LLSD& defaultVal) const { LLSD r = mProcessorInfo["info"].get(name); return r.isDefined() ? r : defaultVal; } - + void setConfig(const std::string& name, const LLSD& value) { mProcessorInfo["config"][name]=value; } LLSD getConfig(const std::string& name, const LLSD& defaultVal) const { LLSD r = mProcessorInfo["config"].get(name); return r.isDefined() ? r : defaultVal; } - bool hasExtension(const std::string& name) const - { - return mProcessorInfo["extension"].has(name); - } - private: + LLSD mProcessorInfo; }; @@ -247,7 +358,7 @@ static F64 calculate_cpu_frequency(U32 measure_msecs) // After that we declare some vars and check the frequency of the high // resolution timer for the measure process. - // If there's no high-res timer, we exit. + // If there"s no high-res timer, we exit. unsigned __int64 starttime, endtime, timedif, freq, start, end, dif; if (!QueryPerformanceFrequency((LARGE_INTEGER *) &freq)) { @@ -271,8 +382,8 @@ static F64 calculate_cpu_frequency(U32 measure_msecs) //// Now we call a CPUID to ensure, that all other prior called functions are //// completed now (serialization) //__asm cpuid - int cpu_info[4] = {-1}; - __cpuid(cpu_info, 0); + int cpu_info[4] = {-1}; + __cpuid(cpu_info, 0); // We ask the high-res timer for the start time QueryPerformanceCounter((LARGE_INTEGER *) &starttime); @@ -331,44 +442,77 @@ private: int cpu_info[4] = {-1}; __cpuid(cpu_info, 0); unsigned int ids = (unsigned int)cpu_info[0]; - setInfo("MaxIDs", ids); + setInfo(eMaxID, ids); char cpu_vendor[0x20]; memset(cpu_vendor, 0, sizeof(cpu_vendor)); *((int*)cpu_vendor) = cpu_info[1]; *((int*)(cpu_vendor+4)) = cpu_info[3]; *((int*)(cpu_vendor+8)) = cpu_info[2]; + setInfo(eVendor, cpu_vendor); // Get the information associated with each valid Id - for(unsigned int i=0; i<=mIds; ++i) + for(unsigned int i=0; i<=ids; ++i) { __cpuid(cpu_info, i); // Interpret CPU feature information. if (i == 1) { - mSteppingID = cpu_info[0] & 0xf; - mModel = (cpu_info[0] >> 4) & 0xf; - mFamily = (cpu_info[0] >> 8) & 0xf; - mProcessorType = (cpu_info[0] >> 12) & 0x3; - mExtendedModel = (cpu_info[0] >> 16) & 0xf; - mExtendedFamily = (cpu_info[0] >> 20) & 0xff; - mBrandIndex = cpu_info[1] & 0xff; - mCLFLUSHCacheLineSize = ((cpu_info[1] >> 8) & 0xff) * 8; - mAPICPhysicalID = (cpu_info[1] >> 24) & 0xff; - mSSE3NewInstructions = (cpu_info[2] & 0x1) || false; - mMONITOR_MWAIT = (cpu_info[2] & 0x8) || false; - mCPLQualifiedDebugStore = (cpu_info[2] & 0x10) || false; - mThermalMonitor2 = (cpu_info[2] & 0x100) || false; - mFeatureInfo = cpu_info[3]; + setInfo(eStepping, cpu_info[0] & 0xf); + setInfo(eModel, (cpu_info[0] >> 4) & 0xf); + int family = (cpu_info[0] >> 8) & 0xf; + setInfo(eFamily, family); + setInfo(eType, (cpu_info[0] >> 12) & 0x3); + setInfo(eExtendedModel, (cpu_info[0] >> 16) & 0xf); + int ext_family = (cpu_info[0] >> 20) & 0xff; + setInfo(eExtendedFamily, ext_family); + setInfo(eBrandIndex, cpu_info[1] & 0xff); + + setInfo(eFamilyName, compute_CPUFamilyName(family, ext_family)); + + setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8); + setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff); + + if(cpu_info[2] & 0x1) + { + setExtension(cpu_feature_names[eSSE3_Features]); + } + + if(cpu_info[2] & 0x8) + { + setExtension(cpu_feature_names[eMONTIOR_MWAIT]); + } + + if(cpu_info[2] & 0x10) || false; + { + setExtension(cpu_feature_names[eCPLDebugStore]); + } + + if(cpu_info[2] & 0x100) + { + setExtension(cpu_feature_names[eThermalMonitor2]); + } + + unsigned int feature_info = (unsigned int) cpu_info[3]; + for(unsigned int index = 0, bit = 1; index < eSSE3_Features; ++index, bit <<= 1) + { + if(feature_info & bit) + { + setExtension(cpu_feature_names[index]); + } + } } } // Calling __cpuid with 0x80000000 as the InfoType argument // gets the number of valid extended IDs. __cpuid(cpu_info, 0x80000000); - mExtIds = cpu_info[0]; - memset(mCPUBrandString, 0, sizeof(mCPUBrandString)); + unsigned int ext_ids = cpu_info[0]; + setConfig(eMaxExtID, 0); + + char cpu_brand_string[0x40]; + memset(cpu_brand_string, 0, sizeof(cpu_brand_string)); // Get the information associated with each extended ID. for(unsigned int i=0x80000000; i<=mExtIds; ++i) @@ -377,67 +521,35 @@ private: // Interpret CPU brand string and cache information. if (i == 0x80000002) - memcpy(mCPUBrandString, cpu_info, sizeof(cpu_info)); + memcpy(cpu_brand_string, cpu_info, sizeof(cpu_info)); else if (i == 0x80000003) - memcpy(mCPUBrandString + 16, cpu_info, sizeof(cpu_info)); + memcpy(cpu_brand_string + 16, cpu_info, sizeof(cpu_info)); else if (i == 0x80000004) - memcpy(mCPUBrandString + 32, cpu_info, sizeof(cpu_info)); - else if (i == 0x80000006) - { - mCacheLineSize = cpu_info[2] & 0xff; - mL2Associativity = (cpu_info[2] >> 12) & 0xf; - mCacheSizeK = (cpu_info[2] >> 16) & 0xffff; - } - } - } - - std::string computeCPUFamilyName() const - { - const char* intel_string = "GenuineIntel"; - const char* amd_string = "AuthenticAMD"; - if(!strncmp(mCPUString, intel_string, strlen(intel_string))) - { - U32 composed_family = mFamily + mExtendedFamily; - switch(composed_family) { - case 3: return "Intel i386"; - case 4: return "Intel i486"; - case 5: return "Intel Pentium"; - case 6: return "Intel Pentium Pro/2/3, Core"; - case 7: return "Intel Itanium (IA-64)"; - case 0xF: return "Intel Pentium 4"; - case 0x10: return "Intel Itanium 2 (IA-64)"; - default: return "Unknown"; + memcpy(cpu_brand_string + 32, cpu_info, sizeof(cpu_info)); + setInfo(eBrandName, cpu_brand_string); } - } - else if(!strncmp(mCPUString, amd_string, strlen(amd_string))) - { - U32 composed_family = (mFamily == 0xF) - ? mFamily + mExtendedFamily - : mFamily; - switch(composed_family) + else if (i == 0x80000006) { - case 4: return "AMD 80486/5x86"; - case 5: return "AMD K5/K6"; - case 6: return "AMD K7"; - case 0xF: return "AMD K8"; - case 0x10: return "AMD K8L"; - default: return "Unknown"; + setConfig(eCacheLineSize, cpu_info[2] & 0xff); + setConfig(eL2Associativity, (cpu_info[2] >> 12) & 0xf); + setConfig(eCacheSizeK, (cpu_info[2] >> 16) & 0xffff); } } - return "Unknown"; } - }; #elif LL_DARWIN -class LLProcessorInfoDarwinImpl +#include +#include + +class LLProcessorInfoDarwinImpl : public LLProcessorInfoImpl { public: LLProcessorInfoDarwinImpl() { - + getCPUIDInfo(); } virtual ~LLProcessorInfoDarwinImpl() {} @@ -449,22 +561,136 @@ public: virtual std::string getCPUFamilyName() const { return "Unknown"; } virtual std::string getCPUBrandName() const { return "Unknown"; } virtual std::string getCPUFeatureDescription() const { return "Unknown"; } -}; -#endif // LL_MSVC +private: + int getSysctlInt(const char* name) + { + int result = 0; + size_t len = sizeof(int); + int error = sysctlbyname(name, (void*)&result, &len, NULL, 0); + return error == -1 ? 0 : result; + } + + uint64_t getSysctlInt64(const char* name) + { + uint64_t value = 0; + size_t size = sizeof(value); + int result = sysctlbyname(name, (void*)&value, &size, NULL, 0); + if ( result == 0 ) + { + if ( size == sizeof( uint64_t ) ) + ; + else if ( size == sizeof( uint32_t ) ) + value = (uint64_t)(( uint32_t *)&value); + else if ( size == sizeof( uint16_t ) ) + value = (uint64_t)(( uint16_t *)&value); + else if ( size == sizeof( uint8_t ) ) + value = (uint64_t)(( uint8_t *)&value); + else + { + LL_ERRS("Unknown type returned from sysctl!") << LL_ENDL; + } + } + + return result == -1 ? 0 : value; + } + + void getCPUIDInfo() + { + size_t len = 0; + + char cpu_brand_string[0x40]; + len = sizeof(cpu_brand_string); + memset(cpu_brand_string, 0, len); + sysctlbyname("machdep.cpu.brand_string", (void*)cpu_brand_string, &len, NULL, 0); + cpu_brand_string[0x3f] = 0; + setInfo(eBrandName, cpu_brand_string); + + char cpu_vendor[0x20]; + len = sizeof(cpu_vendor); + memset(cpu_vendor, 0, len); + sysctlbyname("machdep.cpu.vendor", (void*)cpu_vendor, &len, NULL, 0); + cpu_vendor[0x1f] = 0; + setInfo(eVendor, cpu_vendor); + + setInfo(eStepping, getSysctlInt("machdep.cpu.stepping")); + setInfo(eModel, getSysctlInt("machdep.cpu.model")); + int family = getSysctlInt("machdep.cpu.family"); + int ext_family = getSysctlInt("machdep.cpu.extfamily"); + setInfo(eFamily, family); + setInfo(eExtendedFamily, ext_family); + setInfo(eFamilyName, compute_CPUFamilyName(cpu_vendor, family, ext_family)); + setInfo(eExtendedModel, getSysctlInt("machdep.cpu.extmodel")); + setInfo(eBrandID, getSysctlInt("machdep.cpu.brand")); + setInfo(eType, 0); // ? where to find this? + + //setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8); + //setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff); + setConfig(eCacheLineSize, getSysctlInt("machdep.cpu.cache.linesize")); + setConfig(eL2Associativity, getSysctlInt("machdep.cpu.cache.L2_associativity")); + setConfig(eCacheSizeK, getSysctlInt("machdep.cpu.cache.size")); + + uint64_t feature_info = getSysctlInt64("machdep.cpu.feature_bits"); + S32 *feature_infos = (S32*)(&feature_info); + + setConfig(eFeatureBits, feature_infos[0]); + + for(unsigned int index = 0, bit = 1; index < eSSE3_Features; ++index, bit <<= 1) + { + if(feature_info & bit) + { + setExtension(cpu_feature_names[index]); + } + } + + // *NOTE:Mani - I didn't find any docs that assure me that machdep.cpu.feature_bits will always be + // The feature bits I think it is. Here's a test: +#ifndef LL_RELEASE_FOR_DOWNLOAD + #if defined(__i386__) && defined(__PIC__) + /* %ebx may be the PIC register. */ + #define __cpuid(level, a, b, c, d) \ + __asm__ ("xchgl\t%%ebx, %1\n\t" \ + "cpuid\n\t" \ + "xchgl\t%%ebx, %1\n\t" \ + : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ + : "0" (level)) + #else + #define __cpuid(level, a, b, c, d) \ + __asm__ ("cpuid\n\t" \ + : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ + : "0" (level)) + #endif + + unsigned int eax, ebx, ecx, edx; + __cpuid(0x1, eax, ebx, ecx, edx); + if(feature_infos[0] != (S32)edx) + { + llerrs << "machdep.cpu.feature_bits doesn't match expected cpuid result!" << llendl; + } +#endif // LL_RELEASE_FOR_DOWNLOAD + + uint64_t ext_feature_info = getSysctlInt64("machdep.cpu.extfeature_bits"); + S32 *ext_feature_infos = (S32*)(&ext_feature_info); + setConfig(eExtFeatureBits, ext_feature_infos[0]); + } +}; +#endif // LL_MSVC -// Interface implementation -LLProcessorInfo::LLProcessorInfo() +////////////////////////////////////////////////////// +// Interface definition +LLProcessorInfo::LLProcessorInfo() : mImpl(NULL) { // *NOTE:Mani - not thread safe. - if(gImpl == NULL) + if(!mImpl) { #ifdef LL_MSVC - gImpl.reset(new LLProcessorInfoWindowsImpl); + static LLProcessorInfoWindowsImpl the_impl; + mImpl = &the_impl; #elif LL_DARWIN - gImpl.reset(new LLProcessorInfoDarwinImpl); + static LLProcessorInfoDarwinImpl the_impl; + mImpl = &the_impl; #else #error "Unimplemented" #endif // LL_MSVC @@ -472,13 +698,13 @@ LLProcessorInfo::LLProcessorInfo() } LLProcessorInfo::~LLProcessorInfo() {} -F64 LLProcessorInfo::getCPUFrequency() const { return gImpl->getCPUFrequency(); } -bool LLProcessorInfo::hasSSE() const { return gImpl->hasSSE(); } -bool LLProcessorInfo::hasSSE2() const { return gImpl->hasSSE2(); } -bool LLProcessorInfo::hasAltivec() const { return gImpl->hasAltivec(); } -std::string LLProcessorInfo::getCPUFamilyName() const { return gImpl->getCPUFamilyName(); } -std::string LLProcessorInfo::getCPUBrandName() const { return gImpl->getCPUBrandName(); } -std::string LLProcessorInfo::getCPUFeatureDescription() const { return gImpl->getCPUFeatureDescription(); } +F64 LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); } +bool LLProcessorInfo::hasSSE() const { return mImpl->hasSSE(); } +bool LLProcessorInfo::hasSSE2() const { return mImpl->hasSSE2(); } +bool LLProcessorInfo::hasAltivec() const { return mImpl->hasAltivec(); } +std::string LLProcessorInfo::getCPUFamilyName() const { return mImpl->getCPUFamilyName(); } +std::string LLProcessorInfo::getCPUBrandName() const { return mImpl->getCPUBrandName(); } +std::string LLProcessorInfo::getCPUFeatureDescription() const { return mImpl->getCPUFeatureDescription(); } #if 0 // Filename: Processor.cpp @@ -492,14 +718,14 @@ std::string LLProcessorInfo::getCPUFeatureDescription() const { return gImpl->ge // - Optional include of the windows.h header which is // still need for CProcessor::GetCPUFrequency. // 06.03.2002 - My birthday (18th :-)) -// - Replaced the '\r\n' line endings in function -// CProcessor::cpu_infoToText by '\n' +// - Replaced the "\r\n" line endings in function +// CProcessor::cpu_infoToText by "\n" // - Replaced unsigned __int64 by signed __int64 for // solving some compiler conversion problems // - Fixed a bug at family=6, model=6 (Celeron -> P2) ////////////////////////////////////////////////////////////////////////////////// -#include "linden_common.h" + #include "processor.h" @@ -571,7 +797,7 @@ F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) return 0; #else // If there are invalid measure time parameters, zero msecs for example, - // we've to exit the function + // we"ve to exit the function if (uiMeasureMSecs < 1) { // If theres already a measured frequency available, we return it @@ -601,7 +827,7 @@ F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) // After that we declare some vars and check the frequency of the high // resolution timer for the measure process. - // If there's no high-res timer, we exit. + // If there"s no high-res timer, we exit. __int64 starttime, endtime, timedif, freq, start, end, dif; if (!QueryPerformanceFrequency((LARGE_INTEGER *) &freq)) return 0; @@ -736,7 +962,7 @@ bool CProcessor::AnalyzeIntelProcessor() } // And copy it to the brand id string strncpy(cpu_info.strBrandID, tmp,sizeof(cpu_info.strBrandID)-1); - cpu_info.strBrandID[sizeof(cpu_info.strBrandID)-1]='\0'; + cpu_info.strBrandID[sizeof(cpu_info.strBrandID)-1]="\0"; } else { @@ -892,7 +1118,7 @@ bool CProcessor::AnalyzeIntelProcessor() strcpy(cpu_info.strModel, "Intel Pentium MMX (P55C)"); /*Flawfinder: ignore*/ strncat(strCPUName, "Intel Pentium MMX (P55C core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ break; - case 7: // Model = 7: Pentium processor model (don't know difference to Model=2) + case 7: // Model = 7: Pentium processor model (don"t know difference to Model=2) strcpy(cpu_info.strModel, "Intel Pentium (P54C)"); /*Flawfinder: ignore*/ strncat(strCPUName, "Intel Pentium (P54C core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ break; @@ -1095,7 +1321,7 @@ bool CProcessor::AnalyzeIntelProcessor() } else { - // If there's no serial number support we just put "No serial number" + // If there"s no serial number support we just put "No serial number" snprintf( /* Flawfinder: ignore */ cpu_info.strProcessorSerial, sizeof(cpu_info.strProcessorSerial), @@ -1175,7 +1401,7 @@ bool CProcessor::AnalyzeAMDProcessor() } // And copy it to the brand id string strncpy(cpu_info.strBrandID, tmp,sizeof(cpu_info.strBrandID)-1); - cpu_info.strBrandID[sizeof(cpu_info.strBrandID)-1]='\0'; + cpu_info.strBrandID[sizeof(cpu_info.strBrandID)-1]="\0"; } else { @@ -1380,7 +1606,7 @@ bool CProcessor::AnalyzeAMDProcessor() // 0x80000006 if (cpu_info.MaxSupportedExtendedLevel >= 0x80000006) { - // If it's present, we read it out + // If it"s present, we read it out __asm { mov eax, 0x80000005 @@ -1458,8 +1684,8 @@ bool CProcessor::AnalyzeAMDProcessor() cpu_info._L1.Instruction.uiLineSize = edxreg & 0xFF; } - // Note: I'm not absolutely sure that the L1 page size code (the - // 'if/else if/else if' structs above) really detects the real page + // Note: I"m not absolutely sure that the L1 page size code (the + // "if/else if/else if" structs above) really detects the real page // size for the TLB. Somebody should check it.... // Now we read the ext. CPUID level 0x80000006 @@ -1591,8 +1817,8 @@ bool CProcessor::CheckCPUIDPresence() #if LL_WINDOWS unsigned long BitChanged; - // We've to check if we can toggle the flag register bit 21 - // If we can't the processor does not support the CPUID command + // We"ve to check if we can toggle the flag register bit 21 + // If we can"t the processor does not support the CPUID command __asm { pushfd @@ -1620,7 +1846,7 @@ bool CProcessor::CheckCPUIDPresence() ////////////////////////////////////////////////////////////////////////////////// void CProcessor::DecodeProcessorConfiguration(unsigned int cfg) { - // First we ensure that there's only one single byte + // First we ensure that there"s only one single byte cfg &= 0xFF; // Then we do a big switch @@ -1961,7 +2187,7 @@ void CProcessor::GetStandardProcessorConfiguration() mov ecxreg, ecx mov edxreg, edx } - // We have to repeat this reading for 'num' times + // We have to repeat this reading for "num" times num = eaxreg & 0xFF; // Then we call the big decode switch function @@ -2193,7 +2419,7 @@ const ProcessorInfo *CProcessor::Getcpu_info() { // In Solaris the CPU info is in the kstats // try "psrinfo" or "kstat cpu_info" to see all - // that's available + // that"s available int ncpus=0, i; kstat_ctl_t *kc; kstat_t *ks; @@ -2241,7 +2467,7 @@ const ProcessorInfo *CProcessor::Getcpu_info() strncat(cpu_info.strFamily, (char *)KSTAT_NAMED_STR_PTR(ksi), sizeof(cpu_info.strFamily)-strlen(cpu_info.strFamily)-1); strncpy(cpu_info.strBrandID, strCPUName,sizeof(cpu_info.strBrandID)-1); - cpu_info.strBrandID[sizeof(cpu_info.strBrandID)-1]='\0'; + cpu_info.strBrandID[sizeof(cpu_info.strBrandID)-1]="\0"; // DEBUG llinfos << "CPU brand: " << strCPUName << llendl; continue; } @@ -2274,7 +2500,7 @@ const ProcessorInfo *CProcessor::Getcpu_info() // DEBUG llinfo << "The system has " << ncpus << " CPUs with a clock rate of " << uqwFrequency << "MHz." << llendl; -#if defined (__i386) // we really don't care about the CPU extensions on SPARC but on x86... +#if defined (__i386) // we really don"t care about the CPU extensions on SPARC but on x86... // Now get cpu extensions @@ -2585,7 +2811,7 @@ const ProcessorInfo *CProcessor::Getcpu_info() // Terse CPU info uses this string... strncpy(cpu_info.strBrandID, strCPUName,sizeof(cpu_info.strBrandID)-1); /* Flawfinder: ignore */ - cpu_info.strBrandID[sizeof(cpu_info.strBrandID)-1]='\0'; + cpu_info.strBrandID[sizeof(cpu_info.strBrandID)-1]="\0"; // Fun cache config stuff... @@ -2682,7 +2908,7 @@ bool CProcessor::cpu_infoToText(char *strBuffer, unsigned int uiMaxLen) { COPYADD("Processor Serial: Disabled\n"); } -#if !LL_SOLARIS // NOTE: Why bother printing all this when it's irrelavent +#if !LL_SOLARIS // NOTE: Why bother printing all this when it"s irrelavent COPYADD("\n\n// CPU Configuration\n////////////////////\n"); FORMATADD("L1 instruction cache: %s\n", cpu_info._L1.Instruction.strCache); diff --git a/indra/llcommon/llprocessor.h b/indra/llcommon/llprocessor.h index 1cea6245a3..e33af77143 100644 --- a/indra/llcommon/llprocessor.h +++ b/indra/llcommon/llprocessor.h @@ -33,6 +33,7 @@ #ifndef LLPROCESSOR_H #define LLPROCESSOR_H +class LLProcessorInfoImpl; class LLProcessorInfo { @@ -47,6 +48,8 @@ public: std::string getCPUFamilyName() const; std::string getCPUBrandName() const; std::string getCPUFeatureDescription() const; +private: + LLProcessorInfoImpl* mImpl; }; # if 0 diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index becc30832d..21d908035f 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -324,10 +324,6 @@ const char *VFS_INDEX_FILE_BASE = "index.db2.x."; static std::string gWindowTitle; -std::string gLoginPage; -std::vector gLoginURIs; -static std::string gHelperURI; - LLAppViewer::LLUpdaterInfo *LLAppViewer::sUpdaterInfo = NULL ; void idle_afk_check() -- cgit v1.3 From 0db04cbb67d5420f98cc2090fdcca6bba948527b Mon Sep 17 00:00:00 2001 From: "Mark Palange (Mani)" Date: Tue, 11 May 2010 16:27:50 -0700 Subject: EXT-3780 WIP Adding newline to linux getCPUFeatureDesc output --- indra/llcommon/llprocessor.cpp | 36 ++++++++- indra/llcommon/llprocessor.h | 161 ----------------------------------------- indra/llcommon/llsys.cpp | 74 +------------------ 3 files changed, 36 insertions(+), 235 deletions(-) (limited to 'indra/llcommon/llprocessor.h') diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index 463b07a7a5..a55765e329 100644 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -240,7 +240,9 @@ public: std::string getCPUFamilyName() const { return getInfo(eFamilyName, "Unknown").asString(); } std::string getCPUBrandName() const { return getInfo(eBrandName, "Unknown").asString(); } - std::string getCPUFeatureDescription() const + // This is virtual to support a different linux format. + // *NOTE:Mani - I didn't want to screw up server use of this data... + virtual std::string getCPUFeatureDescription() const { std::ostringstream out; out << std::endl << std::endl; @@ -671,6 +673,7 @@ private: }; #elif LL_LINUX +const char CPUINFO_FILE[] = "/proc/cpuinfo"; class LLProcessorInfoLinuxImpl : public LLProcessorInfoImpl { @@ -820,6 +823,33 @@ private: # endif // LL_X86 } + + std::string getCPUFeatureDescription() const + { + std::ostringstream s; + + // *NOTE:Mani - This is for linux only. + LLFILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "rb"); + if(cpuinfo) + { + char line[MAX_STRING]; + memset(line, 0, MAX_STRING); + while(fgets(line, MAX_STRING, cpuinfo)) + { + line[strlen(line)-1] = ' '; + s << line; + s << std::endl; + } + fclose(cpuinfo); + s << std::endl; + } + else + { + s << "Unable to collect processor information" << std::endl; + } + return s.str(); + } + }; @@ -839,11 +869,13 @@ LLProcessorInfo::LLProcessorInfo() : mImpl(NULL) static LLProcessorInfoDarwinImpl the_impl; mImpl = &the_impl; #else - #error "Unimplemented" + static LLProcessorInfoLinuxImpl the_impl; + mImpl = &the_impl; #endif // LL_MSVC } } + LLProcessorInfo::~LLProcessorInfo() {} F64 LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); } bool LLProcessorInfo::hasSSE() const { return mImpl->hasSSE(); } diff --git a/indra/llcommon/llprocessor.h b/indra/llcommon/llprocessor.h index e33af77143..8350155050 100644 --- a/indra/llcommon/llprocessor.h +++ b/indra/llcommon/llprocessor.h @@ -52,165 +52,4 @@ private: LLProcessorInfoImpl* mImpl; }; -# if 0 -// Author: Benjamin Jurke -// File history: 27.02.2002 File created. -/////////////////////////////////////////// - -// Options: -/////////// -#if LL_WINDOWS -#define PROCESSOR_FREQUENCY_MEASURE_AVAILABLE -#endif - -#if LL_MSVC && _M_X64 -# define LL_X86_64 1 -# define LL_X86 1 -#elif LL_MSVC && _M_IX86 -# define LL_X86 1 -#elif LL_GNUC && ( defined(__amd64__) || defined(__x86_64__) ) -# define LL_X86_64 1 -# define LL_X86 1 -#elif LL_GNUC && ( defined(__i386__) ) -# define LL_X86 1 -#elif LL_GNUC && ( defined(__powerpc__) || defined(__ppc__) ) -# define LL_PPC 1 -#endif - - -struct ProcessorExtensions -{ - bool FPU_FloatingPointUnit; - bool VME_Virtual8086ModeEnhancements; - bool DE_DebuggingExtensions; - bool PSE_PageSizeExtensions; - bool TSC_TimeStampCounter; - bool MSR_ModelSpecificRegisters; - bool PAE_PhysicalAddressExtension; - bool MCE_MachineCheckException; - bool CX8_COMPXCHG8B_Instruction; - bool APIC_AdvancedProgrammableInterruptController; - unsigned int APIC_ID; - bool SEP_FastSystemCall; - bool MTRR_MemoryTypeRangeRegisters; - bool PGE_PTE_GlobalFlag; - bool MCA_MachineCheckArchitecture; - bool CMOV_ConditionalMoveAndCompareInstructions; - bool FGPAT_PageAttributeTable; - bool PSE36_36bitPageSizeExtension; - bool PN_ProcessorSerialNumber; - bool CLFSH_CFLUSH_Instruction; - unsigned int CLFLUSH_InstructionCacheLineSize; - bool DS_DebugStore; - bool ACPI_ThermalMonitorAndClockControl; - bool EMMX_MultimediaExtensions; - bool MMX_MultimediaExtensions; - bool FXSR_FastStreamingSIMD_ExtensionsSaveRestore; - bool SSE_StreamingSIMD_Extensions; - bool SSE2_StreamingSIMD2_Extensions; - bool Altivec_Extensions; - bool SS_SelfSnoop; - bool HT_HyperThreading; - unsigned int HT_HyterThreadingSiblings; - bool TM_ThermalMonitor; - bool IA64_Intel64BitArchitecture; - bool _3DNOW_InstructionExtensions; - bool _E3DNOW_InstructionExtensions; - bool AA64_AMD64BitArchitecture; -}; - -struct ProcessorCache -{ - bool bPresent; - char strSize[32]; /* Flawfinder: ignore */ - unsigned int uiAssociativeWays; - unsigned int uiLineSize; - bool bSectored; - char strCache[128]; /* Flawfinder: ignore */ -}; - -struct ProcessorL1Cache -{ - ProcessorCache Instruction; - ProcessorCache Data; -}; - -struct ProcessorTLB -{ - bool bPresent; - char strPageSize[32]; /* Flawfinder: ignore */ - unsigned int uiAssociativeWays; - unsigned int uiEntries; - char strTLB[128]; /* Flawfinder: ignore */ -}; - -struct ProcessorInfo -{ - char strVendor[16]; /* Flawfinder: ignore */ - unsigned int uiFamily; - unsigned int uiExtendedFamily; - char strFamily[64]; /* Flawfinder: ignore */ - unsigned int uiModel; - unsigned int uiExtendedModel; - char strModel[128]; /* Flawfinder: ignore */ - unsigned int uiStepping; - unsigned int uiType; - char strType[64]; /* Flawfinder: ignore */ - unsigned int uiBrandID; - char strBrandID[64]; /* Flawfinder: ignore */ - char strProcessorSerial[64]; /* Flawfinder: ignore */ - unsigned long MaxSupportedLevel; - unsigned long MaxSupportedExtendedLevel; - ProcessorExtensions _Ext; - ProcessorL1Cache _L1; - ProcessorCache _L2; - ProcessorCache _L3; - ProcessorCache _Trace; - ProcessorTLB _Instruction; - ProcessorTLB _Data; -}; - - -// CProcessor -// ========== -// Class for detecting the processor name, type and available -// extensions as long as it's speed. -///////////////////////////////////////////////////////////// -class CProcessor -{ -// Constructor / Destructor: -//////////////////////////// -public: - CProcessor(); - -// Private vars: -//////////////// -private: - F64 uqwFrequency; - char strCPUName[128]; /* Flawfinder: ignore */ - ProcessorInfo CPUInfo; - -// Private functions: -///////////////////// -private: - bool AnalyzeIntelProcessor(); - bool AnalyzeAMDProcessor(); - bool AnalyzeUnknownProcessor(); - bool CheckCPUIDPresence(); - void DecodeProcessorConfiguration(unsigned int cfg); - void TranslateProcessorConfiguration(); - void GetStandardProcessorConfiguration(); - void GetStandardProcessorExtensions(); - -// Public functions: -//////////////////// -public: - F64 GetCPUFrequency(unsigned int uiMeasureMSecs); - const ProcessorInfo *GetCPUInfo(); - bool CPUInfoToText(char *strBuffer, unsigned int uiMaxLen); - bool WriteInfoTextFile(const std::string& strFilename); -}; - -#endif // 0 - #endif // LLPROCESSOR_H diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index d38fc1b013..86f2736d5a 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -58,7 +58,6 @@ # include # include const char MEMINFO_FILE[] = "/proc/meminfo"; -const char CPUINFO_FILE[] = "/proc/cpuinfo"; #elif LL_SOLARIS # include # include @@ -518,65 +517,16 @@ LLCPUInfo::LLCPUInfo() mHasSSE = proc.hasSSE(); mHasSSE2 = proc.hasSSE2(); mHasAltivec = proc.hasAltivec(); - mCPUMhz = (F64)(proc.getCPUFrequency()/1000000.0); + mCPUMHz = (F64)(proc.getCPUFrequency()/1000000.0); mFamily = proc.getCPUFamilyName(); mCPUString = "Unknown"; -#if LL_WINDOWS || LL_DARWIN || LL_SOLARIS out << proc.getCPUBrandName(); if (200 < mCPUMHz && mCPUMHz < 10000) // *NOTE: cpu speed is often way wrong, do a sanity check { out << " (" << mCPUMHz << " MHz)"; } mCPUString = out.str(); - -#elif LL_LINUX - std::map< std::string, std::string > cpuinfo; - LLFILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, "rb"); - if(cpuinfo_fp) - { - char line[MAX_STRING]; - memset(line, 0, MAX_STRING); - while(fgets(line, MAX_STRING, cpuinfo_fp)) - { - // /proc/cpuinfo on Linux looks like: - // name\t*: value\n - char* tabspot = strchr( line, '\t' ); - if (tabspot == NULL) - continue; - char* colspot = strchr( tabspot, ':' ); - if (colspot == NULL) - continue; - char* spacespot = strchr( colspot, ' ' ); - if (spacespot == NULL) - continue; - char* nlspot = strchr( line, '\n' ); - if (nlspot == NULL) - nlspot = line + strlen( line ); // Fallback to terminating NUL - std::string linename( line, tabspot ); - std::string llinename(linename); - LLStringUtil::toLower(llinename); - std::string lineval( spacespot + 1, nlspot ); - cpuinfo[ llinename ] = lineval; - } - fclose(cpuinfo_fp); - } -# if LL_X86 - std::string flags = " " + cpuinfo["flags"] + " "; - LLStringUtil::toLower(flags); - mHasSSE = ( flags.find( " sse " ) != std::string::npos ); - mHasSSE2 = ( flags.find( " sse2 " ) != std::string::npos ); - - F64 mhz; - if (LLStringUtil::convertToF64(cpuinfo["cpu mhz"], mhz) - && 200.0 < mhz && mhz < 10000.0) - { - mCPUMHz = (F64)(mhz); - } - if (!cpuinfo["model name"].empty()) - mCPUString = cpuinfo["model name"]; -# endif // LL_X86 -#endif // LL_LINUX } bool LLCPUInfo::hasAltivec() const @@ -606,29 +556,9 @@ std::string LLCPUInfo::getCPUString() const void LLCPUInfo::stream(std::ostream& s) const { -#if LL_WINDOWS || LL_DARWIN || LL_SOLARIS // gather machine information. s << LLProcessorInfo().getCPUFeatureDescription(); -#else - // *NOTE: This works on linux. What will it do on other systems? - LLFILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "rb"); - if(cpuinfo) - { - char line[MAX_STRING]; - memset(line, 0, MAX_STRING); - while(fgets(line, MAX_STRING, cpuinfo)) - { - line[strlen(line)-1] = ' '; - s << line; - } - fclose(cpuinfo); - s << std::endl; - } - else - { - s << "Unable to collect processor information" << std::endl; - } -#endif + // These are interesting as they reflect our internal view of the // CPU's attributes regardless of platform s << "->mHasSSE: " << (U32)mHasSSE << std::endl; -- cgit v1.3