diff --git a/Engine/source/platform/platformCPU.cpp b/Engine/source/platform/platformCPU.cpp index 8449d1daa..f3246c6ed 100644 --- a/Engine/source/platform/platformCPU.cpp +++ b/Engine/source/platform/platformCPU.cpp @@ -28,7 +28,8 @@ Signal 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(); -} +} \ No newline at end of file diff --git a/Engine/source/platform/platformCPUCount.h b/Engine/source/platform/platformCPUCount.h index d008201b3..66a0c2e12 100644 --- a/Engine/source/platform/platformCPUCount.h +++ b/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_ diff --git a/Engine/source/platformMac/macCPU.mm b/Engine/source/platformMac/macCPU.mm index d93bcf25f..001d537a0 100644 --- a/Engine/source/platformMac/macCPU.mm +++ b/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:"); diff --git a/Engine/source/platformPOSIX/POSIXCPUInfo.cpp b/Engine/source/platformPOSIX/POSIXCPUInfo.cpp index 279d23f1a..14c22c284 100644 --- a/Engine/source/platformPOSIX/POSIXCPUInfo.cpp +++ b/Engine/source/platformPOSIX/POSIXCPUInfo.cpp @@ -22,30 +22,233 @@ #ifndef __APPLE__ +#include +#include +#include +#include +#include + #include "platform/platform.h" #include "platformPOSIX/platformPOSIX.h" -#include "console/console.h" -#include "core/stringTable.h" -#include "core/strings/stringFunctions.h" -#include - #include "platform/platformCPUCount.h" + +#include "console/console.h" + #include 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(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(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 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 \ No newline at end of file diff --git a/Engine/source/platformWin32/winCPUInfo.cpp b/Engine/source/platformWin32/winCPUInfo.cpp index f8ea9ab2d..e7f2ef4bc 100644 --- a/Engine/source/platformWin32/winCPUInfo.cpp +++ b/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