//! 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) { 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, priority: Option) { 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 { 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 }