mirror of https://github.com/smol-rs/smol
refactor: use libc for epoll
This commit is contained in:
parent
63ffbc575c
commit
a56aa12de8
|
@ -44,7 +44,6 @@ features = ["rt-threaded"]
|
|||
optional = true
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
nix = "0.17.0"
|
||||
libc = "0.2.70"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
|
|
|
@ -678,7 +678,7 @@ impl Async<TcpStream> {
|
|||
socket.connect(&addr.into()).or_else(|err| {
|
||||
// Check for EINPROGRESS on Unix and WSAEWOULDBLOCK on Windows.
|
||||
#[cfg(unix)]
|
||||
let in_progress = err.raw_os_error() == Some(crate::sys::libc::EINPROGRESS);
|
||||
let in_progress = err.raw_os_error() == Some(libc::EINPROGRESS);
|
||||
#[cfg(windows)]
|
||||
let in_progress = err.kind() == io::ErrorKind::WouldBlock;
|
||||
|
||||
|
@ -1006,7 +1006,7 @@ impl Async<UnixStream> {
|
|||
socket
|
||||
.connect(&socket2::SockAddr::unix(path)?)
|
||||
.or_else(|err| {
|
||||
if err.raw_os_error() == Some(crate::sys::libc::EINPROGRESS) {
|
||||
if err.raw_os_error() == Some(libc::EINPROGRESS) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(err)
|
||||
|
|
|
@ -430,15 +430,6 @@ impl Source {
|
|||
}
|
||||
}
|
||||
|
||||
/// Converts a [`nix::Error`] into [`io::Error`].
|
||||
#[cfg(unix)]
|
||||
fn io_err(err: nix::Error) -> io::Error {
|
||||
match err {
|
||||
nix::Error::Sys(code) => code.into(),
|
||||
err => io::Error::new(io::ErrorKind::Other, Box::new(err)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Raw bindings to epoll (Linux, Android, illumos).
|
||||
#[cfg(any(target_os = "linux", target_os = "android", target_os = "illumos"))]
|
||||
mod sys {
|
||||
|
@ -448,23 +439,21 @@ mod sys {
|
|||
use std::time::Duration;
|
||||
|
||||
use crate::sys::epoll::{
|
||||
epoll_create1, epoll_ctl, epoll_wait, EpollCreateFlags, EpollEvent, EpollFlags, EpollOp,
|
||||
epoll_create1, epoll_ctl, epoll_wait, EpollEvent, EpollFlags, EpollOp,
|
||||
};
|
||||
|
||||
use super::io_err;
|
||||
|
||||
pub struct Reactor(RawFd);
|
||||
impl Reactor {
|
||||
pub fn new() -> io::Result<Reactor> {
|
||||
let epoll_fd = epoll_create1(EpollCreateFlags::EPOLL_CLOEXEC).map_err(io_err)?;
|
||||
let epoll_fd = epoll_create1()?;
|
||||
Ok(Reactor(epoll_fd))
|
||||
}
|
||||
pub fn register(&self, fd: RawFd, key: usize) -> io::Result<()> {
|
||||
let ev = &mut EpollEvent::new(EpollFlags::empty(), key as u64);
|
||||
epoll_ctl(self.0, EpollOp::EpollCtlAdd, fd, Some(ev)).map_err(io_err)
|
||||
let ev = &mut EpollEvent::new(0, key as u64);
|
||||
epoll_ctl(self.0, EpollOp::EpollCtlAdd, fd, Some(ev))
|
||||
}
|
||||
pub fn reregister(&self, fd: RawFd, key: usize, read: bool, write: bool) -> io::Result<()> {
|
||||
let mut flags = EpollFlags::EPOLLONESHOT;
|
||||
let mut flags = libc::EPOLLONESHOT;
|
||||
if read {
|
||||
flags |= read_flags();
|
||||
}
|
||||
|
@ -472,10 +461,10 @@ mod sys {
|
|||
flags |= write_flags();
|
||||
}
|
||||
let ev = &mut EpollEvent::new(flags, key as u64);
|
||||
epoll_ctl(self.0, EpollOp::EpollCtlMod, fd, Some(ev)).map_err(io_err)
|
||||
epoll_ctl(self.0, EpollOp::EpollCtlMod, fd, Some(ev))
|
||||
}
|
||||
pub fn deregister(&self, fd: RawFd) -> io::Result<()> {
|
||||
epoll_ctl(self.0, EpollOp::EpollCtlDel, fd, None).map_err(io_err)
|
||||
epoll_ctl(self.0, EpollOp::EpollCtlDel, fd, None)
|
||||
}
|
||||
pub fn wait(&self, events: &mut Events, timeout: Option<Duration>) -> io::Result<usize> {
|
||||
let timeout_ms = timeout
|
||||
|
@ -488,15 +477,15 @@ mod sys {
|
|||
})
|
||||
.and_then(|t| t.as_millis().try_into().ok())
|
||||
.unwrap_or(-1);
|
||||
events.len = epoll_wait(self.0, &mut events.list, timeout_ms).map_err(io_err)?;
|
||||
events.len = epoll_wait(self.0, &mut events.list, timeout_ms)?;
|
||||
Ok(events.len)
|
||||
}
|
||||
}
|
||||
fn read_flags() -> EpollFlags {
|
||||
EpollFlags::EPOLLIN | EpollFlags::EPOLLRDHUP
|
||||
libc::EPOLLIN | libc::EPOLLRDHUP
|
||||
}
|
||||
fn write_flags() -> EpollFlags {
|
||||
EpollFlags::EPOLLOUT
|
||||
libc::EPOLLOUT
|
||||
}
|
||||
|
||||
pub struct Events {
|
||||
|
@ -511,8 +500,8 @@ mod sys {
|
|||
}
|
||||
pub fn iter(&self) -> impl Iterator<Item = Event> + '_ {
|
||||
self.list[..self.len].iter().map(|ev| Event {
|
||||
readable: ev.events().intersects(read_flags()),
|
||||
writable: ev.events().intersects(write_flags()),
|
||||
readable: (ev.events() & read_flags()) > 0,
|
||||
writable: (ev.events() & write_flags()) > 0,
|
||||
key: ev.data() as usize,
|
||||
})
|
||||
}
|
||||
|
@ -540,7 +529,6 @@ mod sys {
|
|||
|
||||
use crate::sys::event::{kevent_ts, kqueue, FilterFlag, KEvent};
|
||||
use crate::sys::fcntl::{fcntl, FcntlArg};
|
||||
use crate::sys::libc;
|
||||
|
||||
pub struct Reactor(RawFd);
|
||||
impl Reactor {
|
||||
|
|
107
src/sys.rs
107
src/sys.rs
|
@ -53,9 +53,6 @@ pub mod unistd {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub use nix::Error;
|
||||
|
||||
#[cfg(unix)]
|
||||
pub mod fcntl {
|
||||
use super::check_err;
|
||||
|
@ -153,7 +150,7 @@ pub mod event {
|
|||
#[allow(non_camel_case_types)]
|
||||
type type_of_data = libc::int64_t;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct KEvent(libc::kevent);
|
||||
|
||||
|
@ -244,13 +241,103 @@ pub mod event {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub use libc;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android", target_os = "illumos"))]
|
||||
/// Epoll.
|
||||
pub mod epoll {
|
||||
pub use nix::sys::epoll::{
|
||||
epoll_create1, epoll_ctl, epoll_wait, EpollCreateFlags, EpollEvent, EpollFlags, EpollOp,
|
||||
};
|
||||
use super::check_err;
|
||||
use std::os::unix::io::RawFd;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
#[repr(i32)]
|
||||
pub enum EpollOp {
|
||||
EpollCtlAdd = libc::EPOLL_CTL_ADD,
|
||||
EpollCtlDel = libc::EPOLL_CTL_DEL,
|
||||
EpollCtlMod = libc::EPOLL_CTL_MOD,
|
||||
}
|
||||
|
||||
pub type EpollFlags = libc::c_int;
|
||||
|
||||
pub fn epoll_create1() -> Result<RawFd, std::io::Error> {
|
||||
// According to libuv, `EPOLL_CLOEXEC` is not defined on Android API <
|
||||
// 21. But `EPOLL_CLOEXEC` is an alias for `O_CLOEXEC` on that platform,
|
||||
// so we use it instead.
|
||||
#[cfg(target_os = "android")]
|
||||
let epoll_create1_flag = libc::O_CLOEXEC;
|
||||
#[cfg(not(target_os = "android"))]
|
||||
let epoll_create1_flag = libc::EPOLL_CLOEXEC;
|
||||
|
||||
let res = unsafe { libc::epoll_create1(epoll_create1_flag) };
|
||||
|
||||
check_err(res)
|
||||
}
|
||||
|
||||
pub fn epoll_ctl<'a, T>(
|
||||
epfd: RawFd,
|
||||
op: EpollOp,
|
||||
fd: RawFd,
|
||||
event: T,
|
||||
) -> Result<(), std::io::Error>
|
||||
where
|
||||
T: Into<Option<&'a mut EpollEvent>>,
|
||||
{
|
||||
let mut event: Option<&mut EpollEvent> = event.into();
|
||||
if event.is_none() && op != EpollOp::EpollCtlDel {
|
||||
Err(std::io::Error::from_raw_os_error(libc::EINVAL))
|
||||
} else {
|
||||
let res = unsafe {
|
||||
if let Some(ref mut event) = event {
|
||||
libc::epoll_ctl(epfd, op as libc::c_int, fd, &mut event.event)
|
||||
} else {
|
||||
libc::epoll_ctl(epfd, op as libc::c_int, fd, std::ptr::null_mut())
|
||||
}
|
||||
};
|
||||
check_err(res).map(drop)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn epoll_wait(
|
||||
epfd: RawFd,
|
||||
events: &mut [EpollEvent],
|
||||
timeout_ms: isize,
|
||||
) -> Result<usize, std::io::Error> {
|
||||
let res = unsafe {
|
||||
libc::epoll_wait(
|
||||
epfd,
|
||||
events.as_mut_ptr() as *mut libc::epoll_event,
|
||||
events.len() as libc::c_int,
|
||||
timeout_ms as libc::c_int,
|
||||
)
|
||||
};
|
||||
|
||||
check_err(res).map(|r| r as usize)
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(transparent)]
|
||||
pub struct EpollEvent {
|
||||
event: libc::epoll_event,
|
||||
}
|
||||
|
||||
impl EpollEvent {
|
||||
pub fn new(events: EpollFlags, data: u64) -> Self {
|
||||
EpollEvent {
|
||||
event: libc::epoll_event {
|
||||
events: events as u32,
|
||||
u64: data,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn empty() -> Self {
|
||||
unsafe { std::mem::zeroed::<EpollEvent>() }
|
||||
}
|
||||
|
||||
pub fn events(&self) -> EpollFlags {
|
||||
self.event.events as libc::c_int
|
||||
}
|
||||
|
||||
pub fn data(&self) -> u64 {
|
||||
self.event.u64
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue