| author | |
| committer | |
| log | 70469d428dd94693295b320a975b1ddf904dda3b |
| tree | 30f2fd925f76db6ead489ab7e5eddf51320113e9 |
| parent | cc44183787adde8b83f9373dd53250f154058dc4 |
`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; |
| 141 | 142 | ||
| 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 { |
| 374 | 375 | ||
| 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 | } |
| 381 | 381 | ||
| 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 | }; |
| 3949 | 3949 | ||
| 3950 | pub 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 | |||
| 3950 | pub const PROCESS_MEMORY_COUNTERS = extern struct { | 3964 | pub 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 | }; |
| 3976 | 3990 | ||
| 3991 | pub const GetProcessMemoryInfoError = error{ | ||
| 3992 | AccessDenied, | ||
| 3993 | InvalidHandle, | ||
| 3994 | Unexpected, | ||
| 3995 | }; | ||
| 3996 | |||
| 3997 | pub 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 | |||
| 3977 | pub const PERFORMANCE_INFORMATION = extern struct { | 4022 | pub 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; |
| 32 | const KNONVOLATILE_CONTEXT_POINTERS = windows.KNONVOLATILE_CONTEXT_POINTERS; | 32 | const KNONVOLATILE_CONTEXT_POINTERS = windows.KNONVOLATILE_CONTEXT_POINTERS; |
| 33 | const EXCEPTION_ROUTINE = windows.EXCEPTION_ROUTINE; | 33 | const EXCEPTION_ROUTINE = windows.EXCEPTION_ROUTINE; |
| 34 | 34 | ||
| 35 | pub 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 | |||
| 90 | pub extern "ntdll" fn NtQueryInformationProcess( | ||
| 91 | ProcessHandle: HANDLE, | ||
| 92 | ProcessInformationClass: PROCESSINFOCLASS, | ||
| 93 | ProcessInformation: *anyopaque, | ||
| 94 | ProcessInformationLength: ULONG, | ||
| 95 | ReturnLength: ?*ULONG, | ||
| 96 | ) callconv(WINAPI) NTSTATUS; | ||
| 97 | |||
| 35 | pub const THREADINFOCLASS = enum(c_int) { | 98 | pub const THREADINFOCLASS = enum(c_int) { |
| 36 | ThreadBasicInformation, | 99 | ThreadBasicInformation, |
| 37 | ThreadTimes, | 100 | ThreadTimes, |