Skip to content

Commit

Permalink
virtio-serial: pop all the received data
Browse files Browse the repository at this point in the history
Pop all the received data from port queue and virtio queue and try to
fill the caller's buffer as much as possible after receiving from virtio
serial device.

Signed-off-by: Jiaqi Gao <[email protected]>
  • Loading branch information
gaojiaqi7 authored and liuw1 committed Nov 14, 2024
1 parent 1e813ea commit cc7099b
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 9 deletions.
12 changes: 12 additions & 0 deletions src/devices/virtio_serial/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,18 @@ impl VirtioSerial {
fn port_queue_pop(port_id: u32) -> Option<Vec<u8>> {
RECEIVE_QUEUES.lock().get_mut(&port_id)?.pop_front()
}

fn can_recv(&self, port_id: u32) -> bool {
RECEIVE_QUEUES
.lock()
.get(&port_id)
.is_some_and(|q| !q.is_empty())
|| self
.queues
.index(Self::port_queue_index(port_id) as usize)
.borrow_mut()
.can_pop()
}
}

/// Align `size` up to a page.
Expand Down
29 changes: 20 additions & 9 deletions src/devices/virtio_serial/src/port.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,26 +64,37 @@ impl VirtioSerialPort {

pub fn recv(&mut self, data: &mut [u8]) -> Result<usize> {
if self.cache.is_empty() {
let recv_bytes = SERIAL_DEVICE
.lock()
.get_mut()
.ok_or(VirtioSerialError::InvalidParameter)?
.dequeue(self.port_id, DEFAULT_TIMEOUT)?;
self.cache.push_back(recv_bytes);
loop {
let recv_bytes = SERIAL_DEVICE
.lock()
.get_mut()
.ok_or(VirtioSerialError::InvalidParameter)?
.dequeue(self.port_id, DEFAULT_TIMEOUT)?;
self.cache.push_back(recv_bytes);

if !SERIAL_DEVICE
.lock()
.get_mut()
.ok_or(VirtioSerialError::InvalidParameter)?
.can_recv(self.port_id)
{
break;
}
}
}

let mut recvd = 0;
if !self.cache.is_empty() {
while !self.cache.is_empty() {
let front = self.cache.front_mut().unwrap();
let expect = data.len() - recvd;
if front.len() <= expect {
data[..front.len()].copy_from_slice(front);
data[recvd..recvd + front.len()].copy_from_slice(front);
recvd += front.len();
self.cache.pop_front();
} else {
data[recvd..].copy_from_slice(&front[..expect]);
front.drain(..expect);
recvd = expect;
recvd += expect;
}
}

Expand Down

0 comments on commit cc7099b

Please sign in to comment.