devices/virtio/console/
port.rs1use std::collections::VecDeque;
8use std::sync::Arc;
9
10use anyhow::Context;
11use base::AsRawDescriptor;
12use base::Descriptor;
13use base::Event;
14use base::RawDescriptor;
15use base::WorkerThread;
16use serde::Deserialize;
17use serde::Serialize;
18use sync::Mutex;
19
20use crate::serial::sys::InStreamType;
21use crate::virtio::console::sys::spawn_input_thread;
22
23#[derive(Clone, Debug)]
25pub struct ConsolePortInfo {
26 pub console: bool,
27 pub name: Option<String>,
28}
29
30impl ConsolePortInfo {
31 pub fn name(&self) -> Option<&str> {
32 self.name.as_deref()
33 }
34}
35
36pub struct ConsolePort {
37 pub(crate) input: Option<InStreamType>,
38 pub(crate) output: Option<Box<dyn std::io::Write + Send>>,
39
40 info: Option<ConsolePortInfo>,
41
42 input_buffer: Arc<Mutex<VecDeque<u8>>>,
44
45 in_avail_evt: Event,
48
49 input_thread: Option<WorkerThread<InStreamType>>,
50
51 keep_descriptors: Vec<Descriptor>,
52}
53
54#[derive(Serialize, Deserialize)]
55pub struct ConsolePortSnapshot {
56 pub(super) input_buffer: Vec<u8>,
57}
58
59impl ConsolePort {
60 pub fn new(
61 input: Option<InStreamType>,
62 output: Option<Box<dyn std::io::Write + Send>>,
63 info: Option<ConsolePortInfo>,
64 mut keep_rds: Vec<RawDescriptor>,
65 ) -> Self {
66 let input_buffer = Arc::new(Mutex::new(VecDeque::new()));
67 let in_avail_evt = Event::new().expect("Event::new() failed");
68 keep_rds.push(in_avail_evt.as_raw_descriptor());
69 ConsolePort {
70 input,
71 output,
72 info,
73 input_buffer,
74 in_avail_evt,
75 input_thread: None,
76 keep_descriptors: keep_rds.iter().map(|rd| Descriptor(*rd)).collect(),
77 }
78 }
79
80 pub fn clone_in_avail_evt(&self) -> anyhow::Result<Event> {
81 self.in_avail_evt
82 .try_clone()
83 .context("clone_in_avail_evt failed")
84 }
85
86 pub fn clone_input_buffer(&self) -> Arc<Mutex<VecDeque<u8>>> {
87 self.input_buffer.clone()
88 }
89
90 pub fn take_output(&mut self) -> Option<Box<dyn std::io::Write + Send>> {
91 self.output.take()
92 }
93
94 pub fn restore_output(&mut self, output: Box<dyn std::io::Write + Send>) {
95 self.output = Some(output);
96 }
97
98 pub fn port_info(&self) -> Option<&ConsolePortInfo> {
99 self.info.as_ref()
100 }
101
102 pub fn start_input_thread(&mut self) {
103 if let Some(input) = self.input.take() {
110 assert!(self.input_thread.is_none());
111
112 let thread_in_avail_evt = self
113 .clone_in_avail_evt()
114 .expect("failed creating input available Event pair");
115
116 let thread = spawn_input_thread(input, thread_in_avail_evt, self.input_buffer.clone());
117 self.input_thread = Some(thread);
118 }
119 }
120
121 pub fn stop_input_thread(&mut self) {
122 if let Some(input_thread) = self.input_thread.take() {
123 let input = input_thread.stop();
124 self.input = Some(input);
125 }
126 }
127
128 pub fn snapshot(&mut self) -> ConsolePortSnapshot {
129 self.stop_input_thread();
131 let input_buffer = self.input_buffer.lock().iter().copied().collect();
132 self.start_input_thread();
133 ConsolePortSnapshot { input_buffer }
134 }
135
136 pub fn restore(&mut self, snap: &ConsolePortSnapshot) {
137 self.stop_input_thread();
138
139 let mut input_buffer = self.input_buffer.lock();
141 input_buffer.clear();
142 input_buffer.extend(snap.input_buffer.iter());
143 drop(input_buffer);
144
145 self.start_input_thread();
146 }
147
148 pub fn keep_rds(&self) -> Vec<RawDescriptor> {
149 self.keep_descriptors
150 .iter()
151 .map(|descr| descr.as_raw_descriptor())
152 .collect()
153 }
154}