From c7493d1b9de5e7aed8ab9f558c47de686e7eec90 Mon Sep 17 00:00:00 2001 From: Guillaume Endignoux Date: Tue, 17 Mar 2020 16:26:05 +0100 Subject: [PATCH] Reduce the number of syscalls made by the console in libtock-rs. --- patches/libtock-rs/08-buffered-console.patch | 95 ++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 patches/libtock-rs/08-buffered-console.patch diff --git a/patches/libtock-rs/08-buffered-console.patch b/patches/libtock-rs/08-buffered-console.patch new file mode 100644 index 0000000..5d8a4fc --- /dev/null +++ b/patches/libtock-rs/08-buffered-console.patch @@ -0,0 +1,95 @@ +diff --git a/src/console.rs b/src/console.rs +index ecd7ad1..785de01 100644 +--- a/src/console.rs ++++ b/src/console.rs +@@ -16,33 +16,58 @@ mod allow_nr { + pub const SHARE_BUFFER: usize = 1; + } + ++const BUFFER_SIZE: usize = 64; ++ + pub struct Console { +- allow_buffer: [u8; 64], ++ allow_buffer: [u8; BUFFER_SIZE], ++ count_pending: usize, + } + + impl Console { + pub fn new() -> Console { + Console { +- allow_buffer: [0; 64], ++ allow_buffer: [0; BUFFER_SIZE], ++ count_pending: 0, + } + } + ++ fn is_empty(&self) -> bool { ++ self.count_pending == 0 ++ } ++ ++ fn is_full(&self) -> bool { ++ self.allow_buffer.len() == self.count_pending ++ } ++ ++ fn available_len(&self) -> usize { ++ self.allow_buffer.len() - self.count_pending ++ } ++ + pub fn write>(&mut self, text: S) { + let mut not_written_yet = text.as_ref(); + while !not_written_yet.is_empty() { +- let num_bytes_to_print = self.allow_buffer.len().min(not_written_yet.len()); +- self.allow_buffer[..num_bytes_to_print] ++ let num_bytes_to_print = self.available_len().min(not_written_yet.len()); ++ self.allow_buffer[self.count_pending..(self.count_pending + num_bytes_to_print)] + .copy_from_slice(¬_written_yet[..num_bytes_to_print]); +- self.flush(num_bytes_to_print); ++ self.count_pending += num_bytes_to_print; ++ ++ if self.is_full() { ++ self.flush(); ++ } ++ + not_written_yet = ¬_written_yet[num_bytes_to_print..]; + } + } + +- fn flush(&mut self, num_bytes_to_print: usize) { ++ fn flush(&mut self) { ++ let count = self.count_pending; ++ // Clear the buffer even in case of error, to avoid an infinite loop. ++ self.count_pending = 0; ++ + let result = syscalls::allow( + DRIVER_NUMBER, + allow_nr::SHARE_BUFFER, +- &mut self.allow_buffer[..num_bytes_to_print], ++ &mut self.allow_buffer[..count], + ); + if result.is_err() { + return; +@@ -59,8 +84,7 @@ impl Console { + return; + } + +- let result_code = +- unsafe { syscalls::command(DRIVER_NUMBER, command_nr::WRITE, num_bytes_to_print, 0) }; ++ let result_code = unsafe { syscalls::command(DRIVER_NUMBER, command_nr::WRITE, count, 0) }; + if result_code < 0 { + return; + } +@@ -69,6 +93,14 @@ impl Console { + } + } + ++impl Drop for Console { ++ fn drop(&mut self) { ++ if !self.is_empty() { ++ self.flush(); ++ } ++ } ++} ++ + impl fmt::Write for Console { + fn write_str(&mut self, string: &str) -> Result<(), fmt::Error> { + self.write(string);