X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fpal%2Fsrc%2Fmisc%2Fsysinfo.cpp;h=495cc8bb94ea27a24a13dc112988be685ac01eec;hb=0ea5fc4456a859a1009b05d0949d3d878b383e9d;hp=3ccb35ab8198e1cdbae1e46886594e488ee7aa49;hpb=0b5d908617ebaa6ad97297d9b3f363d271340a01;p=platform%2Fupstream%2Fcoreclr.git diff --git a/src/pal/src/misc/sysinfo.cpp b/src/pal/src/misc/sysinfo.cpp index 3ccb35a..495cc8b 100644 --- a/src/pal/src/misc/sysinfo.cpp +++ b/src/pal/src/misc/sysinfo.cpp @@ -32,12 +32,20 @@ Revision History: #error Either sysctl or sysconf is required for GetSystemInfo. #endif +#if HAVE_SYSINFO +#include +#endif + #include #if HAVE_SYS_VMPARAM_H #include #endif // HAVE_SYS_VMPARAM_H +#if HAVE_XSWDEV +#include +#endif // HAVE_XSWDEV + #if HAVE_MACH_VM_TYPES_H #include #endif // HAVE_MACH_VM_TYPES_H @@ -73,6 +81,7 @@ Revision History: #include "pal/dbgmsg.h" +#include SET_DEFAULT_DEBUG_CHANNEL(MISC); @@ -87,6 +96,44 @@ SET_DEFAULT_DEBUG_CHANNEL(MISC); #endif // __APPLE__ +DWORD +PALAPI +PAL_GetLogicalCpuCountFromOS() +{ + int nrcpus = 0; + +#if HAVE_SYSCONF + +#if defined(_ARM_) || defined(_ARM64_) +#define SYSCONF_GET_NUMPROCS _SC_NPROCESSORS_CONF +#define SYSCONF_GET_NUMPROCS_NAME "_SC_NPROCESSORS_CONF" +#else +#define SYSCONF_GET_NUMPROCS _SC_NPROCESSORS_ONLN +#define SYSCONF_GET_NUMPROCS_NAME "_SC_NPROCESSORS_ONLN" +#endif + nrcpus = sysconf(SYSCONF_GET_NUMPROCS); + if (nrcpus < 1) + { + ASSERT("sysconf failed for %s (%d)\n", SYSCONF_GET_NUMPROCS_NAME, errno); + } +#elif HAVE_SYSCTL + int rc; + size_t sz; + int mib[2]; + + sz = sizeof(nrcpus); + mib[0] = CTL_HW; + mib[1] = HW_NCPU; + rc = sysctl(mib, 2, &nrcpus, &sz, NULL, 0); + if (rc != 0) + { + ASSERT("sysctl failed for HW_NCPU (%d)\n", errno); + } +#endif // HAVE_SYSCONF + + return nrcpus; +} + /*++ Function: GetSystemInfo @@ -129,27 +176,7 @@ GetSystemInfo( lpSystemInfo->dwPageSize = pagesize; lpSystemInfo->dwActiveProcessorMask_PAL_Undefined = 0; -#if HAVE_SYSCONF - nrcpus = sysconf(_SC_NPROCESSORS_ONLN); - if (nrcpus < 1) - { - ASSERT("sysconf failed for _SC_NPROCESSORS_ONLN (%d)\n", errno); - } -#elif HAVE_SYSCTL - int rc; - size_t sz; - int mib[2]; - - sz = sizeof(nrcpus); - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - rc = sysctl(mib, 2, &nrcpus, &sz, NULL, 0); - if (rc != 0) - { - ASSERT("sysctl failed for HW_NCPU (%d)\n", errno); - } -#endif // HAVE_SYSCONF - + nrcpus = PAL_GetLogicalCpuCountFromOS(); TRACE("dwNumberOfProcessors=%d\n", nrcpus); lpSystemInfo->dwNumberOfProcessors = nrcpus; @@ -216,6 +243,8 @@ GlobalMemoryStatusEx( lpBuffer->ullAvailExtendedVirtual = 0; BOOL fRetVal = FALSE; + int mib[3]; + int rc; // Get the physical memory size #if HAVE_SYSCONF && HAVE__SC_PHYS_PAGES @@ -226,7 +255,6 @@ GlobalMemoryStatusEx( lpBuffer->ullTotalPhys = (DWORDLONG)physical_memory; fRetVal = TRUE; #elif HAVE_SYSCTL - int mib[2]; int64_t physical_memory; size_t length; @@ -234,7 +262,7 @@ GlobalMemoryStatusEx( mib[0] = CTL_HW; mib[1] = HW_MEMSIZE; length = sizeof(INT64); - int rc = sysctl(mib, 2, &physical_memory, &length, NULL, 0); + rc = sysctl(mib, 2, &physical_memory, &length, NULL, 0); if (rc != 0) { ASSERT("sysctl failed for HW_MEMSIZE (%d)\n", errno); @@ -244,11 +272,65 @@ GlobalMemoryStatusEx( lpBuffer->ullTotalPhys = (DWORDLONG)physical_memory; fRetVal = TRUE; } -#elif // HAVE_SYSINFO - // TODO: implement getting memory details via sysinfo. On Linux, it provides swap file details that - // we can use to fill in the xxxPageFile members. -#endif // HAVE_SYSCONF +#endif // HAVE_SYSCTL + + // Get swap file size, consider the ability to get the values optional + // (don't return FALSE from the GlobalMemoryStatusEx) +#if HAVE_XSW_USAGE + // This is available on OSX + struct xsw_usage xsu; + mib[0] = CTL_VM; + mib[1] = VM_SWAPUSAGE; + size_t length = sizeof(xsu); + rc = sysctl(mib, 2, &xsu, &length, NULL, 0); + if (rc == 0) + { + lpBuffer->ullTotalPageFile = xsu.xsu_total; + lpBuffer->ullAvailPageFile = xsu.xsu_avail; + } +#elif HAVE_XSWDEV + // E.g. FreeBSD + struct xswdev xsw; + + size_t length = 2; + rc = sysctlnametomib("vm.swap_info", mib, &length); + if (rc == 0) + { + int pagesize = getpagesize(); + // Aggregate the information for all swap files on the system + for (mib[2] = 0; ; mib[2]++) + { + length = sizeof(xsw); + rc = sysctl(mib, 3, &xsw, &length, NULL, 0); + if ((rc < 0) || (xsw.xsw_version != XSWDEV_VERSION)) + { + // All the swap files were processed or coreclr was built against + // a version of headers not compatible with the current XSWDEV_VERSION. + break; + } + + DWORDLONG avail = xsw.xsw_nblks - xsw.xsw_used; + lpBuffer->ullTotalPageFile += (DWORDLONG)xsw.xsw_nblks * pagesize; + lpBuffer->ullAvailPageFile += (DWORDLONG)avail * pagesize; + } + } +#elif HAVE_SYSINFO + // Linux + struct sysinfo info; + rc = sysinfo(&info); + if (rc == 0) + { + lpBuffer->ullTotalPageFile = info.totalswap; + lpBuffer->ullAvailPageFile = info.freeswap; +#if HAVE_SYSINFO_WITH_MEM_UNIT + // A newer version of the sysinfo structure represents all the sizes + // in mem_unit instead of bytes + lpBuffer->ullTotalPageFile *= info.mem_unit; + lpBuffer->ullAvailPageFile *= info.mem_unit; +#endif // HAVE_SYSINFO_WITH_MEM_UNIT + } +#endif // HAVE_SYSINFO // Get the physical memory in use - from it, we can get the physical memory available. // We do this only when we have the total physical memory available. @@ -311,17 +393,50 @@ PAL_HasGetCurrentProcessorNumber() return HAVE_SCHED_GETCPU; } -DWORD -PALAPI -PAL_GetLogicalCpuCountFromOS() +bool +ReadMemoryValueFromFile(const char* filename, size_t* val) { - DWORD numLogicalCores = 0; + bool result = false; + char *line = nullptr; + size_t lineLen = 0; + char* endptr = nullptr; + size_t num = 0, l, multiplier; -#if HAVE_SYSCONF - numLogicalCores = sysconf(_SC_NPROCESSORS_ONLN); -#endif + if (val == nullptr) + return false; + + FILE* file = fopen(filename, "r"); + if (file == nullptr) + goto done; + + if (getline(&line, &lineLen, file) == -1) + goto done; + + errno = 0; + num = strtoull(line, &endptr, 0); + if (errno != 0) + goto done; - return numLogicalCores; + multiplier = 1; + switch(*endptr) + { + case 'g': + case 'G': multiplier = 1024; + case 'm': + case 'M': multiplier = multiplier*1024; + case 'k': + case 'K': multiplier = multiplier*1024; + } + + *val = num * multiplier; + result = true; + if (*val/multiplier != num) + result = false; +done: + if (file) + fclose(file); + free(line); + return result; } size_t @@ -331,16 +446,59 @@ PAL_GetLogicalProcessorCacheSizeFromOS() size_t cacheSize = 0; #ifdef _SC_LEVEL1_DCACHE_SIZE - cacheSize = max(cacheSize, sysconf(_SC_LEVEL1_DCACHE_SIZE)); + cacheSize = std::max(cacheSize, (size_t)sysconf(_SC_LEVEL1_DCACHE_SIZE)); #endif #ifdef _SC_LEVEL2_CACHE_SIZE - cacheSize = max(cacheSize, sysconf(_SC_LEVEL2_CACHE_SIZE)); + cacheSize = std::max(cacheSize, (size_t)sysconf(_SC_LEVEL2_CACHE_SIZE)); #endif #ifdef _SC_LEVEL3_CACHE_SIZE - cacheSize = max(cacheSize, sysconf(_SC_LEVEL3_CACHE_SIZE)); + cacheSize = std::max(cacheSize, (size_t)sysconf(_SC_LEVEL3_CACHE_SIZE)); #endif #ifdef _SC_LEVEL4_CACHE_SIZE - cacheSize = max(cacheSize, sysconf(_SC_LEVEL4_CACHE_SIZE)); + cacheSize = std::max(cacheSize, (size_t)sysconf(_SC_LEVEL4_CACHE_SIZE)); +#endif + +#if defined(_ARM64_) + if(cacheSize == 0) + { + size_t size; + + if(ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index0/size", &size)) + cacheSize = std::max(cacheSize, size); + if(ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index1/size", &size)) + cacheSize = std::max(cacheSize, size); + if(ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index2/size", &size)) + cacheSize = std::max(cacheSize, size); + if(ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index3/size", &size)) + cacheSize = std::max(cacheSize, size); + if(ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index4/size", &size)) + cacheSize = std::max(cacheSize, size); + } + + if(cacheSize == 0) + { + // It is currently expected to be missing cache size info + // + // _SC_LEVEL*_*CACHE_SIZE is not yet present. Work is in progress to enable this for arm64 + // + // /sys/devices/system/cpu/cpu*/cache/index*/ is also not yet present in most systems. + // Arm64 patch is in Linux kernel tip. + // + // midr_el1 is available in "/sys/devices/system/cpu/cpu0/regs/identification/midr_el1", + // but without an exhaustive list of ARM64 processors any decode of midr_el1 + // Would likely be incomplete + + // Published information on ARM64 architectures is limited. + // If we use recent high core count chips as a guide for state of the art, we find + // total L3 cache to be 1-2MB/core. As always, there are exceptions. + + // Estimate cache size based on CPU count + // Assume lower core count are lighter weight parts which are likely to have smaller caches + // Assume L3$/CPU grows linearly from 256K to 1.5M/CPU as logicalCPUs grows from 2 to 12 CPUs + DWORD logicalCPUs = PAL_GetLogicalCpuCountFromOS(); + + cacheSize = logicalCPUs*std::min(1536, std::max(256, (int)logicalCPUs*128))*1024; + } #endif return cacheSize;