From: Ken Thomases Subject: [PATCH 7/7] kernel32: Prefer the Mach host_statistics64(HOST_VM_INFO64) API over sysctl(HW_USERMEM) to obtain free memory. Message-Id: Date: Sun, 16 Feb 2014 20:43:48 -0600 On OS X, at least, HW_USERMEM is a 32-bit value. Furthermore, it's computed by subtracting the amount of wired memory from HW_PHYSMEM, which is capped at 2GB. So, it's wildly inaccurate on modern systems. For . --- dlls/kernel32/heap.c | 47 +++++++++++++++++++++++++++++++++-------------- 1 files changed, 33 insertions(+), 14 deletions(-) diff --git a/dlls/kernel32/heap.c b/dlls/kernel32/heap.c index cd3a752..1c38ae5 100644 --- a/dlls/kernel32/heap.c +++ b/dlls/kernel32/heap.c @@ -1164,6 +1164,14 @@ BOOL WINAPI GlobalMemoryStatusEx( LPMEMORYSTATUSEX lpmemex ) #ifdef VM_SWAPUSAGE struct xsw_usage swap; #endif +#ifdef HAVE_MACH_MACH_H + host_name_port_t host; + mach_msg_type_number_t count; + kern_return_t kr; + host_basic_info_data_t info; + vm_statistics64_data_t vm_stat; + vm_size_t page_size; +#endif #elif defined(sun) unsigned long pagesize,maxpages,freepages,swapspace,swapfree; struct anoninfo swapinf; @@ -1240,22 +1248,22 @@ BOOL WINAPI GlobalMemoryStatusEx( LPMEMORYSTATUSEX lpmemex ) #endif #ifdef HAVE_MACH_MACH_H + host = mach_host_self(); + if (!total) { - host_name_port_t host; - mach_msg_type_number_t count; - kern_return_t kr; - host_basic_info_data_t info; - - host = mach_host_self(); - count = HOST_BASIC_INFO_COUNT; kr = host_info(host, HOST_BASIC_INFO, (host_info_t)&info, &count); if (kr == KERN_SUCCESS) total = info.max_mem; - - mach_port_deallocate(mach_task_self(), host); } + + count = HOST_VM_INFO64_COUNT; + kr = host_statistics64(host, HOST_VM_INFO64, (host_info64_t)&vm_stat, &count); + if (kr == KERN_SUCCESS) + kr = host_page_size(host, &page_size); + + mach_port_deallocate(mach_task_self(), host); #endif if (!total) @@ -1269,11 +1277,22 @@ BOOL WINAPI GlobalMemoryStatusEx( LPMEMORYSTATUSEX lpmemex ) if (total) lpmemex->ullTotalPhys = total; - mib[1] = HW_USERMEM; - size_sys = sizeof(val); - if (!sysctl(mib, 2, &val, &size_sys, NULL, 0) && size_sys == sizeof(val) && val) - lpmemex->ullAvailPhys = val; - else + lpmemex->ullAvailPhys = 0; + +#ifdef HAVE_MACH_MACH_H + if (kr == KERN_SUCCESS) + lpmemex->ullAvailPhys = (vm_stat.free_count + vm_stat.inactive_count) * (DWORDLONG)page_size; +#endif + + if (!lpmemex->ullAvailPhys) + { + mib[1] = HW_USERMEM; + size_sys = sizeof(val); + if (!sysctl(mib, 2, &val, &size_sys, NULL, 0) && size_sys == sizeof(val) && val) + lpmemex->ullAvailPhys = val; + } + + if (!lpmemex->ullAvailPhys) lpmemex->ullAvailPhys = lpmemex->ullTotalPhys; lpmemex->ullTotalPageFile = lpmemex->ullAvailPhys;