kernel32: Move physical memory status functions to kernelbase.

This commit is contained in:
Alexandre Julliard 2019-11-18 15:05:04 +01:00
parent dad14ab833
commit b73cfa72ed
4 changed files with 83 additions and 276 deletions

View File

@ -30,33 +30,6 @@
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_SYS_SYSCTL_H
#include <sys/sysctl.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_MACH_MACH_H
#include <mach/mach.h>
#endif
#ifdef sun
/* FIXME: Unfortunately swapctl can't be used with largefile.... */
# undef _FILE_OFFSET_BITS
# define _FILE_OFFSET_BITS 32
# ifdef HAVE_SYS_RESOURCE_H
# include <sys/resource.h>
# endif
# ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
# endif
# include <sys/swap.h>
#endif
#include "windef.h"
#include "winbase.h"
@ -66,8 +39,7 @@
#include "wine/exception.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(heap);
WINE_DECLARE_DEBUG_CHANNEL(globalmem);
WINE_DEFAULT_DEBUG_CHANNEL(globalmem);
/* address where we try to map the system heap */
#define SYSTEM_HEAP_BASE ((void*)0x80000000)
@ -590,227 +562,6 @@ SIZE_T WINAPI LocalSize(
}
/***********************************************************************
* GlobalMemoryStatusEx (KERNEL32.@)
* A version of GlobalMemoryStatus that can deal with memory over 4GB
*
* RETURNS
* TRUE
*/
BOOL WINAPI GlobalMemoryStatusEx( LPMEMORYSTATUSEX lpmemex )
{
static MEMORYSTATUSEX cached_memstatus;
static int cache_lastchecked = 0;
SYSTEM_INFO si;
#ifdef linux
FILE *f;
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__)
DWORDLONG total;
#ifdef __APPLE__
unsigned int val;
#else
unsigned long val;
#endif
int mib[2];
size_t size_sys;
#ifdef HW_MEMSIZE
uint64_t val64;
#endif
#ifdef VM_SWAPUSAGE
struct xsw_usage swap;
#endif
#elif defined(sun)
unsigned long pagesize,maxpages,freepages,swapspace,swapfree;
struct anoninfo swapinf;
int rval;
#endif
if (lpmemex->dwLength != sizeof(*lpmemex))
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
if (time(NULL)==cache_lastchecked) {
*lpmemex = cached_memstatus;
return TRUE;
}
cache_lastchecked = time(NULL);
lpmemex->dwMemoryLoad = 0;
lpmemex->ullTotalPhys = 16*1024*1024;
lpmemex->ullAvailPhys = 16*1024*1024;
lpmemex->ullTotalPageFile = 16*1024*1024;
lpmemex->ullAvailPageFile = 16*1024*1024;
#ifdef linux
f = fopen( "/proc/meminfo", "r" );
if (f)
{
char buffer[256];
unsigned long value;
lpmemex->ullTotalPhys = lpmemex->ullAvailPhys = 0;
lpmemex->ullTotalPageFile = lpmemex->ullAvailPageFile = 0;
while (fgets( buffer, sizeof(buffer), f ))
{
if (sscanf(buffer, "MemTotal: %lu", &value))
lpmemex->ullTotalPhys = (ULONG64)value*1024;
else if (sscanf(buffer, "MemFree: %lu", &value))
lpmemex->ullAvailPhys = (ULONG64)value*1024;
else if (sscanf(buffer, "SwapTotal: %lu", &value))
lpmemex->ullTotalPageFile = (ULONG64)value*1024;
else if (sscanf(buffer, "SwapFree: %lu", &value))
lpmemex->ullAvailPageFile = (ULONG64)value*1024;
else if (sscanf(buffer, "Buffers: %lu", &value))
lpmemex->ullAvailPhys += (ULONG64)value*1024;
else if (sscanf(buffer, "Cached: %lu", &value))
lpmemex->ullAvailPhys += (ULONG64)value*1024;
}
fclose( f );
}
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__)
total = 0;
lpmemex->ullAvailPhys = 0;
mib[0] = CTL_HW;
#ifdef HW_MEMSIZE
mib[1] = HW_MEMSIZE;
size_sys = sizeof(val64);
if (!sysctl(mib, 2, &val64, &size_sys, NULL, 0) && size_sys == sizeof(val64) && val64)
total = val64;
#endif
#ifdef HAVE_MACH_MACH_H
{
host_name_port_t host = mach_host_self();
mach_msg_type_number_t count;
#ifdef HOST_VM_INFO64_COUNT
vm_size_t page_size;
vm_statistics64_data_t vm_stat;
count = HOST_VM_INFO64_COUNT;
if (host_statistics64(host, HOST_VM_INFO64, (host_info64_t)&vm_stat, &count) == KERN_SUCCESS &&
host_page_size(host, &page_size) == KERN_SUCCESS)
lpmemex->ullAvailPhys = (vm_stat.free_count + vm_stat.inactive_count) * (DWORDLONG)page_size;
#endif
if (!total)
{
host_basic_info_data_t info;
count = HOST_BASIC_INFO_COUNT;
if (host_info(host, HOST_BASIC_INFO, (host_info_t)&info, &count) == KERN_SUCCESS)
total = info.max_mem;
}
mach_port_deallocate(mach_task_self(), host);
}
#endif
if (!total)
{
mib[1] = HW_PHYSMEM;
size_sys = sizeof(val);
if (!sysctl(mib, 2, &val, &size_sys, NULL, 0) && size_sys == sizeof(val) && val)
total = val;
}
if (total)
lpmemex->ullTotalPhys = total;
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;
lpmemex->ullAvailPageFile = lpmemex->ullAvailPhys;
#ifdef VM_SWAPUSAGE
mib[0] = CTL_VM;
mib[1] = VM_SWAPUSAGE;
size_sys = sizeof(swap);
if (!sysctl(mib, 2, &swap, &size_sys, NULL, 0) && size_sys == sizeof(swap))
{
lpmemex->ullTotalPageFile = swap.xsu_total;
lpmemex->ullAvailPageFile = swap.xsu_avail;
}
#endif
#elif defined ( sun )
pagesize=sysconf(_SC_PAGESIZE);
maxpages=sysconf(_SC_PHYS_PAGES);
freepages=sysconf(_SC_AVPHYS_PAGES);
rval=swapctl(SC_AINFO, &swapinf);
if(rval >-1)
{
swapspace=swapinf.ani_max*pagesize;
swapfree=swapinf.ani_free*pagesize;
}else
{
WARN("Swap size cannot be determined , assuming equal to physical memory\n");
swapspace=maxpages*pagesize;
swapfree=maxpages*pagesize;
}
lpmemex->ullTotalPhys=pagesize*maxpages;
lpmemex->ullAvailPhys = pagesize*freepages;
lpmemex->ullTotalPageFile = swapspace;
lpmemex->ullAvailPageFile = swapfree;
#endif
if (lpmemex->ullTotalPhys)
{
lpmemex->dwMemoryLoad = (lpmemex->ullTotalPhys-lpmemex->ullAvailPhys)
/ (lpmemex->ullTotalPhys / 100);
}
/* Win98 returns only the swapsize in ullTotalPageFile/ullAvailPageFile,
WinXP returns the size of physical memory + swapsize;
mimic the behavior of XP.
Note: Project2k refuses to start if it sees less than 1Mb of free swap.
*/
lpmemex->ullTotalPageFile += lpmemex->ullTotalPhys;
lpmemex->ullAvailPageFile += lpmemex->ullAvailPhys;
/* Titan Quest refuses to run if TotalPageFile <= ullTotalPhys */
if(lpmemex->ullTotalPageFile == lpmemex->ullTotalPhys)
{
lpmemex->ullTotalPhys -= 1;
lpmemex->ullAvailPhys -= 1;
}
/* FIXME: should do something for other systems */
GetSystemInfo(&si);
lpmemex->ullTotalVirtual = (ULONG_PTR)si.lpMaximumApplicationAddress-(ULONG_PTR)si.lpMinimumApplicationAddress;
/* FIXME: we should track down all the already allocated VM pages and subtract them, for now arbitrarily remove 64KB so that it matches NT */
lpmemex->ullAvailVirtual = lpmemex->ullTotalVirtual-64*1024;
/* MSDN says about AvailExtendedVirtual: Size of unreserved and uncommitted
memory in the extended portion of the virtual address space of the calling
process, in bytes.
However, I don't know what this means, so set it to zero :(
*/
lpmemex->ullAvailExtendedVirtual = 0;
cached_memstatus = *lpmemex;
TRACE_(globalmem)("<-- LPMEMORYSTATUSEX: dwLength %d, dwMemoryLoad %d, ullTotalPhys %s, ullAvailPhys %s,"
" ullTotalPageFile %s, ullAvailPageFile %s, ullTotalVirtual %s, ullAvailVirtual %s\n",
lpmemex->dwLength, lpmemex->dwMemoryLoad, wine_dbgstr_longlong(lpmemex->ullTotalPhys),
wine_dbgstr_longlong(lpmemex->ullAvailPhys), wine_dbgstr_longlong(lpmemex->ullTotalPageFile),
wine_dbgstr_longlong(lpmemex->ullAvailPageFile), wine_dbgstr_longlong(lpmemex->ullTotalVirtual),
wine_dbgstr_longlong(lpmemex->ullAvailVirtual) );
return TRUE;
}
/***********************************************************************
* GlobalMemoryStatus (KERNEL32.@)
* Provides information about the status of the memory, so apps can tell
@ -884,30 +635,9 @@ VOID WINAPI GlobalMemoryStatus( LPMEMORYSTATUS lpBuffer )
if (lpBuffer->dwAvailPageFile > MAXLONG) lpBuffer->dwAvailPageFile = MAXLONG;
}
TRACE_(globalmem)("Length %u, MemoryLoad %u, TotalPhys %lx, AvailPhys %lx,"
TRACE("Length %u, MemoryLoad %u, TotalPhys %lx, AvailPhys %lx,"
" TotalPageFile %lx, AvailPageFile %lx, TotalVirtual %lx, AvailVirtual %lx\n",
lpBuffer->dwLength, lpBuffer->dwMemoryLoad, lpBuffer->dwTotalPhys,
lpBuffer->dwAvailPhys, lpBuffer->dwTotalPageFile, lpBuffer->dwAvailPageFile,
lpBuffer->dwTotalVirtual, lpBuffer->dwAvailVirtual );
}
/***********************************************************************
* GetPhysicallyInstalledSystemMemory (KERNEL32.@)
*/
BOOL WINAPI GetPhysicallyInstalledSystemMemory(ULONGLONG *total_memory)
{
MEMORYSTATUSEX memstatus;
FIXME("stub: %p\n", total_memory);
if (!total_memory)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
memstatus.dwLength = sizeof(memstatus);
GlobalMemoryStatusEx(&memstatus);
*total_memory = memstatus.ullTotalPhys / 1024;
return TRUE;
}

