Browse Source

* Feature: Reimplement POSIX CPU information.
* BugFix: Correct a typo in setProcessoInformation -> setProcessorInformation.

Robert MacGregor 3 years ago
parent
commit
2368f1d97c

+ 3 - 2
Engine/source/platform/platformCPU.cpp

@@ -28,7 +28,8 @@
 
 Signal<void(void)> Platform::SystemInfoReady;
 
-void SetProcessoInfo(Platform::SystemInfo_struct::Processor& pInfo, char* vendor, char* brand)
+// fill the specified structure with information obtained from asm code
+void SetProcessorInfo(Platform::SystemInfo_struct::Processor& pInfo, const char* vendor, const char* brand)
 {
    if (dStricmp(vendor, "GenuineIntel") == 0)
    {
@@ -70,4 +71,4 @@ void SetProcessoInfo(Platform::SystemInfo_struct::Processor& pInfo, char* vendor
 
    // Trigger the signal
    Platform::SystemInfoReady.trigger();
-}
+}

+ 1 - 1
Engine/source/platform/platformCPUCount.h

@@ -64,7 +64,7 @@ namespace CPUInfo
    EConfig CPUCount( U32& totalAvailableLogical, U32& totalAvailableCores );
 } // namespace CPUInfo
 
-void SetProcessoInfo(Platform::SystemInfo_struct::Processor& pInfo, char* vendor, char* brand);
+void SetProcessorInfo(Platform::SystemInfo_struct::Processor& pInfo, const char* vendor, const char* brand);
 
 #endif // _TORQUE_PLATFORM_PLATFORMCOUNT_H_
 

+ 1 - 1
Engine/source/platformMac/macCPU.mm

@@ -190,7 +190,7 @@ void Processor::init()
    detectCpuFeatures(procflags);
    
    Platform::SystemInfo.processor.properties = procflags;
-   SetProcessoInfo(Platform::SystemInfo.processor, vendor, brandString);
+   SetProcessorInfo(Platform::SystemInfo.processor, vendor, brandString);
    
    
    Con::printf("System & Processor Information:");

+ 214 - 11
Engine/source/platformPOSIX/POSIXCPUInfo.cpp

@@ -22,30 +22,233 @@
 
 #ifndef __APPLE__
 
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <vector>
+
 #include "platform/platform.h"
 #include "platformPOSIX/platformPOSIX.h"
+#include "platform/platformCPUCount.h"
+
 #include "console/console.h"
-#include "core/stringTable.h"
-#include "core/strings/stringFunctions.h"
-#include <math.h>
 
-#include "platform/platformCPUCount.h"
 #include <unistd.h>
 
 Platform::SystemInfo_struct Platform::SystemInfo;
 
