Files
RedBear-OS/src/header/poll/mod.rs
T

118 lines
2.6 KiB
Rust

//! poll implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/poll.h.html
use core::{mem, slice};
use fs::File;
use header::sys_epoll::{
epoll_create1, EPOLL_CLOEXEC,
epoll_ctl, EPOLL_CTL_ADD,
epoll_wait,
EPOLLIN, EPOLLPRI, EPOLLOUT, EPOLLERR, EPOLLHUP, EPOLLNVAL,
epoll_data, epoll_event
};
use platform::types::*;
pub const POLLIN: c_short = 0x001;
pub const POLLPRI: c_short = 0x002;
pub const POLLOUT: c_short = 0x004;
pub const POLLERR: c_short = 0x008;
pub const POLLHUP: c_short = 0x010;
pub const POLLNVAL: c_short = 0x020;
pub type nfds_t = c_ulong;
#[repr(C)]
pub struct pollfd {
pub fd: c_int,
pub events: c_short,
pub revents: c_short,
}
pub fn poll_epoll(fds: &mut [pollfd], timeout: c_int) -> c_int {
let event_map = [
(POLLIN, EPOLLIN),
(POLLPRI, EPOLLPRI),
(POLLOUT, EPOLLOUT),
(POLLERR, EPOLLERR),
(POLLHUP, EPOLLHUP),
(POLLNVAL, EPOLLNVAL)
];
let ep = {
let epfd = epoll_create1(EPOLL_CLOEXEC);
if epfd < 0 {
return -1;
}
File::new(epfd)
};
for i in 0..fds.len() {
let mut pfd = &mut fds[i];
let mut event = epoll_event {
events: 0,
data: epoll_data {
u64: i as u64,
},
};
for (p, ep) in event_map.iter() {
if pfd.events & p > 0 {
event.events |= ep;
}
}
pfd.revents = 0;
if epoll_ctl(*ep, EPOLL_CTL_ADD, pfd.fd, &mut event) < 0 {
return -1;
}
}
let mut events: [epoll_event; 32] = unsafe { mem::zeroed() };
let res = epoll_wait(
*ep,
events.as_mut_ptr(),
events.len() as c_int,
timeout
);
if res < 0 {
return -1;
}
for i in 0..res as usize {
let event = &events[i];
let pi = unsafe { event.data.u64 as usize };
// TODO: Error status when fd does not match?
if let Some(pfd) = fds.get_mut(pi) {
for (p, ep) in event_map.iter() {
if event.events & ep > 0 {
pfd.revents |= p;
}
}
}
}
let mut count = 0;
for pfd in fds.iter() {
if pfd.revents > 0 {
count += 1;
}
}
count
}
#[no_mangle]
pub unsafe extern "C" fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: c_int) -> c_int {
trace_expr!(
poll_epoll(
slice::from_raw_parts_mut(fds, nfds as usize),
timeout
),
"poll({:p}, {}, {})",
fds,
nfds,
timeout
)
}