inline poll from yanix
This commit is contained in:
17
Cargo.lock
generated
17
Cargo.lock
generated
@@ -2540,6 +2540,7 @@ dependencies = [
|
|||||||
name = "wasi-c2-cap-std-sync"
|
name = "wasi-c2-cap-std-sync"
|
||||||
version = "0.22.0"
|
version = "0.22.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
"cap-fs-ext",
|
"cap-fs-ext",
|
||||||
"cap-rand",
|
"cap-rand",
|
||||||
"cap-std",
|
"cap-std",
|
||||||
@@ -2550,7 +2551,6 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
"unsafe-io",
|
"unsafe-io",
|
||||||
"wasi-c2",
|
"wasi-c2",
|
||||||
"yanix 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2580,7 +2580,7 @@ dependencies = [
|
|||||||
"wiggle",
|
"wiggle",
|
||||||
"winapi",
|
"winapi",
|
||||||
"winx 0.22.0",
|
"winx 0.22.0",
|
||||||
"yanix 0.22.0",
|
"yanix",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3190,19 +3190,6 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "yanix"
|
|
||||||
version = "0.22.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0504d76a87b9e77f1057d419a51acb4344b9e14eaf37dde22cf1fd0ec28901db"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
"cfg-if 1.0.0",
|
|
||||||
"filetime",
|
|
||||||
"libc",
|
|
||||||
"tracing",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "z3"
|
name = "z3"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ cap-time-ext = "0.11"
|
|||||||
cap-rand = "0.11"
|
cap-rand = "0.11"
|
||||||
fs-set-times = "0.2.2"
|
fs-set-times = "0.2.2"
|
||||||
unsafe-io = "0.2"
|
unsafe-io = "0.2"
|
||||||
yanix = "0.22"
|
|
||||||
system-interface = { version = "0.5.2", features = ["cap_std_impls"] }
|
system-interface = { version = "0.5.2", features = ["cap_std_impls"] }
|
||||||
tracing = "0.1.19"
|
tracing = "0.1.19"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
|
bitflags = "1.2"
|
||||||
|
|||||||
@@ -1,189 +1,9 @@
|
|||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
|
mod unix;
|
||||||
|
#[cfg(unix)]
|
||||||
pub use unix::*;
|
pub use unix::*;
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
mod windows;
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
pub use windows::*;
|
pub use windows::*;
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
mod unix {
|
|
||||||
use cap_std::time::Duration;
|
|
||||||
use std::convert::TryInto;
|
|
||||||
use std::ops::Deref;
|
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
|
||||||
use wasi_c2::{
|
|
||||||
file::WasiFile,
|
|
||||||
sched::{
|
|
||||||
subscription::{RwEventFlags, Subscription},
|
|
||||||
Poll, WasiSched,
|
|
||||||
},
|
|
||||||
Error,
|
|
||||||
};
|
|
||||||
use yanix::poll::{PollFd, PollFlags};
|
|
||||||
|
|
||||||
pub struct SyncSched;
|
|
||||||
|
|
||||||
impl WasiSched for SyncSched {
|
|
||||||
fn poll_oneoff<'a>(&self, poll: &'a Poll<'a>) -> Result<(), Error> {
|
|
||||||
if poll.is_empty() {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
let mut pollfds = Vec::new();
|
|
||||||
let timeout = poll.earliest_clock_deadline();
|
|
||||||
for s in poll.rw_subscriptions() {
|
|
||||||
match s {
|
|
||||||
Subscription::Read(f) => {
|
|
||||||
let raw_fd = wasi_file_raw_fd(f.file.deref()).ok_or(Error::Inval)?;
|
|
||||||
pollfds.push(unsafe { PollFd::new(raw_fd, PollFlags::POLLIN) });
|
|
||||||
}
|
|
||||||
|
|
||||||
Subscription::Write(f) => {
|
|
||||||
let raw_fd = wasi_file_raw_fd(f.file.deref()).ok_or(Error::Inval)?;
|
|
||||||
pollfds.push(unsafe { PollFd::new(raw_fd, PollFlags::POLLOUT) });
|
|
||||||
}
|
|
||||||
Subscription::MonotonicClock { .. } => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let ready = loop {
|
|
||||||
let poll_timeout = if let Some(t) = timeout {
|
|
||||||
let duration = t
|
|
||||||
.deadline
|
|
||||||
.checked_duration_since(t.clock.now(t.precision))
|
|
||||||
.unwrap_or(Duration::from_secs(0));
|
|
||||||
(duration.as_millis() + 1) // XXX try always rounding up?
|
|
||||||
.try_into()
|
|
||||||
.map_err(|_| Error::Overflow)?
|
|
||||||
} else {
|
|
||||||
libc::c_int::max_value()
|
|
||||||
};
|
|
||||||
tracing::debug!(
|
|
||||||
poll_timeout = tracing::field::debug(poll_timeout),
|
|
||||||
poll_fds = tracing::field::debug(&pollfds),
|
|
||||||
"poll"
|
|
||||||
);
|
|
||||||
match yanix::poll::poll(&mut pollfds, poll_timeout) {
|
|
||||||
Ok(ready) => break ready,
|
|
||||||
Err(_) => {
|
|
||||||
let last_err = std::io::Error::last_os_error();
|
|
||||||
if last_err.raw_os_error().unwrap() == libc::EINTR {
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
return Err(last_err.into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if ready > 0 {
|
|
||||||
for (rwsub, pollfd) in poll.rw_subscriptions().zip(pollfds.into_iter()) {
|
|
||||||
if let Some(revents) = pollfd.revents() {
|
|
||||||
let (nbytes, rwsub) = match rwsub {
|
|
||||||
Subscription::Read(sub) => {
|
|
||||||
let ready = sub.file.num_ready_bytes()?;
|
|
||||||
(std::cmp::max(ready, 1), sub)
|
|
||||||
}
|
|
||||||
Subscription::Write(sub) => (0, sub),
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
if revents.contains(PollFlags::POLLNVAL) {
|
|
||||||
rwsub.error(Error::Badf);
|
|
||||||
} else if revents.contains(PollFlags::POLLERR) {
|
|
||||||
rwsub.error(Error::Io);
|
|
||||||
} else if revents.contains(PollFlags::POLLHUP) {
|
|
||||||
rwsub.complete(nbytes, RwEventFlags::HANGUP);
|
|
||||||
} else {
|
|
||||||
rwsub.complete(nbytes, RwEventFlags::empty());
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
timeout
|
|
||||||
.expect("timed out")
|
|
||||||
.result()
|
|
||||||
.expect("timer deadline is past")
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn sched_yield(&self) -> Result<(), Error> {
|
|
||||||
std::thread::yield_now();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn wasi_file_raw_fd(f: &dyn WasiFile) -> Option<RawFd> {
|
|
||||||
let a = f.as_any();
|
|
||||||
if a.is::<crate::file::File>() {
|
|
||||||
Some(a.downcast_ref::<crate::file::File>().unwrap().as_raw_fd())
|
|
||||||
} else if a.is::<crate::stdio::Stdin>() {
|
|
||||||
Some(a.downcast_ref::<crate::stdio::Stdin>().unwrap().as_raw_fd())
|
|
||||||
} else if a.is::<crate::stdio::Stdout>() {
|
|
||||||
Some(
|
|
||||||
a.downcast_ref::<crate::stdio::Stdout>()
|
|
||||||
.unwrap()
|
|
||||||
.as_raw_fd(),
|
|
||||||
)
|
|
||||||
} else if a.is::<crate::stdio::Stderr>() {
|
|
||||||
Some(
|
|
||||||
a.downcast_ref::<crate::stdio::Stderr>()
|
|
||||||
.unwrap()
|
|
||||||
.as_raw_fd(),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
|
||||||
mod windows {
|
|
||||||
use std::os::windows::io::{AsRawHandle, RawHandle};
|
|
||||||
use wasi_c2::{
|
|
||||||
file::WasiFile,
|
|
||||||
sched::{Poll, WasiSched},
|
|
||||||
Error,
|
|
||||||
};
|
|
||||||
pub struct SyncSched;
|
|
||||||
|
|
||||||
impl WasiSched for SyncSched {
|
|
||||||
fn poll_oneoff<'a>(&self, poll: &'a Poll<'a>) -> Result<(), Error> {
|
|
||||||
if poll.is_empty() {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
fn sched_yield(&self) -> Result<(), Error> {
|
|
||||||
std::thread::yield_now();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn wasi_file_raw_handle(f: &dyn WasiFile) -> Option<RawHandle> {
|
|
||||||
let a = f.as_any();
|
|
||||||
if a.is::<crate::file::File>() {
|
|
||||||
Some(
|
|
||||||
a.downcast_ref::<crate::file::File>()
|
|
||||||
.unwrap()
|
|
||||||
.as_raw_handle(),
|
|
||||||
)
|
|
||||||
} else if a.is::<crate::stdio::Stdin>() {
|
|
||||||
Some(
|
|
||||||
a.downcast_ref::<crate::stdio::Stdin>()
|
|
||||||
.unwrap()
|
|
||||||
.as_raw_handle(),
|
|
||||||
)
|
|
||||||
} else if a.is::<crate::stdio::Stdout>() {
|
|
||||||
Some(
|
|
||||||
a.downcast_ref::<crate::stdio::Stdout>()
|
|
||||||
.unwrap()
|
|
||||||
.as_raw_handle(),
|
|
||||||
)
|
|
||||||
} else if a.is::<crate::stdio::Stderr>() {
|
|
||||||
Some(
|
|
||||||
a.downcast_ref::<crate::stdio::Stderr>()
|
|
||||||
.unwrap()
|
|
||||||
.as_raw_handle(),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
183
crates/wasi-c2/cap-std-sync/src/sched/unix.rs
Normal file
183
crates/wasi-c2/cap-std-sync/src/sched/unix.rs
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
use cap_std::time::Duration;
|
||||||
|
use std::convert::TryInto;
|
||||||
|
use std::ops::Deref;
|
||||||
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
|
use wasi_c2::{
|
||||||
|
file::WasiFile,
|
||||||
|
sched::{
|
||||||
|
subscription::{RwEventFlags, Subscription},
|
||||||
|
Poll, WasiSched,
|
||||||
|
},
|
||||||
|
Error,
|
||||||
|
};
|
||||||
|
|
||||||
|
use poll::{PollFd, PollFlags};
|
||||||
|
|
||||||
|
pub struct SyncSched;
|
||||||
|
|
||||||
|
impl WasiSched for SyncSched {
|
||||||
|
fn poll_oneoff<'a>(&self, poll: &'a Poll<'a>) -> Result<(), Error> {
|
||||||
|
if poll.is_empty() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let mut pollfds = Vec::new();
|
||||||
|
let timeout = poll.earliest_clock_deadline();
|
||||||
|
for s in poll.rw_subscriptions() {
|
||||||
|
match s {
|
||||||
|
Subscription::Read(f) => {
|
||||||
|
let raw_fd = wasi_file_raw_fd(f.file.deref()).ok_or(Error::Inval)?;
|
||||||
|
pollfds.push(unsafe { PollFd::new(raw_fd, PollFlags::POLLIN) });
|
||||||
|
}
|
||||||
|
|
||||||
|
Subscription::Write(f) => {
|
||||||
|
let raw_fd = wasi_file_raw_fd(f.file.deref()).ok_or(Error::Inval)?;
|
||||||
|
pollfds.push(unsafe { PollFd::new(raw_fd, PollFlags::POLLOUT) });
|
||||||
|
}
|
||||||
|
Subscription::MonotonicClock { .. } => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let ready = loop {
|
||||||
|
let poll_timeout = if let Some(t) = timeout {
|
||||||
|
let duration = t
|
||||||
|
.deadline
|
||||||
|
.checked_duration_since(t.clock.now(t.precision))
|
||||||
|
.unwrap_or(Duration::from_secs(0));
|
||||||
|
(duration.as_millis() + 1) // XXX try always rounding up?
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_| Error::Overflow)?
|
||||||
|
} else {
|
||||||
|
libc::c_int::max_value()
|
||||||
|
};
|
||||||
|
tracing::debug!(
|
||||||
|
poll_timeout = tracing::field::debug(poll_timeout),
|
||||||
|
poll_fds = tracing::field::debug(&pollfds),
|
||||||
|
"poll"
|
||||||
|
);
|
||||||
|
match poll::poll(&mut pollfds, poll_timeout) {
|
||||||
|
Ok(ready) => break ready,
|
||||||
|
Err(_) => {
|
||||||
|
let last_err = std::io::Error::last_os_error();
|
||||||
|
if last_err.raw_os_error().unwrap() == libc::EINTR {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
return Err(last_err.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if ready > 0 {
|
||||||
|
for (rwsub, pollfd) in poll.rw_subscriptions().zip(pollfds.into_iter()) {
|
||||||
|
if let Some(revents) = pollfd.revents() {
|
||||||
|
let (nbytes, rwsub) = match rwsub {
|
||||||
|
Subscription::Read(sub) => {
|
||||||
|
let ready = sub.file.num_ready_bytes()?;
|
||||||
|
(std::cmp::max(ready, 1), sub)
|
||||||
|
}
|
||||||
|
Subscription::Write(sub) => (0, sub),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
if revents.contains(PollFlags::POLLNVAL) {
|
||||||
|
rwsub.error(Error::Badf);
|
||||||
|
} else if revents.contains(PollFlags::POLLERR) {
|
||||||
|
rwsub.error(Error::Io);
|
||||||
|
} else if revents.contains(PollFlags::POLLHUP) {
|
||||||
|
rwsub.complete(nbytes, RwEventFlags::HANGUP);
|
||||||
|
} else {
|
||||||
|
rwsub.complete(nbytes, RwEventFlags::empty());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
timeout
|
||||||
|
.expect("timed out")
|
||||||
|
.result()
|
||||||
|
.expect("timer deadline is past")
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn sched_yield(&self) -> Result<(), Error> {
|
||||||
|
std::thread::yield_now();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wasi_file_raw_fd(f: &dyn WasiFile) -> Option<RawFd> {
|
||||||
|
let a = f.as_any();
|
||||||
|
if a.is::<crate::file::File>() {
|
||||||
|
Some(a.downcast_ref::<crate::file::File>().unwrap().as_raw_fd())
|
||||||
|
} else if a.is::<crate::stdio::Stdin>() {
|
||||||
|
Some(a.downcast_ref::<crate::stdio::Stdin>().unwrap().as_raw_fd())
|
||||||
|
} else if a.is::<crate::stdio::Stdout>() {
|
||||||
|
Some(
|
||||||
|
a.downcast_ref::<crate::stdio::Stdout>()
|
||||||
|
.unwrap()
|
||||||
|
.as_raw_fd(),
|
||||||
|
)
|
||||||
|
} else if a.is::<crate::stdio::Stderr>() {
|
||||||
|
Some(
|
||||||
|
a.downcast_ref::<crate::stdio::Stderr>()
|
||||||
|
.unwrap()
|
||||||
|
.as_raw_fd(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod poll {
|
||||||
|
use bitflags::bitflags;
|
||||||
|
use std::convert::TryInto;
|
||||||
|
use std::os::unix::io::RawFd;
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
pub struct PollFlags: libc::c_short {
|
||||||
|
const POLLIN = libc::POLLIN;
|
||||||
|
const POLLPRI = libc::POLLPRI;
|
||||||
|
const POLLOUT = libc::POLLOUT;
|
||||||
|
const POLLRDNORM = libc::POLLRDNORM;
|
||||||
|
const POLLWRNORM = libc::POLLWRNORM;
|
||||||
|
const POLLRDBAND = libc::POLLRDBAND;
|
||||||
|
const POLLWRBAND = libc::POLLWRBAND;
|
||||||
|
const POLLERR = libc::POLLERR;
|
||||||
|
const POLLHUP = libc::POLLHUP;
|
||||||
|
const POLLNVAL = libc::POLLNVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct PollFd(libc::pollfd);
|
||||||
|
|
||||||
|
impl PollFd {
|
||||||
|
pub unsafe fn new(fd: RawFd, events: PollFlags) -> Self {
|
||||||
|
Self(libc::pollfd {
|
||||||
|
fd,
|
||||||
|
events: events.bits(),
|
||||||
|
revents: PollFlags::empty().bits(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn revents(self) -> Option<PollFlags> {
|
||||||
|
PollFlags::from_bits(self.0.revents)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn poll(fds: &mut [PollFd], timeout: libc::c_int) -> Result<usize, std::io::Error> {
|
||||||
|
let nready = unsafe {
|
||||||
|
libc::poll(
|
||||||
|
fds.as_mut_ptr() as *mut libc::pollfd,
|
||||||
|
fds.len() as libc::nfds_t,
|
||||||
|
timeout,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
if nready == -1 {
|
||||||
|
Err(std::io::Error::last_os_error())
|
||||||
|
} else {
|
||||||
|
// When poll doesn't fail, its return value is a non-negative int, which will
|
||||||
|
// always be convertable to usize, so we can unwrap() here.
|
||||||
|
Ok(nready.try_into().unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
52
crates/wasi-c2/cap-std-sync/src/sched/windows.rs
Normal file
52
crates/wasi-c2/cap-std-sync/src/sched/windows.rs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
|
||||||
|
use std::os::windows::io::{AsRawHandle, RawHandle};
|
||||||
|
use wasi_c2::{
|
||||||
|
file::WasiFile,
|
||||||
|
sched::{Poll, WasiSched},
|
||||||
|
Error,
|
||||||
|
};
|
||||||
|
pub struct SyncSched;
|
||||||
|
|
||||||
|
impl WasiSched for SyncSched {
|
||||||
|
fn poll_oneoff<'a>(&self, poll: &'a Poll<'a>) -> Result<(), Error> {
|
||||||
|
if poll.is_empty() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
fn sched_yield(&self) -> Result<(), Error> {
|
||||||
|
std::thread::yield_now();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wasi_file_raw_handle(f: &dyn WasiFile) -> Option<RawHandle> {
|
||||||
|
let a = f.as_any();
|
||||||
|
if a.is::<crate::file::File>() {
|
||||||
|
Some(
|
||||||
|
a.downcast_ref::<crate::file::File>()
|
||||||
|
.unwrap()
|
||||||
|
.as_raw_handle(),
|
||||||
|
)
|
||||||
|
} else if a.is::<crate::stdio::Stdin>() {
|
||||||
|
Some(
|
||||||
|
a.downcast_ref::<crate::stdio::Stdin>()
|
||||||
|
.unwrap()
|
||||||
|
.as_raw_handle(),
|
||||||
|
)
|
||||||
|
} else if a.is::<crate::stdio::Stdout>() {
|
||||||
|
Some(
|
||||||
|
a.downcast_ref::<crate::stdio::Stdout>()
|
||||||
|
.unwrap()
|
||||||
|
.as_raw_handle(),
|
||||||
|
)
|
||||||
|
} else if a.is::<crate::stdio::Stderr>() {
|
||||||
|
Some(
|
||||||
|
a.downcast_ref::<crate::stdio::Stderr>()
|
||||||
|
.unwrap()
|
||||||
|
.as_raw_handle(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user