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<()>17pub 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<()>28pub 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