use crate::{
driver,
driver::schedule::{ready, ready::task},
};
#[derive(Clone, Copy, Eq, PartialEq)]
#[repr(transparent)]
pub struct Parent<'d>(pub(in crate::driver::schedule::ready::task) ready::Address<'d>);
impl<'d> Parent<'d> {
pub fn wake(self) {
self.0.wake();
}
#[doc(hidden)]
pub fn belongs_to(self, driver: driver::Reference<'_>) -> bool {
self.0.belongs_to(driver)
}
pub(in crate::driver::schedule::ready) fn address(self) -> ready::Address<'d> {
self.0
}
pub(in crate::driver::schedule::ready::task) fn driver(self) -> driver::Reference<'d> {
self.0.driver
}
pub(in crate::driver::schedule::ready::task) fn key(self) -> ready::Key<'d> {
self.0.key()
}
pub(in crate::driver::schedule::ready::task) fn validate(
self,
max: usize,
) -> Result<(), task::Error> {
let address = self.0;
let driver = address.driver;
let mut key = address.key();
let mut hops = max;
let access = ready::Access::new(&driver);
loop {
match driver.ready().arena().task_parent(access, key) {
ready::TaskParent::Root => return Ok(()),
ready::TaskParent::Task(parent) => {
if hops == 0 {
return Err(task::Error::WakeHopCeiling {
minimum: max + 1,
maximum: max,
});
}
hops -= 1;
key = parent;
}
ready::TaskParent::Stale => return Err(task::Error::ParentStale),
}
}
}
pub fn try_admit(self) -> Result<task::raw::Admission<'d>, task::Error> {
self.validate(task::MAX_WAKE_HOPS - 1)?;
let arena = self.0.driver.ready().arena();
let child = arena.entries.pool.try_task(&arena.entries.slots)?;
Ok(task::raw::Admission::new(self, child))
}
pub(in crate::driver::schedule::ready) fn return_lease(
self,
held: ready::ReservedKey<'d>,
chain: &ready::Chain,
) {
let entries = &self.0.driver.ready().arena().entries;
chain.restore(&entries.slots, held);
}
pub(in crate::driver::schedule::ready) fn retarget(self, key: ready::Key<'d>) -> Self {
Self(self.0.retarget(key))
}
}
impl<'d> From<ready::Target<'d>> for Parent<'d> {
fn from(target: ready::Target<'d>) -> Self {
Self(target.address())
}
}
const _: () = {
assert!(std::mem::size_of::<Parent<'static>>() == 2 * std::mem::size_of::<usize>());
};