authorgravatar for egoist@egoistic.devxEgoist <egoist@egoistic.dev> 2023-03-22 05:57:14-05:00
committergravatar for egoist@egoistic.devxEgoist <egoist@egoistic.dev> 2023-03-22 06:13:11-05:00
log70469d428dd94693295b320a975b1ddf904dda3b
tree30f2fd925f76db6ead489ab7e5eddf51320113e9
parentcc44183787adde8b83f9373dd53250f154058dc4

Implemented Zig wrapper for `GetProcessMemoryInfo`

`GetProcessMemoryInfo` is implemented using `NtQueryInformationProcess` with `ProcessVmCounters` to obtain `VM_COUNTERS`. The structs, enum definitions are found in `winternl.h` or `ntddk.h` in the latest WDK. This should give the same results as using `K32GetProcessMemoryInfo`

3 files changed, 111 insertions(+), 3 deletions(-)

lib/std/child_process.zig+3-3
...@@ -137,6 +137,7 @@ pub const ChildProcess = struct {...@@ -137,6 +137,7 @@ pub const ChildProcess = struct {
137 os.SetIdError ||137 os.SetIdError ||
138 os.ChangeCurDirError ||138 os.ChangeCurDirError ||
139 windows.CreateProcessError ||139 windows.CreateProcessError ||
140 windows.GetProcessMemoryInfoError ||
140 windows.WaitForSingleObjectError;141 windows.WaitForSingleObjectError;
141142
142 pub const Term = union(enum) {143 pub const Term = union(enum) {
...@@ -374,9 +375,8 @@ pub const ChildProcess = struct {...@@ -374,9 +375,8 @@ pub const ChildProcess = struct {
374375
375 if (self.request_resource_usage_statistics) {376 if (self.request_resource_usage_statistics) {
376 var pmc: windows.PROCESS_MEMORY_COUNTERS = undefined;377 var pmc: windows.PROCESS_MEMORY_COUNTERS = undefined;
377 if (windows.kernel32.K32GetProcessMemoryInfo(self.id, &pmc, @sizeOf(windows.PROCESS_MEMORY_COUNTERS)) != 0) {378 try windows.GetProcessMemoryInfo(self.id, &pmc);
378 self.resource_usage_statistics.rusage = pmc;379 self.resource_usage_statistics.rusage = pmc;
379 }
380 }380 }
381381
382 os.close(self.id);382 os.close(self.id);
lib/std/os/windows.zig+45
...@@ -3947,6 +3947,20 @@ pub const PSAPI_WS_WATCH_INFORMATION = extern struct {...@@ -3947,6 +3947,20 @@ pub const PSAPI_WS_WATCH_INFORMATION = extern struct {
3947 FaultingVa: LPVOID,3947 FaultingVa: LPVOID,
3948};3948};
39493949
3950pub const VM_COUNTERS = extern struct {
3951 PeakVirtualSize: SIZE_T,
3952 VirtualSize: SIZE_T,
3953 PageFaultCount: ULONG,
3954 PeakWorkingSetSize: SIZE_T,
3955 WorkingSetSize: SIZE_T,
3956 QuotaPeakPagedPoolUsage: SIZE_T,
3957 QuotaPagedPoolUsage: SIZE_T,
3958 QuotaPeakNonPagedPoolUsage: SIZE_T,
3959 QuotaNonPagedPoolUsage: SIZE_T,
3960 PagefileUsage: SIZE_T,
3961 PeakPagefileUsage: SIZE_T,
3962};
3963
3950pub const PROCESS_MEMORY_COUNTERS = extern struct {3964pub const PROCESS_MEMORY_COUNTERS = extern struct {
3951 cb: DWORD,3965 cb: DWORD,
3952 PageFaultCount: DWORD,3966 PageFaultCount: DWORD,
...@@ -3974,6 +3988,37 @@ pub const PROCESS_MEMORY_COUNTERS_EX = extern struct {...@@ -3974,6 +3988,37 @@ pub const PROCESS_MEMORY_COUNTERS_EX = extern struct {
3974 PrivateUsage: SIZE_T,3988 PrivateUsage: SIZE_T,
3975};3989};
39763990
3991pub const GetProcessMemoryInfoError = error{
3992 AccessDenied,
3993 InvalidHandle,
3994 Unexpected,
3995};
3996
3997pub fn GetProcessMemoryInfo(hProcess: HANDLE, out: *PROCESS_MEMORY_COUNTERS) GetProcessMemoryInfoError!void {
3998 var vmc: VM_COUNTERS = undefined;
3999 const rc = ntdll.NtQueryInformationProcess(hProcess, .ProcessVmCounters, &vmc, @sizeOf(VM_COUNTERS), null);
4000 switch (rc) {
4001 .SUCCESS => {
4002 out.* = PROCESS_MEMORY_COUNTERS{
4003 .cb = @sizeOf(PROCESS_MEMORY_COUNTERS),
4004 .PageFaultCount = vmc.PageFaultCount,
4005 .PeakWorkingSetSize = vmc.PeakWorkingSetSize,
4006 .WorkingSetSize = vmc.WorkingSetSize,
4007 .QuotaPeakPagedPoolUsage = vmc.QuotaPeakPagedPoolUsage,
4008 .QuotaPagedPoolUsage = vmc.QuotaPagedPoolUsage,
4009 .QuotaPeakNonPagedPoolUsage = vmc.QuotaPeakNonPagedPoolUsage,
4010 .QuotaNonPagedPoolUsage = vmc.QuotaNonPagedPoolUsage,
4011 .PagefileUsage = vmc.PagefileUsage,
4012 .PeakPagefileUsage = vmc.PeakPagefileUsage,
4013 };
4014 },
4015 .ACCESS_DENIED => return error.AccessDenied,
4016 .INVALID_HANDLE => return error.InvalidHandle,
4017 .INVALID_PARAMETER => unreachable,
4018 else => return unexpectedStatus(rc),
4019 }
4020}
4021
3977pub const PERFORMANCE_INFORMATION = extern struct {4022pub const PERFORMANCE_INFORMATION = extern struct {
3978 cb: DWORD,4023 cb: DWORD,
3979 CommitTotal: SIZE_T,4024 CommitTotal: SIZE_T,
lib/std/os/windows/ntdll.zig+63
...@@ -32,6 +32,69 @@ const RUNTIME_FUNCTION = windows.RUNTIME_FUNCTION;...@@ -32,6 +32,69 @@ const RUNTIME_FUNCTION = windows.RUNTIME_FUNCTION;
32const KNONVOLATILE_CONTEXT_POINTERS = windows.KNONVOLATILE_CONTEXT_POINTERS;32const KNONVOLATILE_CONTEXT_POINTERS = windows.KNONVOLATILE_CONTEXT_POINTERS;
33const EXCEPTION_ROUTINE = windows.EXCEPTION_ROUTINE;33const EXCEPTION_ROUTINE = windows.EXCEPTION_ROUTINE;
3434
35pub const PROCESSINFOCLASS = enum(c_int) {
36 ProcessBasicInformation,
37 ProcessQuotaLimits,
38 ProcessIoCounters,
39 ProcessVmCounters,
40 ProcessTimes,
41 ProcessBasePriority,
42 ProcessRaisePriority,
43 ProcessDebugPort,
44 ProcessExceptionPort,
45 ProcessAccessToken,
46 ProcessLdtInformation,
47 ProcessLdtSize,
48 ProcessDefaultHardErrorMode,
49 ProcessIoPortHandlers,
50 ProcessPooledUsageAndLimits,
51 ProcessWorkingSetWatch,
52 ProcessUserModeIOPL,
53 ProcessEnableAlignmentFaultFixup,
54 ProcessPriorityClass,
55 ProcessWx86Information,
56 ProcessHandleCount,
57 ProcessAffinityMask,
58 ProcessPriorityBoost,
59 ProcessDeviceMap,
60 ProcessSessionInformation,
61 ProcessForegroundInformation,
62 ProcessWow64Information,
63 ProcessImageFileName,
64 ProcessLUIDDeviceMapsEnabled,
65 ProcessBreakOnTermination,
66 ProcessDebugObjectHandle,
67 ProcessDebugFlags,
68 ProcessHandleTracing,
69 ProcessIoPriority,
70 ProcessExecuteFlags,
71 ProcessTlsInformation,
72 ProcessCookie,
73 ProcessImageInformation,
74 ProcessCycleTime,
75 ProcessPagePriority,
76 ProcessInstrumentationCallback,
77 ProcessThreadStackAllocation,
78 ProcessWorkingSetWatchEx,
79 ProcessImageFileNameWin32,
80 ProcessImageFileMapping,
81 ProcessAffinityUpdateMode,
82 ProcessMemoryAllocationMode,
83 ProcessGroupInformation,
84 ProcessTokenVirtualizationEnabled,
85 ProcessConsoleHostProcess,
86 ProcessWindowInformation,
87 MaxProcessInfoClass
88};
89
90pub extern "ntdll" fn NtQueryInformationProcess(
91 ProcessHandle: HANDLE,
92 ProcessInformationClass: PROCESSINFOCLASS,
93 ProcessInformation: *anyopaque,
94 ProcessInformationLength: ULONG,
95 ReturnLength: ?*ULONG,
96) callconv(WINAPI) NTSTATUS;
97
35pub const THREADINFOCLASS = enum(c_int) {98pub const THREADINFOCLASS = enum(c_int) {
36 ThreadBasicInformation,99 ThreadBasicInformation,
37 ThreadTimes,100 ThreadTimes,