Skip to content

Commit dfd1888

Browse files
alexandruagacatangiu
authored andcommitted
vmm: run_control changes
Renamed run_control to run_event_loop, and changed it to return a value represented by variants of the new enum EvenLoopExitReason. The method only actually exits when VmmActionRequest event is triggered. The run_control_action method is now invoked in the main "fc_vmm" thread spawned by start_vmm_thread, and outside the Vmm struct. Essentially, what happens is the event loop runs as before, until the next VmmActionRequest is triggered. At that point the function returns, then some other logic can handle the event and (usually) restart the event loop. This is one of the first steps towards a more modular VMM, where the logic that controls the Vmm struct resides in an outside implementation that interacts with Vmm strictly through its interface. Signed-off-by: Alexandru Agache <[email protected]>
1 parent 58edf03 commit dfd1888

File tree

1 file changed

+47
-15
lines changed

1 file changed

+47
-15
lines changed

vmm/src/lib.rs

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,16 @@ pub type OutcomeReceiver = oneshot::Receiver<VmmRequestOutcome>;
457457

458458
type Result<T> = std::result::Result<T, Error>;
459459

460+
/// Describes all possible reasons which may cause the event loop to return to the caller in
461+
/// the absence of errors.
462+
pub enum EventLoopExitReason {
463+
/// A break statement interrupted the event loop during normal execution. This is the
464+
/// default exit reason.
465+
Break,
466+
/// The control action file descriptor has data available for reading.
467+
ControlAction,
468+
}
469+
460470
/// Holds a micro-second resolution timestamp with both the real time and cpu time.
461471
#[derive(Clone, Default)]
462472
pub struct TimestampUs {
@@ -1561,7 +1571,7 @@ impl Vmm {
15611571
Ok(())
15621572
}
15631573

1564-
fn run_control(&mut self) -> Result<()> {
1574+
fn run_event_loop(&mut self) -> Result<EventLoopExitReason> {
15651575
// TODO: try handling of errors/failures without breaking this main loop.
15661576
loop {
15671577
let event = self.epoll_context.get_event()?;
@@ -1620,10 +1630,7 @@ impl Vmm {
16201630
}
16211631
}
16221632
Some(EpollDispatch::VmmActionRequest) => {
1623-
self.api_event_fd.read().map_err(Error::EventFd)?;
1624-
self.run_vmm_action().unwrap_or_else(|_| {
1625-
warn!("got spurious notification from api thread");
1626-
});
1633+
return Ok(EventLoopExitReason::ControlAction);
16271634
}
16281635
Some(EpollDispatch::WriteMetrics) => {
16291636
self.write_metrics_event_fd.read();
@@ -1638,6 +1645,8 @@ impl Vmm {
16381645
}
16391646
}
16401647
}
1648+
// Currently, we never get to return with Ok(EventLoopExitReason::Break) because
1649+
// we just invoke stop() whenever that would happen.
16411650
}
16421651

16431652
// Count the number of pages dirtied since the last call to this function.
@@ -2177,16 +2186,39 @@ pub fn start_vmm_thread(
21772186
}
21782187
}
21792188

2180-
match vmm.run_control() {
2181-
Ok(()) => {
2182-
info!("Gracefully terminated VMM control loop");
2183-
vmm.stop(i32::from(FC_EXIT_CODE_OK))
2184-
}
2185-
Err(e) => {
2186-
error!("Abruptly exited VMM control loop: {:?}", e);
2187-
vmm.stop(i32::from(FC_EXIT_CODE_GENERIC_ERROR));
2188-
}
2189-
}
2189+
// The loop continues to run as long as there is no error. Whenever run_event_loop
2190+
// returns due to a ControlAction, we handle it and invoke `continue`. Clippy thinks
2191+
// this never loops and complains about it, but Clippy is wrong.
2192+
#[allow(clippy::never_loop)]
2193+
let exit_code = loop {
2194+
// `break <expression>` causes the outer loop to break and return the result
2195+
// of evaluating <expression>, which in this case is the exit code.
2196+
break match vmm.run_event_loop() {
2197+
Ok(exit_reason) => match exit_reason {
2198+
EventLoopExitReason::Break => {
2199+
info!("Gracefully terminated VMM control loop");
2200+
FC_EXIT_CODE_OK
2201+
}
2202+
EventLoopExitReason::ControlAction => {
2203+
if let Err(e) = vmm.api_event_fd.read() {
2204+
error!("Error reading VMM API event_fd {:?}", e);
2205+
FC_EXIT_CODE_GENERIC_ERROR
2206+
} else {
2207+
vmm.run_vmm_action().unwrap_or_else(|_| {
2208+
warn!("Got a spurious notification from api thread");
2209+
});
2210+
continue;
2211+
}
2212+
}
2213+
},
2214+
Err(e) => {
2215+
error!("Abruptly exited VMM control loop: {:?}", e);
2216+
FC_EXIT_CODE_GENERIC_ERROR
2217+
}
2218+
};
2219+
};
2220+
2221+
vmm.stop(i32::from(exit_code));
21902222
})
21912223
.expect("VMM thread spawn failed.")
21922224
}

0 commit comments

Comments
 (0)