POSIXCPUInfo.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. //XXTH orig #ifndef __APPLE__
  23. #if not defined (__APPLE__) //and not defined (__FreeBSD__)
  24. #include <fstream>
  25. #include <iostream>
  26. #include <string>
  27. #include <sstream>
  28. #include <vector>
  29. #include "platform/platform.h"
  30. #include "platformPOSIX/platformPOSIX.h"
  31. #include "platform/platformCPUCount.h"
  32. #include "console/console.h"
  33. #include <unistd.h>
  34. Platform::SystemInfo_struct Platform::SystemInfo;
  35. // trim from start (in place)
  36. static inline void ltrim(std::string &s) {
  37. s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
  38. return !std::isspace(ch);
  39. }));
  40. }
  41. // trim from end (in place)
  42. static inline void rtrim(std::string &s) {
  43. s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
  44. return !std::isspace(ch);
  45. }).base(), s.end());
  46. }
  47. static void getCPUInformation()
  48. {
  49. std::string vendorString;
  50. std::string brandString;
  51. std::ifstream cpuInfo("/proc/cpuinfo");
  52. U32 logicalCoreCount = 0;
  53. U32 physicalCoreCount = 1;
  54. if (cpuInfo.is_open())
  55. {
  56. // Load every line of the CPU Info
  57. std::string line;
  58. while (std::getline(cpuInfo, line))
  59. {
  60. std::string fieldName = line.substr(0, line.find(":"));
  61. rtrim(fieldName);
  62. // Entries are newline separated
  63. if (fieldName == "")
  64. {
  65. ++logicalCoreCount;
  66. continue;
  67. }
  68. std::string fieldValue = line.substr(line.find(":") + 1, line.length());
  69. ltrim(fieldValue);
  70. rtrim(fieldValue);
  71. // Load fields
  72. if (fieldName == "vendor_id")
  73. {
  74. vendorString = fieldValue.c_str();
  75. }
  76. else if (fieldName == "model name")
  77. {
  78. brandString = fieldValue.c_str();
  79. }
  80. else if (fieldName == "cpu cores")
  81. {
  82. physicalCoreCount = dAtoui(fieldValue.c_str());
  83. }
  84. else if (fieldName == "flags")
  85. {
  86. std::vector<std::string> flags;
  87. std::istringstream flagStream(fieldValue);
  88. std::string currentFlag;
  89. while (std::getline(flagStream, currentFlag, ' '))
  90. {
  91. flags.push_back(currentFlag);
  92. }
  93. // Set CPU flags
  94. if (std::find(flags.begin(), flags.end(), "fpu") != flags.end())
  95. {
  96. Platform::SystemInfo.processor.properties |= CPU_PROP_FPU;
  97. }
  98. if (std::find(flags.begin(), flags.end(), "sse3") != flags.end())
  99. {
  100. Platform::SystemInfo.processor.properties |= CPU_PROP_SSE3;
  101. }
  102. if (std::find(flags.begin(), flags.end(), "avx") != flags.end())
  103. {
  104. Platform::SystemInfo.processor.properties |= CPU_PROP_AVX;
  105. }
  106. if (std::find(flags.begin(), flags.end(), "ssse3") != flags.end())
  107. {
  108. Platform::SystemInfo.processor.properties |= CPU_PROP_SSE3ex;
  109. }
  110. if (std::find(flags.begin(), flags.end(), "sse") != flags.end())
  111. {
  112. Platform::SystemInfo.processor.properties |= CPU_PROP_SSE;
  113. }
  114. if (std::find(flags.begin(), flags.end(), "sse2") != flags.end())
  115. {
  116. Platform::SystemInfo.processor.properties |= CPU_PROP_SSE2;
  117. }
  118. if (std::find(flags.begin(), flags.end(), "sse4_1") != flags.end())
  119. {
  120. Platform::SystemInfo.processor.properties |= CPU_PROP_SSE4_1;
  121. }
  122. if (std::find(flags.begin(), flags.end(), "sse4_2") != flags.end())
  123. {
  124. Platform::SystemInfo.processor.properties |= CPU_PROP_SSE4_2;
  125. }
  126. if (std::find(flags.begin(), flags.end(), "mmx") != flags.end())
  127. {
  128. Platform::SystemInfo.processor.properties |= CPU_PROP_MMX;
  129. }
  130. }
  131. }
  132. cpuInfo.close();
  133. }
  134. else
  135. {
  136. logicalCoreCount = 1;
  137. }
  138. Platform::SystemInfo.processor.numLogicalProcessors = logicalCoreCount;
  139. Platform::SystemInfo.processor.numPhysicalProcessors = physicalCoreCount;
  140. Platform::SystemInfo.processor.isHyperThreaded = logicalCoreCount != physicalCoreCount;
  141. Platform::SystemInfo.processor.isMultiCore = physicalCoreCount != 1;
  142. Platform::SystemInfo.processor.numLogicalProcessors = logicalCoreCount;
  143. Platform::SystemInfo.processor.numPhysicalProcessors = physicalCoreCount;
  144. if (Platform::SystemInfo.processor.isMultiCore)
  145. {
  146. Platform::SystemInfo.processor.properties |= CPU_PROP_MP;
  147. }
  148. // Load processor base frequency
  149. std::ifstream baseFrequencyStream("/sys/devices/system/cpu/cpu0/cpufreq/base_frequency");
  150. if (baseFrequencyStream.is_open())
  151. {
  152. U32 baseFrequencyKHz = 0;
  153. baseFrequencyStream >> baseFrequencyKHz;
  154. Platform::SystemInfo.processor.mhz = baseFrequencyKHz / 1000;
  155. baseFrequencyStream.close();
  156. }
  157. SetProcessorInfo(Platform::SystemInfo.processor, vendorString.c_str(), brandString.c_str());
  158. }
  159. void Processor::init()
  160. {
  161. getCPUInformation();
  162. #if defined(TORQUE_CPU_X64) || defined(TORQUE_CPU_X32)
  163. // Set sane default information
  164. Platform::SystemInfo.processor.properties |= CPU_PROP_C | CPU_PROP_FPU | CPU_PROP_LE ;
  165. #elif defined(TORQUE_CPU_ARM32) || defined(TORQUE_CPU_ARM64)
  166. Platform::SystemInfo.processor.type = CPU_ArmCompatible;
  167. Platform::SystemInfo.processor.name = StringTable->insert("Unknown ARM Processor");
  168. Platform::SystemInfo.processor.properties = CPU_PROP_C;
  169. #else
  170. #warning Unsupported CPU
  171. #endif
  172. // Set 64bit flag
  173. #if defined(TORQUE_CPU_X64) || defined(TORQUE_CPU_ARM64)
  174. Platform::SystemInfo.processor.properties |= CPU_PROP_64bit;
  175. #endif
  176. // Once CPU information is resolved, produce an output like Windows does
  177. Con::printf("Processor Init:");
  178. Con::printf(" Processor: %s", Platform::SystemInfo.processor.name);
  179. if (Platform::SystemInfo.processor.properties & CPU_PROP_MMX)
  180. Con::printf(" MMX detected" );
  181. if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE)
  182. Con::printf(" SSE detected" );
  183. if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE2)
  184. Con::printf(" SSE2 detected" );
  185. if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE3)
  186. Con::printf(" SSE3 detected" );
  187. if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE4_1)
  188. Con::printf(" SSE4.1 detected" );
  189. if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE4_2)
  190. Con::printf(" SSE4.2 detected" );
  191. if (Platform::SystemInfo.processor.properties & CPU_PROP_AVX)
  192. Con::printf(" AVX detected" );
  193. if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE3ex)
  194. Con::printf(" SSE3ex detected" );
  195. if (Platform::SystemInfo.processor.properties & CPU_PROP_MP)
  196. Con::printf(" MultiCore CPU detected [%i cores, %i logical]", Platform::SystemInfo.processor.numPhysicalProcessors, Platform::SystemInfo.processor.numLogicalProcessors);
  197. Con::printf(" ");
  198. }
  199. namespace CPUInfo
  200. {
  201. EConfig CPUCount(U32 &logical, U32 &physical)
  202. {
  203. // We don't set logical or physical here because it's already been determined by this point
  204. if (Platform::SystemInfo.processor.isHyperThreaded && Platform::SystemInfo.processor.numPhysicalProcessors == 1)
  205. {
  206. return CONFIG_SingleCoreHTEnabled;
  207. }
  208. else if (!Platform::SystemInfo.processor.isHyperThreaded && Platform::SystemInfo.processor.numPhysicalProcessors > 1)
  209. {
  210. return CONFIG_MultiCoreAndHTNotCapable;
  211. }
  212. else if (!Platform::SystemInfo.processor.isHyperThreaded && Platform::SystemInfo.processor.numPhysicalProcessors == 1)
  213. {
  214. return CONFIG_SingleCoreAndHTNotCapable;
  215. }
  216. return CONFIG_MultiCoreAndHTEnabled;
  217. }
  218. }; // namespace CPUInfo
  219. #endif