1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
15 Implements GetSystemInfo.
23 #include "pal/palinternal.h"
28 #include <sys/types.h>
30 #include <sys/sysctl.h>
32 #error Either sysctl or sysconf is required for GetSystemInfo.
35 #include <sys/param.h>
37 #if HAVE_SYS_VMPARAM_H
38 #include <sys/vmparam.h>
39 #endif // HAVE_SYS_VMPARAM_H
41 #if HAVE_MACH_VM_TYPES_H
42 #include <mach/vm_types.h>
43 #endif // HAVE_MACH_VM_TYPES_H
45 #if HAVE_MACH_VM_PARAM_H
46 #include <mach/vm_param.h>
47 #endif // HAVE_MACH_VM_PARAM_H
49 #if HAVE_MACHINE_VMPARAM_H
50 #include <machine/vmparam.h>
51 #endif // HAVE_MACHINE_VMPARAM_H
53 #if defined(_TARGET_MAC64)
54 #include <mach/vm_statistics.h>
55 #include <mach/mach_types.h>
56 #include <mach/mach_init.h>
57 #include <mach/mach_host.h>
58 #endif // defined(_TARGET_MAC64)
60 // On some platforms sys/user.h ends up defining _DEBUG; if so
61 // remove the definition before including the header and put
62 // back our definition afterwards
63 #if USER_H_DEFINES_DEBUG
64 #define OLD_DEBUG _DEBUG
68 #if USER_H_DEFINES_DEBUG
70 #define _DEBUG OLD_DEBUG
74 #include "pal/dbgmsg.h"
77 SET_DEFAULT_DEBUG_CHANNEL(MISC);
80 #if HAVE_SYSCONF && HAVE__SC_AVPHYS_PAGES
81 #define SYSCONF_PAGES _SC_AVPHYS_PAGES
82 #elif HAVE_SYSCONF && HAVE__SC_PHYS_PAGES
83 #define SYSCONF_PAGES _SC_PHYS_PAGES
85 #error Dont know how to get page-size on this architecture!
96 The GetSystemInfo function returns information about the current system.
101 [out] Pointer to a SYSTEM_INFO structure that receives the information.
105 This function does not return a value.
108 fields returned by this function are:
111 Others are set to zero.
117 OUT LPSYSTEM_INFO lpSystemInfo)
122 PERF_ENTRY(GetSystemInfo);
123 ENTRY("GetSystemInfo (lpSystemInfo=%p)\n", lpSystemInfo);
125 pagesize = getpagesize();
127 lpSystemInfo->wProcessorArchitecture_PAL_Undefined = 0;
128 lpSystemInfo->wReserved_PAL_Undefined = 0;
129 lpSystemInfo->dwPageSize = pagesize;
130 lpSystemInfo->dwActiveProcessorMask_PAL_Undefined = 0;
133 nrcpus = sysconf(_SC_NPROCESSORS_ONLN);
136 ASSERT("sysconf failed for _SC_NPROCESSORS_ONLN (%d)\n", errno);
146 rc = sysctl(mib, 2, &nrcpus, &sz, NULL, 0);
149 ASSERT("sysctl failed for HW_NCPU (%d)\n", errno);
151 #endif // HAVE_SYSCONF
153 TRACE("dwNumberOfProcessors=%d\n", nrcpus);
154 lpSystemInfo->dwNumberOfProcessors = nrcpus;
156 #ifdef VM_MAXUSER_ADDRESS
157 lpSystemInfo->lpMaximumApplicationAddress = (PVOID) VM_MAXUSER_ADDRESS;
158 #elif defined(__linux__)
159 lpSystemInfo->lpMaximumApplicationAddress = (PVOID) (1ull << 47);
160 #elif defined(USERLIMIT)
161 lpSystemInfo->lpMaximumApplicationAddress = (PVOID) USERLIMIT;
162 #elif defined(_WIN64)
163 #if defined(USRSTACK64)
164 lpSystemInfo->lpMaximumApplicationAddress = (PVOID) USRSTACK64;
166 #error How come USRSTACK64 is not defined for 64bit?
168 #elif defined(USRSTACK)
169 lpSystemInfo->lpMaximumApplicationAddress = (PVOID) USRSTACK;
171 #error The maximum application address is not known on this platform.
174 lpSystemInfo->lpMinimumApplicationAddress = (PVOID) pagesize;
176 lpSystemInfo->dwProcessorType_PAL_Undefined = 0;
178 lpSystemInfo->dwAllocationGranularity = pagesize;
180 lpSystemInfo->wProcessorLevel_PAL_Undefined = 0;
181 lpSystemInfo->wProcessorRevision_PAL_Undefined = 0;
183 LOGEXIT("GetSystemInfo returns VOID\n");
184 PERF_EXIT(GetSystemInfo);
193 Retrieves information about the system's current usage of both physical and virtual memory.
197 This function returns a BOOL to indicate its success status.
202 GlobalMemoryStatusEx(
203 IN OUT LPMEMORYSTATUSEX lpBuffer)
206 PERF_ENTRY(GlobalMemoryStatusEx);
207 ENTRY("GlobalMemoryStatusEx (lpBuffer=%p)\n", lpBuffer);
209 lpBuffer->dwMemoryLoad = 0;
210 lpBuffer->ullTotalPhys = 0;
211 lpBuffer->ullAvailPhys = 0;
212 lpBuffer->ullTotalPageFile = 0;
213 lpBuffer->ullAvailPageFile = 0;
214 lpBuffer->ullTotalVirtual = 0;
215 lpBuffer->ullAvailVirtual = 0;
216 lpBuffer->ullAvailExtendedVirtual = 0;
218 BOOL fRetVal = FALSE;
220 // Get the physical memory size
221 #if HAVE_SYSCONF && HAVE__SC_PHYS_PAGES
222 int64_t physical_memory;
224 // Get the Physical memory size
225 physical_memory = sysconf( _SC_PHYS_PAGES ) * sysconf( _SC_PAGE_SIZE );
226 lpBuffer->ullTotalPhys = (DWORDLONG)physical_memory;
230 int64_t physical_memory;
233 // Get the Physical memory size
236 length = sizeof(INT64);
237 int rc = sysctl(mib, 2, &physical_memory, &length, NULL, 0);
240 ASSERT("sysctl failed for HW_MEMSIZE (%d)\n", errno);
244 lpBuffer->ullTotalPhys = (DWORDLONG)physical_memory;
247 #elif // HAVE_SYSINFO
248 // TODO: implement getting memory details via sysinfo. On Linux, it provides swap file details that
249 // we can use to fill in the xxxPageFile members.
251 #endif // HAVE_SYSCONF
253 // Get the physical memory in use - from it, we can get the physical memory available.
254 // We do this only when we have the total physical memory available.
255 if (lpBuffer->ullTotalPhys > 0)
258 lpBuffer->ullAvailPhys = sysconf(SYSCONF_PAGES) * sysconf(_SC_PAGE_SIZE);
259 INT64 used_memory = lpBuffer->ullTotalPhys - lpBuffer->ullAvailPhys;
260 lpBuffer->dwMemoryLoad = (DWORD)((used_memory * 100) / lpBuffer->ullTotalPhys);
263 mach_port_t mach_port;
264 mach_msg_type_number_t count;
265 vm_statistics_data_t vm_stats;
266 mach_port = mach_host_self();
267 count = sizeof(vm_stats) / sizeof(natural_t);
268 if (KERN_SUCCESS == host_page_size(mach_port, &page_size))
270 if (KERN_SUCCESS == host_statistics(mach_port, HOST_VM_INFO, (host_info_t)&vm_stats, &count))
272 lpBuffer->ullAvailPhys = (int64_t)vm_stats.free_count * (int64_t)page_size;
273 INT64 used_memory = ((INT64)vm_stats.active_count + (INT64)vm_stats.inactive_count + (INT64)vm_stats.wire_count) * (INT64)page_size;
274 lpBuffer->dwMemoryLoad = (DWORD)((used_memory * 100) / lpBuffer->ullTotalPhys);
277 mach_port_deallocate(mach_task_self(), mach_port);
281 // There is no API to get the total virtual address space size on
282 // Unix, so we use a constant value representing 128TB, which is
283 // the approximate size of total user virtual address space on
284 // the currently supported Unix systems.
285 static const UINT64 _128TB = (1ull << 47);
286 lpBuffer->ullTotalVirtual = _128TB;
287 lpBuffer->ullAvailVirtual = lpBuffer->ullAvailPhys;
289 LOGEXIT("GlobalMemoryStatusEx returns %d\n", fRetVal);
290 PERF_EXIT(GlobalMemoryStatusEx);
298 GetCurrentProcessorNumber()
300 #if HAVE_SCHED_GETCPU
301 return sched_getcpu();
302 #else //HAVE_SCHED_GETCPU
304 #endif //HAVE_SCHED_GETCPU
309 PAL_HasGetCurrentProcessorNumber()
311 return HAVE_SCHED_GETCPU;
316 PAL_GetLogicalCpuCountFromOS()
318 DWORD numLogicalCores = 0;
321 numLogicalCores = sysconf(_SC_NPROCESSORS_ONLN);
324 return numLogicalCores;
329 PAL_GetLogicalProcessorCacheSizeFromOS()
331 size_t cacheSize = 0;
333 #ifdef _SC_LEVEL1_DCACHE_SIZE
334 cacheSize = max(cacheSize, sysconf(_SC_LEVEL1_DCACHE_SIZE));
336 #ifdef _SC_LEVEL2_CACHE_SIZE
337 cacheSize = max(cacheSize, sysconf(_SC_LEVEL2_CACHE_SIZE));
339 #ifdef _SC_LEVEL3_CACHE_SIZE
340 cacheSize = max(cacheSize, sysconf(_SC_LEVEL3_CACHE_SIZE));
342 #ifdef _SC_LEVEL4_CACHE_SIZE
343 cacheSize = max(cacheSize, sysconf(_SC_LEVEL4_CACHE_SIZE));