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}