From: Akihiro Sagawa Subject: [PATCH 2/4] ntdll: Provide more accurate virtual memory counters. Message-Id: <20170604223626.8618.375B48EC@gmail.com> Date: Sun, 04 Jun 2017 22:37:36 +0900 Current approach is less accurate because VmSize from /proc/self/status contains Wine's reserved area by mmap(2). Thus, the counter doesn't reflect VirtualAlloc()/VirtualFree() simultaneously. This approach is keeping process own VM counters inside ntdll.dll. So, we can provide more accurate values for Windows applications. To avoid wineserver round-trip overheads when allocating, it is implemented as variables in dlls/ntdll/virtual.c. Signed-off-by: Akihiro Sagawa --- dlls/ntdll/ntdll_misc.h | 1 + dlls/ntdll/process.c | 18 ++++++++++++------ dlls/ntdll/tests/info.c | 2 +- dlls/ntdll/virtual.c | 41 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 54 insertions(+), 8 deletions(-) diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 5e4c39e..aa385af 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -162,6 +162,7 @@ extern NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, ANSI_S /* virtual memory */ extern void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info ) DECLSPEC_HIDDEN; +extern void virtual_get_memory_counters( SIZE_T *current, SIZE_T *peak ) DECLSPEC_HIDDEN; extern NTSTATUS virtual_create_builtin_view( void *base ) DECLSPEC_HIDDEN; extern NTSTATUS virtual_alloc_thread_stack( TEB *teb, SIZE_T reserve_size, SIZE_T commit_size ) DECLSPEC_HIDDEN; extern void virtual_clear_thread_stack(void) DECLSPEC_HIDDEN; diff --git a/dlls/ntdll/process.c b/dlls/ntdll/process.c index f615ce2..1d0a703 100644 --- a/dlls/ntdll/process.c +++ b/dlls/ntdll/process.c @@ -123,7 +123,6 @@ static void fill_VM_COUNTERS(VM_COUNTERS* pvmi) mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT; if(task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &infoCount) == KERN_SUCCESS) { - pvmi->VirtualSize = info.resident_size + info.virtual_size; pvmi->PagefileUsage = info.virtual_size; pvmi->WorkingSetSize = info.resident_size; pvmi->PeakWorkingSetSize = info.resident_size_max; @@ -144,11 +143,7 @@ static void fill_VM_COUNTERS(VM_COUNTERS* pvmi) while (fgets(line, sizeof(line), f)) { - if (sscanf(line, "VmPeak: %lu", &value)) - pvmi->PeakVirtualSize = (ULONG64)value * 1024; - else if (sscanf(line, "VmSize: %lu", &value)) - pvmi->VirtualSize = (ULONG64)value * 1024; - else if (sscanf(line, "VmHWM: %lu", &value)) + if (sscanf(line, "VmHWM: %lu", &value)) pvmi->PeakWorkingSetSize = (ULONG64)value * 1024; else if (sscanf(line, "VmRSS: %lu", &value)) pvmi->WorkingSetSize = (ULONG64)value * 1024; @@ -301,7 +296,10 @@ NTSTATUS WINAPI NtQueryInformationProcess( { memset(&pvmi, 0 , sizeof(VM_COUNTERS)); if (ProcessHandle == GetCurrentProcess()) + { + virtual_get_memory_counters(&pvmi.VirtualSize, &pvmi.PeakVirtualSize); fill_VM_COUNTERS(&pvmi); + } else { SERVER_START_REQ(get_process_vm_counters) @@ -320,6 +318,14 @@ NTSTATUS WINAPI NtQueryInformationProcess( SERVER_END_REQ; if (ret) break; } + if (pvmi.PeakWorkingSetSize > pvmi.PeakVirtualSize) + pvmi.PeakWorkingSetSize = pvmi.PeakVirtualSize; + if (pvmi.WorkingSetSize > pvmi.VirtualSize) + pvmi.WorkingSetSize = pvmi.VirtualSize; + if (pvmi.PagefileUsage > pvmi.VirtualSize) + pvmi.PagefileUsage = pvmi.VirtualSize; + if (pvmi.PeakPagefileUsage > pvmi.PeakVirtualSize) + pvmi.PeakPagefileUsage = pvmi.PeakVirtualSize; len = ProcessInformationLength; if (len != FIELD_OFFSET(VM_COUNTERS,PrivatePageCount)) len = sizeof(VM_COUNTERS); diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c index 4198d9c..5e42045 100644 --- a/dlls/ntdll/tests/info.c +++ b/dlls/ntdll/tests/info.c @@ -1135,7 +1135,7 @@ static void test_query_process_vm(void) ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status); if (winetest_debug > 1) dump_vm_counters("VM counters after VirtualAlloc", &pvi); - todo_wine ok( pvi.VirtualSize >= prev_size + alloc_size, + ok( pvi.VirtualSize >= prev_size + alloc_size, "Expected to be greater than %lu, got %lu\n", prev_size + alloc_size, pvi.VirtualSize); VirtualFree( ptr, 0, MEM_RELEASE); } diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index e826fa0..d19d31b 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -108,6 +108,10 @@ static RTL_CRITICAL_SECTION_DEBUG critsect_debug = 0, 0, { (DWORD_PTR)(__FILE__ ": csVirtual") } }; static RTL_CRITICAL_SECTION csVirtual = { &critsect_debug, -1, 0, 0, 0, 0 }; +static struct { + SIZE_T size; + SIZE_T peak; +} vm_counters; #ifdef __i386__ static const UINT page_shift = 12; @@ -438,7 +442,13 @@ static inline void unmap_area( void *addr, size_t size ) */ static void delete_view( struct file_view *view ) /* [in] View */ { - if (!(view->protect & VPROT_SYSTEM)) unmap_area( view->base, view->size ); + if (!(view->protect & VPROT_SYSTEM)) + { + unmap_area( view->base, view->size ); + + /* Decrement VM counters */ + vm_counters.size -= view->size; + } list_remove( &view->entry ); if (view->mapping) close_handle( view->mapping ); RtlFreeHeap( virtual_heap, 0, view ); @@ -512,6 +522,15 @@ static NTSTATUS create_view( struct file_view **view_ret, void *base, size_t siz } } + /* Increment VM counters */ + + if (!(vprot & VPROT_SYSTEM)) + { + vm_counters.size += size; + if (vm_counters.peak < vm_counters.size) + vm_counters.peak = vm_counters.size; + } + *view_ret = view; VIRTUAL_DEBUG_DUMP_VIEW( view ); @@ -1385,6 +1404,26 @@ void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info ) /*********************************************************************** + * virtual_get_memory_counters + */ +void virtual_get_memory_counters( SIZE_T *current, SIZE_T *peak ) +{ + sigset_t sigset; + server_enter_uninterrupted_section( &csVirtual, &sigset ); + + *current = min(vm_counters.size, (SIZE_T)user_space_limit); + *peak = min(vm_counters.peak, (SIZE_T)user_space_limit); + + server_leave_uninterrupted_section( &csVirtual, &sigset ); + + TRACE("current=%s, peak=%s\n", + wine_dbgstr_longlong((ULONGLONG)*current), + wine_dbgstr_longlong((ULONGLONG)*peak)); + +} + + +/*********************************************************************** * virtual_create_builtin_view */ NTSTATUS virtual_create_builtin_view( void *module ) -- 2.7.4