Files
RedBear-OS/src/scheme/sys/stat.rs
T
2025-02-22 14:27:10 +00:00

90 lines
2.3 KiB
Rust

use crate::{
context::{contexts, ContextRef, Status},
cpu_stats::{get_context_switch_count, get_contexts_count, irq_counts},
percpu::get_all_stats,
syscall::error::Result,
time::START,
};
use alloc::{string::String, vec::Vec};
/// Get the sys:stat data as displayed to the user.
pub fn resource() -> Result<Vec<u8>> {
let start_time_sec = *START.lock() / 1_000_000_000;
let (contexts_running, contexts_blocked) = get_contexts_stats();
let res = format!(
"{}{}\n\
boot_time: {start_time_sec}\n\
context_switches: {}\n\
contexts_created: {}\n\
contexts_running: {contexts_running}\n\
contexts_blocked: {contexts_blocked}",
get_cpu_stats(),
get_irq_stats(),
get_context_switch_count(),
get_contexts_count(),
);
Ok(res.into_bytes())
}
/// Formats CPU stats.
fn get_cpu_stats() -> String {
let mut cpu_data = String::new();
let stats = get_all_stats();
let mut total_user = 0;
let mut total_nice = 0;
let mut total_kernel = 0;
let mut total_idle = 0;
let mut total_irq = 0;
for (id, stat) in stats {
total_user += stat.user;
total_nice += stat.nice;
total_kernel += stat.kernel;
total_idle += stat.idle;
total_irq += stat.irq;
cpu_data += &format!("{}\n", stat.to_string(id));
}
format!(
"cpu {total_user} {total_nice} {total_kernel} {total_idle} {total_irq}\n\
{cpu_data}"
)
}
/// Formats IRQ stats.
fn get_irq_stats() -> String {
let irq = irq_counts();
let mut irq_total = 0;
let per_irq = irq
.iter()
.map(|c| {
irq_total += *c;
format!("{c}")
})
.collect::<Vec<_>>()
.join(" ");
format!("IRQs {irq_total} {per_irq}")
}
/// Format contexts stats.
fn get_contexts_stats() -> (u64, u64) {
let mut running = 0;
let mut blocked = 0;
let statuses = contexts()
.iter()
.filter_map(ContextRef::upgrade)
.map(|context| context.read_arc().status.clone())
.collect::<Vec<_>>();
for status in statuses {
if matches!(status, Status::Runnable) {
running += 1;
} else if !matches!(status, Status::Dead) {
blocked += 1;
}
}
(running, blocked)
}