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 Workerpub 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 Workerpub 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