97 lines
2.6 KiB
Rust
97 lines
2.6 KiB
Rust
use core::fmt::Write as _;
|
|
|
|
use crate::{
|
|
context::{contexts, Status},
|
|
cpu_stats::{get_context_switch_count, get_contexts_count, irq_counts},
|
|
percpu::get_all_stats,
|
|
sync::CleanLockToken,
|
|
syscall::error::Result,
|
|
time::START,
|
|
};
|
|
use alloc::{string::String, vec::Vec};
|
|
|
|
/// Get the sys:stat data as displayed to the user.
|
|
pub fn resource(token: &mut CleanLockToken) -> Result<Vec<u8>> {
|
|
let start_time_sec = *START.lock(token.token()) / 1_000_000_000;
|
|
|
|
let (contexts_running, contexts_blocked) = get_contexts_stats(token);
|
|
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;
|
|
let _ = writeln!(&mut cpu_data, "cpu{} {}", id.get(), stat);
|
|
}
|
|
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 mut output = String::with_capacity(64);
|
|
for &c in irq.iter() {
|
|
irq_total += c;
|
|
}
|
|
let _ = write!(output, "IRQs {}", irq_total);
|
|
for &c in irq.iter() {
|
|
let _ = write!(output, " {}", c);
|
|
}
|
|
|
|
output
|
|
}
|
|
|
|
/// Format contexts stats.
|
|
fn get_contexts_stats(token: &mut CleanLockToken) -> (u64, u64) {
|
|
let mut running = 0;
|
|
let mut blocked = 0;
|
|
|
|
let statuses = {
|
|
let mut contexts = contexts(token.downgrade());
|
|
let (contexts, mut token) = contexts.token_split();
|
|
contexts
|
|
.iter()
|
|
.map(|context| context.read(token.token()).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)
|
|
}
|