diff --git a/Cargo.lock b/Cargo.lock index dda83d6e01..81952eea6e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -259,6 +259,18 @@ dependencies = [ "cap-primitives 0.8.0", ] +[[package]] +name = "cap-time-ext" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022f6b679d942c100450e32c142c988c79370374d3f7d4776da815c582aff68" +dependencies = [ + "cap-primitives 0.8.0", + "once_cell", + "posish", + "winx 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "capstone" version = "0.7.0" @@ -2426,6 +2438,7 @@ dependencies = [ "anyhow", "cap-fs-ext", "cap-std 0.8.0", + "cap-time-ext", "cfg-if 1.0.0", "fs-set-times", "getrandom 0.2.0", diff --git a/crates/wasi-c2/Cargo.toml b/crates/wasi-c2/Cargo.toml index 45ddc70609..db59f0ffae 100644 --- a/crates/wasi-c2/Cargo.toml +++ b/crates/wasi-c2/Cargo.toml @@ -28,6 +28,7 @@ tracing = "0.1.19" system-interface = "0.2" cap-std = "0.8" cap-fs-ext = "0.8" +cap-time-ext = "0.8" fs-set-times = "0.2.1" cfg-if = "1" diff --git a/crates/wasi-c2/src/clocks.rs b/crates/wasi-c2/src/clocks.rs new file mode 100644 index 0000000000..7561e91b48 --- /dev/null +++ b/crates/wasi-c2/src/clocks.rs @@ -0,0 +1,30 @@ +use cap_std::time::{Duration, Instant, MonotonicClock, SystemClock, SystemTime}; +use cap_time_ext::{MonotonicClockExt, SystemClockExt}; + +pub trait WasiSystemClock { + fn resolution(&self) -> Duration; + fn now(&self, precision: Duration) -> SystemTime; +} + +impl WasiSystemClock for SystemClock { + fn resolution(&self) -> Duration { + SystemClockExt::resolution(self) + } + fn now(&self, precision: Duration) -> SystemTime { + self.now_with(precision) + } +} + +pub trait WasiMonotonicClock { + fn resolution(&self) -> Duration; + fn now(&self, precision: Duration) -> Instant; +} + +impl WasiMonotonicClock for MonotonicClock { + fn resolution(&self) -> Duration { + MonotonicClockExt::resolution(self) + } + fn now(&self, precision: Duration) -> Instant { + self.now_with(precision) + } +} diff --git a/crates/wasi-c2/src/ctx.rs b/crates/wasi-c2/src/ctx.rs index ce0e05b1e7..cb27328df1 100644 --- a/crates/wasi-c2/src/ctx.rs +++ b/crates/wasi-c2/src/ctx.rs @@ -1,3 +1,4 @@ +use crate::clocks::{WasiMonotonicClock, WasiSystemClock}; use crate::dir::{DirCaps, DirEntry, WasiDir}; use crate::file::{FileCaps, FileEntry, WasiFile}; use crate::random::WasiRandom; @@ -12,6 +13,7 @@ pub struct WasiCtx { pub(crate) args: StringArray, pub(crate) env: StringArray, pub(crate) random: Box, + pub(crate) clocks: WasiCtxClocks, table: Rc>, } @@ -25,6 +27,7 @@ impl WasiCtx { args: StringArray::new(), env: StringArray::new(), random: Box::new(crate::random::GetRandom), + clocks: WasiCtxClocks::default(), table: Rc::new(RefCell::new(Table::new())), } } @@ -119,3 +122,16 @@ impl WasiCtxBuilder { self } } + +pub struct WasiCtxClocks { + pub(crate) system: Box, + pub(crate) monotonic: Box, +} + +impl Default for WasiCtxClocks { + fn default() -> WasiCtxClocks { + let system = Box::new(unsafe { cap_std::time::SystemClock::new() }); + let monotonic = Box::new(unsafe { cap_std::time::MonotonicClock::new() }); + WasiCtxClocks { system, monotonic } + } +} diff --git a/crates/wasi-c2/src/lib.rs b/crates/wasi-c2/src/lib.rs index 8393b1c5c5..ac2844f8bf 100644 --- a/crates/wasi-c2/src/lib.rs +++ b/crates/wasi-c2/src/lib.rs @@ -1,5 +1,6 @@ #![cfg_attr(feature = "nightly", feature(windows_by_handle))] +pub mod clocks; mod ctx; mod dir; mod error; diff --git a/crates/wasi-c2/src/snapshots/preview_1.rs b/crates/wasi-c2/src/snapshots/preview_1.rs index f778654e58..7d489cd304 100644 --- a/crates/wasi-c2/src/snapshots/preview_1.rs +++ b/crates/wasi-c2/src/snapshots/preview_1.rs @@ -146,15 +146,37 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { } fn clock_res_get(&self, id: types::Clockid) -> Result { - unimplemented!() + let resolution = match id { + types::Clockid::Realtime => Ok(self.clocks.system.resolution()), + types::Clockid::Monotonic => Ok(self.clocks.monotonic.resolution()), + types::Clockid::ProcessCputimeId | types::Clockid::ThreadCputimeId => { + Err(Error::NotCapable) + } + }?; + Ok(resolution.as_nanos().try_into()?) } fn clock_time_get( &self, id: types::Clockid, - _precision: types::Timestamp, + precision: types::Timestamp, ) -> Result { - unimplemented!() + use cap_std::time::Duration; + let precision = Duration::from_nanos(precision); + match id { + types::Clockid::Realtime => { + let now = self.clocks.system.now(precision).into_std(); + let d = now + .duration_since(std::time::SystemTime::UNIX_EPOCH) + .map_err(|_| Error::NotCapable)?; // XXX wrong + Ok(d.as_nanos().try_into()?) + } + types::Clockid::Monotonic => { + let now = self.clocks.monotonic.now(precision); + todo!() + } + types::Clockid::ProcessCputimeId | types::Clockid::ThreadCputimeId => Err(Error::Badf), + } } fn fd_advise(