Skip to content

Commit b188377

Browse files
committed
refactor(board): signal VM boot via a CondVar
Use the existing global CondVar to singal VM state transition, remove dedicated per-CPU mpsc channels. Signed-off-by: Changyuan Lyu <changyuanl@google.com>
1 parent dcd524f commit b188377

File tree

2 files changed

+48
-41
lines changed

2 files changed

+48
-41
lines changed

alioth/src/board/board.rs

Lines changed: 45 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ mod x86_64;
2323
use std::collections::HashMap;
2424
use std::ffi::CStr;
2525
use std::sync::Arc;
26-
use std::sync::mpsc::{Receiver, Sender};
26+
use std::sync::mpsc::Sender;
2727
use std::thread::JoinHandle;
2828

2929
use libc::{MAP_PRIVATE, MAP_SHARED};
@@ -97,6 +97,8 @@ pub enum Error {
9797
NotifyVmm,
9898
#[snafu(display("Another VCPU thread has signaled failure"))]
9999
PeerFailure,
100+
#[snafu(display("Unexpected state: {state:?}, want {want:?}"))]
101+
UnexpectedState { state: BoardState, want: BoardState },
100102
}
101103

102104
type Result<T, E = Error> = std::result::Result<T, E>;
@@ -157,7 +159,7 @@ impl CpuConfig {
157159
}
158160

159161
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
160-
enum BoardState {
162+
pub enum BoardState {
161163
Created,
162164
Running,
163165
Shutdown,
@@ -189,8 +191,8 @@ impl BoardConfig {
189191
}
190192
}
191193

192-
type VcpuGuard<'a> = RwLockReadGuard<'a, Vec<(JoinHandle<Result<()>>, Sender<()>)>>;
193-
type VcpuHandle = (JoinHandle<Result<()>>, Sender<()>);
194+
type VcpuGuard<'a> = RwLockReadGuard<'a, Vec<VcpuHandle>>;
195+
type VcpuHandle = JoinHandle<Result<()>>;
194196

195197
pub struct Board<V>
196198
where
@@ -249,12 +251,17 @@ where
249251
}
250252

251253
pub fn boot(&self) -> Result<()> {
252-
let vcpus = self.vcpus.read();
253254
let mut mp_sync = self.mp_sync.lock();
254-
mp_sync.state = BoardState::Running;
255-
for (_, boot_tx) in vcpus.iter() {
256-
boot_tx.send(()).unwrap();
255+
if mp_sync.state == BoardState::Created {
256+
mp_sync.state = BoardState::Running;
257+
} else {
258+
return error::UnexpectedState {
259+
state: mp_sync.state,
260+
want: BoardState::Created,
261+
}
262+
.fail();
257263
}
264+
self.cond_var.notify_all();
258265
Ok(())
259266
}
260267

@@ -371,17 +378,28 @@ where
371378
Ok(())
372379
}
373380

