#include "GLTB/systeminfo.h" #ifdef WIN32 #include "windows.h" #include "shlobj.h" #else #include #include #include #include #include #include #endif #include "GLTB/exception.h" #include "GLTB/stringconvert.h" namespace gltb { #if defined WIN32 unsigned int numberOfProcessors() { SYSTEM_INFO systemInfo; GetSystemInfo(&systemInfo); return systemInfo.dwNumberOfProcessors; } unsigned int numberOfNumaNodes() { ULONG highestNodeNumber; GetNumaHighestNodeNumber(&highestNodeNumber); return highestNodeNumber; } unsigned long long numaNodeMemorySize(unsigned int node) { // Windows only provides the free memory on a node, not the total available amount, // so this cannot be implemented properly on this platform. return 0; } unsigned int numaNodeOfProcessor(unsigned int cpu) { UCHAR node; GetNumaProcessorNode(cpu, &node); return node; } unsigned long long totalPhysicalMemory() { MEMORYSTATUSEX memoryStatus; memoryStatus.dwLength = sizeof(memoryStatus); GlobalMemoryStatusEx(&memoryStatus); return memoryStatus.ullTotalPhys; } unsigned long long freePhysicalMemory() { MEMORYSTATUSEX memoryStatus; memoryStatus.dwLength = sizeof(memoryStatus); GlobalMemoryStatusEx(&memoryStatus); return memoryStatus.ullAvailPhys; } unsigned long long totalSwapMemory() { MEMORYSTATUSEX memoryStatus; memoryStatus.dwLength = sizeof(memoryStatus); GlobalMemoryStatusEx(&memoryStatus); return memoryStatus.ullTotalPageFile; } unsigned long long freeSwapMemory() { MEMORYSTATUSEX memoryStatus; memoryStatus.dwLength = sizeof(memoryStatus); GlobalMemoryStatusEx(&memoryStatus); return memoryStatus.ullAvailPageFile; } int getDataCacheLineSize() { static size_t lineSize = 0; if(lineSize == 0) { DWORD bufferSize = 0; DWORD i = 0; SYSTEM_LOGICAL_PROCESSOR_INFORMATION * buffer = 0; GetLogicalProcessorInformation(0, &bufferSize); buffer = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION *)malloc(bufferSize); GetLogicalProcessorInformation(&buffer[0], &bufferSize); for (i = 0; i != bufferSize / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); ++i) { if (buffer[i].Relationship == RelationCache && buffer[i].Cache.Level == 1) { lineSize = buffer[i].Cache.LineSize; break; } } free(buffer); } return lineSize; } std::wstring userDataDirectory() { TCHAR path[MAX_PATH]; if(SHGetFolderPath(NULL,CSIDL_PERSONAL|CSIDL_FLAG_CREATE,(HANDLE) NULL,SHGFP_TYPE_CURRENT,path)!=S_OK) { throw Error("unable to query user Documents directory","gltb::userDataDirectory()"); } return path; } #elif defined LINUX || defined ANDROID unsigned int numberOfProcessors() { unsigned int numProcessors=sysconf(_SC_NPROCESSORS_ONLN); // just assume 1 processor if this query doesn't work if(numProcessors<1) { numProcessors=1; } return numProcessors; } unsigned int numberOfNumaNodes() { if(numa_available() == -1) { return 1; } return numa_num_configured_nodes(); } unsigned long long numaNodeMemorySize(unsigned int node) { if(numa_available() == -1) { return 0; } return numa_node_size64(node, nullptr); } unsigned int numaNodeOfProcessor(unsigned int cpu) { if(numa_available() == -1) { return 0; } return numa_node_of_cpu(cpu); } unsigned long long totalPhysicalMemory() { return (unsigned long long)sysconf(_SC_PHYS_PAGES) * (unsigned long long)sysconf(_SC_PAGESIZE); } unsigned long long freePhysicalMemory() { struct sysinfo sysInfo; sysinfo(&sysInfo); // count buffers towards free ram as their size is decreased as required by the kernel return (sysInfo.freeram + sysInfo.bufferram) * sysInfo.mem_unit; } unsigned long long totalSwapMemory() { struct sysinfo sysInfo; sysinfo(&sysInfo); return sysInfo.totalswap * sysInfo.mem_unit; } unsigned long long freeSwapMemory() { struct sysinfo sysInfo; sysinfo(&sysInfo); return sysInfo.freeswap * sysInfo.mem_unit; } int getDataCacheLineSize() { #ifdef ANDROID // assume running on ARM (/sys may provide incomplete information, so don't bother) return 32; #else static size_t lineSize = 0; if(lineSize == 0) { // FIXME check if this is actually the data for the level 1 data cache std::ifstream input("/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size"); if(input) { input >> lineSize; } else { lineSize = 32; } } return lineSize; #endif } std::wstring userDataDirectory() { char *home=getenv("HOME"); if(home==0) { throw Error("HOME environment variable not set","Engine::discoverDirectories()"); } return utf8ToUtf16WString(home); } #else #error not implemented for this platform #endif }