Skip to content

Commit 7f912b1

Browse files
author
Stjepan Glavina
authored
Merge pull request async-rs#1 from stjepang/cleanup-sys
Cleanup sys module
2 parents 8a270f4 + 768647d commit 7f912b1

File tree

4 files changed

+165
-325
lines changed

4 files changed

+165
-325
lines changed

.github/workflows/cross.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,7 @@ jobs:
4545
- name: iOS
4646
if: startsWith(matrix.os, 'macos')
4747
run: cross build --target aarch64-apple-ios
48+
49+
# - name: illumos
50+
# if: startsWith(matrix.os, 'ubuntu')
51+
# run: cross build --target x86_64-unknown-illumos

src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ use socket2::{Domain, Protocol, Socket, Type};
3232
use crate::parking::{Reactor, Source};
3333

3434
pub mod parking;
35-
mod sys;
3635

3736
/// Fires at the chosen point in time.
3837
///

src/parking.rs

+161-47
Original file line numberDiff line numberDiff line change
@@ -758,12 +758,9 @@ mod sys {
758758
use std::convert::TryInto;
759759
use std::io;
760760
use std::os::unix::io::RawFd;
761+
use std::ptr;
761762
use std::time::Duration;
762763

763-
use crate::sys::epoll::{
764-
epoll_create1, epoll_ctl, epoll_wait, EpollEvent, EpollFlags, EpollOp,
765-
};
766-
767764
macro_rules! syscall {
768765
($fn:ident $args:tt) => {{
769766
let res = unsafe { libc::$fn $args };
@@ -781,7 +778,42 @@ mod sys {
781778
}
782779
impl Reactor {
783780
pub fn new() -> io::Result<Reactor> {
784-
let epoll_fd = epoll_create1()?;
781+
// According to libuv, `EPOLL_CLOEXEC` is not defined on Android API < 21.
782+
// But `EPOLL_CLOEXEC` is an alias for `O_CLOEXEC` on that platform, so we use it instead.
783+
#[cfg(target_os = "android")]
784+
const CLOEXEC: libc::c_int = libc::O_CLOEXEC;
785+
#[cfg(not(target_os = "android"))]
786+
const CLOEXEC: libc::c_int = libc::EPOLL_CLOEXEC;
787+
788+
let epoll_fd = unsafe {
789+
// Check if the `epoll_create1` symbol is available on this platform.
790+
let ptr = libc::dlsym(
791+
libc::RTLD_DEFAULT,
792+
"epoll_create1\0".as_ptr() as *const libc::c_char,
793+
);
794+
795+
if ptr.is_null() {
796+
// If not, use `epoll_create` and manually set `CLOEXEC`.
797+
let fd = match libc::epoll_create(1024) {
798+
-1 => return Err(io::Error::last_os_error()),
799+
fd => fd,
800+
};
801+
let flags = libc::fcntl(fd, libc::F_GETFD);
802+
libc::fcntl(fd, libc::F_SETFD, flags | libc::FD_CLOEXEC);
803+
fd
804+
} else {
805+
// Use `epoll_create1` with `CLOEXEC`.
806+
let epoll_create1 = std::mem::transmute::<
807+
*mut libc::c_void,
808+
unsafe extern "C" fn(libc::c_int) -> libc::c_int,
809+
>(ptr);
810+
match epoll_create1(CLOEXEC) {
811+
-1 => return Err(io::Error::last_os_error()),
812+
fd => fd,
813+
}
814+
}
815+
};
816+
785817
let event_fd = syscall!(eventfd(0, libc::EFD_CLOEXEC | libc::EFD_NONBLOCK))?;
786818
let reactor = Reactor { epoll_fd, event_fd };
787819
reactor.register(event_fd, !0)?;
@@ -791,8 +823,12 @@ mod sys {
791823
pub fn register(&self, fd: RawFd, key: usize) -> io::Result<()> {
792824
let flags = syscall!(fcntl(fd, libc::F_GETFL))?;
793825
syscall!(fcntl(fd, libc::F_SETFL, flags | libc::O_NONBLOCK))?;
794-
let ev = &mut EpollEvent::new(0, key as u64);
795-
epoll_ctl(self.epoll_fd, EpollOp::EpollCtlAdd, fd, Some(ev))
826+
let mut ev = libc::epoll_event {
827+
events: 0,
828+
u64: key as u64,
829+
};
830+
syscall!(epoll_ctl(self.epoll_fd, libc::EPOLL_CTL_ADD, fd, &mut ev))?;
831+
Ok(())
796832
}
797833
pub fn reregister(&self, fd: RawFd, key: usize, read: bool, write: bool) -> io::Result<()> {
798834
let mut flags = libc::EPOLLONESHOT;
@@ -802,11 +838,21 @@ mod sys {
802838
if write {
803839
flags |= write_flags();
804840
}
805-
let ev = &mut EpollEvent::new(flags, key as u64);
806-
epoll_ctl(self.epoll_fd, EpollOp::EpollCtlMod, fd, Some(ev))
841+
let mut ev = libc::epoll_event {
842+
events: flags as _,
843+
u64: key as u64,
844+
};
845+
syscall!(epoll_ctl(self.epoll_fd, libc::EPOLL_CTL_MOD, fd, &mut ev))?;
846+
Ok(())
807847
}
808848
pub fn deregister(&self, fd: RawFd) -> io::Result<()> {
809-
epoll_ctl(self.epoll_fd, EpollOp::EpollCtlDel, fd, None)
849+
syscall!(epoll_ctl(
850+
self.epoll_fd,
851+
libc::EPOLL_CTL_DEL,
852+
fd,
853+
ptr::null_mut()
854+
))?;
855+
Ok(())
810856
}
811857
pub fn wait(&self, events: &mut Events, timeout: Option<Duration>) -> io::Result<usize> {
812858
let timeout_ms = timeout
@@ -819,7 +865,14 @@ mod sys {
819865
})
820866
.and_then(|t| t.as_millis().try_into().ok())
821867
.unwrap_or(-1);
822-
events.len = epoll_wait(self.epoll_fd, &mut events.list, timeout_ms)?;
868+
869+
let res = syscall!(epoll_wait(
870+
self.epoll_fd,
871+
events.list.as_mut_ptr() as *mut libc::epoll_event,
872+
events.list.len() as libc::c_int,
873+
timeout_ms as libc::c_int,
874+
))?;
875+
events.len = res as usize;
823876

824877
let mut buf = [0u8; 8];
825878
let _ = syscall!(read(
@@ -841,28 +894,29 @@ mod sys {
841894
Ok(())
842895
}
843896
}
844-
fn read_flags() -> EpollFlags {
897+
fn read_flags() -> libc::c_int {
845898
libc::EPOLLIN | libc::EPOLLRDHUP | libc::EPOLLHUP | libc::EPOLLERR | libc::EPOLLPRI
846899
}
847-
fn write_flags() -> EpollFlags {
900+
fn write_flags() -> libc::c_int {
848901
libc::EPOLLOUT | libc::EPOLLHUP | libc::EPOLLERR
849902
}
850903

851904
pub struct Events {
852-
list: Box<[EpollEvent]>,
905+
list: Box<[libc::epoll_event]>,
853906
len: usize,
854907
}
855908
impl Events {
856909
pub fn new() -> Events {
857-
let list = vec![EpollEvent::empty(); 1000].into_boxed_slice();
910+
let ev = libc::epoll_event { events: 0, u64: 0 };
911+
let list = vec![ev; 1000].into_boxed_slice();
858912
let len = 0;
859913
Events { list, len }
860914
}
861915
pub fn iter(&self) -> impl Iterator<Item = Event> + '_ {
862916
self.list[..self.len].iter().map(|ev| Event {
863-
readable: (ev.events() & read_flags()) != 0,
864-
writable: (ev.events() & write_flags()) != 0,
865-
key: ev.data() as usize,
917+
readable: (ev.events as libc::c_int & read_flags()) != 0,
918+
writable: (ev.events as libc::c_int & write_flags()) != 0,
919+
key: ev.u64 as usize,
866920
})
867921
}
868922
}
@@ -886,10 +940,9 @@ mod sys {
886940
use std::io::{self, Read, Write};
887941
use std::os::unix::io::{AsRawFd, RawFd};
888942
use std::os::unix::net::UnixStream;
943+
use std::ptr;
889944
use std::time::Duration;
890945

891-
use crate::sys::event::{kevent_ts, kqueue, KEvent};
892-
893946
macro_rules! syscall {
894947
($fn:ident $args:tt) => {{
895948
let res = unsafe { libc::$fn $args };
@@ -908,7 +961,7 @@ mod sys {
908961
}
909962
impl Reactor {
910963
pub fn new() -> io::Result<Reactor> {
911-
let kqueue_fd = kqueue()?;
964+
let kqueue_fd = syscall!(kqueue())?;
912965
syscall!(fcntl(kqueue_fd, libc::F_SETFD, libc::FD_CLOEXEC))?;
913966
let (read_stream, write_stream) = UnixStream::pair()?;
914967
read_stream.set_nonblocking(true)?;
@@ -939,38 +992,78 @@ mod sys {
939992
} else {
940993
write_flags |= libc::EV_DELETE;
941994
}
942-
let udata = key as _;
943995
let changelist = [
944-
KEvent::new(fd as _, libc::EVFILT_READ, read_flags, 0, 0, udata),
945-
KEvent::new(fd as _, libc::EVFILT_WRITE, write_flags, 0, 0, udata),
996+
libc::kevent {
997+
ident: fd as _,
998+
filter: libc::EVFILT_READ,
999+
flags: read_flags,
1000+
fflags: 0,
1001+
data: 0,
1002+
udata: key as _,
1003+
},
1004+
libc::kevent {
1005+
ident: fd as _,
1006+
filter: libc::EVFILT_WRITE,
1007+
flags: write_flags,
1008+
fflags: 0,
1009+
data: 0,
1010+
udata: key as _,
1011+
},
9461012
];
9471013
let mut eventlist = changelist;
948-
kevent_ts(self.kqueue_fd, &changelist, &mut eventlist, None)?;
1014+
syscall!(kevent(
1015+
self.kqueue_fd,
1016+
changelist.as_ptr() as *const libc::kevent,
1017+
changelist.len() as _,
1018+
eventlist.as_mut_ptr() as *mut libc::kevent,
1019+
eventlist.len() as _,
1020+
ptr::null(),
1021+
))?;
9491022
for ev in &eventlist {
9501023
// Explanation for ignoring EPIPE: https://github.com/tokio-rs/mio/issues/582
951-
let (flags, data) = (ev.flags(), ev.data());
952-
if (flags & libc::EV_ERROR) == 1
953-
&& data != 0
954-
&& data != libc::ENOENT as _
955-
&& data != libc::EPIPE as _
1024+
if (ev.flags & libc::EV_ERROR) != 0
1025+
&& ev.data != 0
1026+
&& ev.data != libc::ENOENT as _
1027+
&& ev.data != libc::EPIPE as _
9561028
{
957-
return Err(io::Error::from_raw_os_error(data as _));
1029+
return Err(io::Error::from_raw_os_error(ev.data as _));
9581030
}
9591031
}
9601032
Ok(())
9611033
}
9621034
pub fn deregister(&self, fd: RawFd) -> io::Result<()> {
9631035
let flags = libc::EV_DELETE | libc::EV_RECEIPT;
9641036
let changelist = [
965-
KEvent::new(fd as _, libc::EVFILT_WRITE, flags, 0, 0, 0),
966-
KEvent::new(fd as _, libc::EVFILT_READ, flags, 0, 0, 0),
1037+
libc::kevent {
1038+
ident: fd as _,
1039+
filter: libc::EVFILT_READ,
1040+
flags: flags,
1041+
fflags: 0,
1042+
data: 0,
1043+
udata: 0 as _,
1044+
},
1045+
libc::kevent {
1046+
ident: fd as _,
1047+
filter: libc::EVFILT_WRITE,
1048+
flags: flags,
1049+
fflags: 0,
1050+
data: 0,
1051+
udata: 0 as _,
1052+
},
9671053
];
9681054
let mut eventlist = changelist;
969-
kevent_ts(self.kqueue_fd, &changelist, &mut eventlist, None)?;
1055+
syscall!(kevent(
1056+
self.kqueue_fd,
1057+
changelist.as_ptr() as *const libc::kevent,
1058+
changelist.len() as _,
1059+
eventlist.as_mut_ptr() as *mut libc::kevent,
1060+
eventlist.len() as _,
1061+
ptr::null(),
1062+
))?;
9701063
for ev in &eventlist {
971-
let (flags, data) = (ev.flags(), ev.data());
972-
if (flags & libc::EV_ERROR == 1) && data != 0 && data != libc::ENOENT as _ {
973-
return Err(io::Error::from_raw_os_error(data as _));
1064+
if (ev.flags & libc::EV_ERROR) != 0 && ev.data != 0 && ev.data != libc::ENOENT as _
1065+
{
1066+
return Err(io::Error::from_raw_os_error(ev.data as _));
9741067
}
9751068
}
9761069
Ok(())
@@ -980,7 +1073,20 @@ mod sys {
9801073
tv_sec: t.as_secs() as libc::time_t,
9811074
tv_nsec: t.subsec_nanos() as libc::c_long,
9821075
});
983-
events.len = kevent_ts(self.kqueue_fd, &[], &mut events.list, timeout)?;
1076+
let changelist = [];
1077+
let eventlist = &mut events.list;
1078+
let res = syscall!(kevent(
1079+
self.kqueue_fd,
1080+
changelist.as_ptr() as *const libc::kevent,
1081+
changelist.len() as _,
1082+
eventlist.as_mut_ptr() as *mut libc::kevent,
1083+
eventlist.len() as _,
1084+
match &timeout {
1085+
None => ptr::null(),
1086+
Some(t) => t,
1087+
}
1088+
))?;
1089+
events.len = res as usize;
9841090

9851091
while (&self.read_stream).read(&mut [0; 64]).is_ok() {}
9861092
self.reregister(self.read_stream.as_raw_fd(), !0, true, false)?;
@@ -994,13 +1100,19 @@ mod sys {
9941100
}
9951101

9961102
pub struct Events {
997-
list: Box<[KEvent]>,
1103+
list: Box<[libc::kevent]>,
9981104
len: usize,
9991105
}
10001106
impl Events {
10011107
pub fn new() -> Events {
1002-
let flags = 0;
1003-
let event = KEvent::new(0, 0, flags, 0, 0, 0);
1108+
let event = libc::kevent {
1109+
ident: 0 as _,
1110+
filter: 0,
1111+
flags: 0,
1112+
fflags: 0,
1113+
data: 0,
1114+
udata: 0 as _,
1115+
};
10041116
let list = vec![event; 1000].into_boxed_slice();
10051117
let len = 0;
10061118
Events { list, len }
@@ -1011,13 +1123,14 @@ mod sys {
10111123
//
10121124
// https://github.com/golang/go/commit/23aad448b1e3f7c3b4ba2af90120bde91ac865b4
10131125
self.list[..self.len].iter().map(|ev| Event {
1014-
readable: ev.filter() == libc::EVFILT_READ,
1015-
writable: ev.filter() == libc::EVFILT_WRITE
1016-
|| (ev.filter() == libc::EVFILT_READ && (ev.flags() & libc::EV_EOF) != 0),
1017-
key: ev.udata() as usize,
1126+
readable: ev.filter == libc::EVFILT_READ,
1127+
writable: ev.filter == libc::EVFILT_WRITE
1128+
|| (ev.filter == libc::EVFILT_READ && (ev.flags & libc::EV_EOF) != 0),
1129+
key: ev.udata as usize,
10181130
})
10191131
}
10201132
}
1133+
unsafe impl Send for Events {}
10211134
pub struct Event {
10221135
pub readable: bool,
10231136
pub writable: bool,
@@ -1031,6 +1144,7 @@ mod sys {
10311144
use std::convert::TryInto;
10321145
use std::io;
10331146
use std::os::windows::io::{AsRawSocket, RawSocket};
1147+
use std::ptr;
10341148
use std::time::Duration;
10351149

10361150
use wepoll_sys_stjepang as we;
@@ -1115,7 +1229,7 @@ mod sys {
11151229
self.handle,
11161230
we::EPOLL_CTL_DEL as libc::c_int,
11171231
sock as we::SOCKET,
1118-
0 as *mut we::epoll_event,
1232+
ptr::null_mut(),
11191233
))?;
11201234
Ok(())
11211235
}
@@ -1148,7 +1262,7 @@ mod sys {
11481262
self.handle as winapi::um::winnt::HANDLE,
11491263
0,
11501264
0,
1151-
0 as *mut _,
1265+
ptr::null_mut(),
11521266
);
11531267
}
11541268
Ok(())

0 commit comments

Comments
 (0)