use sc::syscall;
use crate::platform::{EpollEvent, EpollOp, Fd};
use crate::Result;
#[inline]
pub fn epoll_create(cloexec: bool) -> Result<Fd> {
let flags = if cloexec {
linux_rust_bindings::epoll::EPOLL_CLOEXEC
} else {
0
};
let res = unsafe { syscall!(EPOLL_CREATE1, flags) };
Fd::coerce_from_register(res, "`EPOLL_CREATE1` syscall failed")
}
#[inline]
pub fn epoll_ctl(epoll_fd: Fd, epoll_op: EpollOp, fd: Fd, event: &EpollEvent) -> Result<()> {
let evt_addr = core::ptr::addr_of!(event.0);
let res = unsafe { syscall!(EPOLL_CTL, epoll_fd.0, epoll_op.into_op(), fd.0, evt_addr) };
bail_on_below_zero!(res, "`EPOLL_CTL` syscall failed");
Ok(())
}
#[inline]
pub fn epoll_del(epoll_fd: Fd, fd: Fd) -> Result<()> {
let res = unsafe { syscall!(EPOLL_CTL, epoll_fd.0, EpollOp::Del.into_op(), fd.0, 0) };
bail_on_below_zero!(res, "`EPOLL_CTL` syscall failed");
Ok(())
}
#[inline]
pub fn epoll_wait(epoll_fd: Fd, events: &mut [EpollEvent], timeout_millis: i32) -> Result<usize> {
let res = unsafe {
syscall!(
EPOLL_PWAIT,
epoll_fd.0,
events.as_mut_ptr(),
events.len(),
timeout_millis,
0,
0
)
};
bail_on_below_zero!(res, "`EPOLL_PWAIT` syscall failed");
Ok(res)
}
#[cfg(test)]
mod test {
use crate::platform::{EpollEvent, EpollEventMask, EpollOp, STDOUT};
use crate::select::{epoll_create, epoll_ctl, epoll_wait};
#[test]
fn can_setup_wait() {
let epoll_fd = epoll_create(true).unwrap();
epoll_ctl(
epoll_fd,
EpollOp::Add,
STDOUT,
&EpollEvent::new(15, EpollEventMask::EPOLLIN | EpollEventMask::EPOLLOUT),
)
.unwrap();
let mut ret = [EpollEvent::new(0, EpollEventMask::empty())];
let ready = epoll_wait(epoll_fd, &mut ret, 10).unwrap();
assert_eq!(1, ready);
assert_eq!(15, ret[0].get_data());
assert_eq!(EpollEventMask::EPOLLOUT, ret[0].get_events());
}
}