xref: /aosp_15_r20/external/crosvm/devices/src/virtio/async_utils.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2021 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 //! Virtio device async helper functions.
6 
7 use anyhow::Context;
8 use anyhow::Result;
9 use base::Event;
10 use cros_async::EventAsync;
11 use cros_async::Executor;
12 
13 use super::Interrupt;
14 
15 /// Async task that waits for a signal from `event`.  Once this event is readable, exit. Exiting
16 /// this future will cause the main loop to break and the worker thread to exit.
await_and_exit(ex: &Executor, event: Event) -> Result<()>17 pub async fn await_and_exit(ex: &Executor, event: Event) -> Result<()> {
18     let event_async = EventAsync::new(event, ex).context("failed to create EventAsync")?;
19     let _ = event_async.next_val().await;
20     Ok(())
21 }
22 
23 /// Async task that resamples the status of the interrupt when the guest sends a request by
24 /// signalling the resample event associated with the interrupt.
25 ///
26 /// When called on a vhost-user `Interrupt` (i.e. from a vhost-user backend), this function does
27 /// nothing, which is the correct behavior because irq resampling is handled by the frontend.
handle_irq_resample(ex: &Executor, interrupt: Interrupt) -> Result<()>28 pub async fn handle_irq_resample(ex: &Executor, interrupt: Interrupt) -> Result<()> {
29     // Clone resample_evt if interrupt has one.
30     if let Some(resample_evt) = interrupt.get_resample_evt() {
31         let resample_evt = resample_evt
32             .try_clone()
33             .context("resample_evt.try_clone() failed")?;
34         let resample_evt =
35             EventAsync::new(resample_evt, ex).context("failed to create async resample event")?;
36         loop {
37             let _ = resample_evt
38                 .next_val()
39                 .await
40                 .context("failed to read resample event")?;
41             interrupt.do_interrupt_resample();
42         }
43     } else {
44         // No resample event; park the future.
45         std::future::pending::<()>().await;
46         Ok(())
47     }
48 }
49