View File

@ -762,7 +762,7 @@
@ stdcall -import GetOverlappedResult(long ptr ptr long)
@ stdcall GetUserPreferredUILanguages(long ptr ptr ptr)
@ stdcall GetPackageFullName(long ptr ptr)
@ stdcall GetPhysicallyInstalledSystemMemory(ptr)
@ stdcall -import GetPhysicallyInstalledSystemMemory(ptr)
@ stdcall -import GetPriorityClass(long)
@ stdcall GetPrivateProfileIntA(str str long str)
@ stdcall GetPrivateProfileIntW(wstr wstr long wstr)
@ -906,7 +906,7 @@
@ stdcall GlobalHandle(ptr)
@ stdcall GlobalLock(long)
@ stdcall GlobalMemoryStatus(ptr)
@ stdcall GlobalMemoryStatusEx(ptr)
@ stdcall -import GlobalMemoryStatusEx(ptr)
@ stdcall GlobalReAlloc(long long long)
@ stdcall GlobalSize(long)
@ stdcall GlobalUnWire(long)

View File

@ -614,7 +614,7 @@
# @ stub GetPackageVolumeSisPath
# @ stub GetPackagesByPackageFamily
# @ stub GetPerformanceInfo
@ stdcall GetPhysicallyInstalledSystemMemory(ptr) kernel32.GetPhysicallyInstalledSystemMemory
@ stdcall GetPhysicallyInstalledSystemMemory(ptr)
# @ stub GetPreviousFgPolicyRefreshInfoInternal
@ stdcall GetPriorityClass(long)
@ stdcall GetPrivateObjectSecurity(ptr long ptr long ptr)
@ -767,7 +767,7 @@
# @ stub GetXStateFeaturesMask
@ stdcall GlobalAlloc(long long)
@ stdcall GlobalFree(long)
@ stdcall GlobalMemoryStatusEx(ptr) kernel32.GlobalMemoryStatusEx
@ stdcall GlobalMemoryStatusEx(ptr)
# @ stub GuardCheckLongJumpTarget
# @ stub HasPolicyForegroundProcessingCompletedInternal
@ stdcall HashData(ptr long ptr long)

