summaryrefslogtreecommitdiff
path: root/src/pal/src/misc/sysinfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pal/src/misc/sysinfo.cpp')
-rw-r--r--src/pal/src/misc/sysinfo.cpp363
1 files changed, 363 insertions, 0 deletions
diff --git a/src/pal/src/misc/sysinfo.cpp b/src/pal/src/misc/sysinfo.cpp
new file mode 100644
index 0000000000..515ccf1cdb
--- /dev/null
+++ b/src/pal/src/misc/sysinfo.cpp
@@ -0,0 +1,363 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*++
+
+
+
+Module Name:
+
+ sysinfo.c
+
+Abstract:
+
+ Implements GetSystemInfo.
+
+Revision History:
+
+
+
+--*/
+
+#include "pal/palinternal.h"
+
+#include <sched.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#if HAVE_SYSCTL
+#include <sys/sysctl.h>
+#elif !HAVE_SYSCONF
+#error Either sysctl or sysconf is required for GetSystemInfo.
+#endif
+
+#include <sys/param.h>
+
+#if HAVE_SYS_VMPARAM_H
+#include <sys/vmparam.h>
+#endif // HAVE_SYS_VMPARAM_H
+
+#if HAVE_MACH_VM_TYPES_H
+#include <mach/vm_types.h>
+#endif // HAVE_MACH_VM_TYPES_H
+
+#if HAVE_MACH_VM_PARAM_H
+#include <mach/vm_param.h>
+#endif // HAVE_MACH_VM_PARAM_H
+
+#if HAVE_MACHINE_VMPARAM_H
+#include <machine/vmparam.h>
+#endif // HAVE_MACHINE_VMPARAM_H
+
+#if defined(_TARGET_MAC64)
+#include <mach/vm_statistics.h>
+#include <mach/mach_types.h>
+#include <mach/mach_init.h>
+#include <mach/mach_host.h>
+#endif // defined(_TARGET_MAC64)
+
+// On some platforms sys/user.h ends up defining _DEBUG; if so
+// remove the definition before including the header and put
+// back our definition afterwards
+#if USER_H_DEFINES_DEBUG
+#define OLD_DEBUG _DEBUG
+#undef _DEBUG
+#endif
+#include <sys/user.h>
+#if USER_H_DEFINES_DEBUG
+#undef _DEBUG
+#define _DEBUG OLD_DEBUG
+#undef OLD_DEBUG
+#endif
+
+#include "pal/dbgmsg.h"
+
+
+SET_DEFAULT_DEBUG_CHANNEL(MISC);
+
+#if defined(_HPUX_) && ( defined (_IA64_) || defined (__hppa__) )
+#include <sys/pstat.h>
+#include <sys/vmparam.h>
+#endif
+
+#ifndef __APPLE__
+#if HAVE_SYSCONF && HAVE__SC_AVPHYS_PAGES
+#define SYSCONF_PAGES _SC_AVPHYS_PAGES
+#elif HAVE_SYSCONF && HAVE__SC_PHYS_PAGES
+#define SYSCONF_PAGES _SC_PHYS_PAGES
+#else
+#error Dont know how to get page-size on this architecture!
+#endif
+#endif // __APPLE__
+
+
+/*++
+Function:
+ GetSystemInfo
+
+GetSystemInfo
+
+The GetSystemInfo function returns information about the current system.
+
+Parameters
+
+lpSystemInfo
+ [out] Pointer to a SYSTEM_INFO structure that receives the information.
+
+Return Values
+
+This function does not return a value.
+
+Note:
+ fields returned by this function are:
+ dwNumberOfProcessors
+ dwPageSize
+Others are set to zero.
+
+--*/
+VOID
+PALAPI
+GetSystemInfo(
+ OUT LPSYSTEM_INFO lpSystemInfo)
+{
+ int nrcpus = 0;
+ long pagesize;
+
+ PERF_ENTRY(GetSystemInfo);
+ ENTRY("GetSystemInfo (lpSystemInfo=%p)\n", lpSystemInfo);
+
+ pagesize = getpagesize();
+
+ lpSystemInfo->wProcessorArchitecture_PAL_Undefined = 0;
+ lpSystemInfo->wReserved_PAL_Undefined = 0;
+ lpSystemInfo->dwPageSize = pagesize;
+ lpSystemInfo->dwActiveProcessorMask_PAL_Undefined = 0;
+
+#if HAVE_SYSCONF
+#if defined(_HPUX_) && ( defined (_IA64_) || defined (__hppa__) )
+ struct pst_dynamic psd;
+ if (pstat_getdynamic(&psd, sizeof(psd), (size_t)1, 0) != -1) {
+ nrcpus = psd.psd_proc_cnt;
+ }
+ else {
+ ASSERT("pstat_getdynamic failed (%d)\n", errno);
+ }
+
+#else // !__hppa__
+ nrcpus = sysconf(_SC_NPROCESSORS_ONLN);
+ if (nrcpus < 1)
+ {
+ ASSERT("sysconf failed for _SC_NPROCESSORS_ONLN (%d)\n", errno);
+ }
+#endif // __hppa__
+#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
+
+ TRACE("dwNumberOfProcessors=%d\n", nrcpus);
+ lpSystemInfo->dwNumberOfProcessors = nrcpus;
+
+#ifdef VM_MAXUSER_ADDRESS
+ lpSystemInfo->lpMaximumApplicationAddress = (PVOID) VM_MAXUSER_ADDRESS;
+#elif defined(__sun__) || defined(_AIX) || defined(__hppa__) || ( defined (_IA64_) && defined (_HPUX_) ) || defined(__linux__)
+ lpSystemInfo->lpMaximumApplicationAddress = (PVOID) -1;
+#elif defined(USERLIMIT)
+ lpSystemInfo->lpMaximumApplicationAddress = (PVOID) USERLIMIT;
+#elif defined(_WIN64)
+#if defined(USRSTACK64)
+ lpSystemInfo->lpMaximumApplicationAddress = (PVOID) USRSTACK64;
+#else // !USRSTACK64
+#error How come USRSTACK64 is not defined for 64bit?
+#endif // USRSTACK64
+#elif defined(USRSTACK)
+ lpSystemInfo->lpMaximumApplicationAddress = (PVOID) USRSTACK;
+#else
+#error The maximum application address is not known on this platform.
+#endif
+
+ lpSystemInfo->lpMinimumApplicationAddress = (PVOID) pagesize;
+
+ lpSystemInfo->dwProcessorType_PAL_Undefined = 0;
+
+ lpSystemInfo->dwAllocationGranularity = pagesize;
+
+ lpSystemInfo->wProcessorLevel_PAL_Undefined = 0;
+ lpSystemInfo->wProcessorRevision_PAL_Undefined = 0;
+
+ LOGEXIT("GetSystemInfo returns VOID\n");
+ PERF_EXIT(GetSystemInfo);
+}
+
+/*++
+Function:
+ GlobalMemoryStatusEx
+
+GlobalMemoryStatusEx
+
+Retrieves information about the system's current usage of both physical and virtual memory.
+
+Return Values
+
+This function returns a BOOL to indicate its success status.
+
+--*/
+BOOL
+PALAPI
+GlobalMemoryStatusEx(
+ IN OUT LPMEMORYSTATUSEX lpBuffer)
+{
+
+ PERF_ENTRY(GlobalMemoryStatusEx);
+ ENTRY("GlobalMemoryStatusEx (lpBuffer=%p)\n", lpBuffer);
+
+ lpBuffer->dwMemoryLoad = 0;
+ lpBuffer->ullTotalPhys = 0;
+ lpBuffer->ullAvailPhys = 0;
+ lpBuffer->ullTotalPageFile = 0;
+ lpBuffer->ullAvailPageFile = 0;
+ lpBuffer->ullTotalVirtual = 0;
+ lpBuffer->ullAvailVirtual = 0;
+ lpBuffer->ullAvailExtendedVirtual = 0;
+
+ BOOL fRetVal = FALSE;
+
+ // Get the physical memory size
+#if HAVE_SYSCONF && HAVE__SC_PHYS_PAGES
+ int64_t physical_memory;
+
+ // Get the Physical memory size
+ physical_memory = sysconf( _SC_PHYS_PAGES ) * sysconf( _SC_PAGE_SIZE );
+ lpBuffer->ullTotalPhys = (DWORDLONG)physical_memory;
+ fRetVal = TRUE;
+#elif HAVE_SYSCTL
+ int mib[2];
+ int64_t physical_memory;
+ size_t length;
+
+ // Get the Physical memory size
+ mib[0] = CTL_HW;
+ mib[1] = HW_MEMSIZE;
+ length = sizeof(INT64);
+ int rc = sysctl(mib, 2, &physical_memory, &length, NULL, 0);
+ if (rc != 0)
+ {
+ ASSERT("sysctl failed for HW_MEMSIZE (%d)\n", errno);
+ }
+ else
+ {
+ 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
+
+ // 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.
+ if (lpBuffer->ullTotalPhys > 0)
+ {
+#ifndef __APPLE__
+ lpBuffer->ullAvailPhys = sysconf(SYSCONF_PAGES) * sysconf(_SC_PAGE_SIZE);
+ INT64 used_memory = lpBuffer->ullTotalPhys - lpBuffer->ullAvailPhys;
+ lpBuffer->dwMemoryLoad = (DWORD)((used_memory * 100) / lpBuffer->ullTotalPhys);
+#else
+ vm_size_t page_size;
+ mach_port_t mach_port;
+ mach_msg_type_number_t count;
+ vm_statistics_data_t vm_stats;
+ mach_port = mach_host_self();
+ count = sizeof(vm_stats) / sizeof(natural_t);
+ if (KERN_SUCCESS == host_page_size(mach_port, &page_size))
+ {
+ if (KERN_SUCCESS == host_statistics(mach_port, HOST_VM_INFO, (host_info_t)&vm_stats, &count))
+ {
+ lpBuffer->ullAvailPhys = (int64_t)vm_stats.free_count * (int64_t)page_size;
+ INT64 used_memory = ((INT64)vm_stats.active_count + (INT64)vm_stats.inactive_count + (INT64)vm_stats.wire_count) * (INT64)page_size;
+ lpBuffer->dwMemoryLoad = (DWORD)((used_memory * 100) / lpBuffer->ullTotalPhys);
+ }
+ }
+ mach_port_deallocate(mach_task_self(), mach_port);
+#endif // __APPLE__
+ }
+
+ // There is no API to get the total virtual address space size on
+ // Unix, so we use a constant value representing 128TB, which is
+ // the approximate size of total user virtual address space on
+ // the currently supported Unix systems.
+ static const UINT64 _128TB = (1ull << 47);
+ lpBuffer->ullTotalVirtual = _128TB;
+ lpBuffer->ullAvailVirtual = lpBuffer->ullAvailPhys;
+
+ LOGEXIT("GlobalMemoryStatusEx returns %d\n", fRetVal);
+ PERF_EXIT(GlobalMemoryStatusEx);
+
+ return fRetVal;
+}
+
+PALIMPORT
+DWORD
+PALAPI
+GetCurrentProcessorNumber()
+{
+#if HAVE_SCHED_GETCPU
+ return sched_getcpu();
+#else //HAVE_SCHED_GETCPU
+ return -1;
+#endif //HAVE_SCHED_GETCPU
+}
+
+BOOL
+PALAPI
+PAL_HasGetCurrentProcessorNumber()
+{
+ return HAVE_SCHED_GETCPU;
+}
+
+DWORD
+PALAPI
+PAL_GetLogicalCpuCountFromOS()
+{
+ DWORD numLogicalCores = 0;
+
+#if HAVE_SYSCONF
+ numLogicalCores = sysconf(_SC_NPROCESSORS_ONLN);
+#endif
+
+ return numLogicalCores;
+}
+
+size_t
+PALAPI
+PAL_GetLogicalProcessorCacheSizeFromOS()
+{
+ size_t cacheSize = 0;
+
+#ifdef _SC_LEVEL1_DCACHE_SIZE
+ cacheSize = max(cacheSize, sysconf(_SC_LEVEL1_DCACHE_SIZE));
+#endif
+#ifdef _SC_LEVEL2_CACHE_SIZE
+ cacheSize = max(cacheSize, sysconf(_SC_LEVEL2_CACHE_SIZE));
+#endif
+#ifdef _SC_LEVEL3_CACHE_SIZE
+ cacheSize = max(cacheSize, sysconf(_SC_LEVEL3_CACHE_SIZE));
+#endif
+#ifdef _SC_LEVEL4_CACHE_SIZE
+ cacheSize = max(cacheSize, sysconf(_SC_LEVEL4_CACHE_SIZE));
+#endif
+
+ return cacheSize;
+}