zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 70469d428dd94693295b320a975b1ddf904dda3b (tree)
parent cc44183787adde8b83f9373dd53250f154058dc4
Author: xEgoist <egoist@egoistic.dev>
Date:   Wed, 22 Mar 2023 05:57:14 -0500

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`

Diffstat:
Mlib/std/child_process.zig | 6+++---
Mlib/std/os/windows.zig | 45+++++++++++++++++++++++++++++++++++++++++++++
Mlib/std/os/windows/ntdll.zig | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 111 insertions(+), 3 deletions(-)

diff --git a/lib/std/child_process.zig b/lib/std/child_process.zig @@ -137,6 +137,7 @@ pub const ChildProcess = struct { os.SetIdError || os.ChangeCurDirError || windows.CreateProcessError || + windows.GetProcessMemoryInfoError || windows.WaitForSingleObjectError; pub const Term = union(enum) { @@ -374,9 +375,8 @@ pub const ChildProcess = struct { if (self.request_resource_usage_statistics) { var pmc: windows.PROCESS_MEMORY_COUNTERS = undefined; - if (windows.kernel32.K32GetProcessMemoryInfo(self.id, &pmc, @sizeOf(windows.PROCESS_MEMORY_COUNTERS)) != 0) { - self.resource_usage_statistics.rusage = pmc; - } + try windows.GetProcessMemoryInfo(self.id, &pmc); + self.resource_usage_statistics.rusage = pmc; } os.close(self.id); diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig @@ -3947,6 +3947,20 @@ pub const PSAPI_WS_WATCH_INFORMATION = extern struct { FaultingVa: LPVOID, }; +pub const VM_COUNTERS = extern struct { + PeakVirtualSize: SIZE_T, + VirtualSize: SIZE_T, + PageFaultCount: ULONG, + PeakWorkingSetSize: SIZE_T, + WorkingSetSize: SIZE_T, + QuotaPeakPagedPoolUsage: SIZE_T, + QuotaPagedPoolUsage: SIZE_T, + QuotaPeakNonPagedPoolUsage: SIZE_T, + QuotaNonPagedPoolUsage: SIZE_T, + PagefileUsage: SIZE_T, + PeakPagefileUsage: SIZE_T, +}; + pub const PROCESS_MEMORY_COUNTERS = extern struct { cb: DWORD, PageFaultCount: DWORD, @@ -3974,6 +3988,37 @@ pub const PROCESS_MEMORY_COUNTERS_EX = extern struct { PrivateUsage: SIZE_T, }; +pub const GetProcessMemoryInfoError = error{ + AccessDenied, + InvalidHandle, + Unexpected, +}; + +pub fn GetProcessMemoryInfo(hProcess: HANDLE, out: *PROCESS_MEMORY_COUNTERS) GetProcessMemoryInfoError!void { + var vmc: VM_COUNTERS = undefined; + const rc = ntdll.NtQueryInformationProcess(hProcess, .ProcessVmCounters, &vmc, @sizeOf(VM_COUNTERS), null); + switch (rc) { + .SUCCESS => { + out.* = PROCESS_MEMORY_COUNTERS{ + .cb = @sizeOf(PROCESS_MEMORY_COUNTERS), + .PageFaultCount = vmc.PageFaultCount, + .PeakWorkingSetSize = vmc.PeakWorkingSetSize, + .WorkingSetSize = vmc.WorkingSetSize, + .QuotaPeakPagedPoolUsage = vmc.QuotaPeakPagedPoolUsage, + .QuotaPagedPoolUsage = vmc.QuotaPagedPoolUsage, + .QuotaPeakNonPagedPoolUsage = vmc.QuotaPeakNonPagedPoolUsage, + .QuotaNonPagedPoolUsage = vmc.QuotaNonPagedPoolUsage, + .PagefileUsage = vmc.PagefileUsage, + .PeakPagefileUsage = vmc.PeakPagefileUsage, + }; + }, + .ACCESS_DENIED => return error.AccessDenied, + .INVALID_HANDLE => return error.InvalidHandle, + .INVALID_PARAMETER => unreachable, + else => return unexpectedStatus(rc), + } +} + pub const PERFORMANCE_INFORMATION = extern struct { cb: DWORD, CommitTotal: SIZE_T, diff --git a/lib/std/os/windows/ntdll.zig b/lib/std/os/windows/ntdll.zig @@ -32,6 +32,69 @@ const RUNTIME_FUNCTION = windows.RUNTIME_FUNCTION; const KNONVOLATILE_CONTEXT_POINTERS = windows.KNONVOLATILE_CONTEXT_POINTERS; const EXCEPTION_ROUTINE = windows.EXCEPTION_ROUTINE; +pub const PROCESSINFOCLASS = enum(c_int) { + ProcessBasicInformation, + ProcessQuotaLimits, + ProcessIoCounters, + ProcessVmCounters, + ProcessTimes, + ProcessBasePriority, + ProcessRaisePriority, + ProcessDebugPort, + ProcessExceptionPort, + ProcessAccessToken, + ProcessLdtInformation, + ProcessLdtSize, + ProcessDefaultHardErrorMode, + ProcessIoPortHandlers, + ProcessPooledUsageAndLimits, + ProcessWorkingSetWatch, + ProcessUserModeIOPL, + ProcessEnableAlignmentFaultFixup, + ProcessPriorityClass, + ProcessWx86Information, + ProcessHandleCount, + ProcessAffinityMask, + ProcessPriorityBoost, + ProcessDeviceMap, + ProcessSessionInformation, + ProcessForegroundInformation, + ProcessWow64Information, + ProcessImageFileName, + ProcessLUIDDeviceMapsEnabled, + ProcessBreakOnTermination, + ProcessDebugObjectHandle, + ProcessDebugFlags, + ProcessHandleTracing, + ProcessIoPriority, + ProcessExecuteFlags, + ProcessTlsInformation, + ProcessCookie, + ProcessImageInformation, + ProcessCycleTime, + ProcessPagePriority, + ProcessInstrumentationCallback, + ProcessThreadStackAllocation, + ProcessWorkingSetWatchEx, + ProcessImageFileNameWin32, + ProcessImageFileMapping, + ProcessAffinityUpdateMode, + ProcessMemoryAllocationMode, + ProcessGroupInformation, + ProcessTokenVirtualizationEnabled, + ProcessConsoleHostProcess, + ProcessWindowInformation, + MaxProcessInfoClass +}; + +pub extern "ntdll" fn NtQueryInformationProcess( + ProcessHandle: HANDLE, + ProcessInformationClass: PROCESSINFOCLASS, + ProcessInformation: *anyopaque, + ProcessInformationLength: ULONG, + ReturnLength: ?*ULONG, +) callconv(WINAPI) NTSTATUS; + pub const THREADINFOCLASS = enum(c_int) { ThreadBasicInformation, ThreadTimes,