View File

@ -38,6 +38,7 @@
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(heap);
WINE_DECLARE_DEBUG_CHANNEL(virtual);
/***********************************************************************
@ -816,6 +817,82 @@ BOOL WINAPI DECLSPEC_HOTPATCH FreeUserPhysicalPages( HANDLE process, ULONG_PTR *
}
/***********************************************************************
* GetPhysicallyInstalledSystemMemory (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH GetPhysicallyInstalledSystemMemory( ULONGLONG *memory )
{
MEMORYSTATUSEX status;
if (!memory)
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
status.dwLength = sizeof(status);
GlobalMemoryStatusEx( &status );
*memory = status.ullTotalPhys / 1024;
return TRUE;
}
/***********************************************************************
* GlobalMemoryStatusEx (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH GlobalMemoryStatusEx( MEMORYSTATUSEX *status )
{
static MEMORYSTATUSEX cached_status;
static DWORD last_check;
SYSTEM_BASIC_INFORMATION basic_info;
SYSTEM_PERFORMANCE_INFORMATION perf_info;
if (status->dwLength != sizeof(*status))
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
if ((NtGetTickCount() - last_check) < 1000)
{
*status = cached_status;
return TRUE;
}
last_check = NtGetTickCount();
if (!set_ntstatus( NtQuerySystemInformation( SystemBasicInformation,
&basic_info, sizeof(basic_info), NULL )) ||
!set_ntstatus( NtQuerySystemInformation( SystemPerformanceInformation,
&perf_info, sizeof(perf_info), NULL)))
return FALSE;
status->dwMemoryLoad = 0;
status->ullTotalPhys = perf_info.TotalCommitLimit;
status->ullAvailPhys = perf_info.AvailablePages;
status->ullTotalPageFile = perf_info.TotalCommitLimit + 1; /* Titan Quest refuses to run if TotalPageFile <= TotalPhys */
status->ullAvailPageFile = status->ullTotalPageFile - perf_info.TotalCommittedPages - perf_info.AvailablePages;
status->ullTotalVirtual = (ULONG_PTR)basic_info.HighestUserAddress - (ULONG_PTR)basic_info.LowestUserAddress;
status->ullAvailVirtual = status->ullTotalVirtual - 64 * 1024; /* FIXME */
status->ullAvailExtendedVirtual = 0;
status->ullTotalPhys *= basic_info.PageSize;
status->ullAvailPhys *= basic_info.PageSize;
status->ullTotalPageFile *= basic_info.PageSize;
status->ullAvailPageFile *= basic_info.PageSize;
if (status->ullTotalPhys)
status->dwMemoryLoad = (status->ullTotalPhys - status->ullAvailPhys) / (status->ullTotalPhys / 100);
TRACE_(virtual)( "MemoryLoad %d, TotalPhys %s, AvailPhys %s, TotalPageFile %s,"
"AvailPageFile %s, TotalVirtual %s, AvailVirtual %s\n",
status->dwMemoryLoad, wine_dbgstr_longlong(status->ullTotalPhys),
wine_dbgstr_longlong(status->ullAvailPhys), wine_dbgstr_longlong(status->ullTotalPageFile),
wine_dbgstr_longlong(status->ullAvailPageFile), wine_dbgstr_longlong(status->ullTotalVirtual),
wine_dbgstr_longlong(status->ullAvailVirtual) );
cached_status = *status;
return TRUE;
}
/***********************************************************************
* MapUserPhysicalPages (kernelbase.@)
*/