ntdll: Implement ProcessVmCounters for Linux for other processes.
Signed-off-by: Alex Henrie <alexhenrie24@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
47fca41f42
commit
19a79f4228
|
@ -294,15 +294,29 @@ NTSTATUS WINAPI NtQueryInformationProcess(
|
|||
{
|
||||
if (!ProcessInformation)
|
||||
ret = STATUS_ACCESS_VIOLATION;
|
||||
else if (!ProcessHandle)
|
||||
ret = STATUS_INVALID_HANDLE;
|
||||
else
|
||||
{
|
||||
memset(&pvmi, 0 , sizeof(VM_COUNTERS));
|
||||
if (ProcessHandle == GetCurrentProcess())
|
||||
fill_VM_COUNTERS(&pvmi);
|
||||
else
|
||||
FIXME("Need wineserver call to get VM counters for another process\n");
|
||||
{
|
||||
SERVER_START_REQ(get_process_vm_counters)
|
||||
{
|
||||
req->handle = wine_server_obj_handle( ProcessHandle );
|
||||
if (!(ret = wine_server_call( req )))
|
||||
{
|
||||
pvmi.PeakVirtualSize = reply->peak_virtual_size;
|
||||
pvmi.VirtualSize = reply->virtual_size;
|
||||
pvmi.PeakWorkingSetSize = reply->peak_working_set_size;
|
||||
pvmi.WorkingSetSize = reply->working_set_size;
|
||||
pvmi.PagefileUsage = reply->pagefile_usage;
|
||||
pvmi.PeakPagefileUsage = reply->peak_pagefile_usage;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (ret) break;
|
||||
}
|
||||
|
||||
len = ProcessInformationLength;
|
||||
if (len != FIELD_OFFSET(VM_COUNTERS,PrivatePageCount)) len = sizeof(VM_COUNTERS);
|
||||
|
|
|
@ -1052,6 +1052,7 @@ static void test_query_process_vm(void)
|
|||
ULONG ReturnLength;
|
||||
VM_COUNTERS pvi;
|
||||
ULONG old_size = FIELD_OFFSET(VM_COUNTERS,PrivatePageCount);
|
||||
HANDLE process;
|
||||
|
||||
status = pNtQueryInformationProcess(NULL, ProcessVmCounters, NULL, sizeof(pvi), NULL);
|
||||
ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
|
||||
|
@ -1079,6 +1080,27 @@ static void test_query_process_vm(void)
|
|||
/* Check if we have some return values */
|
||||
trace("WorkingSetSize : %ld\n", pvi.WorkingSetSize);
|
||||
ok( pvi.WorkingSetSize > 0, "Expected a WorkingSetSize > 0\n");
|
||||
|
||||
process = OpenProcess(PROCESS_VM_READ, FALSE, GetCurrentProcessId());
|
||||
status = pNtQueryInformationProcess(process, ProcessVmCounters, &pvi, sizeof(pvi), NULL);
|
||||
ok( status == STATUS_ACCESS_DENIED, "Expected STATUS_ACCESS_DENIED, got %08x\n", status);
|
||||
CloseHandle(process);
|
||||
|
||||
process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, GetCurrentProcessId());
|
||||
status = pNtQueryInformationProcess(process, ProcessVmCounters, &pvi, sizeof(pvi), NULL);
|
||||
ok( status == STATUS_SUCCESS || broken(!process) /* XP */, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
CloseHandle(process);
|
||||
|
||||
memset(&pvi, 0, sizeof(pvi));
|
||||
process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
|
||||
status = pNtQueryInformationProcess(process, ProcessVmCounters, &pvi, sizeof(pvi), NULL);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
|
||||
/* Check if we have some return values */
|
||||
trace("WorkingSetSize : %ld\n", pvi.WorkingSetSize);
|
||||
ok( pvi.WorkingSetSize > 0, "Expected a WorkingSetSize > 0\n");
|
||||
|
||||
CloseHandle(process);
|
||||
}
|
||||
|
||||
static void test_query_process_io(void)
|
||||
|
|
|
@ -885,6 +885,24 @@ struct get_process_info_reply
|
|||
|
||||
|
||||
|
||||
struct get_process_vm_counters_request
|
||||
{
|
||||
struct request_header __header;
|
||||
obj_handle_t handle;
|
||||
};
|
||||
struct get_process_vm_counters_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
mem_size_t peak_virtual_size;
|
||||
mem_size_t virtual_size;
|
||||
mem_size_t peak_working_set_size;
|
||||
mem_size_t working_set_size;
|
||||
mem_size_t pagefile_usage;
|
||||
mem_size_t peak_pagefile_usage;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct set_process_info_request
|
||||
{
|
||||
struct request_header __header;
|
||||
|
@ -5541,6 +5559,7 @@ enum request
|
|||
REQ_terminate_process,
|
||||
REQ_terminate_thread,
|
||||
REQ_get_process_info,
|
||||
REQ_get_process_vm_counters,
|
||||
REQ_set_process_info,
|
||||
REQ_get_thread_info,
|
||||
REQ_get_thread_times,
|
||||
|
@ -5831,6 +5850,7 @@ union generic_request
|
|||
struct terminate_process_request terminate_process_request;
|
||||
struct terminate_thread_request terminate_thread_request;
|
||||
struct get_process_info_request get_process_info_request;
|
||||
struct get_process_vm_counters_request get_process_vm_counters_request;
|
||||
struct set_process_info_request set_process_info_request;
|
||||
struct get_thread_info_request get_thread_info_request;
|
||||
struct get_thread_times_request get_thread_times_request;
|
||||
|
@ -6119,6 +6139,7 @@ union generic_reply
|
|||
struct terminate_process_reply terminate_process_reply;
|
||||
struct terminate_thread_reply terminate_thread_reply;
|
||||
struct get_process_info_reply get_process_info_reply;
|
||||
struct get_process_vm_counters_reply get_process_vm_counters_reply;
|
||||
struct set_process_info_reply set_process_info_reply;
|
||||
struct get_thread_info_reply get_thread_info_reply;
|
||||
struct get_thread_times_reply get_thread_times_reply;
|
||||
|
@ -6395,6 +6416,6 @@ union generic_reply
|
|||
struct terminate_job_reply terminate_job_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 530
|
||||
#define SERVER_PROTOCOL_VERSION 531
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -1371,6 +1371,44 @@ DECL_HANDLER(get_process_info)
|
|||
}
|
||||
}
|
||||
|
||||
/* retrieve information about a process memory usage */
|
||||
DECL_HANDLER(get_process_vm_counters)
|
||||
{
|
||||
struct process *process = get_process_from_handle( req->handle, PROCESS_QUERY_LIMITED_INFORMATION );
|
||||
|
||||
if (!process) return;
|
||||
#ifdef linux
|
||||
if (process->unix_pid != -1)
|
||||
{
|
||||
FILE *f;
|
||||
char proc_path[32], line[256];
|
||||
unsigned long value;
|
||||
|
||||
sprintf( proc_path, "/proc/%u/status", process->unix_pid );
|
||||
if ((f = fopen( proc_path, "r" )))
|
||||
{
|
||||
while (fgets( line, sizeof(line), f ))
|
||||
{
|
||||
if (sscanf( line, "VmPeak: %lu", &value ))
|
||||
reply->peak_virtual_size = (mem_size_t)value * 1024;
|
||||
else if (sscanf( line, "VmSize: %lu", &value ))
|
||||
reply->virtual_size = (mem_size_t)value * 1024;
|
||||
else if (sscanf( line, "VmHWM: %lu", &value ))
|
||||
reply->peak_working_set_size = (mem_size_t)value * 1024;
|
||||
else if (sscanf( line, "VmRSS: %lu", &value ))
|
||||
reply->working_set_size = (mem_size_t)value * 1024;
|
||||
else if (sscanf( line, "VmSwap: %lu", &value ))
|
||||
reply->peak_pagefile_usage = reply->pagefile_usage = (mem_size_t)value * 1024;
|
||||
}
|
||||
fclose( f );
|
||||
}
|
||||
else set_error( STATUS_ACCESS_DENIED );
|
||||
}
|
||||
else set_error( STATUS_ACCESS_DENIED );
|
||||
#endif
|
||||
release_object( process );
|
||||
}
|
||||
|
||||
static void set_process_affinity( struct process *process, affinity_t affinity )
|
||||
{
|
||||
struct thread *thread;
|
||||
|
|
|
@ -845,6 +845,19 @@ struct rawinput_device
|
|||
@END
|
||||
|
||||
|
||||
/* Retrieve information about a process memory usage */
|
||||
@REQ(get_process_vm_counters)
|
||||
obj_handle_t handle; /* process handle */
|
||||
@REPLY
|
||||
mem_size_t peak_virtual_size; /* peak virtual memory in bytes */
|
||||
mem_size_t virtual_size; /* virtual memory in bytes */
|
||||
mem_size_t peak_working_set_size; /* peak real memory in bytes */
|
||||
mem_size_t working_set_size; /* real memory in bytes */
|
||||
mem_size_t pagefile_usage; /* swapped-out memory in bytes */
|
||||
mem_size_t peak_pagefile_usage; /* peak swapped-out memory in bytes */
|
||||
@END
|
||||
|
||||
|
||||
/* Set a process information */
|
||||
@REQ(set_process_info)
|
||||
obj_handle_t handle; /* process handle */
|
||||
|
|
|
@ -121,6 +121,7 @@ DECL_HANDLER(init_thread);
|
|||
DECL_HANDLER(terminate_process);
|
||||
DECL_HANDLER(terminate_thread);
|
||||
DECL_HANDLER(get_process_info);
|
||||
DECL_HANDLER(get_process_vm_counters);
|
||||
DECL_HANDLER(set_process_info);
|
||||
DECL_HANDLER(get_thread_info);
|
||||
DECL_HANDLER(get_thread_times);
|
||||
|
@ -410,6 +411,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_terminate_process,
|
||||
(req_handler)req_terminate_thread,
|
||||
(req_handler)req_get_process_info,
|
||||
(req_handler)req_get_process_vm_counters,
|
||||
(req_handler)req_set_process_info,
|
||||
(req_handler)req_get_thread_info,
|
||||
(req_handler)req_get_thread_times,
|
||||
|
@ -796,6 +798,15 @@ C_ASSERT( FIELD_OFFSET(struct get_process_info_reply, cpu) == 56 );
|
|||
C_ASSERT( FIELD_OFFSET(struct get_process_info_reply, debugger_present) == 60 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_process_info_reply, debug_children) == 62 );
|
||||
C_ASSERT( sizeof(struct get_process_info_reply) == 64 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_process_vm_counters_request, handle) == 12 );
|
||||
C_ASSERT( sizeof(struct get_process_vm_counters_request) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_process_vm_counters_reply, peak_virtual_size) == 8 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_process_vm_counters_reply, virtual_size) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_process_vm_counters_reply, peak_working_set_size) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_process_vm_counters_reply, working_set_size) == 32 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_process_vm_counters_reply, pagefile_usage) == 40 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_process_vm_counters_reply, peak_pagefile_usage) == 48 );
|
||||
C_ASSERT( sizeof(struct get_process_vm_counters_reply) == 56 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_process_info_request, handle) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_process_info_request, mask) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_process_info_request, priority) == 20 );
|
||||
|
|
|
@ -1346,6 +1346,21 @@ static void dump_get_process_info_reply( const struct get_process_info_reply *re
|
|||
fprintf( stderr, ", debug_children=%d", req->debug_children );
|
||||
}
|
||||
|
||||
static void dump_get_process_vm_counters_request( const struct get_process_vm_counters_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%04x", req->handle );
|
||||
}
|
||||
|
||||
static void dump_get_process_vm_counters_reply( const struct get_process_vm_counters_reply *req )
|
||||
{
|
||||
dump_uint64( " peak_virtual_size=", &req->peak_virtual_size );
|
||||
dump_uint64( ", virtual_size=", &req->virtual_size );
|
||||
dump_uint64( ", peak_working_set_size=", &req->peak_working_set_size );
|
||||
dump_uint64( ", working_set_size=", &req->working_set_size );
|
||||
dump_uint64( ", pagefile_usage=", &req->pagefile_usage );
|
||||
dump_uint64( ", peak_pagefile_usage=", &req->peak_pagefile_usage );
|
||||
}
|
||||
|
||||
static void dump_set_process_info_request( const struct set_process_info_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%04x", req->handle );
|
||||
|
@ -4457,6 +4472,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_terminate_process_request,
|
||||
(dump_func)dump_terminate_thread_request,
|
||||
(dump_func)dump_get_process_info_request,
|
||||
(dump_func)dump_get_process_vm_counters_request,
|
||||
(dump_func)dump_set_process_info_request,
|
||||
(dump_func)dump_get_thread_info_request,
|
||||
(dump_func)dump_get_thread_times_request,
|
||||
|
@ -4743,6 +4759,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_terminate_process_reply,
|
||||
(dump_func)dump_terminate_thread_reply,
|
||||
(dump_func)dump_get_process_info_reply,
|
||||
(dump_func)dump_get_process_vm_counters_reply,
|
||||
NULL,
|
||||
(dump_func)dump_get_thread_info_reply,
|
||||
(dump_func)dump_get_thread_times_reply,
|
||||
|
@ -5029,6 +5046,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||
"terminate_process",
|
||||
"terminate_thread",
|
||||
"get_process_info",
|
||||
"get_process_vm_counters",
|
||||
"set_process_info",
|
||||
"get_thread_info",
|
||||
"get_thread_times",
|
||||
|
|
Loading…
Reference in New Issue