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

Co-authored-by: Alex Rønne Petersen <alex@alexrp.com>
This commit is contained in:
Ryan King 2025-04-11 13:28:22 -04:00 committed by Alex Rønne Petersen
parent 933beb4cbd
commit 6c598e8341
3 changed files with 80 additions and 17 deletions

View File

@ -2610,6 +2610,71 @@ pub fn map_shadow_stack(addr: u64, size: u64, flags: u32) usize {
return syscall3(.map_shadow_stack, addr, size, flags);
}
pub const Sysinfo = switch (native_abi) {
.gnux32, .muslx32 => extern struct {
/// Seconds since boot
uptime: i64,
/// 1, 5, and 15 minute load averages
loads: [3]u64,
/// Total usable main memory size
totalram: u64,
/// Available memory size
freeram: u64,
/// Amount of shared memory
sharedram: u64,
/// Memory used by buffers
bufferram: u64,
/// Total swap space size
totalswap: u64,
/// swap space still available
freeswap: u64,
/// Number of current processes
procs: u16,
/// Explicit padding for m68k
pad: u16,
/// Total high memory size
totalhigh: u64,
/// Available high memory size
freehigh: u64,
/// Memory unit size in bytes
mem_unit: u32,
},
else => extern struct {
/// Seconds since boot
uptime: isize,
/// 1, 5, and 15 minute load averages
loads: [3]usize,
/// Total usable main memory size
totalram: usize,
/// Available memory size
freeram: usize,
/// Amount of shared memory
sharedram: usize,
/// Memory used by buffers
bufferram: usize,
/// Total swap space size
totalswap: usize,
/// swap space still available
freeswap: usize,
/// Number of current processes
procs: u16,
/// Explicit padding for m68k
pad: u16,
/// Total high memory size
totalhigh: usize,
/// Available high memory size
freehigh: usize,
/// Memory unit size in bytes
mem_unit: u32,
/// Pad
_f: [20 - 2 * @sizeOf(usize) - @sizeOf(u32)]u8,
},
};
pub fn sysinfo(info: *Sysinfo) usize {
return syscall1(.sysinfo, @intFromPtr(info));
}
pub const E = switch (native_arch) {
.mips, .mipsel, .mips64, .mips64el => enum(u16) {
/// No error occurred.

View File

@ -165,6 +165,15 @@ test "sigset_t" {
try expectEqual(sigset[2], 0);
}
test "sysinfo" {
var info: linux.Sysinfo = undefined;
const result: usize = linux.sysinfo(&info);
try expect(std.os.linux.E.init(result) == .SUCCESS);
try expect(info.mem_unit > 0);
try expect(info.mem_unit <= std.heap.page_size_max);
}
test {
_ = linux.IoUring;
}

View File

@ -1748,7 +1748,12 @@ pub const TotalSystemMemoryError = error{
pub fn totalSystemMemory() TotalSystemMemoryError!u64 {
switch (native_os) {
.linux => {
return totalSystemMemoryLinux() catch return error.UnknownTotalSystemMemory;
var info: std.os.linux.Sysinfo = undefined;
const result: usize = std.os.linux.sysinfo(&info);
if (std.os.linux.E.init(result) != .SUCCESS) {
return error.UnknownTotalSystemMemory;
}
return info.totalram * info.mem_unit;
},
.freebsd => {
var physmem: c_ulong = undefined;
@ -1793,22 +1798,6 @@ pub fn totalSystemMemory() TotalSystemMemoryError!u64 {
}
}
fn totalSystemMemoryLinux() !u64 {
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.tokenizeAny(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(u64, int_text, 10);
return kilobytes * 1024;
}
/// Indicate that we are now terminating with a successful exit code.
/// In debug builds, this is a no-op, so that the calling code's
/// cleanup mechanisms are tested and so that external tools that