Files
@ 2c1fa43903ac
Branch filter:
Location: CSY/reowolf/src/runtime2/poll/mod.rs
2c1fa43903ac
3.1 KiB
application/rls-services+xml
Several unfinished attempts at introducing polling
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | use libc::{self, c_int};
use std::{io, ptr, time};
pub(crate) type FileDescriptor = c_int;
pub(crate) trait AsFileDescriptor {
fn as_file_descriptor(&self) -> FileDescriptor;
}
pub(crate) struct UserData(u64);
#[inline]
pub(crate) fn register_polling<F: AsFileDescriptor>(
poller: &Poller, entity: F, user: UserData, read: bool, write: bool
) -> io::Result<()> {
let file_descriptor = entity.as_file_descriptor();
return poller.register(file_descriptor, user, read, write);
}
#[inline]
pub(crate) fn unregister_polling<F: AsFileDescriptor>(
poller: &Poller, entity: F
) -> io::Result<()> {
let file_descriptor = entity.as_file_descriptor();
return poller.unregister(file_descriptor);
}
#[cfg(unix)]
pub(crate) struct Poller {
handle: c_int,
events: Vec<libc::epoll_event>
}
// All of this is gleaned from the `mio` crate.
#[cfg(unix)]
impl Poller {
pub fn new(event_capacity: usize) -> io::Result<Self> {
assert!(event_capacity < i32::MAX as usize); // because of argument to `epoll_wait`.
let handle = syscall_result(unsafe{ libc::epoll_create1(libc::EPOLL_CLOEXEC) })?;
return Ok(Self{
handle,
events: Vec::with_capacity(event_capacity),
})
}
fn register(&self, fd: FileDescriptor, user: UserData, read: bool, write: bool) -> io::Result<()> {
let mut event = libc::epoll_event{
events: Self::events_from_rw_flags(read, write),
u64: user.0,
};
syscall_result(unsafe{
libc::epoll_ctl(self.handle, libc::EPOLL_CTL_ADD, fd, &mut event)
})?;
return Ok(());
}
fn unregister(&self, fd: FileDescriptor) -> io::Result<()> {
syscall_result(unsafe{
libc::epoll_ctl(self.handle, libc::EPOLL_CTL_DEL, fd, ptr::null_mut())
})?;
return Ok(());
}
pub fn wait(&mut self, timeout: time::Duration) -> io::Result<()> {
// See `mio` for the reason. Works around a linux bug
#[cfg(target_pointer_width = "32")]
const MAX_TIMEOUT: u128 = 1789569;
#[cfg(not(target_pointer_width = "32"))]
const MAX_TIMEOUT: u128 = c_int::MAX as u128;
let mut timeout_millis = timeout.as_millis();
if timeout_millis > MAX_TIMEOUT {
timeout_millis = -1; // effectively infinite
}
let num_events = syscall_result(unsafe{
libc::epoll_wait(self.handle, self.events.as_mut(), self.events.capacity() as i32, timeout_millis)
})?;
unsafe{
debug_assert!(num_events >= 0);
self.events.set_len(num_events as usize);
}
return Ok(());
}
fn events_from_rw_flags(read: bool, write: bool) -> u32 {
let mut events = libc::EPOLLET;
if read {
events |= libc::EPOLLIN | libc::EPOLLRDHUP;
}
if write {
events |= libc::EPOLLOUT;
}
return events as u32;
}
}
#[inline]
fn syscall_result(result: c_int) -> io::Result<c_int> {
if result < 0 {
return Err(io::Error::last_os_error());
} else {
return Ok(result);
}
}
#[cfg(not(unix))]
struct Poller {
}
|