dope_core/driver/schedule/
mod.rs1use std::{cell, marker, mem, time};
2
3use o3::{alloc, base::cell::region, mem::quota};
4use state::{lanes::Quota, 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#[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 driver: marker::PhantomData<fn(&'d ()) -> &'d ()>,
39}
40
41impl<'turn, 'd> Turn<'turn, 'd> {
42 pub(in crate::driver::schedule) const fn new(state: &'turn state::Core<'d>) -> Self {
43 Self {
44 state,
45 driver: marker::PhantomData,
46 }
47 }
48
49 pub fn reborrow(&self) -> Turn<'_, 'd> {
50 Turn::new(self.state)
51 }
52
53 pub fn clock(self) -> clock::Clock<'turn, 'd> {
54 self.state.driver.scheduler().clock()
55 }
56
57 pub fn app(self) -> app::Work<'turn, 'd> {
58 app::Work { state: self.state }
59 }
60
61 pub fn maint(self) -> maint::Work<'turn, 'd> {
62 maint::Work { state: self.state }
63 }
64
65 #[doc(hidden)]
69 pub fn share<const N: usize, T>(
70 self,
71 ranks: [usize; 3],
72 weights: [usize; 2],
73 run: impl for<'scope> FnOnce(Turn<'scope, 'd>) -> T,
74 ) -> T {
75 let _app = Quota::share::<N, _>(&self.state.lanes.app, ranks[0]);
76 let _maint = Quota::share::<N, _>(&self.state.lanes.maint, ranks[1]);
77 let _coord = Quota::weighted::<N, _>(&self.state.lanes.coord, ranks[2], weights);
78 run(Turn::new(self.state))
79 }
80
81 #[doc(hidden)]
82 pub fn coord(self) -> scope::Coord<'turn, 'd> {
83 scope::Coord::new(self.state)
84 }
85}
86
87const _: () = {
88 let word = mem::size_of::<usize>();
89 assert!(mem::size_of::<Turn<'static, 'static>>() == word);
90 assert!(mem::size_of::<quota::Admission<usize>>() == 2 * word);
91 assert!(mem::size_of::<Capacity<&'static u8>>() == word);
92};
93
94#[must_use]
96pub enum Progress<'d> {
97 Runnable,
98 Waiting(Wait<'d>),
99 Quiescent,
100}
101
102impl<'d> Progress<'d> {
103 pub fn waiting(region: ®ion::Token<region::Identity<'d>>) -> Self {
104 Self::Waiting(Wait::event(region))
105 }
106
107 pub fn until(deadline: clock::Deadline<'d>) -> Self {
108 Self::Waiting(Wait::until(deadline))
109 }
110
111 pub fn reduce(self, other: Self) -> Self {
112 match self {
113 runnable @ Self::Runnable => runnable,
114 Self::Waiting(left) => match other {
115 runnable @ Self::Runnable => runnable,
116 Self::Waiting(right) => Self::Waiting(left.reduce(right)),
117 Self::Quiescent => Self::Waiting(left),
118 },
119 Self::Quiescent => other,
120 }
121 }
122}
123
124const _: () = assert!(mem::size_of::<Progress<'static>>() <= 24);
125
126pub(in crate::driver) struct State {
127 pub(in crate::driver) owner: storage::Owner<ready::Stored, credit::Wake, ready::Arena>,
128 clock: cell::Cell<time::Instant>,
129}
130
131impl State {
132 pub(in crate::driver) fn try_new(plan: settings::Plan) -> Result<Self, alloc::Error> {
133 Ok(Self {
134 owner: storage::Owner::try_new(plan)?,
135 clock: cell::Cell::new(time::Instant::now()),
136 })
137 }
138}
139
140#[derive(Clone, Copy)]
141#[repr(transparent)]
142pub struct Context<'d>(driver::Reference<'d>);
143
144impl<'d> Context<'d> {
145 pub(in crate::driver) const fn new(driver: driver::Reference<'d>) -> Self {
146 Self(driver)
147 }
148
149 pub(in crate::driver) fn clock(self) -> clock::Clock<'d, 'd> {
150 clock::Clock::new(&self.0.shared.context().schedule.clock, self.0.brand)
151 }
152
153 pub(in crate::driver) fn set_turn_now(self, now: time::Instant) {
154 self.0.shared.context().schedule.clock.set(now);
155 }
156
157 pub fn try_storage(
159 self,
160 capacity: conn::Capacity,
161 ) -> Result<credit::Storage<'d>, alloc::Error> {
162 let shared: &'d driver::Shared = self.0.shared.context();
163 let owner = &shared.schedule.owner;
164 owner.try_storage(capacity, self.0.brand)
165 }
166}
167
168const _: () = assert!(
169 std::mem::size_of::<Context<'static>>() == std::mem::size_of::<driver::Reference<'static>>()
170);
171
172enum Reason<'d> {
173 Event(region::Proof<region::Identity<'d>>),
174 Until(clock::Deadline<'d>),
175}
176
177#[must_use]
180#[repr(transparent)]
181pub struct Wait<'d> {
182 state: Reason<'d>,
183}
184
185impl<'d> Wait<'d> {
186 pub fn event(region: ®ion::Token<region::Identity<'d>>) -> Self {
187 Self {
188 state: Reason::Event(region.proof()),
189 }
190 }
191
192 pub fn until(deadline: clock::Deadline<'d>) -> Self {
193 Self {
194 state: Reason::Until(deadline),
195 }
196 }
197
198 pub fn deadline(self) -> Option<clock::Deadline<'d>> {
199 match self.state {
200 Reason::Event(_proof) => None,
201 Reason::Until(deadline) => Some(deadline),
202 }
203 }
204
205 pub(super) fn reduce(self, other: Self) -> Self {
206 match self.state {
207 Reason::Event(_proof) => other,
208 Reason::Until(left) => match other.state {
209 Reason::Event(_proof) => Self {
210 state: Reason::Until(left),
211 },
212 Reason::Until(right) => Self {
213 state: Reason::Until(left.min(right)),
214 },
215 },
216 }
217 }
218}
219
220const _: () = {
221 assert!(mem::size_of::<Wait<'static>>() == mem::size_of::<Option<clock::Deadline<'static>>>());
222 assert!(
223 mem::align_of::<Wait<'static>>() == mem::align_of::<Option<clock::Deadline<'static>>>()
224 );
225 assert!(mem::size_of::<Option<Wait<'static>>>() == mem::size_of::<Wait<'static>>());
226 assert!(!mem::needs_drop::<Wait<'static>>());
227};