cros_async/sys/linux/
event.rs

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
5use base::Event;
6
7use crate::AsyncError;
8use crate::AsyncResult;
9use crate::EventAsync;
10use crate::Executor;
11
12impl EventAsync {
13    pub fn new(event: Event, ex: &Executor) -> AsyncResult<EventAsync> {
14        ex.async_from(event)
15            .map(|io_source| EventAsync { io_source })
16    }
17
18    /// Gets the next value from the eventfd.
19    pub async fn next_val(&self) -> AsyncResult<u64> {
20        let (n, v) = self
21            .io_source
22            .read_to_vec(None, 0u64.to_ne_bytes().to_vec())
23            .await?;
24        if n != 8 {
25            return Err(AsyncError::EventAsync(base::Error::new(libc::ENODATA)));
26        }
27        Ok(u64::from_ne_bytes(v.try_into().unwrap()))
28    }
29}
30
31#[cfg(test)]
32mod tests {
33    use std::sync::Arc;
34
35    use base::EventExt;
36
37    use super::super::fd_executor::EpollReactor;
38    use super::super::uring_executor::UringReactor;
39    use super::*;
40    use crate::common_executor::RawExecutor;
41    use crate::sys::linux::uring_executor::is_uring_stable;
42    use crate::ExecutorTrait;
43
44    pub(crate) fn new_poll(
45        event: Event,
46        ex: &Arc<RawExecutor<EpollReactor>>,
47    ) -> AsyncResult<EventAsync> {
48        ex.async_from(event)
49            .map(|io_source| EventAsync { io_source })
50    }
51
52    pub(crate) fn new_uring(
53        event: Event,
54        ex: &Arc<RawExecutor<UringReactor>>,
55    ) -> AsyncResult<EventAsync> {
56        ex.async_from(event)
57            .map(|io_source| EventAsync { io_source })
58    }
59
60    #[test]
61    fn next_val_reads_value() {
62        async fn go(event: Event, ex: &Executor) -> u64 {
63            let event_async = EventAsync::new(event, ex).unwrap();
64            event_async.next_val().await.unwrap()
65        }
66
67        let eventfd = Event::new().unwrap();
68        eventfd.write_count(0xaa).unwrap();
69        let ex = Executor::new().unwrap();
70        let val = ex.run_until(go(eventfd, &ex)).unwrap();
71        assert_eq!(val, 0xaa);
72    }
73
74    #[test]
75    fn next_val_reads_value_poll_and_ring() {
76        if !is_uring_stable() {
77            return;
78        }
79
80        async fn go(event_async: EventAsync) -> u64 {
81            event_async.next_val().await.unwrap()
82        }
83
84        let eventfd = Event::new().unwrap();
85        eventfd.write_count(0xaa).unwrap();
86        let uring_ex = RawExecutor::<UringReactor>::new().unwrap();
87        let val = uring_ex
88            .run_until(go(new_uring(eventfd, &uring_ex).unwrap()))
89            .unwrap();
90        assert_eq!(val, 0xaa);
91
92        let eventfd = Event::new().unwrap();
93        eventfd.write_count(0xaa).unwrap();
94        let poll_ex = RawExecutor::<EpollReactor>::new().unwrap();
95        let val = poll_ex
96            .run_until(go(new_poll(eventfd, &poll_ex).unwrap()))
97            .unwrap();
98        assert_eq!(val, 0xaa);
99    }
100}