Merge branch 'epoll'
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
+89
-3
@@ -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,
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,3 @@
|
||||
use platform::types::*;
|
||||
|
||||
pub const EPOLL_CLOEXEC: c_int = 0x8_0000;
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
use platform::types::*;
|
||||
|
||||
pub const EPOLL_CLOEXEC: c_int = 0x0100_0000;
|
||||
@@ -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,
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
+3
-13
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user