rasi_syscall/
time.rs

1//! syscall for timeout.
2
3use std::{
4    io,
5    sync::OnceLock,
6    task::{Poll, Waker},
7    time::Instant,
8};
9
10use crate::handle::Handle;
11
12/// Timer-related system call interface
13pub trait Timer: Send + Sync {
14    /// Create new `deadline` timer, returns [`None`] if the `deadline` instant is reached.
15    fn deadline(&self, waker: Waker, deadline: Instant) -> io::Result<Option<Handle>>;
16
17    /// Wait timeout event.
18    ///
19    /// Returns [`Poll::Ready(())`](Poll::Ready) if the timer already reached the deadline,
20    /// otherwise returns [`Poll::Pending`] and needs to be retried later.
21    ///
22    /// We don't need to return [`CancelablePoll`](crate::CancelablePoll),
23    /// because the implementation should stop the timer when the timer handler drops.
24    fn timeout_wait(&self, waker: Waker, handle: &Handle) -> Poll<()>;
25}
26
27static GLOBAL_TIMER: OnceLock<Box<dyn Timer>> = OnceLock::new();
28
29/// Register provided [`Timer`] as global timer implementation.
30///
31/// # Panic
32///
33/// Multiple calls to this function are not permitted!!!
34pub fn register_global_timer<T: Timer + 'static>(timer: T) {
35    if GLOBAL_TIMER.set(Box::new(timer)).is_err() {
36        panic!("Multiple calls to register_global_timer are not permitted!!!");
37    }
38}
39
40/// Get the globally registered instance of [`Timer`].
41///
42/// # Panic
43///
44/// You should call [`register_global_timer`] first to register implementation,
45/// otherwise this function will cause a panic with `Call register_global_timer first`
46pub fn global_timer() -> &'static dyn Timer {
47    GLOBAL_TIMER
48        .get()
49        .expect("Call register_global_timer first")
50        .as_ref()
51}