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