Cpu.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. /*#if ANDROID
  4. #include <thread>
  5. #include <cpu-features.h>
  6. #endif*/
  7. namespace EE{
  8. /******************************************************************************/
  9. CPU Cpu;
  10. /******************************************************************************/
  11. void CPU::set()
  12. {
  13. // disable denormals (multiplying denormals on Intel i7-3632QM 2.2 Ghz is 16x slower compared to normal values)
  14. #if !(WINDOWS && ARM) && !IOS && !ANDROID && !WEB
  15. _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
  16. #endif
  17. }
  18. #if MAC
  19. void __cpuid(int regs[4], int cpuid_leaf)
  20. {
  21. int eax, ebx, ecx, edx;
  22. asm(
  23. #if !X64
  24. "pushl %%ebx;\n\t"
  25. #endif
  26. "movl %4, %%eax;\n\t"
  27. "cpuid;\n\t"
  28. "movl %%eax, %0;\n\t"
  29. "movl %%ebx, %1;\n\t"
  30. "movl %%ecx, %2;\n\t"
  31. "movl %%edx, %3;\n\t"
  32. #if !X64
  33. "popl %%ebx;\n\t"
  34. #endif
  35. :"=m" (eax), "=m" (ebx), "=m" (ecx), "=m" (edx)
  36. :"r" (cpuid_leaf)
  37. :"%eax",
  38. #if X64
  39. "%ebx",
  40. #endif
  41. "%ecx", "%edx");
  42. regs[0]=eax;
  43. regs[1]=ebx;
  44. regs[2]=ecx;
  45. regs[3]=edx;
  46. }
  47. #elif LINUX
  48. #undef __cpuid
  49. static void __cpuid(int regs[4], int cpuid_leaf)
  50. {
  51. __get_cpuid(cpuid_leaf, (unsigned int*)&regs[0], (unsigned int*)&regs[1], (unsigned int*)&regs[2], (unsigned int*)&regs[3]);
  52. }
  53. #elif ANDROID
  54. static ULong GetBits(CChar8 *text) // sample: "0,1-3"
  55. {
  56. ULong out=0;
  57. CalcValue val;
  58. for(; text; )
  59. {
  60. text=TextValue(text, val); if(!val.type)break;
  61. Int a=val.asInt();
  62. if(text && *text=='-') // range
  63. {
  64. text=TextValue(text+1, val); if(!val.type)break; // skip '-'
  65. Int b=val.asInt();
  66. for(Int i=a; i<=b; i++)out|=(ULong(1)<<i);
  67. }else // single value
  68. {
  69. out|=(ULong(1)<<a);
  70. }
  71. if(text && *text==',')text++; // skip comma and proceed to next value
  72. }
  73. return out;
  74. }
  75. #endif
  76. CPU::CPU()
  77. {
  78. if(LogInit)LogN("CPU.create");
  79. #if WINDOWS
  80. _flag|=(IsProcessorFeaturePresent(PF_MMX_INSTRUCTIONS_AVAILABLE ) ? CPU_MMX : 0);
  81. _flag|=(IsProcessorFeaturePresent(PF_3DNOW_INSTRUCTIONS_AVAILABLE ) ? CPU_3DNOW : 0);
  82. _flag|=(IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE ) ? CPU_SSE : 0);
  83. _flag|=(IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE) ? CPU_SSE2 : 0);
  84. _flag|=(IsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE ) ? CPU_SSE3 : 0);
  85. #if WINDOWS_OLD
  86. DWORD_PTR process, system; GetProcessAffinityMask(GetCurrentProcess(), &process, &system);
  87. REP(64)if(process&(ULong(1)<<i))_threads++;
  88. #elif WINDOWS_NEW
  89. SYSTEM_INFO sys_info; GetSystemInfo(&sys_info); _threads=sys_info.dwNumberOfProcessors;
  90. #endif
  91. #elif LINUX
  92. _threads=sysconf(_SC_NPROCESSORS_CONF);
  93. #elif APPLE
  94. #if 1
  95. _threads=sysconf(_SC_NPROCESSORS_CONF);
  96. #else
  97. size_t len=SIZE(ncpus); sysctl((int[2]){CTL_HW, HW_NCPU}, 2, &_threads, &len, null, 0);
  98. #endif
  99. #endif
  100. #if (WINDOWS && !ARM) || MAC || LINUX
  101. Int CPUInfo[4];
  102. // constants taken from cpuid.h
  103. __cpuid(CPUInfo, 1);
  104. if(CPUInfo[3]&(1<<23))_flag|=CPU_MMX;
  105. if(CPUInfo[3]&(1<<25))_flag|=CPU_SSE;
  106. if(CPUInfo[3]&(1<<26))_flag|=CPU_SSE2;
  107. if(CPUInfo[2]&(1<< 0))_flag|=CPU_SSE3;
  108. if(CPUInfo[2]&(1<<19))_flag|=CPU_SSE4_1;
  109. if(CPUInfo[2]&(1<<20))_flag|=CPU_SSE4_2;
  110. if(CPUInfo[2]&(1<<28))_flag|=CPU_AVX;
  111. if(CPUInfo[2]&(1<<25))_flag|=CPU_AES;
  112. __cpuid(CPUInfo, 7);
  113. if(CPUInfo[1]&(1<<5))_flag|=CPU_AVX2;
  114. __cpuid(CPUInfo, 0x80000001);
  115. if(CPUInfo[3]&(1<<31))_flag|=CPU_3DNOW;
  116. char string[64]; Zero(string);
  117. __cpuid(CPUInfo, 0x80000000); UInt ids=CPUInfo[0];
  118. for(UInt i=0x80000002; i<=Min(ids, 0x80000004); i++)
  119. {
  120. __cpuid(CPUInfo, i);
  121. if(i==0x80000002)CopyFast(string , CPUInfo, SIZE(CPUInfo));else
  122. if(i==0x80000003)CopyFast(string+16, CPUInfo, SIZE(CPUInfo));else
  123. if(i==0x80000004)CopyFast(string+32, CPUInfo, SIZE(CPUInfo));
  124. }
  125. _name=_SkipWhiteChars(string);
  126. #elif ANDROID
  127. Char8 data[65536];
  128. /* Sample output for Galaxy Note 4
  129. processor : 0
  130. model name : ARMv7 Processor rev 1 (v7l)
  131. BogoMIPS : 52.00
  132. Features : swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt
  133. CPU implementer : 0x41
  134. CPU architecture: 7
  135. CPU variant : 0x0
  136. CPU part : 0xd03
  137. CPU revision : 1
  138. processor : 1
  139. model name : ARMv7 Processor rev 1 (v7l)
  140. BogoMIPS : 52.00
  141. Features : swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt
  142. CPU implementer : 0x41
  143. CPU architecture: 7
  144. CPU variant : 0x0
  145. CPU part : 0xd03
  146. CPU revision : 1
  147. processor : 2
  148. model name : ARMv7 Processor rev 1 (v7l)
  149. BogoMIPS : 52.00
  150. Features : swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt
  151. CPU implementer : 0x41
  152. CPU architecture: 7
  153. CPU variant : 0x0
  154. CPU part : 0xd03
  155. CPU revision : 1
  156. processor : 3
  157. model name : ARMv7 Processor rev 1 (v7l)
  158. BogoMIPS : 52.00
  159. Features : swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt
  160. CPU implementer : 0x41
  161. CPU architecture: 7
  162. CPU variant : 0x0
  163. CPU part : 0xd03
  164. CPU revision : 1
  165. processor : 4
  166. model name : ARMv7 Processor rev 0 (v7l)
  167. BogoMIPS : 76.00
  168. Features : swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt
  169. CPU implementer : 0x41
  170. CPU architecture: 7
  171. CPU variant : 0x1
  172. CPU part : 0xd07
  173. CPU revision : 0
  174. processor : 5
  175. model name : ARMv7 Processor rev 0 (v7l)
  176. BogoMIPS : 76.00
  177. Features : swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt
  178. CPU implementer : 0x41
  179. CPU architecture: 7
  180. CPU variant : 0x1
  181. CPU part : 0xd07
  182. CPU revision : 0
  183. processor : 6
  184. model name : ARMv7 Processor rev 0 (v7l)
  185. BogoMIPS : 76.00
  186. Features : swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt
  187. CPU implementer : 0x41
  188. CPU architecture: 7
  189. CPU variant : 0x1
  190. CPU part : 0xd07
  191. CPU revision : 0
  192. processor : 7
  193. model name : ARMv7 Processor rev 0 (v7l)
  194. BogoMIPS : 76.00
  195. Features : swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt
  196. CPU implementer : 0x41
  197. CPU architecture: 7
  198. CPU variant : 0x1
  199. CPU part : 0xd07
  200. CPU revision : 0
  201. Hardware : Samsung EXYNOS5433
  202. Revision : 000d
  203. Serial : 5b8165e4c0680041
  204. */
  205. // get name
  206. if(UnixReadFile("/proc/cpuinfo", data, SIZE(data)))
  207. {
  208. //LogN(data);
  209. CChar8 *t;
  210. if(t=TextPos(data, "Hardware" , false, true))t+=8;else // Length("Hardware" ) -> 8
  211. if(t=TextPos(data, "Processor", false, true))t+=9; // Length("Processor") -> 9, if "Hardware" not available, then try using "Processor", because in the past sample output was: "Processor: ARMv7 Processor rev 9 (v7l)"
  212. if(t)
  213. {
  214. for(; *t==' ' || *t==':' || *t=='\t'; ) t++; // skip spaces
  215. for(; *t!='\0' && *t!='\n' ; )_name+=*t++;
  216. }
  217. }
  218. // get threads - do not rely on '_SC_NPROCESSORS_CONF' or '_SC_NPROCESSORS_ONLN' as they both may return not all threads (if some are switched off due to power saving), 'sysctl' is not available on Android
  219. UnixReadFile("/sys/devices/system/cpu/present" , data, SIZE(data)); ULong cpu_present =GetBits(data); // sample output: "0-3", "0,1-2" (no spaces, values separated with commas, ranges or single values, ranges inclusive)
  220. UnixReadFile("/sys/devices/system/cpu/possible", data, SIZE(data)); ULong cpu_possible=GetBits(data);
  221. ULong mask=(cpu_present&cpu_possible); REP(64)if(mask&(ULong(1)<<i))_threads++;
  222. MAX(_threads, sysconf(_SC_NPROCESSORS_CONF)); // just in case code above was unsuccessful
  223. //LogN(S+"cpu_present:"+TextBin(cpu_present)+" cpu_possible:"+TextBin(cpu_possible)+" mask:"+TextBin(mask)+", sysconf(_SC_NPROCESSORS_CONF):"+(Int)sysconf(_SC_NPROCESSORS_CONF)+", android_getCpuCount:"+(Int)android_getCpuCount()+", std::thread::hardware_concurrency:"+(Int)std::thread::hardware_concurrency());
  224. #endif
  225. MAX(_threads, 1);
  226. set();
  227. }
  228. /******************************************************************************/
  229. }
  230. /******************************************************************************/