Skip to content

Commit 6c598e8

Browse files
gniknayralexrp
andcommitted
std: add os.linux.sysinfo(), use it for process.totalSystemMemory()
Co-authored-by: Alex Rønne Petersen <alex@alexrp.com>
1 parent 933beb4 commit 6c598e8

File tree

3 files changed

+80
-17
lines changed

3 files changed

+80
-17
lines changed

lib/std/os/linux.zig

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

2613+
pub 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+
2674+
pub fn sysinfo(info: *Sysinfo) usize {
2675+
return syscall1(.sysinfo, @intFromPtr(info));
2676+
}
2677+
26132678
pub const E = switch (native_arch) {
26142679
.mips, .mipsel, .mips64, .mips64el => enum(u16) {
26152680
/// No error occurred.

lib/std/os/linux/test.zig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,15 @@ test "sigset_t" {
165165
try expectEqual(sigset[2], 0);
166166
}
167167

168+
test "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+
168177
test {
169178
_ = linux.IoUring;
170179
}

lib/std/process.zig

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1748,7 +1748,12 @@ pub const TotalSystemMemoryError = error{
17481748
pub 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

1796-
fn 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

0 commit comments

Comments
 (0)