Avoid duplicate wait_events methods

This commit is contained in:
Ruihan Li
2024-06-30 22:38:28 +08:00
committed by Tate, Hongliang Tian
parent 6e8896165d
commit ab9941263b
11 changed files with 126 additions and 134 deletions

View File

@ -12,7 +12,7 @@ use super::*;
use crate::{
events::Observer,
fs::{file_handle::FileLike, file_table::FdEvents, utils::IoctlCmd},
process::signal::{Pollee, Poller},
process::signal::{Pollable, Pollee, Poller},
};
/// A file-like object that provides epoll API.
@ -321,6 +321,12 @@ impl Drop for EpollFile {
}
}
impl Pollable for EpollFile {
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
self.pollee.poll(mask, poller)
}
}
// Implement the common methods required by FileHandle
impl FileLike for EpollFile {
fn read(&self, buf: &mut [u8]) -> Result<usize> {
@ -335,10 +341,6 @@ impl FileLike for EpollFile {
return_errno_with_message!(Errno::EINVAL, "epoll files do not support ioctl");
}
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
self.pollee.poll(mask, poller)
}
fn register_observer(
&self,
observer: Weak<dyn Observer<IoEvents>>,

View File

@ -12,11 +12,11 @@ use crate::{
},
net::socket::Socket,
prelude::*,
process::{signal::Poller, Gid, Uid},
process::{signal::Pollable, Gid, Uid},
};
/// The basic operations defined on a file
pub trait FileLike: Send + Sync + Any {
pub trait FileLike: Pollable + Send + Sync + Any {
fn read(&self, buf: &mut [u8]) -> Result<usize> {
return_errno_with_message!(Errno::EINVAL, "read is not supported");
}
@ -50,10 +50,6 @@ pub trait FileLike: Send + Sync + Any {
return_errno_with_message!(Errno::EINVAL, "ioctl is not supported");
}
fn poll(&self, _mask: IoEvents, _poller: Option<&Poller>) -> IoEvents {
IoEvents::empty()
}
fn resize(&self, new_size: usize) -> Result<()> {
return_errno_with_message!(Errno::EINVAL, "resize is not supported");
}

View File

@ -4,7 +4,7 @@ use aster_rights::TRights;
use inherit_methods_macro::inherit_methods;
use super::*;
use crate::prelude::*;
use crate::{prelude::*, process::signal::Pollable};
impl InodeHandle<Rights> {
pub fn new(
@ -80,8 +80,12 @@ impl Clone for InodeHandle<Rights> {
}
#[inherit_methods(from = "self.0")]
impl FileLike for InodeHandle<Rights> {
impl Pollable for InodeHandle<Rights> {
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents;
}
#[inherit_methods(from = "self.0")]
impl FileLike for InodeHandle<Rights> {
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32>;
fn status_flags(&self) -> StatusFlags;
fn access_mode(&self) -> AccessMode;

View File

@ -9,7 +9,10 @@ use super::{
use crate::{
events::{IoEvents, Observer},
prelude::*,
process::{signal::Poller, Gid, Uid},
process::{
signal::{Pollable, Poller},
Gid, Uid,
},
time::clocks::RealTimeCoarseClock,
};
@ -23,15 +26,17 @@ impl PipeReader {
}
}
impl Pollable for PipeReader {
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
self.consumer.poll(mask, poller)
}
}
impl FileLike for PipeReader {
fn read(&self, buf: &mut [u8]) -> Result<usize> {
self.consumer.read(buf)
}
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
self.consumer.poll(mask, poller)
}
fn status_flags(&self) -> StatusFlags {
self.consumer.status_flags()
}
@ -90,15 +95,17 @@ impl PipeWriter {
}
}
impl Pollable for PipeWriter {
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
self.producer.poll(mask, poller)
}
}
impl FileLike for PipeWriter {
fn write(&self, buf: &[u8]) -> Result<usize> {
self.producer.write(buf)
}
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
self.producer.poll(mask, poller)
}
fn status_flags(&self) -> StatusFlags {
self.producer.status_flags()
}

View File

@ -21,7 +21,7 @@ use crate::{
},
},
prelude::*,
process::signal::{Pollee, Poller},
process::signal::{Pollable, Pollee, Poller},
util::IoVec,
};
@ -170,28 +170,6 @@ impl DatagramSocket {
sent_bytes
}
// TODO: Support timeout
fn wait_events<F, R>(&self, mask: IoEvents, mut cond: F) -> Result<R>
where
F: FnMut() -> Result<R>,
{
let poller = Poller::new();
loop {
match cond() {
Err(err) if err.error() == Errno::EAGAIN => (),
result => return result,
};
let events = self.poll(mask, Some(&poller));
if !events.is_empty() {
continue;
}
poller.wait()?;
}
}
fn update_io_events(&self) {
let inner = self.inner.read();
let Inner::Bound(bound_datagram) = inner.as_ref() else {
@ -201,6 +179,12 @@ impl DatagramSocket {
}
}
impl Pollable for DatagramSocket {
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
self.pollee.poll(mask, poller)
}
}
impl FileLike for DatagramSocket {
fn read(&self, buf: &mut [u8]) -> Result<usize> {
// TODO: set correct flags
@ -223,10 +207,6 @@ impl FileLike for DatagramSocket {
self.try_send(buf, &remote, flags)
}
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
self.pollee.poll(mask, poller)
}
fn as_socket(self: Arc<Self>) -> Option<Arc<dyn Socket>> {
Some(self)
}

View File

@ -34,7 +34,7 @@ use crate::{
},
},
prelude::*,
process::signal::{Pollee, Poller},
process::signal::{Pollable, Pollee, Poller},
util::IoVec,
};
@ -319,28 +319,6 @@ impl StreamSocket {
}
}
// TODO: Support timeout
fn wait_events<F, R>(&self, mask: IoEvents, mut cond: F) -> Result<R>
where
F: FnMut() -> Result<R>,
{
let poller = Poller::new();
loop {
match cond() {
Err(err) if err.error() == Errno::EAGAIN => (),
result => return result,
};
let events = self.poll(mask, Some(&poller));
if !events.is_empty() {
continue;
}
poller.wait()?;
}
}
#[must_use]
fn update_io_events(&self) -> bool {
let state = self.state.read();
@ -359,6 +337,12 @@ impl StreamSocket {
}
}
impl Pollable for StreamSocket {
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
self.pollee.poll(mask, poller)
}
}
impl FileLike for StreamSocket {
fn read(&self, buf: &mut [u8]) -> Result<usize> {
// TODO: Set correct flags
@ -372,10 +356,6 @@ impl FileLike for StreamSocket {
self.send(buf, flags)
}
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
self.pollee.poll(mask, poller)
}
fn status_flags(&self) -> StatusFlags {
// TODO: when we fully support O_ASYNC, return the flag
if self.is_nonblocking() {

View File

@ -23,7 +23,7 @@ use crate::{
SockShutdownCmd, Socket,
},
prelude::*,
process::signal::Poller,
process::signal::{Pollable, Poller},
util::IoVec,
};
@ -103,6 +103,17 @@ impl UnixStreamSocket {
}
}
impl Pollable for UnixStreamSocket {
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
let inner = self.0.read();
match &*inner {
State::Init(init) => init.poll(mask, poller),
State::Listen(listen) => listen.poll(mask, poller),
State::Connected(connected) => connected.poll(mask, poller),
}
}
}
impl FileLike for UnixStreamSocket {
fn as_socket(self: Arc<Self>) -> Option<Arc<dyn Socket>> {
Some(self)
@ -120,15 +131,6 @@ impl FileLike for UnixStreamSocket {
self.send(buf, flags)
}
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
let inner = self.0.read();
match &*inner {
State::Init(init) => init.poll(mask, poller),
State::Listen(listen) => listen.poll(mask, poller),
State::Connected(connected) => connected.poll(mask, poller),
}
}
fn status_flags(&self) -> StatusFlags {
let inner = self.0.read();
let is_nonblocking = match &*inner {

View File

@ -14,7 +14,7 @@ use crate::{
MessageHeader, SendRecvFlags, SockShutdownCmd, Socket, SocketAddr,
},
prelude::*,
process::signal::Poller,
process::signal::{Pollable, Poller},
util::IoVec,
};
@ -53,39 +53,6 @@ impl VsockStreamSocket {
self.is_nonblocking.store(nonblocking, Ordering::Relaxed);
}
// TODO: Support timeout
fn wait_events<F, R>(&self, mask: IoEvents, mut cond: F) -> Result<R>
where
F: FnMut() -> Result<R>,
{
let poller = Poller::new();
loop {
match cond() {
Err(err) if err.error() == Errno::EAGAIN => (),
result => {
if let Err(e) = result {
debug!("The result of cond() is Error: {:?}", e);
}
return result;
}
};
let events = match &*self.status.read() {
Status::Init(init) => init.poll(mask, Some(&poller)),
Status::Listen(listen) => listen.poll(mask, Some(&poller)),
Status::Connected(connected) => connected.poll(mask, Some(&poller)),
};
debug!("events: {:?}", events);
if !events.is_empty() {
continue;
}
poller.wait()?;
}
}
fn try_accept(&self) -> Result<(Arc<dyn FileLike>, SocketAddr)> {
let listen = match &*self.status.read() {
Status::Listen(listen) => listen.clone(),
@ -155,6 +122,16 @@ impl VsockStreamSocket {
}
}
impl Pollable for VsockStreamSocket {
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
match &*self.status.read() {
Status::Init(init) => init.poll(mask, poller),
Status::Listen(listen) => listen.poll(mask, poller),
Status::Connected(connected) => connected.poll(mask, poller),
}
}
}
impl FileLike for VsockStreamSocket {
fn as_socket(self: Arc<Self>) -> Option<Arc<dyn Socket>> {
Some(self)
@ -170,14 +147,6 @@ impl FileLike for VsockStreamSocket {
self.send(buf, SendRecvFlags::empty())
}
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
match &*self.status.read() {
Status::Init(init) => init.poll(mask, poller),
Status::Listen(listen) => listen.poll(mask, poller),
Status::Connected(connected) => connected.poll(mask, poller),
}
}
fn status_flags(&self) -> StatusFlags {
if self.is_nonblocking() {
StatusFlags::O_NONBLOCK

View File

@ -20,7 +20,7 @@ use c_types::{siginfo_t, ucontext_t};
pub use events::{SigEvents, SigEventsFilter};
use ostd::{cpu::UserContext, user::UserContextApi};
pub use pauser::Pauser;
pub use poll::{Pollee, Poller};
pub use poll::{Pollable, Pollee, Poller};
use sig_action::{SigAction, SigActionFlags, SigDefaultAction};
use sig_mask::SigMask;
use sig_num::SigNum;

View File

@ -242,3 +242,53 @@ impl EventCounter {
self.pauser.resume_one();
}
}
/// The `Pollable` trait allows for waiting for events and performing event-based operations.
///
/// Implementors are required to provide a method, [`Pollable::poll`], which is usually implemented
/// by simply calling [`Pollee::poll`] on the internal [`Pollee`]. This trait provides another
/// method, [`Pollable::wait_events`], to allow waiting for events and performing operations
/// according to the events.
///
/// This trait is added instead of creating a new method in [`Pollee`] because sometimes we do not
/// have access to the internal [`Pollee`], but there is a method that provides the same sematics
/// as [`Pollee::poll`] and we need to perform event-based operations using that method.
pub trait Pollable {
/// Returns the interesting events if there are any, or waits for them to happen if there are
/// none.
///
/// This method has the same semantics as [`Pollee::poll`].
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents;
/// Waits for events and performs event-based operations.
///
/// If a call to `cond()` succeeds or fails with an error code other than `EAGAIN`, the method
/// will return whatever the call to `cond()` returns. Otherwise, the method will wait for some
/// interesting events specified in `mask` to happen and try again.
///
/// The user must ensure that a call to `cond()` does not fail with `EAGAIN` when the
/// interesting events occur. However, it is allowed to have spurious `EAGAIN` failures due to
/// race conditions where the events are consumed by another thread.
fn wait_events<F, R>(&self, mask: IoEvents, mut cond: F) -> Result<R>
where
Self: Sized,
F: FnMut() -> Result<R>,
{
let poller = Poller::new();
loop {
match cond() {
Err(err) if err.error() == Errno::EAGAIN => (),
result => return result,
};
let events = self.poll(mask, Some(&poller));
if !events.is_empty() {
continue;
}
// TODO: Support timeout
poller.wait()?;
}
}
}

View File

@ -24,7 +24,7 @@ use crate::{
},
prelude::*,
process::{
signal::{Pauser, Pollee, Poller},
signal::{Pauser, Pollable, Pollee, Poller},
Gid, Uid,
},
time::clocks::RealTimeClock,
@ -150,6 +150,12 @@ impl EventFile {
}
}
impl Pollable for EventFile {
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
self.pollee.poll(mask, poller)
}
}
impl FileLike for EventFile {
fn read(&self, buf: &mut [u8]) -> Result<usize> {
let read_len = core::mem::size_of::<u64>();
@ -216,10 +222,6 @@ impl FileLike for EventFile {
Ok(write_len)
}
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
self.pollee.poll(mask, poller)
}
fn status_flags(&self) -> StatusFlags {
if self.is_nonblocking() {
StatusFlags::O_NONBLOCK