Skip to main content

lenso_kernel/
deterministic.rs

1use super::{
2    AbortHandle, Abortable, AssertUnwindSafe, Cell, DriverTask, Duration, Future, FutureExt,
3    LocalBoxFuture, LocalPool, LocalSpawnExt, LocalSpawner, LocalTask, Poll, Rc, RefCell,
4    RuntimeDriver, SpawnError, TaskOutcome, oneshot,
5};
6
7#[derive(Debug)]
8pub(super) struct DeterministicState {
9    pub(super) now: Cell<Duration>,
10    pub(super) shutdown_requested: Cell<bool>,
11    pub(super) jitter: Cell<Duration>,
12    pub(super) pool: RefCell<Option<LocalPool>>,
13    pub(super) spawner: LocalSpawner,
14    pub(super) timers: RefCell<Vec<(Duration, oneshot::Sender<()>)>>,
15}
16
17/// A deterministic, OS-independent Runtime Driver for Kernel conformance tests.
18#[derive(Clone, Debug)]
19pub struct DeterministicDriver {
20    pub(super) state: Rc<DeterministicState>,
21}
22
23impl DeterministicDriver {
24    /// Creates a Driver at monotonic instant zero.
25    pub fn new() -> Self {
26        let pool = LocalPool::new();
27        let spawner = pool.spawner();
28        Self {
29            state: Rc::new(DeterministicState {
30                now: Cell::new(Duration::ZERO),
31                shutdown_requested: Cell::new(false),
32                jitter: Cell::new(Duration::ZERO),
33                pool: RefCell::new(Some(pool)),
34                spawner,
35                timers: RefCell::new(Vec::new()),
36            }),
37        }
38    }
39
40    /// Runs a root Kernel future until its deterministic terminal result.
41    pub fn run<F: Future>(&self, future: F) -> F::Output {
42        let mut pool = self
43            .state
44            .pool
45            .borrow_mut()
46            .take()
47            .expect("deterministic Driver cannot run recursively");
48        let output = pool.run_until(future);
49        self.state.pool.replace(Some(pool));
50        output
51    }
52
53    /// Advances monotonic time without consulting a host clock.
54    pub fn advance(&self, duration: Duration) {
55        self.state.now.set(self.state.now.get() + duration);
56        let now = self.state.now.get();
57        let mut timers = self.state.timers.borrow_mut();
58        let mut pending = Vec::with_capacity(timers.len());
59        for (deadline, wakeup) in timers.drain(..) {
60            if deadline <= now {
61                let _ = wakeup.send(());
62            } else {
63                pending.push((deadline, wakeup));
64            }
65        }
66        *timers = pending;
67    }
68
69    /// Requests cooperative Kernel shutdown.
70    pub fn request_shutdown(&self) {
71        self.state.shutdown_requested.set(true);
72    }
73
74    /// Returns the current deterministic monotonic instant.
75    pub fn now(&self) -> Duration {
76        self.state.now.get()
77    }
78
79    /// Sets the deterministic jitter returned to supervision callers, capped by each policy.
80    pub fn set_jitter(&self, jitter: Duration) {
81        self.state.jitter.set(jitter);
82    }
83
84    /// Configures deterministic jitter while retaining builder-style Driver setup.
85    #[must_use]
86    pub fn with_jitter(self, jitter: Duration) -> Self {
87        self.set_jitter(jitter);
88        self
89    }
90}
91
92impl Default for DeterministicDriver {
93    fn default() -> Self {
94        Self::new()
95    }
96}
97
98impl RuntimeDriver for DeterministicDriver {
99    fn now(&self) -> Duration {
100        self.now()
101    }
102
103    fn sleep_until(&self, deadline: Duration) -> LocalBoxFuture<'static, ()> {
104        if deadline <= self.now() {
105            return Box::pin(futures::future::ready(()));
106        }
107        let (wakeup, sleeper) = oneshot::channel();
108        self.state.timers.borrow_mut().push((deadline, wakeup));
109        Box::pin(async move {
110            let _ = sleeper.await;
111        })
112    }
113
114    fn yield_now(&self) -> LocalBoxFuture<'static, ()> {
115        let mut yielded = false;
116        Box::pin(futures::future::poll_fn(move |context| {
117            if yielded {
118                Poll::Ready(())
119            } else {
120                yielded = true;
121                context.waker().wake_by_ref();
122                Poll::Pending
123            }
124        }))
125    }
126
127    fn jitter(&self, maximum: Duration) -> Duration {
128        self.state.jitter.get().min(maximum)
129    }
130
131    fn spawn_local(&self, task: LocalTask) -> Result<DriverTask, SpawnError> {
132        let (abort, registration) = AbortHandle::new_pair();
133        let (completed, completion) = oneshot::channel();
134        self.state.spawner.spawn_local(async move {
135            let outcome = match AssertUnwindSafe(Abortable::new(task, registration))
136                .catch_unwind()
137                .await
138            {
139                Ok(Ok(())) => TaskOutcome::Completed,
140                Ok(Err(_)) => TaskOutcome::Cancelled,
141                Err(_) => TaskOutcome::Failed,
142            };
143            let _ = completed.send(outcome);
144        })?;
145        Ok(DriverTask::new(abort, completion))
146    }
147
148    fn shutdown_requested(&self) -> bool {
149        self.state.shutdown_requested.get()
150    }
151}