Files @ 2c1fa43903ac
Branch filter:

Location: CSY/reowolf/src/runtime2/poll/mod.rs - annotation

2c1fa43903ac 3.1 KiB application/rls-services+xml Show Source Show as Raw Download as Raw
MH
Several unfinished attempts at introducing polling
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
2c1fa43903ac
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 {

}