From 2b5e1e03fd439554b8cf9c04dd4254b23ec79ba0 Mon Sep 17 00:00:00 2001 From: vasilito Date: Thu, 9 Jul 2026 10:04:10 +0300 Subject: [PATCH] =?UTF-8?q?kernel:=20implement=20/proc/uptime=20=E2=80=94?= =?UTF-8?q?=20system=20uptime?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added ProcUptime ContextHandle that reads monotonic() time from the kernel and outputs it as uptime_seconds idle_seconds in Linux /proc/uptime format (two floats with newline). Cross-referenced with Linux 7.1 fs/proc/uptime.c uptime_proc_show(). Idle time is 0.0 since Red Bear does not track per-CPU idle time. Also added to ProcRoot directory listing. --- src/scheme/proc.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/scheme/proc.rs b/src/scheme/proc.rs index dfb7bd1e1b..ed830c0535 100644 --- a/src/scheme/proc.rs +++ b/src/scheme/proc.rs @@ -157,6 +157,7 @@ enum ContextHandle { ProcRoot, ProcCpuinfo, ProcMeminfo, + ProcUptime, ProcDir { pid: usize, }, @@ -404,6 +405,9 @@ impl ProcScheme { if path == "proc/meminfo" || path == "meminfo" { return Some(ContextHandle::ProcMeminfo); } + if path == "proc/uptime" || path == "uptime" { + return Some(ContextHandle::ProcUptime); + } let mut parts = path.split('/'); let pid = parts.next()?.parse::().ok()?; match (parts.next(), parts.next()) { @@ -943,8 +947,8 @@ impl KernelScheme for ProcScheme { let mut buf = DirentBuf::new(buf, header_size).ok_or(Error::new(EIO))?; match handle.kind { ContextHandle::ProcRoot => { - // First: system files (cpuinfo, meminfo, etc.) - for (idx, name) in ["cpuinfo", "meminfo"].iter().enumerate() { + // First: system files (cpuinfo, meminfo, uptime) + for (idx, name) in ["cpuinfo", "meminfo", "uptime"].iter().enumerate() { buf.entry(DirEntry { inode: 0, next_opaque_id: (idx + 1) as u64, @@ -960,7 +964,7 @@ impl KernelScheme for ProcScheme { pids.push(context_ref.read(token.token()).pid); } pids.sort_unstable(); - let base_idx = 2; // after cpuinfo + meminfo + let base_idx = 3; // after cpuinfo + meminfo + uptime for (idx, pid) in pids.into_iter().enumerate().skip(opaque.saturating_sub(base_idx)) { let name = format!("{}", pid); buf.entry(DirEntry { @@ -1886,6 +1890,12 @@ impl ContextHandle { ); read_from(buf, output.as_bytes(), offset) } + ContextHandle::ProcUptime => { + let uptime_s = crate::time::monotonic(token) as f64 / crate::time::NANOS_PER_SEC as f64; + let idle_s = 0.0f64; // Red Bear has no per-CPU idle tracking + let output = format!("{:.2} {:.2}\n", uptime_s, idle_s); + read_from(buf, output.as_bytes(), offset) + } ContextHandle::ProcStat { pid } => { let context = proc_context(*pid, token).ok_or(Error::new(ESRCH))?; let (pid, comm, state, ppid, priority, utime, stime, pgrp, session, starttime, owner_proc_id, addr_space) = {