sysinfo.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. // ======================================================================== //
  2. // Copyright 2009-2017 Intel Corporation //
  3. // //
  4. // Licensed under the Apache License, Version 2.0 (the "License"); //
  5. // you may not use this file except in compliance with the License. //
  6. // You may obtain a copy of the License at //
  7. // //
  8. // http://www.apache.org/licenses/LICENSE-2.0 //
  9. // //
  10. // Unless required by applicable law or agreed to in writing, software //
  11. // distributed under the License is distributed on an "AS IS" BASIS, //
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
  13. // See the License for the specific language governing permissions and //
  14. // limitations under the License. //
  15. // ======================================================================== //
  16. #include "sysinfo.h"
  17. #include "intrinsics.h"
  18. #include "string.h"
  19. ////////////////////////////////////////////////////////////////////////////////
  20. /// All Platforms
  21. ////////////////////////////////////////////////////////////////////////////////
  22. namespace embree
  23. {
  24. std::string getPlatformName()
  25. {
  26. #if defined(__LINUX__) && !defined(__X86_64__)
  27. return "Linux (32bit)";
  28. #elif defined(__LINUX__) && defined(__X86_64__)
  29. return "Linux (64bit)";
  30. #elif defined(__FREEBSD__) && !defined(__X86_64__)
  31. return "FreeBSD (32bit)";
  32. #elif defined(__FREEBSD__) && defined(__X86_64__)
  33. return "FreeBSD (64bit)";
  34. #elif defined(__CYGWIN__) && !defined(__X86_64__)
  35. return "Cygwin (32bit)";
  36. #elif defined(__CYGWIN__) && defined(__X86_64__)
  37. return "Cygwin (64bit)";
  38. #elif defined(__WIN32__) && !defined(__X86_64__)
  39. return "Windows (32bit)";
  40. #elif defined(__WIN32__) && defined(__X86_64__)
  41. return "Windows (64bit)";
  42. #elif defined(__MACOSX__) && !defined(__X86_64__)
  43. return "Mac OS X (32bit)";
  44. #elif defined(__MACOSX__) && defined(__X86_64__)
  45. return "Mac OS X (64bit)";
  46. #elif defined(__UNIX__) && !defined(__X86_64__)
  47. return "Unix (32bit)";
  48. #elif defined(__UNIX__) && defined(__X86_64__)
  49. return "Unix (64bit)";
  50. #else
  51. return "Unknown";
  52. #endif
  53. }
  54. std::string getCompilerName()
  55. {
  56. #if defined(__INTEL_COMPILER)
  57. int icc_mayor = __INTEL_COMPILER / 100 % 100;
  58. int icc_minor = __INTEL_COMPILER % 100;
  59. std::string version = "Intel Compiler ";
  60. version += toString(icc_mayor);
  61. version += "." + toString(icc_minor);
  62. #if defined(__INTEL_COMPILER_UPDATE)
  63. version += "." + toString(__INTEL_COMPILER_UPDATE);
  64. #endif
  65. return version;
  66. #elif defined(__clang__)
  67. return "CLANG " __clang_version__;
  68. #elif defined (__GNUC__)
  69. return "GCC " __VERSION__;
  70. #elif defined(_MSC_VER)
  71. std::string version = toString(_MSC_FULL_VER);
  72. version.insert(4,".");
  73. version.insert(9,".");
  74. version.insert(2,".");
  75. return "Visual C++ Compiler " + version;
  76. #else
  77. return "Unknown Compiler";
  78. #endif
  79. }
  80. std::string getCPUVendor()
  81. {
  82. int cpuinfo[4];
  83. __cpuid (cpuinfo, 0);
  84. int name[4];
  85. name[0] = cpuinfo[1];
  86. name[1] = cpuinfo[3];
  87. name[2] = cpuinfo[2];
  88. name[3] = 0;
  89. return (char*)name;
  90. }
  91. CPUModel getCPUModel()
  92. {
  93. int out[4];
  94. __cpuid(out, 0);
  95. if (out[0] < 1) return CPU_UNKNOWN;
  96. __cpuid(out, 1);
  97. int family = ((out[0] >> 8) & 0x0F) + ((out[0] >> 20) & 0xFF);
  98. int model = ((out[0] >> 4) & 0x0F) | ((out[0] >> 12) & 0xF0);
  99. if (family == 11) return CPU_KNC;
  100. if (family != 6) return CPU_UNKNOWN; // earlier than P6
  101. if (model == 0x0E) return CPU_CORE1; // Core 1
  102. if (model == 0x0F) return CPU_CORE2; // Core 2, 65 nm
  103. if (model == 0x16) return CPU_CORE2; // Core 2, 65 nm Celeron
  104. if (model == 0x17) return CPU_CORE2; // Core 2, 45 nm
  105. if (model == 0x1A) return CPU_CORE_NEHALEM; // Core i7, Nehalem
  106. if (model == 0x1E) return CPU_CORE_NEHALEM; // Core i7
  107. if (model == 0x1F) return CPU_CORE_NEHALEM; // Core i7
  108. if (model == 0x2C) return CPU_CORE_NEHALEM; // Core i7, Xeon
  109. if (model == 0x2E) return CPU_CORE_NEHALEM; // Core i7, Xeon
  110. if (model == 0x2A) return CPU_CORE_SANDYBRIDGE; // Core i7, SandyBridge
  111. if (model == 0x2D) return CPU_CORE_SANDYBRIDGE; // Core i7, SandyBridge
  112. if (model == 0x45) return CPU_HASWELL; // Haswell
  113. if (model == 0x3C) return CPU_HASWELL; // Haswell
  114. return CPU_UNKNOWN;
  115. }
  116. std::string stringOfCPUModel(CPUModel model)
  117. {
  118. switch (model) {
  119. case CPU_KNC : return "Knights Corner";
  120. case CPU_CORE1 : return "Core1";
  121. case CPU_CORE2 : return "Core2";
  122. case CPU_CORE_NEHALEM : return "Nehalem";
  123. case CPU_CORE_SANDYBRIDGE: return "SandyBridge";
  124. case CPU_HASWELL : return "Haswell";
  125. default : return "Unknown CPU";
  126. }
  127. }
  128. /* constants to access destination registers of CPUID instruction */
  129. static const int EAX = 0;
  130. static const int EBX = 1;
  131. static const int ECX = 2;
  132. static const int EDX = 3;
  133. /* cpuid[eax=1].ecx */
  134. static const int CPU_FEATURE_BIT_SSE3 = 1 << 0;
  135. static const int CPU_FEATURE_BIT_SSSE3 = 1 << 9;
  136. static const int CPU_FEATURE_BIT_FMA3 = 1 << 12;
  137. static const int CPU_FEATURE_BIT_SSE4_1 = 1 << 19;
  138. static const int CPU_FEATURE_BIT_SSE4_2 = 1 << 20;
  139. //static const int CPU_FEATURE_BIT_MOVBE = 1 << 22;
  140. static const int CPU_FEATURE_BIT_POPCNT = 1 << 23;
  141. //static const int CPU_FEATURE_BIT_XSAVE = 1 << 26;
  142. static const int CPU_FEATURE_BIT_OXSAVE = 1 << 27;
  143. static const int CPU_FEATURE_BIT_AVX = 1 << 28;
  144. static const int CPU_FEATURE_BIT_F16C = 1 << 29;
  145. static const int CPU_FEATURE_BIT_RDRAND = 1 << 30;
  146. /* cpuid[eax=1].edx */
  147. static const int CPU_FEATURE_BIT_SSE = 1 << 25;
  148. static const int CPU_FEATURE_BIT_SSE2 = 1 << 26;
  149. /* cpuid[eax=0x80000001].ecx */
  150. static const int CPU_FEATURE_BIT_LZCNT = 1 << 5;
  151. /* cpuid[eax=7,ecx=0].ebx */
  152. static const int CPU_FEATURE_BIT_BMI1 = 1 << 3;
  153. static const int CPU_FEATURE_BIT_AVX2 = 1 << 5;
  154. static const int CPU_FEATURE_BIT_BMI2 = 1 << 8;
  155. static const int CPU_FEATURE_BIT_AVX512F = 1 << 16; // AVX512F (foundation)
  156. static const int CPU_FEATURE_BIT_AVX512DQ = 1 << 17; // AVX512DQ (doubleword and quadword instructions)
  157. static const int CPU_FEATURE_BIT_AVX512PF = 1 << 26; // AVX512PF (prefetch gather/scatter instructions)
  158. static const int CPU_FEATURE_BIT_AVX512ER = 1 << 27; // AVX512ER (exponential and reciprocal instructions)
  159. static const int CPU_FEATURE_BIT_AVX512CD = 1 << 28; // AVX512CD (conflict detection instructions)
  160. static const int CPU_FEATURE_BIT_AVX512BW = 1 << 30; // AVX512BW (byte and word instructions)
  161. static const int CPU_FEATURE_BIT_AVX512VL = 1 << 31; // AVX512VL (vector length extensions)
  162. static const int CPU_FEATURE_BIT_AVX512IFMA = 1 << 21; // AVX512IFMA (integer fused multiple-add instructions)
  163. /* cpuid[eax=7,ecx=0].ecx */
  164. static const int CPU_FEATURE_BIT_AVX512VBMI = 1 << 1; // AVX512VBMI (vector bit manipulation instructions)
  165. __noinline int64_t get_xcr0()
  166. {
  167. #if defined (__WIN32__)
  168. int64_t xcr0 = 0; // int64_t is workaround for compiler bug under VS2013, Win32
  169. #if defined(__INTEL_COMPILER)
  170. xcr0 = _xgetbv(0);
  171. #elif (defined(_MSC_VER) && (_MSC_FULL_VER >= 160040219)) // min VS2010 SP1 compiler is required
  172. xcr0 = _xgetbv(0);
  173. #else
  174. #pragma message ("WARNING: AVX not supported by your compiler.")
  175. xcr0 = 0;
  176. #endif
  177. return xcr0;
  178. #else
  179. int xcr0 = 0;
  180. #if defined(__INTEL_COMPILER)
  181. __asm__ ("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx" );
  182. #elif ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) && (!defined(__MACOSX__) || defined(__TARGET_AVX__) || defined(__TARGET_AVX2__))
  183. __asm__ ("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx" );
  184. #elif ((__clang_major__ > 3) || (__clang_major__ == 3 && __clang_minor__ >= 1))
  185. __asm__ ("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx" );
  186. #else
  187. #pragma message ("WARNING: AVX not supported by your compiler.")
  188. xcr0 = 0;
  189. #endif
  190. return xcr0;
  191. #endif
  192. }
  193. int getCPUFeatures()
  194. {
  195. /* cache CPU features access */
  196. static int cpu_features = 0;
  197. if (cpu_features)
  198. return cpu_features;
  199. /* get number of CPUID leaves */
  200. int cpuid_leaf0[4];
  201. __cpuid(cpuid_leaf0, 0x00000000);
  202. unsigned nIds = cpuid_leaf0[EAX];
  203. /* get number of extended CPUID leaves */
  204. int cpuid_leafe[4];
  205. __cpuid(cpuid_leafe, 0x80000000);
  206. unsigned nExIds = cpuid_leafe[EAX];
  207. /* get CPUID leaves for EAX = 1,7, and 0x80000001 */
  208. int cpuid_leaf_1[4] = { 0,0,0,0 };
  209. int cpuid_leaf_7[4] = { 0,0,0,0 };
  210. int cpuid_leaf_e1[4] = { 0,0,0,0 };
  211. if (nIds >= 1) __cpuid (cpuid_leaf_1,0x00000001);
  212. #if _WIN32
  213. #if _MSC_VER && (_MSC_FULL_VER < 160040219)
  214. #else
  215. if (nIds >= 7) __cpuidex(cpuid_leaf_7,0x00000007,0);
  216. #endif
  217. #else
  218. if (nIds >= 7) __cpuid_count(cpuid_leaf_7,0x00000007,0);
  219. #endif
  220. if (nExIds >= 0x80000001) __cpuid(cpuid_leaf_e1,0x80000001);
  221. /* detect if OS saves XMM, YMM, and ZMM states */
  222. bool xmm_enabled = true;
  223. bool ymm_enabled = false;
  224. bool zmm_enabled = false;
  225. if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_OXSAVE) {
  226. int64_t xcr0 = get_xcr0();
  227. xmm_enabled = ((xcr0 & 0x02) == 0x02); /* checks if xmm are enabled in XCR0 */
  228. ymm_enabled = xmm_enabled && ((xcr0 & 0x04) == 0x04); /* checks if ymm state are enabled in XCR0 */
  229. zmm_enabled = ymm_enabled && ((xcr0 & 0xE0) == 0xE0); /* checks if OPMASK state, upper 256-bit of ZMM0-ZMM15 and ZMM16-ZMM31 state are enabled in XCR0 */
  230. }
  231. if (xmm_enabled && cpuid_leaf_1[EDX] & CPU_FEATURE_BIT_SSE ) cpu_features |= CPU_FEATURE_SSE;
  232. if (xmm_enabled && cpuid_leaf_1[EDX] & CPU_FEATURE_BIT_SSE2 ) cpu_features |= CPU_FEATURE_SSE2;
  233. if (xmm_enabled && cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSE3 ) cpu_features |= CPU_FEATURE_SSE3;
  234. if (xmm_enabled && cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSSE3 ) cpu_features |= CPU_FEATURE_SSSE3;
  235. if (xmm_enabled && cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSE4_1) cpu_features |= CPU_FEATURE_SSE41;
  236. if (xmm_enabled && cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSE4_2) cpu_features |= CPU_FEATURE_SSE42;
  237. if ( cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_POPCNT) cpu_features |= CPU_FEATURE_POPCNT;
  238. if (ymm_enabled && cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_AVX ) cpu_features |= CPU_FEATURE_AVX;
  239. if (xmm_enabled && cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_F16C ) cpu_features |= CPU_FEATURE_F16C;
  240. if ( cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_RDRAND) cpu_features |= CPU_FEATURE_RDRAND;
  241. if (ymm_enabled && cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX2 ) cpu_features |= CPU_FEATURE_AVX2;
  242. if (ymm_enabled && cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_FMA3 ) cpu_features |= CPU_FEATURE_FMA3;
  243. if (cpuid_leaf_e1[ECX] & CPU_FEATURE_BIT_LZCNT) cpu_features |= CPU_FEATURE_LZCNT;
  244. if (cpuid_leaf_7 [EBX] & CPU_FEATURE_BIT_BMI1 ) cpu_features |= CPU_FEATURE_BMI1;
  245. if (cpuid_leaf_7 [EBX] & CPU_FEATURE_BIT_BMI2 ) cpu_features |= CPU_FEATURE_BMI2;
  246. if (zmm_enabled && cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512F ) cpu_features |= CPU_FEATURE_AVX512F;
  247. if (zmm_enabled && cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512DQ ) cpu_features |= CPU_FEATURE_AVX512DQ;
  248. if (zmm_enabled && cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512PF ) cpu_features |= CPU_FEATURE_AVX512PF;
  249. if (zmm_enabled && cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512ER ) cpu_features |= CPU_FEATURE_AVX512ER;
  250. if (zmm_enabled && cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512CD ) cpu_features |= CPU_FEATURE_AVX512CD;
  251. if (zmm_enabled && cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512BW ) cpu_features |= CPU_FEATURE_AVX512BW;
  252. if (zmm_enabled && cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512IFMA) cpu_features |= CPU_FEATURE_AVX512IFMA;
  253. if (zmm_enabled && cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512VL ) cpu_features |= CPU_FEATURE_AVX512VL;
  254. if (zmm_enabled && cpuid_leaf_7[ECX] & CPU_FEATURE_BIT_AVX512VBMI) cpu_features |= CPU_FEATURE_AVX512VBMI;
  255. return cpu_features;
  256. }
  257. std::string stringOfCPUFeatures(int features)
  258. {
  259. std::string str;
  260. if (features & CPU_FEATURE_SSE ) str += "SSE ";
  261. if (features & CPU_FEATURE_SSE2 ) str += "SSE2 ";
  262. if (features & CPU_FEATURE_SSE3 ) str += "SSE3 ";
  263. if (features & CPU_FEATURE_SSSE3 ) str += "SSSE3 ";
  264. if (features & CPU_FEATURE_SSE41 ) str += "SSE4.1 ";
  265. if (features & CPU_FEATURE_SSE42 ) str += "SSE4.2 ";
  266. if (features & CPU_FEATURE_POPCNT) str += "POPCNT ";
  267. if (features & CPU_FEATURE_AVX ) str += "AVX ";
  268. if (features & CPU_FEATURE_F16C ) str += "F16C ";
  269. if (features & CPU_FEATURE_RDRAND) str += "RDRAND ";
  270. if (features & CPU_FEATURE_AVX2 ) str += "AVX2 ";
  271. if (features & CPU_FEATURE_FMA3 ) str += "FMA3 ";
  272. if (features & CPU_FEATURE_LZCNT ) str += "LZCNT ";
  273. if (features & CPU_FEATURE_BMI1 ) str += "BMI1 ";
  274. if (features & CPU_FEATURE_BMI2 ) str += "BMI2 ";
  275. if (features & CPU_FEATURE_KNC ) str += "KNC ";
  276. if (features & CPU_FEATURE_AVX512F) str += "AVX512F ";
  277. if (features & CPU_FEATURE_AVX512DQ) str += "AVX512DQ ";
  278. if (features & CPU_FEATURE_AVX512PF) str += "AVX512PF ";
  279. if (features & CPU_FEATURE_AVX512ER) str += "AVX512ER ";
  280. if (features & CPU_FEATURE_AVX512CD) str += "AVX512CD ";
  281. if (features & CPU_FEATURE_AVX512BW) str += "AVX512BW ";
  282. if (features & CPU_FEATURE_AVX512VL) str += "AVX512VL ";
  283. if (features & CPU_FEATURE_AVX512IFMA) str += "AVX512IFMA ";
  284. if (features & CPU_FEATURE_AVX512VBMI) str += "AVX512VBMI ";
  285. return str;
  286. }
  287. std::string stringOfISA (int isa)
  288. {
  289. if (isa == SSE) return "SSE";
  290. if (isa == SSE2) return "SSE2";
  291. if (isa == SSE3) return "SSE3";
  292. if (isa == SSSE3) return "SSSE3";
  293. if (isa == SSE41) return "SSE4.1";
  294. if (isa == SSE42) return "SSE4.2";
  295. if (isa == AVX) return "AVX";
  296. if (isa == AVX2) return "AVX2";
  297. if (isa == AVX512KNL) return "AVX512KNL";
  298. if (isa == AVX512SKX) return "AVX512SKX";
  299. if (isa == KNC) return "KNC";
  300. return "UNKNOWN";
  301. }
  302. bool hasISA(int features, int isa) {
  303. return (features & isa) == isa;
  304. }
  305. std::string supportedTargetList (int features)
  306. {
  307. std::string v;
  308. if (hasISA(features,SSE)) v += "SSE ";
  309. if (hasISA(features,SSE2)) v += "SSE2 ";
  310. if (hasISA(features,SSE3)) v += "SSE3 ";
  311. if (hasISA(features,SSSE3)) v += "SSSE3 ";
  312. if (hasISA(features,SSE41)) v += "SSE4.1 ";
  313. if (hasISA(features,SSE42)) v += "SSE4.2 ";
  314. if (hasISA(features,AVX)) v += "AVX ";
  315. if (hasISA(features,AVXI)) v += "AVXI ";
  316. if (hasISA(features,AVX2)) v += "AVX2 ";
  317. if (hasISA(features,AVX512KNL)) v += "AVX512KNL ";
  318. if (hasISA(features,AVX512SKX)) v += "AVX512SKX ";
  319. if (hasISA(features,KNC)) v += "KNC ";
  320. return v;
  321. }
  322. }
  323. ////////////////////////////////////////////////////////////////////////////////
  324. /// Windows Platform
  325. ////////////////////////////////////////////////////////////////////////////////
  326. #if defined(__WIN32__)
  327. #define WIN32_LEAN_AND_MEAN
  328. #include <windows.h>
  329. namespace embree
  330. {
  331. std::string getExecutableFileName() {
  332. char filename[1024];
  333. if (!GetModuleFileName(nullptr, filename, sizeof(filename))) return std::string();
  334. return std::string(filename);
  335. }
  336. unsigned int getNumberOfLogicalThreads()
  337. {
  338. static int nThreads = -1;
  339. if (nThreads != -1) return nThreads;
  340. typedef WORD (WINAPI *GetActiveProcessorGroupCountFunc)();
  341. typedef DWORD (WINAPI *GetActiveProcessorCountFunc)(WORD);
  342. HMODULE hlib = LoadLibrary("Kernel32");
  343. GetActiveProcessorGroupCountFunc pGetActiveProcessorGroupCount = (GetActiveProcessorGroupCountFunc)GetProcAddress(hlib, "GetActiveProcessorGroupCount");
  344. GetActiveProcessorCountFunc pGetActiveProcessorCount = (GetActiveProcessorCountFunc) GetProcAddress(hlib, "GetActiveProcessorCount");
  345. if (pGetActiveProcessorGroupCount && pGetActiveProcessorCount)
  346. {
  347. int groups = pGetActiveProcessorGroupCount();
  348. int totalProcessors = 0;
  349. for (int i = 0; i < groups; i++)
  350. totalProcessors += pGetActiveProcessorCount(i);
  351. nThreads = totalProcessors;
  352. }
  353. else
  354. {
  355. SYSTEM_INFO sysinfo;
  356. GetSystemInfo(&sysinfo);
  357. nThreads = sysinfo.dwNumberOfProcessors;
  358. }
  359. assert(nThreads);
  360. return nThreads;
  361. }
  362. int getTerminalWidth()
  363. {
  364. HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
  365. if (handle == INVALID_HANDLE_VALUE) return 80;
  366. CONSOLE_SCREEN_BUFFER_INFO info;
  367. memset(&info,0,sizeof(info));
  368. GetConsoleScreenBufferInfo(handle, &info);
  369. return info.dwSize.X;
  370. }
  371. double getSeconds()
  372. {
  373. LARGE_INTEGER freq, val;
  374. QueryPerformanceFrequency(&freq);
  375. QueryPerformanceCounter(&val);
  376. return (double)val.QuadPart / (double)freq.QuadPart;
  377. }
  378. void sleepSeconds(double t) {
  379. Sleep(DWORD(1000.0*t));
  380. }
  381. }
  382. #endif
  383. ////////////////////////////////////////////////////////////////////////////////
  384. /// Linux Platform
  385. ////////////////////////////////////////////////////////////////////////////////
  386. #if defined(__LINUX__)
  387. #include <stdio.h>
  388. #include <unistd.h>
  389. namespace embree
  390. {
  391. std::string getExecutableFileName()
  392. {
  393. char pid[32]; sprintf(pid, "/proc/%d/exe", getpid());
  394. char buf[1024];
  395. int bytes = readlink(pid, buf, sizeof(buf)-1);
  396. if (bytes != -1) buf[bytes] = '\0';
  397. return std::string(buf);
  398. }
  399. }
  400. #endif
  401. ////////////////////////////////////////////////////////////////////////////////
  402. /// FreeBSD Platform
  403. ////////////////////////////////////////////////////////////////////////////////
  404. #if defined (__FreeBSD__)
  405. #include <sys/sysctl.h>
  406. namespace embree
  407. {
  408. std::string getExecutableFileName()
  409. {
  410. const int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
  411. char buf[1024];
  412. size_t len = sizeof(buf);
  413. if (sysctl(mib, 4, buf, &len, 0x0, 0) == -1) *buf = '\0';
  414. return std::string(buf);
  415. }
  416. }
  417. #endif
  418. ////////////////////////////////////////////////////////////////////////////////
  419. /// Mac OS X Platform
  420. ////////////////////////////////////////////////////////////////////////////////
  421. #if defined(__MACOSX__)
  422. #include <mach-o/dyld.h>
  423. namespace embree
  424. {
  425. std::string getExecutableFileName()
  426. {
  427. char buf[1024];
  428. uint32_t size = sizeof(buf);
  429. if (_NSGetExecutablePath(buf, &size) != 0) return std::string();
  430. return std::string(buf);
  431. }
  432. }
  433. #endif
  434. ////////////////////////////////////////////////////////////////////////////////
  435. /// Unix Platform
  436. ////////////////////////////////////////////////////////////////////////////////
  437. #if defined(__UNIX__)
  438. #include <unistd.h>
  439. #include <sys/ioctl.h>
  440. #include <sys/time.h>
  441. namespace embree
  442. {
  443. unsigned int getNumberOfLogicalThreads()
  444. {
  445. static int nThreads = -1;
  446. if (nThreads == -1) nThreads = sysconf(_SC_NPROCESSORS_CONF);
  447. assert(nThreads);
  448. return nThreads;
  449. }
  450. int getTerminalWidth()
  451. {
  452. struct winsize info;
  453. if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &info) < 0) return 80;
  454. return info.ws_col;
  455. }
  456. double getSeconds() {
  457. struct timeval tp; gettimeofday(&tp,nullptr);
  458. return double(tp.tv_sec) + double(tp.tv_usec)/1E6;
  459. }
  460. void sleepSeconds(double t) {
  461. usleep(1000000.0*t);
  462. }
  463. }
  464. #endif