From 869eb160bde8f77baaae9af90eca512ec3995f2c Mon Sep 17 00:00:00 2001 From: Jeremy Soller <jeremy@system76.com> Date: Sun, 25 Nov 2018 13:04:38 -0700 Subject: [PATCH] Add poll --- src/header/mod.rs | 1 + src/header/poll/cbindgen.toml | 7 ++ src/header/poll/mod.rs | 22 ++++++ src/header/pwd/mod.rs | 6 +- src/lib.rs | 1 + src/platform/linux/mod.rs | 5 ++ src/platform/pal/mod.rs | 4 + src/platform/redox/mod.rs | 133 ++++++++++++++++++++++++++++++++-- 8 files changed, 169 insertions(+), 10 deletions(-) create mode 100644 src/header/poll/cbindgen.toml create mode 100644 src/header/poll/mod.rs diff --git a/src/header/mod.rs b/src/header/mod.rs index aed7c6580..e02ccd3ef 100644 --- a/src/header/mod.rs +++ b/src/header/mod.rs @@ -16,6 +16,7 @@ pub mod limits; pub mod locale; pub mod netdb; pub mod netinet_in; +pub mod poll; //pub mod pthread; pub mod pwd; pub mod regex; diff --git a/src/header/poll/cbindgen.toml b/src/header/poll/cbindgen.toml new file mode 100644 index 000000000..4d3ce0250 --- /dev/null +++ b/src/header/poll/cbindgen.toml @@ -0,0 +1,7 @@ +sys_includes = [] +include_guard = "_POLL_H" +language = "C" +style = "Tag" + +[enum] +prefix_with_name = true diff --git a/src/header/poll/mod.rs b/src/header/poll/mod.rs new file mode 100644 index 000000000..fab03b382 --- /dev/null +++ b/src/header/poll/mod.rs @@ -0,0 +1,22 @@ +//! poll implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/poll.h.html + +use platform::types::*; +use platform::{Pal, Sys}; + +pub const POLLIN: c_short = 0x001; +pub const POLLPRI: c_short = 0x002; +pub const POLLOUT: c_short = 0x004; + +pub type nfds_t = c_ulong; + +#[repr(C)] +pub struct pollfd { + pub fd: c_int, + pub events: c_short, + pub revents: c_short, +} + +#[no_mangle] +pub extern "C" fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: c_int) -> c_int { + Sys::poll(fds, nfds, timeout) +} diff --git a/src/header/pwd/mod.rs b/src/header/pwd/mod.rs index 7157c0f29..efdcd1d15 100644 --- a/src/header/pwd/mod.rs +++ b/src/header/pwd/mod.rs @@ -2,7 +2,6 @@ use core::ptr; -use c_str::CStr; use fs::File; use header::{errno, fcntl}; use io::{BufRead, BufReader}; @@ -56,10 +55,7 @@ where // TODO F: FnMut(impl Iterator<Item = &[u8]>) -> bool F: FnMut(&[&[u8]]) -> bool, { - let file = match File::open( - unsafe { CStr::from_bytes_with_nul_unchecked(b"/etc/passwd\0") }, - fcntl::O_RDONLY, - ) { + let file = match File::open(c_str!("/etc/passwd"), fcntl::O_RDONLY) { Ok(file) => file, Err(_) => return OptionPasswd::Error, }; diff --git a/src/lib.rs b/src/lib.rs index 33f107ace..95cfc0adb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,7 @@ #![feature(global_asm)] #![feature(lang_items)] #![feature(linkage)] +#![feature(stmt_expr_attributes)] #![feature(str_internals)] #![feature(thread_local)] diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 98e3f310b..3c221b2c4 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -8,6 +8,7 @@ use fs::File; use header::dirent::dirent; use header::errno::EINVAL; use header::fcntl; +use header::poll::{nfds_t, pollfd}; use header::signal::SIGCHLD; use header::sys_ioctl::{winsize, TCGETS, TCSETS, TIOCGWINSZ}; // use header::sys_resource::rusage; @@ -296,6 +297,10 @@ impl Pal for Sys { e(unsafe { syscall!(PIPE2, fildes.as_mut_ptr(), 0) }) as c_int } + fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: c_int) -> c_int { + e(unsafe { syscall!(POLL, fds, nfds, timeout) }) as c_int + } + fn read(fildes: c_int, buf: &mut [u8]) -> ssize_t { e(unsafe { syscall!(READ, fildes, buf.as_mut_ptr(), buf.len()) }) as ssize_t } diff --git a/src/platform/pal/mod.rs b/src/platform/pal/mod.rs index 0866f1f4f..217ff46d5 100644 --- a/src/platform/pal/mod.rs +++ b/src/platform/pal/mod.rs @@ -1,6 +1,7 @@ use super::types::*; use c_str::CStr; use header::dirent::dirent; +use header::poll::{nfds_t, pollfd}; use header::sys_select::fd_set; use header::sys_stat::stat; use header::sys_time::{timeval, timezone}; @@ -110,6 +111,8 @@ pub trait Pal { fn pipe(fildes: &mut [c_int]) -> c_int; + fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: c_int) -> c_int; + fn read(fildes: c_int, buf: &mut [u8]) -> ssize_t; //fn readlink(pathname: &CStr, out: &mut [u8]) -> ssize_t; @@ -120,6 +123,7 @@ pub trait Pal { fn rmdir(path: &CStr) -> c_int; + //TODO: Deprecate in favor of poll fn select( nfds: c_int, readfds: *mut fd_set, diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 320a73f5d..3750178c9 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -15,9 +15,7 @@ use fs::File; use header::dirent::dirent; use header::errno::{EINVAL, EIO, EPERM}; use header::fcntl; -use io::prelude::*; -use io::{self, BufReader, SeekFrom}; -const MAP_ANON: c_int = 1; +use header::poll::{self, nfds_t, pollfd}; use header::sys_select::fd_set; use header::sys_stat::stat; use header::sys_time::{timeval, timezone}; @@ -25,6 +23,8 @@ use header::sys_utsname::{utsname, UTSLENGTH}; use header::termios::termios; use header::time::timespec; use header::unistd::{F_OK, R_OK, SEEK_SET, W_OK, X_OK}; +use io::prelude::*; +use io::{self, BufReader, SeekFrom}; use super::types::*; use super::{errno, Pal, Read}; @@ -32,6 +32,8 @@ use super::{errno, Pal, Read}; mod signal; mod socket; +const MAP_ANON: c_int = 1; + static ANONYMOUS_MAPS: Once<Mutex<BTreeMap<usize, usize>>> = Once::new(); fn anonymous_maps() -> MutexGuard<'static, BTreeMap<usize, usize>> { @@ -705,6 +707,127 @@ 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; + } + + 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 + } + fn read(fd: c_int, buf: &mut [u8]) -> ssize_t { e(syscall::read(fd as usize, buf)) as ssize_t } @@ -756,7 +879,7 @@ impl Pal for Sys { let mut exceptfds = unsafe { exceptfds.as_mut() }.map(|s| BitSet::from_ref(&mut s.fds_bits)); - let event_path = unsafe { CStr::from_bytes_with_nul_unchecked(b"event:\0") }; + 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, @@ -933,7 +1056,7 @@ impl Pal for Sys { fn uname(utsname: *mut utsname) -> c_int { fn inner(utsname: *mut utsname) -> CoreResult<(), i32> { - let file_path = unsafe { CStr::from_bytes_with_nul_unchecked(b"sys:uname\0") }; + let file_path = c_str!("sys:uname\0"); let mut file = match File::open(file_path, fcntl::O_RDONLY | fcntl::O_CLOEXEC) { Ok(file) => file, Err(_) => return Err(EIO), -- GitLab