diff options
-rw-r--r-- | indra/llcommon/CMakeLists.txt | 1 | ||||
-rw-r--r-- | indra/llcommon/llprocessor.cpp | 481 |
2 files changed, 236 insertions, 246 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index ac7cc2cdac..ab8c9b6f9a 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -230,7 +230,6 @@ set(llcommon_HEADER_FILES metaclasst.h metaproperty.h metapropertyt.h - processor.h reflective.h reflectivet.h roles_constants.h diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index 010435f11a..8ac0cdf4e3 100644 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -39,10 +39,11 @@ # define WIN32_LEAN_AND_MEAN # include <winsock2.h> # include <windows.h> +# include <intrin.h> #endif #include <boost/scoped_ptr.hpp> -#include <intrin.h> +#include "llsd.h" #if LL_MSVC && _M_X64 # define LL_X86_64 1 @@ -58,7 +59,66 @@ # define LL_PPC 1 #endif -// The base calss for implementations. +class LLProcessorInfoImpl; // foward declaration for the gImpl; + +namespace +{ + static const char* cpu_feature_names[] = + { + "x87 FPU On Chip", + "Virtual-8086 Mode Enhancement", + "Debugging Extensions", + "Page Size Extensions", + "Time Stamp Counter", + "RDMSR and WRMSR Support", + "Physical Address Extensions", + "Machine Check Exception", + "CMPXCHG8B Instruction", + "APIC On Chip", + "Unknown1", + "SYSENTER and SYSEXIT", + "Memory Type Range Registers", + "PTE Global Bit", + "Machine Check Architecture", + "Conditional Move/Compare Instruction", + "Page Attribute Table", + "Page Size Extension", + "Processor Serial Number", + "CFLUSH Extension", + "Unknown2", + "Debug Store", + "Thermal Monitor and Clock Ctrl", + "MMX Technology", + "FXSAVE/FXRSTOR", + "SSE Extensions", + "SSE2 Extensions", + "Self Snoop", + "Hyper-threading Technology", + "Thermal Monitor", + "Unknown4", + "Pend. Brk. EN.", // End of FeatureInfo bits + + "SSE3 New Instructions", // 32 + "MONITOR/MWAIT", + "CPL Qualified Debug Store", + "Thermal Monitor 2" + }; + + enum cpu_features + { + eSSE_Ext=25, + eSSE2_Ext=26, + eSSE3_Features=32, + eMONTIOR_MWAIT=33, + eCPLDebugStore=34, + eThermalMonitor2=35 + }; + + // Pointer to the active impl. + boost::scoped_ptr<LLProcessorInfoImpl> gImpl; +} + +// The base class for implementations. // Each platform should override this class. class LLProcessorInfoImpl { @@ -66,20 +126,90 @@ public: LLProcessorInfoImpl() {} virtual ~LLProcessorInfoImpl() {} - virtual F64 getCPUFrequency() const { return 0; } - virtual bool hasSSE() const { return false; } - virtual bool hasSSE2() const { return false; } - virtual bool hasAltivec() const { return false; } - virtual std::string getCPUFamilyName() const { return "Unknown"; } - virtual std::string getCPUBrandName() const { return "Unknown"; } - virtual std::string getCPUFeatureDescription() const { return "Unknown"; } + F64 getCPUFrequency() const + { + return getInfo("Frequency", 0).asReal(); + } + + bool hasSSE() const + { + return hasExtension(cpu_feature_names[eSSE_Ext]); + } + + bool hasSSE2() const + { + return hasExtension(cpu_feature_names[eSSE2_Ext]); + } + + bool hasAltivec() const + { + return hasExtension("Altivec"); + } + + std::string getCPUFamilyName() const { return getInfo("FamilyName", "Unknown").asString(); } + std::string getCPUBrandName() const { return getInfo("BrandName", "Unknown").asString(); } + std::string getCPUFeatureDescription() const + { + std::ostringstream out; + out << std::endl << std::endl; + out << "// CPU General Information" << std::endl; + 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 << 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; + out << std::endl; + out << "// CPU Extensions" << std::endl; + out << "//////////////////////////" << std::endl; + + for(LLSD::map_const_iterator itr = mProcessorInfo.beginMap(); itr != mProcessorInfo.endMap(); ++itr) + { + out << " " << itr->first << std::endl; + } + return out.str(); + } + +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 setExtension(const std::string& name) { mProcessorInfo["extension"][name] = "true"; } + + LLSD getInfo(const std::string& name, const LLSD& defaultVal) const + { + LLSD r = mProcessorInfo["info"].get(name); + return r.isDefined() ? r : defaultVal; + } + + 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; }; -namespace -{ - // Pointer to the active impl. - boost::scoped_ptr<LLProcessorInfoImpl> gImpl; -} #ifdef LL_MSVC // LL_MSVC and not LLWINDOWS because some of the following code @@ -178,98 +308,90 @@ static F64 calculate_cpu_frequency(U32 measure_msecs) return frequency; } -static const char* cpu_feature_names[] =
-{
- "x87 FPU On Chip",
- "Virtual-8086 Mode Enhancement",
- "Debugging Extensions",
- "Page Size Extensions",
- "Time Stamp Counter",
- "RDMSR and WRMSR Support",
- "Physical Address Extensions",
- "Machine Check Exception",
- "CMPXCHG8B Instruction",
- "APIC On Chip",
- "Unknown1",
- "SYSENTER and SYSEXIT",
- "Memory Type Range Registers",
- "PTE Global Bit",
- "Machine Check Architecture",
- "Conditional Move/Compare Instruction",
- "Page Attribute Table",
- "Page Size Extension",
- "Processor Serial Number",
- "CFLUSH Extension",
- "Unknown2",
- "Debug Store",
- "Thermal Monitor and Clock Ctrl",
- "MMX Technology",
- "FXSAVE/FXRSTOR",
- "SSE Extensions",
- "SSE2 Extensions",
- "Self Snoop",
- "Hyper-threading Technology",
- "Thermal Monitor",
- "Unknown4",
- "Pend. Brk. EN."
-};
- // Windows implementation class LLProcessorInfoWindowsImpl : public LLProcessorInfoImpl { public: LLProcessorInfoWindowsImpl() : - mCPUFrequency(0), - mSteppingID(0),
- mModel(0),
- mFamily(0),
- mProcessorType(0),
- mExtendedModel(0),
- mExtendedFamily(0),
- mBrandIndex(0),
- mCLFLUSHCacheLineSize(0),
- mAPICPhysicalID(0),
- mCacheLineSize(0),
- mL2Associativity(0),
- mCacheSizeK(0),
-
- mFeatureInfo(0),
- mSSE3NewInstructions(false),
- mMONITOR_MWAIT(false),
- mCPLQualifiedDebugStore(false),
- mThermalMonitor2(false),
- - mIds(0), - mExtIds(0) - - { - memset(&mCPUString, 0, 0x20); - memset(&mCPUBrandString, 0, 0x40); - + { getCPUIDInfo(); - mCPUFrequency = calculate_cpu_frequency(50); - } - - F64 getCPUFrequency() const - { - return mCPUFrequency; + AddInfoItem("Frequency", calculate_cpu_frequency(50)); } - bool hasSSE() const +private: + void getCPUIDInfo() { - // constant comes from the msdn docs for __cpuid - const int sse_feature_index = 25; - return mFeatureInfo & (1 << sse_feature_index); - } + // http://msdn.microsoft.com/en-us/library/hskdteyh(VS.80).aspx + + // __cpuid with an InfoType argument of 0 returns the number of + // valid Ids in cpu_info[0] and the CPU identification string in + // the other three array elements. The CPU identification string is + // not in linear order. The code below arranges the information + // in a human readable form. + int cpu_info[4] = {-1}; + __cpuid(cpu_info, 0); + unsigned int ids = (unsigned int)cpu_info[0]; + setInfo("MaxIDs", 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]; + + // Get the information associated with each valid Id + for(unsigned int i=0; i<=mIds; ++i) + { + __cpuid(cpu_info, i); - bool hasSSE2() const - { - // constant comes from the msdn docs for __cpuid - const int sse2_feature_index = 26; - return mFeatureInfo & (1 << sse2_feature_index); + // 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]; + } + } + + // 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)); + + // Get the information associated with each extended ID. + for(unsigned int i=0x80000000; i<=mExtIds; ++i) + { + __cpuid(cpu_info, i); + + // Interpret CPU brand string and cache information. + if (i == 0x80000002) + memcpy(mCPUBrandString, cpu_info, sizeof(cpu_info)); + else if (i == 0x80000003) + memcpy(mCPUBrandString + 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 getCPUFamilyName() const + std::string computeCPUFamilyName() const { const char* intel_string = "GenuineIntel"; const char* amd_string = "AuthenticAMD"; @@ -306,160 +428,27 @@ public: return "Unknown"; } - std::string getCPUBrandName() const { return mCPUBrandString; } - std::string getCPUFeatureDescription() const - { - std::ostringstream out; - out << std::endl << std::endl; - out << "// CPU General Information" << std::endl; - out << "//////////////////////////" << std::endl; - out << "Processor Name: " << getCPUBrandName() << std::endl; - out << "Frequency: " << mCPUFrequency / (F64)1000000 << " MHz" << std::endl; - out << "Vendor: " << mCPUString << std::endl; - out << "Family: " << getCPUFamilyName() << " (" << mFamily << ")" << std::endl; - out << "Extended family: " << mExtendedFamily << std::endl; - out << "Model: " << mModel << std::endl; - out << "Extended model: " << mExtendedModel << std::endl; - out << "Type: " << mProcessorType << std::endl; - out << "Brand ID: " << mBrandIndex << std::endl; - out << std::endl; - out << "// CPU Configuration" << std::endl; - out << "//////////////////////////" << std::endl; - out << "Max Supported CPUID level = " << mIds << std::endl; - out << "Max Supported Ext. CPUID level = " << std::hex << mExtIds << std::dec << std::endl; - out << "CLFLUSH cache line size = " << mCLFLUSHCacheLineSize << std::endl;
- out << "APIC Physical ID = " << mAPICPhysicalID << std::endl;
- out << "Cache Line Size = " << mCacheLineSize << std::endl;
- out << "L2 Associativity = " << mL2Associativity << std::endl;
- out << "Cache Size = " << mCacheSizeK << "K" << std::endl;
- out << std::endl; - out << "// CPU Extensions" << std::endl; - out << "//////////////////////////" << std::endl; - if(mSSE3NewInstructions)
- {
- out << " SSE3 New Instructions" << std::endl;
- }
- if(mMONITOR_MWAIT)
- {
- out << " MONITOR/MWAIT" << std::endl;
- }
- if(mCPLQualifiedDebugStore)
- {
- out << " CPL Qualified Debug Store" << std::endl;
- }
- if(mThermalMonitor2)
- {
- out << " Thermal Monitor 2" << std::endl;
- }
-
- U32 index = 0;
- U32 bit = 1;
- while(index < (sizeof(cpu_feature_names)/sizeof(const char*)))
- {
- if(mFeatureInfo & bit)
- {
- out << " " << cpu_feature_names[index] << std::endl;
- }
- bit <<= 1;
- ++index;
- }
-
- return out.str(); - } +}; -private: - F64 mCPUFrequency;
- char mCPUString[0x20];
- char mCPUBrandString[0x40];
- int mSteppingID;
- int mModel;
- int mFamily;
- int mProcessorType;
- int mExtendedModel;
- int mExtendedFamily;
- int mBrandIndex;
- int mCLFLUSHCacheLineSize;
- int mAPICPhysicalID;
- int mCacheLineSize;
- int mL2Associativity;
- int mCacheSizeK;
-
- int mFeatureInfo;
- bool mSSE3NewInstructions;
- bool mMONITOR_MWAIT;
- bool mCPLQualifiedDebugStore;
- bool mThermalMonitor2;
- - unsigned int mIds; - unsigned int mExtIds; +#elif LL_DARWIN - void getCPUIDInfo() +class LLProcessorInfoDarwinImpl +{ +public: + LLProcessorInfoDarwinImpl() { - // http://msdn.microsoft.com/en-us/library/hskdteyh(VS.80).aspx
-
- // __cpuid with an InfoType argument of 0 returns the number of
- // valid Ids in cpu_info[0] and the CPU identification string in
- // the other three array elements. The CPU identification string is
- // not in linear order. The code below arranges the information
- // in a human readable form.
- int cpu_info[4] = {-1};
- __cpuid(cpu_info, 0);
- unsigned int mIds = (unsigned int)cpu_info[0];
- *((int*)mCPUString) = cpu_info[1];
- *((int*)(mCPUString+4)) = cpu_info[3];
- *((int*)(mCPUString+8)) = cpu_info[2];
- - // Get the information associated with each valid Id
- for(unsigned int i=0; i<=mIds; ++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];
- }
- }
-
- // 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));
-
- // Get the information associated with each extended ID.
- for(unsigned int i=0x80000000; i<=mExtIds; ++i)
- {
- __cpuid(cpu_info, i);
-
- // Interpret CPU brand string and cache information.
- if (i == 0x80000002)
- memcpy(mCPUBrandString, cpu_info, sizeof(cpu_info));
- else if (i == 0x80000003)
- memcpy(mCPUBrandString + 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;
- }
- }
+ } + + virtual ~LLProcessorInfoDarwinImpl() {} + + virtual F64 getCPUFrequency() const { return 0; } + virtual bool hasSSE() const { return false; } + virtual bool hasSSE2() const { return false; } + virtual bool hasAltivec() const { return false; } + virtual std::string getCPUFamilyName() const { return "Unknown"; } + virtual std::string getCPUBrandName() const { return "Unknown"; } + virtual std::string getCPUFeatureDescription() const { return "Unknown"; } }; #endif // LL_MSVC @@ -474,7 +463,9 @@ LLProcessorInfo::LLProcessorInfo() { #ifdef LL_MSVC gImpl.reset(new LLProcessorInfoWindowsImpl); -#else +#elif LL_DARWIN + gImpl.reset(new LLProcessorInfoDarwinImpl); +#else #error "Unimplemented" #endif // LL_MSVC } |