Skip to main content

dope_core/driver/schedule/
mod.rs

1use std::{cell, mem, time};
2
3use o3::{alloc, base::cell::region, mem::quota};
4use state::{lanes, scope};
5
6use crate::{
7    driver,
8    driver::{
9        receive::{credit, credit::storage},
10        route::table::conn,
11        settings,
12    },
13};
14
15pub mod clock;
16
17pub mod app;
18pub mod maint;
19pub mod ready;
20pub mod sequence;
21#[doc(hidden)]
22pub mod state;
23mod timers;
24
25pub const LIMIT: usize = 256;
26
27/// Exact result of acquiring scheduler capacity from a non-empty source.
28#[must_use = "capacity reports whether the scheduler granted the operation"]
29pub enum Capacity<T> {
30    Available(T),
31    Exhausted,
32}
33
34#[derive(Clone, Copy)]
35#[repr(transparent)]
36pub struct Turn<'turn, 'd> {
37    state: &'turn state::Core<'d>,
38}
39
40impl<'turn, 'd> Turn<'turn, 'd> {
41    pub(in crate::driver::schedule) const fn new(state: &'turn state::Core<'d>) -> Self {
42        Self { state }
43    }
44
45    pub fn reborrow(&self) -> Turn<'_, 'd> {
46        Turn::new(self.state)
47    }
48
49    pub fn clock(self) -> clock::Clock<'turn, 'd> {
50        self.state.driver.scheduler().clock()
51    }
52
53    pub fn app(self) -> app::Work<'turn, 'd> {
54        app::Work { state: self.state }
55    }
56
57    pub fn maint(self) -> maint::Work<'turn, 'd> {
58        maint::Work { state: self.state }
59    }
60
61    /// Runs one sibling with refundable application, maintenance and control
62    /// shares. Ranks choose the remainder recipients when fewer credits than
63    /// siblings remain; sufficiently funded shares keep ceiling division.
64    #[doc(hidden)]
65    pub fn share<const N: usize, T>(
66        self,
67        ranks: [usize; 3],
68        weights: [usize; 2],
69        run: impl for<'scope> FnOnce(Turn<'scope, 'd>) -> T,
70    ) -> T {
71        let _app = lanes::share::<N, _>(&self.state.lanes.app, ranks[0]);
72        let _maint = lanes::share::<N, _>(&self.state.lanes.maint, ranks[1]);
73        let _coord = lanes::weighted::<N, _>(&self.state.lanes.coord, ranks[2], weights);
74        run(Turn::new(self.state))
75    }
76
77    #[doc(hidden)]
78    pub fn coord(self) -> scope::Coord<'turn, 'd> {
79        scope::Coord::new(self.state)
80    }
81}
82
83const _: () = {
84    let word = mem::size_of::<usize>();
85    assert!(mem::size_of::<Turn<'static, 'static>>() == word);
86    assert!(mem::size_of::<quota::Admission<usize>>() == 2 * word);
87    assert!(mem::size_of::<Capacity<&'static u8>>() == word);
88};
89
90/// Aggregate liveness of retained work owned by one driver.
91#[must_use]
92pub enum Progress<'d> {
93    Runnable,
94    Waiting(Wait<'d>),
95    Quiescent,
96}
97
98impl<'d> Progress<'d> {
99    pub fn waiting(region: &region::Token<region::Identity<'d>>) -> Self {
100        Self::Waiting(Wait::event(region))
101    }
102
103    pub fn until(deadline: clock::Deadline<'d>) -> Self {
104        Self::Waiting(Wait::until(deadline))
105    }
106
107    pub fn reduce(self, other: Self) -> Self {
108        match self {
109            runnable @ Self::Runnable => runnable,
110            Self::Waiting(left) => match other {
111                runnable @ Self::Runnable => runnable,
112                Self::Waiting(right) => Self::Waiting(left.reduce(right)),
113                Self::Quiescent => Self::Waiting(left),
114            },
115            Self::Quiescent => other,
116        }
117    }
118}
119
120const _: () = assert!(mem::size_of::<Progress<'static>>() <= 24);
121
122pub(in crate::driver) struct State {
123    pub(in crate::driver) owner: storage::Owner<ready::Stored, credit::Wake, ready::Arena>,
124    clock: cell::Cell<time::Instant>,
125}
126
127impl State {
128    pub(in crate::driver) fn try_new(plan: settings::Plan) -> Result<Self, alloc::Error> {
129        Ok(Self {
130            owner: storage::Owner::try_new(plan)?,
131            clock: cell::Cell::new(time::Instant::now()),
132        })
133    }
134}
135
136#[derive(Clone, Copy)]
137#[repr(transparent)]
138pub struct Context<'d>(driver::Reference<'d>);
139
140impl<'d> Context<'d> {
141    pub(in crate::driver) const fn new(driver: driver::Reference<'d>) -> Self {
142        Self(driver)
143    }
144
145    pub(in crate::driver) fn clock(self) -> clock::Clock<'d, 'd> {
146        clock::Clock::new(&self.0.shared.context().schedule.clock, self.0.brand)
147    }
148
149    pub(in crate::driver) fn set_turn_now(self, now: time::Instant) {
150        self.0.shared.context().schedule.clock.set(now);
151    }
152
153    /// Allocates fixed retained-credit storage in this driver generation.
154    pub fn try_storage(
155        self,
156        capacity: conn::Capacity,
157    ) -> Result<credit::Storage<'d>, alloc::Error> {
158        let shared: &'d driver::Shared = self.0.shared.context();
159        let owner = &shared.schedule.owner;
160        owner.try_storage(capacity, self.0.brand)
161    }
162}
163
164const _: () = assert!(
165    std::mem::size_of::<Context<'static>>() == std::mem::size_of::<driver::Reference<'static>>()
166);
167
168enum Reason<'d> {
169    Event(region::Proof<region::Identity<'d>>),
170    Until(clock::Deadline<'d>),
171}
172
173/// Driver-scoped evidence that a retained owner is waiting for an external
174/// wake or a monotonic deadline.
175#[must_use]
176#[repr(transparent)]
177pub struct Wait<'d> {
178    state: Reason<'d>,
179}
180
181impl<'d> Wait<'d> {
182    pub fn event(region: &region::Token<region::Identity<'d>>) -> Self {
183        Self {
184            state: Reason::Event(region.proof()),
185        }
186    }
187
188    pub fn until(deadline: clock::Deadline<'d>) -> Self {
189        Self {
190            state: Reason::Until(deadline),
191        }
192    }
193
194    pub fn deadline(self) -> Option<clock::Deadline<'d>> {
195        match self.state {
196            Reason::Event(_proof) => None,
197            Reason::Until(deadline) => Some(deadline),
198        }
199    }
200
201    pub(super) fn reduce(self, other: Self) -> Self {
202        match self.state {
203            Reason::Event(_proof) => other,
204            Reason::Until(left) => match other.state {
205                Reason::Event(_proof) => Self {
206                    state: Reason::Until(left),
207                },
208                Reason::Until(right) => Self {
209                    state: Reason::Until(left.min(right)),
210                },
211            },
212        }
213    }
214}
215
216const _: () = {
217    assert!(mem::size_of::<Wait<'static>>() == mem::size_of::<Option<clock::Deadline<'static>>>());
218    assert!(
219        mem::align_of::<Wait<'static>>() == mem::align_of::<Option<clock::Deadline<'static>>>()
220    );
221    assert!(mem::size_of::<Option<Wait<'static>>>() == mem::size_of::<Wait<'static>>());
222    assert!(!mem::needs_drop::<Wait<'static>>());
223};