-void Processor::init() {}
+static inline void rtrim(std::string &s)
+{
+    s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
+}
+
+static inline void ltrim(std::string &s)
+{
+    s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
+}
+
+void getCPUInformation()
+{
+    std::string vendorString;
+    std::string brandString;
+
+    std::ifstream cpuInfo("/proc/cpuinfo");
+
+    U32 logicalCoreCount = 0;
+    U32 physicalCoreCount = 1;
+
+    if (cpuInfo.is_open())
+    {
+        // Load every line of the CPU Info
+        std::string line;
+
+        while (std::getline(cpuInfo, line))
+        {
+            std::string fieldName = line.substr(0, line.find(":"));
+            rtrim(fieldName);
+
+            // Entries are newline separated
+            if (fieldName == "")
+            {
+                ++logicalCoreCount;
+                continue;
+            }
+
+            std::string fieldValue = line.substr(line.find(":") + 1, line.length());
+            ltrim(fieldValue);
+            rtrim(fieldValue);
+
+            // Load fields
+            if (fieldName == "vendor_id")
+            {
+                vendorString = fieldValue.c_str();
+            }
+            else if (fieldName == "model name")
+            {
+                brandString = fieldValue.c_str();
+            }
+            else if (fieldName == "cpu cores")
+            {
+                physicalCoreCount = dAtoui(fieldValue.c_str());
+            }
+            else if (fieldName == "flags")
+            {
+                std::vector<std::string> flags;
+                std::istringstream flagStream(fieldValue);
+
+                std::string currentFlag;
+                while (std::getline(flagStream, currentFlag, ' '))
+                {
+                    flags.push_back(currentFlag);
+                }
+
+                // Set CPU flags
+                if (std::find(flags.begin(), flags.end(), "fpu") != flags.end())
+                {
+                    Platform::SystemInfo.processor.properties |= CPU_PROP_FPU;
+                }
+
+                if (std::find(flags.begin(), flags.end(), "sse3") != flags.end())
+                {
+                    Platform::SystemInfo.processor.properties |= CPU_PROP_SSE3;
+                }
+
+                if (std::find(flags.begin(), flags.end(), "avx") != flags.end())
+                {
+                    Platform::SystemInfo.processor.properties |= CPU_PROP_AVX;
+                }
+
+                if (std::find(flags.begin(), flags.end(), "ssse3") != flags.end())
+                {
+                    Platform::SystemInfo.processor.properties |= CPU_PROP_SSE3ex;
+                }
+
+                if (std::find(flags.begin(), flags.end(), "sse") != flags.end())
+                {
+                    Platform::SystemInfo.processor.properties |= CPU_PROP_SSE;
+                }
+
+                if (std::find(flags.begin(), flags.end(), "sse2") != flags.end())
+                {
+                    Platform::SystemInfo.processor.properties |= CPU_PROP_SSE2;
+                }
+
+                if (std::find(flags.begin(), flags.end(), "sse4_1") != flags.end())
+                {
+                    Platform::SystemInfo.processor.properties |= CPU_PROP_SSE4_1;
+                }
+
+                if (std::find(flags.begin(), flags.end(), "sse4_2") != flags.end())
+                {
+                    Platform::SystemInfo.processor.properties |= CPU_PROP_SSE4_2;
+                }
+
+                if (std::find(flags.begin(), flags.end(), "mmx") != flags.end())
+                {
+                    Platform::SystemInfo.processor.properties |= CPU_PROP_MMX;
+                }
+            }
+        }
+
+        cpuInfo.close();
+    }
+    else
+    {
+        logicalCoreCount = 1;
+    }
+
+    Platform::SystemInfo.processor.numLogicalProcessors = logicalCoreCount;
+    Platform::SystemInfo.processor.numPhysicalProcessors = physicalCoreCount;
+    Platform::SystemInfo.processor.isHyperThreaded = logicalCoreCount != physicalCoreCount;
+    Platform::SystemInfo.processor.isMultiCore = physicalCoreCount != 1;
+    Platform::SystemInfo.processor.numLogicalProcessors = logicalCoreCount;
+    Platform::SystemInfo.processor.numPhysicalProcessors = physicalCoreCount;
+    if (Platform::SystemInfo.processor.isMultiCore)
+    {
+        Platform::SystemInfo.processor.properties |= CPU_PROP_MP;
+    }
+
+    // Load processor base frequency
+    std::ifstream baseFrequencyStream("/sys/devices/system/cpu/cpu0/cpufreq/base_frequency");
+    if (baseFrequencyStream.is_open())
+    {
+        U32 baseFrequencyKHz = 0;
+        baseFrequencyStream >> baseFrequencyKHz;
+
+        Platform::SystemInfo.processor.mhz = baseFrequencyKHz / 1000;
+        baseFrequencyStream.close();
+    }
+
+    SetProcessorInfo(Platform::SystemInfo.processor, vendorString.c_str(), brandString.c_str());
+}
+
+void Processor::init() 
+{
+    getCPUInformation();
+
+#if defined(TORQUE_CPU_X64) || defined(TORQUE_CPU_X32)
+    // Set sane default information
+    Platform::SystemInfo.processor.properties |= CPU_PROP_C | CPU_PROP_FPU | CPU_PROP_LE ;
+
+#elif defined(TORQUE_CPU_ARM32) || defined(TORQUE_CPU_ARM64)
+    Platform::SystemInfo.processor.type = CPU_ArmCompatible;
+    Platform::SystemInfo.processor.name = StringTable->insert("Unknown ARM Processor");
+    Platform::SystemInfo.processor.properties = CPU_PROP_C;
+#else
+#warning Unsupported CPU
+#endif
+
+    // Set 64bit flag
+#if defined(TORQUE_CPU_X64) || defined(TORQUE_CPU_ARM64)
+    Platform::SystemInfo.processor.properties |= CPU_PROP_64bit;
+#endif
+
+    // Once CPU information is resolved, produce an output like Windows does
+    Con::printf("Processor Init:");
+    Con::printf("   Processor: %s", Platform::SystemInfo.processor.name);
+    if (Platform::SystemInfo.processor.properties & CPU_PROP_MMX)
+        Con::printf("      MMX detected" );
+    if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE)
+        Con::printf("      SSE detected" );
+    if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE2)
+        Con::printf("      SSE2 detected" );
+    if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE3)
+        Con::printf("      SSE3 detected" );
+    if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE4_1)
+        Con::printf("      SSE4.1 detected" );
+    if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE4_2)
+        Con::printf("      SSE4.2 detected" );
+    if (Platform::SystemInfo.processor.properties & CPU_PROP_AVX)
+        Con::printf("      AVX detected" );
+    if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE3ex)
+        Con::printf("      SSE3ex detected" );
+    if (Platform::SystemInfo.processor.properties & CPU_PROP_MP)
+        Con::printf("   MultiCore CPU detected [%i cores, %i logical]", Platform::SystemInfo.processor.numPhysicalProcessors, Platform::SystemInfo.processor.numLogicalProcessors);
+
+    Con::printf(" ");
+}
 
