Skip to content

Commit 776b803

Browse files
AlexandruCihodaruandreeaflorescu
authored andcommitted
[serial]: Add a new method to SerialEvents trait
- Add in_buffer_empty method to SerialEvents trait. This method has the role to inform the vmm that there are no pending bytes in the in_buffer container and it should do something about it. Signed-off-by: AlexandruCihodaru <[email protected]> Suggested-by: Andreea Florescu <[email protected]>
1 parent eb78875 commit 776b803

File tree

1 file changed

+59
-8
lines changed

1 file changed

+59
-8
lines changed

src/serial.rs

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ pub trait SerialEvents {
117117
fn out_byte(&self);
118118
/// An error occurred while writing a byte to serial output resulting in a lost byte.
119119
fn tx_lost_byte(&self);
120+
/// This event can be used by the consumer to re-enable events coming from
121+
/// the serial input.
122+
fn in_buffer_empty(&self);
120123
}
121124

122125
/// Provides a no-op implementation of `SerialEvents` which can be used in situations that
@@ -128,6 +131,7 @@ impl SerialEvents for NoEvents {
128131
fn buffer_read(&self) {}
129132
fn out_byte(&self) {}
130133
fn tx_lost_byte(&self) {}
134+
fn in_buffer_empty(&self) {}
131135
}
132136

133137
impl<EV: SerialEvents> SerialEvents for Arc<EV> {
@@ -142,6 +146,10 @@ impl<EV: SerialEvents> SerialEvents for Arc<EV> {
142146
fn tx_lost_byte(&self) {
143147
self.as_ref().tx_lost_byte();
144148
}
149+
150+
fn in_buffer_empty(&self) {
151+
self.as_ref().in_buffer_empty();
152+
}
145153
}
146154

147155
/// The serial console emulation is done by emulating a serial COM port.
@@ -450,12 +458,13 @@ impl<T: Trigger, EV: SerialEvents, W: Write> Serial<T, EV, W> {
450458
// interrupt identification register and RDA bit when no
451459
// more data is available).
452460
self.del_interrupt(IIR_RDA_BIT);
453-
if self.in_buffer.len() <= 1 {
461+
let byte = self.in_buffer.pop_front().unwrap_or_default();
462+
if self.in_buffer.is_empty() {
454463
self.clear_lsr_rda_bit();
464+
self.events.in_buffer_empty();
455465
}
456-
457466
self.events.buffer_read();
458-
self.in_buffer.pop_front().unwrap_or_default()
467+
byte
459468
}
460469
IER_OFFSET => self.interrupt_enable,
461470
IIR_OFFSET => {
@@ -566,14 +575,25 @@ mod tests {
566575
}
567576
}
568577

569-
#[derive(Default)]
570-
struct ExampleSerialMetrics {
578+
struct ExampleSerialEvents {
571579
read_count: AtomicU64,
572580
out_byte_count: AtomicU64,
573581
tx_lost_byte_count: AtomicU64,
582+
buffer_ready_event: EventFd,
583+
}
584+
585+
impl ExampleSerialEvents {
586+
fn new() -> Self {
587+
ExampleSerialEvents {
588+
read_count: AtomicU64::new(0),
589+
out_byte_count: AtomicU64::new(0),
590+
tx_lost_byte_count: AtomicU64::new(0),
591+
buffer_ready_event: EventFd::new(libc::EFD_NONBLOCK).unwrap(),
592+
}
593+
}
574594
}
575595

576-
impl SerialEvents for ExampleSerialMetrics {
596+
impl SerialEvents for ExampleSerialEvents {
577597
fn buffer_read(&self) {
578598
self.read_count.inc();
579599
// We can also log a message here, or as part of any of the other methods.
@@ -586,6 +606,10 @@ mod tests {
586606
fn tx_lost_byte(&self) {
587607
self.tx_lost_byte_count.inc();
588608
}
609+
610+
fn in_buffer_empty(&self) {
611+
self.buffer_ready_event.write(1).unwrap();
612+
}
589613
}
590614

591615
#[test]
@@ -812,18 +836,29 @@ mod tests {
812836
#[test]
813837
fn test_serial_events() {
814838
let intr_evt = EventFd::new(libc::EFD_NONBLOCK).unwrap();
815-
let metrics = Arc::new(ExampleSerialMetrics::default());
839+
840+
let events_ = Arc::new(ExampleSerialEvents::new());
816841
let mut oneslot_buf = [0u8; 1];
817-
let mut serial = Serial::with_events(intr_evt, metrics, oneslot_buf.as_mut());
842+
let mut serial = Serial::with_events(intr_evt, events_, oneslot_buf.as_mut());
843+
844+
// This should be an error because buffer_ready_event has not been
845+
// triggered yet so no one should have written to that fd yet.
846+
assert_eq!(
847+
serial.events.buffer_ready_event.read().unwrap_err().kind(),
848+
io::ErrorKind::WouldBlock
849+
);
818850

819851
// Check everything is equal to 0 at the beginning.
820852
assert_eq!(serial.events.read_count.count(), 0);
821853
assert_eq!(serial.events.out_byte_count.count(), 0);
822854
assert_eq!(serial.events.tx_lost_byte_count.count(), 0);
823855

824856
// This DATA read should cause the `SerialEvents::buffer_read` method to be invoked.
857+
// And since the in_buffer is empty the buffer_ready_event should have
858+
// been triggered, hence we can read from that fd.
825859
serial.read(DATA_OFFSET);
826860
assert_eq!(serial.events.read_count.count(), 1);
861+
assert_eq!(serial.events.buffer_ready_event.read().unwrap(), 1);
827862

828863
// This DATA write should cause `SerialEvents::out_byte` to be called.
829864
serial.write(DATA_OFFSET, 1).unwrap();
@@ -840,6 +875,22 @@ mod tests {
840875
assert_eq!(serial.events.read_count.count(), 1);
841876
assert_eq!(serial.events.out_byte_count.count(), 1);
842877
assert_eq!(serial.events.tx_lost_byte_count.count(), 1);
878+
879+
// This DATA read should cause the `SerialEvents::buffer_read` method to be invoked.
880+
// And since it was the last byte from in buffer the `SerialEvents::in_buffer_empty`
881+
// was also invoked.
882+
serial.read(DATA_OFFSET);
883+
assert_eq!(serial.events.read_count.count(), 2);
884+
assert_eq!(serial.events.buffer_ready_event.read().unwrap(), 1);
885+
let _res = serial.enqueue_raw_bytes(&[1, 2]);
886+
serial.read(DATA_OFFSET);
887+
// Since there is still one byte in the in_buffer, buffer_ready_events
888+
// should have not been triggered so we shouldn't have anything to read
889+
// from that fd.
890+
assert_eq!(
891+
serial.events.buffer_ready_event.read().unwrap_err().kind(),
892+
io::ErrorKind::WouldBlock
893+
);
843894
}
844895

845896
#[test]

0 commit comments

Comments
 (0)