mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-20 13:06:33 +00:00
Avoid duplicate wait_events
methods
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
6e8896165d
commit
ab9941263b
@ -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>>,
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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()?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user