-// TODO LINUX CPUInfo::CPUCount better support
 namespace CPUInfo
 {
-    EConfig CPUCount(U32& TotAvailLogical, U32& TotAvailCore, U32& PhysicalNum)
+    EConfig CPUCount(U32 &logical, U32 &physical)
     {
-        PhysicalNum = TotAvailCore = 0;
-        TotAvailLogical = (int)sysconf(_SC_NPROCESSORS_ONLN);
+        // We don't set logical or physical here because it's already been determined by this point
+        if (Platform::SystemInfo.processor.isHyperThreaded && Platform::SystemInfo.processor.numPhysicalProcessors == 1)
+        {
+            return CONFIG_SingleCoreHTEnabled;
+        }
+        else if (!Platform::SystemInfo.processor.isHyperThreaded && Platform::SystemInfo.processor.numPhysicalProcessors > 1)
+        {
+            return CONFIG_MultiCoreAndHTNotCapable;
+        }
+        else if (!Platform::SystemInfo.processor.isHyperThreaded && Platform::SystemInfo.processor.numPhysicalProcessors == 1)
+        {
+            return CONFIG_SingleCoreAndHTNotCapable;   
+        }
 
-       return CONFIG_SingleCoreHTDisabled;
+        return CONFIG_MultiCoreAndHTEnabled;
     }
-}; // namespace CPUInfo 
+}; // namespace CPUInfo
 
 #endif

+ 1 - 1
Engine/source/platformWin32/winCPUInfo.cpp

@@ -137,7 +137,7 @@ void Processor::init()
    dMemset(brand, 0, sizeof(brand));
    getBrand(brand);
 
-   SetProcessoInfo(Platform::SystemInfo.processor, vendor, brand);
+   SetProcessorInfo(Platform::SystemInfo.processor, vendor, brand);
    detectCpuFeatures(Platform::SystemInfo.processor);
 
    U32 mhz = 1000; // default if it can't be found