sysfs: basic scheduler stats

This commit is contained in:
Mark Poliakov 2024-04-11 16:36:14 +03:00
parent 8adc011281
commit becbf2aea1
6 changed files with 82 additions and 11 deletions

View File

@ -6,8 +6,6 @@ build = "build.rs"
authors = ["Mark Poliakov <mark@alnyan.me>"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[profile.dev.package.tock-registers]
opt-level = 3
[dependencies]
abi-lib = { path = "../lib/abi-lib" }

View File

@ -34,6 +34,3 @@ version = "0.7.2"
git = "https://git.alnyan.me/yggdrasil/yggdrasil-elf.git"
default-features = false
features = ["no_std_stream"]
[profile.dev]
rustflags = ["-Clink-dead-code=yes -Zexport-executable-symbols -Cprefer-dynamic"]

View File

@ -1,4 +1,8 @@
use core::cell::Cell;
use core::{
cell::Cell,
sync::atomic::{AtomicU64, Ordering},
time::Duration,
};
use alloc::{sync::Arc, vec::Vec};
use crossbeam_queue::SegQueue;
@ -6,6 +10,7 @@ use kernel_arch::{
task::{Scheduler, TaskContext},
Architecture, ArchitectureImpl, CpuImpl,
};
use libk_device::monotonic_timestamp;
use libk_util::{sync::IrqGuard, OneTimeInit};
use crate::task::{thread::Thread, TaskContextImpl, ThreadId, ThreadState};
@ -15,6 +20,17 @@ pub struct CpuQueue {
queue: SegQueue<ThreadId>,
index: usize,
idle: Cell<TaskContextImpl>,
stats: SchedulerStats,
last_stats_measure: Cell<Option<Duration>>,
}
#[derive(Default)]
pub struct SchedulerStats {
pub idle: AtomicU64,
pub user: AtomicU64,
pub kernel: AtomicU64,
pub total: AtomicU64,
}
static QUEUES: OneTimeInit<Vec<CpuQueue>> = OneTimeInit::new();
@ -32,6 +48,9 @@ impl CpuQueue {
queue: SegQueue::new(),
index,
idle: Cell::new(idle),
stats: SchedulerStats::default(),
last_stats_measure: Cell::new(None),
}
}
@ -86,6 +105,23 @@ impl CpuQueue {
(None, None)
}
fn update_stats(&self, delta: Duration, current: Option<&Arc<Thread>>) {
let counter = if let Some(current) = current {
if current.is_user() {
&self.stats.user
} else {
&self.stats.kernel
}
} else {
&self.stats.idle
};
let t = delta.as_millis() as u64;
self.stats.total.fetch_add(t, Ordering::Relaxed);
counter.fetch_add(t, Ordering::Relaxed);
}
}
impl Scheduler for CpuQueue {
@ -127,6 +163,13 @@ impl Scheduler for CpuQueue {
let current_id = cpu.current_thread_id();
let current = current_id.and_then(Thread::get);
let t = monotonic_timestamp().unwrap();
if let Some(t0) = self.last_stats_measure.get() {
let dt = t - t0;
self.update_stats(dt, current.as_ref());
}
self.last_stats_measure.set(Some(t));
let drop_current = if let Some(current) = current.as_ref() {
let mut sched = current.sched.lock();
@ -196,6 +239,10 @@ impl Scheduler for CpuQueue {
}
}
pub fn stats(index: usize) -> &'static SchedulerStats {
&QUEUES.get()[index].stats
}
/// Initializes the global queue list
pub fn init_queues(queues: Vec<CpuQueue>) {
QUEUES.init(queues);

View File

@ -173,6 +173,9 @@ impl Thread {
}
// Get/Set
pub fn is_user(&self) -> bool {
self.id.is_user()
}
/// Updates the thread affinity to run on a specific set of CPUs
pub fn set_affinity(&self, affinity: u64) {

View File

@ -1,10 +1,16 @@
//! "System" filesystem implementation
use abi::error::Error;
use core::sync::atomic::Ordering;
use abi::{error::Error, io::OpenOptions};
use alloc::{format, string::String, sync::Arc};
use git_version::git_version;
use libk::vfs::{
impls::{const_value_node, mdir, read_fn_node, ReadOnlyFnValueNode},
NodeRef,
use libk::{
task::{cpu_count, process::Process, sched},
vfs::{
impls::{const_value_node, mdir, read_fn_node, ReadOnlyFnValueNode},
CommonImpl, InstanceData, NodeRef, RegularImpl,
},
};
use libk_mm::phys;
use libk_util::OneTimeInit;
@ -22,6 +28,21 @@ fn read_kernel_log(pos: u64, buffer: &mut [u8]) -> Result<usize, Error> {
Ok(debug::RING_LOGGER_SINK.read(pos as usize, buffer))
}
fn sched_stats() -> String {
let mut res = String::new();
for i in 0..cpu_count() {
let stats = sched::stats(i);
res.push_str(&format!(
"{} {} {} {}",
stats.idle.load(Ordering::Relaxed),
stats.user.load(Ordering::Relaxed),
stats.kernel.load(Ordering::Relaxed),
stats.total.load(Ordering::Relaxed)
));
}
res
}
/// Sets up the entries within the filesystem
pub fn init() {
let d_kernel = mdir([
@ -29,6 +50,10 @@ pub fn init() {
("rev", const_value_node(git_version!())),
("log", read_fn_node(read_kernel_log)),
]);
let d_proc = mdir([(
"sched_stats",
ReadOnlyFnValueNode::new_node(|| Ok(sched_stats())),
)]);
let d_mem_phys = mdir([
(
"total_pages",
@ -47,6 +72,7 @@ pub fn init() {
let root = mdir([
("kernel", d_kernel),
("mem", d_mem),
("proc", d_proc),
("arch", const_value_node(util::arch_str())),
]);

View File

@ -1,5 +1,5 @@
use std::{
collections::{HashMap, HashSet},
collections::HashMap,
fs::{File, OpenOptions},
io::{Read, Seek, SeekFrom, Write},
ops::Range,