Files
k-os/crates/adapter-riscv/src/smp/hints.rs

43 lines
1.6 KiB
Rust

//! State published under the kernel lock for lock-free fast paths to read.
use core::sync::atomic::{AtomicUsize, Ordering};
use super::{MAX_HARTS, hart_id};
/// Per core: highest waiting priority + 1, 0 if its queue is empty.
static WAITING: [AtomicUsize; MAX_HARTS] = [const { AtomicUsize::new(0) }; MAX_HARTS];
/// Per hart: the running thread's process id + 1 and priority + 1.
static RUNNING_PID: [AtomicUsize; MAX_HARTS] = [const { AtomicUsize::new(0) }; MAX_HARTS];
static RUNNING_PRIORITY: [AtomicUsize; MAX_HARTS] = [const { AtomicUsize::new(0) }; MAX_HARTS];
pub fn publish_waiting(core: usize, highest: Option<u8>) {
if let Some(w) = WAITING.get(core) {
w.store(highest.map_or(0, |p| p as usize + 1), Ordering::Release);
}
}
pub fn publish_running(pid: Option<u16>, priority: Option<u8>) {
let me = hart_id();
if let (Some(p), Some(q)) = (RUNNING_PID.get(me), RUNNING_PRIORITY.get(me)) {
p.store(pid.map_or(0, |x| x as usize + 1), Ordering::Release);
q.store(priority.map_or(0, |x| x as usize + 1), Ordering::Release);
}
}
/// The process the thread running on this hart belongs to.
pub fn running_pid() -> Option<usize> {
let v = RUNNING_PID.get(hart_id())?.load(Ordering::Acquire);
v.checked_sub(1)
}
/// Whether a Yield by the running thread would change nothing: no thread
/// waits on this core at its priority or above.
pub fn yield_is_noop() -> bool {
let me = hart_id();
let (Some(w), Some(p)) = (WAITING.get(me), RUNNING_PRIORITY.get(me)) else {
return false;
};
let mine = p.load(Ordering::Acquire);
mine != 0 && w.load(Ordering::Acquire) < mine
}