poll now handles monotonic clocks, not system clocks
I initially had it backwards. It is not sensible to poll on a system clock timeout because the system clock is not necessarily monotonic! only a monotonic clock makes sense for a timeout.
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
use crate::clocks::WasiSystemClock;
|
||||
use crate::clocks::WasiMonotonicClock;
|
||||
use crate::file::WasiFile;
|
||||
use crate::Error;
|
||||
use cap_std::time::{Duration, SystemTime};
|
||||
use cap_std::time::{Duration, Instant};
|
||||
use std::cell::Ref;
|
||||
pub mod subscription;
|
||||
|
||||
mod sync;
|
||||
pub use sync::SyncSched;
|
||||
|
||||
use subscription::{RwSubscription, Subscription, SubscriptionResult, SystemTimerSubscription};
|
||||
use subscription::{MonotonicClockSubscription, RwSubscription, Subscription, SubscriptionResult};
|
||||
|
||||
pub trait WasiSched {
|
||||
fn poll_oneoff(&self, poll: &Poll) -> Result<(), Error>;
|
||||
@@ -36,15 +36,15 @@ impl<'a> Poll<'a> {
|
||||
pub fn new() -> Self {
|
||||
Self { subs: Vec::new() }
|
||||
}
|
||||
pub fn subscribe_system_timer(
|
||||
pub fn subscribe_monotonic_clock(
|
||||
&mut self,
|
||||
clock: &'a dyn WasiSystemClock,
|
||||
deadline: SystemTime,
|
||||
clock: &'a dyn WasiMonotonicClock,
|
||||
deadline: Instant,
|
||||
precision: Duration,
|
||||
ud: Userdata,
|
||||
) {
|
||||
self.subs.push((
|
||||
Subscription::SystemTimer(SystemTimerSubscription {
|
||||
Subscription::MonotonicClock(MonotonicClockSubscription {
|
||||
clock,
|
||||
deadline,
|
||||
precision,
|
||||
@@ -69,15 +69,15 @@ impl<'a> Poll<'a> {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.subs.is_empty()
|
||||
}
|
||||
pub fn earliest_system_timer(&'a self) -> Option<&SystemTimerSubscription<'a>> {
|
||||
pub fn earliest_clock_deadline(&'a self) -> Option<&MonotonicClockSubscription<'a>> {
|
||||
let mut subs = self
|
||||
.subs
|
||||
.iter()
|
||||
.filter_map(|(s, _ud)| match s {
|
||||
Subscription::SystemTimer(t) => Some(t),
|
||||
Subscription::MonotonicClock(t) => Some(t),
|
||||
_ => None,
|
||||
})
|
||||
.collect::<Vec<&SystemTimerSubscription<'a>>>();
|
||||
.collect::<Vec<&MonotonicClockSubscription<'a>>>();
|
||||
subs.sort_by(|a, b| a.deadline.cmp(&b.deadline));
|
||||
subs.into_iter().next() // First element is earliest
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use crate::clocks::WasiSystemClock;
|
||||
use crate::clocks::WasiMonotonicClock;
|
||||
use crate::file::WasiFile;
|
||||
use crate::Error;
|
||||
use bitflags::bitflags;
|
||||
use cap_std::time::{Duration, SystemTime};
|
||||
use cap_std::time::{Duration, Instant};
|
||||
use std::cell::{Cell, Ref};
|
||||
|
||||
bitflags! {
|
||||
@@ -34,18 +34,18 @@ impl<'a> RwSubscription<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SystemTimerSubscription<'a> {
|
||||
pub clock: &'a dyn WasiSystemClock,
|
||||
pub deadline: SystemTime,
|
||||
pub struct MonotonicClockSubscription<'a> {
|
||||
pub clock: &'a dyn WasiMonotonicClock,
|
||||
pub deadline: Instant,
|
||||
pub precision: Duration,
|
||||
}
|
||||
|
||||
impl<'a> SystemTimerSubscription<'a> {
|
||||
pub fn now(&self) -> SystemTime {
|
||||
impl<'a> MonotonicClockSubscription<'a> {
|
||||
pub fn now(&self) -> Instant {
|
||||
self.clock.now(self.precision)
|
||||
}
|
||||
pub fn result(&self) -> Option<Result<(), Error>> {
|
||||
if self.now().duration_since(self.deadline).is_ok() {
|
||||
if self.now().checked_duration_since(self.deadline).is_some() {
|
||||
Some(Ok(()))
|
||||
} else {
|
||||
None
|
||||
@@ -56,13 +56,13 @@ impl<'a> SystemTimerSubscription<'a> {
|
||||
pub enum Subscription<'a> {
|
||||
Read(RwSubscription<'a>),
|
||||
Write(RwSubscription<'a>),
|
||||
SystemTimer(SystemTimerSubscription<'a>),
|
||||
MonotonicClock(MonotonicClockSubscription<'a>),
|
||||
}
|
||||
|
||||
pub enum SubscriptionResult {
|
||||
Read(Result<(u64, RwEventFlags), Error>),
|
||||
Write(Result<(u64, RwEventFlags), Error>),
|
||||
SystemTimer(Result<(), Error>),
|
||||
MonotonicClock(Result<(), Error>),
|
||||
}
|
||||
|
||||
impl SubscriptionResult {
|
||||
@@ -70,7 +70,7 @@ impl SubscriptionResult {
|
||||
match s {
|
||||
Subscription::Read(s) => s.result().map(SubscriptionResult::Read),
|
||||
Subscription::Write(s) => s.result().map(SubscriptionResult::Write),
|
||||
Subscription::SystemTimer(s) => s.result().map(SubscriptionResult::SystemTimer),
|
||||
Subscription::MonotonicClock(s) => s.result().map(SubscriptionResult::MonotonicClock),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ mod unix {
|
||||
return Ok(());
|
||||
}
|
||||
let mut pollfds = Vec::new();
|
||||
let timeout = poll.earliest_system_timer();
|
||||
let timeout = poll.earliest_clock_deadline();
|
||||
for s in poll.rw_subscriptions() {
|
||||
match s {
|
||||
Subscription::Read(f) => {
|
||||
@@ -34,7 +34,7 @@ mod unix {
|
||||
let raw_fd = wasi_file_raw_fd(f.file.deref()).ok_or(Error::Inval)?;
|
||||
pollfds.push(unsafe { PollFd::new(raw_fd, PollFlags::POLLOUT) });
|
||||
}
|
||||
Subscription::SystemTimer { .. } => unreachable!(),
|
||||
Subscription::MonotonicClock { .. } => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ mod unix {
|
||||
let poll_timeout = if let Some(t) = timeout {
|
||||
let duration = t
|
||||
.deadline
|
||||
.duration_since(t.clock.now(t.precision))
|
||||
.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()
|
||||
|
||||
@@ -895,7 +895,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
|
||||
return Err(Error::Inval);
|
||||
}
|
||||
|
||||
use cap_std::time::{Duration, SystemClock};
|
||||
use cap_std::time::Duration;
|
||||
let table = self.table();
|
||||
let mut poll = Poll::new();
|
||||
|
||||
@@ -905,15 +905,16 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
|
||||
let sub = sub_ptr.read()?;
|
||||
match sub.u {
|
||||
types::SubscriptionU::Clock(clocksub) => match clocksub.id {
|
||||
types::Clockid::Realtime => {
|
||||
let clock = self.clocks.system.deref();
|
||||
types::Clockid::Monotonic => {
|
||||
let clock = self.clocks.monotonic.deref();
|
||||
let precision = Duration::from_micros(clocksub.precision);
|
||||
let duration = Duration::from_micros(clocksub.timeout);
|
||||
let deadline = if clocksub
|
||||
.flags
|
||||
.contains(types::Subclockflags::SUBSCRIPTION_CLOCK_ABSTIME)
|
||||
{
|
||||
SystemClock::UNIX_EPOCH
|
||||
self.clocks
|
||||
.creation_time
|
||||
.checked_add(duration)
|
||||
.ok_or(Error::Overflow)?
|
||||
} else {
|
||||
@@ -922,7 +923,12 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
|
||||
.checked_add(duration)
|
||||
.ok_or(Error::Overflow)?
|
||||
};
|
||||
poll.subscribe_system_timer(clock, deadline, precision, sub.userdata.into())
|
||||
poll.subscribe_monotonic_clock(
|
||||
clock,
|
||||
deadline,
|
||||
precision,
|
||||
sub.userdata.into(),
|
||||
)
|
||||
}
|
||||
_ => Err(Error::Inval)?,
|
||||
},
|
||||
@@ -1000,7 +1006,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
|
||||
},
|
||||
}
|
||||
}
|
||||
SubscriptionResult::SystemTimer(r) => {
|
||||
SubscriptionResult::MonotonicClock(r) => {
|
||||
let type_ = types::Eventtype::Clock;
|
||||
types::Event {
|
||||
userdata,
|
||||
|
||||
Reference in New Issue
Block a user