Skip to main content

dope_core/driver/retained/flight/
mod.rs

1use crate::{driver::life::finish, io::fd::handles};
2pub mod cancel;
3mod complete;
4pub(crate) mod raw;
5mod request;
6mod slots;
7pub mod storage;
8use std::{marker, mem};
9
10pub(crate) use complete::Complete;
11use dope_sys::{engine::admit::Cancelled, table::token::host};
12use o3::{alloc, base::marker::ThreadBound};
13pub(crate) use request::Request;
14use route::table;
15pub use slots::Slots;
16use table::conn;
17
18use crate::{
19    driver::{
20        self,
21        route::{self, kind},
22    },
23    io::fd::domain::retire,
24};
25
26type Invariant<'d> = (driver::Invariant<'d>, marker::PhantomData<ThreadBound>);
27
28const INDEX_BITS: u32 = route::SLOT_BITS;
29const GENERATION_BITS: u32 = 32;
30
31#[derive(Clone, Copy, Debug, Eq, PartialEq)]
32#[repr(C)]
33struct Target {
34    epoch: route::Epoch,
35    slot: route::indices::SlotIndex,
36    kind: kind::Native,
37    route: route::Route,
38}
39
40impl Target {
41    fn new<Tag: route::Tag, C: kind::Flight>(target: route::Operation<'_, Tag, C>) -> Self {
42        let parts = target.parts();
43        Self {
44            epoch: parts.epoch(),
45            slot: parts.slot(),
46            kind: C::FLIGHT,
47            route: Tag::ROUTE,
48        }
49    }
50
51    fn token(self) -> route::Token {
52        route::Token::from_flight(self.epoch, self.slot, self.kind, self.route)
53    }
54
55    fn bind<'d, C: kind::Class>(
56        self,
57        driver: driver::Invariant<'d>,
58        flight: raw::Echo,
59    ) -> route::Erased<'d, C> {
60        route::Erased {
61            token: self.token(),
62            flight: Some(flight),
63            driver,
64            class: marker::PhantomData,
65        }
66    }
67}
68
69#[repr(transparent)]
70pub(crate) struct Arena(storage::Flights<Target, INDEX_BITS, GENERATION_BITS>);
71
72/// Exact kernel-flight capacity derived from an existing typed resource bound.
73#[derive(Clone, Copy, Eq, PartialEq)]
74#[repr(transparent)]
75pub struct Capacity(usize);
76
77/// Typed flight-group requirements retained until their shared preparation.
78pub struct Need<Tags, const GROUPS: usize = 1> {
79    caps: [Capacity; GROUPS],
80    tags: marker::PhantomData<Tags>,
81}
82
83/// Exact connection scaling rejected by the kernel-flight slot bound.
84#[derive(Clone, Copy, Eq, PartialEq, Debug)]
85pub enum ScaleError {
86    Product {
87        capacity: conn::Capacity,
88        factor: usize,
89    },
90    Limit {
91        actual: usize,
92        maximum: usize,
93    },
94}
95
96impl Capacity {
97    pub const fn fixed<const FLIGHTS: usize>() -> Self {
98        const { assert!(FLIGHTS > 0 && FLIGHTS <= route::SLOT_MASK as usize + 1) };
99        Self(FLIGHTS)
100    }
101
102    pub const fn table(capacity: table::Capacity) -> Self {
103        Self(capacity.count().get())
104    }
105
106    pub const fn connections<const PER_CONNECTION: usize>(
107        capacity: conn::Capacity,
108    ) -> Result<Self, ScaleError> {
109        const { assert!(PER_CONNECTION > 0) };
110        let Some(total) = (capacity.raw() as usize).checked_mul(PER_CONNECTION) else {
111            return Err(ScaleError::Product {
112                capacity,
113                factor: PER_CONNECTION,
114            });
115        };
116        let maximum = route::SLOT_MASK as usize + 1;
117        if total > maximum {
118            return Err(ScaleError::Limit {
119                actual: total,
120                maximum,
121            });
122        }
123        Ok(Self(total))
124    }
125
126    pub const fn capped<const MAX: usize>(capacity: table::Capacity) -> Self {
127        const { assert!(MAX > 0) };
128        let capacity = capacity.count().get();
129        Self(if capacity < MAX { capacity } else { MAX })
130    }
131
132    pub(crate) const fn get(self) -> usize {
133        self.0
134    }
135}
136
137impl<Tag: route::Tag> Need<Tag> {
138    pub const fn new(cap: Capacity) -> Self {
139        Self {
140            caps: [cap],
141            tags: marker::PhantomData,
142        }
143    }
144}
145
146impl<A: route::Tag> Need<A> {
147    pub fn pair<B: route::Tag>(self, other: Need<B>) -> Need<(A, B), 2> {
148        let Self {
149            caps: [first],
150            tags: marker::PhantomData,
151        } = self;
152        let Need {
153            caps: [second],
154            tags: marker::PhantomData,
155        } = other;
156        Need {
157            caps: [first, second],
158            tags: marker::PhantomData,
159        }
160    }
161}
162
163impl<A: route::Tag, B: route::Tag> Need<(A, B), 2> {
164    pub fn push<C: route::Tag>(self, other: Need<C>) -> Need<(A, B, C), 3> {
165        let Self {
166            caps: [first, second],
167            tags: marker::PhantomData,
168        } = self;
169        let Need {
170            caps: [third],
171            tags: marker::PhantomData,
172        } = other;
173        Need {
174            caps: [first, second, third],
175            tags: marker::PhantomData,
176        }
177    }
178}
179
180impl<Tags, const GROUPS: usize> Need<Tags, GROUPS> {
181    const fn into_caps(self) -> [Capacity; GROUPS] {
182        self.caps
183    }
184}
185
186#[must_use = "prepared flight slots must be committed"]
187pub struct Prepared<'a, 'd, Tags, const GROUPS: usize = 1> {
188    prepared: storage::Prepared<'a, 'd, Target, INDEX_BITS, GENERATION_BITS, GROUPS>,
189    driver: driver::Invariant<'d>,
190    tags: marker::PhantomData<Tags>,
191}
192
193#[must_use = "a validated flight vacancy must be reserved or released"]
194pub(crate) struct Vacant<'slot, 'd, Tag: route::Tag, C: kind::Class = <Tag as route::Tag>::Class> {
195    vacancy: storage::Vacant<'slot, 'd, Target, INDEX_BITS, GENERATION_BITS>,
196    target: Target,
197    driver: Invariant<'d>,
198    class: marker::PhantomData<(Tag, C)>,
199}
200
201#[must_use = "a reserved flight must be committed or released"]
202#[repr(transparent)]
203pub(crate) struct Reserved<'d, C: kind::Class = kind::Any> {
204    reservation: storage::Reserved<'d, Target, INDEX_BITS, GENERATION_BITS>,
205    driver: Invariant<'d>,
206    class: marker::PhantomData<C>,
207}
208
209/// Exact kernel-flight authority bound invariantly to its driver.
210/// Dropping this owner preserves any pending native completion.
211#[must_use = "a live flight must reach terminal completion or quiescence"]
212#[repr(transparent)]
213pub struct Flight<'d, C: kind::Class = kind::Any> {
214    flight: storage::Lease<'d, Target, INDEX_BITS, GENERATION_BITS>,
215    driver: Invariant<'d>,
216    class: marker::PhantomData<C>,
217}
218
219pub(crate) struct Drain<'q, 'd> {
220    drain: storage::Drain<'q, Target, INDEX_BITS, GENERATION_BITS>,
221    driver: driver::Reference<'d>,
222}
223
224impl Arena {
225    pub(crate) fn new() -> Self {
226        Self(storage::Flights::new())
227    }
228
229    pub(in crate::driver) fn is_pending(&self) -> bool {
230        self.0.is_pending()
231    }
232
233    pub(in crate::driver) fn finish(&self) {
234        self.0.finish();
235    }
236
237    pub(crate) fn try_prepare<'a, 'd, Tags, const GROUPS: usize>(
238        &'a mut self,
239        need: Need<Tags, GROUPS>,
240        driver: driver::Reference<'d>,
241    ) -> Result<Prepared<'a, 'd, Tags, GROUPS>, alloc::Error> {
242        raw::prepare(&mut self.0, need, driver)
243    }
244}
245
246impl<'d, Tags, const GROUPS: usize> Prepared<'_, 'd, Tags, GROUPS> {
247    fn commit(
248        self,
249    ) -> (
250        [storage::Slots<'d, Target, INDEX_BITS, GENERATION_BITS>; GROUPS],
251        Invariant<'d>,
252    ) {
253        let Self {
254            prepared,
255            driver,
256            tags: marker::PhantomData,
257        } = self;
258        let slots = prepared.groups();
259        (slots, (driver, marker::PhantomData))
260    }
261}
262
263impl<'d, Tag: route::Tag> Prepared<'_, 'd, Tag> {
264    pub fn slots(self) -> Slots<'d, Tag> {
265        let ([slots], driver) = self.commit();
266        Slots::new(slots, driver)
267    }
268}
269
270impl<'d, A: route::Tag, B: route::Tag> Prepared<'_, 'd, (A, B), 2> {
271    pub fn slots(self) -> (Slots<'d, A>, Slots<'d, B>) {
272        let ([first, second], driver) = self.commit();
273        (Slots::new(first, driver), Slots::new(second, driver))
274    }
275}
276
277impl<'d, A: route::Tag, B: route::Tag, C: route::Tag> Prepared<'_, 'd, (A, B, C), 3> {
278    pub fn slots(self) -> (Slots<'d, A>, Slots<'d, B>, Slots<'d, C>) {
279        let ([first, second, third], driver) = self.commit();
280        (
281            Slots::new(first, driver),
282            Slots::new(second, driver),
283            Slots::new(third, driver),
284        )
285    }
286}
287
288impl<'d, Tag: route::Tag, C: kind::Class> Vacant<'_, 'd, Tag, C> {
289    pub(crate) fn reserve(self) -> Reserved<'d, C> {
290        Reserved {
291            reservation: self.vacancy.reserve(self.target),
292            driver: self.driver,
293            class: marker::PhantomData,
294        }
295    }
296}
297
298impl<'d, C: kind::Class> Reserved<'d, C> {
299    pub(crate) fn key(&self) -> raw::Echo {
300        raw::Echo::from_inner(self.reservation.echo())
301    }
302
303    pub(crate) fn commit(self) -> Flight<'d, C> {
304        Flight {
305            flight: self.reservation.commit(),
306            driver: self.driver,
307            class: marker::PhantomData,
308        }
309    }
310}
311
312impl<'q, 'd> Drain<'q, 'd> {
313    pub(crate) fn new(arena: &'q Arena, driver: driver::Reference<'d>) -> Self {
314        Self {
315            drain: arena.0.drain(),
316            driver,
317        }
318    }
319}
320
321impl<'q, 'd> host::Drain for Drain<'q, 'd> {
322    type Driver = driver::Reference<'d>;
323
324    fn driver(&self) -> Self::Driver {
325        self.driver
326    }
327
328    type Key = raw::Echo;
329    type Returned = retire::Returned;
330    type Flight = Complete<'q, 'd>;
331    type Echo = retire::Echo<'d>;
332    type Class = handles::Retirement;
333
334    fn bind(&self, key: raw::Echo) -> Option<Complete<'q, 'd>> {
335        self.drain.bind(key.into_inner()).map(|bound| Complete {
336            completion: bound,
337            driver: self.driver,
338            class: marker::PhantomData,
339        })
340    }
341
342    fn retired(&self, returned: Self::Returned) -> host::Closed<Self::Echo, Self::Class> {
343        use host::Closed;
344        match self.driver.descriptors().retirement().bind(returned) {
345            retire::Bind::Ready(echo) => Closed::Ready(echo),
346            retire::Bind::Class {
347                echo,
348                expected,
349                observed,
350            } => Closed::Class {
351                echo,
352                expected,
353                observed,
354            },
355            retire::Bind::Missing => Closed::Missing,
356        }
357    }
358}
359
360impl<'d, C: kind::Class> Flight<'d, C> {
361    pub(crate) fn is_pending(&self) -> bool {
362        self.flight.is_pending()
363    }
364
365    pub(crate) fn key(&self) -> raw::Echo {
366        raw::Echo::from_inner(self.flight.echo())
367    }
368
369    pub fn target(&self) -> route::Erased<'d, C> {
370        self.flight.value().bind(self.driver.0, self.key())
371    }
372
373    pub fn matches(&self, target: route::Erased<'d, C>) -> bool {
374        self.target().matches_flight(target)
375    }
376
377    pub(in crate::driver) fn finish(mut self, proof: &mut finish::Finish<'_, 'd>) {
378        self.driver.0 = proof.brand();
379    }
380}
381
382const _: () = {
383    assert!(mem::size_of::<Arena>() == 4 * mem::size_of::<usize>());
384    assert!(mem::align_of::<Arena>() == mem::align_of::<usize>());
385    assert!(mem::size_of::<Target>() == mem::size_of::<route::Token>());
386    assert!(mem::align_of::<Target>() == mem::align_of::<route::Token>());
387    assert!(mem::size_of::<raw::Echo>() == mem::size_of::<usize>());
388    assert!(mem::size_of::<Flight<'static>>() == mem::size_of::<usize>());
389    assert!(mem::size_of::<Option<Flight<'static>>>() == mem::size_of::<usize>());
390    assert!(mem::size_of::<Reserved<'static>>() == mem::size_of::<usize>());
391    assert!(
392        mem::size_of::<Vacant<'static, 'static, route::KeyTag<1>>>()
393            == mem::size_of::<storage::Vacant<'static, 'static, Target, INDEX_BITS, GENERATION_BITS>>(
394            ) + mem::size_of::<route::Token>()
395    );
396    assert!(mem::size_of::<Drain<'static, 'static>>() == 2 * mem::size_of::<usize>());
397    assert!(mem::size_of::<Complete<'static, 'static>>() == 2 * mem::size_of::<usize>());
398    assert!(mem::size_of::<Slots<'static, route::KeyTag<1>>>() == mem::size_of::<usize>());
399};
400
401pub(crate) struct Mismatch<'q, 'd> {
402    pub(crate) bound: Complete<'q, 'd>,
403    pub(crate) expected: kind::Native,
404    pub(crate) observed: kind::Native,
405}
406
407impl<'d, C: kind::Class> Flight<'d, C> {
408    /// Submits cancellation for this exact flight without releasing its owners.
409    pub fn try_cancel(
410        &mut self,
411        driver: &mut driver::Context<'_, 'd>,
412    ) -> Result<Cancelled, cancel::Error> {
413        driver.native().try_cancel(self)
414    }
415}
416
417impl<'d, C: kind::Class> Flight<'d, C> {
418    /// Cancellation reserves no new flight, so capacity refusal is queue fullness.
419    pub fn try_stop(
420        &mut self,
421        driver: &mut driver::Context<'_, 'd>,
422    ) -> Result<cancel::Outcome, cancel::Failure> {
423        let status = match self.try_cancel(driver) {
424            Ok(status) => status,
425            Err(cancel::Error::Full(_)) => {
426                return Ok(cancel::Outcome::Deferred);
427            }
428            Err(cancel::Error::Rejected(cause)) => return Err(cause),
429        };
430        Ok(match status {
431            Cancelled::Submitted => cancel::Outcome::Submitted,
432            Cancelled::Queued => cancel::Outcome::Queued,
433            Cancelled::Completed => cancel::Outcome::Completed,
434        })
435    }
436}