xref: /aosp_15_r20/external/crosvm/cros_async/src/sys/linux/timer.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2022 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use base::TimerTrait;
6 
7 use crate::AsyncError;
8 use crate::AsyncResult;
9 use crate::IntoAsync;
10 use crate::TimerAsync;
11 
12 impl<T: TimerTrait + IntoAsync> TimerAsync<T> {
wait_sys(&self) -> AsyncResult<()>13     pub async fn wait_sys(&self) -> AsyncResult<()> {
14         let (n, _) = self
15             .io_source
16             .read_to_vec(None, 0u64.to_ne_bytes().to_vec())
17             .await?;
18         if n != 8 {
19             return Err(AsyncError::EventAsync(base::Error::new(libc::ENODATA)));
20         }
21         Ok(())
22     }
23 }
24 
25 #[cfg(test)]
26 mod tests {
27     use std::sync::Arc;
28     use std::time::Duration;
29     use std::time::Instant;
30 
31     use base::Timer;
32 
33     use super::super::fd_executor::EpollReactor;
34     use super::super::uring_executor::UringReactor;
35     use super::*;
36     use crate::common_executor::RawExecutor;
37     use crate::sys::linux::uring_executor::is_uring_stable;
38     use crate::Executor;
39     use crate::ExecutorTrait;
40 
41     impl TimerAsync<Timer> {
new_poll( timer: Timer, ex: &Arc<RawExecutor<EpollReactor>>, ) -> AsyncResult<TimerAsync<Timer>>42         pub(crate) fn new_poll(
43             timer: Timer,
44             ex: &Arc<RawExecutor<EpollReactor>>,
45         ) -> AsyncResult<TimerAsync<Timer>> {
46             ex.async_from(timer)
47                 .map(|io_source| TimerAsync { io_source })
48         }
49 
new_uring( timer: Timer, ex: &Arc<RawExecutor<UringReactor>>, ) -> AsyncResult<TimerAsync<Timer>>50         pub(crate) fn new_uring(
51             timer: Timer,
52             ex: &Arc<RawExecutor<UringReactor>>,
53         ) -> AsyncResult<TimerAsync<Timer>> {
54             ex.async_from(timer)
55                 .map(|io_source| TimerAsync { io_source })
56         }
57     }
58 
59     #[test]
timer()60     fn timer() {
61         async fn this_test(ex: &Executor) {
62             let dur = Duration::from_millis(200);
63             let now = Instant::now();
64             TimerAsync::sleep(ex, dur).await.expect("unable to sleep");
65             assert!(now.elapsed() >= dur);
66         }
67 
68         let ex = Executor::new().expect("creating an executor failed");
69         ex.run_until(this_test(&ex)).unwrap();
70     }
71 
72     #[test]
one_shot()73     fn one_shot() {
74         if !is_uring_stable() {
75             return;
76         }
77 
78         async fn this_test(ex: &Arc<RawExecutor<UringReactor>>) {
79             let mut tfd = Timer::new().expect("failed to create timerfd");
80 
81             let dur = Duration::from_millis(200);
82             let now = Instant::now();
83             tfd.reset_oneshot(dur).expect("failed to arm timer");
84 
85             let t = TimerAsync::new_uring(tfd, ex).unwrap();
86             t.wait().await.expect("unable to wait for timer");
87 
88             assert!(now.elapsed() >= dur);
89         }
90 
91         let ex = RawExecutor::<UringReactor>::new().unwrap();
92         ex.run_until(this_test(&ex)).unwrap();
93     }
94 
95     #[test]
one_shot_fd()96     fn one_shot_fd() {
97         async fn this_test(ex: &Arc<RawExecutor<EpollReactor>>) {
98             let mut tfd = Timer::new().expect("failed to create timerfd");
99 
100             let dur = Duration::from_millis(200);
101             let now = Instant::now();
102             tfd.reset_oneshot(dur).expect("failed to arm timer");
103 
104             let t = TimerAsync::new_poll(tfd, ex).unwrap();
105             t.wait().await.expect("unable to wait for timer");
106 
107             assert!(now.elapsed() >= dur);
108         }
109 
110         let ex = RawExecutor::<EpollReactor>::new().unwrap();
111         ex.run_until(this_test(&ex)).unwrap();
112     }
113 }
114