diff options
author | Frederick Mayle <fmayle@google.com> | 2023-11-09 23:20:35 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-11-09 23:20:35 +0000 |
commit | e7b3c7b32c68197ca252bb90e262f11b77222d1b (patch) | |
tree | 16884898ac7178d3574190152c1dcfde5ed9e432 | |
parent | dd8dd381e0766595f8b1ccf554da0ba358a62cbe (diff) | |
parent | ec982164912a30d730c8fcaef14a99f3ee869b78 (diff) | |
download | crosvm-e7b3c7b32c68197ca252bb90e262f11b77222d1b.tar.gz |
Merge changes I16e3fdd5,I1baf006b into main am: fd3a5e7fe5 am: ec98216491
Original change: https://android-review.googlesource.com/c/platform/external/crosvm/+/2824115
Change-Id: Icaff3758e2ff9a14cda0b230b346cd95afcf729d
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r-- | devices/src/virtio/console.rs | 35 | ||||
-rw-r--r-- | devices/src/virtio/console/sys/linux.rs | 18 | ||||
-rw-r--r-- | devices/src/virtio/console/sys/windows.rs | 11 |
3 files changed, 31 insertions, 33 deletions
diff --git a/devices/src/virtio/console.rs b/devices/src/virtio/console.rs index 88646da24..6523783ee 100644 --- a/devices/src/virtio/console.rs +++ b/devices/src/virtio/console.rs @@ -43,6 +43,7 @@ use zerocopy::AsBytes; use zerocopy::FromBytes; use zerocopy::FromZeroes; +use crate::serial::sys::InStreamType; use crate::virtio::base_features; use crate::virtio::copy_config; use crate::virtio::DeviceType; @@ -256,20 +257,15 @@ impl Worker { } } -enum ConsoleInput { - FromRead(crate::serial::sys::InStreamType), - FromThread(Arc<Mutex<VecDeque<u8>>>), -} - /// Virtio console device. pub struct Console { base_features: u64, in_avail_evt: Option<Event>, worker_thread: Option<WorkerThread<Worker>>, - input: Option<ConsoleInput>, + input: Option<InStreamType>, output: Option<Box<dyn io::Write + Send>>, keep_descriptors: Vec<Descriptor>, - input_thread: Option<WorkerThread<()>>, + input_thread: Option<WorkerThread<InStreamType>>, // input_buffer is not continuously updated. It holds the state of the buffer when a snapshot // happens, or when a restore is performed. On a fresh startup, it will be empty. On a restore, // it will contain whatever data was remaining in the buffer in the snapshot. @@ -285,7 +281,7 @@ struct ConsoleSnapshot { impl Console { fn new( protection_type: ProtectionType, - input: Option<ConsoleInput>, + input: Option<InStreamType>, output: Option<Box<dyn io::Write + Send>>, keep_rds: Vec<RawDescriptor>, ) -> Console { @@ -360,16 +356,15 @@ impl VirtioDevice for Console { // descriptor). Moving the blocking read call to a separate thread and sending data back to // the main worker thread with an event for notification bridges this gap. let input = match self.input.take() { - Some(ConsoleInput::FromRead(read)) => { + Some(read) => { let (buffer, thread) = sys::spawn_input_thread( read, self.in_avail_evt.as_ref().unwrap(), - self.input_buffer.clone(), + std::mem::take(&mut self.input_buffer), ); self.input_thread = Some(thread); Some(buffer) } - Some(ConsoleInput::FromThread(buffer)) => Some(buffer), None => None, }; let output = self.output.take().unwrap_or_else(|| Box::new(io::sink())); @@ -395,9 +390,14 @@ impl VirtioDevice for Console { } fn reset(&mut self) -> bool { + self.input = self.input_thread.take().map(|t| t.stop()); if let Some(worker_thread) = self.worker_thread.take() { let worker = worker_thread.stop(); - self.input = worker.input.map(ConsoleInput::FromThread); + // NOTE: Even though we are reseting the device, it still makes sense to preserve the + // pending input bytes that the host sent but the guest hasn't accepted yet. + self.input_buffer = worker + .input + .map_or(VecDeque::new(), |arc_mutex| arc_mutex.lock().clone()); self.output = Some(worker.output); return true; } @@ -405,14 +405,13 @@ impl VirtioDevice for Console { } fn virtio_sleep(&mut self) -> anyhow::Result<Option<BTreeMap<usize, Queue>>> { + self.input = self.input_thread.take().map(|t| t.stop()); if let Some(worker_thread) = self.worker_thread.take() { - if let Some(input_thread) = self.input_thread.take() { - input_thread.stop(); - } let worker = worker_thread.stop(); - if let Some(in_buf_ref) = worker.input.as_ref() { - self.input_buffer = in_buf_ref.lock().clone(); - } + self.input_buffer = worker + .input + .map_or(VecDeque::new(), |arc_mutex| arc_mutex.lock().clone()); + self.output = Some(worker.output); let receive_queue = match Arc::try_unwrap(worker.receive_queue) { Ok(mutex) => mutex.into_inner(), Err(_) => return Err(anyhow!("failed to retrieve receive queue to sleep device.")), diff --git a/devices/src/virtio/console/sys/linux.rs b/devices/src/virtio/console/sys/linux.rs index bbd9ffc39..f78dc4fab 100644 --- a/devices/src/virtio/console/sys/linux.rs +++ b/devices/src/virtio/console/sys/linux.rs @@ -17,9 +17,9 @@ use base::WaitContext; use base::WorkerThread; use sync::Mutex; +use crate::serial::sys::InStreamType; use crate::serial_device::SerialInput; use crate::virtio::console::Console; -use crate::virtio::console::ConsoleInput; use crate::virtio::ProtectionType; use crate::SerialDevice; @@ -34,12 +34,7 @@ impl SerialDevice for Console { _out_timestamp: bool, keep_rds: Vec<RawDescriptor>, ) -> Console { - Console::new( - protection_type, - input.map(ConsoleInput::FromRead), - out, - keep_rds, - ) + Console::new(protection_type, input, out, keep_rds) } } @@ -58,10 +53,10 @@ fn is_a_fatal_input_error(e: &io::Error) -> bool { /// * `rx` - Data source that the reader thread will wait on to send data back to the buffer /// * `in_avail_evt` - Event triggered by the thread when new input is available on the buffer pub(in crate::virtio::console) fn spawn_input_thread( - mut rx: crate::serial::sys::InStreamType, + mut rx: InStreamType, in_avail_evt: &Event, input_buffer: VecDeque<u8>, -) -> (Arc<Mutex<VecDeque<u8>>>, WorkerThread<()>) { +) -> (Arc<Mutex<VecDeque<u8>>>, WorkerThread<InStreamType>) { let buffer = Arc::new(Mutex::new(input_buffer)); let buffer_cloned = buffer.clone(); @@ -88,7 +83,7 @@ pub(in crate::virtio::console) fn spawn_input_thread( Ok(ctx) => ctx, Err(e) => { error!("failed creating WaitContext {:?}", e); - return; + return rx; } }; @@ -99,7 +94,7 @@ pub(in crate::virtio::console) fn spawn_input_thread( Ok(events) => events, Err(e) => { error!("Failed to wait for events. {}", e); - return; + return rx; } }; for event in events.iter() { @@ -149,6 +144,7 @@ pub(in crate::virtio::console) fn spawn_input_thread( } } } + rx }); (buffer_cloned, res) } diff --git a/devices/src/virtio/console/sys/windows.rs b/devices/src/virtio/console/sys/windows.rs index c238dfd77..58e7bd018 100644 --- a/devices/src/virtio/console/sys/windows.rs +++ b/devices/src/virtio/console/sys/windows.rs @@ -18,7 +18,6 @@ use sync::Mutex; use crate::serial_device::SerialInput; use crate::virtio::console::Console; -use crate::virtio::console::ConsoleInput; use crate::virtio::ProtectionType; use crate::SerialDevice; @@ -46,7 +45,7 @@ impl SerialDevice for Console { ) -> Console { Console::new( protection_type, - Some(ConsoleInput::FromRead(Box::new(pipe_in))), + Some(Box::new(pipe_in)), Some(Box::new(pipe_out)), keep_rds, ) @@ -90,7 +89,10 @@ pub(in crate::virtio::console) fn spawn_input_thread( mut rx: Box<named_pipes::PipeConnection>, in_avail_evt: &Event, input_buffer: VecDeque<u8>, -) -> (Arc<Mutex<VecDeque<u8>>>, WorkerThread<()>) { +) -> ( + Arc<Mutex<VecDeque<u8>>>, + WorkerThread<Box<named_pipes::PipeConnection>>, +) { let buffer = Arc::new(Mutex::new(input_buffer)); let buffer_cloned = buffer.clone(); @@ -107,7 +109,7 @@ pub(in crate::virtio::console) fn spawn_input_thread( } match rx.wait_for_client_connection_overlapped_blocking(&kill_evt) { - Err(e) if e.kind() == io::ErrorKind::Interrupted => return, + Err(e) if e.kind() == io::ErrorKind::Interrupted => return rx, Err(e) => panic!("failed to wait for client: {}", e), Ok(()) => (), } @@ -148,6 +150,7 @@ pub(in crate::virtio::console) fn spawn_input_thread( // Depending on the platform, a short sleep is needed here (ie. Windows). read_delay_if_needed(); } + rx }); (buffer_cloned, res) } |