1 // Copyright 2021 The Chromium OS Authors. All rights reserved.
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 std::cell::RefCell;
8 use std::rc::Rc;
9
10 use anyhow::{Context, Result};
11 use base::Event;
12 use cros_async::{EventAsync, Executor};
13
14 use super::{Interrupt, SignalableInterrupt};
15
16 /// Async task that waits for a signal from `event`. Once this event is readable, exit. Exiting
17 /// this future will cause the main loop to break and the worker thread to exit.
await_and_exit(ex: &Executor, event: Event) -> Result<()>18 pub async fn await_and_exit(ex: &Executor, event: Event) -> Result<()> {
19 let event_async = EventAsync::new(event.0, ex).context("failed to create EventAsync")?;
20 let _ = event_async.next_val().await;
21 Ok(())
22 }
23
24 /// Async task that resamples the status of the interrupt when the guest sends a request by
25 /// signalling the resample event associated with the interrupt.
handle_irq_resample(ex: &Executor, interrupt: Rc<RefCell<Interrupt>>) -> Result<()>26 pub async fn handle_irq_resample(ex: &Executor, interrupt: Rc<RefCell<Interrupt>>) -> Result<()> {
27 // Clone resample_evt if interrupt has one.
28 // This is a separate block so that we do not hold a RefCell borrow across await.
29 let resample_evt = if let Some(resample_evt) = interrupt.borrow().get_resample_evt() {
30 let resample_evt = resample_evt
31 .try_clone()
32 .context("resample_evt.try_clone() failed")?;
33 Some(EventAsync::new(resample_evt.0, ex).context("failed to create async resample event")?)
34 } else {
35 None
36 };
37
38 if let Some(resample_evt) = resample_evt {
39 loop {
40 let _ = resample_evt
41 .next_val()
42 .await
43 .context("failed to read resample event")?;
44 interrupt.borrow().do_interrupt_resample();
45 }
46 } else {
47 // No resample event; park the future.
48 let () = futures::future::pending().await;
49 }
50 Ok(())
51 }
52