use crate::convert_res;
use alloc::vec::Vec;
use errno::{set_errno, Errno};
use libc::c_int;
use rustix::buffer::spare_capacity;
use rustix::event::epoll::{add, delete, modify, CreateFlags, Event, EventData, EventFlags};
use rustix::fd::{BorrowedFd, IntoRawFd};
#[no_mangle]
unsafe extern "C" fn epoll_create(size: c_int) -> c_int {
libc!(libc::epoll_create(size));
if size <= 0 {
set_errno(Errno(libc::EINVAL));
return -1;
}
epoll_create1(0)
}
#[no_mangle]
unsafe extern "C" fn epoll_create1(flags: c_int) -> c_int {
libc!(libc::epoll_create1(flags));
let flags = CreateFlags::from_bits(flags as _).unwrap();
match convert_res(rustix::event::epoll::create(flags)) {
Some(epoll) => epoll.into_raw_fd(),
None => -1,
}
}
#[cfg(any(target_os = "android", target_os = "linux"))]
#[no_mangle]
unsafe extern "C" fn epoll_ctl(
epfd: c_int,
op: c_int,
fd: c_int,
event: *mut libc::epoll_event,
) -> c_int {
libc!(libc::epoll_ctl(epfd, op, fd, event));
let epfd = BorrowedFd::borrow_raw(epfd);
let fd = BorrowedFd::borrow_raw(fd);
let res = match op {
libc::EPOLL_CTL_ADD => {
let libc::epoll_event { events, r#u64 } = event.read();
let events = EventFlags::from_bits(events).unwrap();
add(epfd, fd, EventData::new_u64(r#u64), events)
}
libc::EPOLL_CTL_MOD => {
let libc::epoll_event { events, r#u64 } = event.read();
let events = EventFlags::from_bits(events).unwrap();
modify(epfd, fd, EventData::new_u64(r#u64), events)
}
libc::EPOLL_CTL_DEL => delete(epfd, fd),
_ => {
set_errno(Errno(libc::EINVAL));
return -1;
}
};
match convert_res(res) {
Some(()) => 0,
None => -1,
}
}
#[no_mangle]
unsafe extern "C" fn epoll_wait(
epfd: c_int,
events: *mut libc::epoll_event,
maxevents: c_int,
timeout: c_int,
) -> c_int {
libc!(libc::epoll_wait(epfd, events, maxevents, timeout));
if maxevents <= 0 {
set_errno(Errno(libc::EINVAL));
return -1;
}
let timeout = if timeout < 0 {
None
} else {
Some(rustix::event::Timespec {
tv_sec: i64::from(timeout) / 1000,
tv_nsec: (i64::from(timeout) % 1000) * 1_000_000,
})
};
let mut events_vec = Vec::with_capacity(maxevents as usize);
match convert_res(rustix::event::epoll::wait(
BorrowedFd::borrow_raw(epfd),
spare_capacity(&mut events_vec),
timeout.as_ref(),
)) {
Some(_) => {
let mut events = events;
for Event { flags, data } in events_vec.iter().copied() {
events.write(libc::epoll_event {
events: flags.bits(),
r#u64: data.u64(),
});
events = events.add(1);
}
events_vec.len() as c_int
}
None => -1,
}
}