Skip to content

Commit

Permalink
Implemented multithreading and fixed a number of bugs with WASIX
Browse files Browse the repository at this point in the history
  • Loading branch information
john-sharratt committed Jun 13, 2022
1 parent dced984 commit 98f0d19
Show file tree
Hide file tree
Showing 24 changed files with 2,146 additions and 1,752 deletions.
5 changes: 2 additions & 3 deletions examples/wasi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,15 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {

println!("Creating `WasiEnv`...");
// First, we create the `WasiEnv`
let wasi_env = WasiState::new("hello")
let mut wasi_env = WasiState::new("hello")
// .args(&["world"])
// .env("KEY", "Value")
.finalize()?;

println!("Instantiating module with WASI imports...");
// Then, we get the import object related to our WASI
// and attach it to the Wasm instance.
let mut wasi_thread = wasi_env.new_thread();
let import_object = wasi_thread.import_object(&module)?;
let import_object = wasi_env.import_object(&module)?;
let instance = Instance::new(&module, &import_object)?;

println!("Call WASI `_start` function...");
Expand Down
5 changes: 2 additions & 3 deletions examples/wasi_pipes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,15 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// First, we create the `WasiEnv` with the stdio pipes
let mut input = Pipe::new();
let mut output = Pipe::new();
let wasi_env = WasiState::new("hello")
let mut wasi_env = WasiState::new("hello")
.stdin(Box::new(input.clone()))
.stdout(Box::new(output.clone()))
.finalize()?;

println!("Instantiating module with WASI imports...");
// Then, we get the import object related to our WASI
// and attach it to the Wasm instance.
let mut wasi_thread = wasi_env.new_thread();
let import_object = wasi_thread.import_object(&module)?;
let import_object = wasi_env.import_object(&module)?;
let instance = Instance::new(&module, &import_object)?;

let msg = "racecar go zoom";
Expand Down
5 changes: 2 additions & 3 deletions lib/c-api/src/wasm_c_api/unstable/wasi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use super::super::{
wasi::wasi_env_t,
};
use wasmer_api::{Exportable, Extern};
use wasmer_wasi::{generate_import_object_from_thread, get_wasi_version};
use wasmer_wasi::{generate_import_object_from_env, get_wasi_version};

/// Unstable non-standard type wrapping `wasm_extern_t` with the
/// addition of two `wasm_name_t` respectively for the module name and
Expand Down Expand Up @@ -170,8 +170,7 @@ fn wasi_get_unordered_imports_inner(
let version = c_try!(get_wasi_version(&module.inner, false)
.ok_or("could not detect a WASI version on the given module"));

let thread = wasi_env.inner.new_thread();
let import_object = generate_import_object_from_thread(store, thread, version);
let import_object = generate_import_object_from_env(store, wasi_env.inner.clone(), version);

imports.set_buffer(
import_object
Expand Down
26 changes: 11 additions & 15 deletions lib/c-api/src/wasm_c_api/wasi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use std::os::raw::c_char;
use std::slice;
use wasmer_api::{Exportable, Extern};
use wasmer_wasi::{
generate_import_object_from_thread, get_wasi_version, WasiEnv, WasiFile, WasiState,
generate_import_object_from_env, get_wasi_version, WasiEnv, WasiFile, WasiState,
WasiStateBuilder, WasiVersion,
};

Expand Down Expand Up @@ -206,19 +206,18 @@ pub unsafe extern "C" fn wasi_env_read_stdout(
buffer_len: usize,
) -> isize {
let inner_buffer = slice::from_raw_parts_mut(buffer as *mut _, buffer_len as usize);
let mut state = env.inner.state();
let state = env.inner.state();

let stdout = if let Ok(stdout) = state.fs.stdout_mut() {
if let Ok(mut stdout) = state.stdout() {
if let Some(stdout) = stdout.as_mut() {
stdout
read_inner(stdout, inner_buffer)
} else {
update_last_error("could not find a file handle for `stdout`");
return -1;
}
} else {
return -1;
};
read_inner(stdout, inner_buffer)
}
}

#[no_mangle]
Expand All @@ -228,23 +227,21 @@ pub unsafe extern "C" fn wasi_env_read_stderr(
buffer_len: usize,
) -> isize {
let inner_buffer = slice::from_raw_parts_mut(buffer as *mut _, buffer_len as usize);
let mut state = env.inner.state();
let inodes = state.inodes.write().unwrap();
let stderr = if let Ok(stderr) = inodes.stderr_mut(&state.fs.fd_map) {
let state = env.inner.state();
if let Ok(mut stderr) = state.stderr() {
if let Some(stderr) = stderr.as_mut() {
stderr
read_inner(stderr, inner_buffer)
} else {
update_last_error("could not find a file handle for `stderr`");
return -1;
}
} else {
update_last_error("could not find a file handle for `stderr`");
return -1;
};
read_inner(stderr, inner_buffer)
}
}

fn read_inner(wasi_file: &mut Box<dyn WasiFile>, inner_buffer: &mut [u8]) -> isize {
fn read_inner(wasi_file: &mut Box<dyn WasiFile + Send + Sync + 'static>, inner_buffer: &mut [u8]) -> isize {
if let Some(oc) = wasi_file.downcast_mut::<capture_files::OutputCapturer>() {
let total_to_read = min(inner_buffer.len(), oc.buffer.len());

Expand Down Expand Up @@ -356,8 +353,7 @@ fn wasi_get_imports_inner(
let version = c_try!(get_wasi_version(&module.inner, false)
.ok_or("could not detect a WASI version on the given module"));

let mut thread = wasi_env.inner.new_thread();
let import_object = generate_import_object_from_thread(store, thread, version);
let import_object = generate_import_object_from_env(store, wasi_env.inner.clone(), version);

imports.set_buffer(c_try!(module
.inner
Expand Down
12 changes: 8 additions & 4 deletions lib/cli/src/commands/run/wasi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use anyhow::Result;
use std::collections::BTreeSet;
use std::path::PathBuf;
use wasmer::{Instance, Module, RuntimeError, Val};
use wasmer_wasi::{get_wasi_versions, WasiError, WasiState, WasiVersion};
use wasmer_wasi::{get_wasi_versions, is_wasix_module, WasiError, WasiState, WasiVersion};

use structopt::StructOpt;

Expand Down Expand Up @@ -96,9 +96,13 @@ impl Wasi {
}
}

let wasi_env = wasi_state_builder.finalize()?;
let mut wasi_thread = wasi_env.new_thread();
let import_object = wasi_thread.import_object_for_all_wasi_versions(&module)?;
let mut wasi_env = wasi_state_builder.finalize()?;
wasi_env.state.fs.is_wasix.store(
is_wasix_module(&module),
std::sync::atomic::Ordering::Release,
);

let import_object = wasi_env.import_object_for_all_wasi_versions(&module)?;
let instance = Instance::new(&module, &import_object)?;
Ok(instance)
}
Expand Down
37 changes: 31 additions & 6 deletions lib/vbus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,19 @@ pub type Result<T> = std::result::Result<T, BusError>;

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct BusDescriptor(usize);
pub struct CallDescriptor(u32);

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct CallDescriptor(usize);
impl CallDescriptor {
pub fn raw(&self) -> u32 {
self.0
}
}

impl From<u32> for CallDescriptor {
fn from(a: u32) -> Self {
Self(a)
}
}

pub trait VirtualBus: fmt::Debug + Send + Sync + 'static {
/// Starts a new WAPM sub process
Expand All @@ -31,6 +39,7 @@ pub trait VirtualBusSpawner {

#[derive(Debug, Clone)]
pub struct SpawnOptionsConfig {
reuse: bool,
chroot: bool,
args: Vec<String>,
preopen: Vec<String>,
Expand All @@ -43,6 +52,10 @@ pub struct SpawnOptionsConfig {
}

impl SpawnOptionsConfig {
pub const fn reuse(&self) -> bool {
self.reuse
}

pub const fn chroot(&self) -> bool {
self.chroot
}
Expand Down Expand Up @@ -90,6 +103,7 @@ impl SpawnOptions {
Self {
spawner,
conf: SpawnOptionsConfig {
reuse: false,
chroot: false,
args: Vec::new(),
preopen: Vec::new(),
Expand All @@ -107,6 +121,16 @@ impl SpawnOptions {
self
}

pub fn reuse(&mut self, reuse: bool) -> &mut Self {
self.conf.reuse = reuse;
self
}

pub fn chroot(&mut self, chroot: bool) -> &mut Self {
self.conf.chroot = chroot;
self
}

pub fn args(&mut self, args: Vec<String>) -> &mut Self {
self.conf.args = args;
self
Expand Down Expand Up @@ -155,8 +179,6 @@ impl SpawnOptions {

#[derive(Debug)]
pub struct BusSpawnedProcess {
/// Handle of the instance
pub handle: BusDescriptor,
/// Reference to the spawned instance
pub inst: Box<dyn VirtualBusProcess + Sync>,
}
Expand Down Expand Up @@ -330,6 +352,9 @@ pub enum BusError {
/// Invocation has failed
#[error("invocation has failed")]
InvokeFailed,
/// Already consumed
#[error("already consumed")]
AlreadyConsumed,
/// Memory access violation
#[error("memory access violation")]
MemoryAccessViolation,
Expand Down
23 changes: 23 additions & 0 deletions lib/vfs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ pub type Result<T> = std::result::Result<T, FsError>;
#[repr(transparent)]
pub struct FileDescriptor(usize);

impl From<u32> for FileDescriptor {
fn from(a: u32) -> Self {
Self(a as usize)
}
}

impl Into<u32> for FileDescriptor {
fn into(self) -> u32 {
self.0 as u32
}
}

pub trait FileSystem: fmt::Debug + Send + Sync + 'static + Upcastable {
fn read_dir(&self, path: &Path) -> Result<ReadDir>;
fn create_dir(&self, path: &Path) -> Result<()>;
Expand Down Expand Up @@ -238,6 +250,17 @@ impl<T: Any + fmt::Debug + 'static> Upcastable for T {
}
}

impl dyn VirtualFile + Send + Sync + 'static {
#[inline]
pub fn downcast_ref<T: 'static>(&'_ self) -> Option<&'_ T> {
self.upcast_any_ref().downcast_ref::<T>()
}
#[inline]
pub fn downcast_mut<T: 'static>(&'_ mut self) -> Option<&'_ mut T> {
self.upcast_any_mut().downcast_mut::<T>()
}
}

impl dyn VirtualFile + 'static {
#[inline]
pub fn downcast_ref<T: 'static>(&'_ self) -> Option<&'_ T> {
Expand Down
2 changes: 1 addition & 1 deletion lib/vm/src/instance/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,7 @@ impl Instance {
///
/// This is more or less a public facade of the private `Instance`,
/// providing useful higher-level API.
#[derive(Debug, PartialEq)]
#[derive(Debug, Clone, PartialEq)]
pub struct InstanceHandle {
/// The [`InstanceRef`]. See its documentation to learn more.
instance: InstanceRef,
Expand Down
Loading

0 comments on commit 98f0d19

Please sign in to comment.