diff --git a/src/header/sys_epoll/linux.rs b/src/header/sys_epoll/linux.rs index af4972e7006f0365147d6c408ae6a27e53c3ebf7..654d4ff5cea04ac946b47da3ca6485f0d4ac5d9c 100644 --- a/src/header/sys_epoll/linux.rs +++ b/src/header/sys_epoll/linux.rs @@ -1,3 +1,20 @@ use platform::types::*; pub const EPOLL_CLOEXEC: c_int = 0x8_0000; + +pub const EPOLLIN: c_uint = 0x001; +pub const EPOLLPRI: c_uint = 0x002; +pub const EPOLLOUT: c_uint = 0x004; +pub const EPOLLRDNORM: c_uint = 0x040; +pub const EPOLLNVAL: c_uint = 0x020; +pub const EPOLLRDBAND: c_uint = 0x080; +pub const EPOLLWRNORM: c_uint = 0x100; +pub const EPOLLWRBAND: c_uint = 0x200; +pub const EPOLLMSG: c_uint = 0x400; +pub const EPOLLERR: c_uint = 0x008; +pub const EPOLLHUP: c_uint = 0x010; +pub const EPOLLRDHUP: c_uint = 0x2000; +pub const EPOLLEXCLUSIVE: c_uint = 1 << 28; +pub const EPOLLWAKEUP: c_uint = 1 << 29; +pub const EPOLLONESHOT: c_uint = 1 << 30; +pub const EPOLLET: c_uint = 1 << 31; diff --git a/src/header/sys_epoll/mod.rs b/src/header/sys_epoll/mod.rs index 06893bc0aa45d61fee2ebfe8ed7bf0b852fa85d3..cdde02441d5616acee0a8b26d4a1ca5cffb0e187 100644 --- a/src/header/sys_epoll/mod.rs +++ b/src/header/sys_epoll/mod.rs @@ -20,31 +20,32 @@ pub const EPOLL_CTL_ADD: c_int = 1; pub const EPOLL_CTL_DEL: c_int = 2; pub const EPOLL_CTL_MOD: c_int = 3; -pub const EPOLLIN: u32 = 0x0001; -pub const EPOLLPRI: u32 = 0x0002; -pub const EPOLLOUT: u32 = 0x0004; -pub const EPOLLERR: u32 = 0x0008; -pub const EPOLLHUP: u32 = 0x0010; -pub const EPOLLNVAL: u32 = 0x0020; -pub const EPOLLRDNORM: u32 = 0x0040; -pub const EPOLLRDBAND: u32 = 0x0080; -pub const EPOLLWRNORM: u32 = 0x0100; -pub const EPOLLWRBAND: u32 = 0x0200; -pub const EPOLLMSG: u32 = 0x0400; -pub const EPOLLRDHUP: u32 = 0x2000; - #[repr(C)] +#[derive(Clone, Copy)] pub union epoll_data { pub ptr: *mut c_void, pub fd: c_int, pub u32: u32, pub u64: u64, } +impl Default for epoll_data { + fn default() -> Self { + Self { u64: 0 } + } +} #[repr(C)] +#[derive(Clone, Copy, Default)] +// This will match in size with syscall::Event (24 bytes on 64-bit +// systems) on redox. The `Default` trait is here so we don't need to +// worry about the padding when using this type. pub struct epoll_event { - pub events: u32, - pub data: epoll_data, + pub events: u32, // 4 bytes + // 4 automatic alignment bytes + pub data: epoll_data, // 8 bytes + + #[cfg(target_os = "redox")] + pub _pad: u64, // 8 bytes } #[no_mangle] diff --git a/src/header/sys_epoll/redox.rs b/src/header/sys_epoll/redox.rs index 870f7f9d9f9c4864ca6fb158276313c8397c8bb7..d1172fbb35e4c5745e0f21f78e87cc73e958596c 100644 --- a/src/header/sys_epoll/redox.rs +++ b/src/header/sys_epoll/redox.rs @@ -1,3 +1,20 @@ use platform::types::*; pub const EPOLL_CLOEXEC: c_int = 0x0100_0000; + +pub const EPOLLIN: c_uint = 1; +pub const EPOLLPRI: c_uint = 0; +pub const EPOLLOUT: c_uint = 2; +pub const EPOLLRDNORM: c_uint = 0; +pub const EPOLLNVAL: c_uint = 0; +pub const EPOLLRDBAND: c_uint = 0; +pub const EPOLLWRNORM: c_uint = 0; +pub const EPOLLWRBAND: c_uint = 0; +pub const EPOLLMSG: c_uint = 0; +pub const EPOLLERR: c_uint = 0; +pub const EPOLLHUP: c_uint = 0; +pub const EPOLLRDHUP: c_uint = 0; +pub const EPOLLEXCLUSIVE: c_uint = 0; +pub const EPOLLWAKEUP: c_uint = 0; +pub const EPOLLONESHOT: c_uint = 0; +pub const EPOLLET: c_uint = 0; diff --git a/src/platform/redox/epoll.rs b/src/platform/redox/epoll.rs new file mode 100644 index 0000000000000000000000000000000000000000..03e3f591a8a1e13e44124f8e04341a9c54b0ee36 --- /dev/null +++ b/src/platform/redox/epoll.rs @@ -0,0 +1,91 @@ +use super::super::types::*; +use super::super::{Pal, PalEpoll}; +use super::Sys; + +use c_str::CStr; +use core::{mem, slice}; +use fs::File; +use io::prelude::*; +use header::errno::*; +use header::fcntl::*; +use header::signal::sigset_t; +use header::sys_epoll::*; +use syscall::data::{Event, TimeSpec}; +use syscall::flag::EVENT_READ; + +impl PalEpoll for Sys { + fn epoll_create1(flags: c_int) -> c_int { + Sys::open( + CStr::from_bytes_with_nul(b"event:\0").unwrap(), + O_RDWR | flags, + 0 + ) + } + + fn epoll_ctl(epfd: c_int, op: c_int, fd: c_int, event: *mut epoll_event) -> c_int { + Sys::write(epfd, &Event { + id: fd as usize, + flags: unsafe { (*event).events as usize }, + + // NOTE: Danger when using non 64-bit systems. If this is + // needed, use a box or something + data: unsafe { mem::transmute((*event).data) } + }) as c_int + } + + fn epoll_pwait(epfd: c_int, mut events: *mut epoll_event, maxevents: c_int, timeout: c_int, _sigset: *const sigset_t) -> c_int { + // TODO: sigset + + let _timer; + if timeout != -1 { + _timer = File::open(CStr::from_bytes_with_nul(b"time:\0").unwrap(), O_RDWR); + match _timer { + Err(_) => return -1, + Ok(mut timer) => { + let mut time = TimeSpec::default(); + if let Err(err) = timer.read(&mut time) { + return -1; + } + time.tv_nsec += timeout; + if let Err(err) = timer.write(&time) { + return -1; + } + + if Sys::write(epfd, &Event { + id: timer.fd as usize, + flags: EVENT_READ, + data: 0 + }) == -1 { + return -1; + } + } + } + } + + let bytes_read = Sys::read(epfd, unsafe { slice::from_raw_parts_mut( + events as *mut u8, + maxevents as usize + ) }); + if bytes_read == -1 { + return -1; + } + let read = bytes_read as usize / mem::size_of::<Event>(); + + for i in 0..maxevents { + unsafe { + let event = *(events as *mut Event); + if event.data == 0 { + return EINTR; + } + *events = epoll_event { + events: event.flags as _, + data: mem::transmute(event.data), + ..Default::default() + }; + events = events.add(mem::size_of::<epoll_event>()); + } + } + + read as c_int + } +} diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index b3293534f75d85a6d4a31d486643de1164195348..9da86dd9d9441c73abb508f877e5fdf484f26549 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -1,6 +1,5 @@ //! sys/socket implementation, following http://pubs.opengroup.org/onlinepubs/009696699/basedefs/sys/socket.h.html -use cbitset::BitSet; use core::result::Result as CoreResult; use core::{mem, ptr, slice}; use syscall::data::Map; @@ -27,6 +26,7 @@ use io::{self, BufReader, SeekFrom}; use super::types::*; use super::{errno, Pal, Read}; +mod epoll; mod extra; mod signal; mod socket; @@ -679,7 +679,7 @@ impl Pal for Sys { )) as c_int } - fn pipe(fds: &mut [c_int], flags: c_int) -> c_int { + fn pipe2(fds: &mut [c_int], flags: c_int) -> c_int { let mut usize_fds: [usize; 2] = [0; 2]; let res = e(syscall::pipe2(&mut usize_fds, flags as usize)); fds[0] = usize_fds[0] as c_int; @@ -687,135 +687,6 @@ impl Pal for Sys { res as c_int } - fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: c_int) -> c_int { - let fds = unsafe { slice::from_raw_parts_mut(fds, nfds as usize) }; - - let event_path = c_str!("event:"); - let mut event_file = match File::open(event_path, fcntl::O_RDWR | fcntl::O_CLOEXEC) { - Ok(file) => file, - Err(_) => return -1, - }; - - for fd in fds.iter_mut() { - let mut flags = 0; - - if fd.events & poll::POLLIN > 0 { - flags |= syscall::EVENT_READ; - } - - if fd.events & poll::POLLOUT > 0 { - flags |= syscall::EVENT_WRITE; - } - - fd.revents = 0; - - if fd.fd >= 0 && flags > 0 { - if event_file - .write(&syscall::Event { - id: fd.fd as usize, - flags: flags, - data: 0, - }) - .is_err() - { - return -1; - } - } - } - - const TIMEOUT_TOKEN: usize = 1; - - let timeout_file = if timeout < 0 { - None - } else { - let timeout_path = unsafe { - CString::from_vec_unchecked( - format!("time:{}", syscall::CLOCK_MONOTONIC).into_bytes(), - ) - }; - let mut timeout_file = match File::open(&timeout_path, fcntl::O_RDWR | fcntl::O_CLOEXEC) - { - Ok(file) => file, - Err(_) => return -1, - }; - - if event_file - .write(&syscall::Event { - id: *timeout_file as usize, - flags: syscall::EVENT_READ, - data: TIMEOUT_TOKEN, - }) - .is_err() - { - return -1; - } - - let mut time = syscall::TimeSpec::default(); - if timeout_file.read(&mut time).is_err() { - return -1; - } - - time.tv_nsec += timeout * 1000000; - while time.tv_nsec >= 1000000000 { - time.tv_sec += 1; - time.tv_nsec -= 1000000000; - } - - // Teehee - if timeout == 0 { - time.tv_sec += 1; - } - - if timeout_file.write(&time).is_err() { - return -1; - } - - Some(timeout_file) - }; - - let mut events = [syscall::Event::default(); 32]; - let read = { - let mut events = unsafe { - slice::from_raw_parts_mut( - &mut events as *mut _ as *mut u8, - mem::size_of::<syscall::Event>() * events.len(), - ) - }; - match event_file.read(&mut events) { - Ok(i) => i / mem::size_of::<syscall::Event>(), - Err(_) => return -1, - } - }; - - for event in &events[..read] { - if event.data == TIMEOUT_TOKEN { - continue; - } - - for fd in fds.iter_mut() { - if event.id == fd.fd as usize { - if event.flags & syscall::EVENT_READ > 0 { - fd.revents |= poll::POLLIN; - } - - if event.flags & syscall::EVENT_WRITE > 0 { - fd.revents |= poll::POLLOUT; - } - } - } - } - - let mut total = 0; - - for fd in fds.iter_mut() { - if fd.revents > 0 { - total += 1; - } - } - - total - } - #[cfg(target_arch = "x86_64")] unsafe fn pte_clone(stack: *mut usize) -> pid_t { let flags = syscall::CLONE_VM