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