devices: Add a trait for Interrupt

Having a trait for interrupts used by queue and the devices allows for a
slightly different implementation to handle interrupting the guest when
using vhost-user.

Change devices to handle the resample event being optional as it is
handled on the VMM side with vhost_user.

Change-Id: I511d3db66a7986e7a2a8bce5f48285171dee3388
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2795284
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Keiichi Watanabe <keiichiw@chromium.org>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Commit-Queue: Dylan Reid <dgreid@chromium.org>
This commit is contained in:
Dylan Reid 2021-01-06 22:52:34 -08:00 committed by Commit Bot
parent f860f50b8a
commit 4786cee521
18 changed files with 221 additions and 109 deletions

View file

@ -19,8 +19,8 @@ use vm_control::{BalloonControlCommand, BalloonControlResult, BalloonStats};
use vm_memory::{GuestAddress, GuestMemory};
use super::{
copy_config, descriptor_utils, DescriptorChain, Interrupt, Queue, Reader, VirtioDevice,
TYPE_BALLOON,
copy_config, descriptor_utils, DescriptorChain, Interrupt, Queue, Reader, SignalableInterrupt,
VirtioDevice, TYPE_BALLOON,
};
#[sorted]
@ -276,14 +276,20 @@ async fn handle_command_tube(
// Async task that resamples the status of the interrupt when the guest sends a request by
// signalling the resample event associated with the interrupt.
async fn handle_irq_resample(ex: &Executor, interrupt: Rc<RefCell<Interrupt>>) {
let resample_evt = interrupt
.borrow_mut()
.get_resample_evt()
.try_clone()
.unwrap();
let resample_evt = EventAsync::new(resample_evt.0, ex).unwrap();
while resample_evt.next_val().await.is_ok() {
interrupt.borrow_mut().do_interrupt_resample();
let resample_evt = if let Some(resample_evt) = interrupt.borrow_mut().get_resample_evt() {
let resample_evt = resample_evt.try_clone().unwrap();
let resample_evt = EventAsync::new(resample_evt.0, ex).unwrap();
Some(resample_evt)
} else {
None
};
if let Some(resample_evt) = resample_evt {
while resample_evt.next_val().await.is_ok() {
interrupt.borrow_mut().do_interrupt_resample();
}
} else {
// no resample event, park the future.
let () = futures::future::pending().await;
}
}

View file

@ -26,8 +26,8 @@ use vm_control::{DiskControlCommand, DiskControlResult};
use vm_memory::GuestMemory;
use super::{
copy_config, DescriptorChain, DescriptorError, Interrupt, Queue, Reader, VirtioDevice, Writer,
TYPE_BLOCK,
copy_config, DescriptorChain, DescriptorError, Interrupt, Queue, Reader, SignalableInterrupt,
VirtioDevice, Writer, TYPE_BLOCK,
};
const QUEUE_SIZE: u16 = 256;
@ -397,9 +397,14 @@ impl Worker {
let wait_ctx: WaitContext<Token> = match WaitContext::build_with(&[
(&flush_timer, Token::FlushTimer),
(&queue_evt, Token::QueueAvailable),
(self.interrupt.get_resample_evt(), Token::InterruptResample),
(&kill_evt, Token::Kill),
])
.and_then(|wc| {
if let Some(resample_evt) = self.interrupt.get_resample_evt() {
wc.add(resample_evt, Token::InterruptResample)?;
}
Ok(wc)
})
.and_then(|pc| {
if let Some(control_tube) = self.control_tube.as_ref() {
pc.add(control_tube, Token::ControlRequest)?

View file

@ -33,8 +33,8 @@ use vm_control::{DiskControlCommand, DiskControlResult};
use vm_memory::GuestMemory;
use super::{
copy_config, DescriptorChain, DescriptorError, Interrupt, Queue, Reader, VirtioDevice, Writer,
TYPE_BLOCK,
copy_config, DescriptorChain, DescriptorError, Interrupt, Queue, Reader, SignalableInterrupt,
VirtioDevice, Writer, TYPE_BLOCK,
};
const QUEUE_SIZE: u16 = 256;
@ -306,7 +306,7 @@ async fn process_one_request_task(
let mut queue = queue.borrow_mut();
queue.add_used(&mem, descriptor_index, len as u32);
queue.trigger_interrupt(&mem, &interrupt.borrow());
queue.trigger_interrupt(&mem, &*interrupt.borrow());
queue.update_int_required(&mem);
}
@ -347,19 +347,28 @@ async fn handle_irq_resample(
ex: &Executor,
interrupt: Rc<RefCell<Interrupt>>,
) -> result::Result<(), OtherError> {
let resample_evt = interrupt
.borrow_mut()
.get_resample_evt()
.try_clone()
.map_err(OtherError::CloneResampleEvent)?;
let resample_evt =
EventAsync::new(resample_evt.0, ex).map_err(OtherError::AsyncResampleCreate)?;
loop {
let _ = resample_evt
.next_val()
.await
.map_err(OtherError::ReadResampleEvent)?;
interrupt.borrow_mut().do_interrupt_resample();
let resample_evt = if let Some(resample_evt) = interrupt.borrow().get_resample_evt() {
let resample_evt = resample_evt
.try_clone()
.map_err(OtherError::CloneResampleEvent)?;
let resample_evt =
EventAsync::new(resample_evt.0, ex).map_err(OtherError::AsyncResampleCreate)?;
Some(resample_evt)
} else {
None
};
if let Some(resample_evt) = resample_evt {
loop {
let _ = resample_evt
.next_val()
.await
.map_err(OtherError::ReadResampleEvent)?;
interrupt.borrow().do_interrupt_resample();
}
} else {
// no resample event, park the future.
let () = futures::future::pending().await;
Ok(())
}
}

View file

@ -11,7 +11,8 @@ use data_model::{DataInit, Le16, Le32};
use vm_memory::GuestMemory;
use super::{
base_features, copy_config, Interrupt, Queue, Reader, VirtioDevice, Writer, TYPE_CONSOLE,
base_features, copy_config, Interrupt, Queue, Reader, SignalableInterrupt, VirtioDevice,
Writer, TYPE_CONSOLE,
};
use crate::{ProtectionType, SerialDevice};
@ -239,7 +240,6 @@ impl Worker {
(&transmit_evt, Token::TransmitQueueAvailable),
(&receive_evt, Token::ReceiveQueueAvailable),
(&in_avail_evt, Token::InputAvailable),
(self.interrupt.get_resample_evt(), Token::InterruptResample),
(&kill_evt, Token::Kill),
]) {
Ok(pc) => pc,
@ -248,6 +248,15 @@ impl Worker {
return;
}
};
if let Some(resample_evt) = self.interrupt.get_resample_evt() {
if wait_ctx
.add(resample_evt, Token::InterruptResample)
.is_err()
{
error!("failed adding resample event to WaitContext.");
return;
}
}
let mut output: Box<dyn io::Write> = match self.output.take() {
Some(o) => o,

View file

@ -14,7 +14,7 @@ use vm_control::{FsMappingRequest, VmResponse};
use vm_memory::GuestMemory;
use crate::virtio::fs::{Error, Result};
use crate::virtio::{Interrupt, Queue, Reader, Writer};
use crate::virtio::{Interrupt, Queue, Reader, SignalableInterrupt, Writer};
impl fuse::Reader for Reader {}
@ -217,9 +217,11 @@ impl<F: FileSystem + Sync> Worker<F> {
.map_err(Error::CreateWaitContext)?;
if watch_resample_event {
wait_ctx
.add(self.irq.get_resample_evt(), Token::InterruptResample)
.map_err(Error::CreateWaitContext)?;
if let Some(resample_evt) = self.irq.get_resample_evt() {
wait_ctx
.add(resample_evt, Token::InterruptResample)
.map_err(Error::CreateWaitContext)?;
}
}
loop {

View file

@ -37,8 +37,8 @@ use sync::Mutex;
use vm_memory::{GuestAddress, GuestMemory};
use super::{
copy_config, resource_bridge::*, DescriptorChain, Interrupt, Queue, Reader, VirtioDevice,
Writer, TYPE_GPU,
copy_config, resource_bridge::*, DescriptorChain, Interrupt, Queue, Reader,
SignalableInterrupt, VirtioDevice, Writer, TYPE_GPU,
};
use super::{PciCapabilityType, VirtioPciShmCap};
@ -703,7 +703,6 @@ impl Worker {
(&self.ctrl_evt, Token::CtrlQueue),
(&self.cursor_evt, Token::CursorQueue),
(&*self.state.display().borrow(), Token::Display),
(self.interrupt.get_resample_evt(), Token::InterruptResample),
(&self.kill_evt, Token::Kill),
]) {
Ok(pc) => pc,
@ -712,6 +711,15 @@ impl Worker {
return;
}
};
if let Some(resample_evt) = self.interrupt.get_resample_evt() {
if wait_ctx
.add(resample_evt, Token::InterruptResample)
.is_err()
{
error!("failed creating WaitContext");
return;
}
}
for (index, bridge) in self.resource_bridges.iter().enumerate() {
if let Err(e) = wait_ctx.add(bridge, Token::ResourceBridge { index }) {

View file

@ -16,8 +16,8 @@ use vm_memory::GuestMemory;
use self::event_source::{EvdevEventSource, EventSource, SocketEventSource};
use super::{
copy_config, DescriptorChain, DescriptorError, Interrupt, Queue, Reader, VirtioDevice, Writer,
TYPE_INPUT,
copy_config, DescriptorChain, DescriptorError, Interrupt, Queue, Reader, SignalableInterrupt,
VirtioDevice, Writer, TYPE_INPUT,
};
use linux_input_sys::{virtio_input_event, InputEventDecoder};
use std::collections::BTreeMap;
@ -463,7 +463,6 @@ impl<T: EventSource> Worker<T> {
(&event_queue_evt, Token::EventQAvailable),
(&status_queue_evt, Token::StatusQAvailable),
(&self.event_source, Token::InputEventsAvailable),
(self.interrupt.get_resample_evt(), Token::InterruptResample),
(&kill_evt, Token::Kill),
]) {
Ok(wait_ctx) => wait_ctx,
@ -472,6 +471,15 @@ impl<T: EventSource> Worker<T> {
return;
}
};
if let Some(resample_evt) = self.interrupt.get_resample_evt() {
if wait_ctx
.add(resample_evt, Token::InterruptResample)
.is_err()
{
error!("failed adding resample event to WaitContext.");
return;
}
}
'wait: loop {
let wait_events = match wait_ctx.wait() {

View file

@ -9,6 +9,26 @@ use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use sync::Mutex;
pub trait SignalableInterrupt {
/// Writes to the irqfd to VMM to deliver virtual interrupt to the guest.
fn signal(&self, vector: u16, interrupt_status_mask: u32);
/// Notify the driver that buffers have been placed in the used queue.
fn signal_used_queue(&self, vector: u16) {
self.signal(vector, INTERRUPT_STATUS_USED_RING)
}
/// Notify the driver that the device configuration has changed.
fn signal_config_changed(&self);
/// Get the event to signal resampling is needed if it exists.
fn get_resample_evt(&self) -> Option<&Event>;
/// Reads the status and writes to the interrupt event. Doesn't read the resample event, it
/// assumes the resample has been requested.
fn do_interrupt_resample(&self);
}
pub struct Interrupt {
interrupt_status: Arc<AtomicUsize>,
interrupt_evt: Event,
@ -17,23 +37,7 @@ pub struct Interrupt {
config_msix_vector: u16,
}
impl Interrupt {
pub fn new(
interrupt_status: Arc<AtomicUsize>,
interrupt_evt: Event,
interrupt_resample_evt: Event,
msix_config: Option<Arc<Mutex<MsixConfig>>>,
config_msix_vector: u16,
) -> Interrupt {
Interrupt {
interrupt_status,
interrupt_evt,
interrupt_resample_evt,
msix_config,
config_msix_vector,
}
}
impl SignalableInterrupt for Interrupt {
/// Virtqueue Interrupts From The Device
///
/// If MSI-X is enabled in this device, MSI-X interrupt is preferred.
@ -62,14 +66,36 @@ impl Interrupt {
}
}
/// Notify the driver that buffers have been placed in the used queue.
pub fn signal_used_queue(&self, vector: u16) {
self.signal(vector, INTERRUPT_STATUS_USED_RING)
fn signal_config_changed(&self) {
self.signal(self.config_msix_vector, INTERRUPT_STATUS_CONFIG_CHANGED)
}
/// Notify the driver that the device configuration has changed.
pub fn signal_config_changed(&self) {
self.signal(self.config_msix_vector, INTERRUPT_STATUS_CONFIG_CHANGED)
fn get_resample_evt(&self) -> Option<&Event> {
Some(&self.interrupt_resample_evt)
}
fn do_interrupt_resample(&self) {
if self.interrupt_status.load(Ordering::SeqCst) != 0 {
self.interrupt_evt.write(1).unwrap();
}
}
}
impl Interrupt {
pub fn new(
interrupt_status: Arc<AtomicUsize>,
interrupt_evt: Event,
interrupt_resample_evt: Event,
msix_config: Option<Arc<Mutex<MsixConfig>>>,
config_msix_vector: u16,
) -> Interrupt {
Interrupt {
interrupt_status,
interrupt_evt,
interrupt_resample_evt,
msix_config,
config_msix_vector,
}
}
/// Handle interrupt resampling event, reading the value from the event and doing the resample.
@ -78,20 +104,6 @@ impl Interrupt {
self.do_interrupt_resample();
}
/// Read the status and write to the interrupt event. Don't read the resample event, assume the
/// resample has been requested.
pub fn do_interrupt_resample(&self) {
if self.interrupt_status.load(Ordering::SeqCst) != 0 {
self.interrupt_evt.write(1).unwrap();
}
}
/// Return the reference of interrupt_resample_evt
/// To keep the interface clean, this member is private.
pub fn get_resample_evt(&self) -> &Event {
&self.interrupt_resample_evt
}
/// Get a reference to the msix configuration
pub fn get_msix_config(&self) -> &Option<Arc<Mutex<MsixConfig>>> {
&self.msix_config

View file

@ -23,7 +23,8 @@ use virtio_sys::virtio_net::{
use vm_memory::GuestMemory;
use super::{
copy_config, DescriptorError, Interrupt, Queue, Reader, VirtioDevice, Writer, TYPE_NET,
copy_config, DescriptorError, Interrupt, Queue, Reader, SignalableInterrupt, VirtioDevice,
Writer, TYPE_NET,
};
const QUEUE_SIZE: u16 = 256;
@ -351,9 +352,11 @@ where
.add(ctrl_evt, Token::CtrlQueue)
.map_err(NetError::CreateWaitContext)?;
// Let CtrlQueue's thread handle InterruptResample also.
wait_ctx
.add(self.interrupt.get_resample_evt(), Token::InterruptResample)
.map_err(NetError::CreateWaitContext)?;
if let Some(resample_evt) = self.interrupt.get_resample_evt() {
wait_ctx
.add(resample_evt, Token::InterruptResample)
.map_err(NetError::CreateWaitContext)?;
}
}
let mut tap_polling_enabled = true;

View file

@ -12,7 +12,8 @@ use base::{error, warn, Error as SysError, Event, PollToken, RawDescriptor, Wait
use vm_memory::GuestMemory;
use super::{
copy_config, DescriptorError, Interrupt, Queue, Reader, VirtioDevice, Writer, TYPE_9P,
copy_config, DescriptorError, Interrupt, Queue, Reader, SignalableInterrupt, VirtioDevice,
Writer, TYPE_9P,
};
const QUEUE_SIZE: u16 = 128;
@ -115,12 +116,14 @@ impl Worker {
Kill,
}
let wait_ctx: WaitContext<Token> = WaitContext::build_with(&[
(&queue_evt, Token::QueueReady),
(self.interrupt.get_resample_evt(), Token::InterruptResample),
(&kill_evt, Token::Kill),
])
.map_err(P9Error::CreateWaitContext)?;
let wait_ctx: WaitContext<Token> =
WaitContext::build_with(&[(&queue_evt, Token::QueueReady), (&kill_evt, Token::Kill)])
.map_err(P9Error::CreateWaitContext)?;
if let Some(resample_evt) = self.interrupt.get_resample_evt() {
wait_ctx
.add(resample_evt, Token::InterruptResample)
.map_err(P9Error::CreateWaitContext)?;
}
loop {
let events = wait_ctx.wait().map_err(P9Error::WaitError)?;

View file

@ -14,8 +14,8 @@ use vm_control::{MemSlot, VmMsyncRequest, VmMsyncResponse};
use vm_memory::{GuestAddress, GuestMemory};
use super::{
copy_config, DescriptorChain, DescriptorError, Interrupt, Queue, Reader, VirtioDevice, Writer,
TYPE_PMEM,
copy_config, DescriptorChain, DescriptorError, Interrupt, Queue, Reader, SignalableInterrupt,
VirtioDevice, Writer, TYPE_PMEM,
};
const QUEUE_SIZE: u16 = 256;
@ -173,7 +173,6 @@ impl Worker {
let wait_ctx: WaitContext<Token> = match WaitContext::build_with(&[
(&queue_evt, Token::QueueAvailable),
(self.interrupt.get_resample_evt(), Token::InterruptResample),
(&kill_evt, Token::Kill),
]) {
Ok(pc) => pc,
@ -182,6 +181,15 @@ impl Worker {
return;
}
};
if let Some(resample_evt) = self.interrupt.get_resample_evt() {
if wait_ctx
.add(resample_evt, Token::InterruptResample)
.is_err()
{
error!("failed adding resample event to WaitContext.");
return;
}
}
'wait: loop {
let events = match wait_ctx.wait() {

View file

@ -11,7 +11,7 @@ use cros_async::{AsyncError, EventAsync};
use virtio_sys::virtio_ring::VIRTIO_RING_F_EVENT_IDX;
use vm_memory::{GuestAddress, GuestMemory};
use super::{Interrupt, VIRTIO_MSI_NO_VECTOR};
use super::{SignalableInterrupt, VIRTIO_MSI_NO_VECTOR};
const VIRTQ_DESC_F_NEXT: u16 = 0x1;
const VIRTQ_DESC_F_WRITE: u16 = 0x2;
@ -536,7 +536,11 @@ impl Queue {
/// inject interrupt into guest on this queue
/// return true: interrupt is injected into guest for this queue
/// false: interrupt isn't injected
pub fn trigger_interrupt(&mut self, mem: &GuestMemory, interrupt: &Interrupt) -> bool {
pub fn trigger_interrupt(
&mut self,
mem: &GuestMemory,
interrupt: &dyn SignalableInterrupt,
) -> bool {
if self.available_interrupt_enabled(mem) {
self.last_used = self.next_used;
interrupt.signal_used_queue(self.vector);
@ -554,6 +558,7 @@ impl Queue {
#[cfg(test)]
mod tests {
use super::super::Interrupt;
use super::*;
use base::Event;
use data_model::{DataInit, Le16, Le32, Le64};

View file

@ -10,7 +10,7 @@ use std::thread;
use base::{error, warn, AsRawDescriptor, Event, PollToken, RawDescriptor, WaitContext};
use vm_memory::GuestMemory;
use super::{Interrupt, Queue, VirtioDevice, Writer, TYPE_RNG};
use super::{Interrupt, Queue, SignalableInterrupt, VirtioDevice, Writer, TYPE_RNG};
const QUEUE_SIZE: u16 = 256;
const QUEUE_SIZES: &[u16] = &[QUEUE_SIZE];
@ -75,7 +75,6 @@ impl Worker {
let wait_ctx: WaitContext<Token> = match WaitContext::build_with(&[
(&queue_evt, Token::QueueAvailable),
(self.interrupt.get_resample_evt(), Token::InterruptResample),
(&kill_evt, Token::Kill),
]) {
Ok(pc) => pc,
@ -84,6 +83,15 @@ impl Worker {
return;
}
};
if let Some(resample_evt) = self.interrupt.get_resample_evt() {
if wait_ctx
.add(resample_evt, Token::InterruptResample)
.is_err()
{
error!("failed adding resample event to WaitContext.");
return;
}
}
'wait: loop {
let events = match wait_ctx.wait() {

View file

@ -14,7 +14,8 @@ use base::{error, Event, PollToken, RawDescriptor, WaitContext};
use vm_memory::GuestMemory;
use super::{
DescriptorChain, DescriptorError, Interrupt, Queue, Reader, VirtioDevice, Writer, TYPE_TPM,
DescriptorChain, DescriptorError, Interrupt, Queue, Reader, SignalableInterrupt, VirtioDevice,
Writer, TYPE_TPM,
};
// A single queue of size 2. The guest kernel driver will enqueue a single
@ -112,9 +113,14 @@ impl Worker {
let wait_ctx = match WaitContext::build_with(&[
(&self.queue_evt, Token::QueueAvailable),
(self.interrupt.get_resample_evt(), Token::InterruptResample),
(&self.kill_evt, Token::Kill),
]) {
])
.and_then(|wc| {
if let Some(resample_evt) = self.interrupt.get_resample_evt() {
wc.add(resample_evt, Token::InterruptResample)?;
}
Ok(wc)
}) {
Ok(pc) => pc,
Err(e) => {
error!("vtpm failed creating WaitContext: {}", e);

View file

@ -8,6 +8,7 @@ use futures::pin_mut;
use thiserror::Error as ThisError;
use vm_memory::GuestMemory;
use crate::virtio::interrupt::SignalableInterrupt;
use crate::virtio::{Interrupt, Queue};
#[derive(ThisError, Debug)]
@ -49,6 +50,7 @@ impl Worker {
pub fn run(&mut self, ex: &Executor, interrupt: Interrupt) -> Result<(), String> {
let resample_evt = interrupt
.get_resample_evt()
.expect("resample event required")
.try_clone()
.expect("failed to clone resample event");
let async_resample_evt =

View file

@ -9,7 +9,7 @@ use vhost::Vhost;
use super::control_socket::{VhostDevRequest, VhostDevResponse};
use super::{Error, Result};
use crate::virtio::{Interrupt, Queue};
use crate::virtio::{Interrupt, Queue, SignalableInterrupt};
use libc::EIO;
/// Worker that takes care of running the vhost device.
@ -105,11 +105,9 @@ impl<T: Vhost> Worker<T> {
ControlNotify,
}
let wait_ctx: WaitContext<Token> = WaitContext::build_with(&[
(self.interrupt.get_resample_evt(), Token::InterruptResample),
(&self.kill_evt, Token::Kill),
])
.map_err(Error::CreateWaitContext)?;
let wait_ctx: WaitContext<Token> =
WaitContext::build_with(&[(&self.kill_evt, Token::Kill)])
.map_err(Error::CreateWaitContext)?;
for (index, vhost_int) in self.vhost_interrupt.iter().enumerate() {
wait_ctx
@ -121,6 +119,11 @@ impl<T: Vhost> Worker<T> {
.add(socket, Token::ControlNotify)
.map_err(Error::CreateWaitContext)?;
}
if let Some(resample_evt) = self.interrupt.get_resample_evt() {
wait_ctx
.add(resample_evt, Token::InterruptResample)
.map_err(Error::CreateWaitContext)?;
}
'wait: loop {
let events = wait_ctx.wait().map_err(Error::WaitError)?;

View file

@ -18,7 +18,7 @@ use crate::virtio::video::device::{
use crate::virtio::video::event::{self, EvtType, VideoEvt};
use crate::virtio::video::response::{self, Response};
use crate::virtio::video::{Error, Result};
use crate::virtio::{Interrupt, Reader, Writer};
use crate::virtio::{Interrupt, Reader, SignalableInterrupt, Writer};
pub struct Worker {
pub interrupt: Interrupt,
@ -275,8 +275,13 @@ impl Worker {
(&self.cmd_evt, Token::CmdQueue),
(&self.event_evt, Token::EventQueue),
(&self.kill_evt, Token::Kill),
(self.interrupt.get_resample_evt(), Token::InterruptResample),
])
.and_then(|wc| {
if let Some(resample_evt) = self.interrupt.get_resample_evt() {
wc.add(resample_evt, Token::InterruptResample)?;
}
Ok(wc)
})
.map_err(Error::WaitContextCreationFailed)?;
// Stores descriptors in which responses for asynchronous commands will be written.

View file

@ -67,7 +67,9 @@ use vm_control::GpuMemoryDesc;
use super::resource_bridge::{
get_resource_info, BufferInfo, ResourceBridgeError, ResourceInfo, ResourceRequest,
};
use super::{DescriptorChain, Interrupt, Queue, Reader, VirtioDevice, Writer, TYPE_WL};
use super::{
DescriptorChain, Interrupt, Queue, Reader, SignalableInterrupt, VirtioDevice, Writer, TYPE_WL,
};
use vm_control::{MemSlot, VmMemoryRequest, VmMemoryResponse};
const VIRTWL_SEND_MAX_ALLOCS: usize = 28;
@ -1514,7 +1516,6 @@ impl Worker {
(&out_queue_evt, Token::OutQueue),
(&kill_evt, Token::Kill),
(&self.state.wait_ctx, Token::State),
(self.interrupt.get_resample_evt(), Token::InterruptResample),
]) {
Ok(pc) => pc,
Err(e) => {
@ -1522,6 +1523,15 @@ impl Worker {
return;
}
};
if let Some(resample_evt) = self.interrupt.get_resample_evt() {
if wait_ctx
.add(resample_evt, Token::InterruptResample)
.is_err()
{
error!("failed adding resample event to WaitContext.");
return;
}
}
'wait: loop {
let mut signal_used_in = false;