Skip to content
Snippets Groups Projects
Commit 02f202ff authored by 8tab's avatar 8tab
Browse files

Use BufWriter (instead of LineWriter) for FILEs other than stdout and stderr

BufWriter has more capacity (8k vs 1k) and doesn't flush the stream after '\n'.
That change helps to reduce the number of syscalls, especially when dealing with text files.

Since BufWriter has a different way of getting number of pending elements than LineWriter -
Pending trait was introduced to deal with that.
parent ccee7eae
No related branches found
No related tags found
1 merge request!328Use BufWriter (instead of LineWriter) for FILEs other than stdout and stderr
...@@ -2,13 +2,13 @@ use super::{constants, Buffer, BUFSIZ, FILE}; ...@@ -2,13 +2,13 @@ use super::{constants, Buffer, BUFSIZ, FILE};
use core::{cell::UnsafeCell, ptr}; use core::{cell::UnsafeCell, ptr};
use crate::{fs::File, io::LineWriter, platform::types::*, sync::Mutex}; use crate::{fs::File, io::LineWriter, platform::types::*, sync::Mutex};
use alloc::vec::Vec; use alloc::{boxed::Box, vec::Vec};
pub struct GlobalFile(UnsafeCell<FILE>); pub struct GlobalFile(UnsafeCell<FILE>);
impl GlobalFile { impl GlobalFile {
fn new(file: c_int, flags: c_int) -> Self { fn new(file: c_int, flags: c_int) -> Self {
let file = File::new(file); let file = File::new(file);
let writer = LineWriter::new(unsafe { file.get_ref() }); let writer = Box::new(LineWriter::new(unsafe { file.get_ref() }));
GlobalFile(UnsafeCell::new(FILE { GlobalFile(UnsafeCell::new(FILE {
lock: Mutex::new(()), lock: Mutex::new(()),
......
...@@ -7,7 +7,7 @@ use crate::{ ...@@ -7,7 +7,7 @@ use crate::{
pub extern "C" fn __fpending(stream: *mut FILE) -> size_t { pub extern "C" fn __fpending(stream: *mut FILE) -> size_t {
let stream = unsafe { &mut *stream }.lock(); let stream = unsafe { &mut *stream }.lock();
stream.writer.inner.buf.len() as size_t stream.writer.pending()
} }
#[no_mangle] #[no_mangle]
......
...@@ -4,7 +4,7 @@ use super::{constants::*, Buffer, FILE}; ...@@ -4,7 +4,7 @@ use super::{constants::*, Buffer, FILE};
use crate::{ use crate::{
fs::File, fs::File,
header::{errno, fcntl::*, string::strchr}, header::{errno, fcntl::*, string::strchr},
io::LineWriter, io::BufWriter,
platform::{self, types::*}, platform::{self, types::*},
sync::Mutex, sync::Mutex,
}; };
...@@ -62,7 +62,7 @@ pub unsafe fn _fdopen(fd: c_int, mode: *const c_char) -> Option<*mut FILE> { ...@@ -62,7 +62,7 @@ pub unsafe fn _fdopen(fd: c_int, mode: *const c_char) -> Option<*mut FILE> {
} }
let file = File::new(fd); let file = File::new(fd);
let writer = LineWriter::new(file.get_ref()); let writer = Box::new(BufWriter::new(file.get_ref()));
Some(Box::into_raw(Box::new(FILE { Some(Box::into_raw(Box::new(FILE {
lock: Mutex::new(()), lock: Mutex::new(()),
......
...@@ -24,7 +24,7 @@ use crate::{ ...@@ -24,7 +24,7 @@ use crate::{
string::{self, strlen}, string::{self, strlen},
unistd, unistd,
}, },
io::{self, BufRead, LineWriter, Read, Write}, io::{self, BufRead, BufWriter, LineWriter, Read, Write},
platform::{self, errno, types::*, Pal, Sys, WriteByte}, platform::{self, errno, types::*, Pal, Sys, WriteByte},
sync::Mutex, sync::Mutex,
}; };
...@@ -69,6 +69,27 @@ impl<'a> DerefMut for Buffer<'a> { ...@@ -69,6 +69,27 @@ impl<'a> DerefMut for Buffer<'a> {
} }
} }
pub trait Pending {
fn pending(&self) -> size_t;
}
impl<W: core_io::Write> Pending for BufWriter<W> {
fn pending(&self) -> size_t {
self.buf.len() as size_t
}
}
impl<W: core_io::Write> Pending for LineWriter<W> {
fn pending(&self) -> size_t {
self.inner.buf.len() as size_t
}
}
pub trait Writer: Write + Pending {}
impl<W: core_io::Write> Writer for BufWriter<W> {}
impl<W: core_io::Write> Writer for LineWriter<W> {}
/// This struct gets exposed to the C API. /// This struct gets exposed to the C API.
pub struct FILE { pub struct FILE {
lock: Mutex<()>, lock: Mutex<()>,
...@@ -81,7 +102,7 @@ pub struct FILE { ...@@ -81,7 +102,7 @@ pub struct FILE {
read_size: usize, read_size: usize,
unget: Vec<u8>, unget: Vec<u8>,
// pub for stdio_ext // pub for stdio_ext
pub(crate) writer: LineWriter<File>, pub(crate) writer: Box<dyn Writer + Send>,
// Optional pid for use with popen/pclose // Optional pid for use with popen/pclose
pid: Option<c_int>, pid: Option<c_int>,
...@@ -1145,3 +1166,12 @@ pub unsafe extern "C" fn vsscanf(s: *const c_char, format: *const c_char, ap: va ...@@ -1145,3 +1166,12 @@ pub unsafe extern "C" fn vsscanf(s: *const c_char, format: *const c_char, ap: va
let reader = (s as *const u8).into(); let reader = (s as *const u8).into();
scanf::scanf(reader, format, ap) scanf::scanf(reader, format, ap)
} }
pub unsafe fn flush_io_streams() {
let flush = |stream: *mut FILE| {
let stream = &mut *stream;
stream.flush()
};
flush(stdout);
flush(stderr);
}
...@@ -16,6 +16,7 @@ use crate::{ ...@@ -16,6 +16,7 @@ use crate::{
errno::{self, *}, errno::{self, *},
fcntl::*, fcntl::*,
limits, limits,
stdio::flush_io_streams,
string::*, string::*,
time::constants::CLOCK_MONOTONIC, time::constants::CLOCK_MONOTONIC,
unistd::{self, sysconf, _SC_PAGESIZE}, unistd::{self, sysconf, _SC_PAGESIZE},
...@@ -297,6 +298,8 @@ pub unsafe extern "C" fn exit(status: c_int) { ...@@ -297,6 +298,8 @@ pub unsafe extern "C" fn exit(status: c_int) {
pthread_terminate(); pthread_terminate();
flush_io_streams();
Sys::exit(status); Sys::exit(status);
} }
......
zß水🍌
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment