authorgravatar for root@ryank.ingRyan King <root@ryank.ing> 2025-04-11 13:28:22-04:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-04-15 20:08:59+02:00
log6c598e8341c202a61dc24678f4450fd5af961b4e
treecba11463a469fb9185b504056d13b6e2fb5984b5
parent933beb4cbd82ce8026a7bd4e887d8096dd3784a9

std: add os.linux.sysinfo(), use it for process.totalSystemMemory()

Co-authored-by: Alex Rønne Petersen <alex@alexrp.com>

3 files changed, 80 insertions(+), 17 deletions(-)

lib/std/os/linux.zig+65
......@@ -2610,6 +2610,71 @@ pub fn map_shadow_stack(addr: u64, size: u64, flags: u32) usize {
26102610 return syscall3(.map_shadow_stack, addr, size, flags);
26112611}
26122612
2613pub const Sysinfo = switch (native_abi) {
2614 .gnux32, .muslx32 => extern struct {
2615 /// Seconds since boot
2616 uptime: i64,
2617 /// 1, 5, and 15 minute load averages
2618 loads: [3]u64,
2619 /// Total usable main memory size
2620 totalram: u64,
2621 /// Available memory size
2622 freeram: u64,
2623 /// Amount of shared memory
2624 sharedram: u64,
2625 /// Memory used by buffers
2626 bufferram: u64,
2627 /// Total swap space size
2628 totalswap: u64,
2629 /// swap space still available
2630 freeswap: u64,
2631 /// Number of current processes
2632 procs: u16,
2633 /// Explicit padding for m68k
2634 pad: u16,
2635 /// Total high memory size
2636 totalhigh: u64,
2637 /// Available high memory size
2638 freehigh: u64,
2639 /// Memory unit size in bytes
2640 mem_unit: u32,
2641 },
2642 else => extern struct {
2643 /// Seconds since boot
2644 uptime: isize,
2645 /// 1, 5, and 15 minute load averages
2646 loads: [3]usize,
2647 /// Total usable main memory size
2648 totalram: usize,
2649 /// Available memory size
2650 freeram: usize,
2651 /// Amount of shared memory
2652 sharedram: usize,
2653 /// Memory used by buffers
2654 bufferram: usize,
2655 /// Total swap space size
2656 totalswap: usize,
2657 /// swap space still available
2658 freeswap: usize,
2659 /// Number of current processes
2660 procs: u16,
2661 /// Explicit padding for m68k
2662 pad: u16,
2663 /// Total high memory size
2664 totalhigh: usize,
2665 /// Available high memory size
2666 freehigh: usize,
2667 /// Memory unit size in bytes
2668 mem_unit: u32,
2669 /// Pad
2670 _f: [20 - 2 * @sizeOf(usize) - @sizeOf(u32)]u8,
2671 },
2672};
2673
2674pub fn sysinfo(info: *Sysinfo) usize {
2675 return syscall1(.sysinfo, @intFromPtr(info));
2676}
2677
26132678pub const E = switch (native_arch) {
26142679 .mips, .mipsel, .mips64, .mips64el => enum(u16) {
26152680 /// No error occurred.
lib/std/os/linux/test.zig+9
......@@ -165,6 +165,15 @@ test "sigset_t" {
165165 try expectEqual(sigset[2], 0);
166166}
167167
168test "sysinfo" {
169 var info: linux.Sysinfo = undefined;
170 const result: usize = linux.sysinfo(&info);
171 try expect(std.os.linux.E.init(result) == .SUCCESS);
172
173 try expect(info.mem_unit > 0);
174 try expect(info.mem_unit <= std.heap.page_size_max);
175}
176
168177test {
169178 _ = linux.IoUring;
170179}
lib/std/process.zig+6-17
......@@ -1748,7 +1748,12 @@ pub const TotalSystemMemoryError = error{
17481748pub fn totalSystemMemory() TotalSystemMemoryError!u64 {
17491749 switch (native_os) {
17501750 .linux => {
1751 return totalSystemMemoryLinux() catch return error.UnknownTotalSystemMemory;
1751 var info: std.os.linux.Sysinfo = undefined;
1752 const result: usize = std.os.linux.sysinfo(&info);
1753 if (std.os.linux.E.init(result) != .SUCCESS) {
1754 return error.UnknownTotalSystemMemory;
1755 }
1756 return info.totalram * info.mem_unit;
17521757 },
17531758 .freebsd => {
17541759 var physmem: c_ulong = undefined;
......@@ -1793,22 +1798,6 @@ pub fn totalSystemMemory() TotalSystemMemoryError!u64 {
17931798 }
17941799}
17951800
1796fn totalSystemMemoryLinux() !u64 {
1797 var file = try std.fs.openFileAbsoluteZ("/proc/meminfo", .{});
1798 defer file.close();
1799 var buf: [50]u8 = undefined;
1800 const amt = try file.read(&buf);
1801 if (amt != 50) return error.Unexpected;
1802 var it = std.mem.tokenizeAny(u8, buf[0..amt], " \n");
1803 const label = it.next().?;
1804 if (!std.mem.eql(u8, label, "MemTotal:")) return error.Unexpected;
1805 const int_text = it.next() orelse return error.Unexpected;
1806 const units = it.next() orelse return error.Unexpected;
1807 if (!std.mem.eql(u8, units, "kB")) return error.Unexpected;
1808 const kilobytes = try std.fmt.parseInt(u64, int_text, 10);
1809 return kilobytes * 1024;
1810}
1811
18121801/// Indicate that we are now terminating with a successful exit code.
18131802/// In debug builds, this is a no-op, so that the calling code's
18141803/// cleanup mechanisms are tested and so that external tools that