Commit 3b29d00c98

Andrew Kelley <andrew@ziglang.org>
2023-03-06 08:19:32
add std.process.totalSystemMemory
1 parent 6377aad
Changed files (2)
lib
lib/std/os/windows/kernel32.zig
@@ -67,6 +67,7 @@ const RUNTIME_FUNCTION = windows.RUNTIME_FUNCTION;
 const KNONVOLATILE_CONTEXT_POINTERS = windows.KNONVOLATILE_CONTEXT_POINTERS;
 const EXCEPTION_ROUTINE = windows.EXCEPTION_ROUTINE;
 const MODULEENTRY32 = windows.MODULEENTRY32;
+const ULONGLONG = windows.ULONGLONG;
 
 pub extern "kernel32" fn AddVectoredExceptionHandler(First: c_ulong, Handler: ?VECTORED_EXCEPTION_HANDLER) callconv(WINAPI) ?*anyopaque;
 pub extern "kernel32" fn RemoveVectoredExceptionHandler(Handle: HANDLE) callconv(WINAPI) c_ulong;
@@ -457,3 +458,5 @@ pub extern "kernel32" fn RegOpenKeyExW(
     samDesired: REGSAM,
     phkResult: *HKEY,
 ) callconv(WINAPI) LSTATUS;
+
+pub extern "kernel32" fn GetPhysicallyInstalledSystemMemory(TotalMemoryInKilobytes: *ULONGLONG) BOOL;
lib/std/process.zig
@@ -1169,3 +1169,38 @@ pub fn execve(
 
     return os.execvpeZ_expandArg0(.no_expand, argv_buf.ptr[0].?, argv_buf.ptr, envp);
 }
+
+pub const TotalSystemMemoryError = error{
+    UnknownTotalSystemMemory,
+};
+
+/// Returns the total system memory, in bytes.
+pub fn totalSystemMemory() TotalSystemMemoryError!usize {
+    switch (builtin.os.tag) {
+        .linux => {
+            return totalSystemMemoryLinux() catch return error.UnknownTotalSystemMemory;
+        },
+        .windows => {
+            var kilobytes: std.os.windows.ULONGLONG = undefined;
+            assert(std.os.windows.kernel32.GetPhysicallyInstalledSystemMemory(&kilobytes) == std.os.windows.TRUE);
+            return kilobytes * 1024;
+        },
+        else => return error.UnknownTotalSystemMemory,
+    }
+}
+
+fn totalSystemMemoryLinux() !usize {
+    var file = try std.fs.openFileAbsoluteZ("/proc/meminfo", .{});
+    defer file.close();
+    var buf: [50]u8 = undefined;
+    const amt = try file.read(&buf);
+    if (amt != 50) return error.Unexpected;
+    var it = std.mem.tokenize(u8, buf[0..amt], " \n");
+    const label = it.next().?;
+    if (!std.mem.eql(u8, label, "MemTotal:")) return error.Unexpected;
+    const int_text = it.next() orelse return error.Unexpected;
+    const units = it.next() orelse return error.Unexpected;
+    if (!std.mem.eql(u8, units, "kB")) return error.Unexpected;
+    const kilobytes = try std.fmt.parseInt(usize, int_text, 10);
+    return kilobytes * 1024;
+}