Path: blob/master/thirdparty/embree/common/sys/sysinfo.cpp
9912 views
// Copyright 2009-2021 Intel Corporation1// SPDX-License-Identifier: Apache-2.023#if defined(__INTEL_LLVM_COMPILER)4// prevents "'__thiscall' calling convention is not supported for this target" warning from TBB5#pragma clang diagnostic push6#pragma clang diagnostic ignored "-Wignored-attributes"7#endif89#include "sysinfo.h"10#include "intrinsics.h"11#include "estring.h"12#include "ref.h"13#if defined(__FREEBSD__)14#include <sys/cpuset.h>15#include <pthread_np.h>16typedef cpuset_t cpu_set_t;17#endif1819////////////////////////////////////////////////////////////////////////////////20/// All Platforms21////////////////////////////////////////////////////////////////////////////////2223namespace embree24{25NullTy null;2627std::string getPlatformName()28{29#if defined(__ANDROID__) && !defined(__64BIT__)30return "Android (32bit)";31#elif defined(__ANDROID__) && defined(__64BIT__)32return "Android (64bit)";33#elif defined(__LINUX__) && !defined(__64BIT__)34return "Linux (32bit)";35#elif defined(__LINUX__) && defined(__64BIT__)36return "Linux (64bit)";37#elif defined(__FREEBSD__) && !defined(__64BIT__)38return "FreeBSD (32bit)";39#elif defined(__FREEBSD__) && defined(__64BIT__)40return "FreeBSD (64bit)";41#elif defined(__CYGWIN__) && !defined(__64BIT__)42return "Cygwin (32bit)";43#elif defined(__CYGWIN__) && defined(__64BIT__)44return "Cygwin (64bit)";45#elif defined(__WIN32__) && !defined(__64BIT__)46return "Windows (32bit)";47#elif defined(__WIN32__) && defined(__64BIT__)48return "Windows (64bit)";49#elif defined(__MACOSX__) && !defined(__64BIT__)50return "Mac OS X (32bit)";51#elif defined(__MACOSX__) && defined(__64BIT__)52return "Mac OS X (64bit)";53#elif defined(__UNIX__) && !defined(__64BIT__)54return "Unix (32bit)";55#elif defined(__UNIX__) && defined(__64BIT__)56return "Unix (64bit)";57#else58return "Unknown";59#endif60}6162std::string getCompilerName()63{64#if defined(__INTEL_COMPILER)65int icc_mayor = __INTEL_COMPILER / 100 % 100;66int icc_minor = __INTEL_COMPILER % 100;67std::string version = "Intel Compiler ";68version += toString(icc_mayor);69version += "." + toString(icc_minor);70#if defined(__INTEL_COMPILER_UPDATE)71version += "." + toString(__INTEL_COMPILER_UPDATE);72#endif73return version;74#elif defined(__clang__)75return "CLANG " __clang_version__;76#elif defined (__GNUC__)77return "GCC " __VERSION__;78#elif defined(_MSC_VER)79std::string version = toString(_MSC_FULL_VER);80version.insert(4,".");81version.insert(9,".");82version.insert(2,".");83return "Visual C++ Compiler " + version;84#else85return "Unknown Compiler";86#endif87}8889std::string getCPUVendor()90{91#if defined(__X86_ASM__)92int cpuinfo[4];93__cpuid (cpuinfo, 0);94int name[4];95name[0] = cpuinfo[1];96name[1] = cpuinfo[3];97name[2] = cpuinfo[2];98name[3] = 0;99return (char*)name;100#elif defined(__ARM_NEON)101return "ARM";102#else103return "Unknown";104#endif105}106107CPU getCPUModel()108{109#if defined(__X86_ASM__)110if (getCPUVendor() != "GenuineIntel")111return CPU::UNKNOWN;112113int out[4];114__cpuid(out, 0);115if (out[0] < 1) return CPU::UNKNOWN;116__cpuid(out, 1);117118/* please see CPUID documentation for these formulas */119uint32_t family_ID = (out[0] >> 8) & 0x0F;120uint32_t extended_family_ID = (out[0] >> 20) & 0xFF;121122uint32_t model_ID = (out[0] >> 4) & 0x0F;123uint32_t extended_model_ID = (out[0] >> 16) & 0x0F;124125uint32_t DisplayFamily = family_ID;126if (family_ID == 0x0F)127DisplayFamily += extended_family_ID;128129uint32_t DisplayModel = model_ID;130if (family_ID == 0x06 || family_ID == 0x0F)131DisplayModel += extended_model_ID << 4;132133uint32_t DisplayFamily_DisplayModel = (DisplayFamily << 8) + (DisplayModel << 0);134135// Data from IntelĀ® 64 and IA-32 Architectures, Volume 4, Chapter 2, Table 2-1 (CPUID Signature Values of DisplayFamily_DisplayModel)136if (DisplayFamily_DisplayModel == 0x067D) return CPU::CORE_ICE_LAKE;137if (DisplayFamily_DisplayModel == 0x067E) return CPU::CORE_ICE_LAKE;138if (DisplayFamily_DisplayModel == 0x068C) return CPU::CORE_TIGER_LAKE;139if (DisplayFamily_DisplayModel == 0x06A5) return CPU::CORE_COMET_LAKE;140if (DisplayFamily_DisplayModel == 0x06A6) return CPU::CORE_COMET_LAKE;141if (DisplayFamily_DisplayModel == 0x0666) return CPU::CORE_CANNON_LAKE;142if (DisplayFamily_DisplayModel == 0x068E) return CPU::CORE_KABY_LAKE;143if (DisplayFamily_DisplayModel == 0x069E) return CPU::CORE_KABY_LAKE;144if (DisplayFamily_DisplayModel == 0x066A) return CPU::XEON_ICE_LAKE;145if (DisplayFamily_DisplayModel == 0x066C) return CPU::XEON_ICE_LAKE;146if (DisplayFamily_DisplayModel == 0x0655) return CPU::XEON_SKY_LAKE;147if (DisplayFamily_DisplayModel == 0x064E) return CPU::CORE_SKY_LAKE;148if (DisplayFamily_DisplayModel == 0x065E) return CPU::CORE_SKY_LAKE;149if (DisplayFamily_DisplayModel == 0x0656) return CPU::XEON_BROADWELL;150if (DisplayFamily_DisplayModel == 0x064F) return CPU::XEON_BROADWELL;151if (DisplayFamily_DisplayModel == 0x0647) return CPU::CORE_BROADWELL;152if (DisplayFamily_DisplayModel == 0x063D) return CPU::CORE_BROADWELL;153if (DisplayFamily_DisplayModel == 0x063F) return CPU::XEON_HASWELL;154if (DisplayFamily_DisplayModel == 0x063C) return CPU::CORE_HASWELL;155if (DisplayFamily_DisplayModel == 0x0645) return CPU::CORE_HASWELL;156if (DisplayFamily_DisplayModel == 0x0646) return CPU::CORE_HASWELL;157if (DisplayFamily_DisplayModel == 0x063E) return CPU::XEON_IVY_BRIDGE;158if (DisplayFamily_DisplayModel == 0x063A) return CPU::CORE_IVY_BRIDGE;159if (DisplayFamily_DisplayModel == 0x062D) return CPU::SANDY_BRIDGE;160if (DisplayFamily_DisplayModel == 0x062F) return CPU::SANDY_BRIDGE;161if (DisplayFamily_DisplayModel == 0x062A) return CPU::SANDY_BRIDGE;162if (DisplayFamily_DisplayModel == 0x062E) return CPU::NEHALEM;163if (DisplayFamily_DisplayModel == 0x0625) return CPU::NEHALEM;164if (DisplayFamily_DisplayModel == 0x062C) return CPU::NEHALEM;165if (DisplayFamily_DisplayModel == 0x061E) return CPU::NEHALEM;166if (DisplayFamily_DisplayModel == 0x061F) return CPU::NEHALEM;167if (DisplayFamily_DisplayModel == 0x061A) return CPU::NEHALEM;168if (DisplayFamily_DisplayModel == 0x061D) return CPU::NEHALEM;169if (DisplayFamily_DisplayModel == 0x0617) return CPU::CORE2;170if (DisplayFamily_DisplayModel == 0x060F) return CPU::CORE2;171if (DisplayFamily_DisplayModel == 0x060E) return CPU::CORE1;172173if (DisplayFamily_DisplayModel == 0x0685) return CPU::XEON_PHI_KNIGHTS_MILL;174if (DisplayFamily_DisplayModel == 0x0657) return CPU::XEON_PHI_KNIGHTS_LANDING;175176#elif defined(__ARM_NEON)177return CPU::ARM;178#endif179180return CPU::UNKNOWN;181}182183std::string stringOfCPUModel(CPU model)184{185switch (model) {186case CPU::XEON_ICE_LAKE : return "Xeon Ice Lake";187case CPU::CORE_ICE_LAKE : return "Core Ice Lake";188case CPU::CORE_TIGER_LAKE : return "Core Tiger Lake";189case CPU::CORE_COMET_LAKE : return "Core Comet Lake";190case CPU::CORE_CANNON_LAKE : return "Core Cannon Lake";191case CPU::CORE_KABY_LAKE : return "Core Kaby Lake";192case CPU::XEON_SKY_LAKE : return "Xeon Sky Lake";193case CPU::CORE_SKY_LAKE : return "Core Sky Lake";194case CPU::XEON_PHI_KNIGHTS_MILL : return "Xeon Phi Knights Mill";195case CPU::XEON_PHI_KNIGHTS_LANDING: return "Xeon Phi Knights Landing";196case CPU::XEON_BROADWELL : return "Xeon Broadwell";197case CPU::CORE_BROADWELL : return "Core Broadwell";198case CPU::XEON_HASWELL : return "Xeon Haswell";199case CPU::CORE_HASWELL : return "Core Haswell";200case CPU::XEON_IVY_BRIDGE : return "Xeon Ivy Bridge";201case CPU::CORE_IVY_BRIDGE : return "Core Ivy Bridge";202case CPU::SANDY_BRIDGE : return "Sandy Bridge";203case CPU::NEHALEM : return "Nehalem";204case CPU::CORE2 : return "Core2";205case CPU::CORE1 : return "Core";206case CPU::ARM : return "ARM";207case CPU::UNKNOWN : return "Unknown CPU";208}209return "Unknown CPU (error)";210}211212#if defined(__X86_ASM__)213/* constants to access destination registers of CPUID instruction */214static const int EAX = 0;215static const int EBX = 1;216static const int ECX = 2;217static const int EDX = 3;218219/* cpuid[eax=1].ecx */220static const int CPU_FEATURE_BIT_SSE3 = 1 << 0;221static const int CPU_FEATURE_BIT_SSSE3 = 1 << 9;222static const int CPU_FEATURE_BIT_FMA3 = 1 << 12;223static const int CPU_FEATURE_BIT_SSE4_1 = 1 << 19;224static const int CPU_FEATURE_BIT_SSE4_2 = 1 << 20;225//static const int CPU_FEATURE_BIT_MOVBE = 1 << 22;226static const int CPU_FEATURE_BIT_POPCNT = 1 << 23;227//static const int CPU_FEATURE_BIT_XSAVE = 1 << 26;228static const int CPU_FEATURE_BIT_OXSAVE = 1 << 27;229static const int CPU_FEATURE_BIT_AVX = 1 << 28;230static const int CPU_FEATURE_BIT_F16C = 1 << 29;231static const int CPU_FEATURE_BIT_RDRAND = 1 << 30;232233/* cpuid[eax=1].edx */234static const int CPU_FEATURE_BIT_SSE = 1 << 25;235static const int CPU_FEATURE_BIT_SSE2 = 1 << 26;236237/* cpuid[eax=0x80000001].ecx */238static const int CPU_FEATURE_BIT_LZCNT = 1 << 5;239240/* cpuid[eax=7,ecx=0].ebx */241static const int CPU_FEATURE_BIT_BMI1 = 1 << 3;242static const int CPU_FEATURE_BIT_AVX2 = 1 << 5;243static const int CPU_FEATURE_BIT_BMI2 = 1 << 8;244static const int CPU_FEATURE_BIT_AVX512F = 1 << 16; // AVX512F (foundation)245static const int CPU_FEATURE_BIT_AVX512DQ = 1 << 17; // AVX512DQ (doubleword and quadword instructions)246static const int CPU_FEATURE_BIT_AVX512PF = 1 << 26; // AVX512PF (prefetch gather/scatter instructions)247static const int CPU_FEATURE_BIT_AVX512ER = 1 << 27; // AVX512ER (exponential and reciprocal instructions)248static const int CPU_FEATURE_BIT_AVX512CD = 1 << 28; // AVX512CD (conflict detection instructions)249static const int CPU_FEATURE_BIT_AVX512BW = 1 << 30; // AVX512BW (byte and word instructions)250static const int CPU_FEATURE_BIT_AVX512VL = 1 << 31; // AVX512VL (vector length extensions)251static const int CPU_FEATURE_BIT_AVX512IFMA = 1 << 21; // AVX512IFMA (integer fused multiple-add instructions)252253/* cpuid[eax=7,ecx=0].ecx */254static const int CPU_FEATURE_BIT_AVX512VBMI = 1 << 1; // AVX512VBMI (vector bit manipulation instructions)255#endif256257#if defined(__X86_ASM__)258__noinline int64_t get_xcr0()259{260#if defined (__WIN32__) && !defined (__MINGW32__) && defined(_XCR_XFEATURE_ENABLED_MASK)261int64_t xcr0 = 0; // int64_t is workaround for compiler bug under VS2013, Win32262xcr0 = _xgetbv(0);263return xcr0;264#else265int xcr0 = 0;266__asm__ ("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx" );267return xcr0;268#endif269}270#endif271272int getCPUFeatures()273{274#if defined(__X86_ASM__)275/* cache CPU features access */276static int cpu_features = 0;277if (cpu_features)278return cpu_features;279280/* get number of CPUID leaves */281int cpuid_leaf0[4];282__cpuid(cpuid_leaf0, 0x00000000);283unsigned nIds = cpuid_leaf0[EAX];284285/* get number of extended CPUID leaves */286int cpuid_leafe[4];287__cpuid(cpuid_leafe, 0x80000000);288unsigned nExIds = cpuid_leafe[EAX];289290/* get CPUID leaves for EAX = 1,7, and 0x80000001 */291int cpuid_leaf_1[4] = { 0,0,0,0 };292int cpuid_leaf_7[4] = { 0,0,0,0 };293int cpuid_leaf_e1[4] = { 0,0,0,0 };294if (nIds >= 1) __cpuid (cpuid_leaf_1,0x00000001);295#if _WIN32296#if _MSC_VER && (_MSC_FULL_VER < 160040219)297#elif defined(_MSC_VER)298if (nIds >= 7) __cpuidex(cpuid_leaf_7,0x00000007,0);299#endif300#else301if (nIds >= 7) __cpuid_count(cpuid_leaf_7,0x00000007,0);302#endif303if (nExIds >= 0x80000001) __cpuid(cpuid_leaf_e1,0x80000001);304305/* detect if OS saves XMM, YMM, and ZMM states */306bool xmm_enabled = true;307bool ymm_enabled = false;308bool zmm_enabled = false;309if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_OXSAVE) {310int64_t xcr0 = get_xcr0();311xmm_enabled = ((xcr0 & 0x02) == 0x02); /* checks if xmm are enabled in XCR0 */312ymm_enabled = xmm_enabled && ((xcr0 & 0x04) == 0x04); /* checks if ymm state are enabled in XCR0 */313zmm_enabled = ymm_enabled && ((xcr0 & 0xE0) == 0xE0); /* checks if OPMASK state, upper 256-bit of ZMM0-ZMM15 and ZMM16-ZMM31 state are enabled in XCR0 */314}315if (xmm_enabled) cpu_features |= CPU_FEATURE_XMM_ENABLED;316if (ymm_enabled) cpu_features |= CPU_FEATURE_YMM_ENABLED;317if (zmm_enabled) cpu_features |= CPU_FEATURE_ZMM_ENABLED;318319if (cpuid_leaf_1[EDX] & CPU_FEATURE_BIT_SSE ) cpu_features |= CPU_FEATURE_SSE;320if (cpuid_leaf_1[EDX] & CPU_FEATURE_BIT_SSE2 ) cpu_features |= CPU_FEATURE_SSE2;321if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSE3 ) cpu_features |= CPU_FEATURE_SSE3;322if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSSE3 ) cpu_features |= CPU_FEATURE_SSSE3;323if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSE4_1) cpu_features |= CPU_FEATURE_SSE41;324if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_SSE4_2) cpu_features |= CPU_FEATURE_SSE42;325if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_POPCNT) cpu_features |= CPU_FEATURE_POPCNT;326327if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_AVX ) cpu_features |= CPU_FEATURE_AVX;328if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_F16C ) cpu_features |= CPU_FEATURE_F16C;329if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_RDRAND) cpu_features |= CPU_FEATURE_RDRAND;330if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX2 ) cpu_features |= CPU_FEATURE_AVX2;331if (cpuid_leaf_1[ECX] & CPU_FEATURE_BIT_FMA3 ) cpu_features |= CPU_FEATURE_FMA3;332if (cpuid_leaf_e1[ECX] & CPU_FEATURE_BIT_LZCNT) cpu_features |= CPU_FEATURE_LZCNT;333if (cpuid_leaf_7 [EBX] & CPU_FEATURE_BIT_BMI1 ) cpu_features |= CPU_FEATURE_BMI1;334if (cpuid_leaf_7 [EBX] & CPU_FEATURE_BIT_BMI2 ) cpu_features |= CPU_FEATURE_BMI2;335336if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512F ) cpu_features |= CPU_FEATURE_AVX512F;337if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512DQ ) cpu_features |= CPU_FEATURE_AVX512DQ;338if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512PF ) cpu_features |= CPU_FEATURE_AVX512PF;339if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512ER ) cpu_features |= CPU_FEATURE_AVX512ER;340if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512CD ) cpu_features |= CPU_FEATURE_AVX512CD;341if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512BW ) cpu_features |= CPU_FEATURE_AVX512BW;342if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512IFMA) cpu_features |= CPU_FEATURE_AVX512IFMA;343if (cpuid_leaf_7[EBX] & CPU_FEATURE_BIT_AVX512VL ) cpu_features |= CPU_FEATURE_AVX512VL;344if (cpuid_leaf_7[ECX] & CPU_FEATURE_BIT_AVX512VBMI) cpu_features |= CPU_FEATURE_AVX512VBMI;345346#if defined(__MACOSX__)347if ( (cpu_features & CPU_FEATURE_AVX512F)348|| (cpu_features & CPU_FEATURE_AVX512DQ)349|| (cpu_features & CPU_FEATURE_AVX512CD)350|| (cpu_features & CPU_FEATURE_AVX512BW)351|| (cpu_features & CPU_FEATURE_AVX512VL) )352{353// on macOS AVX512 will be enabled automatically by the kernel when the first AVX512 instruction is called354// see https://github.com/apple/darwin-xnu/blob/0a798f6738bc1db01281fc08ae024145e84df927/osfmk/i386/fpu.c#L176355// therefore we ignore the state of XCR0356cpu_features |= CPU_FEATURE_ZMM_ENABLED;357}358#endif359return cpu_features;360361#elif defined(__ARM_NEON) || defined(__EMSCRIPTEN__)362363int cpu_features = CPU_FEATURE_NEON|CPU_FEATURE_SSE|CPU_FEATURE_SSE2;364cpu_features |= CPU_FEATURE_SSE3|CPU_FEATURE_SSSE3|CPU_FEATURE_SSE42;365cpu_features |= CPU_FEATURE_XMM_ENABLED;366cpu_features |= CPU_FEATURE_YMM_ENABLED;367cpu_features |= CPU_FEATURE_SSE41 | CPU_FEATURE_RDRAND | CPU_FEATURE_F16C;368cpu_features |= CPU_FEATURE_POPCNT;369cpu_features |= CPU_FEATURE_AVX;370cpu_features |= CPU_FEATURE_AVX2;371cpu_features |= CPU_FEATURE_FMA3;372cpu_features |= CPU_FEATURE_LZCNT;373cpu_features |= CPU_FEATURE_BMI1;374cpu_features |= CPU_FEATURE_BMI2;375cpu_features |= CPU_FEATURE_NEON_2X;376return cpu_features;377378#else379/* Unknown CPU. */380return 0;381#endif382}383384std::string stringOfCPUFeatures(int features)385{386std::string str;387if (features & CPU_FEATURE_XMM_ENABLED) str += "XMM ";388if (features & CPU_FEATURE_YMM_ENABLED) str += "YMM ";389if (features & CPU_FEATURE_ZMM_ENABLED) str += "ZMM ";390if (features & CPU_FEATURE_SSE ) str += "SSE ";391if (features & CPU_FEATURE_SSE2 ) str += "SSE2 ";392if (features & CPU_FEATURE_SSE3 ) str += "SSE3 ";393if (features & CPU_FEATURE_SSSE3 ) str += "SSSE3 ";394if (features & CPU_FEATURE_SSE41 ) str += "SSE4.1 ";395if (features & CPU_FEATURE_SSE42 ) str += "SSE4.2 ";396if (features & CPU_FEATURE_POPCNT) str += "POPCNT ";397if (features & CPU_FEATURE_AVX ) str += "AVX ";398if (features & CPU_FEATURE_F16C ) str += "F16C ";399if (features & CPU_FEATURE_RDRAND) str += "RDRAND ";400if (features & CPU_FEATURE_AVX2 ) str += "AVX2 ";401if (features & CPU_FEATURE_FMA3 ) str += "FMA3 ";402if (features & CPU_FEATURE_LZCNT ) str += "LZCNT ";403if (features & CPU_FEATURE_BMI1 ) str += "BMI1 ";404if (features & CPU_FEATURE_BMI2 ) str += "BMI2 ";405if (features & CPU_FEATURE_AVX512F) str += "AVX512F ";406if (features & CPU_FEATURE_AVX512DQ) str += "AVX512DQ ";407if (features & CPU_FEATURE_AVX512PF) str += "AVX512PF ";408if (features & CPU_FEATURE_AVX512ER) str += "AVX512ER ";409if (features & CPU_FEATURE_AVX512CD) str += "AVX512CD ";410if (features & CPU_FEATURE_AVX512BW) str += "AVX512BW ";411if (features & CPU_FEATURE_AVX512VL) str += "AVX512VL ";412if (features & CPU_FEATURE_AVX512IFMA) str += "AVX512IFMA ";413if (features & CPU_FEATURE_AVX512VBMI) str += "AVX512VBMI ";414if (features & CPU_FEATURE_NEON) str += "NEON ";415if (features & CPU_FEATURE_NEON_2X) str += "2xNEON ";416return str;417}418419std::string stringOfISA (int isa)420{421if (isa == SSE) return "SSE";422if (isa == SSE2) return "SSE2";423if (isa == SSE3) return "SSE3";424if (isa == SSSE3) return "SSSE3";425if (isa == SSE41) return "SSE4.1";426if (isa == SSE42) return "SSE4.2";427if (isa == AVX) return "AVX";428if (isa == AVX2) return "AVX2";429if (isa == AVX512) return "AVX512";430431if (isa == NEON) return "NEON";432if (isa == NEON_2X) return "2xNEON";433return "UNKNOWN";434}435436bool hasISA(int features, int isa) {437return (features & isa) == isa;438}439440std::string supportedTargetList (int features)441{442std::string v;443if (hasISA(features,SSE)) v += "SSE ";444if (hasISA(features,SSE2)) v += "SSE2 ";445if (hasISA(features,SSE3)) v += "SSE3 ";446if (hasISA(features,SSSE3)) v += "SSSE3 ";447if (hasISA(features,SSE41)) v += "SSE4.1 ";448if (hasISA(features,SSE42)) v += "SSE4.2 ";449if (hasISA(features,AVX)) v += "AVX ";450if (hasISA(features,AVXI)) v += "AVXI ";451if (hasISA(features,AVX2)) v += "AVX2 ";452if (hasISA(features,AVX512)) v += "AVX512 ";453454if (hasISA(features,NEON)) v += "NEON ";455if (hasISA(features,NEON_2X)) v += "2xNEON ";456return v;457}458}459460////////////////////////////////////////////////////////////////////////////////461/// Windows Platform462////////////////////////////////////////////////////////////////////////////////463464#if defined(__WIN32__)465466#define WIN32_LEAN_AND_MEAN467#include <windows.h>468#include <psapi.h>469470namespace embree471{472std::string getExecutableFileName() {473char filename[1024];474if (!GetModuleFileName(nullptr, filename, sizeof(filename)))475return std::string();476return std::string(filename);477}478479unsigned int getNumberOfLogicalThreads()480{481static int nThreads = -1;482if (nThreads != -1) return nThreads;483484typedef WORD (WINAPI *GetActiveProcessorGroupCountFunc)();485typedef DWORD (WINAPI *GetActiveProcessorCountFunc)(WORD);486HMODULE hlib = LoadLibrary("Kernel32");487GetActiveProcessorGroupCountFunc pGetActiveProcessorGroupCount = (GetActiveProcessorGroupCountFunc)GetProcAddress(hlib, "GetActiveProcessorGroupCount");488GetActiveProcessorCountFunc pGetActiveProcessorCount = (GetActiveProcessorCountFunc) GetProcAddress(hlib, "GetActiveProcessorCount");489490if (pGetActiveProcessorGroupCount && pGetActiveProcessorCount)491{492int groups = pGetActiveProcessorGroupCount();493int totalProcessors = 0;494for (int i = 0; i < groups; i++)495totalProcessors += pGetActiveProcessorCount(i);496nThreads = totalProcessors;497}498else499{500SYSTEM_INFO sysinfo;501GetSystemInfo(&sysinfo);502nThreads = sysinfo.dwNumberOfProcessors;503}504assert(nThreads);505return nThreads;506}507508int getTerminalWidth()509{510HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);511if (handle == INVALID_HANDLE_VALUE) return 80;512CONSOLE_SCREEN_BUFFER_INFO info;513memset(&info,0,sizeof(info));514GetConsoleScreenBufferInfo(handle, &info);515return info.dwSize.X;516}517518double getSeconds()519{520LARGE_INTEGER freq, val;521QueryPerformanceFrequency(&freq);522QueryPerformanceCounter(&val);523return (double)val.QuadPart / (double)freq.QuadPart;524}525526void sleepSeconds(double t) {527Sleep(DWORD(1000.0*t));528}529530size_t getVirtualMemoryBytes()531{532PROCESS_MEMORY_COUNTERS info;533GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );534return (size_t)info.QuotaPeakPagedPoolUsage;535}536537size_t getResidentMemoryBytes()538{539PROCESS_MEMORY_COUNTERS info;540GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );541return (size_t)info.WorkingSetSize;542}543}544#endif545546////////////////////////////////////////////////////////////////////////////////547/// Linux Platform548////////////////////////////////////////////////////////////////////////////////549550#if defined(__LINUX__)551552#include <stdio.h>553#include <unistd.h>554555namespace embree556{557std::string getExecutableFileName()558{559std::string pid = "/proc/" + toString(getpid()) + "/exe";560char buf[4096];561memset(buf,0,sizeof(buf));562if (readlink(pid.c_str(), buf, sizeof(buf)-1) == -1)563return std::string();564return std::string(buf);565}566567size_t getVirtualMemoryBytes()568{569size_t virt, resident, shared;570std::ifstream buffer("/proc/self/statm");571buffer >> virt >> resident >> shared;572return virt*sysconf(_SC_PAGE_SIZE);573}574575size_t getResidentMemoryBytes()576{577size_t virt, resident, shared;578std::ifstream buffer("/proc/self/statm");579buffer >> virt >> resident >> shared;580return resident*sysconf(_SC_PAGE_SIZE);581}582}583584#endif585586////////////////////////////////////////////////////////////////////////////////587/// FreeBSD Platform588////////////////////////////////////////////////////////////////////////////////589590#if defined (__FreeBSD__)591592#include <sys/sysctl.h>593594namespace embree595{596std::string getExecutableFileName()597{598const int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };599char buf[4096];600memset(buf,0,sizeof(buf));601size_t len = sizeof(buf)-1;602if (sysctl(mib, 4, buf, &len, 0x0, 0) == -1)603return std::string();604return std::string(buf);605}606607size_t getVirtualMemoryBytes() {608return 0;609}610611size_t getResidentMemoryBytes() {612return 0;613}614}615616#endif617618////////////////////////////////////////////////////////////////////////////////619/// Mac OS X Platform620////////////////////////////////////////////////////////////////////////////////621622#if defined(__MACOSX__)623624#include <mach-o/dyld.h>625626namespace embree627{628std::string getExecutableFileName()629{630char buf[4096];631uint32_t size = sizeof(buf);632if (_NSGetExecutablePath(buf, &size) != 0)633return std::string();634return std::string(buf);635}636637size_t getVirtualMemoryBytes() {638return 0;639}640641size_t getResidentMemoryBytes() {642return 0;643}644}645646#endif647648////////////////////////////////////////////////////////////////////////////////649/// Unix Platform650////////////////////////////////////////////////////////////////////////////////651652#if defined(__UNIX__)653654#include <unistd.h>655#include <sys/ioctl.h>656#include <sys/time.h>657#include <pthread.h>658659#if defined(__EMSCRIPTEN__)660#include <emscripten.h>661662extern "C" {663extern int godot_js_os_hw_concurrency_get();664}665#endif666667namespace embree668{669unsigned int getNumberOfLogicalThreads()670{671static int nThreads = -1;672if (nThreads != -1) return nThreads;673674#if defined(__MACOSX__) || defined(__ANDROID__)675nThreads = sysconf(_SC_NPROCESSORS_ONLN); // does not work in Linux LXC container676assert(nThreads);677#elif defined(__EMSCRIPTEN__)678nThreads = godot_js_os_hw_concurrency_get();679#if 0680// WebAssembly supports pthreads, but not pthread_getaffinity_np. Get the number of logical681// threads from the browser or Node.js using JavaScript.682nThreads = MAIN_THREAD_EM_ASM_INT({683const isBrowser = typeof window !== 'undefined';684const isNode = typeof process !== 'undefined' && process.versions != null &&685process.versions.node != null;686if (isBrowser) {687// Return 1 if the browser does not expose hardwareConcurrency.688return window.navigator.hardwareConcurrency || 1;689} else if (isNode) {690return require('os').cpus().length;691} else {692return 1;693}694});695#endif696#else697cpu_set_t set;698if (pthread_getaffinity_np(pthread_self(), sizeof(set), &set) == 0)699nThreads = CPU_COUNT(&set);700#endif701702assert(nThreads);703return nThreads;704}705706int getTerminalWidth()707{708struct winsize info;709if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &info) < 0) return 80;710return info.ws_col;711}712713double getSeconds() {714struct timeval tp; gettimeofday(&tp,nullptr);715return double(tp.tv_sec) + double(tp.tv_usec)/1E6;716}717718void sleepSeconds(double t) {719usleep(1000000.0*t);720}721}722#endif723724#if defined(__INTEL_LLVM_COMPILER)725#pragma clang diagnostic pop726#endif727728729