kernel: implement /proc/[pid]/statm — memory summary

New ProcStatm ContextHandle that reports the 7-field memory summary
matching Linux /proc/[pid]/statm format:

  size resident shared text lib data dt

All values in pages. Cross-referenced with Linux 7.1
fs/proc/array.c:proc_pid_statm().

Resident count is approximated as the total physical grants
(GRANT_PHYS), since Red Bear has no paging/swapping and all
memory is resident. Other fields (shared, lib, dt) are 0 since
Red Bear's memory model doesn't distinguish these.
This commit is contained in:
2026-07-08 18:54:32 +03:00
parent b8b9b02051
commit 0b089c7582
+32
View File
@@ -173,6 +173,9 @@ enum ContextHandle {
ProcMaps {
pid: usize,
},
ProcStatm {
pid: usize,
},
}
#[derive(Clone)]
struct Handle {
@@ -393,6 +396,7 @@ impl ProcScheme {
(Some("cmdline"), None) => Some(ContextHandle::ProcCmdline { pid }),
(Some("status"), None) => Some(ContextHandle::ProcStatus { pid }),
(Some("maps"), None) => Some(ContextHandle::ProcMaps { pid }),
(Some("statm"), None) => Some(ContextHandle::ProcStatm { pid }),
_ => None,
}
}
@@ -1930,6 +1934,34 @@ impl ContextHandle {
}
read_from(buf, output.as_bytes(), offset)
}
ContextHandle::ProcStatm { pid } => {
let context = proc_context(*pid, token).ok_or(Error::new(ESRCH))?;
let addr_space = context.read(token.token()).addr_space.clone();
let (size, resident) = if let Some(addr_space) = addr_space {
let token2 = token.downgrade();
let guard = addr_space.acquire_read(token2);
let mut total_size = 0usize;
let mut total_resident = 0usize;
for (_grant_base, grant_info) in guard.grants.iter() {
let page_count = grant_info.page_count() * PAGE_SIZE;
total_size += page_count;
if grant_info.grant_flags().contains(GrantFlags::GRANT_PHYS) {
total_resident += page_count;
}
}
(total_size / PAGE_SIZE, total_resident / PAGE_SIZE)
} else {
(0, 0)
};
// Format: size resident shared text lib data dt (in pages)
// Cross-referenced with Linux 7.1 fs/proc/array.c:proc_pid_statm().
// On Red Bear we approximate: shared=0, text=size, lib=0, data=size, dt=0.
let output = alloc::format!(
"{} {} 0 {} 0 {} 0\n",
size, resident, size, size
);
read_from(buf, output.as_bytes(), offset)
}
ContextHandle::ProcRoot | ContextHandle::ProcDir { .. } => Err(Error::new(EBADF)),
ContextHandle::MmapMinAddr(addrspace) => {
let mut token = token.token();