diff --git a/Cargo.lock b/Cargo.lock index 18ac80db931..f15fd52757c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1482,6 +1482,8 @@ dependencies = [ name = "wasmer-wasi" version = "0.1.0" dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-runtime-core 0.2.1", ] diff --git a/lib/wasi/Cargo.toml b/lib/wasi/Cargo.toml index 17a2f14f429..2b3efd25bf0 100644 --- a/lib/wasi/Cargo.toml +++ b/lib/wasi/Cargo.toml @@ -5,4 +5,6 @@ authors = ["The Wasmer Engineering Team "] edition = "2018" [dependencies] -wasmer-runtime-core = { path = "../runtime-core", version = "0.2.1" } \ No newline at end of file +wasmer-runtime-core = { path = "../runtime-core", version = "0.2.1" } +libc = "0.2.50" +rand = "0.6.5" \ No newline at end of file diff --git a/lib/wasi/src/syscalls/mod.rs b/lib/wasi/src/syscalls/mod.rs index d72cbf46610..f4566c1c110 100644 --- a/lib/wasi/src/syscalls/mod.rs +++ b/lib/wasi/src/syscalls/mod.rs @@ -1,14 +1,24 @@ #![allow(unused)] - -mod types; +pub mod types; +#[cfg(any(target_os = "linux", target_os = "macos"))] +pub mod unix; +#[cfg(any(target_os = "windows"))] +pub mod windows; use self::types::*; use crate::{ ptr::{Array, WasmPtr}, state::WasiState, }; +use rand::{thread_rng, Rng}; use wasmer_runtime_core::{memory::Memory, vm::Ctx}; +#[cfg(any(target_os = "linux", target_os = "macos"))] +pub use unix::*; + +#[cfg(any(target_os = "windows"))] +pub use windows::*; + #[allow(clippy::mut_from_ref)] fn get_wasi_state(ctx: &Ctx) -> &mut WasiState { unsafe { &mut *(ctx.data as *mut WasiState) } @@ -99,15 +109,28 @@ pub fn clock_res_get( clock_id: __wasi_clockid_t, resolution: WasmPtr<__wasi_timestamp_t>, ) -> __wasi_errno_t { - unimplemented!() + let memory = ctx.memory(0); + + if let Some(out_addr) = resolution.deref(memory) { + platform_clock_res_get(clock_id, out_addr) + } else { + __WASI_EFAULT + } } + pub fn clock_time_get( ctx: &mut Ctx, clock_id: __wasi_clockid_t, precision: __wasi_timestamp_t, time: WasmPtr<__wasi_timestamp_t>, ) -> __wasi_errno_t { - unimplemented!() + let memory = ctx.memory(0); + + if let Some(out_addr) = time.deref(memory) { + platform_clock_time_get(clock_id, precision, out_addr) + } else { + __WASI_EFAULT + } } /// ### `environ_get()` @@ -429,12 +452,36 @@ pub fn proc_exit(ctx: &mut Ctx, rval: __wasi_exitcode_t) { pub fn proc_raise(ctx: &mut Ctx, sig: __wasi_signal_t) -> __wasi_errno_t { unimplemented!() } + +/// ### `random_get()` +/// Fill buffer with high-quality random data. This function may be slow and block +/// Inputs: +/// - `void *buf` +/// A pointer to a buffer where the random bytes will be written +/// - `size_t buf_len` +/// The number of bytes that will be written pub fn random_get(ctx: &mut Ctx, buf: WasmPtr, buf_len: u32) -> __wasi_errno_t { - unimplemented!() + let mut rng = thread_rng(); + let memory = ctx.memory(0); + + if let Some(buf) = buf.deref(memory, 0, buf_len) { + for i in 0..(buf_len as usize) { + let random_byte = rng.gen::(); + buf[i].set(random_byte); + } + } else { + return __WASI_EFAULT; + } + + __WASI_ESUCCESS } + +/// ### `sched_yield()` +/// Yields execution of the thread pub fn sched_yield(ctx: &mut Ctx) -> __wasi_errno_t { - unimplemented!() + __WASI_ESUCCESS } + pub fn sock_recv( ctx: &mut Ctx, sock: __wasi_fd_t, diff --git a/lib/wasi/src/syscalls/unix/linux.rs b/lib/wasi/src/syscalls/unix/linux.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/lib/wasi/src/syscalls/unix/linux.rs @@ -0,0 +1 @@ + diff --git a/lib/wasi/src/syscalls/unix/macos.rs b/lib/wasi/src/syscalls/unix/macos.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/lib/wasi/src/syscalls/unix/macos.rs @@ -0,0 +1 @@ + diff --git a/lib/wasi/src/syscalls/unix/mod.rs b/lib/wasi/src/syscalls/unix/mod.rs new file mode 100644 index 00000000000..915699c24ec --- /dev/null +++ b/lib/wasi/src/syscalls/unix/mod.rs @@ -0,0 +1,71 @@ +#[cfg(target_os = "linux")] +pub mod linux; + +#[cfg(target_os = "macos")] +pub mod macos; + +#[cfg(target_os = "linux")] +pub use linux::*; + +#[cfg(target_os = "macos")] +pub use macos::*; + +use crate::syscalls::types::*; +use libc::{ + clock_getres, clock_gettime, timespec, CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID, + CLOCK_REALTIME, CLOCK_THREAD_CPUTIME_ID, +}; +use std::cell::Cell; +use std::mem; + +pub fn platform_clock_res_get( + clock_id: __wasi_clockid_t, + resolution: &Cell<__wasi_timestamp_t>, +) -> __wasi_errno_t { + let unix_clock_id = match clock_id { + __WASI_CLOCK_MONOTONIC => CLOCK_MONOTONIC, + __WASI_CLOCK_PROCESS_CPUTIME_ID => CLOCK_PROCESS_CPUTIME_ID, + __WASI_CLOCK_REALTIME => CLOCK_REALTIME, + __WASI_CLOCK_THREAD_CPUTIME_ID => CLOCK_THREAD_CPUTIME_ID, + _ => return __WASI_EINVAL, + }; + + let (output, timespec_out) = unsafe { + let mut timespec_out: timespec = mem::uninitialized(); + (clock_getres(unix_clock_id, &mut timespec_out), timespec_out) + }; + + resolution.set(timespec_out.tv_nsec as __wasi_timestamp_t); + + // TODO: map output of clock_getres to __wasi_errno_t + __WASI_ESUCCESS +} + +pub fn platform_clock_time_get( + clock_id: __wasi_clockid_t, + precision: __wasi_timestamp_t, + time: &Cell<__wasi_timestamp_t>, +) -> __wasi_errno_t { + let unix_clock_id = match clock_id { + __WASI_CLOCK_MONOTONIC => CLOCK_MONOTONIC, + __WASI_CLOCK_PROCESS_CPUTIME_ID => CLOCK_PROCESS_CPUTIME_ID, + __WASI_CLOCK_REALTIME => CLOCK_REALTIME, + __WASI_CLOCK_THREAD_CPUTIME_ID => CLOCK_THREAD_CPUTIME_ID, + _ => return __WASI_EINVAL, + }; + + let (output, timespec_out) = unsafe { + let mut timespec_out: timespec = mem::uninitialized(); + ( + clock_gettime(unix_clock_id, &mut timespec_out), + timespec_out, + ) + }; + + // TODO: adjust output by precision... + + time.set(timespec_out.tv_nsec as __wasi_timestamp_t); + + // TODO: map output of clock_gettime to __wasi_errno_t + __WASI_ESUCCESS +} diff --git a/lib/wasi/src/syscalls/windows.rs b/lib/wasi/src/syscalls/windows.rs new file mode 100644 index 00000000000..6273695d322 --- /dev/null +++ b/lib/wasi/src/syscalls/windows.rs @@ -0,0 +1,17 @@ +use crate::syscalls::types::*; +use std::cell::Cell; + +pub fn platform_clock_res_get( + clock_id: __wasi_clockid_t, + resolution: &Cell<__wasi_timestamp_t>, +) -> __wasi_errno_t { + __WASI_EINVAL +} + +pub fn platform_clock_time_get( + clock_id: __wasi_clockid_t, + precision: __wasi_timestamp_t, + time: &Cell<__wasi_timestamp_t>, +) -> __wasi_errno_t { + unimplemented!() +}