diff --git a/src/header/fcntl/linux.rs b/src/header/fcntl/linux.rs index 9e3a7a516724fb66498a6ec1ceb9b9abc090bd42..ae1bcc97e589f73c9704cb996f8f473b24b8bd3f 100644 --- a/src/header/fcntl/linux.rs +++ b/src/header/fcntl/linux.rs @@ -13,3 +13,5 @@ pub const O_DIRECTORY: c_int = 0x1_0000; pub const O_NOFOLLOW: c_int = 0x2_0000; pub const O_CLOEXEC: c_int = 0x8_0000; pub const O_PATH: c_int = 0x20_0000; + +pub const FD_CLOEXEC: c_int = 0x8_0000; diff --git a/src/header/fcntl/mod.rs b/src/header/fcntl/mod.rs index c2178c4eb79c5e8e8943210cfc4a0a7ca5f8921b..1946c6bebb8e2887596ad706e2e070b984807774 100644 --- a/src/header/fcntl/mod.rs +++ b/src/header/fcntl/mod.rs @@ -23,8 +23,6 @@ pub const F_GETLK: c_int = 5; pub const F_SETLK: c_int = 6; pub const F_SETLKW: c_int = 7; -pub const FD_CLOEXEC: c_int = 0x0100_0000; - pub const F_RDLCK: c_int = 0; pub const F_WRLCK: c_int = 1; pub const F_UNLCK: c_int = 2; diff --git a/src/header/fcntl/redox.rs b/src/header/fcntl/redox.rs index 7bc92a00a63b783b82d0e99d66343c9e0eb2f845..2f32784093cba72bea2b4cbfc7156e0ead80f01c 100644 --- a/src/header/fcntl/redox.rs +++ b/src/header/fcntl/redox.rs @@ -20,3 +20,5 @@ pub const O_SYMLINK: c_int = 0x4000_0000; // Negative to allow it to be used as int // TODO: Fix negative values missing from includes pub const O_NOFOLLOW: c_int = -0x8000_0000; + +pub const FD_CLOEXEC: c_int = 0x0100_0000; diff --git a/src/header/mod.rs b/src/header/mod.rs index a03a7b9701026eefbc0985a114e0b3040d6bcadb..e11ffb4c14a15fda97e3233692f0f8dc65357ec5 100644 --- a/src/header/mod.rs +++ b/src/header/mod.rs @@ -33,6 +33,7 @@ pub mod stdlib; pub mod string; pub mod strings; pub mod sys_auxv; +pub mod sys_epoll; pub mod sys_file; pub mod sys_ioctl; pub mod sys_mman; diff --git a/src/header/poll/mod.rs b/src/header/poll/mod.rs index 08bb87ab232608f9555ed567ba807587cb434ad6..4d6f9e41e4a83fc1fbb7c61280c74df982a4a9d4 100644 --- a/src/header/poll/mod.rs +++ b/src/header/poll/mod.rs @@ -1,7 +1,16 @@ //! 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::*; -use platform::{Pal, Sys}; pub const POLLIN: c_short = 0x001; pub const POLLPRI: c_short = 0x002; @@ -19,10 +28,87 @@ pub struct pollfd { 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 extern "C" fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: c_int) -> c_int { +pub unsafe extern "C" fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: c_int) -> c_int { trace_expr!( - Sys::poll(fds, nfds, timeout), + poll_epoll( + slice::from_raw_parts_mut(fds, nfds as usize), + timeout + ), "poll({:p}, {}, {})", fds, nfds, diff --git a/src/header/sys_epoll/cbindgen.toml b/src/header/sys_epoll/cbindgen.toml new file mode 100644 index 0000000000000000000000000000000000000000..e162dbb4f6ce185318d8a0e8d9e9e35a0907fe7f --- /dev/null +++ b/src/header/sys_epoll/cbindgen.toml @@ -0,0 +1,11 @@ +sys_includes = [] +include_guard = "_SYS_EPOLL_H" +language = "C" +style = "Tag" + +[defines] +"target_os=linux" = "__linux__" +"target_os=redox" = "__redox__" + +[enum] +prefix_with_name = true diff --git a/src/header/sys_epoll/linux.rs b/src/header/sys_epoll/linux.rs new file mode 100644 index 0000000000000000000000000000000000000000..af4972e7006f0365147d6c408ae6a27e53c3ebf7 --- /dev/null +++ b/src/header/sys_epoll/linux.rs @@ -0,0 +1,3 @@ +use platform::types::*; + +pub const EPOLL_CLOEXEC: c_int = 0x8_0000; diff --git a/src/header/sys_epoll/mod.rs b/src/header/sys_epoll/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..06893bc0aa45d61fee2ebfe8ed7bf0b852fa85d3 --- /dev/null +++ b/src/header/sys_epoll/mod.rs @@ -0,0 +1,92 @@ +//! sys/epoll.h implementation for Redox, following http://man7.org/linux/man-pages/man7/epoll.7.html + +use core::ptr; + +use header::signal::sigset_t; +use platform::{PalEpoll, Sys}; +use platform::types::*; + +pub use self::sys::*; + +#[cfg(target_os = "linux")] +#[path = "linux.rs"] +pub mod sys; + +#[cfg(target_os = "redox")] +#[path = "redox.rs"] +pub mod sys; + +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)] +pub union epoll_data { + pub ptr: *mut c_void, + pub fd: c_int, + pub u32: u32, + pub u64: u64, +} + +#[repr(C)] +pub struct epoll_event { + pub events: u32, + pub data: epoll_data, +} + +#[no_mangle] +pub extern "C" fn epoll_create(_size: c_int) -> c_int { + epoll_create1(0) +} + +#[no_mangle] +pub extern "C" fn epoll_create1(flags: c_int) -> c_int { + trace_expr!( + Sys::epoll_create1(flags), + "epoll_create1({:#x})", + flags + ) +} + +#[no_mangle] +pub extern "C" fn epoll_ctl(epfd: c_int, op: c_int, fd: c_int, event: *mut epoll_event) -> c_int { + trace_expr!( + Sys::epoll_ctl(epfd, op, fd, event), + "epoll_ctl({}, {}, {}, {:p})", + epfd, + op, + fd, + event + ) +} + +#[no_mangle] +pub extern "C" fn epoll_wait(epfd: c_int, events: *mut epoll_event, maxevents: c_int, timeout: c_int) -> c_int { + epoll_pwait(epfd, events, maxevents, timeout, ptr::null()) +} + +#[no_mangle] +pub extern "C" fn epoll_pwait(epfd: c_int, events: *mut epoll_event, maxevents: c_int, timeout: c_int, sigmask: *const sigset_t) -> c_int { + trace_expr!( + Sys::epoll_pwait(epfd, events, maxevents, timeout, sigmask), + "epoll_pwait({}, {:p}, {}, {}, {:p})", + epfd, + events, + maxevents, + timeout, + sigmask + ) +} diff --git a/src/header/sys_epoll/redox.rs b/src/header/sys_epoll/redox.rs new file mode 100644 index 0000000000000000000000000000000000000000..870f7f9d9f9c4864ca6fb158276313c8397c8bb7 --- /dev/null +++ b/src/header/sys_epoll/redox.rs @@ -0,0 +1,3 @@ +use platform::types::*; + +pub const EPOLL_CLOEXEC: c_int = 0x0100_0000; diff --git a/src/header/sys_select/mod.rs b/src/header/sys_select/mod.rs index 6565ce402aa43eea7de212e4e8ac28c0cd19eb2f..bf77b819e1e2077a59c5e98787003affdaf56bde 100644 --- a/src/header/sys_select/mod.rs +++ b/src/header/sys_select/mod.rs @@ -1,9 +1,19 @@ //! sys/select.h implementation use core::mem; + +use fs::File; +use header::errno; +use header::sys_epoll::{ + epoll_create1, EPOLL_CLOEXEC, + epoll_ctl, EPOLL_CTL_ADD, + epoll_wait, + EPOLLIN, EPOLLOUT, EPOLLERR, + epoll_data, epoll_event +}; use header::sys_time::timeval; +use platform; use platform::types::*; -use platform::{Pal, Sys}; // fd_set is also defined in C because cbindgen is incompatible with mem::size_of booo @@ -14,8 +24,155 @@ pub struct fd_set { pub fds_bits: [c_ulong; FD_SETSIZE / (8 * mem::size_of::<c_ulong>())], } +impl fd_set { + fn index(fd: c_int) -> usize { + (fd as usize) / (8 * mem::size_of::<c_ulong>()) + } + + fn bitmask(fd: c_int) -> c_ulong { + 1 << ((fd as usize) & (8 * mem::size_of::<c_ulong>() - 1)) as c_ulong + } + + fn zero(&mut self) { + for i in 0..self.fds_bits.len() { + self.fds_bits[i] = 0; + } + } + + fn set(&mut self, fd: c_int) { + self.fds_bits[Self::index(fd)] |= Self::bitmask(fd); + } + + fn clr(&mut self, fd: c_int) { + self.fds_bits[Self::index(fd)] &= !Self::bitmask(fd); + } + + fn isset(&self, fd: c_int) -> bool { + self.fds_bits[Self::index(fd)] & Self::bitmask(fd) > 0 + } +} + +pub fn select_epoll( + nfds: c_int, + mut readfds: Option<&mut fd_set>, + mut writefds: Option<&mut fd_set>, + mut exceptfds: Option<&mut fd_set>, + timeout: Option<&mut timeval> +) -> c_int { + if nfds < 0 || nfds > FD_SETSIZE as i32 { + unsafe { platform::errno = errno::EINVAL }; + return -1; + }; + + let ep = { + let epfd = epoll_create1(EPOLL_CLOEXEC); + if epfd < 0 { + return -1; + } + File::new(epfd) + }; + + for fd in 0..nfds { + if let Some(ref fd_set) = readfds { + if fd_set.isset(fd) { + let mut event = epoll_event { + events: EPOLLIN, + data: epoll_data { + fd: fd, + }, + }; + if epoll_ctl(*ep, EPOLL_CTL_ADD, fd, &mut event) < 0 { + return -1; + } + } + } + if let Some(ref fd_set) = writefds { + if fd_set.isset(fd) { + let mut event = epoll_event { + events: EPOLLOUT, + data: epoll_data { + fd: fd, + }, + }; + if epoll_ctl(*ep, EPOLL_CTL_ADD, fd, &mut event) < 0 { + return -1; + } + } + } + if let Some(ref fd_set) = exceptfds { + if fd_set.isset(fd) { + let mut event = epoll_event { + events: EPOLLERR, + data: epoll_data { + fd: fd, + }, + }; + if epoll_ctl(*ep, EPOLL_CTL_ADD, 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, + match timeout { + Some(timeout) => { + //TODO: Check for overflow + ((timeout.tv_sec as c_int) * 1000) + + ((timeout.tv_usec as c_int) / 1000) + }, + None => -1 + } + ); + if res < 0 { + return -1; + } + + if let Some(ref mut fd_set) = readfds { + fd_set.zero(); + } + if let Some(ref mut fd_set) = writefds { + fd_set.zero(); + } + if let Some(ref mut fd_set) = exceptfds { + fd_set.zero(); + } + + let mut count = 0; + for i in 0..res as usize { + let event = &events[i]; + let fd = unsafe { event.data.fd }; + // TODO: Error status when fd does not match? + if fd >= 0 && fd <= FD_SETSIZE as c_int { + if event.events & EPOLLIN > 0 { + if let Some(ref mut fd_set) = readfds { + fd_set.set(fd); + count += 1; + } + } + if event.events & EPOLLOUT > 0 { + if let Some(ref mut fd_set) = writefds { + fd_set.set(fd); + count += 1; + } + } + if event.events & EPOLLERR > 0 { + if let Some(ref mut fd_set) = exceptfds { + fd_set.set(fd); + count += 1; + } + } + } + } + count +} + #[no_mangle] -pub extern "C" fn select( +pub unsafe extern "C" fn select( nfds: c_int, readfds: *mut fd_set, writefds: *mut fd_set, @@ -23,7 +180,29 @@ pub extern "C" fn select( timeout: *mut timeval, ) -> c_int { trace_expr!( - Sys::select(nfds, readfds, writefds, exceptfds, timeout), + select_epoll( + nfds, + if readfds.is_null() { + None + } else { + Some(&mut *readfds) + }, + if writefds.is_null() { + None + } else { + Some(&mut *writefds) + }, + if exceptfds.is_null() { + None + } else { + Some(&mut *exceptfds) + }, + if timeout.is_null() { + None + } else { + Some(&mut *timeout) + } + ), "select({}, {:p}, {:p}, {:p}, {:p})", nfds, readfds, diff --git a/src/platform/linux/epoll.rs b/src/platform/linux/epoll.rs new file mode 100644 index 0000000000000000000000000000000000000000..e83a97ab8ea02ce95580bf4ad4e96d1979fa57c1 --- /dev/null +++ b/src/platform/linux/epoll.rs @@ -0,0 +1,19 @@ +use super::super::types::*; +use super::super::PalEpoll; +use super::{e, Sys}; +use header::signal::sigset_t; +use header::sys_epoll::epoll_event; + +impl PalEpoll for Sys { + fn epoll_create1(flags: c_int) -> c_int { + unsafe { e(syscall!(EPOLL_CREATE1, flags)) as c_int } + } + + fn epoll_ctl(epfd: c_int, op: c_int, fd: c_int, event: *mut epoll_event) -> c_int { + unsafe { e(syscall!(EPOLL_CTL, epfd, op, fd, event)) as c_int } + } + + fn epoll_pwait(epfd: c_int, events: *mut epoll_event, maxevents: c_int, timeout: c_int, sigmask: *const sigset_t) -> c_int { + unsafe { e(syscall!(EPOLL_PWAIT, epfd, events, maxevents, timeout, sigmask)) as c_int } + } +} diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index fcd1f3b1388084f0251f356193f8ec8df4891388..a92776c9a5fc42b242526c595f15ef3e32410821 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -5,10 +5,8 @@ use super::types::*; use super::{errno, Pal}; use c_str::CStr; use header::dirent::dirent; -use header::poll::{nfds_t, pollfd}; use header::signal::SIGCHLD; // use header::sys_resource::rusage; -use header::sys_select::fd_set; use header::sys_stat::stat; use header::sys_statvfs::statvfs; use header::sys_time::{timeval, timezone}; @@ -16,6 +14,7 @@ use header::sys_time::{timeval, timezone}; use header::sys_utsname::utsname; use header::time::timespec; +mod epoll; mod signal; mod socket; @@ -320,10 +319,6 @@ 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 - } - #[cfg(target_arch = "x86_64")] unsafe fn pte_clone(stack: *mut usize) -> pid_t { let flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND; @@ -396,16 +391,6 @@ impl Pal for Sys { e(unsafe { syscall!(SCHED_YIELD) }) as c_int } - fn select( - nfds: c_int, - readfds: *mut fd_set, - writefds: *mut fd_set, - exceptfds: *mut fd_set, - timeout: *mut timeval, - ) -> c_int { - e(unsafe { syscall!(SELECT, nfds, readfds, writefds, exceptfds, timeout) }) as c_int - } - fn setpgid(pid: pid_t, pgid: pid_t) -> c_int { e(unsafe { syscall!(SETPGID, pid, pgid) }) as c_int } diff --git a/src/platform/mod.rs b/src/platform/mod.rs index 37da18e64abd673f25b5dd32cd9ce4db5e25442f..8dfaa1f897fa093bab16ae88935d26b25bb7bedd 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -12,7 +12,7 @@ mod allocator; #[path = "allocator/ralloc.rs"] mod allocator; -pub use self::pal::{Pal, PalSignal, PalSocket}; +pub use self::pal::{Pal, PalEpoll, PalSignal, PalSocket}; mod pal; diff --git a/src/platform/pal/epoll.rs b/src/platform/pal/epoll.rs new file mode 100644 index 0000000000000000000000000000000000000000..deace670fecec0e9bf37dddb72930ef1eaf0172d --- /dev/null +++ b/src/platform/pal/epoll.rs @@ -0,0 +1,10 @@ +use super::super::types::*; +use super::super::Pal; +use header::signal::sigset_t; +use header::sys_epoll::epoll_event; + +pub trait PalEpoll: Pal { + fn epoll_create1(flags: c_int) -> c_int; + fn epoll_ctl(epfd: c_int, op: c_int, fd: c_int, event: *mut epoll_event) -> c_int; + fn epoll_pwait(epfd: c_int, events: *mut epoll_event, maxevents: c_int, timeout: c_int, sigmask: *const sigset_t) -> c_int; +} diff --git a/src/platform/pal/mod.rs b/src/platform/pal/mod.rs index ba1052a7847c701bc260b87b08e2f18acecdbbad..a3d55f53753567eb4e017b91c5f471ec7d19122a 100644 --- a/src/platform/pal/mod.rs +++ b/src/platform/pal/mod.rs @@ -1,14 +1,15 @@ 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_statvfs::statvfs; use header::sys_time::{timeval, timezone}; use header::sys_utsname::utsname; use header::time::timespec; +pub use self::epoll::PalEpoll; +mod epoll; + pub use self::signal::PalSignal; mod signal; @@ -115,8 +116,6 @@ pub trait Pal { fn pipe(fildes: &mut [c_int]) -> c_int; - fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: c_int) -> c_int; - unsafe fn pte_clone(stack: *mut usize) -> pid_t; fn read(fildes: c_int, buf: &mut [u8]) -> ssize_t; @@ -129,15 +128,6 @@ pub trait Pal { fn sched_yield() -> c_int; - //TODO: Deprecate in favor of poll - fn select( - nfds: c_int, - readfds: *mut fd_set, - writefds: *mut fd_set, - exceptfds: *mut fd_set, - timeout: *mut timeval, - ) -> c_int; - fn setpgid(pid: pid_t, pgid: pid_t) -> c_int; fn setregid(rgid: gid_t, egid: gid_t) -> c_int; diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index eb45d814b308d885208b4463d5b1e43cfd1bb59d..272f18903417e69a33a425a29cde1fbe0330f638 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -14,9 +14,7 @@ use fs::File; use header::dirent::dirent; use header::errno::{EINVAL, EIO, EPERM}; use header::fcntl; -use header::poll::{self, nfds_t, pollfd}; use header::sys_mman::MAP_ANON; -use header::sys_select::fd_set; use header::sys_stat::stat; use header::sys_statvfs::statvfs; use header::sys_time::{timeval, timezone}; @@ -912,143 +910,6 @@ impl Pal for Sys { e(syscall::sched_yield()) as c_int } - fn select( - nfds: c_int, - readfds: *mut fd_set, - writefds: *mut fd_set, - exceptfds: *mut fd_set, - timeout: *mut timeval, - ) -> c_int { - let mut readfds = unsafe { readfds.as_mut() }.map(|s| BitSet::from_ref(&mut s.fds_bits)); - let mut writefds = unsafe { writefds.as_mut() }.map(|s| BitSet::from_ref(&mut s.fds_bits)); - let mut exceptfds = - unsafe { exceptfds.as_mut() }.map(|s| BitSet::from_ref(&mut s.fds_bits)); - - 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 0..nfds as usize { - macro_rules! register { - ($fd:expr, $flags:expr) => { - if event_file - .write(&syscall::Event { - id: $fd, - flags: $flags, - data: 0, - }) - .is_err() - { - return -1; - } - }; - } - if readfds.as_mut().map(|s| s.contains(fd)).unwrap_or(false) { - register!(fd, syscall::EVENT_READ); - } - if writefds.as_mut().map(|s| s.contains(fd)).unwrap_or(false) { - register!(fd, syscall::EVENT_WRITE); - } - } - - const TIMEOUT_TOKEN: usize = 1; - - let timeout_file = if timeout.is_null() { - None - } else { - let timeout = unsafe { &*timeout }; - - 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_sec += timeout.tv_sec; - time.tv_nsec += timeout.tv_usec * 1000; - 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, - } - }; - - let mut total = 0; - - if let Some(ref mut set) = readfds { - set.clear(); - } - if let Some(ref mut set) = writefds { - set.clear(); - } - if let Some(ref mut set) = exceptfds { - set.clear(); - } - - for event in &events[..read] { - if event.data == TIMEOUT_TOKEN { - continue; - } - - if event.flags & syscall::EVENT_READ == syscall::EVENT_READ { - if let Some(ref mut set) = readfds { - set.insert(event.id); - } - total += 1; - } - if event.flags & syscall::EVENT_WRITE == syscall::EVENT_WRITE { - if let Some(ref mut set) = writefds { - set.insert(event.id); - } - total += 1; - } - } - - total - } - fn setpgid(pid: pid_t, pgid: pid_t) -> c_int { e(syscall::setpgid(pid as usize, pgid as usize)) as c_int }