374-
fn run_vcpu_inner(
375-
&self,
376-
index: u16,
377-
vcpu: &mut V::Vcpu,
378-
boot_rx: &Receiver<()>,
379-
) -> Result<(), Error> {
380-
self.init_vcpu(index, vcpu)?;
381-
boot_rx.recv().unwrap();
382-
if self.mp_sync.lock().state != BoardState::Running {
381+
fn notify_vmm(&self, index: u16, event_tx: &Sender<u16>) -> Result<()> {
382+
if event_tx.send(index).is_err() {
383+
error::NotifyVmm.fail()
384+
} else {
385+
Ok(())
386+
}
387+
}
388+
389+
fn run_vcpu_inner(&self, index: u16, event_tx: &Sender<u16>) -> Result<(), Error> {
390+
let mut vcpu = self.create_vcpu(index)?;
391+
self.notify_vmm(index, event_tx)?;
392+
self.init_vcpu(index, &mut vcpu)?;
393+
394+
let mut mp_sync = self.mp_sync.lock();
395+
while mp_sync.state == BoardState::Created {
396+
self.cond_var.wait(&mut mp_sync);
397+
}
398+
if mp_sync.state != BoardState::Running {
383399
return Ok(());
384400
}
401+
drop(mp_sync);
402+
385403
loop {
386404
let vcpus = self.vcpus.read();
387405
self.coco_init(index)?;
@@ -396,15 +414,15 @@ where
396414
}
397415
self.add_pci_devs()?;
398416
let init_state = self.load_payload()?;
399-
self.init_boot_vcpu(vcpu, &init_state)?;
417+
self.init_boot_vcpu(&mut vcpu, &init_state)?;
400418
self.create_firmware_data(&init_state)?;
401419
}
402-
self.init_ap(index, vcpu, &vcpus)?;
420+
self.init_ap(index, &mut vcpu, &vcpus)?;
403421
self.coco_finalize(index, &vcpus)?;
404422
self.sync_vcpus(&vcpus)?;
405423
drop(vcpus);
406424

407-
let maybe_reboot = self.vcpu_loop(vcpu, index);
425+
let maybe_reboot = self.vcpu_loop(&mut vcpu, index);
408426

409427
let vcpus = self.vcpus.read();
410428
let mut mp_sync = self.mp_sync.lock();
@@ -414,7 +432,7 @@ where
414432
} else {
415433
BoardState::Shutdown
416434
};
417-
for (another, (handle, _)) in vcpus.iter().enumerate() {
435+
for (another, handle) in vcpus.iter().enumerate() {
418436
if index == another as u16 {
419437
continue;
420438
}
@@ -433,7 +451,7 @@ where
433451
self.pci_bus.segment.reset().context(error::ResetPci)?;
434452
self.memory.reset()?;
435453
}
436-
self.reset_vcpu(index, vcpu)?;
454+
self.reset_vcpu(index, &mut vcpu)?;
437455

438456
if let Err(e) = maybe_reboot {
439457
break Err(e);
@@ -447,29 +465,19 @@ where
447465
}
448466
}
449467

450-
fn create_vcpu(&self, index: u16, event_tx: &Sender<u16>) -> Result<V::Vcpu> {
468+
fn create_vcpu(&self, index: u16) -> Result<V::Vcpu> {
451469
let identity = self.encode_cpu_identity(index);
452470
let vcpu = self
453471
.vm
454472
.create_vcpu(index, identity)
455473
.context(error::CreateVcpu { index })?;
456-
if event_tx.send(index).is_err() {
457-
error::NotifyVmm.fail()
458-
} else {
459-
Ok(vcpu)
460-
}
474+
Ok(vcpu)
461475
}
462476

463-
pub fn run_vcpu(
464-
&self,
465-
index: u16,
466-
event_tx: Sender<u16>,
467-
boot_rx: Receiver<()>,
468-
) -> Result<(), Error> {
469-
let mut vcpu = self.create_vcpu(index, &event_tx)?;
477+
pub fn run_vcpu(&self, index: u16, event_tx: Sender<u16>) -> Result<(), Error> {
478+
let ret = self.run_vcpu_inner(index, &event_tx);
470479

471-
let ret = self.run_vcpu_inner(index, &mut vcpu, &boot_rx);
472-
event_tx.send(index).unwrap();
480+
let _ = self.notify_vmm(index, &event_tx);
473481

474482
if matches!(ret, Ok(_) | Err(Error::PeerFailure { .. })) {
475483
return Ok(());

alioth/src/vm.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,18 +140,17 @@ where
140140

141141
let mut vcpus = board.vcpus.write();
142142
for index in 0..board.config.cpu.count {
143-
let (boot_tx, boot_rx) = mpsc::channel();
144143
let event_tx = event_tx.clone();
145144
let board = board.clone();
146145
let handle = thread::Builder::new()
147146
.name(format!("vcpu_{index}"))
148-
.spawn(move || board.run_vcpu(index, event_tx, boot_rx))
147+
.spawn(move || board.run_vcpu(index, event_tx))
149148
.context(error::VcpuThread { index })?;
150149
if event_rx.recv_timeout(Duration::from_secs(2)).is_err() {
151150
let err = std::io::ErrorKind::TimedOut.into();
152151
Err(err).context(error::VcpuThread { index })?;
153152
}
154-
vcpus.push((handle, boot_tx));
153+
vcpus.push(handle);
155154
}
156155
drop(vcpus);
157156

@@ -294,7 +293,7 @@ where
294293
drop(vcpus);
295294
let mut vcpus = self.board.vcpus.write();
296295
let mut ret = Ok(());
297-
for (index, (handle, _)) in vcpus.drain(..).enumerate() {
296+
for (index, handle) in vcpus.drain(..).enumerate() {
298297
let Ok(r) = handle.join() else {
299298
log::error!("Cannot join VCPU-{index}");
300299
continue;

0 commit comments

Comments
 (0)