diff --git a/kernel/src/device/pty/pty.rs b/kernel/src/device/pty/pty.rs index 4ffb74402..1ddbc83c4 100644 --- a/kernel/src/device/pty/pty.rs +++ b/kernel/src/device/pty/pty.rs @@ -89,6 +89,19 @@ impl PtyMaster { self.output.buffer_len() } + fn try_read(&self, writer: &mut VmWriter) -> Result { + let mut input = self.input.disable_irq().lock(); + + if input.is_empty() { + return_errno_with_message!(Errno::EAGAIN, "the buffer is empty"); + } + + let read_len = input.read_fallible(writer)?; + self.update_state(&input); + + Ok(read_len) + } + fn update_state(&self, buf: &RingBuffer) { if buf.is_empty() { self.pollee.del_events(IoEvents::IN) @@ -120,35 +133,12 @@ impl Pollable for PtyMaster { impl FileIo for PtyMaster { fn read(&self, writer: &mut VmWriter) -> Result { - let read_len = writer.avail(); - // TODO: deal with nonblocking read - if read_len == 0 { + if !writer.has_avail() { return Ok(0); } - let mut poller = Poller::new(); - loop { - let mut input = self.input.disable_irq().lock(); - - if input.is_empty() { - let events = self.pollee.poll(IoEvents::IN, Some(&mut poller)); - - if events.contains(IoEvents::ERR) { - return_errno_with_message!(Errno::EACCES, "unexpected err"); - } - - if events.is_empty() { - drop(input); - // FIXME: deal with pty read timeout - poller.wait()?; - } - continue; - } - - let read_len = input.read_fallible(writer)?; - self.update_state(&input); - return Ok(read_len); - } + // TODO: deal with nonblocking and timeout + self.wait_events(IoEvents::IN, || self.try_read(writer)) } fn write(&self, reader: &mut VmReader) -> Result { diff --git a/kernel/src/device/tty/line_discipline.rs b/kernel/src/device/tty/line_discipline.rs index b5737fafe..8a7956975 100644 --- a/kernel/src/device/tty/line_discipline.rs +++ b/kernel/src/device/tty/line_discipline.rs @@ -16,7 +16,7 @@ use crate::{ process::signal::{ constants::{SIGINT, SIGQUIT}, signals::kernel::KernelSignal, - Pollee, Poller, + Pollable, Pollee, Poller, }, thread::work_queue::{submit_work_item, work_item::WorkItem, WorkPriority}, util::ring_buffer::RingBuffer, @@ -87,6 +87,12 @@ impl CurrentLine { } } +impl Pollable for LineDiscipline { + fn poll(&self, mask: IoEvents, poller: Option<&mut Poller>) -> IoEvents { + self.pollee.poll(mask, poller) + } +} + impl LineDiscipline { /// Creates a new line discipline pub fn new(send_signal: LdiscSignalSender) -> Arc { @@ -229,19 +235,7 @@ impl LineDiscipline { } pub fn read(&self, buf: &mut [u8]) -> Result { - loop { - let res = self.try_read(buf); - match res { - Ok(len) => return Ok(len), - Err(e) if e.error() != Errno::EAGAIN => return Err(e), - Err(_) => { - let mut poller = Poller::new(); - if self.poll(IoEvents::IN, Some(&mut poller)).is_empty() { - poller.wait()? - } - } - } - } + self.wait_events(IoEvents::IN, || self.try_read(buf)) } /// Reads all bytes buffered to `dst`. @@ -275,10 +269,6 @@ impl LineDiscipline { Ok(read_len) } - pub fn poll(&self, mask: IoEvents, poller: Option<&mut Poller>) -> IoEvents { - self.pollee.poll(mask, poller) - } - /// Reads bytes from `self` to `dst`, returning the actual bytes read. /// /// If no bytes are available, this method returns 0 immediately. diff --git a/kernel/src/syscall/eventfd.rs b/kernel/src/syscall/eventfd.rs index c77b48e54..ad3d9ff70 100644 --- a/kernel/src/syscall/eventfd.rs +++ b/kernel/src/syscall/eventfd.rs @@ -130,6 +130,28 @@ impl EventFile { // TODO: deal with overflow logic } + fn try_read(&self, writer: &mut VmWriter) -> Result<()> { + let mut counter = self.counter.lock(); + + // Wait until the counter becomes non-zero + if *counter == 0 { + return_errno_with_message!(Errno::EAGAIN, "the counter is zero"); + } + + // Copy value from counter, and set the new counter value + if self.flags.lock().contains(Flags::EFD_SEMAPHORE) { + writer.write_fallible(&mut 1u64.as_bytes().into())?; + *counter -= 1; + } else { + writer.write_fallible(&mut (*counter).as_bytes().into())?; + *counter = 0; + } + + self.update_io_state(&counter); + + Ok(()) + } + /// Adds val to the counter. /// /// If the new_value is overflowed or exceeds MAX_COUNTER_VALUE, the counter value @@ -160,40 +182,15 @@ impl Pollable for EventFile { impl FileLike for EventFile { fn read(&self, writer: &mut VmWriter) -> Result { let read_len = core::mem::size_of::(); + if writer.avail() < read_len { return_errno_with_message!(Errno::EINVAL, "buf len is less len u64 size"); } - loop { - let mut counter = self.counter.lock(); - - // Wait until the counter becomes non-zero - if *counter == 0 { - if self.is_nonblocking() { - return_errno_with_message!(Errno::EAGAIN, "try reading event file again"); - } - - self.update_io_state(&counter); - drop(counter); - - let mut poller = Poller::new(); - if self.pollee.poll(IoEvents::IN, Some(&mut poller)).is_empty() { - poller.wait()?; - } - continue; - } - - // Copy value from counter, and set the new counter value - if self.flags.lock().contains(Flags::EFD_SEMAPHORE) { - writer.write_fallible(&mut 1u64.as_bytes().into())?; - *counter -= 1; - } else { - writer.write_fallible(&mut (*counter).as_bytes().into())?; - *counter = 0; - } - - self.update_io_state(&counter); - break; + if self.is_nonblocking() { + self.try_read(writer)?; + } else { + self.wait_events(IoEvents::IN, || self.try_read(writer))?; } Ok(read_len)