1// Copyright 2009-2021 Intel Corporation
2// SPDX-License-Identifier: Apache-2.0
3
4#include "sysinfo.h"
5#include "intrinsics.h"
6#include "string.h"
7#include "ref.h"
8#if defined(__FREEBSD__)
9#include <sys/cpuset.h>
10#include <pthread_np.h>
11typedef cpuset_t cpu_set_t;
12#endif
13
14////////////////////////////////////////////////////////////////////////////////
15/// All Platforms
16////////////////////////////////////////////////////////////////////////////////
17
18namespace embree
19{
20 NullTy null;
21
22 std::string getPlatformName()
23 {
24#if defined(__ANDROID__) && !defined(__64BIT__)
25 return "Android (32bit)";
26#elif defined(__ANDROID__) && defined(__64BIT__)
27 return "Android (64bit)";
28#elif defined(__LINUX__) && !defined(__64BIT__)
29 return "Linux (32bit)";
30#elif defined(__LINUX__) && defined(__64BIT__)
31 return "Linux (64bit)";
32#elif defined(__FREEBSD__) && !defined(__64BIT__)
33 return "FreeBSD (32bit)";
34#elif defined(__FREEBSD__) && defined(__64BIT__)
35 return "FreeBSD (64bit)";
36#elif defined(__CYGWIN__) && !defined(__64BIT__)
37 return "Cygwin (32bit)";
38#elif defined(__CYGWIN__) && defined(__64BIT__)
39 return "Cygwin (64bit)";
40#elif defined(__WIN32__) && !defined(__64BIT__)
41 return "Windows (32bit)";
42#elif defined(__WIN32__) && defined(__64BIT__)
43 return "Windows (64bit)";
44#elif defined(__MACOSX__) && !defined(__64BIT__)
45 return "Mac OS X (32bit)";
46#elif defined(__MACOSX__) && defined(__64BIT__)
47 return "Mac OS X (64bit)";
48#elif defined(__UNIX__) && !defined(__64BIT__)
49 return "Unix (32bit)";
50#elif defined(__UNIX__) && defined(__64BIT__)
51 return "Unix (64bit)";
52#else
53 return "Unknown";
54#endif
55 }
56
57 std::string getCompilerName()
58 {
59#if defined(__INTEL_COMPILER)
60 int icc_mayor = __INTEL_COMPILER / 100 % 100;
61 int icc_minor = __INTEL_COMPILER % 100;
62 std::string version = "Intel Compiler ";
63 version += toString(icc_mayor);
64 version += "." + toString(icc_minor);
65#if defined(__INTEL_COMPILER_UPDATE)
66 version += "." + toString(__INTEL_COMPILER_UPDATE);
67#endif
68 return version;
69#elif defined(__clang__)
70 return "CLANG " __clang_version__;
71#elif defined (__GNUC__)
72 return "GCC " __VERSION__;
73#elif defined(_MSC_VER)
74 std::string version = toString(_MSC_FULL_VER);
75 version.insert(4,".");
76 version.insert(9,".");
77 version.insert(2,".");
78 return "Visual C++ Compiler " + version;
79#else
80 return "Unknown Compiler";
81#endif
82 }
83
84 std::string getCPUVendor()
85 {
86#if defined(__X86_ASM__)
87 int cpuinfo[4];
88 __cpuid (out: cpuinfo, op: 0);
89 int name[4];
90 name[0] = cpuinfo[1];
91 name[1] = cpuinfo[3];
92 name[2] = cpuinfo[2];
93 name[3] = 0;
94 return (char*)name;
95#elif defined(__ARM_NEON)
96 return "ARM";
97#else
98 return "Unknown";
99#endif
100 }
101
102 CPU getCPUModel()
103 {
104#if defined(__X86_ASM__)
105 if (getCPUVendor() != "GenuineIntel")
106 return CPU::UNKNOWN;
107
108 int out[4];
109 __cpuid(out, op: 0);
110 if (out[0] < 1) return CPU::UNKNOWN;
111 __cpuid(out, op: 1);
112
113 /* please see CPUID documentation for these formulas */
114 uint32_t family_ID = (out[0] >> 8) & 0x0F;
115 uint32_t extended_family_ID = (out[0] >> 20) & 0xFF;
116
117 uint32_t model_ID = (out[0] >> 4) & 0x0F;
118 uint32_t extended_model_ID = (out[0] >> 16) & 0x0F;
119
120 uint32_t DisplayFamily = family_ID;
121 if (family_ID == 0x0F)
122 DisplayFamily += extended_family_ID;
123
124 uint32_t DisplayModel = model_ID;
125 if (family_ID == 0x06 || family_ID == 0x0F)
126 DisplayModel += extended_model_ID << 4;
127
128 uint32_t DisplayFamily_DisplayModel = (DisplayFamily << 8) + (DisplayModel << 0);
129
130 // Data from IntelĀ® 64 and IA-32 Architectures, Volume 4, Chapter 2, Table 2-1 (CPUID Signature Values of DisplayFamily_DisplayModel)
131 if (DisplayFamily_DisplayModel == 0x067D) return CPU::CORE_ICE_LAKE;
132 if (DisplayFamily_DisplayModel == 0x067E) return CPU::CORE_ICE_LAKE;
133 if (DisplayFamily_DisplayModel == 0x068C) return CPU::CORE_TIGER_LAKE;
134 if (DisplayFamily_DisplayModel == 0x06A5) return CPU::CORE_COMET_LAKE;
135 if (DisplayFamily_DisplayModel == 0x06A6) return CPU::CORE_COMET_LAKE;
136 if (DisplayFamily_DisplayModel == 0x0666) return CPU::CORE_CANNON_LAKE;
137 if (DisplayFamily_DisplayModel == 0x068E) return CPU::CORE_KABY_LAKE;
138 if (DisplayFamily_DisplayModel == 0x069E) return CPU::CORE_KABY_LAKE;
139 if (DisplayFamily_DisplayModel == 0x066A) return CPU::XEON_ICE_LAKE;
140 if (DisplayFamily_DisplayModel == 0x066C) return CPU::XEON_ICE_LAKE;
141 if (DisplayFamily_DisplayModel == 0x0655) return CPU::XEON_SKY_LAKE;
142 if (DisplayFamily_DisplayModel == 0x064E) return CPU::CORE_SKY_LAKE;
143 if (DisplayFamily_DisplayModel == 0x065E) return CPU::CORE_SKY_LAKE;
144 if (DisplayFamily_DisplayModel == 0x0656) return CPU::XEON_BROADWELL;
145 if (DisplayFamily_DisplayModel == 0x064F) return CPU::XEON_BROADWELL;
146 if (DisplayFamily_DisplayModel == 0x0647) return CPU::CORE_BROADWELL;
147 if (DisplayFamily_DisplayModel == 0x063D) return CPU::CORE_BROADWELL;
148 if (DisplayFamily_DisplayModel == 0x063F) return CPU::XEON_HASWELL;
149 if (DisplayFamily_DisplayModel == 0x063C) return CPU::CORE_HASWELL;
150 if (DisplayFamily_DisplayModel == 0x0645) return CPU::CORE_HASWELL;
151 if (DisplayFamily_DisplayModel == 0x0646) return CPU::CORE_HASWELL;
152 if (DisplayFamily_DisplayModel == 0x063E) return CPU::XEON_IVY_BRIDGE;
153 if (DisplayFamily_DisplayModel == 0x063A) return CPU::CORE_IVY_BRIDGE;
154 if (DisplayFamily_DisplayModel == 0x062D) return CPU::SANDY_BRIDGE;
155 if (DisplayFamily_DisplayModel == 0x062F) return CPU::SANDY_BRIDGE;
156 if (DisplayFamily_DisplayModel == 0x062A) return CPU::SANDY_BRIDGE;
157 if (DisplayFamily_DisplayModel == 0x062E) return CPU::NEHALEM;
158 if (DisplayFamily_DisplayModel == 0x0625) return CPU::NEHALEM;
159 if (DisplayFamily_DisplayModel == 0x062C) return CPU::NEHALEM;
160 if (DisplayFamily_DisplayModel == 0x061E) return CPU::NEHALEM;
161 if (DisplayFamily_DisplayModel == 0x061F) return CPU::NEHALEM;
162 if (DisplayFamily_DisplayModel == 0x061A) return CPU::NEHALEM;
163 if (DisplayFamily_DisplayModel == 0x061D) return CPU::NEHALEM;
164 if (DisplayFamily_DisplayModel == 0x0617) return CPU::CORE2;
165 if (DisplayFamily_DisplayModel == 0x060F) return CPU::CORE2;
166 if (DisplayFamily_DisplayModel == 0x060E) return CPU::CORE1;
167
168 if (DisplayFamily_DisplayModel == 0x0685) return CPU::XEON_PHI_KNIGHTS_MILL;
169 if (DisplayFamily_DisplayModel == 0x0657) return CPU::XEON_PHI_KNIGHTS_LANDING;
170
171#elif defined(__ARM_NEON)
172 return CPU::ARM;
173#endif
174
175 return CPU::UNKNOWN;
176 }
177
178 std::string stringOfCPUModel(CPU model)
179 {
180 switch (model) {
181 case CPU::XEON_ICE_LAKE : return "Xeon Ice Lake";
182 case CPU::CORE_ICE_LAKE : return "Core Ice Lake";
183 case CPU::CORE_TIGER_LAKE : return "Core Tiger Lake";
184 case CPU::CORE_COMET_LAKE : return "Core Comet Lake";
185 case CPU::CORE_CANNON_LAKE : return "Core Cannon Lake";
186 case CPU::CORE_KABY_LAKE : return "Core Kaby Lake";
187 case CPU::XEON_SKY_LAKE : return "Xeon Sky Lake";
188 case CPU::CORE_SKY_LAKE : return "Core Sky Lake";
189 case CPU::XEON_PHI_KNIGHTS_MILL : return "Xeon Phi Knights Mill";
190 case CPU::XEON_PHI_KNIGHTS_LANDING: return "Xeon Phi Knights Landing";
191 case CPU::XEON_BROADWELL : return "Xeon Broadwell";
192 case CPU::CORE_BROADWELL : return "Core Broadwell";
193 case CPU::XEON_HASWELL : return "Xeon Haswell";
194 case CPU::CORE_HASWELL : return "Core Haswell";
195 case CPU::XEON_IVY_BRIDGE : return "Xeon Ivy Bridge";
196 case CPU::CORE_IVY_BRIDGE : return "Core Ivy Bridge";
197 case CPU::SANDY_BRIDGE : return "Sandy Bridge";
198 case CPU::NEHALEM : return "Nehalem";
199 case CPU::CORE2 : return "Core2";
200 case CPU::CORE1 : return "Core";
201 case CPU::ARM : return "ARM";
202 case CPU::UNKNOWN : return "Unknown CPU";
203 }
204 return "Unknown CPU (error)";
205 }
206
207#if defined(__X86_ASM__)
208 /* constants to access destination registers of CPUID instruction */
209 static const int EAX = 0;
210 static const int EBX = 1;
211 static const int ECX = 2;
212 static const int EDX = 3;
213
214 /* cpuid[eax=1].ecx */
215 static const int CPU_FEATURE_BIT_SSE3 = 1 << 0;
216 static const int CPU_FEATURE_BIT_SSSE3 = 1 << 9;
217 static const int CPU_FEATURE_BIT_FMA3 = 1 << 12;
218 static const int CPU_FEATURE_BIT_SSE4_1 = 1 << 19;
219 static const int CPU_FEATURE_BIT_SSE4_2 = 1 << 20;
220 //static const int CPU_FEATURE_BIT_MOVBE = 1 << 22;
221 static const int CPU_FEATURE_BIT_POPCNT = 1 << 23;
222 //static const int CPU_FEATURE_BIT_XSAVE = 1 << 26;
223 static const int CPU_FEATURE_BIT_OXSAVE = 1 << 27;
224 static const int CPU_FEATURE_BIT_AVX = 1 << 28;
225 static const int CPU_FEATURE_BIT_F16C = 1 << 29;
226 static const int CPU_FEATURE_BIT_RDRAND = 1 << 30;
227
228 /* cpuid[eax=1].edx */
229 static const int CPU_FEATURE_BIT_SSE = 1 << 25;
230 static const int CPU_FEATURE_BIT_SSE2 = 1 << 26;
231
232 /* cpuid[eax=0x80000001].ecx */
233 static const int CPU_FEATURE_BIT_LZCNT = 1 << 5;
234
235 /* cpuid[eax=7,ecx=0].ebx */
236 static const int CPU_FEATURE_BIT_BMI1 = 1 << 3;
237 static const int CPU_FEATURE_BIT_AVX2 = 1 << 5;
238 static const int CPU_FEATURE_BIT_BMI2 = 1 << 8;
239 static const int CPU_FEATURE_BIT_AVX512F = 1 << 16; // AVX512F (foundation)
240 static const int CPU_FEATURE_BIT_AVX512DQ = 1 << 17; // AVX512DQ (doubleword and quadword instructions)
241 static const int CPU_FEATURE_BIT_AVX512PF = 1 << 26; // AVX512PF (prefetch gather/scatter instructions)
242 static const int CPU_FEATURE_BIT_AVX512ER = 1 << 27; // AVX512ER (exponential and reciprocal instructions)
243 static const int CPU_FEATURE_BIT_AVX512CD = 1 << 28; // AVX512CD (conflict detection instructions)
244 static const int CPU_FEATURE_BIT_AVX512BW = 1 << 30; // AVX512BW (byte and word instructions)
245 static const int CPU_FEATURE_BIT_AVX512VL = 1 << 31; // AVX512VL (vector length extensions)
246 static const int CPU_FEATURE_BIT_AVX512IFMA = 1 << 21; // AVX512IFMA (integer fused multiple-add instructions)
247
248 /* cpuid[eax=7,ecx=0].ecx */
249 static const int CPU_FEATURE_BIT_AVX512VBMI = 1 << 1; // AVX512VBMI (vector bit manipulation instructions)
250#endif
251
252#if defined(__X86_ASM__)
253 __noinline int64_t get_xcr0()
254 {
255#if defined (__WIN32__) && !defined (__MINGW32__)
256 int64_t xcr0 = 0; // int64_t is workaround for compiler bug under VS2013, Win32
257 xcr0 = _xgetbv(0);
258 return xcr0;
259#else
260 int xcr0 = 0;
261 __asm__ ("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx" );
262 return xcr0;
263#endif
264 }
265#endif
266
267 int getCPUFeatures()
268 {
269#if defined(__X86_ASM__)
270 /* cache CPU features access */
271 static int cpu_features = 0;
272 if (cpu_features)
273 return cpu_features;
274
275 /* get number of CPUID leaves */
276 int cpuid_leaf0[4];
277 __cpuid(out: cpuid_leaf0, op: 0x00000000);
278 unsigned nIds = cpuid_leaf0[EAX];
279
280 /* get number of extended CPUID leaves */
281 int cpuid_leafe[4];
282 __cpuid(out: cpuid_leafe, op: 0x80000000);
283 unsigned nExIds = cpuid_leafe[EAX];
284
285 /* get CPUID leaves for EAX = 1,7, and 0x80000001 */
286 int cpuid_leaf_1[4] = { 0,0,0,0 };
287 int cpuid_leaf_7[4] = { 0,0,0,0 };
288 int cpuid_leaf_e1[4] = { 0,0,0,0 };
289 if (nIds >= 1) __cpuid (out: cpuid_leaf_1,op: 0x00000001);
290#if _WIN32
291#if _MSC_VER && (_MSC_FULL_VER < 160040219)
292#else
293 if (nIds >= 7) __cpuidex(cpuid_leaf_7,0x00000007,0);
294#endif
295#else
296 if (nIds >= 7) __cpuid_count(out: cpuid_leaf_7,op1: 0x00000007,op2: 0);
297#endif
298 if (nExIds >= 0x80000001) __cpuid(out: cpuid_leaf_e1,op: 0x80000001);
299
300 /* detect if OS saves XMM, YMM, and ZMM states */
301 bool xmm_enabled = true;
302 bool ymm_enabled = false;
303 bool zmm_enabled = false;
304 if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_OXSAVE) {
305 int64_t xcr0 = get_xcr0();
306 xmm_enabled = ((xcr0 & 0x02) == 0x02); /* checks if xmm are enabled in XCR0 */
307 ymm_enabled = xmm_enabled && ((xcr0 & 0x04) == 0x04); /* checks if ymm state are enabled in XCR0 */
308 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 */
309 }
310 if (xmm_enabled) cpu_features |= CPU_FEATURE_XMM_ENABLED;
311 if (ymm_enabled) cpu_features |= CPU_FEATURE_YMM_ENABLED;
312 if (zmm_enabled) cpu_features |= CPU_FEATURE_ZMM_ENABLED;
313
314 if (cpuid_leaf_1[EDX] & CPU_FEATURE_BIT_SSE ) cpu_features |= CPU_FEATURE_SSE;
315 if (cpuid_leaf_1[EDX] & CPU_FEATURE_BIT_SSE2 ) cpu_features |= CPU_FEATURE_SSE2;
316 if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSE3 ) cpu_features |= CPU_FEATURE_SSE3;
317 if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSSE3 ) cpu_features |= CPU_FEATURE_SSSE3;
318 if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSE4_1) cpu_features |= CPU_FEATURE_SSE41;
319 if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSE4_2) cpu_features |= CPU_FEATURE_SSE42;
320 if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_POPCNT) cpu_features |= CPU_FEATURE_POPCNT;
321
322 if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_AVX ) cpu_features |= CPU_FEATURE_AVX;
323 if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_F16C ) cpu_features |= CPU_FEATURE_F16C;
324 if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_RDRAND) cpu_features |= CPU_FEATURE_RDRAND;
325 if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX2 ) cpu_features |= CPU_FEATURE_AVX2;
326 if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_FMA3 ) cpu_features |= CPU_FEATURE_FMA3;
327 if (cpuid_leaf_e1[ECX] & CPU_FEATURE_BIT_LZCNT) cpu_features |= CPU_FEATURE_LZCNT;
328 if (cpuid_leaf_7 [EBX] & CPU_FEATURE_BIT_BMI1 ) cpu_features |= CPU_FEATURE_BMI1;
329 if (cpuid_leaf_7 [EBX] & CPU_FEATURE_BIT_BMI2 ) cpu_features |= CPU_FEATURE_BMI2;
330
331 if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512F ) cpu_features |= CPU_FEATURE_AVX512F;
332 if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512DQ ) cpu_features |= CPU_FEATURE_AVX512DQ;
333 if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512PF ) cpu_features |= CPU_FEATURE_AVX512PF;
334 if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512ER ) cpu_features |= CPU_FEATURE_AVX512ER;
335 if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512CD ) cpu_features |= CPU_FEATURE_AVX512CD;
336 if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512BW ) cpu_features |= CPU_FEATURE_AVX512BW;
337 if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512IFMA) cpu_features |= CPU_FEATURE_AVX512IFMA;
338 if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512VL ) cpu_features |= CPU_FEATURE_AVX512VL;
339 if (cpuid_leaf_7[ECX] & CPU_FEATURE_BIT_AVX512VBMI) cpu_features |= CPU_FEATURE_AVX512VBMI;
340
341 return cpu_features;
342#elif defined(__ARM_NEON) || defined(__EMSCRIPTEN__)
343 /* emulated features with sse2neon */
344 return CPU_FEATURE_SSE|CPU_FEATURE_SSE2|CPU_FEATURE_XMM_ENABLED;
345#else
346 /* Unknown CPU. */
347 return 0;
348#endif
349 }
350
351 std::string stringOfCPUFeatures(int features)
352 {
353 std::string str;
354 if (features & CPU_FEATURE_XMM_ENABLED) str += "XMM ";
355 if (features & CPU_FEATURE_YMM_ENABLED) str += "YMM ";
356 if (features & CPU_FEATURE_ZMM_ENABLED) str += "ZMM ";
357 if (features & CPU_FEATURE_SSE ) str += "SSE ";
358 if (features & CPU_FEATURE_SSE2 ) str += "SSE2 ";
359 if (features & CPU_FEATURE_SSE3 ) str += "SSE3 ";
360 if (features & CPU_FEATURE_SSSE3 ) str += "SSSE3 ";
361 if (features & CPU_FEATURE_SSE41 ) str += "SSE4.1 ";
362 if (features & CPU_FEATURE_SSE42 ) str += "SSE4.2 ";
363 if (features & CPU_FEATURE_POPCNT) str += "POPCNT ";
364 if (features & CPU_FEATURE_AVX ) str += "AVX ";
365 if (features & CPU_FEATURE_F16C ) str += "F16C ";
366 if (features & CPU_FEATURE_RDRAND) str += "RDRAND ";
367 if (features & CPU_FEATURE_AVX2 ) str += "AVX2 ";
368 if (features & CPU_FEATURE_FMA3 ) str += "FMA3 ";
369 if (features & CPU_FEATURE_LZCNT ) str += "LZCNT ";
370 if (features & CPU_FEATURE_BMI1 ) str += "BMI1 ";
371 if (features & CPU_FEATURE_BMI2 ) str += "BMI2 ";
372 if (features & CPU_FEATURE_AVX512F) str += "AVX512F ";
373 if (features & CPU_FEATURE_AVX512DQ) str += "AVX512DQ ";
374 if (features & CPU_FEATURE_AVX512PF) str += "AVX512PF ";
375 if (features & CPU_FEATURE_AVX512ER) str += "AVX512ER ";
376 if (features & CPU_FEATURE_AVX512CD) str += "AVX512CD ";
377 if (features & CPU_FEATURE_AVX512BW) str += "AVX512BW ";
378 if (features & CPU_FEATURE_AVX512VL) str += "AVX512VL ";
379 if (features & CPU_FEATURE_AVX512IFMA) str += "AVX512IFMA ";
380 if (features & CPU_FEATURE_AVX512VBMI) str += "AVX512VBMI ";
381 return str;
382 }
383
384 std::string stringOfISA (int isa)
385 {
386 if (isa == SSE) return "SSE";
387 if (isa == SSE2) return "SSE2";
388 if (isa == SSE3) return "SSE3";
389 if (isa == SSSE3) return "SSSE3";
390 if (isa == SSE41) return "SSE4.1";
391 if (isa == SSE42) return "SSE4.2";
392 if (isa == AVX) return "AVX";
393 if (isa == AVX2) return "AVX2";
394 if (isa == AVX512) return "AVX512";
395 return "UNKNOWN";
396 }
397
398 bool hasISA(int features, int isa) {
399 return (features & isa) == isa;
400 }
401
402 std::string supportedTargetList (int features)
403 {
404 std::string v;
405 if (hasISA(features,sse2: SSE)) v += "SSE ";
406 if (hasISA(features,sse2: SSE2)) v += "SSE2 ";
407 if (hasISA(features,sse2: SSE3)) v += "SSE3 ";
408 if (hasISA(features,sse2: SSSE3)) v += "SSSE3 ";
409 if (hasISA(features,sse2: SSE41)) v += "SSE4.1 ";
410 if (hasISA(features,sse2: SSE42)) v += "SSE4.2 ";
411 if (hasISA(features,sse2: AVX)) v += "AVX ";
412 if (hasISA(features,sse2: AVXI)) v += "AVXI ";
413 if (hasISA(features,sse2: AVX2)) v += "AVX2 ";
414 if (hasISA(features,sse2: AVX512)) v += "AVX512 ";
415 return v;
416 }
417}
418
419////////////////////////////////////////////////////////////////////////////////
420/// Windows Platform
421////////////////////////////////////////////////////////////////////////////////
422
423#if defined(__WIN32__)
424
425#define WIN32_LEAN_AND_MEAN
426#include <windows.h>
427#include <psapi.h>
428
429namespace embree
430{
431 std::string getExecutableFileName() {
432 char filename[1024];
433 if (!GetModuleFileName(nullptr, filename, sizeof(filename)))
434 return std::string();
435 return std::string(filename);
436 }
437
438 unsigned int getNumberOfLogicalThreads()
439 {
440 static int nThreads = -1;
441 if (nThreads != -1) return nThreads;
442
443 typedef WORD (WINAPI *GetActiveProcessorGroupCountFunc)();
444 typedef DWORD (WINAPI *GetActiveProcessorCountFunc)(WORD);
445 HMODULE hlib = LoadLibrary("Kernel32");
446 GetActiveProcessorGroupCountFunc pGetActiveProcessorGroupCount = (GetActiveProcessorGroupCountFunc)GetProcAddress(hlib, "GetActiveProcessorGroupCount");
447 GetActiveProcessorCountFunc pGetActiveProcessorCount = (GetActiveProcessorCountFunc) GetProcAddress(hlib, "GetActiveProcessorCount");
448
449 if (pGetActiveProcessorGroupCount && pGetActiveProcessorCount)
450 {
451 int groups = pGetActiveProcessorGroupCount();
452 int totalProcessors = 0;
453 for (int i = 0; i < groups; i++)
454 totalProcessors += pGetActiveProcessorCount(i);
455 nThreads = totalProcessors;
456 }
457 else
458 {
459 SYSTEM_INFO sysinfo;
460 GetSystemInfo(&sysinfo);
461 nThreads = sysinfo.dwNumberOfProcessors;
462 }
463 assert(nThreads);
464 return nThreads;
465 }
466
467 int getTerminalWidth()
468 {
469 HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
470 if (handle == INVALID_HANDLE_VALUE) return 80;
471 CONSOLE_SCREEN_BUFFER_INFO info;
472 memset(&info,0,sizeof(info));
473 GetConsoleScreenBufferInfo(handle, &info);
474 return info.dwSize.X;
475 }
476
477 double getSeconds()
478 {
479 LARGE_INTEGER freq, val;
480 QueryPerformanceFrequency(&freq);
481 QueryPerformanceCounter(&val);
482 return (double)val.QuadPart / (double)freq.QuadPart;
483 }
484
485 void sleepSeconds(double t) {
486 Sleep(DWORD(1000.0*t));
487 }
488
489 size_t getVirtualMemoryBytes()
490 {
491 PROCESS_MEMORY_COUNTERS info;
492 GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
493 return (size_t)info.QuotaPeakPagedPoolUsage;
494 }
495
496 size_t getResidentMemoryBytes()
497 {
498 PROCESS_MEMORY_COUNTERS info;
499 GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
500 return (size_t)info.WorkingSetSize;
501 }
502}
503#endif
504
505////////////////////////////////////////////////////////////////////////////////
506/// Linux Platform
507////////////////////////////////////////////////////////////////////////////////
508
509#if defined(__LINUX__)
510
511#include <stdio.h>
512#include <unistd.h>
513
514namespace embree
515{
516 std::string getExecutableFileName()
517 {
518 std::string pid = "/proc/" + toString(value: getpid()) + "/exe";
519 char buf[4096];
520 memset(s: buf,c: 0,n: sizeof(buf));
521 if (readlink(path: pid.c_str(), buf: buf, len: sizeof(buf)-1) == -1)
522 return std::string();
523 return std::string(buf);
524 }
525
526 size_t getVirtualMemoryBytes()
527 {
528 size_t virt, resident, shared;
529 std::ifstream buffer("/proc/self/statm");
530 buffer >> virt >> resident >> shared;
531 return virt*sysconf(_SC_PAGE_SIZE);
532 }
533
534 size_t getResidentMemoryBytes()
535 {
536 size_t virt, resident, shared;
537 std::ifstream buffer("/proc/self/statm");
538 buffer >> virt >> resident >> shared;
539 return resident*sysconf(_SC_PAGE_SIZE);
540 }
541}
542
543#endif
544
545////////////////////////////////////////////////////////////////////////////////
546/// FreeBSD Platform
547////////////////////////////////////////////////////////////////////////////////
548
549#if defined (__FreeBSD__)
550
551#include <sys/sysctl.h>
552
553namespace embree
554{
555 std::string getExecutableFileName()
556 {
557 const int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
558 char buf[4096];
559 memset(buf,0,sizeof(buf));
560 size_t len = sizeof(buf)-1;
561 if (sysctl(mib, 4, buf, &len, 0x0, 0) == -1)
562 return std::string();
563 return std::string(buf);
564 }
565
566 size_t getVirtualMemoryBytes() {
567 return 0;
568 }
569
570 size_t getResidentMemoryBytes() {
571 return 0;
572 }
573}
574
575#endif
576
577////////////////////////////////////////////////////////////////////////////////
578/// Mac OS X Platform
579////////////////////////////////////////////////////////////////////////////////
580
581#if defined(__MACOSX__)
582
583#include <mach-o/dyld.h>
584
585namespace embree
586{
587 std::string getExecutableFileName()
588 {
589 char buf[4096];
590 uint32_t size = sizeof(buf);
591 if (_NSGetExecutablePath(buf, &size) != 0)
592 return std::string();
593 return std::string(buf);
594 }
595
596 size_t getVirtualMemoryBytes() {
597 return 0;
598 }
599
600 size_t getResidentMemoryBytes() {
601 return 0;
602 }
603}
604
605#endif
606
607////////////////////////////////////////////////////////////////////////////////
608/// Unix Platform
609////////////////////////////////////////////////////////////////////////////////
610
611#if defined(__UNIX__)
612
613#include <unistd.h>
614#include <sys/ioctl.h>
615#include <sys/time.h>
616#include <pthread.h>
617
618#if defined(__EMSCRIPTEN__)
619#include <emscripten.h>
620#endif
621
622namespace embree
623{
624 unsigned int getNumberOfLogicalThreads()
625 {
626 static int nThreads = -1;
627 if (nThreads != -1) return nThreads;
628
629#if defined(__MACOSX__) || defined(__ANDROID__)
630 nThreads = sysconf(_SC_NPROCESSORS_ONLN); // does not work in Linux LXC container
631 assert(nThreads);
632#elif defined(__EMSCRIPTEN__)
633 // WebAssembly supports pthreads, but not pthread_getaffinity_np. Get the number of logical
634 // threads from the browser or Node.js using JavaScript.
635 nThreads = MAIN_THREAD_EM_ASM_INT({
636 const isBrowser = typeof window !== 'undefined';
637 const isNode = typeof process !== 'undefined' && process.versions != null &&
638 process.versions.node != null;
639 if (isBrowser) {
640 // Return 1 if the browser does not expose hardwareConcurrency.
641 return window.navigator.hardwareConcurrency || 1;
642 } else if (isNode) {
643 return require('os').cpus().length;
644 } else {
645 return 1;
646 }
647 });
648#else
649 cpu_set_t set;
650 if (pthread_getaffinity_np(th: pthread_self(), cpusetsize: sizeof(set), cpuset: &set) == 0)
651 nThreads = CPU_COUNT(&set);
652#endif
653
654 assert(nThreads);
655 return nThreads;
656 }
657
658 int getTerminalWidth()
659 {
660 struct winsize info;
661 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &info) < 0) return 80;
662 return info.ws_col;
663 }
664
665 double getSeconds() {
666 struct timeval tp; gettimeofday(tv: &tp,tz: nullptr);
667 return double(tp.tv_sec) + double(tp.tv_usec)/1E6;
668 }
669
670 void sleepSeconds(double t) {
671 usleep(useconds: 1000000.0*t);
672 }
673}
674#endif
675
676

source code of qtquick3d/src/3rdparty/embree/common/sys/sysinfo.cpp