diff --git a/Cargo.lock b/Cargo.lock index 04df81af3cd..b51938343e1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -474,6 +474,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +[[package]] +name = "cooked-waker" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147be55d677052dabc6b22252d5dd0fd4c29c8c27aa4f2fbef0f94aa003b406f" + [[package]] name = "corosensei" version = "0.1.3" @@ -487,6 +493,15 @@ dependencies = [ "windows-sys 0.33.0", ] +[[package]] +name = "cpufeatures" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +dependencies = [ + "libc", +] + [[package]] name = "cranelift-bforest" version = "0.86.1" @@ -1368,6 +1383,15 @@ dependencies = [ "libc", ] +[[package]] +name = "matchers" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" +dependencies = [ + "regex-automata", +] + [[package]] name = "matchers" version = "0.1.0" @@ -2266,6 +2290,17 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" +[[package]] +name = "sha2" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "digest", +] + [[package]] name = "sharded-slab" version = "0.1.4" @@ -2617,6 +2652,50 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-serde" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +dependencies = [ + "serde", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" +dependencies = [ + "ansi_term", + "chrono", + "lazy_static", + "matchers 0.0.1", + "regex", + "serde", + "serde_json", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", + "tracing-serde", ] [[package]] @@ -2625,7 +2704,7 @@ version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b" dependencies = [ - "matchers", + "matchers 0.1.0", "once_cell", "regex", "sharded-slab", @@ -2641,7 +2720,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4575c663a174420fa2d78f4108ff68f65bf2fbb7dd89f33749b6e826b3626e07" dependencies = [ "tracing", - "tracing-subscriber", + "tracing-subscriber 0.3.15", "wasm-bindgen", ] @@ -2729,6 +2808,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "vec_map" version = "0.8.2" @@ -2756,6 +2841,12 @@ dependencies = [ "libc", ] +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + [[package]] name = "walkdir" version = "2.3.2" @@ -3271,15 +3362,20 @@ dependencies = [ "bytes", "cfg-if 1.0.0", "chrono", + "cooked-waker", "derivative", "generational-arena", "getrandom", + "lazy_static", "libc", "serde", + "sha2", "thiserror", "tracing", + "tracing-subscriber 0.2.25", "tracing-wasm", "typetag", + "waker-fn", "wasm-bindgen", "wasm-bindgen-test", "wasmer", @@ -3356,7 +3452,7 @@ dependencies = [ "test-generator", "test-log", "tracing", - "tracing-subscriber", + "tracing-subscriber 0.3.15", "wasi-test-generator", "wasmer", "wasmer-cache", diff --git a/docs/migration_to_3.0.0.md b/docs/migration_to_3.0.0.md index 2a87147af62..d780749593f 100644 --- a/docs/migration_to_3.0.0.md +++ b/docs/migration_to_3.0.0.md @@ -139,14 +139,13 @@ import_object.define("env", "host_function", host_function); let instance = Instance::new(&mut store, &module, &import_object).expect("Could not instantiate module."); ``` -For WASI, don't forget to import memory to `WasiEnv` +For WASI, don't forget to initialize it ```rust let mut wasi_env = WasiState::new("hello").finalize()?; let import_object = wasi_env.import_object(&mut store, &module)?; let instance = Instance::new(&mut store, &module, &import_object).expect("Could not instantiate module."); -let memory = instance.exports.get_memory("memory")?; -wasi_env.data_mut(&mut store).set_memory(memory.clone()); +wasi_env.initialize(&mut store, &instance).unwrap(); ``` #### `ChainableNamedResolver` is removed diff --git a/examples/imports_function_env.rs b/examples/imports_function_env.rs index dc870625e69..0b235f93f49 100644 --- a/examples/imports_function_env.rs +++ b/examples/imports_function_env.rs @@ -80,8 +80,8 @@ fn main() -> Result<(), Box> { fn get_counter(env: FunctionEnvMut) -> i32 { *env.data().counter.lock().unwrap() } - fn add_to_counter(mut env: FunctionEnvMut, add: i32) -> i32 { - let mut counter_ref = env.data_mut().counter.lock().unwrap(); + fn add_to_counter(env: FunctionEnvMut, add: i32) -> i32 { + let mut counter_ref = env.data().counter.lock().unwrap(); *counter_ref += add; *counter_ref diff --git a/examples/wasi.rs b/examples/wasi.rs index e3232061148..b8880b5d5a5 100644 --- a/examples/wasi.rs +++ b/examples/wasi.rs @@ -39,7 +39,7 @@ fn main() -> Result<(), Box> { 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(&mut store)?; @@ -50,10 +50,9 @@ fn main() -> Result<(), Box> { let import_object = wasi_env.import_object(&mut store, &module)?; let instance = Instance::new(&mut store, &module, &import_object)?; - println!("Attach WASI memory..."); - // Attach the memory export - let memory = instance.exports.get_memory("memory")?; - wasi_env.data_mut(&mut store).set_memory(memory.clone()); + println!("Initializing WASI environment..."); + // Initialize the WASI environment (which will attach memory) + wasi_env.initialize(&mut store, &instance).unwrap(); println!("Call WASI `_start` function..."); // And we just call the `_start` function! diff --git a/examples/wasi_pipes.rs b/examples/wasi_pipes.rs index ed7ef03a075..8f1c41c2614 100644 --- a/examples/wasi_pipes.rs +++ b/examples/wasi_pipes.rs @@ -49,10 +49,9 @@ fn main() -> Result<(), Box> { let import_object = wasi_env.import_object(&mut store, &module)?; let instance = Instance::new(&mut store, &module, &import_object)?; - println!("Attach WASI memory..."); - // Attach the memory export - let memory = instance.exports.get_memory("memory")?; - wasi_env.data_mut(&mut store).set_memory(memory.clone()); + println!("Initializing WASI environment..."); + // Initialize the WASI environment (which will attach memory) + wasi_env.initialize(&mut store, &instance).unwrap(); let msg = "racecar go zoom"; println!("Writing \"{}\" to the WASI stdin...", msg); diff --git a/lib/api/src/js/exports.rs b/lib/api/src/js/exports.rs index 024ab8b9696..339095bafa0 100644 --- a/lib/api/src/js/exports.rs +++ b/lib/api/src/js/exports.rs @@ -53,6 +53,9 @@ pub enum ExportError { /// This error arises when an export is missing #[error("Missing export {0}")] Missing(String), + /// This error arises when an export is missing + #[error("Serialization failed {0}")] + SerializationFailed(String), } /// Exports is a special kind of map that allows easily unwrapping diff --git a/lib/api/src/js/instance.rs b/lib/api/src/js/instance.rs index 6d2762adf66..fb849743a28 100644 --- a/lib/api/src/js/instance.rs +++ b/lib/api/src/js/instance.rs @@ -20,8 +20,6 @@ use std::fmt; pub struct Instance { _handle: StoreHandle, module: Module, - #[allow(dead_code)] - imports: Imports, /// The exports for an instance. pub exports: Exports, } @@ -65,12 +63,11 @@ impl Instance { module: &Module, imports: &Imports, ) -> Result { - let import_copy = imports.clone(); - let (instance, _imports): (StoreHandle, Vec) = module + let (instance, externs): (StoreHandle, Vec) = module .instantiate(&mut store, imports) .map_err(|e| InstantiationError::Start(e))?; - let self_instance = Self::from_module_and_instance(store, module, instance, import_copy)?; + let self_instance = Self::from_module_and_instance(store, module, externs, instance)?; //self_instance.init_envs(&imports.iter().map(Extern::to_export).collect::>())?; Ok(self_instance) } @@ -87,11 +84,11 @@ impl Instance { pub fn from_module_and_instance( mut store: &mut impl AsStoreMut, module: &Module, + externs: Vec, instance: StoreHandle, - imports: Imports, ) -> Result { let instance_exports = instance.get(store.as_store_ref().objects()).exports(); - let exports = module + let mut exports = module .exports() .map(|export_type| { let name = export_type.name(); @@ -110,10 +107,17 @@ impl Instance { }) .collect::>()?; + // If the memory is imported then also export it for backwards compatibility reasons + // (many will assume the memory is always exported) - later we can remove this + if exports.get_memory("memory").is_err() { + if let Some(memory) = externs.iter().filter(|a| a.ty(store).memory().is_some()).next() { + exports.insert("memory", memory.clone()); + } + } + Ok(Self { _handle: instance, module: module.clone(), - imports, exports, }) } diff --git a/lib/api/src/js/module.rs b/lib/api/src/js/module.rs index 975d1bee5d5..5197c34165a 100644 --- a/lib/api/src/js/module.rs +++ b/lib/api/src/js/module.rs @@ -20,6 +20,8 @@ use wasmer_types::{ ExportsIterator, ExternType, FunctionType, GlobalType, ImportsIterator, MemoryType, Mutability, Pages, TableType, Type, }; +#[cfg(feature = "tracing")] +use tracing::{debug, warn}; #[derive(Debug)] #[cfg_attr(feature = "std", derive(Error))] @@ -236,6 +238,21 @@ impl Module { let mut import_externs: Vec = vec![]; for import_type in self.imports() { let resolved_import = imports.get_export(import_type.module(), import_type.name()); + #[allow(unused_variables)] + if let wasmer_types::ExternType::Memory(mem_ty) = import_type.ty() { + if resolved_import.is_some() { + #[cfg(feature = "tracing")] + debug!("imported shared memory {:?}", &mem_ty); + } else { + #[cfg(feature = "tracing")] + warn!( + "Error while importing {0:?}.{1:?}: memory. Expected {2:?}", + import_type.module(), + import_type.name(), + import_type.ty(), + ); + } + } if let Some(import) = resolved_import { let val = js_sys::Reflect::get(&imports_object, &import_type.module().into())?; if !val.is_undefined() { @@ -260,6 +277,9 @@ impl Module { )?; } import_externs.push(import); + } else { + #[cfg(feature = "tracing")] + warn!("import not found {}:{}", import_type.module(), import_type.name()); } // in case the import is not found, the JS Wasm VM will handle // the error for us, so we don't need to handle it @@ -383,7 +403,8 @@ impl Module { let imports = WebAssembly::Module::imports(&self.module); let iter = imports .iter() - .map(move |val| { + .enumerate() + .map(move |(i, val)| { let module = Reflect::get(val.as_ref(), &"module".into()) .unwrap() .as_string() @@ -396,24 +417,34 @@ impl Module { .unwrap() .as_string() .unwrap(); - let extern_type = match kind.as_str() { - "function" => { - let func_type = FunctionType::new(vec![], vec![]); - ExternType::Function(func_type) - } - "global" => { - let global_type = GlobalType::new(Type::I32, Mutability::Const); - ExternType::Global(global_type) - } - "memory" => { - let memory_type = MemoryType::new(Pages(1), None, false); - ExternType::Memory(memory_type) - } - "table" => { - let table_type = TableType::new(Type::FuncRef, 1, None); - ExternType::Table(table_type) + let type_hint = self + .type_hints + .as_ref() + .map(|hints| hints.imports.get(i).unwrap().clone()); + let extern_type = if let Some(hint) = type_hint { + hint + } else { + match kind.as_str() { + "function" => { + let func_type = FunctionType::new(vec![], vec![]); + ExternType::Function(func_type) + } + "global" => { + let global_type = GlobalType::new(Type::I32, Mutability::Const); + ExternType::Global(global_type) + } + "memory" => { + // The javascript API does not yet expose these properties so without + // the type_hints we don't know what memory to import. + let memory_type = MemoryType::new(Pages(1), None, false); + ExternType::Memory(memory_type) + } + "table" => { + let table_type = TableType::new(Type::FuncRef, 1, None); + ExternType::Table(table_type) + } + _ => unimplemented!(), } - _ => unimplemented!(), }; ImportType::new(&module, &field, extern_type) }) @@ -525,6 +556,16 @@ impl Module { ExportsIterator::new(iter, exports.length() as usize) } + /// Returns true if the module is still ok - this will be + /// false if the module was passed between threads in a + /// way that it became undefined (JS does not share objects + /// between threads except via a post_message()) + pub fn is_ok(&self) -> bool { + let val = JsValue::from(&self.module); + !val.is_undefined() && + !val.is_null() + } + // /// Get the custom sections of the module given a `name`. // /// // /// # Important diff --git a/lib/api/src/js/store.rs b/lib/api/src/js/store.rs index 66d6d58ec8c..a14a663d963 100644 --- a/lib/api/src/js/store.rs +++ b/lib/api/src/js/store.rs @@ -446,6 +446,7 @@ mod objects { Instance(NonNull), } + #[allow(dead_code)] impl MaybeInstanceOwned { /// Returns underlying pointer to the VM data. #[allow(dead_code)] diff --git a/lib/api/src/js/wasm_bindgen_polyfill.rs b/lib/api/src/js/wasm_bindgen_polyfill.rs index 1b5dad63a12..80f89a6a702 100644 --- a/lib/api/src/js/wasm_bindgen_polyfill.rs +++ b/lib/api/src/js/wasm_bindgen_polyfill.rs @@ -16,6 +16,7 @@ extern "C" { /// of the given type and value. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global) + #[allow(unused_doc_comments)] #[wasm_bindgen(constructor, js_namespace = WebAssembly, catch)] pub fn new(global_descriptor: &Object, value: &JsValue) -> Result; @@ -23,6 +24,7 @@ extern "C" { /// returns the value of the global. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global) + #[allow(unused_doc_comments)] #[wasm_bindgen(method, getter, structural, js_namespace = WebAssembly)] pub fn value(this: &Global) -> JsValue; diff --git a/lib/api/src/sys/exports.rs b/lib/api/src/sys/exports.rs index f744a21c61d..0141f8cd9ea 100644 --- a/lib/api/src/sys/exports.rs +++ b/lib/api/src/sys/exports.rs @@ -57,6 +57,9 @@ pub enum ExportError { /// This error arises when an export is missing #[error("Missing export {0}")] Missing(String), + /// This error arises when an export is missing + #[error("Serialization failed {0}")] + SerializationFailed(String), } /// Exports is a special kind of map that allows easily unwrapping @@ -183,18 +186,6 @@ impl Exports { } } - /// Like `get_with_generics` but with a WeakReference to the `InstanceRef` internally. - /// This is useful for passing data into Context data, for example. - pub fn get_with_generics_weak<'a, T, Args, Rets>(&'a self, name: &str) -> Result - where - Args: WasmTypeList, - Rets: WasmTypeList, - T: ExportableWithGenerics<'a, Args, Rets>, - { - let out: T = self.get_with_generics(name)?; - Ok(out) - } - /// Get an export as an `Extern`. pub fn get_extern(&self, name: &str) -> Option<&Extern> { self.map.get(name) diff --git a/lib/api/src/sys/function_env.rs b/lib/api/src/sys/function_env.rs index deb5c0b4304..6ef7b48a3c9 100644 --- a/lib/api/src/sys/function_env.rs +++ b/lib/api/src/sys/function_env.rs @@ -29,7 +29,7 @@ impl FunctionEnv { } /// Get the data as reference - pub fn as_ref<'a>(&self, store: &'a impl AsStoreMut) -> &'a T + pub fn as_ref<'a>(&self, store: &'a impl AsStoreRef) -> &'a T where T: Any + Send + 'static + Sized, { @@ -105,6 +105,11 @@ impl FunctionEnvMut<'_, T> { self.func_env.as_mut(&mut self.store_mut) } + /// Borrows a new immmutable reference + pub fn as_ref(&self) -> FunctionEnv { + self.func_env.clone() + } + /// Borrows a new mutable reference pub fn as_mut(&mut self) -> FunctionEnvMut<'_, T> { FunctionEnvMut { diff --git a/lib/api/src/sys/imports.rs b/lib/api/src/sys/imports.rs index 80e51f7367d..82d44eb78da 100644 --- a/lib/api/src/sys/imports.rs +++ b/lib/api/src/sys/imports.rs @@ -176,6 +176,36 @@ impl Imports { } Ok(ret) } + + /// Iterates through all the imports in this structure + pub fn iter<'a>(&'a self) -> ImportsIterator<'a> { + ImportsIterator::new(self) + } +} + +pub struct ImportsIterator<'a> { + iter: std::collections::hash_map::Iter<'a, (String, String), Extern> +} + +impl<'a> ImportsIterator<'a> +{ + fn new(imports: &'a Imports) -> Self { + let iter = imports.map.iter(); + Self { iter } + } +} + +impl<'a> Iterator +for ImportsIterator<'a> { + type Item = (&'a str, &'a str, &'a Extern); + + fn next(&mut self) -> Option { + self.iter + .next() + .map(|(k, v)| { + (k.0.as_str(), k.1.as_str(), v) + }) + } } impl IntoIterator for &Imports { diff --git a/lib/api/src/sys/instance.rs b/lib/api/src/sys/instance.rs index ab8e9d5c293..3cc967530ac 100644 --- a/lib/api/src/sys/instance.rs +++ b/lib/api/src/sys/instance.rs @@ -115,11 +115,11 @@ impl Instance { module: &Module, imports: &Imports, ) -> Result { - let imports = imports + let externs = imports .imports_for_module(module) .map_err(InstantiationError::Link)?; - let mut handle = module.instantiate(store, &imports)?; - let exports = module + let mut handle = module.instantiate(store, &externs)?; + let mut exports = module .exports() .map(|export| { let name = export.name().to_string(); @@ -128,6 +128,14 @@ impl Instance { (name, extern_) }) .collect::(); + + // If the memory is imported then also export it for backwards compatibility reasons + // (many will assume the memory is always exported) - later we can remove this + if exports.get_memory("memory").is_err() { + if let Some(memory) = externs.iter().filter(|a| a.ty(store).memory().is_some()).next() { + exports.insert("memory", memory.clone()); + } + } let instance = Self { _handle: StoreHandle::new(store.objects_mut(), handle), @@ -154,9 +162,9 @@ impl Instance { module: &Module, externs: &[Extern], ) -> Result { - let imports = externs.to_vec(); - let mut handle = module.instantiate(store, &imports)?; - let exports = module + let externs = externs.to_vec(); + let mut handle = module.instantiate(store, &externs)?; + let mut exports = module .exports() .map(|export| { let name = export.name().to_string(); @@ -166,6 +174,14 @@ impl Instance { }) .collect::(); + // If the memory is imported then also export it for backwards compatibility reasons + // (many will assume the memory is always exported) - later we can remove this + if exports.get_memory("memory").is_err() { + if let Some(memory) = externs.iter().filter(|a| a.ty(store).memory().is_some()).next() { + exports.insert("memory", memory.clone()); + } + } + let instance = Self { _handle: StoreHandle::new(store.objects_mut(), handle), module: module.clone(), diff --git a/lib/api/src/sys/module.rs b/lib/api/src/sys/module.rs index b730a19b9dd..98f10287e64 100644 --- a/lib/api/src/sys/module.rs +++ b/lib/api/src/sys/module.rs @@ -438,6 +438,16 @@ impl Module { self.module_info.exports() } + /// Returns true if the module is still ok - this will be + /// false if the module was passed between threads in a + /// way that it became undefined (JS does not share objects + /// between threads except via a post_message()) + pub fn is_ok(&self) -> bool { + // As RUST is a type safe language modules in SYS are always ok + true + } + + /// Get the custom sections of the module given a `name`. /// /// # Important diff --git a/lib/api/src/sys/ptr.rs b/lib/api/src/sys/ptr.rs index f14383946d1..8e7935e2834 100644 --- a/lib/api/src/sys/ptr.rs +++ b/lib/api/src/sys/ptr.rs @@ -76,7 +76,7 @@ impl WasmPtr { /// Get the offset into Wasm linear memory for this `WasmPtr`. #[inline] - pub fn offset(self) -> M::Offset { + pub fn offset(&self) -> M::Offset { self.offset } @@ -97,7 +97,7 @@ impl WasmPtr { /// Checks whether the `WasmPtr` is null. #[inline] - pub fn is_null(self) -> bool { + pub fn is_null(&self) -> bool { self.offset.into() == 0 } @@ -142,19 +142,19 @@ impl WasmPtr { /// Creates a `WasmRef` from this `WasmPtr` which allows reading and /// mutating of the value being pointed to. #[inline] - pub fn deref<'a>(self, view: &'a MemoryView) -> WasmRef<'a, T> { + pub fn deref<'a>(&self, view: &'a MemoryView) -> WasmRef<'a, T> { WasmRef::new(view, self.offset.into()) } /// Reads the address pointed to by this `WasmPtr` in a memory. #[inline] - pub fn read(self, view: &MemoryView) -> Result { + pub fn read(&self, view: &MemoryView) -> Result { self.deref(view).read() } /// Writes to the address pointed to by this `WasmPtr` in a memory. #[inline] - pub fn write(self, view: &MemoryView, val: T) -> Result<(), MemoryAccessError> { + pub fn write(&self, view: &MemoryView, val: T) -> Result<(), MemoryAccessError> { self.deref(view).write(val) } @@ -165,7 +165,7 @@ impl WasmPtr { /// address. #[inline] pub fn slice<'a>( - self, + &self, view: &'a MemoryView, len: M::Offset, ) -> Result, MemoryAccessError> { @@ -178,7 +178,7 @@ impl WasmPtr { /// This last value is not included in the returned vector. #[inline] pub fn read_until( - self, + &self, view: &MemoryView, mut end: impl FnMut(&T) -> bool, ) -> Result, MemoryAccessError> { @@ -202,7 +202,7 @@ impl WasmPtr { /// modified. #[inline] pub fn read_utf8_string( - self, + &self, view: &MemoryView, len: M::Offset, ) -> Result { @@ -215,7 +215,7 @@ impl WasmPtr { /// This method is safe to call even if the memory is being concurrently /// modified. #[inline] - pub fn read_utf8_string_with_nul(self, view: &MemoryView) -> Result { + pub fn read_utf8_string_with_nul(&self, view: &MemoryView) -> Result { let vec = self.read_until(view, |&byte| byte == 0)?; Ok(String::from_utf8(vec)?) } diff --git a/lib/api/src/sys/store.rs b/lib/api/src/sys/store.rs index 542ef61f7e2..e90bbe48c81 100644 --- a/lib/api/src/sys/store.rs +++ b/lib/api/src/sys/store.rs @@ -1,6 +1,5 @@ use crate::sys::tunables::BaseTunables; use std::fmt; -use std::sync::{Arc, RwLock}; #[cfg(feature = "compiler")] use wasmer_compiler::{Engine, EngineBuilder, Tunables}; use wasmer_vm::{init_traps, TrapHandler, TrapHandlerFn}; @@ -33,7 +32,6 @@ pub struct Store { pub(crate) inner: Box, #[cfg(feature = "compiler")] engine: Engine, - trap_handler: Arc>>>>, } impl Store { @@ -80,7 +78,6 @@ impl Store { trap_handler: None, }), engine: engine.cloned(), - trap_handler: Arc::new(RwLock::new(None)), } } @@ -114,8 +111,8 @@ impl PartialEq for Store { unsafe impl TrapHandler for Store { fn custom_trap_handler(&self, call: &dyn Fn(&TrapHandlerFn) -> bool) -> bool { - if let Some(handler) = self.trap_handler.read().unwrap().as_ref() { - call(handler) + if let Some(handler) = self.inner.trap_handler.as_ref() { + call(handler.as_ref()) } else { false } @@ -242,7 +239,7 @@ impl<'a> StoreRef<'a> { self.inner .trap_handler .as_ref() - .map(|handler| handler as *const _) + .map(|handler| handler.as_ref() as *const _) } } diff --git a/lib/api/tests/sys_reference_types.rs b/lib/api/tests/sys_reference_types.rs index b481a07d8f9..22833b7ce11 100644 --- a/lib/api/tests/sys_reference_types.rs +++ b/lib/api/tests/sys_reference_types.rs @@ -44,15 +44,15 @@ mod sys { } let func_to_call = - Function::new_typed_with_env(&mut store, &env, |mut env: FunctionEnvMut| -> i32 { - env.data_mut().0.store(true, Ordering::SeqCst); + Function::new_typed_with_env(&mut store, &env, |env: FunctionEnvMut| -> i32 { + env.data().0.store(true, Ordering::SeqCst); 343 }); let call_set_value: &Function = instance.exports.get_function("call_set_value")?; let results: Box<[Value]> = call_set_value.call(&mut store, &[Value::FuncRef(Some(func_to_call))])?; assert!(env - .as_mut(&mut store.as_store_mut()) + .as_ref(&store.as_store_ref()) .0 .load(Ordering::SeqCst)); assert_eq!(&*results, &[Value::I32(343)]); diff --git a/lib/c-api/src/wasm_c_api/wasi/mod.rs b/lib/c-api/src/wasm_c_api/wasi/mod.rs index 4501b83f44f..a4a40358f10 100644 --- a/lib/c-api/src/wasm_c_api/wasi/mod.rs +++ b/lib/c-api/src/wasm_c_api/wasi/mod.rs @@ -197,14 +197,6 @@ pub unsafe extern "C" fn wasi_env_new( #[no_mangle] pub extern "C" fn wasi_env_delete(_state: Option>) {} -/// Set the memory on a [`wasi_env_t`]. -#[no_mangle] -pub unsafe extern "C" fn wasi_env_set_memory(env: &mut wasi_env_t, memory: &wasm_memory_t) { - let mut store_mut = env.store.store_mut(); - let wasi_env = env.inner.data_mut(&mut store_mut); - wasi_env.set_memory(memory.extern_.memory()); -} - #[no_mangle] pub unsafe extern "C" fn wasi_env_read_stdout( env: &mut wasi_env_t, @@ -212,8 +204,8 @@ 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 store_mut = env.store.store_mut(); - let state = env.inner.data_mut(&mut store_mut).state(); + let store = env.store.store(); + let state = env.inner.data(&store).state(); if let Ok(mut stdout) = state.stdout() { if let Some(stdout) = stdout.as_mut() { @@ -382,11 +374,10 @@ pub unsafe extern "C" fn wasi_env_initialize_instance( store: &mut wasm_store_t, instance: &mut wasm_instance_t, ) -> bool { - let mem = c_try!(instance.inner.exports.get_memory("memory"); otherwise false); wasi_env .inner - .data_mut(&mut store.inner.store_mut()) - .set_memory(mem.clone()); + .initialize(&mut store.inner.store_mut(), &instance.inner) + .unwrap(); true } diff --git a/lib/cli/src/commands/run.rs b/lib/cli/src/commands/run.rs index 4c742306e00..5cbce9d0f3c 100644 --- a/lib/cli/src/commands/run.rs +++ b/lib/cli/src/commands/run.rs @@ -382,6 +382,9 @@ impl Run { name, suggestion ), + ExportError::SerializationFailed(err) => { + anyhow!("Failed to serialize the module - {}", err) + } } } })? diff --git a/lib/cli/src/commands/run/wasi.rs b/lib/cli/src/commands/run/wasi.rs index af971543696..a5c16169ed2 100644 --- a/lib/cli/src/commands/run/wasi.rs +++ b/lib/cli/src/commands/run/wasi.rs @@ -4,7 +4,7 @@ use std::collections::BTreeSet; use std::path::PathBuf; use wasmer::{AsStoreMut, FunctionEnv, Instance, Module, RuntimeError, Value}; use wasmer_wasi::{ - get_wasi_versions, import_object_for_all_wasi_versions, is_wasix_module, WasiEnv, WasiError, + get_wasi_versions, import_object_for_all_wasi_versions, WasiEnv, WasiError, WasiState, WasiVersion, }; @@ -69,7 +69,7 @@ impl Wasi { /// Helper function for instantiating a module with Wasi imports for the `Run` command. pub fn instantiate( &self, - store: &mut impl AsStoreMut, + mut store: &mut impl AsStoreMut, module: &Module, program_name: String, args: Vec, @@ -91,16 +91,12 @@ impl Wasi { } } - let wasi_env = wasi_state_builder.finalize(store)?; - wasi_env.env.as_mut(store).state.fs.is_wasix.store( - is_wasix_module(module), - std::sync::atomic::Ordering::Release, - ); + let mut wasi_env = wasi_state_builder.finalize(store)?; let mut import_object = import_object_for_all_wasi_versions(store, &wasi_env.env); - import_object.import_shared_memory(module, store); + import_object.import_shared_memory(module, &mut store); + let instance = Instance::new(store, module, &import_object)?; - let memory = instance.exports.get_memory("memory")?; - wasi_env.data_mut(store).set_memory(memory.clone()); + wasi_env.initialize(&mut store, &instance)?; Ok((wasi_env.env, instance)) } diff --git a/lib/cli/src/commands/wasmer_create_exe_main.c b/lib/cli/src/commands/wasmer_create_exe_main.c index a58fb5c73c2..a1966b106cc 100644 --- a/lib/cli/src/commands/wasmer_create_exe_main.c +++ b/lib/cli/src/commands/wasmer_create_exe_main.c @@ -149,23 +149,11 @@ int main(int argc, char *argv[]) { } #ifdef WASI - // Read the exports. - wasm_extern_vec_t exports; - wasm_instance_exports(instance, &exports); - wasm_memory_t* mem = NULL; - for (size_t i = 0; i < exports.size; i++) { - mem = wasm_extern_as_memory(exports.data[i]); - if (mem) { - break; - } - } - - if (!mem) { - fprintf(stderr, "Failed to create instance: Could not find memory in exports\n"); + if (!wasi_env_initialize_instance(wasi_env, store, instance)) { + fprintf(stderr, "Failed to initialize env\n"); print_wasmer_error(); return -1; } - wasi_env_set_memory(wasi_env, mem); own wasm_func_t *start_function = wasi_get_start_function(instance); if (!start_function) { diff --git a/lib/cli/src/commands/wasmer_static_create_exe_main.c b/lib/cli/src/commands/wasmer_static_create_exe_main.c index 2276ed3bc75..20e6d13bff5 100644 --- a/lib/cli/src/commands/wasmer_static_create_exe_main.c +++ b/lib/cli/src/commands/wasmer_static_create_exe_main.c @@ -144,23 +144,11 @@ int main(int argc, char *argv[]) { } #ifdef WASI - // Read the exports. - wasm_extern_vec_t exports; - wasm_instance_exports(instance, &exports); - wasm_memory_t* mem = NULL; - for (size_t i = 0; i < exports.size; i++) { - mem = wasm_extern_as_memory(exports.data[i]); - if (mem) { - break; - } - } - - if (!mem) { - fprintf(stderr, "Failed to create instance: Could not find memory in exports\n"); + if (!wasi_env_initialize_instance(wasi_env, store, instance)) { + fprintf(stderr, "Failed to initialize env\n"); print_wasmer_error(); return -1; } - wasi_env_set_memory(wasi_env, mem); own wasm_func_t *start_function = wasi_get_start_function(instance); if (!start_function) { diff --git a/lib/derive/src/value_type.rs b/lib/derive/src/value_type.rs index 5e9fe23c826..0280f5ead13 100644 --- a/lib/derive/src/value_type.rs +++ b/lib/derive/src/value_type.rs @@ -1,7 +1,7 @@ use proc_macro2::TokenStream; use proc_macro_error::abort; use quote::quote; -use syn::{Data, DeriveInput, Fields, Member, Meta, MetaList, NestedMeta}; +use syn::{Data, DeriveInput, Member, Meta, MetaList, NestedMeta, Field}; /// We can only validate types that have a well defined layout. fn check_repr(input: &DeriveInput) { @@ -35,7 +35,7 @@ fn check_repr(input: &DeriveInput) { } /// Zero out any padding bytes between fields. -fn zero_padding(fields: &Fields) -> TokenStream { +fn zero_padding(fields: Vec<&Field>) -> TokenStream { let names: Vec<_> = fields .iter() .enumerate() @@ -93,18 +93,18 @@ pub fn impl_value_type(input: &DeriveInput) -> TokenStream { let struct_name = &input.ident; let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); - let fields = match &input.data { - Data::Struct(ds) => &ds.fields, + let zero_padding = match &input.data { + Data::Struct(ds) => zero_padding(ds.fields.iter().collect()), _ => abort!(input, "ValueType can only be derived for structs"), }; - let zero_padding = zero_padding(fields); - quote! { unsafe impl #impl_generics ::wasmer::ValueType for #struct_name #ty_generics #where_clause { #[inline] fn zero_padding_bytes(&self, _bytes: &mut [::core::mem::MaybeUninit]) { - #zero_padding + unsafe { + #zero_padding + } } } } diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index 1e4b7af80ea..8a6a2f794f8 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -25,7 +25,7 @@ use std::sync::{Arc, Mutex, RwLock}; use wasmer::{ imports, namespace, AsStoreMut, ExportError, Exports, Function, FunctionEnv, FunctionEnvMut, FunctionType, Global, Imports, Instance, Memory, MemoryType, Module, Pages, RuntimeError, - Table, TableType, TypedFunction, Value, WasmPtr, + Table, TableType, TypedFunction, Value, WasmPtr, AsStoreRef, }; use wasmer_types::Type as ValType; @@ -98,7 +98,7 @@ impl EmEnv { } } - pub fn set_memory(&mut self, memory: Memory) { + pub fn set_memory(&self, memory: Memory) { let mut w = self.memory.write().unwrap(); *w = Some(memory); } @@ -108,12 +108,13 @@ impl EmEnv { (&*self.memory.read().unwrap()).as_ref().cloned().unwrap() } - pub fn set_functions(&mut self, funcs: EmscriptenFunctions) { - self.funcs = Arc::new(Mutex::new(funcs)); + pub fn set_functions(&self, funcs: EmscriptenFunctions) { + let mut w = self.funcs.lock().unwrap(); + *w = funcs; } pub fn set_data( - &mut self, + &self, data: &EmscriptenGlobalsData, mapped_dirs: HashMap, ) { @@ -823,7 +824,7 @@ pub fn run_emscripten_instance( if let Ok(func) = instance.exports.get_typed_function(&env, "setThrew") { emfuncs.set_threw = Some(func); } - env.data_mut().set_functions(emfuncs); + env.data().set_functions(emfuncs); set_up_emscripten(&mut env, instance)?; @@ -864,12 +865,12 @@ fn store_module_arguments(env: &mut FunctionEnvMut, args: Vec<&str>) -> ( } pub fn emscripten_set_up_memory( - store: &mut impl AsStoreMut, + store: &impl AsStoreRef, env: &FunctionEnv, memory: &Memory, globals: &EmscriptenGlobalsData, ) -> Result<(), String> { - env.as_mut(store).set_memory(memory.clone()); + env.as_ref(store).set_memory(memory.clone()); let memory = memory.view(store); let dynamictop_ptr = WasmPtr::::new(globals.dynamictop_ptr).deref(&memory); let dynamic_base = globals.dynamic_base; diff --git a/lib/emscripten/src/memory.rs b/lib/emscripten/src/memory.rs index 2c905e30c88..4294a42cbfc 100644 --- a/lib/emscripten/src/memory.rs +++ b/lib/emscripten/src/memory.rs @@ -110,6 +110,8 @@ pub fn sbrk(mut ctx: FunctionEnvMut, increment: i32) -> i32 { increment, total_memory ); + drop(dynamictop_ptr); + if increment > 0 && new_dynamic_top < old_dynamic_top || new_dynamic_top < 0 { abort_on_cannot_grow_memory_old(ctx); return -1; diff --git a/lib/vbus/src/lib.rs b/lib/vbus/src/lib.rs index e51ec11ffac..0cda403e17b 100644 --- a/lib/vbus/src/lib.rs +++ b/lib/vbus/src/lib.rs @@ -5,8 +5,9 @@ use thiserror::Error; pub use wasmer_vfs::FileDescriptor; pub use wasmer_vfs::StdioMode; +use wasmer_vfs::VirtualFile; -pub type Result = std::result::Result; +pub type Result = std::result::Result; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] #[repr(transparent)] @@ -26,10 +27,14 @@ impl From for CallDescriptor { pub trait VirtualBus: fmt::Debug + Send + Sync + 'static { /// Starts a new WAPM sub process - fn new_spawn(&self) -> SpawnOptions; + fn new_spawn(&self) -> SpawnOptions { + SpawnOptions::new(Box::new(UnsupportedVirtualBusSpawner::default())) + } /// Creates a listener thats used to receive BUS commands - fn listen(&self) -> Result>; + fn listen<'a>(&'a self) -> Result<&'a dyn VirtualBusListener> { + Err(VirtualBusError::Unsupported) + } } pub trait VirtualBusSpawner { @@ -46,7 +51,7 @@ pub struct SpawnOptionsConfig { stdin_mode: StdioMode, stdout_mode: StdioMode, stderr_mode: StdioMode, - working_dir: String, + working_dir: Option, remote_instance: Option, access_token: Option, } @@ -80,8 +85,8 @@ impl SpawnOptionsConfig { self.stderr_mode } - pub fn working_dir(&self) -> &str { - self.working_dir.as_str() + pub fn working_dir(&self) -> Option<&str> { + self.working_dir.as_ref().map(|a| a.as_str()) } pub fn remote_instance(&self) -> Option<&str> { @@ -110,7 +115,7 @@ impl SpawnOptions { stdin_mode: StdioMode::Null, stdout_mode: StdioMode::Null, stderr_mode: StdioMode::Null, - working_dir: "/".to_string(), + working_dir: None, remote_instance: None, access_token: None, }, @@ -157,7 +162,7 @@ impl SpawnOptions { } pub fn working_dir(&mut self, working_dir: String) -> &mut Self { - self.conf.working_dir = working_dir; + self.conf.working_dir = Some(working_dir); self } @@ -179,8 +184,18 @@ impl SpawnOptions { #[derive(Debug)] pub struct BusSpawnedProcess { + /// Name of the spawned process + pub name: String, + /// Configuration applied to this spawned thread + pub config: SpawnOptionsConfig, /// Reference to the spawned instance - pub inst: Box, + pub inst: Box, + /// Virtual file used for stdin + pub stdin: Option>, + /// Virtual file used for stdout + pub stdout: Option>, + /// Virtual file used for stderr + pub stderr: Option>, } pub trait VirtualBusScope: fmt::Debug + Send + Sync + 'static { @@ -192,10 +207,15 @@ pub trait VirtualBusInvokable: fmt::Debug + Send + Sync + 'static { /// Invokes a service within this instance fn invoke( &self, - topic: String, + topic_hash: u128, format: BusDataFormat, - buf: &[u8], - ) -> Result>; + buf: Vec, + ) -> Box; +} + +pub trait VirtualBusInvoked: fmt::Debug + Unpin + 'static { + //// Returns once the bus has been invoked (or failed) + fn poll_invoked(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>>; } pub trait VirtualBusProcess: @@ -204,29 +224,117 @@ pub trait VirtualBusProcess: /// Returns the exit code if the instance has finished fn exit_code(&self) -> Option; - /// Returns a file descriptor used to read the STDIN - fn stdin_fd(&self) -> Option; - - /// Returns a file descriptor used to write to STDOUT - fn stdout_fd(&self) -> Option; - - /// Returns a file descriptor used to write to STDERR - fn stderr_fd(&self) -> Option; + /// Polls to check if the process is ready yet to receive commands + fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()>; } pub trait VirtualBusInvocation: - VirtualBusScope + VirtualBusInvokable + fmt::Debug + Send + Sync + 'static + VirtualBusInvokable + fmt::Debug + Send + Sync + Unpin + 'static { /// Polls for new listen events related to this context fn poll_event(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll; } +#[derive(Debug)] +pub struct InstantInvocation +{ + val: Option, + err: Option, + call: Option>, +} + +impl InstantInvocation +{ + pub fn response(format: BusDataFormat, data: Vec) -> Self { + Self { + val: Some(BusInvocationEvent::Response { format, data }), + err: None, + call: None + } + } + + pub fn fault(err: VirtualBusError) -> Self { + Self { + val: None, + err: Some(err), + call: None + } + } + + pub fn call(val: Box) -> Self { + Self { + val: None, + err: None, + call: Some(val) + } + } +} + +impl VirtualBusInvoked +for InstantInvocation +{ + fn poll_invoked(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll>> { + if let Some(err) = self.err.take() { + return Poll::Ready(Err(err)); + } + if let Some(val) = self.val.take() { + return Poll::Ready(Ok(Box::new(InstantInvocation { + val: Some(val), + err: None, + call: None, + }))); + } + match self.call.take() { + Some(val) => { + Poll::Ready(Ok(val)) + }, + None => { + Poll::Ready(Err(VirtualBusError::AlreadyConsumed)) + } + } + } +} + +impl VirtualBusInvocation +for InstantInvocation +{ + fn poll_event(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { + match self.val.take() { + Some(val) => { + Poll::Ready(val) + }, + None => { + Poll::Ready(BusInvocationEvent::Fault { fault: VirtualBusError::AlreadyConsumed }) + } + } + } +} + +impl VirtualBusInvokable +for InstantInvocation +{ + fn invoke( + &self, + _topic_hash: u128, + _format: BusDataFormat, + _buf: Vec, + ) -> Box { + Box::new( + InstantInvocation { + val: None, + err: Some(VirtualBusError::InvalidTopic), + call: None + } + ) + } +} + #[derive(Debug)] pub enum BusInvocationEvent { /// The server has sent some out-of-band data to you Callback { /// Topic that this call relates to - topic: String, + topic_hash: u128, /// Format of the data we received format: BusDataFormat, /// Data passed in the call @@ -239,34 +347,43 @@ pub enum BusInvocationEvent { /// Data returned by the call data: Vec, }, + /// The service has responded with a fault + Fault { + /// Fault code that was raised + fault: VirtualBusError + } } -pub trait VirtualBusListener: fmt::Debug + Send + Sync + 'static { +pub trait VirtualBusListener: fmt::Debug + Send + Sync + Unpin + 'static { /// Polls for new calls to this service - fn poll_call(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll; + fn poll(self: Pin<&Self>, cx: &mut Context<'_>) -> Poll; } #[derive(Debug)] pub struct BusCallEvent { - /// Topic that this call relates to - pub topic: String, + /// Topic hash that this call relates to + pub topic_hash: u128, /// Reference to the call itself - pub called: Box, + pub called: Box, /// Format of the data we received pub format: BusDataFormat, /// Data passed in the call pub data: Vec, } -pub trait VirtualBusCalled: VirtualBusListener + fmt::Debug + Send + Sync + 'static { +pub trait VirtualBusCalled: fmt::Debug + Send + Sync + 'static +{ + /// Polls for new calls to this service + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll; + /// Sends an out-of-band message back to the caller - fn callback(&self, topic: String, format: BusDataFormat, buf: &[u8]) -> Result<()>; + fn callback(&self, topic_hash: u128, format: BusDataFormat, buf: Vec); /// Informs the caller that their call has failed - fn fault(self, fault: BusError) -> Result<()>; + fn fault(self: Box, fault: VirtualBusError); /// Finishes the call and returns a particular response - fn reply(self, format: BusDataFormat, buf: &[u8]) -> Result<()>; + fn reply(&self, format: BusDataFormat, buf: Vec); } /// Format that the supplied data is in @@ -284,13 +401,6 @@ pub enum BusDataFormat { pub struct UnsupportedVirtualBus {} impl VirtualBus for UnsupportedVirtualBus { - fn new_spawn(&self) -> SpawnOptions { - SpawnOptions::new(Box::new(UnsupportedVirtualBusSpawner::default())) - } - - fn listen(&self) -> Result> { - Err(BusError::Unsupported) - } } #[derive(Debug, Default)] @@ -298,12 +408,12 @@ pub struct UnsupportedVirtualBusSpawner {} impl VirtualBusSpawner for UnsupportedVirtualBusSpawner { fn spawn(&mut self, _name: &str, _config: &SpawnOptionsConfig) -> Result { - Err(BusError::Unsupported) + Err(VirtualBusError::Unsupported) } } #[derive(Error, Copy, Clone, Debug, PartialEq, Eq)] -pub enum BusError { +pub enum VirtualBusError { /// Failed during serialization #[error("serialization failed")] Serialization, diff --git a/lib/wasi-types/src/bus.rs b/lib/wasi-types/src/bus.rs index ff8bea2ecb3..33ff6e77ec4 100644 --- a/lib/wasi-types/src/bus.rs +++ b/lib/wasi-types/src/bus.rs @@ -1,6 +1,7 @@ use super::*; use wasmer_derive::ValueType; -use wasmer_types::MemorySize; + +pub type __wasi_hash_t = u128; pub type __wasi_busdataformat_t = u8; pub const __WASI_BUS_DATA_FORMAT_RAW: __wasi_busdataformat_t = 0; @@ -28,7 +29,7 @@ pub struct __wasi_option_bid_t { pub bid: __wasi_bid_t, } -pub type __wasi_cid_t = u8; +pub type __wasi_cid_t = u64; #[derive(Debug, Copy, Clone, PartialEq, Eq, ValueType)] #[repr(C)] @@ -62,23 +63,20 @@ pub struct __wasi_busevent_exit_t { #[derive(Debug, Copy, Clone, PartialEq, Eq, ValueType)] #[repr(C)] -pub struct __wasi_busevent_call_t { +pub struct __wasi_busevent_call_t { pub parent: __wasi_option_cid_t, pub cid: __wasi_cid_t, pub format: __wasi_busdataformat_t, - pub topic_ptr: M::Offset, - pub topic_len: M::Offset, - pub buf_ptr: M::Offset, - pub buf_len: M::Offset, + pub topic_hash: __wasi_hash_t, + pub fd: __wasi_fd_t, } #[derive(Debug, Copy, Clone, PartialEq, Eq, ValueType)] #[repr(C)] -pub struct __wasi_busevent_result_t { +pub struct __wasi_busevent_result_t { pub format: __wasi_busdataformat_t, pub cid: __wasi_cid_t, - pub buf_ptr: M::Offset, - pub buf_len: M::Offset, + pub fd: __wasi_fd_t, } #[derive(Debug, Copy, Clone, PartialEq, Eq, ValueType)] @@ -96,18 +94,25 @@ pub struct __wasi_busevent_close_t { #[derive(Copy, Clone)] #[repr(C)] -pub union __wasi_busevent_u { +pub union __wasi_busevent_u { pub noop: u8, pub exit: __wasi_busevent_exit_t, - pub call: __wasi_busevent_call_t, - pub result: __wasi_busevent_result_t, + pub call: __wasi_busevent_call_t, + pub result: __wasi_busevent_result_t, pub fault: __wasi_busevent_fault_t, pub close: __wasi_busevent_close_t, } +#[derive(Copy, Clone, ValueType)] +#[repr(C)] +pub struct __wasi_busevent_t { + pub tag: __wasi_buseventtype_t, + pub padding: [u8; 63], +} + #[derive(Copy, Clone)] #[repr(C)] -pub struct __wasi_busevent_t { +pub struct __wasi_busevent_t2 { pub tag: __wasi_buseventtype_t, - pub u: __wasi_busevent_u, + pub u: __wasi_busevent_u, } diff --git a/lib/wasi-types/src/file.rs b/lib/wasi-types/src/file.rs index 0d58ba9bbe4..92f0e74a6be 100644 --- a/lib/wasi-types/src/file.rs +++ b/lib/wasi-types/src/file.rs @@ -18,6 +18,9 @@ pub const __WASI_STDERR_FILENO: __wasi_fd_t = 2; pub type __wasi_pid_t = u32; pub type __wasi_tid_t = u32; +pub type __wasi_tl_key_t = u32; +pub type __wasi_tl_val_t = u64; + pub type __wasi_fdflags_t = u16; pub const __WASI_FDFLAG_APPEND: __wasi_fdflags_t = 1 << 0; pub const __WASI_FDFLAG_DSYNC: __wasi_fdflags_t = 1 << 1; diff --git a/lib/wasi/Cargo.toml b/lib/wasi/Cargo.toml index bfa746e2921..7f4a456d44c 100644 --- a/lib/wasi/Cargo.toml +++ b/lib/wasi/Cargo.toml @@ -31,6 +31,10 @@ bincode = { version = "1.3", optional = true } chrono = { version = "^0.4", default-features = false, features = [ "wasmbind", "std", "clock" ], optional = true } derivative = { version = "^2" } bytes = "1" +lazy_static = "1.4" +sha2 = { version = "0.10" } +waker-fn = { version = "1.1" } +cooked-waker = "^5" [target.'cfg(unix)'.dependencies] libc = { version = "^0.2", default-features = false } @@ -45,18 +49,23 @@ wasm-bindgen = "0.2.74" wasm-bindgen-test = "0.3.0" tracing-wasm = "0.2" +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] +tracing-subscriber = { version = "^0.2" } + [features] default = ["sys-default"] sys = ["wasmer/sys"] -sys-default = ["wasmer/wat", "wasmer/compiler", "sys", "logging", "host-fs", "sys-poll", "host-vnet" ] +sys-default = ["wasmer/wat", "wasmer/compiler", "sys", "logging", "host-fs", "sys-poll", "sys-thread", "host-vnet", "host-threads" ] sys-poll = [] +sys-thread = [] js = ["wasmer/js", "mem-fs", "wasmer-vfs/no-time", "getrandom/js", "chrono"] js-default = ["js", "wasmer/js-default"] test-js = ["js", "wasmer/js-default", "wasmer/wat"] host-vnet = [ "wasmer-wasi-local-networking" ] +host-threads = [] host-fs = ["wasmer-vfs/host-fs"] mem-fs = ["wasmer-vfs/mem-fs"] diff --git a/lib/wasi/src/lib.rs b/lib/wasi/src/lib.rs index 4daeb25a47d..ed1152f5ac0 100644 --- a/lib/wasi/src/lib.rs +++ b/lib/wasi/src/lib.rs @@ -40,8 +40,6 @@ mod state; mod syscalls; mod utils; -use crate::syscalls::*; - pub use crate::state::{ Fd, Pipe, Stderr, Stdin, Stdout, WasiFs, WasiInodes, WasiState, WasiStateBuilder, WasiStateCreationError, ALL_RIGHTS, VIRTUAL_ROOT_FD, @@ -50,6 +48,11 @@ pub use crate::syscalls::types; pub use crate::utils::{ get_wasi_version, get_wasi_versions, is_wasi_module, is_wasix_module, WasiVersion, }; +#[allow(unused_imports)] +#[cfg(feature = "js")] +use bytes::Bytes; +use derivative::Derivative; +use tracing::trace; pub use wasmer_vbus::{UnsupportedVirtualBus, VirtualBus}; #[deprecated(since = "2.1.0", note = "Please use `wasmer_vfs::FsError`")] pub use wasmer_vfs::FsError as WasiFsError; @@ -59,18 +62,19 @@ pub use wasmer_vfs::{FsError, VirtualFile}; pub use wasmer_vnet::{UnsupportedVirtualNetworking, VirtualNetworking}; use wasmer_wasi_types::__WASI_CLOCK_MONOTONIC; -use derivative::*; +use std::cell::RefCell; use std::ops::Deref; +use std::sync::atomic::{AtomicU32, Ordering}; use thiserror::Error; use wasmer::{ - imports, namespace, AsStoreMut, AsStoreRef, Exports, Function, FunctionEnv, Imports, Memory, - Memory32, MemoryAccessError, MemorySize, MemoryView, Module, TypedFunction, + imports, namespace, AsStoreMut, Exports, Function, FunctionEnv, Imports, Memory, Memory32, + MemoryAccessError, MemorySize, Module, TypedFunction, Memory64, MemoryView, AsStoreRef, Instance, ExportError }; pub use runtime::{ - PluggableRuntimeImplementation, WasiRuntimeImplementation, WasiThreadError, WasiTtyState, + PluggableRuntimeImplementation, WasiRuntimeImplementation, WasiThreadError, WasiTtyState }; -use std::sync::{mpsc, Arc, Mutex, RwLockReadGuard, RwLockWriteGuard}; +use std::sync::{Arc, RwLockReadGuard, RwLockWriteGuard}; use std::time::Duration; /// This is returned in `RuntimeError`. @@ -84,9 +88,20 @@ pub enum WasiError { } /// Represents the ID of a WASI thread -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct WasiThreadId(u32); +impl WasiThreadId { + pub fn raw(&self) -> u32 { + self.0 + } + + pub fn inc(&mut self) -> WasiThreadId { + self.0 += 1; + self.clone() + } +} + impl From for WasiThreadId { fn from(id: u32) -> Self { Self(id) @@ -98,203 +113,156 @@ impl From for u32 { } } -/// Represents the ID of a sub-process -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct WasiBusProcessId(u32); +/// Represents the ID of a WASI calling thread +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct WasiCallingId(u32); -impl From for WasiBusProcessId { - fn from(id: u32) -> Self { - Self(id) +impl WasiCallingId { + pub fn raw(&self) -> u32 { + self.0 } -} -impl From for u32 { - fn from(id: WasiBusProcessId) -> u32 { - id.0 as u32 - } -} -#[derive(Debug, Clone)] -pub struct WasiThread { - /// ID of this thread - #[allow(dead_code)] - id: WasiThreadId, - /// Signalers used to tell joiners that the thread has exited - exit: Arc>>>, - /// Event to wait on for the thread to join - join: Arc>>, + pub fn inc(&mut self) -> WasiCallingId { + self.0 += 1; + self.clone() + } } -impl WasiThread { - /// Waits for the thread to exit (false = timeout) - pub fn join(&self, timeout: Duration) -> bool { - let guard = self.join.lock().unwrap(); - let timeout = guard.recv_timeout(timeout); - match timeout { - Ok(_) => true, - Err(mpsc::RecvTimeoutError::Disconnected) => true, - Err(mpsc::RecvTimeoutError::Timeout) => false, - } +impl From for WasiCallingId { + fn from(id: u32) -> Self { + Self(id) } } - -pub struct WasiFunctionEnv { - pub env: FunctionEnv, +impl From for u32 { + fn from(t: WasiCallingId) -> u32 { + t.0 as u32 + } } -impl WasiFunctionEnv { - pub fn new(store: &mut impl AsStoreMut, env: WasiEnv) -> Self { - Self { - env: FunctionEnv::new(store, env), - } - } +/// Represents the ID of a sub-process +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct WasiBusProcessId(u32); - /// Get an `Imports` for a specific version of WASI detected in the module. - pub fn import_object( - &self, - store: &mut impl AsStoreMut, - module: &Module, - ) -> Result { - let wasi_version = get_wasi_version(module, false).ok_or(WasiError::UnknownWasiVersion)?; - Ok(generate_import_object_from_env( - store, - &self.env, - wasi_version, - )) +impl From for WasiBusProcessId { + fn from(id: u32) -> Self { + Self(id) } - - pub fn data_mut<'a>(&'a self, store: &'a mut impl AsStoreMut) -> &'a mut WasiEnv { - self.env.as_mut(store) +} +impl Into for WasiBusProcessId { + fn into(self) -> u32 { + self.0 as u32 } +} - /// Like `import_object` but containing all the WASI versions detected in - /// the module. - pub fn import_object_for_all_wasi_versions( - &self, - store: &mut impl AsStoreMut, - module: &Module, - ) -> Result { - let wasi_versions = - get_wasi_versions(module, false).ok_or(WasiError::UnknownWasiVersion)?; - - let mut resolver = Imports::new(); - for version in wasi_versions.iter() { - let new_import_object = generate_import_object_from_env(store, &self.env, *version); - for ((n, m), e) in new_import_object.into_iter() { - resolver.define(&n, &m, e); - } - } - - if is_wasix_module(module) { - self.data_mut(store) - .state - .fs - .is_wasix - .store(true, std::sync::atomic::Ordering::Release); - } - - Ok(resolver) - } +#[derive(Clone)] +pub struct WasiEnvInner +{ + /// Represents a reference to the memory + memory: Memory, + /// Represents the module that is being used (this is NOT send/sync) + /// however the code itself makes sure that it is used in a safe way + module: Module, + /// Represents the callback for spawning a thread (name = "_start_thread") + thread_spawn: Option>, + /// Represents the callback for spawning a reactor (name = "_react") + react: Option>, + /// Represents the callback for destroying a local thread variable (name = "_thread_local_destroy") + thread_local_destroy: Option>, + /// Represents the callback for allocating memory (name = "_malloc") + _malloc: Option>, + /// Represents the callback for deallocating memory (name = "_free") + _free: Option>, } +/// The code itself makes safe use of the struct so multiple threads don't access +/// it (without this the JS code prevents the reference to the module from being stored +/// which is needed for the multithreading mode) +unsafe impl Send for WasiEnvInner { } +unsafe impl Sync for WasiEnvInner { } + /// The environment provided to the WASI imports. #[derive(Derivative, Clone)] #[derivative(Debug)] -#[allow(dead_code)] -pub struct WasiEnv { +pub struct WasiEnv +where +{ /// ID of this thread (zero is the main thread) id: WasiThreadId, - /// Represents a reference to the memory - memory: Option, - /// If the module has it then map the thread start - #[derivative(Debug = "ignore")] - thread_start: Option>, - #[derivative(Debug = "ignore")] - reactor_work: Option>, - #[derivative(Debug = "ignore")] - reactor_finish: Option>, - #[derivative(Debug = "ignore")] - malloc: Option>, - #[derivative(Debug = "ignore")] - free: Option>, /// Shared state of the WASI system. Manages all the data that the /// executing WASI program can see. pub state: Arc, + /// Inner functions and references that are loaded before the environment starts + #[derivative(Debug = "ignore")] + pub inner: Option, /// Implementation of the WASI runtime. pub(crate) runtime: Arc, } +// Represents the current thread ID for the executing method +thread_local!(static CALLER_ID: RefCell = RefCell::new(0)); +lazy_static::lazy_static! { + static ref CALLER_ID_SEED: Arc = Arc::new(AtomicU32::new(1)); +} + +/// Returns the current thread ID +pub fn current_caller_id() -> WasiCallingId { + CALLER_ID.with(|f| { + let mut caller_id = f.borrow_mut(); + if *caller_id == 0 { + *caller_id = CALLER_ID_SEED.fetch_add(1, Ordering::AcqRel); + } + *caller_id + }).into() +} + impl WasiEnv { - /// Create a new WasiEnv from a WasiState (memory will be set to None) pub fn new(state: WasiState) -> Self { - Self { + let state = Arc::new(state); + Self::new_ext(state) + } + + fn new_ext(state: Arc) -> Self { + let ret = Self { id: 0u32.into(), - state: Arc::new(state), - memory: None, - thread_start: None, - reactor_work: None, - reactor_finish: None, - malloc: None, - free: None, + state, + inner: None, runtime: Arc::new(PluggableRuntimeImplementation::default()), - } + }; + ret } - + /// Returns a copy of the current runtime implementation for this environment - pub fn runtime(&self) -> &(dyn WasiRuntimeImplementation) { + pub fn runtime<'a>(&'a self) -> &'a (dyn WasiRuntimeImplementation) { self.runtime.deref() } /// Overrides the runtime implementation for this environment - pub fn set_runtime(&mut self, runtime: R) + pub fn set_runtime(&mut self, runtime: R) where R: WasiRuntimeImplementation + Send + Sync + 'static, { self.runtime = Arc::new(runtime); } - /// Returns the current thread ID - pub fn current_thread_id(&self) -> WasiThreadId { - self.id - } - - /// Creates a new thread only this wasi environment - pub fn new_thread(&self) -> WasiThread { - let (tx, rx) = mpsc::channel(); - - let mut guard = self.state.threading.lock().unwrap(); - - guard.thread_seed += 1; - let next_id: WasiThreadId = guard.thread_seed.into(); - - let thread = WasiThread { - id: next_id, - exit: Arc::new(Mutex::new(Some(tx))), - join: Arc::new(Mutex::new(rx)), - }; - - guard.threads.insert(thread.id, thread.clone()); - thread - } - - /// Copy the lazy reference so that when it's initialized during the - /// export phase, all the other references get a copy of it - pub fn memory_clone(&self) -> Option { - self.memory.clone() + /// Returns the number of active threads + pub fn active_threads(&self) -> u32 { + let guard = self.state.threading.read().unwrap(); + guard.active_threads() } // Yields execution pub fn yield_now(&self) -> Result<(), WasiError> { - self.runtime.yield_now(self.id)?; + self.runtime.yield_now(current_caller_id())?; Ok(()) } // Sleeps for a period of time pub fn sleep(&self, duration: Duration) -> Result<(), WasiError> { let duration = duration.as_nanos(); - let start = platform_clock_time_get(__WASI_CLOCK_MONOTONIC, 1_000_000).unwrap() as u128; + let start = syscalls::platform_clock_time_get(__WASI_CLOCK_MONOTONIC, 1_000_000).unwrap() as u128; self.yield_now()?; loop { - let now = platform_clock_time_get(__WASI_CLOCK_MONOTONIC, 1_000_000).unwrap() as u128; + let now = syscalls::platform_clock_time_get(__WASI_CLOCK_MONOTONIC, 1_000_000).unwrap() as u128; let delta = match now.checked_sub(start) { Some(a) => a, None => { @@ -317,44 +285,46 @@ impl WasiEnv { } /// Accesses the virtual networking implementation - pub fn net(&self) -> &(dyn VirtualNetworking) { + pub fn net<'a>(&'a self) -> &'a (dyn VirtualNetworking) { self.runtime.networking() } /// Accesses the virtual bus implementation - pub fn bus(&self) -> &(dyn VirtualBus) { + pub fn bus<'a>(&'a self) -> &'a (dyn VirtualBus) { self.runtime.bus() } - /// Set the memory of the WasiEnv (can only be done once) - pub fn set_memory(&mut self, memory: Memory) { - if self.memory.is_some() { - panic!("Memory of a WasiEnv can only be set once!"); - } - self.memory = Some(memory); + /// Providers safe access to the initialized part of WasiEnv + /// (it must be initialized before it can be used) + pub fn inner(&self) -> &WasiEnvInner { + self.inner.as_ref() + .expect("You must initialize the WasiEnv before using it") } - + /// Providers safe access to the memory /// (it must be initialized before it can be used) pub fn memory_view<'a>(&'a self, store: &'a impl AsStoreRef) -> MemoryView<'a> { self.memory().view(store) } - /// Get memory, that needs to have been set fist + /// Providers safe access to the memory + /// (it must be initialized before it can be used) pub fn memory(&self) -> &Memory { - self.memory.as_ref().unwrap() + &self.inner().memory + } + + /// Copy the lazy reference so that when it's initialized during the + /// export phase, all the other references get a copy of it + pub fn memory_clone(&self) -> Memory { + self.memory().clone() } /// Get the WASI state pub fn state(&self) -> &WasiState { &self.state } - - pub(crate) fn get_memory_and_wasi_state<'a>( - &'a self, - store: &'a impl AsStoreRef, - _mem_index: u32, - ) -> (MemoryView<'a>, &WasiState) { + + pub(crate) fn get_memory_and_wasi_state<'a>(&'a self, store: &'a impl AsStoreRef, _mem_index: u32) -> (MemoryView<'a>, &WasiState) { let memory = self.memory_view(store); let state = self.state.deref(); (memory, state) @@ -383,23 +353,123 @@ impl WasiEnv { } } -/// Create an [`Imports`] from a [`Context`] +pub struct WasiFunctionEnv { + pub env: FunctionEnv, +} + +impl WasiFunctionEnv { + pub fn new(store: &mut impl AsStoreMut, env: WasiEnv) -> Self { + Self { + env: FunctionEnv::new(store, env), + } + } + + /// Get an `Imports` for a specific version of WASI detected in the module. + pub fn import_object( + &self, + store: &mut impl AsStoreMut, + module: &Module, + ) -> Result { + let wasi_version = get_wasi_version(module, false).ok_or(WasiError::UnknownWasiVersion)?; + Ok(generate_import_object_from_env( + store, + &self.env, + wasi_version, + )) + } + + /// Gets a reference to the WasiEnvironment + pub fn data<'a>(&'a self, store: &'a impl AsStoreRef) -> &'a WasiEnv { + self.env.as_ref(store) + } + + /// Gets a mutable- reference to the host state in this context. + pub fn data_mut<'a>(&'a mut self, store: &'a mut impl AsStoreMut) -> &'a mut WasiEnv { + self.env + .as_mut(store) + } + + /// Initializes the WasiEnv using the instance exports + /// (this must be executed before attempting to use it) + /// (as the stores can not by themselves be passed between threads we can store the module + /// in a thread-local variables and use it later - for multithreading) + pub fn initialize(&mut self, store: &mut impl AsStoreMut, instance: &Instance) -> Result<(), ExportError> + { + // List all the exports and imports + for ns in instance.module().exports() { + //trace!("module::export - {} ({:?})", ns.name(), ns.ty()); + trace!("module::export - {}", ns.name()); + } + for ns in instance.module().imports() { + trace!("module::import - {}::{}", ns.module(), ns.name()); + } + + // First we get the malloc function which if it exists will be used to + // create the pthread_self structure + let memory = instance.exports.get_memory("memory")?.clone(); + let new_inner = WasiEnvInner { + memory, + module: instance.module().clone(), + thread_spawn: instance.exports.get_typed_function(store, "_start_thread").ok(), + react: instance.exports.get_typed_function(store, "_react").ok(), + thread_local_destroy: instance.exports.get_typed_function(store, "_thread_local_destroy").ok(), + _malloc: instance.exports.get_typed_function(&store, "_malloc").ok(), + _free: instance.exports.get_typed_function(store, "_free").ok() + }; + + let env = self.data_mut(store); + env.inner.replace(new_inner); + + env.state.fs.is_wasix.store( + is_wasix_module(instance.module()), + std::sync::atomic::Ordering::Release, + ); + + Ok(()) + } + + /// Like `import_object` but containing all the WASI versions detected in + /// the module. + pub fn import_object_for_all_wasi_versions( + &self, + store: &mut impl AsStoreMut, + module: &Module, + ) -> Result { + let wasi_versions = + get_wasi_versions(module, false).ok_or(WasiError::UnknownWasiVersion)?; + + let mut resolver = Imports::new(); + for version in wasi_versions.iter() { + let new_import_object = generate_import_object_from_env(store, &self.env, *version); + for ((n, m), e) in new_import_object.into_iter() { + resolver.define(&n, &m, e); + } + } + + Ok(resolver) + } +} + +/// Create an [`Imports`] with an existing [`WasiEnv`]. `WasiEnv` +/// needs a [`WasiState`], that can be constructed from a +/// [`WasiStateBuilder`](state::WasiStateBuilder). pub fn generate_import_object_from_env( store: &mut impl AsStoreMut, - env: &FunctionEnv, + ctx: &FunctionEnv, version: WasiVersion, ) -> Imports { match version { - WasiVersion::Snapshot0 => generate_import_object_snapshot0(store, env), + WasiVersion::Snapshot0 => generate_import_object_snapshot0(store, ctx), WasiVersion::Snapshot1 | WasiVersion::Latest => { - generate_import_object_snapshot1(store, env) + generate_import_object_snapshot1(store, ctx) } - WasiVersion::Wasix32v1 => generate_import_object_wasix32_v1(store, env), - WasiVersion::Wasix64v1 => generate_import_object_wasix64_v1(store, env), + WasiVersion::Wasix32v1 => generate_import_object_wasix32_v1(store, ctx), + WasiVersion::Wasix64v1 => generate_import_object_wasix64_v1(store, ctx), } } fn wasi_unstable_exports(mut store: &mut impl AsStoreMut, env: &FunctionEnv) -> Exports { + use syscalls::*; let namespace = namespace! { "args_get" => Function::new_typed_with_env(&mut store, env, args_get::), "args_sizes_get" => Function::new_typed_with_env(&mut store, env, args_sizes_get::), @@ -454,6 +524,7 @@ fn wasi_snapshot_preview1_exports( mut store: &mut impl AsStoreMut, env: &FunctionEnv, ) -> Exports { + use syscalls::*; let namespace = namespace! { "args_get" => Function::new_typed_with_env(&mut store, env, args_get::), "args_sizes_get" => Function::new_typed_with_env(&mut store, env, args_sizes_get::), @@ -503,15 +574,270 @@ fn wasi_snapshot_preview1_exports( }; namespace } + +fn wasix_exports_32( + mut store: &mut impl AsStoreMut, + env: &FunctionEnv, +) -> Exports +{ + use syscalls::*; + let namespace = namespace! { + "args_get" => Function::new_typed_with_env(&mut store, env, args_get::), + "args_sizes_get" => Function::new_typed_with_env(&mut store, env, args_sizes_get::), + "clock_res_get" => Function::new_typed_with_env(&mut store, env, clock_res_get::), + "clock_time_get" => Function::new_typed_with_env(&mut store, env, clock_time_get::), + "environ_get" => Function::new_typed_with_env(&mut store, env, environ_get::), + "environ_sizes_get" => Function::new_typed_with_env(&mut store, env, environ_sizes_get::), + "fd_advise" => Function::new_typed_with_env(&mut store, env, fd_advise), + "fd_allocate" => Function::new_typed_with_env(&mut store, env, fd_allocate), + "fd_close" => Function::new_typed_with_env(&mut store, env, fd_close), + "fd_datasync" => Function::new_typed_with_env(&mut store, env, fd_datasync), + "fd_fdstat_get" => Function::new_typed_with_env(&mut store, env, fd_fdstat_get::), + "fd_fdstat_set_flags" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_flags), + "fd_fdstat_set_rights" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_rights), + "fd_filestat_get" => Function::new_typed_with_env(&mut store, env, fd_filestat_get::), + "fd_filestat_set_size" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_size), + "fd_filestat_set_times" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_times), + "fd_pread" => Function::new_typed_with_env(&mut store, env, fd_pread::), + "fd_prestat_get" => Function::new_typed_with_env(&mut store, env, fd_prestat_get::), + "fd_prestat_dir_name" => Function::new_typed_with_env(&mut store, env, fd_prestat_dir_name::), + "fd_pwrite" => Function::new_typed_with_env(&mut store, env, fd_pwrite::), + "fd_read" => Function::new_typed_with_env(&mut store, env, fd_read::), + "fd_readdir" => Function::new_typed_with_env(&mut store, env, fd_readdir::), + "fd_renumber" => Function::new_typed_with_env(&mut store, env, fd_renumber), + "fd_dup" => Function::new_typed_with_env(&mut store, env, fd_dup::), + "fd_event" => Function::new_typed_with_env(&mut store, env, fd_event::), + "fd_seek" => Function::new_typed_with_env(&mut store, env, fd_seek::), + "fd_sync" => Function::new_typed_with_env(&mut store, env, fd_sync), + "fd_tell" => Function::new_typed_with_env(&mut store, env, fd_tell::), + "fd_write" => Function::new_typed_with_env(&mut store, env, fd_write::), + "fd_pipe" => Function::new_typed_with_env(&mut store, env, fd_pipe::), + "path_create_directory" => Function::new_typed_with_env(&mut store, env, path_create_directory::), + "path_filestat_get" => Function::new_typed_with_env(&mut store, env, path_filestat_get::), + "path_filestat_set_times" => Function::new_typed_with_env(&mut store, env, path_filestat_set_times::), + "path_link" => Function::new_typed_with_env(&mut store, env, path_link::), + "path_open" => Function::new_typed_with_env(&mut store, env, path_open::), + "path_readlink" => Function::new_typed_with_env(&mut store, env, path_readlink::), + "path_remove_directory" => Function::new_typed_with_env(&mut store, env, path_remove_directory::), + "path_rename" => Function::new_typed_with_env(&mut store, env, path_rename::), + "path_symlink" => Function::new_typed_with_env(&mut store, env, path_symlink::), + "path_unlink_file" => Function::new_typed_with_env(&mut store, env, path_unlink_file::), + "poll_oneoff" => Function::new_typed_with_env(&mut store, env, poll_oneoff::), + "proc_exit" => Function::new_typed_with_env(&mut store, env, proc_exit), + "proc_raise" => Function::new_typed_with_env(&mut store, env, proc_raise), + "random_get" => Function::new_typed_with_env(&mut store, env, random_get::), + "tty_get" => Function::new_typed_with_env(&mut store, env, tty_get::), + "tty_set" => Function::new_typed_with_env(&mut store, env, tty_set::), + "getcwd" => Function::new_typed_with_env(&mut store, env, getcwd::), + "chdir" => Function::new_typed_with_env(&mut store, env, chdir::), + "thread_spawn" => Function::new_typed_with_env(&mut store, env, thread_spawn::), + "thread_local_create" => Function::new_typed_with_env(&mut store, env, thread_local_create::), + "thread_local_destroy" => Function::new_typed_with_env(&mut store, env, thread_local_destroy), + "thread_local_set" => Function::new_typed_with_env(&mut store, env, thread_local_set), + "thread_local_get" => Function::new_typed_with_env(&mut store, env, thread_local_get::), + "thread_sleep" => Function::new_typed_with_env(&mut store, env, thread_sleep), + "thread_id" => Function::new_typed_with_env(&mut store, env, thread_id::), + "thread_join" => Function::new_typed_with_env(&mut store, env, thread_join), + "thread_parallelism" => Function::new_typed_with_env(&mut store, env, thread_parallelism::), + "thread_exit" => Function::new_typed_with_env(&mut store, env, thread_exit), + "sched_yield" => Function::new_typed_with_env(&mut store, env, sched_yield), + "futex_wait" => Function::new_typed_with_env(&mut store, env, futex_wait::), + "futex_wake" => Function::new_typed_with_env(&mut store, env, futex_wake::), + "futex_wake_all" => Function::new_typed_with_env(&mut store, env, futex_wake_all::), + "getpid" => Function::new_typed_with_env(&mut store, env, getpid::), + "process_spawn" => Function::new_typed_with_env(&mut store, env, process_spawn::), + "bus_open_local" => Function::new_typed_with_env(&mut store, env, bus_open_local::), + "bus_open_remote" => Function::new_typed_with_env(&mut store, env, bus_open_remote::), + "bus_close" => Function::new_typed_with_env(&mut store, env, bus_close), + "bus_call" => Function::new_typed_with_env(&mut store, env, bus_call::), + "bus_subcall" => Function::new_typed_with_env(&mut store, env, bus_subcall::), + "bus_poll" => Function::new_typed_with_env(&mut store, env, bus_poll::), + "call_reply" => Function::new_typed_with_env(&mut store, env, call_reply::), + "call_fault" => Function::new_typed_with_env(&mut store, env, call_fault), + "call_close" => Function::new_typed_with_env(&mut store, env, call_close), + "ws_connect" => Function::new_typed_with_env(&mut store, env, ws_connect::), + "http_request" => Function::new_typed_with_env(&mut store, env, http_request::), + "http_status" => Function::new_typed_with_env(&mut store, env, http_status::), + "port_bridge" => Function::new_typed_with_env(&mut store, env, port_bridge::), + "port_unbridge" => Function::new_typed_with_env(&mut store, env, port_unbridge), + "port_dhcp_acquire" => Function::new_typed_with_env(&mut store, env, port_dhcp_acquire), + "port_addr_add" => Function::new_typed_with_env(&mut store, env, port_addr_add::), + "port_addr_remove" => Function::new_typed_with_env(&mut store, env, port_addr_remove::), + "port_addr_clear" => Function::new_typed_with_env(&mut store, env, port_addr_clear), + "port_addr_list" => Function::new_typed_with_env(&mut store, env, port_addr_list::), + "port_mac" => Function::new_typed_with_env(&mut store, env, port_mac::), + "port_gateway_set" => Function::new_typed_with_env(&mut store, env, port_gateway_set::), + "port_route_add" => Function::new_typed_with_env(&mut store, env, port_route_add::), + "port_route_remove" => Function::new_typed_with_env(&mut store, env, port_route_remove::), + "port_route_clear" => Function::new_typed_with_env(&mut store, env, port_route_clear), + "port_route_list" => Function::new_typed_with_env(&mut store, env, port_route_list::), + "sock_status" => Function::new_typed_with_env(&mut store, env, sock_status::), + "sock_addr_local" => Function::new_typed_with_env(&mut store, env, sock_addr_local::), + "sock_addr_peer" => Function::new_typed_with_env(&mut store, env, sock_addr_peer::), + "sock_open" => Function::new_typed_with_env(&mut store, env, sock_open::), + "sock_set_opt_flag" => Function::new_typed_with_env(&mut store, env, sock_set_opt_flag), + "sock_get_opt_flag" => Function::new_typed_with_env(&mut store, env, sock_get_opt_flag::), + "sock_set_opt_time" => Function::new_typed_with_env(&mut store, env, sock_set_opt_time::), + "sock_get_opt_time" => Function::new_typed_with_env(&mut store, env, sock_get_opt_time::), + "sock_set_opt_size" => Function::new_typed_with_env(&mut store, env, sock_set_opt_size), + "sock_get_opt_size" => Function::new_typed_with_env(&mut store, env, sock_get_opt_size::), + "sock_join_multicast_v4" => Function::new_typed_with_env(&mut store, env, sock_join_multicast_v4::), + "sock_leave_multicast_v4" => Function::new_typed_with_env(&mut store, env, sock_leave_multicast_v4::), + "sock_join_multicast_v6" => Function::new_typed_with_env(&mut store, env, sock_join_multicast_v6::), + "sock_leave_multicast_v6" => Function::new_typed_with_env(&mut store, env, sock_leave_multicast_v6::), + "sock_bind" => Function::new_typed_with_env(&mut store, env, sock_bind::), + "sock_listen" => Function::new_typed_with_env(&mut store, env, sock_listen::), + "sock_accept" => Function::new_typed_with_env(&mut store, env, sock_accept::), + "sock_connect" => Function::new_typed_with_env(&mut store, env, sock_connect::), + "sock_recv" => Function::new_typed_with_env(&mut store, env, sock_recv::), + "sock_recv_from" => Function::new_typed_with_env(&mut store, env, sock_recv_from::), + "sock_send" => Function::new_typed_with_env(&mut store, env, sock_send::), + "sock_send_to" => Function::new_typed_with_env(&mut store, env, sock_send_to::), + "sock_send_file" => Function::new_typed_with_env(&mut store, env, sock_send_file::), + "sock_shutdown" => Function::new_typed_with_env(&mut store, env, sock_shutdown), + "resolve" => Function::new_typed_with_env(&mut store, env, resolve::), + }; + namespace +} + +fn wasix_exports_64( + mut store: &mut impl AsStoreMut, + env: &FunctionEnv, +) -> Exports +{ + use syscalls::*; + let namespace = namespace! { + "args_get" => Function::new_typed_with_env(&mut store, env, args_get::), + "args_sizes_get" => Function::new_typed_with_env(&mut store, env, args_sizes_get::), + "clock_res_get" => Function::new_typed_with_env(&mut store, env, clock_res_get::), + "clock_time_get" => Function::new_typed_with_env(&mut store, env, clock_time_get::), + "environ_get" => Function::new_typed_with_env(&mut store, env, environ_get::), + "environ_sizes_get" => Function::new_typed_with_env(&mut store, env, environ_sizes_get::), + "fd_advise" => Function::new_typed_with_env(&mut store, env, fd_advise), + "fd_allocate" => Function::new_typed_with_env(&mut store, env, fd_allocate), + "fd_close" => Function::new_typed_with_env(&mut store, env, fd_close), + "fd_datasync" => Function::new_typed_with_env(&mut store, env, fd_datasync), + "fd_fdstat_get" => Function::new_typed_with_env(&mut store, env, fd_fdstat_get::), + "fd_fdstat_set_flags" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_flags), + "fd_fdstat_set_rights" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_rights), + "fd_filestat_get" => Function::new_typed_with_env(&mut store, env, fd_filestat_get::), + "fd_filestat_set_size" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_size), + "fd_filestat_set_times" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_times), + "fd_pread" => Function::new_typed_with_env(&mut store, env, fd_pread::), + "fd_prestat_get" => Function::new_typed_with_env(&mut store, env, fd_prestat_get::), + "fd_prestat_dir_name" => Function::new_typed_with_env(&mut store, env, fd_prestat_dir_name::), + "fd_pwrite" => Function::new_typed_with_env(&mut store, env, fd_pwrite::), + "fd_read" => Function::new_typed_with_env(&mut store, env, fd_read::), + "fd_readdir" => Function::new_typed_with_env(&mut store, env, fd_readdir::), + "fd_renumber" => Function::new_typed_with_env(&mut store, env, fd_renumber), + "fd_dup" => Function::new_typed_with_env(&mut store, env, fd_dup::), + "fd_event" => Function::new_typed_with_env(&mut store, env, fd_event::), + "fd_seek" => Function::new_typed_with_env(&mut store, env, fd_seek::), + "fd_sync" => Function::new_typed_with_env(&mut store, env, fd_sync), + "fd_tell" => Function::new_typed_with_env(&mut store, env, fd_tell::), + "fd_write" => Function::new_typed_with_env(&mut store, env, fd_write::), + "fd_pipe" => Function::new_typed_with_env(&mut store, env, fd_pipe::), + "path_create_directory" => Function::new_typed_with_env(&mut store, env, path_create_directory::), + "path_filestat_get" => Function::new_typed_with_env(&mut store, env, path_filestat_get::), + "path_filestat_set_times" => Function::new_typed_with_env(&mut store, env, path_filestat_set_times::), + "path_link" => Function::new_typed_with_env(&mut store, env, path_link::), + "path_open" => Function::new_typed_with_env(&mut store, env, path_open::), + "path_readlink" => Function::new_typed_with_env(&mut store, env, path_readlink::), + "path_remove_directory" => Function::new_typed_with_env(&mut store, env, path_remove_directory::), + "path_rename" => Function::new_typed_with_env(&mut store, env, path_rename::), + "path_symlink" => Function::new_typed_with_env(&mut store, env, path_symlink::), + "path_unlink_file" => Function::new_typed_with_env(&mut store, env, path_unlink_file::), + "poll_oneoff" => Function::new_typed_with_env(&mut store, env, poll_oneoff::), + "proc_exit" => Function::new_typed_with_env(&mut store, env, proc_exit), + "proc_raise" => Function::new_typed_with_env(&mut store, env, proc_raise), + "random_get" => Function::new_typed_with_env(&mut store, env, random_get::), + "tty_get" => Function::new_typed_with_env(&mut store, env, tty_get::), + "tty_set" => Function::new_typed_with_env(&mut store, env, tty_set::), + "getcwd" => Function::new_typed_with_env(&mut store, env, getcwd::), + "chdir" => Function::new_typed_with_env(&mut store, env, chdir::), + "thread_spawn" => Function::new_typed_with_env(&mut store, env, thread_spawn::), + "thread_local_create" => Function::new_typed_with_env(&mut store, env, thread_local_create::), + "thread_local_destroy" => Function::new_typed_with_env(&mut store, env, thread_local_destroy), + "thread_local_set" => Function::new_typed_with_env(&mut store, env, thread_local_set), + "thread_local_get" => Function::new_typed_with_env(&mut store, env, thread_local_get::), + "thread_sleep" => Function::new_typed_with_env(&mut store, env, thread_sleep), + "thread_id" => Function::new_typed_with_env(&mut store, env, thread_id::), + "thread_join" => Function::new_typed_with_env(&mut store, env, thread_join), + "thread_parallelism" => Function::new_typed_with_env(&mut store, env, thread_parallelism::), + "thread_exit" => Function::new_typed_with_env(&mut store, env, thread_exit), + "sched_yield" => Function::new_typed_with_env(&mut store, env, sched_yield), + "futex_wait" => Function::new_typed_with_env(&mut store, env, futex_wait::), + "futex_wake" => Function::new_typed_with_env(&mut store, env, futex_wake::), + "futex_wake_all" => Function::new_typed_with_env(&mut store, env, futex_wake_all::), + "getpid" => Function::new_typed_with_env(&mut store, env, getpid::), + "process_spawn" => Function::new_typed_with_env(&mut store, env, process_spawn::), + "bus_open_local" => Function::new_typed_with_env(&mut store, env, bus_open_local::), + "bus_open_remote" => Function::new_typed_with_env(&mut store, env, bus_open_remote::), + "bus_close" => Function::new_typed_with_env(&mut store, env, bus_close), + "bus_call" => Function::new_typed_with_env(&mut store, env, bus_call::), + "bus_subcall" => Function::new_typed_with_env(&mut store, env, bus_subcall::), + "bus_poll" => Function::new_typed_with_env(&mut store, env, bus_poll::), + "call_reply" => Function::new_typed_with_env(&mut store, env, call_reply::), + "call_fault" => Function::new_typed_with_env(&mut store, env, call_fault), + "call_close" => Function::new_typed_with_env(&mut store, env, call_close), + "ws_connect" => Function::new_typed_with_env(&mut store, env, ws_connect::), + "http_request" => Function::new_typed_with_env(&mut store, env, http_request::), + "http_status" => Function::new_typed_with_env(&mut store, env, http_status::), + "port_bridge" => Function::new_typed_with_env(&mut store, env, port_bridge::), + "port_unbridge" => Function::new_typed_with_env(&mut store, env, port_unbridge), + "port_dhcp_acquire" => Function::new_typed_with_env(&mut store, env, port_dhcp_acquire), + "port_addr_add" => Function::new_typed_with_env(&mut store, env, port_addr_add::), + "port_addr_remove" => Function::new_typed_with_env(&mut store, env, port_addr_remove::), + "port_addr_clear" => Function::new_typed_with_env(&mut store, env, port_addr_clear), + "port_addr_list" => Function::new_typed_with_env(&mut store, env, port_addr_list::), + "port_mac" => Function::new_typed_with_env(&mut store, env, port_mac::), + "port_gateway_set" => Function::new_typed_with_env(&mut store, env, port_gateway_set::), + "port_route_add" => Function::new_typed_with_env(&mut store, env, port_route_add::), + "port_route_remove" => Function::new_typed_with_env(&mut store, env, port_route_remove::), + "port_route_clear" => Function::new_typed_with_env(&mut store, env, port_route_clear), + "port_route_list" => Function::new_typed_with_env(&mut store, env, port_route_list::), + "sock_status" => Function::new_typed_with_env(&mut store, env, sock_status::), + "sock_addr_local" => Function::new_typed_with_env(&mut store, env, sock_addr_local::), + "sock_addr_peer" => Function::new_typed_with_env(&mut store, env, sock_addr_peer::), + "sock_open" => Function::new_typed_with_env(&mut store, env, sock_open::), + "sock_set_opt_flag" => Function::new_typed_with_env(&mut store, env, sock_set_opt_flag), + "sock_get_opt_flag" => Function::new_typed_with_env(&mut store, env, sock_get_opt_flag::), + "sock_set_opt_time" => Function::new_typed_with_env(&mut store, env, sock_set_opt_time::), + "sock_get_opt_time" => Function::new_typed_with_env(&mut store, env, sock_get_opt_time::), + "sock_set_opt_size" => Function::new_typed_with_env(&mut store, env, sock_set_opt_size), + "sock_get_opt_size" => Function::new_typed_with_env(&mut store, env, sock_get_opt_size::), + "sock_join_multicast_v4" => Function::new_typed_with_env(&mut store, env, sock_join_multicast_v4::), + "sock_leave_multicast_v4" => Function::new_typed_with_env(&mut store, env, sock_leave_multicast_v4::), + "sock_join_multicast_v6" => Function::new_typed_with_env(&mut store, env, sock_join_multicast_v6::), + "sock_leave_multicast_v6" => Function::new_typed_with_env(&mut store, env, sock_leave_multicast_v6::), + "sock_bind" => Function::new_typed_with_env(&mut store, env, sock_bind::), + "sock_listen" => Function::new_typed_with_env(&mut store, env, sock_listen::), + "sock_accept" => Function::new_typed_with_env(&mut store, env, sock_accept::), + "sock_connect" => Function::new_typed_with_env(&mut store, env, sock_connect::), + "sock_recv" => Function::new_typed_with_env(&mut store, env, sock_recv::), + "sock_recv_from" => Function::new_typed_with_env(&mut store, env, sock_recv_from::), + "sock_send" => Function::new_typed_with_env(&mut store, env, sock_send::), + "sock_send_to" => Function::new_typed_with_env(&mut store, env, sock_send_to::), + "sock_send_file" => Function::new_typed_with_env(&mut store, env, sock_send_file::), + "sock_shutdown" => Function::new_typed_with_env(&mut store, env, sock_shutdown), + "resolve" => Function::new_typed_with_env(&mut store, env, resolve::), + }; + namespace +} + pub fn import_object_for_all_wasi_versions( store: &mut impl AsStoreMut, env: &FunctionEnv, ) -> Imports { - let wasi_unstable_exports = wasi_unstable_exports(store, env); - let wasi_snapshot_preview1_exports = wasi_snapshot_preview1_exports(store, env); + let exports_wasi_unstable = wasi_unstable_exports(store, env); + let exports_wasi_snapshot_preview1 = wasi_snapshot_preview1_exports(store, env); + let exports_wasix_32v1 = wasix_exports_32(store, env); + let exports_wasix_64v1 = wasix_exports_64(store, env); imports! { - "wasi_unstable" => wasi_unstable_exports, - "wasi_snapshot_preview1" => wasi_snapshot_preview1_exports, + "wasi_unstable" => exports_wasi_unstable, + "wasi_snapshot_preview1" => exports_wasi_snapshot_preview1, + "wasix_32v1" => exports_wasix_32v1, + "wasix_64v1" => exports_wasix_64v1, } } @@ -520,9 +846,9 @@ fn generate_import_object_snapshot0( store: &mut impl AsStoreMut, env: &FunctionEnv, ) -> Imports { - let wasi_unstable_exports = wasi_unstable_exports(store, env); + let exports_unstable = wasi_unstable_exports(store, env); imports! { - "wasi_unstable" => wasi_unstable_exports + "wasi_unstable" => exports_unstable } } @@ -530,246 +856,30 @@ fn generate_import_object_snapshot1( store: &mut impl AsStoreMut, env: &FunctionEnv, ) -> Imports { - let wasi_snapshot_preview1_exports = wasi_snapshot_preview1_exports(store, env); + let exports_wasi_snapshot_preview1 = wasi_snapshot_preview1_exports(store, env); imports! { - "wasi_snapshot_preview1" => wasi_snapshot_preview1_exports + "wasi_snapshot_preview1" => exports_wasi_snapshot_preview1 } } /// Combines a state generating function with the import list for snapshot 1 fn generate_import_object_wasix32_v1( - mut store: &mut impl AsStoreMut, + store: &mut impl AsStoreMut, env: &FunctionEnv, ) -> Imports { - use self::wasix32::*; + let exports_wasix_32v1 = wasix_exports_32(store, env); imports! { - "wasix_32v1" => { - "args_get" => Function::new_typed_with_env(&mut store, env, args_get), - "args_sizes_get" => Function::new_typed_with_env(&mut store, env, args_sizes_get), - "clock_res_get" => Function::new_typed_with_env(&mut store, env, clock_res_get), - "clock_time_get" => Function::new_typed_with_env(&mut store, env, clock_time_get), - "environ_get" => Function::new_typed_with_env(&mut store, env, environ_get), - "environ_sizes_get" => Function::new_typed_with_env(&mut store, env, environ_sizes_get), - "fd_advise" => Function::new_typed_with_env(&mut store, env, fd_advise), - "fd_allocate" => Function::new_typed_with_env(&mut store, env, fd_allocate), - "fd_close" => Function::new_typed_with_env(&mut store, env, fd_close), - "fd_datasync" => Function::new_typed_with_env(&mut store, env, fd_datasync), - "fd_fdstat_get" => Function::new_typed_with_env(&mut store, env, fd_fdstat_get), - "fd_fdstat_set_flags" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_flags), - "fd_fdstat_set_rights" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_rights), - "fd_filestat_get" => Function::new_typed_with_env(&mut store, env, fd_filestat_get), - "fd_filestat_set_size" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_size), - "fd_filestat_set_times" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_times), - "fd_pread" => Function::new_typed_with_env(&mut store, env, fd_pread), - "fd_prestat_get" => Function::new_typed_with_env(&mut store, env, fd_prestat_get), - "fd_prestat_dir_name" => Function::new_typed_with_env(&mut store, env, fd_prestat_dir_name), - "fd_pwrite" => Function::new_typed_with_env(&mut store, env, fd_pwrite), - "fd_read" => Function::new_typed_with_env(&mut store, env, fd_read), - "fd_readdir" => Function::new_typed_with_env(&mut store, env, fd_readdir), - "fd_renumber" => Function::new_typed_with_env(&mut store, env, fd_renumber), - "fd_dup" => Function::new_typed_with_env(&mut store, env, fd_dup), - "fd_event" => Function::new_typed_with_env(&mut store, env, fd_event), - "fd_seek" => Function::new_typed_with_env(&mut store, env, fd_seek), - "fd_sync" => Function::new_typed_with_env(&mut store, env, fd_sync), - "fd_tell" => Function::new_typed_with_env(&mut store, env, fd_tell), - "fd_write" => Function::new_typed_with_env(&mut store, env, fd_write), - "fd_pipe" => Function::new_typed_with_env(&mut store, env, fd_pipe), - "path_create_directory" => Function::new_typed_with_env(&mut store, env, path_create_directory), - "path_filestat_get" => Function::new_typed_with_env(&mut store, env, path_filestat_get), - "path_filestat_set_times" => Function::new_typed_with_env(&mut store, env, path_filestat_set_times), - "path_link" => Function::new_typed_with_env(&mut store, env, path_link), - "path_open" => Function::new_typed_with_env(&mut store, env, path_open), - "path_readlink" => Function::new_typed_with_env(&mut store, env, path_readlink), - "path_remove_directory" => Function::new_typed_with_env(&mut store, env, path_remove_directory), - "path_rename" => Function::new_typed_with_env(&mut store, env, path_rename), - "path_symlink" => Function::new_typed_with_env(&mut store, env, path_symlink), - "path_unlink_file" => Function::new_typed_with_env(&mut store, env, path_unlink_file), - "poll_oneoff" => Function::new_typed_with_env(&mut store, env, poll_oneoff), - "proc_exit" => Function::new_typed_with_env(&mut store, env, proc_exit), - "proc_raise" => Function::new_typed_with_env(&mut store, env, proc_raise), - "random_get" => Function::new_typed_with_env(&mut store, env, random_get), - "tty_get" => Function::new_typed_with_env(&mut store, env, tty_get), - "tty_set" => Function::new_typed_with_env(&mut store, env, tty_set), - "getcwd" => Function::new_typed_with_env(&mut store, env, getcwd), - "chdir" => Function::new_typed_with_env(&mut store, env, chdir), - "thread_spawn" => Function::new_typed_with_env(&mut store, env, thread_spawn), - "thread_sleep" => Function::new_typed_with_env(&mut store, env, thread_sleep), - "thread_id" => Function::new_typed_with_env(&mut store, env, thread_id), - "thread_join" => Function::new_typed_with_env(&mut store, env, thread_join), - "thread_parallelism" => Function::new_typed_with_env(&mut store, env, thread_parallelism), - "thread_exit" => Function::new_typed_with_env(&mut store, env, thread_exit), - "sched_yield" => Function::new_typed_with_env(&mut store, env, sched_yield), - "getpid" => Function::new_typed_with_env(&mut store, env, getpid), - "process_spawn" => Function::new_typed_with_env(&mut store, env, process_spawn), - "bus_open_local" => Function::new_typed_with_env(&mut store, env, bus_open_local), - "bus_open_remote" => Function::new_typed_with_env(&mut store, env, bus_open_remote), - "bus_close" => Function::new_typed_with_env(&mut store, env, bus_close), - "bus_call" => Function::new_typed_with_env(&mut store, env, bus_call), - "bus_subcall" => Function::new_typed_with_env(&mut store, env, bus_subcall), - "bus_poll" => Function::new_typed_with_env(&mut store, env, bus_poll), - "call_reply" => Function::new_typed_with_env(&mut store, env, call_reply), - "call_fault" => Function::new_typed_with_env(&mut store, env, call_fault), - "call_close" => Function::new_typed_with_env(&mut store, env, call_close), - "ws_connect" => Function::new_typed_with_env(&mut store, env, ws_connect), - "http_request" => Function::new_typed_with_env(&mut store, env, http_request), - "http_status" => Function::new_typed_with_env(&mut store, env, http_status), - "port_bridge" => Function::new_typed_with_env(&mut store, env, port_bridge), - "port_unbridge" => Function::new_typed_with_env(&mut store, env, port_unbridge), - "port_dhcp_acquire" => Function::new_typed_with_env(&mut store, env, port_dhcp_acquire), - "port_addr_add" => Function::new_typed_with_env(&mut store, env, port_addr_add), - "port_addr_remove" => Function::new_typed_with_env(&mut store, env, port_addr_remove), - "port_addr_clear" => Function::new_typed_with_env(&mut store, env, port_addr_clear), - "port_addr_list" => Function::new_typed_with_env(&mut store, env, port_addr_list), - "port_mac" => Function::new_typed_with_env(&mut store, env, port_mac), - "port_gateway_set" => Function::new_typed_with_env(&mut store, env, port_gateway_set), - "port_route_add" => Function::new_typed_with_env(&mut store, env, port_route_add), - "port_route_remove" => Function::new_typed_with_env(&mut store, env, port_route_remove), - "port_route_clear" => Function::new_typed_with_env(&mut store, env, port_route_clear), - "port_route_list" => Function::new_typed_with_env(&mut store, env, port_route_list), - "sock_status" => Function::new_typed_with_env(&mut store, env, sock_status), - "sock_addr_local" => Function::new_typed_with_env(&mut store, env, sock_addr_local), - "sock_addr_peer" => Function::new_typed_with_env(&mut store, env, sock_addr_peer), - "sock_open" => Function::new_typed_with_env(&mut store, env, sock_open), - "sock_set_opt_flag" => Function::new_typed_with_env(&mut store, env, sock_set_opt_flag), - "sock_get_opt_flag" => Function::new_typed_with_env(&mut store, env, sock_get_opt_flag), - "sock_set_opt_time" => Function::new_typed_with_env(&mut store, env, sock_set_opt_time), - "sock_get_opt_time" => Function::new_typed_with_env(&mut store, env, sock_get_opt_time), - "sock_set_opt_size" => Function::new_typed_with_env(&mut store, env, sock_set_opt_size), - "sock_get_opt_size" => Function::new_typed_with_env(&mut store, env, sock_get_opt_size), - "sock_join_multicast_v4" => Function::new_typed_with_env(&mut store, env, sock_join_multicast_v4), - "sock_leave_multicast_v4" => Function::new_typed_with_env(&mut store, env, sock_leave_multicast_v4), - "sock_join_multicast_v6" => Function::new_typed_with_env(&mut store, env, sock_join_multicast_v6), - "sock_leave_multicast_v6" => Function::new_typed_with_env(&mut store, env, sock_leave_multicast_v6), - "sock_bind" => Function::new_typed_with_env(&mut store, env, sock_bind), - "sock_listen" => Function::new_typed_with_env(&mut store, env, sock_listen), - "sock_accept" => Function::new_typed_with_env(&mut store, env, sock_accept), - "sock_connect" => Function::new_typed_with_env(&mut store, env, sock_connect), - "sock_recv" => Function::new_typed_with_env(&mut store, env, sock_recv), - "sock_recv_from" => Function::new_typed_with_env(&mut store, env, sock_recv_from), - "sock_send" => Function::new_typed_with_env(&mut store, env, sock_send), - "sock_send_to" => Function::new_typed_with_env(&mut store, env, sock_send_to), - "sock_send_file" => Function::new_typed_with_env(&mut store, env, sock_send_file), - "sock_shutdown" => Function::new_typed_with_env(&mut store, env, sock_shutdown), - "resolve" => Function::new_typed_with_env(&mut store, env, resolve), - } + "wasix_32v1" => exports_wasix_32v1 } } fn generate_import_object_wasix64_v1( - mut store: &mut impl AsStoreMut, + store: &mut impl AsStoreMut, env: &FunctionEnv, ) -> Imports { - use self::wasix64::*; + let exports_wasix_64v1 = wasix_exports_64(store, env); imports! { - "wasix_64v1" => { - "args_get" => Function::new_typed_with_env(&mut store, env, args_get), - "args_sizes_get" => Function::new_typed_with_env(&mut store, env, args_sizes_get), - "clock_res_get" => Function::new_typed_with_env(&mut store, env, clock_res_get), - "clock_time_get" => Function::new_typed_with_env(&mut store, env, clock_time_get), - "environ_get" => Function::new_typed_with_env(&mut store, env, environ_get), - "environ_sizes_get" => Function::new_typed_with_env(&mut store, env, environ_sizes_get), - "fd_advise" => Function::new_typed_with_env(&mut store, env, fd_advise), - "fd_allocate" => Function::new_typed_with_env(&mut store, env, fd_allocate), - "fd_close" => Function::new_typed_with_env(&mut store, env, fd_close), - "fd_datasync" => Function::new_typed_with_env(&mut store, env, fd_datasync), - "fd_fdstat_get" => Function::new_typed_with_env(&mut store, env, fd_fdstat_get), - "fd_fdstat_set_flags" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_flags), - "fd_fdstat_set_rights" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_rights), - "fd_filestat_get" => Function::new_typed_with_env(&mut store, env, fd_filestat_get), - "fd_filestat_set_size" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_size), - "fd_filestat_set_times" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_times), - "fd_pread" => Function::new_typed_with_env(&mut store, env, fd_pread), - "fd_prestat_get" => Function::new_typed_with_env(&mut store, env, fd_prestat_get), - "fd_prestat_dir_name" => Function::new_typed_with_env(&mut store, env, fd_prestat_dir_name), - "fd_pwrite" => Function::new_typed_with_env(&mut store, env, fd_pwrite), - "fd_read" => Function::new_typed_with_env(&mut store, env, fd_read), - "fd_readdir" => Function::new_typed_with_env(&mut store, env, fd_readdir), - "fd_renumber" => Function::new_typed_with_env(&mut store, env, fd_renumber), - "fd_dup" => Function::new_typed_with_env(&mut store, env, fd_dup), - "fd_event" => Function::new_typed_with_env(&mut store, env, fd_event), - "fd_seek" => Function::new_typed_with_env(&mut store, env, fd_seek), - "fd_sync" => Function::new_typed_with_env(&mut store, env, fd_sync), - "fd_tell" => Function::new_typed_with_env(&mut store, env, fd_tell), - "fd_write" => Function::new_typed_with_env(&mut store, env, fd_write), - "fd_pipe" => Function::new_typed_with_env(&mut store, env, fd_pipe), - "path_create_directory" => Function::new_typed_with_env(&mut store, env, path_create_directory), - "path_filestat_get" => Function::new_typed_with_env(&mut store, env, path_filestat_get), - "path_filestat_set_times" => Function::new_typed_with_env(&mut store, env, path_filestat_set_times), - "path_link" => Function::new_typed_with_env(&mut store, env, path_link), - "path_open" => Function::new_typed_with_env(&mut store, env, path_open), - "path_readlink" => Function::new_typed_with_env(&mut store, env, path_readlink), - "path_remove_directory" => Function::new_typed_with_env(&mut store, env, path_remove_directory), - "path_rename" => Function::new_typed_with_env(&mut store, env, path_rename), - "path_symlink" => Function::new_typed_with_env(&mut store, env, path_symlink), - "path_unlink_file" => Function::new_typed_with_env(&mut store, env, path_unlink_file), - "poll_oneoff" => Function::new_typed_with_env(&mut store, env, poll_oneoff), - "proc_exit" => Function::new_typed_with_env(&mut store, env, proc_exit), - "proc_raise" => Function::new_typed_with_env(&mut store, env, proc_raise), - "random_get" => Function::new_typed_with_env(&mut store, env, random_get), - "tty_get" => Function::new_typed_with_env(&mut store, env, tty_get), - "tty_set" => Function::new_typed_with_env(&mut store, env, tty_set), - "getcwd" => Function::new_typed_with_env(&mut store, env, getcwd), - "chdir" => Function::new_typed_with_env(&mut store, env, chdir), - "thread_spawn" => Function::new_typed_with_env(&mut store, env, thread_spawn), - "thread_sleep" => Function::new_typed_with_env(&mut store, env, thread_sleep), - "thread_id" => Function::new_typed_with_env(&mut store, env, thread_id), - "thread_join" => Function::new_typed_with_env(&mut store, env, thread_join), - "thread_parallelism" => Function::new_typed_with_env(&mut store, env, thread_parallelism), - "thread_exit" => Function::new_typed_with_env(&mut store, env, thread_exit), - "sched_yield" => Function::new_typed_with_env(&mut store, env, sched_yield), - "getpid" => Function::new_typed_with_env(&mut store, env, getpid), - "process_spawn" => Function::new_typed_with_env(&mut store, env, process_spawn), - "bus_open_local" => Function::new_typed_with_env(&mut store, env, bus_open_local), - "bus_open_remote" => Function::new_typed_with_env(&mut store, env, bus_open_remote), - "bus_close" => Function::new_typed_with_env(&mut store, env, bus_close), - "bus_call" => Function::new_typed_with_env(&mut store, env, bus_call), - "bus_subcall" => Function::new_typed_with_env(&mut store, env, bus_subcall), - "bus_poll" => Function::new_typed_with_env(&mut store, env, bus_poll), - "call_reply" => Function::new_typed_with_env(&mut store, env, call_reply), - "call_fault" => Function::new_typed_with_env(&mut store, env, call_fault), - "call_close" => Function::new_typed_with_env(&mut store, env, call_close), - "ws_connect" => Function::new_typed_with_env(&mut store, env, ws_connect), - "http_request" => Function::new_typed_with_env(&mut store, env, http_request), - "http_status" => Function::new_typed_with_env(&mut store, env, http_status), - "port_bridge" => Function::new_typed_with_env(&mut store, env, port_bridge), - "port_unbridge" => Function::new_typed_with_env(&mut store, env, port_unbridge), - "port_dhcp_acquire" => Function::new_typed_with_env(&mut store, env, port_dhcp_acquire), - "port_addr_add" => Function::new_typed_with_env(&mut store, env, port_addr_add), - "port_addr_remove" => Function::new_typed_with_env(&mut store, env, port_addr_remove), - "port_addr_clear" => Function::new_typed_with_env(&mut store, env, port_addr_clear), - "port_addr_list" => Function::new_typed_with_env(&mut store, env, port_addr_list), - "port_mac" => Function::new_typed_with_env(&mut store, env, port_mac), - "port_gateway_set" => Function::new_typed_with_env(&mut store, env, port_gateway_set), - "port_route_add" => Function::new_typed_with_env(&mut store, env, port_route_add), - "port_route_remove" => Function::new_typed_with_env(&mut store, env, port_route_remove), - "port_route_clear" => Function::new_typed_with_env(&mut store, env, port_route_clear), - "port_route_list" => Function::new_typed_with_env(&mut store, env, port_route_list), - "sock_status" => Function::new_typed_with_env(&mut store, env, sock_status), - "sock_addr_local" => Function::new_typed_with_env(&mut store, env, sock_addr_local), - "sock_addr_peer" => Function::new_typed_with_env(&mut store, env, sock_addr_peer), - "sock_open" => Function::new_typed_with_env(&mut store, env, sock_open), - "sock_set_opt_flag" => Function::new_typed_with_env(&mut store, env, sock_set_opt_flag), - "sock_get_opt_flag" => Function::new_typed_with_env(&mut store, env, sock_get_opt_flag), - "sock_set_opt_time" => Function::new_typed_with_env(&mut store, env, sock_set_opt_time), - "sock_get_opt_time" => Function::new_typed_with_env(&mut store, env, sock_get_opt_time), - "sock_set_opt_size" => Function::new_typed_with_env(&mut store, env, sock_set_opt_size), - "sock_get_opt_size" => Function::new_typed_with_env(&mut store, env, sock_get_opt_size), - "sock_join_multicast_v4" => Function::new_typed_with_env(&mut store, env, sock_join_multicast_v4), - "sock_leave_multicast_v4" => Function::new_typed_with_env(&mut store, env, sock_leave_multicast_v4), - "sock_join_multicast_v6" => Function::new_typed_with_env(&mut store, env, sock_join_multicast_v6), - "sock_leave_multicast_v6" => Function::new_typed_with_env(&mut store, env, sock_leave_multicast_v6), - "sock_bind" => Function::new_typed_with_env(&mut store, env, sock_bind), - "sock_listen" => Function::new_typed_with_env(&mut store, env, sock_listen), - "sock_accept" => Function::new_typed_with_env(&mut store, env, sock_accept), - "sock_connect" => Function::new_typed_with_env(&mut store, env, sock_connect), - "sock_recv" => Function::new_typed_with_env(&mut store, env, sock_recv), - "sock_recv_from" => Function::new_typed_with_env(&mut store, env, sock_recv_from), - "sock_send" => Function::new_typed_with_env(&mut store, env, sock_send), - "sock_send_to" => Function::new_typed_with_env(&mut store, env, sock_send_to), - "sock_send_file" => Function::new_typed_with_env(&mut store, env, sock_send_file), - "sock_shutdown" => Function::new_typed_with_env(&mut store, env, sock_shutdown), - "resolve" => Function::new_typed_with_env(&mut store, env, resolve), - } + "wasix_64v1" => exports_wasix_64v1 } } diff --git a/lib/wasi/src/macros.rs b/lib/wasi/src/macros.rs index b9ec4245597..7df520bcab9 100644 --- a/lib/wasi/src/macros.rs +++ b/lib/wasi/src/macros.rs @@ -7,7 +7,6 @@ macro_rules! wasi_try { let res: Result<_, crate::syscalls::types::__wasi_errno_t> = $expr; match res { Ok(val) => { - tracing::trace!("wasi::wasi_try::val: {:?}", val); val } Err(err) => { @@ -25,7 +24,6 @@ macro_rules! wasi_try_ok { let res: Result<_, crate::syscalls::types::__wasi_errno_t> = $expr; match res { Ok(val) => { - tracing::trace!("wasi::wasi_try_ok::val: {:?}", val); val } Err(err) => { @@ -39,7 +37,6 @@ macro_rules! wasi_try_ok { let res: Result<_, crate::syscalls::types::__wasi_errno_t> = $expr; match res { Ok(val) => { - tracing::trace!("wasi::wasi_try_ok::val: {:?}", val); val } Err(err) => { @@ -60,7 +57,6 @@ macro_rules! wasi_try_bus { let res: Result<_, crate::syscalls::types::__bus_errno_t> = $expr; match res { Ok(val) => { - tracing::trace!("wasi::wasi_try_bus::val: {:?}", val); val } Err(err) => { @@ -71,6 +67,24 @@ macro_rules! wasi_try_bus { }}; } +/// Like the `try!` macro or `?` syntax: returns the value if the computation +/// succeeded or returns the error value. +macro_rules! wasi_try_bus_ok { + ($expr:expr) => {{ + let res: Result<_, crate::syscalls::types::__bus_errno_t> = $expr; + match res { + Ok(val) => { + //tracing::trace!("wasi::wasi_try_bus::val: {:?}", val); + val + } + Err(err) => { + tracing::debug!("wasi::wasi_try_bus::err: {:?}", err); + return Ok(err); + } + } + }}; +} + /// Like `wasi_try` but converts a `MemoryAccessError` to a __wasi_errno_t`. macro_rules! wasi_try_mem { ($expr:expr) => {{ @@ -85,6 +99,13 @@ macro_rules! wasi_try_mem_bus { }}; } +/// Like `wasi_try` but converts a `MemoryAccessError` to a __bus_errno_t`. +macro_rules! wasi_try_mem_bus_ok { + ($expr:expr) => {{ + wasi_try_bus_ok!($expr.map_err($crate::mem_error_to_bus)) + }}; +} + /// Like `wasi_try` but converts a `MemoryAccessError` to a __wasi_errno_t`. macro_rules! wasi_try_mem_ok { ($expr:expr) => {{ @@ -108,3 +129,9 @@ macro_rules! get_input_str_bus { wasi_try_mem_bus!($data.read_utf8_string($memory, $len)) }}; } + +macro_rules! get_input_str_bus_ok { + ($memory:expr, $data:expr, $len:expr) => {{ + wasi_try_mem_bus_ok!($data.read_utf8_string($memory, $len)) + }}; +} diff --git a/lib/wasi/src/runtime.rs b/lib/wasi/src/runtime.rs index 00c208bd166..1b332d2cb5b 100644 --- a/lib/wasi/src/runtime.rs +++ b/lib/wasi/src/runtime.rs @@ -2,9 +2,13 @@ use std::fmt; use std::ops::Deref; use std::sync::atomic::{AtomicU32, Ordering}; use thiserror::Error; +use wasmer::Module; +use wasmer::vm::VMMemory; use wasmer_vbus::{UnsupportedVirtualBus, VirtualBus}; use wasmer_vnet::VirtualNetworking; +use crate::WasiCallingId; + use super::types::*; use super::WasiError; use super::WasiThreadId; @@ -15,6 +19,11 @@ pub enum WasiThreadError { Unsupported, #[error("The method named is not an exported function")] MethodNotFound, + #[error("Failed to create the requested memory")] + MemoryCreateFailed, + /// This will happen if WASM is running in a thread has not been created by the spawn_wasm call + #[error("WASM context is invalid")] + InvalidWasmContext, } impl From for __wasi_errno_t { @@ -22,6 +31,8 @@ impl From for __wasi_errno_t { match a { WasiThreadError::Unsupported => __WASI_ENOTSUP, WasiThreadError::MethodNotFound => __WASI_EINVAL, + WasiThreadError::MemoryCreateFailed => __WASI_EFAULT, + WasiThreadError::InvalidWasmContext => __WASI_ENOEXEC, } } } @@ -41,7 +52,9 @@ pub struct WasiTtyState { /// Represents an implementation of the WASI runtime - by default everything is /// unimplemented. -pub trait WasiRuntimeImplementation: fmt::Debug + Sync { +pub trait WasiRuntimeImplementation +where Self: fmt::Debug + Sync, +{ /// For WASI runtimes that support it they can implement a message BUS implementation /// which allows runtimes to pass serialized messages between each other similar to /// RPC's. BUS implementation can be implemented that communicate across runtimes @@ -76,8 +89,11 @@ pub trait WasiRuntimeImplementation: fmt::Debug + Sync { /// Spawns a new thread by invoking the fn thread_spawn( &self, - _callback: Box, - ) -> Result<(), WasiThreadError> { + _callback: Box, + _existing_module: Module, + _existing_memory: VMMemory, + ) -> Result<(), WasiThreadError> + { Err(WasiThreadError::Unsupported) } @@ -89,7 +105,7 @@ pub trait WasiRuntimeImplementation: fmt::Debug + Sync { /// Invokes whenever a WASM thread goes idle. In some runtimes (like singlethreaded /// execution environments) they will need to do asynchronous work whenever the main /// thread goes idle and this is the place to hook for that. - fn yield_now(&self, _id: WasiThreadId) -> Result<(), WasiError> { + fn yield_now(&self, _id: WasiCallingId) -> Result<(), WasiError> { std::thread::yield_now(); Ok(()) } @@ -101,13 +117,15 @@ pub trait WasiRuntimeImplementation: fmt::Debug + Sync { } #[derive(Debug)] -pub struct PluggableRuntimeImplementation { +pub struct PluggableRuntimeImplementation +{ pub bus: Box, pub networking: Box, pub thread_id_seed: AtomicU32, } -impl PluggableRuntimeImplementation { +impl PluggableRuntimeImplementation +{ pub fn set_bus_implementation(&mut self, bus: I) where I: VirtualBus + Sync, @@ -123,7 +141,9 @@ impl PluggableRuntimeImplementation { } } -impl Default for PluggableRuntimeImplementation { +impl Default +for PluggableRuntimeImplementation +{ fn default() -> Self { Self { #[cfg(not(feature = "host-vnet"))] @@ -136,16 +156,39 @@ impl Default for PluggableRuntimeImplementation { } } -impl WasiRuntimeImplementation for PluggableRuntimeImplementation { - fn bus(&self) -> &(dyn VirtualBus) { +impl WasiRuntimeImplementation +for PluggableRuntimeImplementation +{ + fn bus<'a>(&'a self) -> &'a (dyn VirtualBus) { self.bus.deref() } - fn networking(&self) -> &(dyn VirtualNetworking) { + fn networking<'a>(&'a self) -> &'a (dyn VirtualNetworking) { self.networking.deref() } fn thread_generate_id(&self) -> WasiThreadId { self.thread_id_seed.fetch_add(1, Ordering::Relaxed).into() } + + #[cfg(feature = "sys-thread")] + fn thread_spawn( + &self, + callback: Box, + existing_module: Module, + existing_memory: VMMemory, + ) -> Result<(), WasiThreadError> + { + let existing_module = existing_module.clone(); + std::thread::spawn(move || { + callback(existing_module, existing_memory) + }); + Ok(()) + } + + fn thread_parallelism(&self) -> Result { + std::thread::available_parallelism() + .map(|a| usize::from(a)) + .map_err(|_| WasiThreadError::Unsupported) + } } diff --git a/lib/wasi/src/state/builder.rs b/lib/wasi/src/state/builder.rs index 61e2451d807..4507060e092 100644 --- a/lib/wasi/src/state/builder.rs +++ b/lib/wasi/src/state/builder.rs @@ -468,6 +468,8 @@ impl WasiStateBuilder { inodes: Arc::new(inodes), args: self.args.clone(), threading: Default::default(), + futexs: Default::default(), + bus: Default::default(), envs: self .envs .iter() diff --git a/lib/wasi/src/state/mod.rs b/lib/wasi/src/state/mod.rs index 4b1a75a718d..d38f078b9ae 100644 --- a/lib/wasi/src/state/mod.rs +++ b/lib/wasi/src/state/mod.rs @@ -20,26 +20,44 @@ mod guard; mod pipe; mod socket; mod types; +mod thread; +mod parking; pub use self::builder::*; pub use self::guard::*; pub use self::pipe::*; pub use self::socket::*; pub use self::types::*; +pub use self::guard::*; +pub use self::thread::*; +pub use self::parking::*; +use crate::WasiCallingId; +use crate::WasiFunctionEnv; +use crate::WasiThreadId; use crate::syscalls::types::*; use crate::utils::map_io_err; use crate::WasiBusProcessId; -use crate::WasiThread; -use crate::WasiThreadId; +use cooked_waker::ViaRawPointer; +use cooked_waker::Wake; +use cooked_waker::WakeRef; +use derivative::Derivative; use generational_arena::Arena; pub use generational_arena::Index as Inode; #[cfg(feature = "enable-serde")] use serde::{Deserialize, Serialize}; +use wasmer::Store; +use wasmer_vbus::VirtualBusCalled; +use wasmer_vbus::VirtualBusInvocation; use std::borrow::Cow; +use std::cell::RefCell; use std::collections::HashMap; use std::collections::VecDeque; +use std::sync::Condvar; +use std::sync::MutexGuard; use std::sync::mpsc; use std::sync::Arc; +use std::task::Waker; +use std::time::Duration; use std::{ borrow::Borrow, io::Write, @@ -83,7 +101,7 @@ pub const MAX_SYMLINKS: u32 = 128; pub struct InodeVal { pub stat: RwLock<__wasi_filestat_t>, pub is_preopened: bool, - pub name: String, + pub name: Cow<'static, str>, pub kind: RwLock, } @@ -654,8 +672,7 @@ impl WasiFs { for c in path.components() { let segment_name = c.as_os_str().to_string_lossy().to_string(); let guard = inodes.arena[cur_inode].read(); - let deref = guard.deref(); - match deref { + match guard.deref() { Kind::Dir { ref entries, .. } | Kind::Root { ref entries } => { if let Some(_entry) = entries.get(&segment_name) { // TODO: this should be fixed @@ -673,14 +690,13 @@ impl WasiFs { inodes, kind, false, - segment_name.clone(), + segment_name.clone().into(), ); // reborrow to insert { let mut guard = inodes.arena[cur_inode].write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::Dir { ref mut entries, .. } @@ -727,8 +743,7 @@ impl WasiFs { let base_inode = self.get_fd_inode(base).map_err(fs_error_from_wasi_err)?; let guard = inodes.arena[base_inode].read(); - let deref = guard.deref(); - match deref { + match guard.deref() { Kind::Dir { ref entries, .. } | Kind::Root { ref entries } => { if let Some(_entry) = entries.get(&name) { // TODO: eventually change the logic here to allow overwrites @@ -748,8 +763,7 @@ impl WasiFs { { let mut guard = inodes.arena[base_inode].write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::Dir { ref mut entries, .. } @@ -794,8 +808,7 @@ impl WasiFs { _ => { let base_inode = self.get_fd_inode(fd).map_err(fs_error_from_wasi_err)?; let mut guard = inodes.arena[base_inode].write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::File { ref mut handle, .. } => { std::mem::swap(handle, &mut ret); } @@ -815,8 +828,7 @@ impl WasiFs { ) -> Result<__wasi_filesize_t, __wasi_errno_t> { let inode = self.get_fd_inode(fd)?; let mut guard = inodes.arena[inode].write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::File { handle, .. } => { if let Some(h) = handle { let new_size = h.size(); @@ -905,8 +917,7 @@ impl WasiFs { // loading inodes as necessary 'symlink_resolution: while symlink_count < MAX_SYMLINKS { let mut guard = inodes.arena[cur_inode].write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::Buffer { .. } => unimplemented!("state::get_inode_at_path for buffers"), Kind::Dir { ref mut entries, @@ -1011,7 +1022,7 @@ impl WasiFs { inodes, kind, false, - file.to_string_lossy().to_string(), + file.to_string_lossy().to_string().into(), __wasi_filestat_t { st_filetype: file_type, ..__wasi_filestat_t::default() @@ -1172,12 +1183,10 @@ impl WasiFs { let mut res = BaseFdAndRelPath::None; // for each preopened directory let preopen_fds = self.preopen_fds.read().unwrap(); - let deref = preopen_fds.deref(); - for po_fd in deref { + for po_fd in preopen_fds.deref() { let po_inode = self.fd_map.read().unwrap()[po_fd].inode; let guard = inodes.arena[po_inode].read(); - let deref = guard.deref(); - let po_path = match deref { + let po_path = match guard.deref() { Kind::Dir { path, .. } => &**path, Kind::Root { .. } => Path::new("/"), _ => unreachable!("Preopened FD that's not a directory or the root"), @@ -1219,8 +1228,7 @@ impl WasiFs { while cur_inode != base_inode { counter += 1; let guard = inodes.arena[cur_inode].read(); - let deref = guard.deref(); - match deref { + match guard.deref() { Kind::Dir { parent, .. } => { if let Some(p) = parent { cur_inode = *p; @@ -1355,9 +1363,8 @@ impl WasiFs { debug!("fdstat: {:?}", fd); let guard = inodes.arena[fd.inode].read(); - let deref = guard.deref(); Ok(__wasi_fdstat_t { - fs_filetype: match deref { + fs_filetype: match guard.deref() { Kind::File { .. } => __WASI_FILETYPE_REGULAR_FILE, Kind::Dir { .. } => __WASI_FILETYPE_DIRECTORY, Kind::Symlink { .. } => __WASI_FILETYPE_SYMBOLIC_LINK, @@ -1419,8 +1426,7 @@ impl WasiFs { } let mut guard = inodes.arena[fd.inode].write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::File { handle: Some(file), .. } => file.flush().map_err(|_| __WASI_EIO)?, @@ -1444,7 +1450,7 @@ impl WasiFs { name: String, ) -> Result { let stat = self.get_stat_for_kind(inodes, &kind)?; - Ok(self.create_inode_with_stat(inodes, kind, is_preopened, name, stat)) + Ok(self.create_inode_with_stat(inodes, kind, is_preopened, name.into(), stat)) } /// Creates an inode and inserts it given a Kind, does not assume the file exists. @@ -1453,7 +1459,7 @@ impl WasiFs { inodes: &mut WasiInodes, kind: Kind, is_preopened: bool, - name: String, + name: Cow<'static, str>, ) -> Inode { let stat = __wasi_filestat_t::default(); self.create_inode_with_stat(inodes, kind, is_preopened, name, stat) @@ -1465,7 +1471,7 @@ impl WasiFs { inodes: &mut WasiInodes, kind: Kind, is_preopened: bool, - name: String, + name: Cow<'static, str>, mut stat: __wasi_filestat_t, ) -> Inode { stat.st_ino = self.get_next_inode_index(); @@ -1543,7 +1549,7 @@ impl WasiFs { inodes.arena.insert(InodeVal { stat: RwLock::new(stat), is_preopened: true, - name: "/".to_string(), + name: "/".into(), kind: RwLock::new(root_kind), }) } @@ -1602,7 +1608,7 @@ impl WasiFs { inodes.arena.insert(InodeVal { stat: RwLock::new(stat), is_preopened: true, - name: name.to_string(), + name: name.to_string().into(), kind: RwLock::new(kind), }) }; @@ -1655,8 +1661,7 @@ impl WasiFs { let base_po_inode = &self.fd_map.read().unwrap()[base_po_dir].inode; let base_po_inode_v = &inodes.arena[*base_po_inode]; let guard = base_po_inode_v.read(); - let deref = guard.deref(); - match deref { + match guard.deref() { Kind::Root { .. } => { self.fs_backing.symlink_metadata(path_to_symlink).map_err(fs_error_into_wasi_err)? } @@ -1698,8 +1703,7 @@ impl WasiFs { let is_preopened = inodeval.is_preopened; let mut guard = inodeval.write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::File { ref mut handle, .. } => { let mut empty_handle = None; std::mem::swap(handle, &mut empty_handle); @@ -1721,16 +1725,14 @@ impl WasiFs { if let Some(p) = *parent { drop(guard); let mut guard = inodes.arena[p].write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::Dir { entries, .. } | Kind::Root { entries } => { self.fd_map.write().unwrap().remove(&fd).unwrap(); if is_preopened { let mut idx = None; { let preopen_fds = self.preopen_fds.read().unwrap(); - let preopen_fds_iter = preopen_fds.iter().enumerate(); - for (i, po_fd) in preopen_fds_iter { + for (i, po_fd) in preopen_fds.iter().enumerate() { if *po_fd == fd { idx = Some(i); break; @@ -1814,21 +1816,152 @@ impl WasiState { } } +pub(crate) struct WasiThreadContext { + pub ctx: WasiFunctionEnv, + pub store: RefCell, +} + +/// The code itself makes safe use of the struct so multiple threads don't access +/// it (without this the JS code prevents the reference to the module from being stored +/// which is needed for the multithreading mode) +unsafe impl Send for WasiThreadContext { } +unsafe impl Sync for WasiThreadContext { } + /// Structures used for the threading and sub-processes /// /// These internal implementation details are hidden away from the /// consumer who should instead implement the vbus trait on the runtime -#[derive(Debug, Default)] + +#[derive(Derivative, Default)] +#[derivative(Debug)] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub(crate) struct WasiStateThreading { - #[cfg_attr(feature = "enable-serde", serde(skip))] - pub threads: HashMap, - pub thread_seed: u32, - #[cfg_attr(feature = "enable-serde", serde(skip))] - pub processes: HashMap, - #[cfg_attr(feature = "enable-serde", serde(skip))] + threads: Arc>>, + thread_count: Arc, + pub processes: HashMap>, pub process_reuse: HashMap, WasiBusProcessId>, pub process_seed: u32, + pub thread_seed: WasiThreadId, + pub thread_local: HashMap<(WasiThreadId, u32), u64>, + pub thread_local_user_data: HashMap, + pub thread_local_seed: u32, + #[derivative(Debug = "ignore")] + pub thread_ctx: HashMap>, +} + +impl WasiStateThreading +{ + /// Creates a a thread and returns it + pub fn new_thread(&mut self) -> WasiThreadHandle { + let id = self.thread_seed.inc(); + let ctrl = WasiThread::default(); + { + let mut guard = self.threads.write().unwrap(); + guard.insert(id, ctrl); + } + self.thread_count.fetch_add(1, Ordering::AcqRel); + + WasiThreadHandle { + id, + threads: self.threads.clone(), + thread_count: self.thread_count.clone() + } + } + + pub fn get(&self, tid: &WasiThreadId) -> Option { + let guard = self.threads.read().unwrap(); + guard.get(tid).map(|a| a.clone()) + } + + pub fn active_threads(&self) -> u32 { + self.thread_count.load(Ordering::Acquire) + } +} + +#[derive(Debug, Clone)] +pub struct WasiThreadHandle { + id: WasiThreadId, + threads: Arc>>, + pub(crate) thread_count: Arc, +} + +impl WasiThreadHandle { + pub fn id(&self) -> WasiThreadId { + self.id + } +} + +impl Drop +for WasiThreadHandle { + fn drop(&mut self) { + if let Some(ctrl) = { + let mut guard = self.threads.write().unwrap(); + guard.remove(&self.id) + } { + ctrl.mark_finished(); + } + self.thread_count.fetch_sub(1, Ordering::AcqRel); + } +} + +/// Represents a futex which will make threads wait for completion in a more +/// CPU efficient manner +#[derive(Debug, Clone)] +pub struct WasiFutex { + pub(crate) refcnt: Arc, + pub(crate) inner: Arc<(Mutex<()>, Condvar)>, +} + +#[derive(Debug)] +pub struct WasiBusCall +{ + pub bid: WasiBusProcessId, + pub invocation: Box, +} + +/// Protected area of the BUS state +#[derive(Debug, Default)] +pub struct WasiBusProtectedState +{ + pub call_seed: u64, + pub called: HashMap>, + pub calls: HashMap, +} + +/// Structure that holds the state of BUS calls to this process and from +/// this process. BUS calls are the equivalent of RPC's with support +/// for all the major serializers +#[derive(Debug, Default)] +pub struct WasiBusState +{ + protected: Mutex, + poll_waker: WasiParkingLot, +} + +impl WasiBusState +{ + /// Gets a reference to the waker that can be used for + /// asynchronous calls + pub fn get_poll_waker(&self) -> Waker { + self.poll_waker.get_waker() + } + + /// Wakes one of the reactors thats currently waiting + pub fn poll_wake(&self) { + self.poll_waker.wake() + } + + /// Will wait until either the reactor is triggered + /// or the timeout occurs + pub fn poll_wait(&self, timeout: Duration) -> bool { + self.poll_waker.wait(timeout) + } + + /// Locks the protected area of the BUS and returns a guard that + /// can be used to access it + pub fn protected<'a>(&'a self) -> MutexGuard<'a, WasiBusProtectedState> { + self.protected.lock().unwrap() + } } /// Top level data type containing all* the state with which WASI can @@ -1864,7 +1997,9 @@ pub(crate) struct WasiStateThreading { pub struct WasiState { pub fs: WasiFs, pub inodes: Arc>, - pub(crate) threading: Mutex, + pub(crate) threading: RwLock, + pub(crate) futexs: Mutex>, + pub(crate) bus: WasiBusState, pub args: Vec>, pub envs: Vec>, } @@ -1941,10 +2076,10 @@ impl WasiState { fd: __wasi_fd_t, ) -> Result>, FsError> { let ret = WasiStateFileGuard::new(self, fd)?.map(|a| { - let ret = Box::new(a); - let ret: Box = ret; - ret - }); + let ret = Box::new(a); + let ret: Box = ret; + ret + }); Ok(ret) } } @@ -1961,3 +2096,27 @@ pub fn virtual_file_type_to_wasi_file_type(file_type: wasmer_vfs::FileType) -> _ __WASI_FILETYPE_UNKNOWN } } + +#[derive(Debug, Clone)] +pub struct WasiDummyWaker; + +impl WakeRef for WasiDummyWaker { + fn wake_by_ref(&self) { + } +} + +impl Wake for WasiDummyWaker { + fn wake(self) { + } +} + +unsafe impl ViaRawPointer for WasiDummyWaker { + type Target = (); + fn into_raw(self) -> *mut () { + std::mem::forget(self); + std::ptr::null_mut() + } + unsafe fn from_raw(_ptr: *mut ()) -> Self { + WasiDummyWaker + } +} diff --git a/lib/wasi/src/state/parking.rs b/lib/wasi/src/state/parking.rs new file mode 100644 index 00000000000..bb25f5d8f95 --- /dev/null +++ b/lib/wasi/src/state/parking.rs @@ -0,0 +1,82 @@ +use std::{ + task::Waker, + sync::{ + Mutex, + Arc, + Condvar + }, + time::Duration +}; + +/// Represents a waker that can be used to put a thread to +/// sleep while it waits for an event to occur +#[derive(Debug)] +pub struct WasiParkingLot +{ + waker: Waker, + run: Arc<(Mutex, Condvar)>, +} + +impl Default +for WasiParkingLot +{ + fn default() -> Self + { + Self::new(true) + } +} + +impl WasiParkingLot +{ + /// Creates a new parking lot with a specific value + pub fn new(initial_val: bool) -> Self + { + let run = Arc::new((Mutex::new(initial_val), Condvar::default())); + let waker = { + let run = run.clone(); + waker_fn::waker_fn(move || + { + let mut guard = run.0.lock().unwrap(); + *guard = true; + run.1.notify_one(); + }) + }; + + Self { + waker, + run, + } + } + + /// Gets a reference to the waker that can be used for + /// asynchronous calls + pub fn get_waker(&self) -> Waker { + self.waker.clone() + } + + /// Wakes one of the reactors thats currently waiting + pub fn wake(&self) { + self.waker.wake_by_ref(); + } + + /// Will wait until either the reactor is triggered + /// or the timeout occurs + pub fn wait(&self, timeout: Duration) -> bool { + let mut run = self.run.0.lock().unwrap(); + if *run == true { + *run = false; + return true; + } + loop { + let woken = self.run.1.wait_timeout(run, timeout).unwrap(); + if woken.1.timed_out() { + return false; + } + run = woken.0; + if *run == true { + *run = false; + return true; + } + } + } +} \ No newline at end of file diff --git a/lib/wasi/src/state/thread.rs b/lib/wasi/src/state/thread.rs new file mode 100644 index 00000000000..0b3185163ca --- /dev/null +++ b/lib/wasi/src/state/thread.rs @@ -0,0 +1,56 @@ +use std::{ + sync::{ + Mutex, + Arc, + Condvar + }, + time::Duration +}; + +/// Represents a running thread which allows a joiner to +/// wait for the thread to exit +#[derive(Debug, Clone)] +pub struct WasiThread +{ + finished: Arc<(Mutex, Condvar)>, +} + +impl Default +for WasiThread +{ + fn default() -> Self + { + Self { + finished: Arc::new((Mutex::new(false), Condvar::default())), + } + } +} + +impl WasiThread +{ + /// Marks the thread as finished (which will cause anyone that + /// joined on it to wake up) + pub fn mark_finished(&self) { + let mut guard = self.finished.0.lock().unwrap(); + *guard = true; + self.finished.1.notify_all(); + } + + /// Waits until the thread is finished or the timeout is reached + pub fn join(&self, timeout: Duration) -> bool { + let mut finished = self.finished.0.lock().unwrap(); + if *finished == true { + return true; + } + loop { + let woken = self.finished.1.wait_timeout(finished, timeout).unwrap(); + if woken.1.timed_out() { + return false; + } + finished = woken.0; + if *finished == true { + return true; + } + } + } +} diff --git a/lib/wasi/src/state/types.rs b/lib/wasi/src/state/types.rs index 462a008f19f..695d4977f76 100644 --- a/lib/wasi/src/state/types.rs +++ b/lib/wasi/src/state/types.rs @@ -10,7 +10,7 @@ use std::{ sync::{Arc, Mutex}, time::Duration, }; -use wasmer_vbus::BusError; +use wasmer_vbus::VirtualBusError; #[cfg(feature = "host-fs")] pub use wasmer_vfs::host_fs::{Stderr, Stdin, Stdout}; @@ -102,8 +102,8 @@ pub fn net_error_into_wasi_err(net_error: NetworkError) -> __wasi_errno_t { } } -pub fn bus_error_into_wasi_err(bus_error: BusError) -> __bus_errno_t { - use BusError::*; +pub fn bus_error_into_wasi_err(bus_error: VirtualBusError) -> __bus_errno_t { + use VirtualBusError::*; match bus_error { Serialization => __BUS_ESER, Deserialization => __BUS_EDES, @@ -127,8 +127,8 @@ pub fn bus_error_into_wasi_err(bus_error: BusError) -> __bus_errno_t { } } -pub fn wasi_error_into_bus_err(bus_error: __bus_errno_t) -> BusError { - use BusError::*; +pub fn wasi_error_into_bus_err(bus_error: __bus_errno_t) -> VirtualBusError { + use VirtualBusError::*; match bus_error { __BUS_ESER => Serialization, __BUS_EDES => Deserialization, @@ -148,10 +148,24 @@ pub fn wasi_error_into_bus_err(bus_error: __bus_errno_t) -> BusError { __BUS_EINVOKE => InvokeFailed, __BUS_ECONSUMED => AlreadyConsumed, __BUS_EMEMVIOLATION => MemoryAccessViolation, - /*__BUS_EUNKNOWN |*/ _ => UnknownError, + __BUS_EUNKNOWN | _ => UnknownError, } } +pub(crate) fn bus_read_rights() -> __wasi_rights_t { + __WASI_RIGHT_FD_FDSTAT_SET_FLAGS + | __WASI_RIGHT_FD_FILESTAT_GET + | __WASI_RIGHT_FD_READ + | __WASI_RIGHT_POLL_FD_READWRITE +} + +pub(crate) fn bus_write_rights() -> __wasi_rights_t { + __WASI_RIGHT_FD_FDSTAT_SET_FLAGS + | __WASI_RIGHT_FD_FILESTAT_GET + | __WASI_RIGHT_FD_WRITE + | __WASI_RIGHT_POLL_FD_READWRITE +} + #[derive(Debug, Clone)] #[allow(clippy::enum_variant_names)] pub enum PollEvent { diff --git a/lib/wasi/src/syscalls/legacy/snapshot0.rs b/lib/wasi/src/syscalls/legacy/snapshot0.rs index 033abe11e04..ae69976923d 100644 --- a/lib/wasi/src/syscalls/legacy/snapshot0.rs +++ b/lib/wasi/src/syscalls/legacy/snapshot0.rs @@ -1,6 +1,6 @@ use crate::syscalls; use crate::syscalls::types::{self, snapshot0}; -use crate::{mem_error_to_wasi, Memory32, MemorySize, WasiEnv, WasiError, WasiThread}; +use crate::{mem_error_to_wasi, Memory32, MemorySize, WasiEnv, WasiError}; use wasmer::{AsStoreMut, FunctionEnvMut, WasmPtr}; /// Wrapper around `syscalls::fd_filestat_get` with extra logic to handle the size @@ -27,7 +27,7 @@ pub fn fd_filestat_get( // Set up complete, make the call with the pointer that will write to the // struct and some unrelated memory after the struct. - let result = syscalls::fd_filestat_get::(ctx.as_mut(), fd, new_buf); + let result = syscalls::fd_filestat_get_internal::(&mut ctx, fd, new_buf); // reborrow memory let env = ctx.data(); @@ -130,40 +130,43 @@ pub fn poll_oneoff( // in this case the new type is smaller than the old type, so it all fits into memory, // we just need to readjust and copy it - // we start by adjusting `in_` into a format that the new code can understand - let env = ctx.data(); - let memory = env.memory_view(&ctx); let nsubscriptions_offset: u32 = nsubscriptions; - let in_origs = wasi_try_mem_ok!(in_.slice(&memory, nsubscriptions_offset)); - let in_origs = wasi_try_mem_ok!(in_origs.read_to_vec()); - - // get a pointer to the smaller new type - let in_new_type_ptr: WasmPtr = in_.cast(); - - for (in_sub_new, orig) in - wasi_try_mem_ok!(in_new_type_ptr.slice(&memory, nsubscriptions_offset)) - .iter() - .zip(in_origs.iter()) - { - wasi_try_mem_ok!(in_sub_new.write(types::__wasi_subscription_t { - userdata: orig.userdata, - type_: orig.type_, - u: if orig.type_ == types::__WASI_EVENTTYPE_CLOCK { - types::__wasi_subscription_u { - clock: types::__wasi_subscription_clock_t { - clock_id: unsafe { orig.u.clock.clock_id }, - timeout: unsafe { orig.u.clock.timeout }, - precision: unsafe { orig.u.clock.precision }, - flags: unsafe { orig.u.clock.flags }, - }, - } - } else { - types::__wasi_subscription_u { - fd_readwrite: unsafe { orig.u.fd_readwrite }, - } - }, - })); - } + let in_new_type_ptr = { + // we start by adjusting `in_` into a format that the new code can understand + let env = ctx.data(); + let memory = env.memory_view(&ctx); + let in_origs = wasi_try_mem_ok!(in_.slice(&memory, nsubscriptions_offset)); + let in_origs = wasi_try_mem_ok!(in_origs.read_to_vec()); + + // get a pointer to the smaller new type + let in_new_type_ptr: WasmPtr = in_.cast(); + + for (in_sub_new, orig) in + wasi_try_mem_ok!(in_new_type_ptr.slice(&memory, nsubscriptions_offset)) + .iter() + .zip(in_origs.iter()) + { + wasi_try_mem_ok!(in_sub_new.write(types::__wasi_subscription_t { + userdata: orig.userdata, + type_: orig.type_, + u: if orig.type_ == types::__WASI_EVENTTYPE_CLOCK { + types::__wasi_subscription_u { + clock: types::__wasi_subscription_clock_t { + clock_id: unsafe { orig.u.clock.clock_id }, + timeout: unsafe { orig.u.clock.timeout }, + precision: unsafe { orig.u.clock.precision }, + flags: unsafe { orig.u.clock.flags }, + }, + } + } else { + types::__wasi_subscription_u { + fd_readwrite: unsafe { orig.u.fd_readwrite }, + } + }, + })); + } + in_new_type_ptr + }; // make the call let result = syscalls::poll_oneoff::( @@ -172,11 +175,13 @@ pub fn poll_oneoff( out_, nsubscriptions, nevents, - ); + )?; // replace the old values of in, in case the calling code reuses the memory let env = ctx.data(); let memory = env.memory_view(&ctx); + let in_origs = wasi_try_mem_ok!(in_.slice(&memory, nsubscriptions_offset)); + let in_origs = wasi_try_mem_ok!(in_origs.read_to_vec()); for (in_sub, orig) in wasi_try_mem_ok!(in_.slice(&memory, nsubscriptions_offset)) .iter() @@ -185,5 +190,5 @@ pub fn poll_oneoff( wasi_try_mem_ok!(in_sub.write(orig)); } - result + Ok(result) } diff --git a/lib/wasi/src/syscalls/mod.rs b/lib/wasi/src/syscalls/mod.rs index 0c5266e6efc..a639c70e817 100644 --- a/lib/wasi/src/syscalls/mod.rs +++ b/lib/wasi/src/syscalls/mod.rs @@ -11,20 +11,17 @@ pub mod types { target_vendor = "apple" ))] pub mod unix; -#[cfg(any(target_arch = "wasm32"))] -pub mod wasm32; +#[cfg(any(target_family = "wasm"))] +pub mod wasm; #[cfg(any(target_os = "windows"))] pub mod windows; pub mod legacy; -//pub mod wasi; -pub mod wasix32; -pub mod wasix64; use self::types::*; -use crate::state::{bus_error_into_wasi_err, wasi_error_into_bus_err, InodeHttpSocketType}; +use crate::state::{bus_error_into_wasi_err, wasi_error_into_bus_err, InodeHttpSocketType, WasiFutex, bus_write_rights, bus_read_rights, WasiBusCall, WasiThreadContext, WasiParkingLot, WasiDummyWaker}; use crate::utils::map_io_err; -use crate::WasiBusProcessId; +use crate::{WasiBusProcessId, WasiEnvInner, import_object_for_all_wasi_versions, WasiFunctionEnv, current_caller_id}; use crate::{ mem_error_to_wasi, state::{ @@ -32,25 +29,34 @@ use crate::{ virtual_file_type_to_wasi_file_type, Fd, Inode, InodeSocket, InodeSocketKind, InodeVal, Kind, PollEvent, PollEventBuilder, WasiPipe, WasiState, MAX_SYMLINKS, }, - WasiEnv, WasiError, WasiThread, WasiThreadId, + WasiEnv, WasiError, WasiThreadId, }; use bytes::Bytes; +use cooked_waker::IntoWaker; +use sha2::Sha256; +use wasmer::vm::VMMemory; use std::borrow::{Borrow, Cow}; +use std::cell::RefCell; +use std::collections::HashSet; +use std::collections::hash_map::Entry; use std::convert::{Infallible, TryInto}; use std::io::{self, Read, Seek, Write}; use std::mem::transmute; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; use std::ops::{Deref, DerefMut}; -use std::sync::atomic::AtomicU64; +use std::pin::Pin; +use std::sync::atomic::{AtomicU64, AtomicU32}; use std::sync::{atomic::Ordering, Mutex}; -use std::sync::{mpsc, Arc}; +use std::sync::{mpsc, Arc, Condvar}; +use std::task::{Poll, Context}; +use std::thread::LocalKey; use std::time::Duration; use tracing::{debug, error, trace, warn}; use wasmer::{ - AsStoreMut, Extern, FunctionEnv, FunctionEnvMut, Instance, Memory, Memory32, Memory64, - MemorySize, MemoryView, Module, RuntimeError, Value, WasmPtr, WasmSlice, + AsStoreMut, FunctionEnvMut, Memory, Memory32, Memory64, MemorySize, RuntimeError, Value, + WasmPtr, WasmSlice, FunctionEnv, Instance, Module, Extern, MemoryView, TypedFunction, Store, Pages, Global, AsStoreRef, }; -use wasmer_vbus::{FileDescriptor, StdioMode}; +use wasmer_vbus::{FileDescriptor, StdioMode, BusDataFormat, BusInvocationEvent}; use wasmer_vfs::{FsError, VirtualFile}; use wasmer_vnet::{SocketHttpRequest, StreamSecurity}; @@ -65,8 +71,8 @@ pub use unix::*; #[cfg(any(target_os = "windows"))] pub use windows::*; -#[cfg(any(target_arch = "wasm32"))] -pub use wasm32::*; +#[cfg(any(target_family = "wasm"))] +pub use wasm::*; fn to_offset(offset: usize) -> Result { let ret: M::Offset = offset.try_into().map_err(|_| __WASI_EINVAL)?; @@ -164,8 +170,7 @@ where let inode = &inodes.arena[inode_idx]; let mut guard = inode.read(); - let deref = guard.deref(); - match deref { + match guard.deref() { Kind::Socket { socket } => actor(socket)?, _ => { return Err(__WASI_ENOTSOCK); @@ -198,8 +203,7 @@ where let inode = &inodes.arena[inode_idx]; let mut guard = inode.write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::Socket { socket } => actor(socket)?, _ => { return Err(__WASI_ENOTSOCK); @@ -233,8 +237,7 @@ where let inode = &inodes.arena[inode_idx]; let mut guard = inode.write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::Socket { socket } => { let new_socket = actor(socket)?; @@ -393,7 +396,7 @@ pub fn clock_time_get( precision: __wasi_timestamp_t, time: WasmPtr<__wasi_timestamp_t, M>, ) -> __wasi_errno_t { - debug!( + trace!( "wasi::clock_time_get clock_id: {}, precision: {}", clock_id, precision ); @@ -425,7 +428,7 @@ pub fn environ_get( environ: WasmPtr, M>, environ_buf: WasmPtr, ) -> __wasi_errno_t { - debug!( + trace!( "wasi::environ_get. Environ: {:?}, environ_buf: {:?}", environ, environ_buf ); @@ -523,8 +526,7 @@ pub fn fd_allocate( let new_size = wasi_try!(offset.checked_add(len).ok_or(__WASI_EINVAL)); { let mut guard = inodes.arena[inode].write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::File { handle, .. } => { if let Some(handle) = handle { wasi_try!(handle.set_len(new_size).map_err(fs_error_into_wasi_err)); @@ -689,7 +691,23 @@ pub fn fd_fdstat_set_rights( /// - `__wasi_filestat_t *buf` /// Where the metadata from `fd` will be written pub fn fd_filestat_get( - ctx: FunctionEnvMut<'_, WasiEnv>, + mut ctx: FunctionEnvMut<'_, WasiEnv>, + fd: __wasi_fd_t, + buf: WasmPtr<__wasi_filestat_t, M>, +) -> __wasi_errno_t { + fd_filestat_get_internal(&mut ctx, fd, buf) +} + +/// ### `fd_filestat_get()` +/// Get the metadata of an open file +/// Input: +/// - `__wasi_fd_t fd` +/// The open file descriptor whose metadata will be read +/// Output: +/// - `__wasi_filestat_t *buf` +/// Where the metadata from `fd` will be written +pub(crate) fn fd_filestat_get_internal( + ctx: &mut FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t, buf: WasmPtr<__wasi_filestat_t, M>, ) -> __wasi_errno_t { @@ -733,8 +751,7 @@ pub fn fd_filestat_set_size( { let mut guard = inodes.arena[inode].write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::File { handle, .. } => { if let Some(handle) = handle { wasi_try!(handle.set_len(st_size).map_err(fs_error_into_wasi_err)); @@ -873,8 +890,7 @@ pub fn fd_pread( return Ok(__WASI_EACCES); } let mut guard = inodes.arena[inode].write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::File { handle, .. } => { if let Some(h) = handle { wasi_try_ok!( @@ -897,7 +913,10 @@ pub fn fd_pread( Kind::Dir { .. } | Kind::Root { .. } => return Ok(__WASI_EISDIR), Kind::Symlink { .. } => unimplemented!("Symlinks in wasi::fd_pread"), Kind::Buffer { buffer } => { - wasi_try_ok!(read_bytes(&buffer[(offset as usize)..], &memory, iovs), env) + wasi_try_ok!( + read_bytes(&buffer[(offset as usize)..], &memory, iovs), + env + ) } } } @@ -927,14 +946,13 @@ pub fn fd_prestat_get( let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); let prestat_ptr = buf.deref(&memory); - wasi_try_mem!( - prestat_ptr.write(wasi_try!(state.fs.prestat_fd(inodes.deref(), fd).map_err( - |code| { + wasi_try_mem!(prestat_ptr.write(wasi_try!( + state.fs.prestat_fd(inodes.deref(), fd) + .map_err(|code| { debug!("fd_prestat_get failed (fd={}) - errno={}", fd, code); code - } - ))) - ); + }) + ))); __WASI_ESUCCESS } @@ -961,8 +979,7 @@ pub fn fd_prestat_dir_name( trace!("=> inode: {:?}", inode_val); let guard = inode_val.read(); - let deref = guard.deref(); - match deref { + match guard.deref() { Kind::Dir { .. } | Kind::Root { .. } => { // TODO: verify this: null termination, etc let path_len: u64 = path_len.into(); @@ -1057,8 +1074,7 @@ pub fn fd_pwrite( let inode = &inodes.arena[inode_idx]; let mut guard = inode.write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::File { handle, .. } => { if let Some(handle) = handle { wasi_try_ok!( @@ -1157,8 +1173,7 @@ pub fn fd_read( let bytes_read = { let mut guard = inode.write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::File { handle, .. } => { if let Some(handle) = handle { wasi_try_ok!( @@ -1295,8 +1310,7 @@ pub fn fd_readdir( let entries: Vec<(String, u8, u64)> = { let guard = inodes.arena[working_dir.inode].read(); - let deref = guard.deref(); - match deref { + match guard.deref() { Kind::Dir { path, entries, .. } => { debug!("Reading dir {:?}", path); // TODO: refactor this code @@ -1477,7 +1491,7 @@ pub fn fd_event( inodes.deref_mut(), kind, false, - "event".to_string(), + "event".into(), ); let rights = __WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_WRITE | __WASI_RIGHT_POLL_FD_READWRITE; let fd = wasi_try!(state.fs.create_fd(rights, rights, 0, 0, inode)); @@ -1527,8 +1541,7 @@ pub fn fd_seek( use std::io::SeekFrom; let inode_idx = fd_entry.inode; let mut guard = inodes.arena[inode_idx].write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::File { ref mut handle, .. } => { if let Some(handle) = handle { let end = @@ -1598,8 +1611,7 @@ pub fn fd_sync(ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errn // TODO: implement this for more than files { let mut guard = inodes.arena[inode].write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::File { handle, .. } => { if let Some(h) = handle { wasi_try!(h.sync_to_disk().map_err(fs_error_into_wasi_err)); @@ -1715,8 +1727,7 @@ pub fn fd_write( let bytes_written = { let mut guard = inode.write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::File { handle, .. } => { if let Some(handle) = handle { wasi_try_ok!( @@ -1744,7 +1755,8 @@ pub fn fd_write( counter, wakers, .. } => { let mut val = 0u64.to_ne_bytes(); - let written = wasi_try_ok!(write_bytes(&mut val[..], &memory, iovs_arr)); + let written = + wasi_try_ok!(write_bytes(&mut val[..], &memory, iovs_arr)); if written != val.len() { return Ok(__WASI_EINVAL); } @@ -1764,7 +1776,10 @@ pub fn fd_write( } Kind::Symlink { .. } => unimplemented!("Symlinks in wasi::fd_write"), Kind::Buffer { buffer } => { - wasi_try_ok!(write_bytes(&mut buffer[offset..], &memory, iovs_arr), env) + wasi_try_ok!( + write_bytes(&mut buffer[offset..], &memory, iovs_arr), + env + ) } } }; @@ -1811,13 +1826,13 @@ pub fn fd_pipe( inodes.deref_mut(), Kind::Pipe { pipe: pipe1 }, false, - "pipe".to_string(), + "pipe".into(), ); let inode2 = state.fs.create_inode_with_default_stat( inodes.deref_mut(), Kind::Pipe { pipe: pipe2 }, false, - "pipe".to_string(), + "pipe".into(), ); let rights = super::state::all_socket_rights(); @@ -1886,8 +1901,7 @@ pub fn path_create_directory( for comp in &path_vec { debug!("Creating dir {}", comp); let mut guard = inodes.arena[cur_dir_inode].write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::Dir { ref mut entries, path, @@ -2189,8 +2203,7 @@ pub fn path_link( } { let mut guard = inodes.arena[target_parent_inode].write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::Dir { entries, .. } => { if entries.contains_key(&new_entry_name) { return __WASI_EEXIST; @@ -2295,8 +2308,7 @@ pub fn path_open( let inode = if let Ok(inode) = maybe_inode { // Happy path, we found the file we're trying to open let mut guard = inodes.arena[inode].write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::File { ref mut handle, path, @@ -2383,8 +2395,7 @@ pub fn path_open( )); let new_file_host_path = { let guard = inodes.arena[parent_inode].read(); - let deref = guard.deref(); - match deref { + match guard.deref() { Kind::Dir { path, .. } => { let mut new_path = path.clone(); new_path.push(&new_entity_name); @@ -2444,10 +2455,6 @@ pub fn path_open( } }; - { - debug!("inode {:?} value {:#?} found!", inode, inodes.arena[inode]); - } - // TODO: check and reduce these // TODO: ensure a mutable fd to root can never be opened let out_fd = wasi_try!(state.fs.create_fd( @@ -2514,7 +2521,8 @@ pub fn path_readlink( } let bytes: Vec<_> = bytes.collect(); - let out = wasi_try_mem!(buf.slice(&memory, wasi_try!(to_offset::(bytes.len())))); + let out = + wasi_try_mem!(buf.slice(&memory, wasi_try!(to_offset::(bytes.len())))); wasi_try_mem!(out.write_slice(&bytes)); // should we null terminate this? @@ -2556,8 +2564,7 @@ pub fn path_remove_directory( let host_path_to_remove = { let guard = inodes.arena[inode].read(); - let deref = guard.deref(); - match deref { + match guard.deref() { Kind::Dir { entries, path, .. } => { if !entries.is_empty() || wasi_try!(state.fs_read_dir(path)).count() != 0 { return __WASI_ENOTEMPTY; @@ -2571,8 +2578,7 @@ pub fn path_remove_directory( { let mut guard = inodes.arena[parent_inode].write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::Dir { ref mut entries, .. } => { @@ -2676,10 +2682,10 @@ pub fn path_rename( wasi_try!(state .fs .get_parent_inode_at_path(inodes.deref_mut(), new_fd, target_path, true)); + let host_adjusted_target_path = { let guard = inodes.arena[target_parent_inode].read(); - let deref = guard.deref(); - match deref { + match guard.deref() { Kind::Dir { entries, path, .. } => { if entries.contains_key(&target_entry_name) { return __WASI_EEXIST; @@ -2700,8 +2706,7 @@ pub fn path_rename( let source_entry = { let mut guard = inodes.arena[source_parent_inode].write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::Dir { entries, .. } => { wasi_try!(entries.remove(&source_entry_name).ok_or(__WASI_ENOENT)) } @@ -2717,8 +2722,7 @@ pub fn path_rename( { let mut guard = inodes.arena[source_entry].write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::File { handle, ref path, .. } => { @@ -2840,8 +2844,7 @@ pub fn path_symlink( // short circuit if anything is wrong, before we create an inode { let guard = inodes.arena[target_parent_inode].read(); - let deref = guard.deref(); - match deref { + match guard.deref() { Kind::Dir { entries, .. } => { if entries.contains_key(&entry_name) { return __WASI_EEXIST; @@ -2878,7 +2881,7 @@ pub fn path_symlink( inodes.deref_mut(), kind, false, - entry_name.clone(), + entry_name.clone().into(), ); { @@ -2932,8 +2935,7 @@ pub fn path_unlink_file( let removed_inode = { let mut guard = inodes.arena[parent_inode].write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::Dir { ref mut entries, .. } => { @@ -2958,8 +2960,7 @@ pub fn path_unlink_file( if st_nlink == 0 { { let mut guard = inodes.arena[removed_inode].write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::File { handle, path, .. } => { if let Some(h) = handle { wasi_try!(h.unlink().map_err(fs_error_into_wasi_err)); @@ -3119,8 +3120,7 @@ pub fn poll_oneoff( { let guard = inodes.arena[inode].read(); - let deref = guard.deref(); - match deref { + match guard.deref() { Kind::File { handle, .. } => { if let Some(h) = handle { crate::state::InodeValFileReadGuard { guard } @@ -3494,83 +3494,340 @@ pub fn chdir( /// Returns the thread index of the newly created thread /// (indices always start from zero) pub fn thread_spawn( - ctx: FunctionEnvMut<'_, WasiEnv>, - method: WasmPtr, - method_len: M::Offset, + mut ctx: FunctionEnvMut<'_, WasiEnv>, user_data: u64, reactor: __wasi_bool_t, ret_tid: WasmPtr<__wasi_tid_t, M>, ) -> __wasi_errno_t { - debug!("wasi::thread_spawn"); + debug!("wasi::thread_spawn (reactor={}, thread_id={}, caller_id={})", reactor, ctx.data().id.raw(), current_caller_id().raw()); + + // Now we use the environment and memory references let env = ctx.data(); let memory = env.memory_view(&ctx); - let method = unsafe { get_input_str!(&memory, method, method_len) }; + let runtime = env.runtime.clone(); - // Load the callback function - if method.as_str() != "_thread_start" { - return __WASI_ENOTCAPABLE; + // Create the handle that represents this thread + let mut thread_handle = { + let mut guard = env.state.threading.write().unwrap(); + guard.new_thread() }; - /* - let funct = unsafe { - if env.thread_start_ref().is_none() { - return __WASI_EADDRNOTAVAIL; + let thread_id: __wasi_tid_t = thread_handle.id().into(); + + // We need a copy of the process memory and a packaged store in order to + // launch threads and reactors + let thread_memory = wasi_try!( + ctx.data() + .memory() + .try_clone(&ctx) + .ok_or_else(|| { + error!("thread failed - the memory could not be cloned"); + __WASI_ENOTCAPABLE + }) + ); + #[cfg(feature = "compiler")] + let engine = ctx.as_store_ref().engine().clone(); + + // This function takes in memory and a store and creates a context that + // can be used to call back into the process + let create_ctx = { + let state = env.state.clone(); + let wasi_env = env.clone(); + let thread_id = thread_handle.id(); + move |module: Module, memory: VMMemory| + { + // We need to reconstruct some things + #[cfg(feature = "compiler")] + let mut store = Store::new(engine); + #[cfg(not(feature = "compiler"))] + let mut store = Store::default(); + let module = module.clone(); + let memory = Memory::new_from_existing(&mut store, memory); + + // Build the context object and import the memory + let mut ctx = WasiFunctionEnv::new(&mut store, wasi_env.clone()); + ctx.data_mut(&mut store).id = thread_id; + + let mut import_object = import_object_for_all_wasi_versions(&mut store, &ctx.env); + import_object.define("env", "memory", memory.clone()); + + let instance = match Instance::new(&mut store, &module, &import_object) { + Ok(a) => a, + Err(err) => { + error!("thread failed - clone instance failed: {}", err); + return Err(__WASI_ENOEXEC as u32); + } + }; + + // Set the current thread ID + ctx.data_mut(&mut store).inner = Some( + WasiEnvInner { + module, + memory, + thread_spawn: instance.exports.get_typed_function(&store, "_start_thread").ok(), + react: instance.exports.get_typed_function(&store, "_react").ok(), + thread_local_destroy: instance.exports.get_typed_function(&store, "_thread_local_destroy").ok(), + _malloc: instance.exports.get_typed_function(&store, "_malloc").ok(), + _free: instance.exports.get_typed_function(&store, "_free").ok() + } + ); + trace!("threading: new context created for thread_id = {}", thread_id.raw()); + Ok(WasiThreadContext { + ctx, + store: RefCell::new(store) + }) } - env.thread_start_ref_unchecked() }; - */ - let reactor = match reactor { - __WASI_BOOL_FALSE => false, - __WASI_BOOL_TRUE => true, - _ => return __WASI_EINVAL, - }; - - // Create the sub-thread - let mut sub_env = env.clone(); - let mut sub_thread = env.new_thread(); - sub_env.id = sub_thread.id; - - let child = { - let id = sub_thread.id; - wasi_try!(env - .runtime - .thread_spawn(Box::new(move || { - /* - if let Some(funct) = sub_env.thread_start_ref() { - if let Err(err) = funct.call(user_data) { - warn!("thread failed: {}", err); - std::mem::forget(sub_thread); - return; + // This function calls into the module + let call_module = move |ctx: &WasiFunctionEnv, store: &mut Store| + { + // We either call the reactor callback or the thread spawn callback + //trace!("threading: invoking thread callback (reactor={})", reactor); + let spawn = match reactor { + __WASI_BOOL_FALSE => ctx.data(&store).inner().thread_spawn.clone().unwrap(), + __WASI_BOOL_TRUE => ctx.data(&store).inner().react.clone().unwrap(), + _ => { + debug!("thread failed - failed as the reactor type is not value"); + return __WASI_ENOEXEC as u32; + } + }; + let mut ret = __WASI_ESUCCESS; + if let Err(err) = spawn.call(store, user_data as i64) { + debug!("thread failed - start: {}", err); + ret = __WASI_ENOEXEC; + } + //trace!("threading: thread callback finished (reactor={}, ret={})", reactor, ret); + + // If we are NOT a reactor then we will only run once and need to clean up + if reactor == __WASI_BOOL_FALSE + { + trace!("threading: cleaning up local thread variables"); + + // Destroy all the local thread variables that were allocated for this thread + let to_local_destroy = { + let thread_id = ctx.data(store).id; + let mut to_local_destroy = Vec::new(); + let mut guard = ctx.data(store).state.threading.write().unwrap(); + for ((thread, key), val) in guard.thread_local.iter() { + if *thread == thread_id { + if let Some(user_data) = guard.thread_local_user_data.get(key) { + to_local_destroy.push((*user_data, *val)) + } } - } else { - warn!("failed to start thread: missing callback '__wasix_thread_start'"); - std::mem::forget(sub_thread); - return; } - */ + guard.thread_local.retain(|(t, _), _| *t != thread_id); + to_local_destroy + }; + if to_local_destroy.len() > 0 { + if let Some(thread_local_destroy) = ctx.data(store).inner().thread_local_destroy.as_ref().map(|a| a.clone()) { + for (userdata, val) in to_local_destroy { + let _ = thread_local_destroy.call(store, user_data as i64, val as i64); + } + } + } + } + // Return the result + ret as u32 + }; + + // This next function gets a context for the local thread and then + // calls into the process + let mut execute_module = { + let state = env.state.clone(); + move |module: Module, memory: &mut Option| + { + // We capture the thread handle here, it is used to notify + // anyone that is interested when this thread has terminated + let _captured_handle = Box::new(&mut thread_handle); + + // Given that it is not safe to assume this delegate will run on the + // same thread we need to capture a simple process that will create + // context objects on demand and reuse them + let caller_id = current_caller_id(); + + // We loop because read locks are held while functions run which need + // to be relocked in the case of a miss hit. + loop { let thread = { - let mut guard = sub_env.state.threading.lock().unwrap(); - let thread = guard.threads.remove(&id); - drop(guard); - thread + let guard = state.threading.read().unwrap(); + guard.thread_ctx.get(&caller_id).map(|a| a.clone()) }; - - if let Some(thread) = thread { - let mut thread_guard = thread.exit.lock().unwrap(); - thread_guard.take(); + if let Some(thread) = thread + { + let mut store = thread.store.borrow_mut(); + let ret = call_module(&thread.ctx, store.deref_mut()); + return ret; } - drop(sub_thread); - })) - .map_err(|err| { - let err: __wasi_errno_t = err.into(); - err - })); - id + + // Otherwise we need to create a new context under a write lock + debug!("encountered a new caller (ref={}) - creating WASM execution context...", caller_id.raw()); + + // We can only create the context once per thread + let memory = match memory.take() { + Some(m) => m, + None => { + debug!("thread failed - memory can only be consumed once per context creation"); + return __WASI_ENOEXEC as u32; + } + }; + + // Now create the context and hook it up + let mut guard = state.threading.write().unwrap(); + let ctx = match create_ctx(module.clone(), memory) { + Ok(c) => c, + Err(err) => { + return err; + } + }; + guard.thread_ctx.insert(caller_id, Arc::new(ctx)); + } + } }; - let child: __wasi_tid_t = child.into(); - wasi_try_mem!(ret_tid.write(&memory, child)); + // If we are a reactor then instead of launching the thread now + // we store it in the state machine and only launch it whenever + // work arrives that needs to be processed + match reactor { + __WASI_BOOL_TRUE => { + warn!("thread failed - reactors are not currently supported"); + return __WASI_ENOTCAPABLE; + }, + __WASI_BOOL_FALSE => { + // If the process does not export a thread spawn function then obviously + // we can't spawn a background thread + if env.inner().thread_spawn.is_none() { + warn!("thread failed - the program does not export a _start_thread function"); + return __WASI_ENOTCAPABLE; + } + + // Now spawn a thread + trace!("threading: spawning background thread"); + let thread_module = env.inner().module.clone(); + wasi_try!(runtime + .thread_spawn(Box::new(move |module: Module, thread_memory: VMMemory| { + let mut thread_memory = Some(thread_memory); + execute_module(module, &mut thread_memory); + }), thread_module, thread_memory) + .map_err(|err| { + let err: __wasi_errno_t = err.into(); + err + })); + }, + _ => { + warn!("thread failed - invalid reactor parameter value"); + return __WASI_ENOTCAPABLE; + } + } + + // Success + let memory = ctx.data().memory_view(&ctx); + wasi_try_mem!(ret_tid.write(&memory, thread_id)); + __WASI_ESUCCESS +} + +/// ### `thread_local_create()` +/// Create a thread local variable +/// If The web assembly process exports function named '_thread_local_destroy' +/// then it will be invoked when the thread goes out of scope and dies. +/// +/// ## Parameters +/// +/// * `user_data` - User data that will be passed to the destructor +/// when the thread variable goes out of scope +pub fn thread_local_create( + ctx: FunctionEnvMut<'_, WasiEnv>, + user_data: u64, + ret_key: WasmPtr<__wasi_tl_key_t, M>, +) -> __wasi_errno_t { + trace!("wasi::thread_local_create (user_data={})", user_data); + let env = ctx.data(); + + let key = { + let mut guard = env.state.threading.write().unwrap(); + guard.thread_local_seed += 1; + let key = guard.thread_local_seed; + guard.thread_local_user_data.insert(key, user_data); + key + }; + + let memory = env.memory_view(&ctx); + wasi_try_mem!(ret_key.write(&memory, key)); + __WASI_ESUCCESS +} + +/// ### `thread_local_destroy()` +/// Destroys a thread local variable +/// +/// ## Parameters +/// +/// * `user_data` - User data that will be passed to the destructor +/// when the thread variable goes out of scope +/// * `key` - Thread key that was previously created +pub fn thread_local_destroy( + mut ctx: FunctionEnvMut<'_, WasiEnv>, + key: __wasi_tl_key_t +) -> __wasi_errno_t { + trace!("wasi::thread_local_destroy (key={})", key); + let state = ctx.data().state.clone(); + let mut guard = state.threading.write().unwrap(); + if let Some(user_data) = guard.thread_local_user_data.remove(&key) { + if let Some(thread_local_destroy) = ctx.data().inner().thread_local_destroy.as_ref().map(|a| a.clone()) { + guard.thread_local + .iter() + .filter(|((_, k), _)| *k == key) + .for_each(|((_, _), val)| { + let _ = thread_local_destroy.call(&mut ctx, user_data as i64, *val as i64); + }); + } + } + guard.thread_local.retain(|(_, k), _| *k != key); + __WASI_ESUCCESS +} + +/// ### `thread_local_set()` +/// Sets the value of a thread local variable +/// +/// ## Parameters +/// +/// * `key` - Thread key that this local variable will be associated with +/// * `val` - Value to be set for the thread local variable +pub fn thread_local_set( + ctx: FunctionEnvMut<'_, WasiEnv>, + key: __wasi_tl_key_t, + val: __wasi_tl_val_t +) -> __wasi_errno_t { + //trace!("wasi::thread_local_set (key={}, val={})", key, val); + let env = ctx.data(); + + let current_thread = ctx.data().id; + let mut guard = env.state.threading.write().unwrap(); + guard.thread_local.insert((current_thread, key), val); + __WASI_ESUCCESS +} + +/// ### `thread_local_get()` +/// Gets the value of a thread local variable +/// +/// ## Parameters +/// +/// * `key` - Thread key that this local variable that was previous set +pub fn thread_local_get( + ctx: FunctionEnvMut<'_, WasiEnv>, + key: __wasi_tl_key_t, + ret_val: WasmPtr<__wasi_tl_val_t, M>, +) -> __wasi_errno_t { + //trace!("wasi::thread_local_get (key={})", key); + let env = ctx.data(); + + let val = { + let current_thread = ctx.data().id; + let guard = env.state.threading.read().unwrap(); + guard.thread_local.get(&(current_thread, key)).map(|a| a.clone()) + }; + let val = val.unwrap_or_default(); + let memory = env.memory_view(&ctx); + wasi_try_mem!(ret_val.write(&memory, val)); __WASI_ESUCCESS } @@ -3584,7 +3841,7 @@ pub fn thread_sleep( ctx: FunctionEnvMut<'_, WasiEnv>, duration: __wasi_timestamp_t, ) -> Result<__wasi_errno_t, WasiError> { - debug!("wasi::thread_sleep"); + //trace!("wasi::thread_sleep"); let env = ctx.data(); let duration = Duration::from_nanos(duration as u64); @@ -3599,7 +3856,7 @@ pub fn thread_id( ctx: FunctionEnvMut<'_, WasiEnv>, ret_tid: WasmPtr<__wasi_tid_t, M>, ) -> __wasi_errno_t { - debug!("wasi::thread_id"); + //trace!("wasi::thread_id"); let env = ctx.data(); let tid: __wasi_tid_t = env.id.into(); @@ -3624,15 +3881,15 @@ pub fn thread_join( let env = ctx.data(); let tid: WasiThreadId = tid.into(); let other_thread = { - let guard = env.state.threading.lock().unwrap(); - guard.threads.get(&tid).cloned() + let guard = env.state.threading.read().unwrap(); + guard.get(&tid) }; if let Some(other_thread) = other_thread { loop { - if other_thread.join(Duration::from_millis(5)) { + env.yield_now()?; + if other_thread.join(Duration::from_millis(50)) { break; } - env.yield_now()?; } Ok(__WASI_ESUCCESS) } else { @@ -3660,6 +3917,161 @@ pub fn thread_parallelism( __WASI_ESUCCESS } +/// Wait for a futex_wake operation to wake us. +/// Returns with EINVAL if the futex doesn't hold the expected value. +/// Returns false on timeout, and true in all other cases. +/// +/// ## Parameters +/// +/// * `futex` - Memory location that holds the value that will be checked +/// * `expected` - Expected value that should be currently held at the memory location +/// * `timeout` - Timeout should the futex not be triggered in the allocated time +pub fn futex_wait( + ctx: FunctionEnvMut<'_, WasiEnv>, + futex_ptr: WasmPtr, + expected: u32, + timeout: WasmPtr<__wasi_option_timestamp_t, M>, + ret_woken: WasmPtr<__wasi_bool_t, M>, +) -> Result<__wasi_errno_t, WasiError> { + trace!("wasi::futex_wait(offset={})", futex_ptr.offset()); + let env = ctx.data(); + let state = env.state.deref(); + + let pointer: u64 = wasi_try_ok!(futex_ptr.offset().try_into().map_err(|_| __WASI_EOVERFLOW)); + + // Register the waiting futex + let futex = { + use std::collections::hash_map::Entry; + let mut guard = state.futexs.lock().unwrap(); + match guard.entry(pointer) { + Entry::Occupied(entry) => { + entry.get().clone() + }, + Entry::Vacant(entry) => { + let futex = WasiFutex { + refcnt: Arc::new(AtomicU32::new(1)), + inner: Arc::new((Mutex::new(()), Condvar::new())) + }; + entry.insert(futex.clone()); + futex + } + } + }; + + // Loop until we either hit a yield error or the futex is woken + let mut yielded = Ok(()); + loop { + let futex_lock = futex.inner.0.lock().unwrap(); + + // If the value of the memory is no longer the expected value + // then terminate from the loop (we do this under a futex lock + // so that its protected) + { + let view = env.memory_view(&ctx); + let val = wasi_try_mem_ok!(futex_ptr.read(&view)); + if val != expected { + break; + } + } + + let result = futex.inner.1.wait_timeout(futex_lock, Duration::from_millis(50)).unwrap(); + if result.1.timed_out() { + yielded = env.yield_now(); + if yielded.is_err() { + break; + } + } else { + break; + } + } + + // Drop the reference count to the futex (and remove it if the refcnt hits zero) + { + let mut guard = state.futexs.lock().unwrap(); + if guard.get(&pointer) + .map(|futex| futex.refcnt.fetch_sub(1, Ordering::AcqRel) == 1) + .unwrap_or(false) + { + guard.remove(&pointer); + } + } + + // We may have a yield error (such as a terminate) + yielded?; + + Ok(__WASI_ESUCCESS) +} + +/// Wake up one thread that's blocked on futex_wait on this futex. +/// Returns true if this actually woke up such a thread, +/// or false if no thread was waiting on this futex. +/// +/// ## Parameters +/// +/// * `futex` - Memory location that holds a futex that others may be waiting on +pub fn futex_wake( + ctx: FunctionEnvMut<'_, WasiEnv>, + futex: WasmPtr, + ret_woken: WasmPtr<__wasi_bool_t, M>, +) -> __wasi_errno_t { + trace!("wasi::futex_wake(offset={})", futex.offset()); + let env = ctx.data(); + let memory = env.memory_view(&ctx); + let state = env.state.deref(); + + let pointer: u64 = wasi_try!(futex.offset().try_into().map_err(|_| __WASI_EOVERFLOW)); + let mut woken = false; + + let mut guard = state.futexs.lock().unwrap(); + if let Some(futex) = guard.get(&pointer) { + futex.inner.1.notify_one(); + woken = true; + } else { + trace!("wasi::futex_wake - nothing waiting!"); + } + + let woken = match woken { + false => __WASI_BOOL_FALSE, + true => __WASI_BOOL_TRUE, + }; + wasi_try_mem!(ret_woken.write(&memory, woken)); + + __WASI_ESUCCESS +} + +/// Wake up all threads that are waiting on futex_wait on this futex. +/// +/// ## Parameters +/// +/// * `futex` - Memory location that holds a futex that others may be waiting on +pub fn futex_wake_all( + ctx: FunctionEnvMut<'_, WasiEnv>, + futex: WasmPtr, + ret_woken: WasmPtr<__wasi_bool_t, M>, +) -> __wasi_errno_t { + trace!("wasi::futex_wake_all(offset={})", futex.offset()); + let env = ctx.data(); + let memory = env.memory_view(&ctx); + let state = env.state.deref(); + + let pointer: u64 = wasi_try!(futex.offset().try_into().map_err(|_| __WASI_EOVERFLOW)); + let mut woken = false; + + let mut guard = state.futexs.lock().unwrap(); + if let Some(futex) = guard.remove(&pointer) { + futex.inner.1.notify_all(); + woken = true; + } + + let woken = match woken { + false => __WASI_BOOL_FALSE, + true => __WASI_BOOL_TRUE, + }; + wasi_try_mem!(ret_woken.write(&memory, woken)); + + __WASI_ESUCCESS +} + /// ### `getpid()` /// Returns the handle of the current process pub fn getpid( @@ -3752,10 +4164,10 @@ pub fn process_spawn( __WASI_STDIO_MODE_PIPED => StdioMode::Piped, __WASI_STDIO_MODE_INHERIT => StdioMode::Inherit, __WASI_STDIO_MODE_LOG => StdioMode::Log, - /*__WASI_STDIO_MODE_NULL |*/ _ => StdioMode::Null, + __WASI_STDIO_MODE_NULL | _ => StdioMode::Null, }; - let process = wasi_try_bus!(bus + let mut process = wasi_try_bus!(bus .new_spawn() .chroot(chroot) .args(args) @@ -3767,7 +4179,54 @@ pub fn process_spawn( .spawn(name.as_str()) .map_err(bus_error_into_wasi_err)); - let conv_stdio_fd = |a: Option| match a { + // Create the file descriptors used to access this process + let (fd_stdin, fd_stdout, fd_stderr) = { + let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0); + + // Register the inodes for the stdio for this sub process + let fd_stdin = match process.stdin.take() { + Some(handle) => Some( + wasi_try_bus!(state.fs.create_fd(bus_write_rights(), bus_write_rights(), 0, 0, + state.fs.create_inode_with_default_stat( + inodes.deref_mut(), + Kind::File { handle: Some(handle), path: "/dev/stdin".into(), fd: None }, + false, + "stdin".into(), + ) + ).map_err(|_| __BUS_EINTERNAL)) + ), + None => None, + }; + let fd_stdout = match process.stdout.take() { + Some(handle) => Some( + wasi_try_bus!(state.fs.create_fd(bus_read_rights(), bus_read_rights(), 0, 0, + state.fs.create_inode_with_default_stat( + inodes.deref_mut(), + Kind::File { handle: Some(handle), path: "/dev/stdout".into(), fd: None }, + false, + "stdout".into(), + ) + ).map_err(|_| __BUS_EINTERNAL)) + ), + None => None + }; + let fd_stderr = match process.stderr.take() { + Some(handle) => Some( + wasi_try_bus!(state.fs.create_fd(bus_read_rights(), bus_read_rights(), 0, 0, + state.fs.create_inode_with_default_stat( + inodes.deref_mut(), + Kind::File { handle: Some(handle), path: "/dev/stderr".into(), fd: None }, + false, + "stderr".into(), + ) + ).map_err(|_| __BUS_EINTERNAL)) + ), + None => None + }; + (fd_stdin, fd_stdout, fd_stderr) + }; + + let conv_stdio_fd = |a: Option<__wasi_fd_t>| match a { Some(fd) => __wasi_option_fd_t { tag: __WASI_OPTION_SOME, fd: fd.into(), @@ -3777,18 +4236,18 @@ pub fn process_spawn( fd: 0, }, }; - + // Convert the stdio - let stdin = conv_stdio_fd(process.inst.stdin_fd()); - let stdout = conv_stdio_fd(process.inst.stdout_fd()); - let stderr = conv_stdio_fd(process.inst.stderr_fd()); + let stdin = conv_stdio_fd(fd_stdin); + let stdout = conv_stdio_fd(fd_stdout); + let stderr = conv_stdio_fd(fd_stderr); // Add the process to the environment state let bid = { - let mut guard = env.state.threading.lock().unwrap(); + let mut guard = env.state.threading.write().unwrap(); guard.process_seed += 1; let bid = guard.process_seed; - guard.processes.insert(bid.into(), process); + guard.processes.insert(bid.into(), Box::new(process)); bid }; @@ -3822,15 +4281,15 @@ pub fn bus_open_local( name_len: M::Offset, reuse: __wasi_bool_t, ret_bid: WasmPtr<__wasi_bid_t, M>, -) -> __bus_errno_t { +) -> Result<__bus_errno_t, WasiError> { let env = ctx.data(); let bus = env.runtime.bus(); let memory = env.memory_view(&ctx); - let name = unsafe { get_input_str_bus!(&memory, name, name_len) }; + let name = unsafe { get_input_str_bus_ok!(&memory, name, name_len) }; let reuse = reuse == __WASI_BOOL_TRUE; debug!("wasi::bus_open_local (name={}, reuse={})", name, reuse); - bus_open_local_internal(ctx, name, reuse, None, None, ret_bid) + bus_open_internal(ctx, name, reuse, None, None, ret_bid) } /// Spawns a new bus process for a particular web WebAssembly @@ -3857,30 +4316,30 @@ pub fn bus_open_remote( token: WasmPtr, token_len: M::Offset, ret_bid: WasmPtr<__wasi_bid_t, M>, -) -> __bus_errno_t { +) -> Result<__bus_errno_t, WasiError> { let env = ctx.data(); let bus = env.runtime.bus(); let memory = env.memory_view(&ctx); - let name = unsafe { get_input_str_bus!(&memory, name, name_len) }; - let instance = unsafe { get_input_str_bus!(&memory, instance, instance_len) }; - let token = unsafe { get_input_str_bus!(&memory, token, token_len) }; + let name = unsafe { get_input_str_bus_ok!(&memory, name, name_len) }; + let instance = unsafe { get_input_str_bus_ok!(&memory, instance, instance_len) }; + let token = unsafe { get_input_str_bus_ok!(&memory, token, token_len) }; let reuse = reuse == __WASI_BOOL_TRUE; debug!( "wasi::bus_open_remote (name={}, reuse={}, instance={})", name, reuse, instance ); - bus_open_local_internal(ctx, name, reuse, Some(instance), Some(token), ret_bid) + bus_open_internal(ctx, name, reuse, Some(instance), Some(token), ret_bid) } -fn bus_open_local_internal( +fn bus_open_internal( ctx: FunctionEnvMut<'_, WasiEnv>, name: String, reuse: bool, instance: Option, token: Option, ret_bid: WasmPtr<__wasi_bid_t, M>, -) -> __bus_errno_t { +) -> Result<__bus_errno_t, WasiError> { let env = ctx.data(); let bus = env.runtime.bus(); let memory = env.memory_view(&ctx); @@ -3888,11 +4347,11 @@ fn bus_open_local_internal( // Check if it already exists if reuse { - let guard = env.state.threading.lock().unwrap(); + let guard = env.state.threading.read().unwrap(); if let Some(bid) = guard.process_reuse.get(&name) { if guard.processes.contains_key(bid) { - wasi_try_mem_bus!(ret_bid.write(&memory, (*bid).into())); - return __BUS_ESUCCESS; + wasi_try_mem_bus_ok!(ret_bid.write(&memory, bid.clone().into())); + return Ok(__BUS_ESUCCESS); } } } @@ -3912,23 +4371,24 @@ fn bus_open_local_internal( process.access_token(token); } - let process = wasi_try_bus!(process + // Spawn the process + let mut process = wasi_try_bus_ok!(process .spawn(name.as_ref()) .map_err(bus_error_into_wasi_err)); // Add the process to the environment state let bid = { - let mut guard = env.state.threading.lock().unwrap(); + let mut guard = env.state.threading.write().unwrap(); guard.process_seed += 1; let bid: WasiBusProcessId = guard.process_seed.into(); - guard.processes.insert(bid, process); + guard.processes.insert(bid, Box::new(process)); guard.process_reuse.insert(name, bid); bid }; - wasi_try_mem_bus!(ret_bid.write(&memory, bid.into())); + wasi_try_mem_bus_ok!(ret_bid.write(&memory, bid.into())); - __BUS_ESUCCESS + Ok(__BUS_ESUCCESS) } /// Closes a bus process and releases all associated resources @@ -3941,10 +4401,13 @@ pub fn bus_close(ctx: FunctionEnvMut<'_, WasiEnv>, bid: __wasi_bid_t) -> __bus_e let bid: WasiBusProcessId = bid.into(); let env = ctx.data(); - let mut guard = env.state.threading.lock().unwrap(); - guard.processes.remove(&bid); + let mut guard = env.state.threading.write().unwrap(); + if let Some(process) = guard.processes.remove(&bid) { + let name: Cow<'static, str> = process.name.clone().into(); + guard.process_reuse.remove(&name); + } - __BUS_EUNSUPPORTED + __BUS_ESUCCESS } /// Invokes a call within a running bus process. @@ -3961,27 +4424,102 @@ pub fn bus_close(ctx: FunctionEnvMut<'_, WasiEnv>, bid: __wasi_bid_t) -> __bus_e pub fn bus_call( ctx: FunctionEnvMut<'_, WasiEnv>, bid: __wasi_bid_t, - keep_alive: __wasi_bool_t, - topic: WasmPtr, - topic_len: M::Offset, + topic_hash: WasmPtr<__wasi_hash_t>, format: __wasi_busdataformat_t, buf: WasmPtr, buf_len: M::Offset, ret_cid: WasmPtr<__wasi_cid_t, M>, -) -> __bus_errno_t { +) -> Result<__bus_errno_t, WasiError> { let env = ctx.data(); let bus = env.runtime.bus(); let memory = env.memory_view(&ctx); - let topic = unsafe { get_input_str_bus!(&memory, topic, topic_len) }; - let keep_alive = keep_alive == __WASI_BOOL_TRUE; + let topic_hash = wasi_try_mem_bus_ok!(topic_hash.read(&memory)); + let buf_slice = wasi_try_mem_bus_ok!(buf.slice(&memory, buf_len)); trace!( - "wasi::bus_call (bid={}, topic={}, buf_len={})", + "wasi::bus_call (bid={}, buf_len={})", bid, - topic, buf_len ); - __BUS_EUNSUPPORTED + // Get the process that we'll invoke this call for + let mut guard = env.state.threading.read().unwrap(); + let bid: WasiBusProcessId = bid.into(); + let process = if let Some(process) = { + guard.processes.get(&bid).map(|p| p.clone()) + } { process } else { + return Ok(__BUS_EBADHANDLE); + }; + + // Invoke the bus process + let format = wasi_try_bus_ok!(conv_bus_format_from(format)); + + // Check if the process has finished + if let Some(code) = process.inst.exit_code() { + debug!("process has already exited (code = {})", code); + return Ok(__BUS_EABORTED); + } + + // Invoke the call + let buf = wasi_try_mem_bus_ok!(buf_slice.read_to_vec()); + let mut invoked = process.inst.invoke(topic_hash, format, buf); + drop(process); + drop(guard); + + // Poll the invocation until it does its thing + let mut invocation; + { + // Fast path (does not have to create a futex creation) + let waker = WasiDummyWaker.into_waker(); + let mut cx = Context::from_waker(&waker); + let pinned_invoked = Pin::new(invoked.deref_mut()); + match pinned_invoked.poll_invoked(&mut cx) { + Poll::Ready(i) => { + invocation = wasi_try_bus_ok!(i + .map_err(bus_error_into_wasi_err)); + }, + Poll::Pending => { + // Slow path (will put the thread to sleep) + let parking = WasiParkingLot::default(); + let waker = parking.get_waker(); + let mut cx = Context::from_waker(&waker); + loop { + let pinned_invoked = Pin::new(invoked.deref_mut()); + match pinned_invoked.poll_invoked(&mut cx) { + Poll::Ready(i) => { + invocation = wasi_try_bus_ok!(i + .map_err(bus_error_into_wasi_err)); + break; + }, + Poll::Pending => { + env.yield_now()?; + parking.wait(Duration::from_millis(5)); + } + } + } + } + } + } + + // Record the invocation + let cid = { + let mut guard = env.state.bus.protected(); + guard.call_seed += 1; + let cid = guard.call_seed; + guard.calls.insert(cid, WasiBusCall { + bid, + invocation + }); + cid + }; + + // Now we wake any BUS pollers so that they can drive forward the + // call to completion - when they poll the call they will also + // register a BUS waker + env.state.bus.poll_wake(); + + // Return the CID and success to the caller + wasi_try_mem_bus_ok!(ret_cid.write(&memory, cid)); + Ok(__BUS_ESUCCESS) } /// Invokes a call within the context of another call @@ -3998,27 +4536,121 @@ pub fn bus_call( pub fn bus_subcall( ctx: FunctionEnvMut<'_, WasiEnv>, parent: __wasi_cid_t, - keep_alive: __wasi_bool_t, - topic: WasmPtr, - topic_len: M::Offset, + topic_hash: WasmPtr<__wasi_hash_t>, format: __wasi_busdataformat_t, buf: WasmPtr, buf_len: M::Offset, ret_cid: WasmPtr<__wasi_cid_t, M>, -) -> __bus_errno_t { +) -> Result<__bus_errno_t, WasiError> { let env = ctx.data(); let bus = env.runtime.bus(); let memory = env.memory_view(&ctx); - let topic = unsafe { get_input_str_bus!(&memory, topic, topic_len) }; - let keep_alive = keep_alive == __WASI_BOOL_TRUE; + let topic_hash = wasi_try_mem_bus_ok!(topic_hash.read(&memory)); + let buf_slice = wasi_try_mem_bus_ok!(buf.slice(&memory, buf_len)); trace!( - "wasi::bus_subcall (parent={}, topic={}, buf_len={})", + "wasi::bus_subcall (parent={}, buf_len={})", parent, - topic, buf_len ); - __BUS_EUNSUPPORTED + let format = wasi_try_bus_ok!(conv_bus_format_from(format)); + let buf = wasi_try_mem_bus_ok!(buf_slice.read_to_vec()); + + // Get the parent call that we'll invoke this call for + let mut guard = env.state.bus.protected(); + if let Some(parent) = guard.calls.get(&parent) + { + let bid = parent.bid.clone(); + + // Invoke the sub-call in the existing parent call + let mut invoked = parent.invocation.invoke(topic_hash, format, buf); + drop(parent); + drop(guard); + + // Poll the invocation until it does its thing + let invocation; + { + // Fast path (does not have to create a futex creation) + let waker = WasiDummyWaker.into_waker(); + let mut cx = Context::from_waker(&waker); + let pinned_invoked = Pin::new(invoked.deref_mut()); + match pinned_invoked.poll_invoked(&mut cx) { + Poll::Ready(i) => { + invocation = wasi_try_bus_ok!(i + .map_err(bus_error_into_wasi_err)); + }, + Poll::Pending => { + // Slow path (will put the thread to sleep) + let parking = WasiParkingLot::default(); + let waker = parking.get_waker(); + let mut cx = Context::from_waker(&waker); + loop { + let pinned_invoked = Pin::new(invoked.deref_mut()); + match pinned_invoked.poll_invoked(&mut cx) { + Poll::Ready(i) => { + invocation = wasi_try_bus_ok!(i + .map_err(bus_error_into_wasi_err)); + break; + }, + Poll::Pending => { + env.yield_now()?; + parking.wait(Duration::from_millis(5)); + } + } + } + } + } + } + + // Add the call and return the ID + let cid = { + let mut guard = env.state.bus.protected(); + guard.call_seed += 1; + let cid = guard.call_seed; + guard.calls.insert(cid, WasiBusCall { + bid, + invocation + }); + cid + }; + + // Now we wake any BUS pollers so that they can drive forward the + // call to completion - when they poll the call they will also + // register a BUS waker + env.state.bus.poll_wake(); + + // Return the CID and success to the caller + wasi_try_mem_bus_ok!(ret_cid.write(&memory, cid)); + Ok(__BUS_ESUCCESS) + } else { + Ok(__BUS_EBADHANDLE) + } +} + +// Function for converting the format +fn conv_bus_format(format: BusDataFormat) -> __wasi_busdataformat_t { + match format { + BusDataFormat::Raw => __WASI_BUS_DATA_FORMAT_RAW, + BusDataFormat::Bincode => __WASI_BUS_DATA_FORMAT_BINCODE, + BusDataFormat::MessagePack => __WASI_BUS_DATA_FORMAT_MESSAGE_PACK, + BusDataFormat::Json => __WASI_BUS_DATA_FORMAT_JSON, + BusDataFormat::Yaml => __WASI_BUS_DATA_FORMAT_YAML, + BusDataFormat::Xml => __WASI_BUS_DATA_FORMAT_XML, + } +} + +fn conv_bus_format_from(format: __wasi_busdataformat_t) -> Result { + Ok( + match format { + __WASI_BUS_DATA_FORMAT_RAW => BusDataFormat::Raw, + __WASI_BUS_DATA_FORMAT_BINCODE => BusDataFormat::Bincode, + __WASI_BUS_DATA_FORMAT_MESSAGE_PACK => BusDataFormat::MessagePack, + __WASI_BUS_DATA_FORMAT_JSON => BusDataFormat::Json, + __WASI_BUS_DATA_FORMAT_YAML => BusDataFormat::Yaml, + __WASI_BUS_DATA_FORMAT_XML => BusDataFormat::Xml, + _ => { return Err(__BUS_EDES); } + } + ) } /// Polls for any outstanding events from a particular @@ -4038,19 +4670,346 @@ pub fn bus_subcall( pub fn bus_poll( ctx: FunctionEnvMut<'_, WasiEnv>, timeout: __wasi_timestamp_t, - events: WasmPtr, - nevents: M::Offset, - malloc: WasmPtr, - malloc_len: M::Offset, + events: WasmPtr<__wasi_busevent_t, M>, + maxevents: M::Offset, ret_nevents: WasmPtr, -) -> __bus_errno_t { +) -> Result<__bus_errno_t, WasiError> { let env = ctx.data(); let bus = env.runtime.bus(); let memory = env.memory_view(&ctx); - let malloc = unsafe { get_input_str_bus!(&memory, malloc, malloc_len) }; - trace!("wasi::bus_poll (timeout={}, malloc={})", timeout, malloc); + //trace!("wasi::bus_poll (timeout={})", timeout); + + // Lets start by processing events for calls that are already running + let mut nevents = M::ZERO; + let events = wasi_try_mem_bus_ok!(events.slice(&memory, maxevents)); + + let state = env.state.clone(); + let start = platform_clock_time_get(__WASI_CLOCK_MONOTONIC, 1_000_000).unwrap() as u128; + loop + { + // The waker will wake this thread should any work arrive + // or need further processing (i.e. async operation) + let waker = state.bus.get_poll_waker(); + let mut cx = Context::from_waker(&waker); + + // Check if any of the processes have closed + let mut exited_bids = HashSet::new(); + { + let mut guard = env.state.threading.write().unwrap(); + for (pid, process) in guard.processes.iter_mut() { + let pinned_process = Pin::new(process.inst.as_mut()); + if pinned_process.poll_finished(&mut cx) == Poll::Ready(()) { + exited_bids.insert(*pid); + } + } + for pid in exited_bids.iter() { + guard.processes.remove(pid); + } + } + + { + // The waker will trigger the reactors when work arrives from the BUS + let mut guard = env.state.bus.protected(); + + // Function that hashes the topic using SHA256 + let hash_topic = |topic: Cow<'static, str>| -> __wasi_hash_t { + use sha2::{Sha256, Digest}; + let mut hasher = Sha256::new(); + hasher.update(&topic.bytes().collect::>()); + let hash: [u8; 16] = hasher.finalize()[..16].try_into().unwrap(); + u128::from_le_bytes(hash) + }; + + // Function that turns a buffer into a readable file handle + let buf_to_fd = { + let state = env.state.clone(); + let inodes = state.inodes.clone(); + move |data: Vec| -> __wasi_fd_t { + let mut inodes = inodes.write().unwrap(); + let inode = state.fs.create_inode_with_default_stat( + inodes.deref_mut(), + Kind::Buffer { buffer: data }, + false, + "bus".into(), + ); + let rights = super::state::bus_read_rights(); + wasi_try_bus!(state.fs.create_fd(rights, rights, 0, 0, inode) + .map_err(|err| { + debug!("failed to create file descriptor for BUS event buffer - {}", err); + __BUS_EALLOC + })) + } + }; + + // Grab all the events we can from all the existing calls up to the limit of + // maximum events that the user requested + if nevents < maxevents { + let mut drop_calls = Vec::new(); + let mut call_seed = guard.call_seed; + for (key, call) in guard.calls.iter_mut() { + let cid: __wasi_cid_t = (*key).into(); + + if nevents >= maxevents { + break; + } + + // If the process that is hosting the call is finished then so is the call + if exited_bids.contains(&call.bid) { + drop_calls.push(*key); + trace!("wasi::bus_poll (aborted, cid={})", cid); + let evt = unsafe { + std::mem::transmute(__wasi_busevent_t2 { + tag: __WASI_BUS_EVENT_TYPE_FAULT, + u: __wasi_busevent_u { + fault: __wasi_busevent_fault_t { + cid, + err: __BUS_EABORTED + } + } + }) + }; + + let nevents64: u64 = wasi_try_bus_ok!(nevents.try_into().map_err(|_| __BUS_EINTERNAL)); + wasi_try_mem_bus_ok!(events.write(nevents64, evt)); + + nevents += M::ONE; + continue; + } + + // Otherwise lets poll for events + while nevents < maxevents { + let mut finished = false; + let call = Pin::new(call.invocation.as_mut()); + match call.poll_event(&mut cx) { + Poll::Ready(evt) => + { + let evt = match evt { + BusInvocationEvent::Callback { topic_hash, format, data } => { + let sub_cid = { + call_seed += 1; + call_seed + }; + + trace!("wasi::bus_poll (callback, parent={}, cid={}, topic={})", cid, sub_cid, topic_hash); + __wasi_busevent_t2 { + tag: __WASI_BUS_EVENT_TYPE_CALL, + u: __wasi_busevent_u { + call: __wasi_busevent_call_t { + parent: __wasi_option_cid_t { + tag: __WASI_OPTION_SOME, + cid, + }, + cid: sub_cid, + format: conv_bus_format(format), + topic_hash, + fd: buf_to_fd(data), + } + } + } + }, + BusInvocationEvent::Response { format, data } => { + drop_calls.push(*key); + finished = true; + + trace!("wasi::bus_poll (response, cid={}, len={})", cid, data.len()); + __wasi_busevent_t2 { + tag: __WASI_BUS_EVENT_TYPE_RESULT, + u: __wasi_busevent_u { + result: __wasi_busevent_result_t { + format: conv_bus_format(format), + cid, + fd: buf_to_fd(data), + } + } + } + }, + BusInvocationEvent::Fault { fault } => { + drop_calls.push(*key); + finished = true; + + trace!("wasi::bus_poll (fault, cid={}, err={})", cid, fault); + __wasi_busevent_t2 { + tag: __WASI_BUS_EVENT_TYPE_FAULT, + u: __wasi_busevent_u { + fault: __wasi_busevent_fault_t { + cid, + err: bus_error_into_wasi_err(fault) + } + } + } + } + }; + let evt = unsafe { + std::mem::transmute(evt) + }; + + let nevents64: u64 = wasi_try_bus_ok!(nevents.try_into().map_err(|_| __BUS_EINTERNAL)); + wasi_try_mem_bus_ok!(events.write(nevents64, evt)); + + nevents += M::ONE; + + if finished { + break; + } + }, + Poll::Pending => { break; } + } + } + } + guard.call_seed = call_seed; + + // Drop any calls that are no longer in scope + if drop_calls.is_empty() == false { + for key in drop_calls { + guard.calls.remove(&key); + } + } + } + + if nevents < maxevents { + let mut call_seed = guard.call_seed; + let mut to_add = Vec::new(); + for (key, call) in guard.called.iter_mut() { + let cid: __wasi_cid_t = (*key).into(); + while nevents < maxevents { + let call = Pin::new(call.deref_mut()); + match call.poll(&mut cx) { + Poll::Ready(event) => { + // Register the call + let sub_cid = { + call_seed += 1; + to_add.push((call_seed, event.called)); + call_seed + }; + + let event = __wasi_busevent_t2 { + tag: __WASI_BUS_EVENT_TYPE_CALL, + u: __wasi_busevent_u { + call: __wasi_busevent_call_t { + parent: __wasi_option_cid_t { + tag: __WASI_OPTION_SOME, + cid, + }, + cid: sub_cid, + format: conv_bus_format(event.format), + topic_hash: event.topic_hash, + fd: buf_to_fd(event.data), + } + } + }; + let event = unsafe { + std::mem::transmute(event) + }; + + let nevents64: u64 = wasi_try_bus_ok!(nevents.try_into().map_err(|_| __BUS_EINTERNAL)); + wasi_try_mem_bus_ok!(events.write(nevents64, event)); + nevents += M::ONE; + }, + Poll::Pending => { break; } + }; + } + if nevents >= maxevents { + break; + } + } + + guard.call_seed = call_seed; + for (cid, called) in to_add { + guard.called.insert(cid, called); + } + } - __BUS_EUNSUPPORTED + while nevents < maxevents + { + // Check the listener (if none exists then one is created) + let event = { + let listener = wasi_try_bus_ok!(env.runtime + .bus() + .listen() + .map_err(bus_error_into_wasi_err)); + let listener = Pin::new(listener.deref()); + listener.poll(&mut cx) + }; + + // Process the event returned by the listener or exit the poll loop + let event = match event { + Poll::Ready(event) => { + + // Register the call + let sub_cid = { + guard.call_seed += 1; + let cid = guard.call_seed; + guard.called.insert(cid, event.called); + cid + }; + + __wasi_busevent_t2 { + tag: __WASI_BUS_EVENT_TYPE_CALL, + u: __wasi_busevent_u { + call: __wasi_busevent_call_t { + parent: __wasi_option_cid_t { + tag: __WASI_OPTION_NONE, + cid: 0, + }, + cid: sub_cid, + format: conv_bus_format(event.format), + topic_hash: event.topic_hash, + fd: buf_to_fd(event.data), + } + } + } + }, + Poll::Pending => { break; } + }; + let event = unsafe { + std::mem::transmute(event) + }; + + let nevents64: u64 = wasi_try_bus_ok!(nevents.try_into().map_err(|_| __BUS_EINTERNAL)); + wasi_try_mem_bus_ok!(events.write(nevents64, event)); + nevents += M::ONE; + } + } + + // If we still have no events + if nevents >= M::ONE { + break; + } + + // Determine the interval we will wake to check things like timeouts + // or the thread terminating + let now = platform_clock_time_get(__WASI_CLOCK_MONOTONIC, 1_000_000).unwrap() as u128; + let delta = match now.checked_sub(start) { + Some(a) => Duration::from_nanos(a as u64), + None => Duration::ZERO, + }; + let interval = Duration::from_millis(5).min(delta); + + // Every 50 milliseconds we check if the thread needs to terminate (20 times a second) + // or for timeout, otherwise the reactor has to be woken + loop { + // Check for timeout (zero will mean the loop will not wait) + let now = platform_clock_time_get(__WASI_CLOCK_MONOTONIC, 1_000_000).unwrap() as u128; + let delta = (now - start) as __wasi_timestamp_t; + if delta >= timeout { + trace!("wasi::bus_poll (timeout)"); + wasi_try_mem_bus_ok!(ret_nevents.write(&memory, nevents)); + return Ok(__BUS_ESUCCESS); + } + + env.yield_now()?; + state.bus.poll_wait(interval); + break; + } + } + if nevents > M::ZERO { + trace!("wasi::bus_poll (return nevents={})", nevents); + } else { + trace!("wasi::bus_poll (idle - no events)"); + } + + wasi_try_mem_bus_ok!(ret_nevents.write(&memory, nevents)); + Ok(__BUS_ESUCCESS) } /// Replies to a call that was made to this process @@ -4071,6 +5030,7 @@ pub fn call_reply( buf_len: M::Offset, ) -> __bus_errno_t { let env = ctx.data(); + let memory = env.memory_view(&ctx); let bus = env.runtime.bus(); trace!( "wasi::call_reply (cid={}, format={}, data_len={})", @@ -4078,8 +5038,19 @@ pub fn call_reply( format, buf_len ); + let buf_slice = wasi_try_mem_bus!(buf.slice(&memory, buf_len)); + let buf = wasi_try_mem_bus!(buf_slice.read_to_vec()); + + let mut guard = env.state.bus.protected(); + if let Some(call) = guard.called.remove(&cid) { + drop(guard); - __BUS_EUNSUPPORTED + let format = wasi_try_bus!(conv_bus_format_from(format)); + call.reply(format, buf); + __BUS_ESUCCESS + } else { + __BUS_EBADHANDLE + } } /// Causes a fault on a particular call that was made @@ -4093,13 +5064,19 @@ pub fn call_reply( pub fn call_fault( ctx: FunctionEnvMut<'_, WasiEnv>, cid: __wasi_cid_t, - fault: __bus_errno_t, -) -> __bus_errno_t { + fault: __bus_errno_t) +{ let env = ctx.data(); let bus = env.runtime.bus(); debug!("wasi::call_fault (cid={}, fault={})", cid, fault); - __BUS_EUNSUPPORTED + let mut guard = env.state.bus.protected(); + guard.calls.remove(&cid); + + if let Some(call) = guard.called.remove(&cid) { + drop(guard); + call.fault(wasi_error_into_bus_err(fault)); + } } /// Closes a bus call based on its bus call handle @@ -4107,12 +5084,17 @@ pub fn call_fault( /// ## Parameters /// /// * `cid` - Handle of the bus call handle to be dropped -pub fn call_close(ctx: FunctionEnvMut<'_, WasiEnv>, cid: __wasi_cid_t) -> __bus_errno_t { +pub fn call_close( + ctx: FunctionEnvMut<'_, WasiEnv>, + cid: __wasi_cid_t +) { let env = ctx.data(); let bus = env.runtime.bus(); trace!("wasi::call_close (cid={})", cid); - __BUS_EUNSUPPORTED + let mut guard = env.state.bus.protected(); + guard.calls.remove(&cid); + guard.called.remove(&cid); } /// ### `ws_connect()` @@ -4151,7 +5133,7 @@ pub fn ws_connect( inodes.deref_mut(), kind, false, - "socket".to_string(), + "socket".into(), ); let rights = super::state::all_socket_rights(); let fd = wasi_try!(state.fs.create_fd(rights, rights, 0, 0, inode)); @@ -4249,19 +5231,19 @@ pub fn http_request( inodes.deref_mut(), kind_req, false, - "http_request".to_string(), + "http_request".into(), ); let inode_res = state.fs.create_inode_with_default_stat( inodes.deref_mut(), kind_res, false, - "http_response".to_string(), + "http_response".into(), ); let inode_hdr = state.fs.create_inode_with_default_stat( inodes.deref_mut(), kind_hdr, false, - "http_headers".to_string(), + "http_headers".into(), ); let rights = super::state::all_socket_rights(); @@ -4571,7 +5553,8 @@ pub fn port_route_list( let max_routes: usize = wasi_try!(wasi_try_mem!(nroutes.read()) .try_into() .map_err(|_| __WASI_EINVAL)); - let ref_routes = wasi_try_mem!(routes.slice(&memory, wasi_try!(to_offset::(max_routes)))); + let ref_routes = + wasi_try_mem!(routes.slice(&memory, wasi_try!(to_offset::(max_routes)))); let routes = wasi_try!(env.net().route_list().map_err(net_error_into_wasi_err)); @@ -4768,7 +5751,7 @@ pub fn sock_open( inodes.deref_mut(), kind, false, - "socket".to_string(), + "socket".into(), ); let rights = super::state::all_socket_rights(); let fd = wasi_try!(state.fs.create_fd(rights, rights, 0, 0, inode)); @@ -5221,7 +6204,7 @@ pub fn sock_accept( inodes.deref_mut(), kind, false, - "socket".to_string(), + "socket".into(), ); let rights = super::state::all_socket_rights(); @@ -5251,12 +6234,10 @@ pub fn sock_accept( /// * `fd` - Socket descriptor /// * `addr` - Address of the socket to connect to pub fn sock_connect( - ctx: FunctionEnvMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, addr: WasmPtr<__wasi_addr_port_t, M>, ) -> __wasi_errno_t { - debug!("wasi::sock_connect"); - let env = ctx.data(); let memory = env.memory_view(&ctx); let addr = wasi_try!(super::state::read_ip_port(&memory, addr)); @@ -5302,7 +6283,7 @@ pub fn sock_recv( &ctx, sock, __WASI_RIGHT_SOCK_RECV, - |socket| { socket.recv(&memory, iovs_arr) } + |socket| { socket.recv(& memory, iovs_arr) } )); let bytes_read: M::Offset = wasi_try_ok!(bytes_read.try_into().map_err(|_| __WASI_EOVERFLOW)); @@ -5451,8 +6432,8 @@ pub fn sock_send_to( /// ## Return /// /// Number of bytes transmitted. -pub unsafe fn sock_send_file( - mut ctx: FunctionEnvMut<'_, WasiEnv>, +pub fn sock_send_file( + ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, in_fd: __wasi_fd_t, offset: __wasi_filesize_t, @@ -5505,8 +6486,7 @@ pub unsafe fn sock_send_file( let bytes_read = { let mut guard = inode.write(); - let deref_mut = guard.deref_mut(); - match deref_mut { + match guard.deref_mut() { Kind::File { handle, .. } => { if let Some(handle) = handle { wasi_try_ok!( diff --git a/lib/wasi/src/syscalls/wasi.rs b/lib/wasi/src/syscalls/wasi.rs deleted file mode 100644 index b2575f6e53c..00000000000 --- a/lib/wasi/src/syscalls/wasi.rs +++ /dev/null @@ -1,450 +0,0 @@ -#![deny(dead_code)] -use crate::{WasiEnv, WasiError, WasiState, WasiThread}; -use wasmer::{StoreMut, Memory, Memory32, MemorySize, WasmPtr, WasmSlice}; -use wasmer_wasi_types::*; - -type MemoryType = Memory32; -type MemoryOffset = u32; - -pub(crate) fn args_get( - ctx: FunctionEnvMut, - argv: WasmPtr, MemoryType>, - argv_buf: WasmPtr, -) -> __wasi_errno_t { - super::args_get::(ctx, argv, argv_buf) -} - -pub(crate) fn args_sizes_get( - ctx: FunctionEnvMut, - argc: WasmPtr, - argv_buf_size: WasmPtr, -) -> __wasi_errno_t { - super::args_sizes_get::(ctx, argc, argv_buf_size) -} - -pub(crate) fn clock_res_get( - ctx: FunctionEnvMut, - clock_id: __wasi_clockid_t, - resolution: WasmPtr<__wasi_timestamp_t, MemoryType>, -) -> __wasi_errno_t { - super::clock_res_get::(ctx, clock_id, resolution) -} - -pub(crate) fn clock_time_get( - ctx: FunctionEnvMut, - clock_id: __wasi_clockid_t, - precision: __wasi_timestamp_t, - time: WasmPtr<__wasi_timestamp_t, MemoryType>, -) -> __wasi_errno_t { - super::clock_time_get::(ctx, clock_id, precision, time) -} - -pub(crate) fn environ_get( - ctx: FunctionEnvMut, - environ: WasmPtr, MemoryType>, - environ_buf: WasmPtr, -) -> __wasi_errno_t { - super::environ_get::(ctx, environ, environ_buf) -} - -pub(crate) fn environ_sizes_get( - ctx: FunctionEnvMut, - environ_count: WasmPtr, - environ_buf_size: WasmPtr, -) -> __wasi_errno_t { - super::environ_sizes_get::(ctx, environ_count, environ_buf_size) -} - -pub(crate) fn fd_advise( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - offset: __wasi_filesize_t, - len: __wasi_filesize_t, - advice: __wasi_advice_t, -) -> __wasi_errno_t { - super::fd_advise(ctx, fd, offset, len, advice) -} - -pub(crate) fn fd_allocate( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - offset: __wasi_filesize_t, - len: __wasi_filesize_t, -) -> __wasi_errno_t { - super::fd_allocate(ctx, fd, offset, len) -} - -pub(crate) fn fd_close(ctx: FunctionEnvMut, fd: __wasi_fd_t) -> __wasi_errno_t { - super::fd_close(ctx, fd) -} - -pub(crate) fn fd_datasync(ctx: FunctionEnvMut, fd: __wasi_fd_t) -> __wasi_errno_t { - super::fd_datasync(ctx, fd) -} - -pub(crate) fn fd_fdstat_get( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - buf_ptr: WasmPtr<__wasi_fdstat_t, MemoryType>, -) -> __wasi_errno_t { - super::fd_fdstat_get::(ctx, fd, buf_ptr) -} - -pub(crate) fn fd_fdstat_set_flags( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - flags: __wasi_fdflags_t, -) -> __wasi_errno_t { - super::fd_fdstat_set_flags(ctx, fd, flags) -} - -pub(crate) fn fd_fdstat_set_rights( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - fs_rights_base: __wasi_rights_t, - fs_rights_inheriting: __wasi_rights_t, -) -> __wasi_errno_t { - super::fd_fdstat_set_rights(ctx, fd, fs_rights_base, fs_rights_inheriting) -} - -pub(crate) fn fd_filestat_get( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - buf: WasmPtr<__wasi_filestat_t, MemoryType>, -) -> __wasi_errno_t { - super::fd_filestat_get::(ctx, fd, buf) -} - -pub(crate) fn fd_filestat_set_size( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - st_size: __wasi_filesize_t, -) -> __wasi_errno_t { - super::fd_filestat_set_size(ctx, fd, st_size) -} - -pub(crate) fn fd_filestat_set_times( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - st_atim: __wasi_timestamp_t, - st_mtim: __wasi_timestamp_t, - fst_flags: __wasi_fstflags_t, -) -> __wasi_errno_t { - super::fd_filestat_set_times(ctx, fd, st_atim, st_mtim, fst_flags) -} - -pub(crate) fn fd_pread( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - iovs: WasmPtr<__wasi_iovec_t, MemoryType>, - iovs_len: MemoryOffset, - offset: __wasi_filesize_t, - nread: WasmPtr, -) -> Result<__wasi_errno_t, WasiError> { - super::fd_pread::(ctx, fd, iovs, iovs_len, offset, nread) -} - -pub(crate) fn fd_prestat_get( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - buf: WasmPtr<__wasi_prestat_t, MemoryType>, -) -> __wasi_errno_t { - super::fd_prestat_get::(ctx, fd, buf) -} - -pub(crate) fn fd_prestat_dir_name( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - path: WasmPtr, - path_len: MemoryOffset, -) -> __wasi_errno_t { - super::fd_prestat_dir_name::(ctx, fd, path, path_len) -} - -pub(crate) fn fd_pwrite( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - iovs: WasmPtr<__wasi_ciovec_t, MemoryType>, - iovs_len: MemoryOffset, - offset: __wasi_filesize_t, - nwritten: WasmPtr, -) -> Result<__wasi_errno_t, WasiError> { - super::fd_pwrite::(ctx, fd, iovs, iovs_len, offset, nwritten) -} - -pub(crate) fn fd_read( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - iovs: WasmPtr<__wasi_iovec_t, MemoryType>, - iovs_len: MemoryOffset, - nread: WasmPtr, -) -> Result<__wasi_errno_t, WasiError> { - super::fd_read::(ctx, fd, iovs, iovs_len, nread) -} - -pub(crate) fn fd_readdir( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - buf: WasmPtr, - buf_len: MemoryOffset, - cookie: __wasi_dircookie_t, - bufused: WasmPtr, -) -> __wasi_errno_t { - super::fd_readdir::(ctx, fd, buf, buf_len, cookie, bufused) -} - -pub(crate) fn fd_renumber( - ctx: FunctionEnvMut, - from: __wasi_fd_t, - to: __wasi_fd_t, -) -> __wasi_errno_t { - super::fd_renumber(ctx, from, to) -} - -pub(crate) fn fd_seek( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - offset: __wasi_filedelta_t, - whence: __wasi_whence_t, - newoffset: WasmPtr<__wasi_filesize_t, MemoryType>, -) -> Result<__wasi_errno_t, WasiError> { - super::fd_seek::(ctx, fd, offset, whence, newoffset) -} - -pub(crate) fn fd_sync(ctx: FunctionEnvMut, fd: __wasi_fd_t) -> __wasi_errno_t { - super::fd_sync(ctx, fd) -} - -pub(crate) fn fd_tell( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - offset: WasmPtr<__wasi_filesize_t, MemoryType>, -) -> __wasi_errno_t { - super::fd_tell::(ctx, fd, offset) -} - -pub(crate) fn fd_write( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - iovs: WasmPtr<__wasi_ciovec_t, MemoryType>, - iovs_len: MemoryOffset, - nwritten: WasmPtr, -) -> Result<__wasi_errno_t, WasiError> { - super::fd_write::(ctx, fd, iovs, iovs_len, nwritten) -} - -pub(crate) fn path_create_directory( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - path: WasmPtr, - path_len: MemoryOffset, -) -> __wasi_errno_t { - super::path_create_directory::(ctx, fd, path, path_len) -} - -pub(crate) fn path_filestat_get( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - flags: __wasi_lookupflags_t, - path: WasmPtr, - path_len: MemoryOffset, - buf: WasmPtr<__wasi_filestat_t, MemoryType>, -) -> __wasi_errno_t { - super::path_filestat_get::(ctx, fd, flags, path, path_len, buf) -} - -pub(crate) fn path_filestat_set_times( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - flags: __wasi_lookupflags_t, - path: WasmPtr, - path_len: MemoryOffset, - st_atim: __wasi_timestamp_t, - st_mtim: __wasi_timestamp_t, - fst_flags: __wasi_fstflags_t, -) -> __wasi_errno_t { - super::path_filestat_set_times::( - ctx, fd, flags, path, path_len, st_atim, st_mtim, fst_flags, - ) -} - -pub(crate) fn path_link( - ctx: FunctionEnvMut, - old_fd: __wasi_fd_t, - old_flags: __wasi_lookupflags_t, - old_path: WasmPtr, - old_path_len: MemoryOffset, - new_fd: __wasi_fd_t, - new_path: WasmPtr, - new_path_len: MemoryOffset, -) -> __wasi_errno_t { - super::path_link::( - ctx, - old_fd, - old_flags, - old_path, - old_path_len, - new_fd, - new_path, - new_path_len, - ) -} - -pub(crate) fn path_open( - ctx: FunctionEnvMut, - dirfd: __wasi_fd_t, - dirflags: __wasi_lookupflags_t, - path: WasmPtr, - path_len: MemoryOffset, - o_flags: __wasi_oflags_t, - fs_rights_base: __wasi_rights_t, - fs_rights_inheriting: __wasi_rights_t, - fs_flags: __wasi_fdflags_t, - fd: WasmPtr<__wasi_fd_t, MemoryType>, -) -> __wasi_errno_t { - super::path_open::( - ctx, - dirfd, - dirflags, - path, - path_len, - o_flags, - fs_rights_base, - fs_rights_inheriting, - fs_flags, - fd, - ) -} - -pub(crate) fn path_readlink( - ctx: FunctionEnvMut, - dir_fd: __wasi_fd_t, - path: WasmPtr, - path_len: MemoryOffset, - buf: WasmPtr, - buf_len: MemoryOffset, - buf_used: WasmPtr, -) -> __wasi_errno_t { - super::path_readlink::(ctx, dir_fd, path, path_len, buf, buf_len, buf_used) -} - -pub(crate) fn path_remove_directory( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - path: WasmPtr, - path_len: MemoryOffset, -) -> __wasi_errno_t { - super::path_remove_directory::(ctx, fd, path, path_len) -} - -pub(crate) fn path_rename( - ctx: FunctionEnvMut, - old_fd: __wasi_fd_t, - old_path: WasmPtr, - old_path_len: MemoryOffset, - new_fd: __wasi_fd_t, - new_path: WasmPtr, - new_path_len: MemoryOffset, -) -> __wasi_errno_t { - super::path_rename::( - ctx, - old_fd, - old_path, - old_path_len, - new_fd, - new_path, - new_path_len, - ) -} - -pub(crate) fn path_symlink( - ctx: FunctionEnvMut, - old_path: WasmPtr, - old_path_len: MemoryOffset, - fd: __wasi_fd_t, - new_path: WasmPtr, - new_path_len: MemoryOffset, -) -> __wasi_errno_t { - super::path_symlink::(ctx, old_path, old_path_len, fd, new_path, new_path_len) -} - -pub(crate) fn path_unlink_file( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - path: WasmPtr, - path_len: MemoryOffset, -) -> __wasi_errno_t { - super::path_unlink_file::(ctx, fd, path, path_len) -} - -pub(crate) fn poll_oneoff( - ctx: FunctionEnvMut, - in_: WasmPtr<__wasi_subscription_t, MemoryType>, - out_: WasmPtr<__wasi_event_t, MemoryType>, - nsubscriptions: MemoryOffset, - nevents: WasmPtr, -) -> Result<__wasi_errno_t, WasiError> { - super::poll_oneoff::(ctx, in_, out_, nsubscriptions, nevents) -} - -pub(crate) fn proc_exit( - ctx: FunctionEnvMut, - code: __wasi_exitcode_t, -) -> Result<(), WasiError> { - super::proc_exit(ctx, code) -} - -pub(crate) fn proc_raise(ctx: FunctionEnvMut, sig: __wasi_signal_t) -> __wasi_errno_t { - super::proc_raise(ctx, sig) -} - -pub(crate) fn random_get( - ctx: FunctionEnvMut, - buf: WasmPtr, - buf_len: MemoryOffset, -) -> __wasi_errno_t { - super::random_get::(ctx, buf, buf_len) -} - -pub(crate) fn sched_yield(ctx: FunctionEnvMut) -> Result<__wasi_errno_t, WasiError> { - super::sched_yield(ctx) -} - -pub(crate) fn sock_recv( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - ri_data: WasmPtr<__wasi_iovec_t, MemoryType>, - ri_data_len: MemoryOffset, - ri_flags: __wasi_riflags_t, - ro_data_len: WasmPtr, - ro_flags: WasmPtr<__wasi_roflags_t, MemoryType>, -) -> Result<__wasi_errno_t, WasiError> { - super::sock_recv::( - ctx, - sock, - ri_data, - ri_data_len, - ri_flags, - ro_data_len, - ro_flags, - ) -} - -pub(crate) fn sock_send( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - si_data: WasmPtr<__wasi_ciovec_t, MemoryType>, - si_data_len: MemoryOffset, - si_flags: __wasi_siflags_t, - ret_data_len: WasmPtr, -) -> Result<__wasi_errno_t, WasiError> { - super::sock_send::(ctx, sock, si_data, si_data_len, si_flags, ret_data_len) -} - -pub(crate) fn sock_shutdown( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - how: __wasi_sdflags_t, -) -> __wasi_errno_t { - super::sock_shutdown(ctx, sock, how) -} diff --git a/lib/wasi/src/syscalls/wasix32.rs b/lib/wasi/src/syscalls/wasix32.rs deleted file mode 100644 index 5cb6899c3ef..00000000000 --- a/lib/wasi/src/syscalls/wasix32.rs +++ /dev/null @@ -1,1060 +0,0 @@ -#![deny(dead_code)] -use crate::{WasiEnv, WasiError, WasiState, WasiThread}; -use wasmer::{FunctionEnvMut, Memory, Memory32, MemorySize, StoreMut, WasmPtr, WasmSlice}; -use wasmer_wasi_types::*; - -type MemoryType = Memory32; -type MemoryOffset = u32; - -pub(crate) fn args_get( - ctx: FunctionEnvMut, - argv: WasmPtr, MemoryType>, - argv_buf: WasmPtr, -) -> __wasi_errno_t { - super::args_get::(ctx, argv, argv_buf) -} - -pub(crate) fn args_sizes_get( - ctx: FunctionEnvMut, - argc: WasmPtr, - argv_buf_size: WasmPtr, -) -> __wasi_errno_t { - super::args_sizes_get::(ctx, argc, argv_buf_size) -} - -pub(crate) fn clock_res_get( - ctx: FunctionEnvMut, - clock_id: __wasi_clockid_t, - resolution: WasmPtr<__wasi_timestamp_t, MemoryType>, -) -> __wasi_errno_t { - super::clock_res_get::(ctx, clock_id, resolution) -} - -pub(crate) fn clock_time_get( - ctx: FunctionEnvMut, - clock_id: __wasi_clockid_t, - precision: __wasi_timestamp_t, - time: WasmPtr<__wasi_timestamp_t, MemoryType>, -) -> __wasi_errno_t { - super::clock_time_get::(ctx, clock_id, precision, time) -} - -pub(crate) fn environ_get( - ctx: FunctionEnvMut, - environ: WasmPtr, MemoryType>, - environ_buf: WasmPtr, -) -> __wasi_errno_t { - super::environ_get::(ctx, environ, environ_buf) -} - -pub(crate) fn environ_sizes_get( - ctx: FunctionEnvMut, - environ_count: WasmPtr, - environ_buf_size: WasmPtr, -) -> __wasi_errno_t { - super::environ_sizes_get::(ctx, environ_count, environ_buf_size) -} - -pub(crate) fn fd_advise( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - offset: __wasi_filesize_t, - len: __wasi_filesize_t, - advice: __wasi_advice_t, -) -> __wasi_errno_t { - super::fd_advise(ctx, fd, offset, len, advice) -} - -pub(crate) fn fd_allocate( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - offset: __wasi_filesize_t, - len: __wasi_filesize_t, -) -> __wasi_errno_t { - super::fd_allocate(ctx, fd, offset, len) -} - -pub(crate) fn fd_close(ctx: FunctionEnvMut, fd: __wasi_fd_t) -> __wasi_errno_t { - super::fd_close(ctx, fd) -} - -pub(crate) fn fd_datasync(ctx: FunctionEnvMut, fd: __wasi_fd_t) -> __wasi_errno_t { - super::fd_datasync(ctx, fd) -} - -pub(crate) fn fd_fdstat_get( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - buf_ptr: WasmPtr<__wasi_fdstat_t, MemoryType>, -) -> __wasi_errno_t { - super::fd_fdstat_get::(ctx, fd, buf_ptr) -} - -pub(crate) fn fd_fdstat_set_flags( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - flags: __wasi_fdflags_t, -) -> __wasi_errno_t { - super::fd_fdstat_set_flags(ctx, fd, flags) -} - -pub(crate) fn fd_fdstat_set_rights( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - fs_rights_base: __wasi_rights_t, - fs_rights_inheriting: __wasi_rights_t, -) -> __wasi_errno_t { - super::fd_fdstat_set_rights(ctx, fd, fs_rights_base, fs_rights_inheriting) -} - -pub(crate) fn fd_filestat_get( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - buf: WasmPtr<__wasi_filestat_t, MemoryType>, -) -> __wasi_errno_t { - super::fd_filestat_get::(ctx, fd, buf) -} - -pub(crate) fn fd_filestat_set_size( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - st_size: __wasi_filesize_t, -) -> __wasi_errno_t { - super::fd_filestat_set_size(ctx, fd, st_size) -} - -pub(crate) fn fd_filestat_set_times( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - st_atim: __wasi_timestamp_t, - st_mtim: __wasi_timestamp_t, - fst_flags: __wasi_fstflags_t, -) -> __wasi_errno_t { - super::fd_filestat_set_times(ctx, fd, st_atim, st_mtim, fst_flags) -} - -pub(crate) fn fd_pread( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - iovs: WasmPtr<__wasi_iovec_t, MemoryType>, - iovs_len: MemoryOffset, - offset: __wasi_filesize_t, - nread: WasmPtr, -) -> Result<__wasi_errno_t, WasiError> { - super::fd_pread::(ctx, fd, iovs, iovs_len, offset, nread) -} - -pub(crate) fn fd_prestat_get( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - buf: WasmPtr<__wasi_prestat_t, MemoryType>, -) -> __wasi_errno_t { - super::fd_prestat_get::(ctx, fd, buf) -} - -pub(crate) fn fd_prestat_dir_name( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - path: WasmPtr, - path_len: MemoryOffset, -) -> __wasi_errno_t { - super::fd_prestat_dir_name::(ctx, fd, path, path_len) -} - -pub(crate) fn fd_pwrite( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - iovs: WasmPtr<__wasi_ciovec_t, MemoryType>, - iovs_len: MemoryOffset, - offset: __wasi_filesize_t, - nwritten: WasmPtr, -) -> Result<__wasi_errno_t, WasiError> { - super::fd_pwrite::(ctx, fd, iovs, iovs_len, offset, nwritten) -} - -pub(crate) fn fd_read( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - iovs: WasmPtr<__wasi_iovec_t, MemoryType>, - iovs_len: MemoryOffset, - nread: WasmPtr, -) -> Result<__wasi_errno_t, WasiError> { - super::fd_read::(ctx, fd, iovs, iovs_len, nread) -} - -pub(crate) fn fd_readdir( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - buf: WasmPtr, - buf_len: MemoryOffset, - cookie: __wasi_dircookie_t, - bufused: WasmPtr, -) -> __wasi_errno_t { - super::fd_readdir::(ctx, fd, buf, buf_len, cookie, bufused) -} - -pub(crate) fn fd_renumber( - ctx: FunctionEnvMut, - from: __wasi_fd_t, - to: __wasi_fd_t, -) -> __wasi_errno_t { - super::fd_renumber(ctx, from, to) -} - -pub(crate) fn fd_seek( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - offset: __wasi_filedelta_t, - whence: __wasi_whence_t, - newoffset: WasmPtr<__wasi_filesize_t, MemoryType>, -) -> Result<__wasi_errno_t, WasiError> { - super::fd_seek::(ctx, fd, offset, whence, newoffset) -} - -pub(crate) fn fd_sync(ctx: FunctionEnvMut, fd: __wasi_fd_t) -> __wasi_errno_t { - super::fd_sync(ctx, fd) -} - -pub(crate) fn fd_tell( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - offset: WasmPtr<__wasi_filesize_t, MemoryType>, -) -> __wasi_errno_t { - super::fd_tell::(ctx, fd, offset) -} - -pub(crate) fn fd_write( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - iovs: WasmPtr<__wasi_ciovec_t, MemoryType>, - iovs_len: MemoryOffset, - nwritten: WasmPtr, -) -> Result<__wasi_errno_t, WasiError> { - super::fd_write::(ctx, fd, iovs, iovs_len, nwritten) -} - -pub(crate) fn path_create_directory( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - path: WasmPtr, - path_len: MemoryOffset, -) -> __wasi_errno_t { - super::path_create_directory::(ctx, fd, path, path_len) -} - -pub(crate) fn path_filestat_get( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - flags: __wasi_lookupflags_t, - path: WasmPtr, - path_len: MemoryOffset, - buf: WasmPtr<__wasi_filestat_t, MemoryType>, -) -> __wasi_errno_t { - super::path_filestat_get::(ctx, fd, flags, path, path_len, buf) -} - -pub(crate) fn path_filestat_set_times( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - flags: __wasi_lookupflags_t, - path: WasmPtr, - path_len: MemoryOffset, - st_atim: __wasi_timestamp_t, - st_mtim: __wasi_timestamp_t, - fst_flags: __wasi_fstflags_t, -) -> __wasi_errno_t { - super::path_filestat_set_times::( - ctx, fd, flags, path, path_len, st_atim, st_mtim, fst_flags, - ) -} - -pub(crate) fn path_link( - ctx: FunctionEnvMut, - old_fd: __wasi_fd_t, - old_flags: __wasi_lookupflags_t, - old_path: WasmPtr, - old_path_len: MemoryOffset, - new_fd: __wasi_fd_t, - new_path: WasmPtr, - new_path_len: MemoryOffset, -) -> __wasi_errno_t { - super::path_link::( - ctx, - old_fd, - old_flags, - old_path, - old_path_len, - new_fd, - new_path, - new_path_len, - ) -} - -pub(crate) fn path_open( - ctx: FunctionEnvMut, - dirfd: __wasi_fd_t, - dirflags: __wasi_lookupflags_t, - path: WasmPtr, - path_len: MemoryOffset, - o_flags: __wasi_oflags_t, - fs_rights_base: __wasi_rights_t, - fs_rights_inheriting: __wasi_rights_t, - fs_flags: __wasi_fdflags_t, - fd: WasmPtr<__wasi_fd_t, MemoryType>, -) -> __wasi_errno_t { - super::path_open::( - ctx, - dirfd, - dirflags, - path, - path_len, - o_flags, - fs_rights_base, - fs_rights_inheriting, - fs_flags, - fd, - ) -} - -pub(crate) fn path_readlink( - ctx: FunctionEnvMut, - dir_fd: __wasi_fd_t, - path: WasmPtr, - path_len: MemoryOffset, - buf: WasmPtr, - buf_len: MemoryOffset, - buf_used: WasmPtr, -) -> __wasi_errno_t { - super::path_readlink::(ctx, dir_fd, path, path_len, buf, buf_len, buf_used) -} - -pub(crate) fn path_remove_directory( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - path: WasmPtr, - path_len: MemoryOffset, -) -> __wasi_errno_t { - super::path_remove_directory::(ctx, fd, path, path_len) -} - -pub(crate) fn path_rename( - ctx: FunctionEnvMut, - old_fd: __wasi_fd_t, - old_path: WasmPtr, - old_path_len: MemoryOffset, - new_fd: __wasi_fd_t, - new_path: WasmPtr, - new_path_len: MemoryOffset, -) -> __wasi_errno_t { - super::path_rename::( - ctx, - old_fd, - old_path, - old_path_len, - new_fd, - new_path, - new_path_len, - ) -} - -pub(crate) fn path_symlink( - ctx: FunctionEnvMut, - old_path: WasmPtr, - old_path_len: MemoryOffset, - fd: __wasi_fd_t, - new_path: WasmPtr, - new_path_len: MemoryOffset, -) -> __wasi_errno_t { - super::path_symlink::(ctx, old_path, old_path_len, fd, new_path, new_path_len) -} - -pub(crate) fn path_unlink_file( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - path: WasmPtr, - path_len: MemoryOffset, -) -> __wasi_errno_t { - super::path_unlink_file::(ctx, fd, path, path_len) -} - -pub(crate) fn poll_oneoff( - ctx: FunctionEnvMut, - in_: WasmPtr<__wasi_subscription_t, MemoryType>, - out_: WasmPtr<__wasi_event_t, MemoryType>, - nsubscriptions: MemoryOffset, - nevents: WasmPtr, -) -> Result<__wasi_errno_t, WasiError> { - super::poll_oneoff::(ctx, in_, out_, nsubscriptions, nevents) -} - -pub(crate) fn proc_exit( - ctx: FunctionEnvMut, - code: __wasi_exitcode_t, -) -> Result<(), WasiError> { - super::proc_exit(ctx, code) -} - -pub(crate) fn proc_raise(ctx: FunctionEnvMut, sig: __wasi_signal_t) -> __wasi_errno_t { - super::proc_raise(ctx, sig) -} - -pub(crate) fn random_get( - ctx: FunctionEnvMut, - buf: WasmPtr, - buf_len: MemoryOffset, -) -> __wasi_errno_t { - super::random_get::(ctx, buf, buf_len) -} - -pub(crate) fn fd_dup( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - ret_fd: WasmPtr<__wasi_fd_t, MemoryType>, -) -> __wasi_errno_t { - super::fd_dup::(ctx, fd, ret_fd) -} - -pub(crate) fn fd_event( - ctx: FunctionEnvMut, - initial_val: u64, - flags: __wasi_eventfdflags, - ret_fd: WasmPtr<__wasi_fd_t, MemoryType>, -) -> __wasi_errno_t { - super::fd_event(ctx, initial_val, flags, ret_fd) -} - -pub(crate) fn fd_pipe( - ctx: FunctionEnvMut, - ro_fd1: WasmPtr<__wasi_fd_t, MemoryType>, - ro_fd2: WasmPtr<__wasi_fd_t, MemoryType>, -) -> __wasi_errno_t { - super::fd_pipe::(ctx, ro_fd1, ro_fd2) -} - -pub(crate) fn tty_get( - ctx: FunctionEnvMut, - tty_state: WasmPtr<__wasi_tty_t, MemoryType>, -) -> __wasi_errno_t { - super::tty_get::(ctx, tty_state) -} - -pub(crate) fn tty_set( - ctx: FunctionEnvMut, - tty_state: WasmPtr<__wasi_tty_t, MemoryType>, -) -> __wasi_errno_t { - super::tty_set::(ctx, tty_state) -} - -pub(crate) fn getcwd( - ctx: FunctionEnvMut, - path: WasmPtr, - path_len: WasmPtr, -) -> __wasi_errno_t { - super::getcwd::(ctx, path, path_len) -} - -pub(crate) fn chdir( - ctx: FunctionEnvMut, - path: WasmPtr, - path_len: MemoryOffset, -) -> __wasi_errno_t { - super::chdir::(ctx, path, path_len) -} - -pub(crate) fn thread_spawn( - ctx: FunctionEnvMut, - method: WasmPtr, - method_len: MemoryOffset, - user_data: u64, - reactor: __wasi_bool_t, - ret_tid: WasmPtr<__wasi_tid_t, MemoryType>, -) -> __wasi_errno_t { - super::thread_spawn::(ctx, method, method_len, user_data, reactor, ret_tid) -} - -pub(crate) fn thread_sleep( - ctx: FunctionEnvMut, - duration: __wasi_timestamp_t, -) -> Result<__wasi_errno_t, WasiError> { - super::thread_sleep(ctx, duration) -} - -pub(crate) fn thread_id( - ctx: FunctionEnvMut, - ret_tid: WasmPtr<__wasi_tid_t, MemoryType>, -) -> __wasi_errno_t { - super::thread_id::(ctx, ret_tid) -} - -pub(crate) fn thread_join( - ctx: FunctionEnvMut, - tid: __wasi_tid_t, -) -> Result<__wasi_errno_t, WasiError> { - super::thread_join(ctx, tid) -} - -pub(crate) fn thread_parallelism( - ctx: FunctionEnvMut, - ret_parallelism: WasmPtr, -) -> __wasi_errno_t { - super::thread_parallelism::(ctx, ret_parallelism) -} - -pub(crate) fn thread_exit( - ctx: FunctionEnvMut, - exitcode: __wasi_exitcode_t, -) -> Result<__wasi_errno_t, WasiError> { - super::thread_exit(ctx, exitcode) -} - -pub(crate) fn sched_yield(ctx: FunctionEnvMut) -> Result<__wasi_errno_t, WasiError> { - super::sched_yield(ctx) -} - -pub(crate) fn getpid( - ctx: FunctionEnvMut, - ret_pid: WasmPtr<__wasi_pid_t, MemoryType>, -) -> __wasi_errno_t { - super::getpid::(ctx, ret_pid) -} - -pub(crate) fn process_spawn( - ctx: FunctionEnvMut, - name: WasmPtr, - name_len: MemoryOffset, - chroot: __wasi_bool_t, - args: WasmPtr, - args_len: MemoryOffset, - preopen: WasmPtr, - preopen_len: MemoryOffset, - stdin: __wasi_stdiomode_t, - stdout: __wasi_stdiomode_t, - stderr: __wasi_stdiomode_t, - working_dir: WasmPtr, - working_dir_len: MemoryOffset, - ret_handles: WasmPtr<__wasi_bus_handles_t, MemoryType>, -) -> __bus_errno_t { - super::process_spawn::( - ctx, - name, - name_len, - chroot, - args, - args_len, - preopen, - preopen_len, - stdin, - stdout, - stderr, - working_dir, - working_dir_len, - ret_handles, - ) -} - -pub(crate) fn bus_open_local( - ctx: FunctionEnvMut, - name: WasmPtr, - name_len: MemoryOffset, - reuse: __wasi_bool_t, - ret_bid: WasmPtr<__wasi_bid_t, MemoryType>, -) -> __bus_errno_t { - super::bus_open_local::(ctx, name, name_len, reuse, ret_bid) -} - -pub(crate) fn bus_open_remote( - ctx: FunctionEnvMut, - name: WasmPtr, - name_len: MemoryOffset, - reuse: __wasi_bool_t, - instance: WasmPtr, - instance_len: MemoryOffset, - token: WasmPtr, - token_len: MemoryOffset, - ret_bid: WasmPtr<__wasi_bid_t, MemoryType>, -) -> __bus_errno_t { - super::bus_open_remote::( - ctx, - name, - name_len, - reuse, - instance, - instance_len, - token, - token_len, - ret_bid, - ) -} - -pub(crate) fn bus_close(ctx: FunctionEnvMut, bid: __wasi_bid_t) -> __bus_errno_t { - super::bus_close(ctx, bid) -} - -pub(crate) fn bus_call( - ctx: FunctionEnvMut, - bid: __wasi_bid_t, - keep_alive: __wasi_bool_t, - topic: WasmPtr, - topic_len: MemoryOffset, - format: __wasi_busdataformat_t, - buf: WasmPtr, - buf_len: MemoryOffset, - ret_cid: WasmPtr<__wasi_cid_t, MemoryType>, -) -> __bus_errno_t { - super::bus_call::( - ctx, bid, keep_alive, topic, topic_len, format, buf, buf_len, ret_cid, - ) -} - -pub(crate) fn bus_subcall( - ctx: FunctionEnvMut, - parent: __wasi_cid_t, - keep_alive: __wasi_bool_t, - topic: WasmPtr, - topic_len: MemoryOffset, - format: __wasi_busdataformat_t, - buf: WasmPtr, - buf_len: MemoryOffset, - ret_cid: WasmPtr<__wasi_cid_t, MemoryType>, -) -> __bus_errno_t { - super::bus_subcall::( - ctx, parent, keep_alive, topic, topic_len, format, buf, buf_len, ret_cid, - ) -} - -pub(crate) fn bus_poll( - ctx: FunctionEnvMut, - timeout: __wasi_timestamp_t, - events: WasmPtr, - nevents: MemoryOffset, - malloc: WasmPtr, - malloc_len: MemoryOffset, - ret_nevents: WasmPtr, -) -> __bus_errno_t { - super::bus_poll::( - ctx, - timeout, - events, - nevents, - malloc, - malloc_len, - ret_nevents, - ) -} - -pub(crate) fn call_reply( - ctx: FunctionEnvMut, - cid: __wasi_cid_t, - format: __wasi_busdataformat_t, - buf: WasmPtr, - buf_len: MemoryOffset, -) -> __bus_errno_t { - super::call_reply::(ctx, cid, format, buf, buf_len) -} - -pub(crate) fn call_fault( - ctx: FunctionEnvMut, - cid: __wasi_cid_t, - fault: __bus_errno_t, -) -> __bus_errno_t { - super::call_fault(ctx, cid, fault) -} - -pub(crate) fn call_close(ctx: FunctionEnvMut, cid: __wasi_cid_t) -> __bus_errno_t { - super::call_close(ctx, cid) -} - -pub(crate) fn port_bridge( - ctx: FunctionEnvMut, - network: WasmPtr, - network_len: MemoryOffset, - token: WasmPtr, - token_len: MemoryOffset, - security: __wasi_streamsecurity_t, -) -> __wasi_errno_t { - super::port_bridge::(ctx, network, network_len, token, token_len, security) -} - -pub(crate) fn port_unbridge(ctx: FunctionEnvMut) -> __wasi_errno_t { - super::port_unbridge(ctx) -} - -pub(crate) fn port_dhcp_acquire(ctx: FunctionEnvMut) -> __wasi_errno_t { - super::port_dhcp_acquire(ctx) -} - -pub(crate) fn port_addr_add( - ctx: FunctionEnvMut, - addr: WasmPtr<__wasi_cidr_t, MemoryType>, -) -> __wasi_errno_t { - super::port_addr_add::(ctx, addr) -} - -pub(crate) fn port_addr_remove( - ctx: FunctionEnvMut, - addr: WasmPtr<__wasi_addr_t, MemoryType>, -) -> __wasi_errno_t { - super::port_addr_remove::(ctx, addr) -} - -pub(crate) fn port_addr_clear(ctx: FunctionEnvMut) -> __wasi_errno_t { - super::port_addr_clear(ctx) -} - -pub(crate) fn port_addr_list( - ctx: FunctionEnvMut, - addrs: WasmPtr<__wasi_cidr_t, MemoryType>, - naddrs: WasmPtr, -) -> __wasi_errno_t { - super::port_addr_list::(ctx, addrs, naddrs) -} - -pub(crate) fn port_mac( - ctx: FunctionEnvMut, - ret_mac: WasmPtr<__wasi_hardwareaddress_t, MemoryType>, -) -> __wasi_errno_t { - super::port_mac::(ctx, ret_mac) -} - -pub(crate) fn port_gateway_set( - ctx: FunctionEnvMut, - ip: WasmPtr<__wasi_addr_t, MemoryType>, -) -> __wasi_errno_t { - super::port_gateway_set::(ctx, ip) -} - -pub(crate) fn port_route_add( - ctx: FunctionEnvMut, - cidr: WasmPtr<__wasi_cidr_t, MemoryType>, - via_router: WasmPtr<__wasi_addr_t, MemoryType>, - preferred_until: WasmPtr<__wasi_option_timestamp_t, MemoryType>, - expires_at: WasmPtr<__wasi_option_timestamp_t, MemoryType>, -) -> __wasi_errno_t { - super::port_route_add::(ctx, cidr, via_router, preferred_until, expires_at) -} - -pub(crate) fn port_route_remove( - ctx: FunctionEnvMut, - ip: WasmPtr<__wasi_addr_t, MemoryType>, -) -> __wasi_errno_t { - super::port_route_remove::(ctx, ip) -} - -pub(crate) fn port_route_clear(ctx: FunctionEnvMut) -> __wasi_errno_t { - super::port_route_clear(ctx) -} - -pub(crate) fn port_route_list( - ctx: FunctionEnvMut, - routes: WasmPtr<__wasi_route_t, MemoryType>, - nroutes: WasmPtr, -) -> __wasi_errno_t { - super::port_route_list::(ctx, routes, nroutes) -} - -pub(crate) fn ws_connect( - ctx: FunctionEnvMut, - url: WasmPtr, - url_len: MemoryOffset, - ret_sock: WasmPtr<__wasi_fd_t, MemoryType>, -) -> __wasi_errno_t { - super::ws_connect::(ctx, url, url_len, ret_sock) -} - -pub(crate) fn http_request( - ctx: FunctionEnvMut, - url: WasmPtr, - url_len: MemoryOffset, - method: WasmPtr, - method_len: MemoryOffset, - headers: WasmPtr, - headers_len: MemoryOffset, - gzip: __wasi_bool_t, - ret_handles: WasmPtr<__wasi_http_handles_t, MemoryType>, -) -> __wasi_errno_t { - super::http_request::( - ctx, - url, - url_len, - method, - method_len, - headers, - headers_len, - gzip, - ret_handles, - ) -} - -pub(crate) fn http_status( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - status: WasmPtr<__wasi_http_status_t, MemoryType>, - status_text: WasmPtr, - status_text_len: WasmPtr, - headers: WasmPtr, - headers_len: WasmPtr, -) -> __wasi_errno_t { - super::http_status::(ctx, sock, status) -} - -pub(crate) fn sock_status( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - ret_status: WasmPtr<__wasi_sockstatus_t, MemoryType>, -) -> __wasi_errno_t { - super::sock_status::(ctx, sock, ret_status) -} - -pub(crate) fn sock_addr_local( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - ret_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, -) -> __wasi_errno_t { - super::sock_addr_local::(ctx, sock, ret_addr) -} - -pub(crate) fn sock_addr_peer( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - ro_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, -) -> __wasi_errno_t { - super::sock_addr_peer::(ctx, sock, ro_addr) -} - -pub(crate) fn sock_open( - ctx: FunctionEnvMut, - af: __wasi_addressfamily_t, - ty: __wasi_socktype_t, - pt: __wasi_sockproto_t, - ro_sock: WasmPtr<__wasi_fd_t, MemoryType>, -) -> __wasi_errno_t { - super::sock_open::(ctx, af, ty, pt, ro_sock) -} - -pub(crate) fn sock_set_opt_flag( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - opt: __wasi_sockoption_t, - flag: __wasi_bool_t, -) -> __wasi_errno_t { - super::sock_set_opt_flag(ctx, sock, opt, flag) -} - -pub(crate) fn sock_get_opt_flag( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - opt: __wasi_sockoption_t, - ret_flag: WasmPtr<__wasi_bool_t, MemoryType>, -) -> __wasi_errno_t { - super::sock_get_opt_flag::(ctx, sock, opt, ret_flag) -} - -pub fn sock_set_opt_time( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - opt: __wasi_sockoption_t, - time: WasmPtr<__wasi_option_timestamp_t, MemoryType>, -) -> __wasi_errno_t { - super::sock_set_opt_time(ctx, sock, opt, time) -} - -pub fn sock_get_opt_time( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - opt: __wasi_sockoption_t, - ret_time: WasmPtr<__wasi_option_timestamp_t, MemoryType>, -) -> __wasi_errno_t { - super::sock_get_opt_time(ctx, sock, opt, ret_time) -} - -pub fn sock_set_opt_size( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - opt: __wasi_sockoption_t, - size: __wasi_filesize_t, -) -> __wasi_errno_t { - super::sock_set_opt_size(ctx, sock, opt, size) -} - -pub fn sock_get_opt_size( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - opt: __wasi_sockoption_t, - ret_size: WasmPtr<__wasi_filesize_t, MemoryType>, -) -> __wasi_errno_t { - super::sock_get_opt_size(ctx, sock, opt, ret_size) -} - -pub(crate) fn sock_join_multicast_v4( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - multiaddr: WasmPtr<__wasi_addr_ip4_t, MemoryType>, - iface: WasmPtr<__wasi_addr_ip4_t, MemoryType>, -) -> __wasi_errno_t { - super::sock_join_multicast_v4::(ctx, sock, multiaddr, iface) -} - -pub(crate) fn sock_leave_multicast_v4( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - multiaddr: WasmPtr<__wasi_addr_ip4_t, MemoryType>, - iface: WasmPtr<__wasi_addr_ip4_t, MemoryType>, -) -> __wasi_errno_t { - super::sock_leave_multicast_v4::(ctx, sock, multiaddr, iface) -} - -pub(crate) fn sock_join_multicast_v6( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - multiaddr: WasmPtr<__wasi_addr_ip6_t, MemoryType>, - iface: u32, -) -> __wasi_errno_t { - super::sock_join_multicast_v6::(ctx, sock, multiaddr, iface) -} - -pub(crate) fn sock_leave_multicast_v6( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - multiaddr: WasmPtr<__wasi_addr_ip6_t, MemoryType>, - iface: u32, -) -> __wasi_errno_t { - super::sock_leave_multicast_v6::(ctx, sock, multiaddr, iface) -} - -pub(crate) fn sock_bind( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - addr: WasmPtr<__wasi_addr_port_t, MemoryType>, -) -> __wasi_errno_t { - super::sock_bind::(ctx, sock, addr) -} - -pub(crate) fn sock_listen( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - backlog: MemoryOffset, -) -> __wasi_errno_t { - super::sock_listen::(ctx, sock, backlog) -} - -pub(crate) fn sock_accept( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - fd_flags: __wasi_fdflags_t, - ro_fd: WasmPtr<__wasi_fd_t, MemoryType>, - ro_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, -) -> Result<__wasi_errno_t, WasiError> { - super::sock_accept::(ctx, sock, fd_flags, ro_fd, ro_addr) -} - -pub(crate) fn sock_connect( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - addr: WasmPtr<__wasi_addr_port_t, MemoryType>, -) -> __wasi_errno_t { - super::sock_connect::(ctx, sock, addr) -} - -pub(crate) fn sock_recv( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - ri_data: WasmPtr<__wasi_iovec_t, MemoryType>, - ri_data_len: MemoryOffset, - ri_flags: __wasi_riflags_t, - ro_data_len: WasmPtr, - ro_flags: WasmPtr<__wasi_roflags_t, MemoryType>, -) -> Result<__wasi_errno_t, WasiError> { - super::sock_recv::( - ctx, - sock, - ri_data, - ri_data_len, - ri_flags, - ro_data_len, - ro_flags, - ) -} - -pub(crate) fn sock_recv_from( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - ri_data: WasmPtr<__wasi_iovec_t, MemoryType>, - ri_data_len: MemoryOffset, - ri_flags: __wasi_riflags_t, - ro_data_len: WasmPtr, - ro_flags: WasmPtr<__wasi_roflags_t, MemoryType>, - ro_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, -) -> Result<__wasi_errno_t, WasiError> { - super::sock_recv_from::( - ctx, - sock, - ri_data, - ri_data_len, - ri_flags, - ro_data_len, - ro_flags, - ro_addr, - ) -} - -pub(crate) fn sock_send( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - si_data: WasmPtr<__wasi_ciovec_t, MemoryType>, - si_data_len: MemoryOffset, - si_flags: __wasi_siflags_t, - ret_data_len: WasmPtr, -) -> Result<__wasi_errno_t, WasiError> { - super::sock_send::(ctx, sock, si_data, si_data_len, si_flags, ret_data_len) -} - -pub(crate) fn sock_send_to( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - si_data: WasmPtr<__wasi_ciovec_t, MemoryType>, - si_data_len: MemoryOffset, - si_flags: __wasi_siflags_t, - addr: WasmPtr<__wasi_addr_port_t, MemoryType>, - ret_data_len: WasmPtr, -) -> Result<__wasi_errno_t, WasiError> { - super::sock_send_to::( - ctx, - sock, - si_data, - si_data_len, - si_flags, - addr, - ret_data_len, - ) -} - -pub(crate) fn sock_send_file( - ctx: FunctionEnvMut, - out_fd: __wasi_fd_t, - in_fd: __wasi_fd_t, - offset: __wasi_filesize_t, - count: __wasi_filesize_t, - ret_sent: WasmPtr<__wasi_filesize_t, MemoryType>, -) -> Result<__wasi_errno_t, WasiError> { - unsafe { super::sock_send_file::(ctx, out_fd, in_fd, offset, count, ret_sent) } -} - -pub(crate) fn sock_shutdown( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - how: __wasi_sdflags_t, -) -> __wasi_errno_t { - super::sock_shutdown(ctx, sock, how) -} - -pub(crate) fn resolve( - ctx: FunctionEnvMut, - host: WasmPtr, - host_len: MemoryOffset, - port: u16, - ips: WasmPtr<__wasi_addr_t, MemoryType>, - nips: MemoryOffset, - ret_nips: WasmPtr, -) -> __wasi_errno_t { - super::resolve::(ctx, host, host_len, port, ips, nips, ret_nips) -} diff --git a/lib/wasi/src/syscalls/wasix64.rs b/lib/wasi/src/syscalls/wasix64.rs deleted file mode 100644 index b42307e0da8..00000000000 --- a/lib/wasi/src/syscalls/wasix64.rs +++ /dev/null @@ -1,1060 +0,0 @@ -#![deny(dead_code)] -use crate::{WasiEnv, WasiError, WasiState, WasiThread}; -use wasmer::{FunctionEnvMut, Memory, Memory64, MemorySize, StoreMut, WasmPtr, WasmSlice}; -use wasmer_wasi_types::*; - -type MemoryType = Memory64; -type MemoryOffset = u64; - -pub(crate) fn args_get( - ctx: FunctionEnvMut, - argv: WasmPtr, MemoryType>, - argv_buf: WasmPtr, -) -> __wasi_errno_t { - super::args_get::(ctx, argv, argv_buf) -} - -pub(crate) fn args_sizes_get( - ctx: FunctionEnvMut, - argc: WasmPtr, - argv_buf_size: WasmPtr, -) -> __wasi_errno_t { - super::args_sizes_get::(ctx, argc, argv_buf_size) -} - -pub(crate) fn clock_res_get( - ctx: FunctionEnvMut, - clock_id: __wasi_clockid_t, - resolution: WasmPtr<__wasi_timestamp_t, MemoryType>, -) -> __wasi_errno_t { - super::clock_res_get::(ctx, clock_id, resolution) -} - -pub(crate) fn clock_time_get( - ctx: FunctionEnvMut, - clock_id: __wasi_clockid_t, - precision: __wasi_timestamp_t, - time: WasmPtr<__wasi_timestamp_t, MemoryType>, -) -> __wasi_errno_t { - super::clock_time_get::(ctx, clock_id, precision, time) -} - -pub(crate) fn environ_get( - ctx: FunctionEnvMut, - environ: WasmPtr, MemoryType>, - environ_buf: WasmPtr, -) -> __wasi_errno_t { - super::environ_get::(ctx, environ, environ_buf) -} - -pub(crate) fn environ_sizes_get( - ctx: FunctionEnvMut, - environ_count: WasmPtr, - environ_buf_size: WasmPtr, -) -> __wasi_errno_t { - super::environ_sizes_get::(ctx, environ_count, environ_buf_size) -} - -pub(crate) fn fd_advise( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - offset: __wasi_filesize_t, - len: __wasi_filesize_t, - advice: __wasi_advice_t, -) -> __wasi_errno_t { - super::fd_advise(ctx, fd, offset, len, advice) -} - -pub(crate) fn fd_allocate( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - offset: __wasi_filesize_t, - len: __wasi_filesize_t, -) -> __wasi_errno_t { - super::fd_allocate(ctx, fd, offset, len) -} - -pub(crate) fn fd_close(ctx: FunctionEnvMut, fd: __wasi_fd_t) -> __wasi_errno_t { - super::fd_close(ctx, fd) -} - -pub(crate) fn fd_datasync(ctx: FunctionEnvMut, fd: __wasi_fd_t) -> __wasi_errno_t { - super::fd_datasync(ctx, fd) -} - -pub(crate) fn fd_fdstat_get( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - buf_ptr: WasmPtr<__wasi_fdstat_t, MemoryType>, -) -> __wasi_errno_t { - super::fd_fdstat_get::(ctx, fd, buf_ptr) -} - -pub(crate) fn fd_fdstat_set_flags( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - flags: __wasi_fdflags_t, -) -> __wasi_errno_t { - super::fd_fdstat_set_flags(ctx, fd, flags) -} - -pub(crate) fn fd_fdstat_set_rights( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - fs_rights_base: __wasi_rights_t, - fs_rights_inheriting: __wasi_rights_t, -) -> __wasi_errno_t { - super::fd_fdstat_set_rights(ctx, fd, fs_rights_base, fs_rights_inheriting) -} - -pub(crate) fn fd_filestat_get( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - buf: WasmPtr<__wasi_filestat_t, MemoryType>, -) -> __wasi_errno_t { - super::fd_filestat_get::(ctx, fd, buf) -} - -pub(crate) fn fd_filestat_set_size( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - st_size: __wasi_filesize_t, -) -> __wasi_errno_t { - super::fd_filestat_set_size(ctx, fd, st_size) -} - -pub(crate) fn fd_filestat_set_times( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - st_atim: __wasi_timestamp_t, - st_mtim: __wasi_timestamp_t, - fst_flags: __wasi_fstflags_t, -) -> __wasi_errno_t { - super::fd_filestat_set_times(ctx, fd, st_atim, st_mtim, fst_flags) -} - -pub(crate) fn fd_pread( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - iovs: WasmPtr<__wasi_iovec_t, MemoryType>, - iovs_len: MemoryOffset, - offset: __wasi_filesize_t, - nread: WasmPtr, -) -> Result<__wasi_errno_t, WasiError> { - super::fd_pread::(ctx, fd, iovs, iovs_len, offset, nread) -} - -pub(crate) fn fd_prestat_get( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - buf: WasmPtr<__wasi_prestat_t, MemoryType>, -) -> __wasi_errno_t { - super::fd_prestat_get::(ctx, fd, buf) -} - -pub(crate) fn fd_prestat_dir_name( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - path: WasmPtr, - path_len: MemoryOffset, -) -> __wasi_errno_t { - super::fd_prestat_dir_name::(ctx, fd, path, path_len) -} - -pub(crate) fn fd_pwrite( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - iovs: WasmPtr<__wasi_ciovec_t, MemoryType>, - iovs_len: MemoryOffset, - offset: __wasi_filesize_t, - nwritten: WasmPtr, -) -> Result<__wasi_errno_t, WasiError> { - super::fd_pwrite::(ctx, fd, iovs, iovs_len, offset, nwritten) -} - -pub(crate) fn fd_read( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - iovs: WasmPtr<__wasi_iovec_t, MemoryType>, - iovs_len: MemoryOffset, - nread: WasmPtr, -) -> Result<__wasi_errno_t, WasiError> { - super::fd_read::(ctx, fd, iovs, iovs_len, nread) -} - -pub(crate) fn fd_readdir( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - buf: WasmPtr, - buf_len: MemoryOffset, - cookie: __wasi_dircookie_t, - bufused: WasmPtr, -) -> __wasi_errno_t { - super::fd_readdir::(ctx, fd, buf, buf_len, cookie, bufused) -} - -pub(crate) fn fd_renumber( - ctx: FunctionEnvMut, - from: __wasi_fd_t, - to: __wasi_fd_t, -) -> __wasi_errno_t { - super::fd_renumber(ctx, from, to) -} - -pub(crate) fn fd_seek( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - offset: __wasi_filedelta_t, - whence: __wasi_whence_t, - newoffset: WasmPtr<__wasi_filesize_t, MemoryType>, -) -> Result<__wasi_errno_t, WasiError> { - super::fd_seek::(ctx, fd, offset, whence, newoffset) -} - -pub(crate) fn fd_sync(ctx: FunctionEnvMut, fd: __wasi_fd_t) -> __wasi_errno_t { - super::fd_sync(ctx, fd) -} - -pub(crate) fn fd_tell( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - offset: WasmPtr<__wasi_filesize_t, MemoryType>, -) -> __wasi_errno_t { - super::fd_tell::(ctx, fd, offset) -} - -pub(crate) fn fd_write( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - iovs: WasmPtr<__wasi_ciovec_t, MemoryType>, - iovs_len: MemoryOffset, - nwritten: WasmPtr, -) -> Result<__wasi_errno_t, WasiError> { - super::fd_write::(ctx, fd, iovs, iovs_len, nwritten) -} - -pub(crate) fn path_create_directory( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - path: WasmPtr, - path_len: MemoryOffset, -) -> __wasi_errno_t { - super::path_create_directory::(ctx, fd, path, path_len) -} - -pub(crate) fn path_filestat_get( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - flags: __wasi_lookupflags_t, - path: WasmPtr, - path_len: MemoryOffset, - buf: WasmPtr<__wasi_filestat_t, MemoryType>, -) -> __wasi_errno_t { - super::path_filestat_get::(ctx, fd, flags, path, path_len, buf) -} - -pub(crate) fn path_filestat_set_times( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - flags: __wasi_lookupflags_t, - path: WasmPtr, - path_len: MemoryOffset, - st_atim: __wasi_timestamp_t, - st_mtim: __wasi_timestamp_t, - fst_flags: __wasi_fstflags_t, -) -> __wasi_errno_t { - super::path_filestat_set_times::( - ctx, fd, flags, path, path_len, st_atim, st_mtim, fst_flags, - ) -} - -pub(crate) fn path_link( - ctx: FunctionEnvMut, - old_fd: __wasi_fd_t, - old_flags: __wasi_lookupflags_t, - old_path: WasmPtr, - old_path_len: MemoryOffset, - new_fd: __wasi_fd_t, - new_path: WasmPtr, - new_path_len: MemoryOffset, -) -> __wasi_errno_t { - super::path_link::( - ctx, - old_fd, - old_flags, - old_path, - old_path_len, - new_fd, - new_path, - new_path_len, - ) -} - -pub(crate) fn path_open( - ctx: FunctionEnvMut, - dirfd: __wasi_fd_t, - dirflags: __wasi_lookupflags_t, - path: WasmPtr, - path_len: MemoryOffset, - o_flags: __wasi_oflags_t, - fs_rights_base: __wasi_rights_t, - fs_rights_inheriting: __wasi_rights_t, - fs_flags: __wasi_fdflags_t, - fd: WasmPtr<__wasi_fd_t, MemoryType>, -) -> __wasi_errno_t { - super::path_open::( - ctx, - dirfd, - dirflags, - path, - path_len, - o_flags, - fs_rights_base, - fs_rights_inheriting, - fs_flags, - fd, - ) -} - -pub(crate) fn path_readlink( - ctx: FunctionEnvMut, - dir_fd: __wasi_fd_t, - path: WasmPtr, - path_len: MemoryOffset, - buf: WasmPtr, - buf_len: MemoryOffset, - buf_used: WasmPtr, -) -> __wasi_errno_t { - super::path_readlink::(ctx, dir_fd, path, path_len, buf, buf_len, buf_used) -} - -pub(crate) fn path_remove_directory( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - path: WasmPtr, - path_len: MemoryOffset, -) -> __wasi_errno_t { - super::path_remove_directory::(ctx, fd, path, path_len) -} - -pub(crate) fn path_rename( - ctx: FunctionEnvMut, - old_fd: __wasi_fd_t, - old_path: WasmPtr, - old_path_len: MemoryOffset, - new_fd: __wasi_fd_t, - new_path: WasmPtr, - new_path_len: MemoryOffset, -) -> __wasi_errno_t { - super::path_rename::( - ctx, - old_fd, - old_path, - old_path_len, - new_fd, - new_path, - new_path_len, - ) -} - -pub(crate) fn path_symlink( - ctx: FunctionEnvMut, - old_path: WasmPtr, - old_path_len: MemoryOffset, - fd: __wasi_fd_t, - new_path: WasmPtr, - new_path_len: MemoryOffset, -) -> __wasi_errno_t { - super::path_symlink::(ctx, old_path, old_path_len, fd, new_path, new_path_len) -} - -pub(crate) fn path_unlink_file( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - path: WasmPtr, - path_len: MemoryOffset, -) -> __wasi_errno_t { - super::path_unlink_file::(ctx, fd, path, path_len) -} - -pub(crate) fn poll_oneoff( - ctx: FunctionEnvMut, - in_: WasmPtr<__wasi_subscription_t, MemoryType>, - out_: WasmPtr<__wasi_event_t, MemoryType>, - nsubscriptions: MemoryOffset, - nevents: WasmPtr, -) -> Result<__wasi_errno_t, WasiError> { - super::poll_oneoff::(ctx, in_, out_, nsubscriptions, nevents) -} - -pub(crate) fn proc_exit( - ctx: FunctionEnvMut, - code: __wasi_exitcode_t, -) -> Result<(), WasiError> { - super::proc_exit(ctx, code) -} - -pub(crate) fn proc_raise(ctx: FunctionEnvMut, sig: __wasi_signal_t) -> __wasi_errno_t { - super::proc_raise(ctx, sig) -} - -pub(crate) fn random_get( - ctx: FunctionEnvMut, - buf: WasmPtr, - buf_len: MemoryOffset, -) -> __wasi_errno_t { - super::random_get::(ctx, buf, buf_len) -} - -pub(crate) fn fd_dup( - ctx: FunctionEnvMut, - fd: __wasi_fd_t, - ret_fd: WasmPtr<__wasi_fd_t, MemoryType>, -) -> __wasi_errno_t { - super::fd_dup::(ctx, fd, ret_fd) -} - -pub(crate) fn fd_event( - ctx: FunctionEnvMut, - initial_val: u64, - flags: __wasi_eventfdflags, - ret_fd: WasmPtr<__wasi_fd_t, MemoryType>, -) -> __wasi_errno_t { - super::fd_event(ctx, initial_val, flags, ret_fd) -} - -pub(crate) fn fd_pipe( - ctx: FunctionEnvMut, - ro_fd1: WasmPtr<__wasi_fd_t, MemoryType>, - ro_fd2: WasmPtr<__wasi_fd_t, MemoryType>, -) -> __wasi_errno_t { - super::fd_pipe::(ctx, ro_fd1, ro_fd2) -} - -pub(crate) fn tty_get( - ctx: FunctionEnvMut, - tty_state: WasmPtr<__wasi_tty_t, MemoryType>, -) -> __wasi_errno_t { - super::tty_get::(ctx, tty_state) -} - -pub(crate) fn tty_set( - ctx: FunctionEnvMut, - tty_state: WasmPtr<__wasi_tty_t, MemoryType>, -) -> __wasi_errno_t { - super::tty_set::(ctx, tty_state) -} - -pub(crate) fn getcwd( - ctx: FunctionEnvMut, - path: WasmPtr, - path_len: WasmPtr, -) -> __wasi_errno_t { - super::getcwd::(ctx, path, path_len) -} - -pub(crate) fn chdir( - ctx: FunctionEnvMut, - path: WasmPtr, - path_len: MemoryOffset, -) -> __wasi_errno_t { - super::chdir::(ctx, path, path_len) -} - -pub(crate) fn thread_spawn( - ctx: FunctionEnvMut, - method: WasmPtr, - method_len: MemoryOffset, - user_data: u64, - reactor: __wasi_bool_t, - ret_tid: WasmPtr<__wasi_tid_t, MemoryType>, -) -> __wasi_errno_t { - super::thread_spawn::(ctx, method, method_len, user_data, reactor, ret_tid) -} - -pub(crate) fn thread_sleep( - ctx: FunctionEnvMut, - duration: __wasi_timestamp_t, -) -> Result<__wasi_errno_t, WasiError> { - super::thread_sleep(ctx, duration) -} - -pub(crate) fn thread_id( - ctx: FunctionEnvMut, - ret_tid: WasmPtr<__wasi_tid_t, MemoryType>, -) -> __wasi_errno_t { - super::thread_id::(ctx, ret_tid) -} - -pub(crate) fn thread_join( - ctx: FunctionEnvMut, - tid: __wasi_tid_t, -) -> Result<__wasi_errno_t, WasiError> { - super::thread_join(ctx, tid) -} - -pub(crate) fn thread_parallelism( - ctx: FunctionEnvMut, - ret_parallelism: WasmPtr, -) -> __wasi_errno_t { - super::thread_parallelism::(ctx, ret_parallelism) -} - -pub(crate) fn thread_exit( - ctx: FunctionEnvMut, - exitcode: __wasi_exitcode_t, -) -> Result<__wasi_errno_t, WasiError> { - super::thread_exit(ctx, exitcode) -} - -pub(crate) fn sched_yield(ctx: FunctionEnvMut) -> Result<__wasi_errno_t, WasiError> { - super::sched_yield(ctx) -} - -pub(crate) fn getpid( - ctx: FunctionEnvMut, - ret_pid: WasmPtr<__wasi_pid_t, MemoryType>, -) -> __wasi_errno_t { - super::getpid::(ctx, ret_pid) -} - -pub(crate) fn process_spawn( - ctx: FunctionEnvMut, - name: WasmPtr, - name_len: MemoryOffset, - chroot: __wasi_bool_t, - args: WasmPtr, - args_len: MemoryOffset, - preopen: WasmPtr, - preopen_len: MemoryOffset, - stdin: __wasi_stdiomode_t, - stdout: __wasi_stdiomode_t, - stderr: __wasi_stdiomode_t, - working_dir: WasmPtr, - working_dir_len: MemoryOffset, - ret_handles: WasmPtr<__wasi_bus_handles_t, MemoryType>, -) -> __bus_errno_t { - super::process_spawn::( - ctx, - name, - name_len, - chroot, - args, - args_len, - preopen, - preopen_len, - stdin, - stdout, - stderr, - working_dir, - working_dir_len, - ret_handles, - ) -} - -pub(crate) fn bus_open_local( - ctx: FunctionEnvMut, - name: WasmPtr, - name_len: MemoryOffset, - reuse: __wasi_bool_t, - ret_bid: WasmPtr<__wasi_bid_t, MemoryType>, -) -> __bus_errno_t { - super::bus_open_local::(ctx, name, name_len, reuse, ret_bid) -} - -pub(crate) fn bus_open_remote( - ctx: FunctionEnvMut, - name: WasmPtr, - name_len: MemoryOffset, - reuse: __wasi_bool_t, - instance: WasmPtr, - instance_len: MemoryOffset, - token: WasmPtr, - token_len: MemoryOffset, - ret_bid: WasmPtr<__wasi_bid_t, MemoryType>, -) -> __bus_errno_t { - super::bus_open_remote::( - ctx, - name, - name_len, - reuse, - instance, - instance_len, - token, - token_len, - ret_bid, - ) -} - -pub(crate) fn bus_close(ctx: FunctionEnvMut, bid: __wasi_bid_t) -> __bus_errno_t { - super::bus_close(ctx, bid) -} - -pub(crate) fn bus_call( - ctx: FunctionEnvMut, - bid: __wasi_bid_t, - keep_alive: __wasi_bool_t, - topic: WasmPtr, - topic_len: MemoryOffset, - format: __wasi_busdataformat_t, - buf: WasmPtr, - buf_len: MemoryOffset, - ret_cid: WasmPtr<__wasi_cid_t, MemoryType>, -) -> __bus_errno_t { - super::bus_call::( - ctx, bid, keep_alive, topic, topic_len, format, buf, buf_len, ret_cid, - ) -} - -pub(crate) fn bus_subcall( - ctx: FunctionEnvMut, - parent: __wasi_cid_t, - keep_alive: __wasi_bool_t, - topic: WasmPtr, - topic_len: MemoryOffset, - format: __wasi_busdataformat_t, - buf: WasmPtr, - buf_len: MemoryOffset, - ret_cid: WasmPtr<__wasi_cid_t, MemoryType>, -) -> __bus_errno_t { - super::bus_subcall::( - ctx, parent, keep_alive, topic, topic_len, format, buf, buf_len, ret_cid, - ) -} - -pub(crate) fn bus_poll( - ctx: FunctionEnvMut, - timeout: __wasi_timestamp_t, - events: WasmPtr, - nevents: MemoryOffset, - malloc: WasmPtr, - malloc_len: MemoryOffset, - ret_nevents: WasmPtr, -) -> __bus_errno_t { - super::bus_poll::( - ctx, - timeout, - events, - nevents, - malloc, - malloc_len, - ret_nevents, - ) -} - -pub(crate) fn call_reply( - ctx: FunctionEnvMut, - cid: __wasi_cid_t, - format: __wasi_busdataformat_t, - buf: WasmPtr, - buf_len: MemoryOffset, -) -> __bus_errno_t { - super::call_reply::(ctx, cid, format, buf, buf_len) -} - -pub(crate) fn call_fault( - ctx: FunctionEnvMut, - cid: __wasi_cid_t, - fault: __bus_errno_t, -) -> __bus_errno_t { - super::call_fault(ctx, cid, fault) -} - -pub(crate) fn call_close(ctx: FunctionEnvMut, cid: __wasi_cid_t) -> __bus_errno_t { - super::call_close(ctx, cid) -} - -pub(crate) fn port_bridge( - ctx: FunctionEnvMut, - network: WasmPtr, - network_len: MemoryOffset, - token: WasmPtr, - token_len: MemoryOffset, - security: __wasi_streamsecurity_t, -) -> __wasi_errno_t { - super::port_bridge::(ctx, network, network_len, token, token_len, security) -} - -pub(crate) fn port_unbridge(ctx: FunctionEnvMut) -> __wasi_errno_t { - super::port_unbridge(ctx) -} - -pub(crate) fn port_dhcp_acquire(ctx: FunctionEnvMut) -> __wasi_errno_t { - super::port_dhcp_acquire(ctx) -} - -pub(crate) fn port_addr_add( - ctx: FunctionEnvMut, - addr: WasmPtr<__wasi_cidr_t, MemoryType>, -) -> __wasi_errno_t { - super::port_addr_add::(ctx, addr) -} - -pub(crate) fn port_addr_remove( - ctx: FunctionEnvMut, - addr: WasmPtr<__wasi_addr_t, MemoryType>, -) -> __wasi_errno_t { - super::port_addr_remove::(ctx, addr) -} - -pub(crate) fn port_addr_clear(ctx: FunctionEnvMut) -> __wasi_errno_t { - super::port_addr_clear(ctx) -} - -pub(crate) fn port_addr_list( - ctx: FunctionEnvMut, - addrs: WasmPtr<__wasi_cidr_t, MemoryType>, - naddrs: WasmPtr, -) -> __wasi_errno_t { - super::port_addr_list::(ctx, addrs, naddrs) -} - -pub(crate) fn port_mac( - ctx: FunctionEnvMut, - ret_mac: WasmPtr<__wasi_hardwareaddress_t, MemoryType>, -) -> __wasi_errno_t { - super::port_mac::(ctx, ret_mac) -} - -pub(crate) fn port_gateway_set( - ctx: FunctionEnvMut, - ip: WasmPtr<__wasi_addr_t, MemoryType>, -) -> __wasi_errno_t { - super::port_gateway_set::(ctx, ip) -} - -pub(crate) fn port_route_add( - ctx: FunctionEnvMut, - cidr: WasmPtr<__wasi_cidr_t, MemoryType>, - via_router: WasmPtr<__wasi_addr_t, MemoryType>, - preferred_until: WasmPtr<__wasi_option_timestamp_t, MemoryType>, - expires_at: WasmPtr<__wasi_option_timestamp_t, MemoryType>, -) -> __wasi_errno_t { - super::port_route_add::(ctx, cidr, via_router, preferred_until, expires_at) -} - -pub(crate) fn port_route_remove( - ctx: FunctionEnvMut, - ip: WasmPtr<__wasi_addr_t, MemoryType>, -) -> __wasi_errno_t { - super::port_route_remove::(ctx, ip) -} - -pub(crate) fn port_route_clear(ctx: FunctionEnvMut) -> __wasi_errno_t { - super::port_route_clear(ctx) -} - -pub(crate) fn port_route_list( - ctx: FunctionEnvMut, - routes: WasmPtr<__wasi_route_t, MemoryType>, - nroutes: WasmPtr, -) -> __wasi_errno_t { - super::port_route_list::(ctx, routes, nroutes) -} - -pub(crate) fn ws_connect( - ctx: FunctionEnvMut, - url: WasmPtr, - url_len: MemoryOffset, - ret_sock: WasmPtr<__wasi_fd_t, MemoryType>, -) -> __wasi_errno_t { - super::ws_connect::(ctx, url, url_len, ret_sock) -} - -pub(crate) fn http_request( - ctx: FunctionEnvMut, - url: WasmPtr, - url_len: MemoryOffset, - method: WasmPtr, - method_len: MemoryOffset, - headers: WasmPtr, - headers_len: MemoryOffset, - gzip: __wasi_bool_t, - ret_handles: WasmPtr<__wasi_http_handles_t, MemoryType>, -) -> __wasi_errno_t { - super::http_request::( - ctx, - url, - url_len, - method, - method_len, - headers, - headers_len, - gzip, - ret_handles, - ) -} - -pub(crate) fn http_status( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - status: WasmPtr<__wasi_http_status_t, MemoryType>, - status_text: WasmPtr, - status_text_len: WasmPtr, - headers: WasmPtr, - headers_len: WasmPtr, -) -> __wasi_errno_t { - super::http_status::(ctx, sock, status) -} - -pub(crate) fn sock_status( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - ret_status: WasmPtr<__wasi_sockstatus_t, MemoryType>, -) -> __wasi_errno_t { - super::sock_status::(ctx, sock, ret_status) -} - -pub(crate) fn sock_addr_local( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - ret_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, -) -> __wasi_errno_t { - super::sock_addr_local::(ctx, sock, ret_addr) -} - -pub(crate) fn sock_addr_peer( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - ro_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, -) -> __wasi_errno_t { - super::sock_addr_peer::(ctx, sock, ro_addr) -} - -pub(crate) fn sock_open( - ctx: FunctionEnvMut, - af: __wasi_addressfamily_t, - ty: __wasi_socktype_t, - pt: __wasi_sockproto_t, - ro_sock: WasmPtr<__wasi_fd_t, MemoryType>, -) -> __wasi_errno_t { - super::sock_open::(ctx, af, ty, pt, ro_sock) -} - -pub(crate) fn sock_set_opt_flag( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - opt: __wasi_sockoption_t, - flag: __wasi_bool_t, -) -> __wasi_errno_t { - super::sock_set_opt_flag(ctx, sock, opt, flag) -} - -pub(crate) fn sock_get_opt_flag( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - opt: __wasi_sockoption_t, - ret_flag: WasmPtr<__wasi_bool_t, MemoryType>, -) -> __wasi_errno_t { - super::sock_get_opt_flag::(ctx, sock, opt, ret_flag) -} - -pub fn sock_set_opt_time( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - opt: __wasi_sockoption_t, - time: WasmPtr<__wasi_option_timestamp_t, MemoryType>, -) -> __wasi_errno_t { - super::sock_set_opt_time(ctx, sock, opt, time) -} - -pub fn sock_get_opt_time( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - opt: __wasi_sockoption_t, - ret_time: WasmPtr<__wasi_option_timestamp_t, MemoryType>, -) -> __wasi_errno_t { - super::sock_get_opt_time(ctx, sock, opt, ret_time) -} - -pub fn sock_set_opt_size( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - opt: __wasi_sockoption_t, - size: __wasi_filesize_t, -) -> __wasi_errno_t { - super::sock_set_opt_size(ctx, sock, opt, size) -} - -pub fn sock_get_opt_size( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - opt: __wasi_sockoption_t, - ret_size: WasmPtr<__wasi_filesize_t, MemoryType>, -) -> __wasi_errno_t { - super::sock_get_opt_size(ctx, sock, opt, ret_size) -} - -pub(crate) fn sock_join_multicast_v4( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - multiaddr: WasmPtr<__wasi_addr_ip4_t, MemoryType>, - iface: WasmPtr<__wasi_addr_ip4_t, MemoryType>, -) -> __wasi_errno_t { - super::sock_join_multicast_v4::(ctx, sock, multiaddr, iface) -} - -pub(crate) fn sock_leave_multicast_v4( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - multiaddr: WasmPtr<__wasi_addr_ip4_t, MemoryType>, - iface: WasmPtr<__wasi_addr_ip4_t, MemoryType>, -) -> __wasi_errno_t { - super::sock_leave_multicast_v4::(ctx, sock, multiaddr, iface) -} - -pub(crate) fn sock_join_multicast_v6( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - multiaddr: WasmPtr<__wasi_addr_ip6_t, MemoryType>, - iface: u32, -) -> __wasi_errno_t { - super::sock_join_multicast_v6::(ctx, sock, multiaddr, iface) -} - -pub(crate) fn sock_leave_multicast_v6( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - multiaddr: WasmPtr<__wasi_addr_ip6_t, MemoryType>, - iface: u32, -) -> __wasi_errno_t { - super::sock_leave_multicast_v6::(ctx, sock, multiaddr, iface) -} - -pub(crate) fn sock_bind( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - addr: WasmPtr<__wasi_addr_port_t, MemoryType>, -) -> __wasi_errno_t { - super::sock_bind::(ctx, sock, addr) -} - -pub(crate) fn sock_listen( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - backlog: MemoryOffset, -) -> __wasi_errno_t { - super::sock_listen::(ctx, sock, backlog) -} - -pub(crate) fn sock_accept( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - fd_flags: __wasi_fdflags_t, - ro_fd: WasmPtr<__wasi_fd_t, MemoryType>, - ro_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, -) -> Result<__wasi_errno_t, WasiError> { - super::sock_accept::(ctx, sock, fd_flags, ro_fd, ro_addr) -} - -pub(crate) fn sock_connect( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - addr: WasmPtr<__wasi_addr_port_t, MemoryType>, -) -> __wasi_errno_t { - super::sock_connect::(ctx, sock, addr) -} - -pub(crate) fn sock_recv( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - ri_data: WasmPtr<__wasi_iovec_t, MemoryType>, - ri_data_len: MemoryOffset, - ri_flags: __wasi_riflags_t, - ro_data_len: WasmPtr, - ro_flags: WasmPtr<__wasi_roflags_t, MemoryType>, -) -> Result<__wasi_errno_t, WasiError> { - super::sock_recv::( - ctx, - sock, - ri_data, - ri_data_len, - ri_flags, - ro_data_len, - ro_flags, - ) -} - -pub(crate) fn sock_recv_from( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - ri_data: WasmPtr<__wasi_iovec_t, MemoryType>, - ri_data_len: MemoryOffset, - ri_flags: __wasi_riflags_t, - ro_data_len: WasmPtr, - ro_flags: WasmPtr<__wasi_roflags_t, MemoryType>, - ro_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, -) -> Result<__wasi_errno_t, WasiError> { - super::sock_recv_from::( - ctx, - sock, - ri_data, - ri_data_len, - ri_flags, - ro_data_len, - ro_flags, - ro_addr, - ) -} - -pub(crate) fn sock_send( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - si_data: WasmPtr<__wasi_ciovec_t, MemoryType>, - si_data_len: MemoryOffset, - si_flags: __wasi_siflags_t, - ret_data_len: WasmPtr, -) -> Result<__wasi_errno_t, WasiError> { - super::sock_send::(ctx, sock, si_data, si_data_len, si_flags, ret_data_len) -} - -pub(crate) fn sock_send_to( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - si_data: WasmPtr<__wasi_ciovec_t, MemoryType>, - si_data_len: MemoryOffset, - si_flags: __wasi_siflags_t, - addr: WasmPtr<__wasi_addr_port_t, MemoryType>, - ret_data_len: WasmPtr, -) -> Result<__wasi_errno_t, WasiError> { - super::sock_send_to::( - ctx, - sock, - si_data, - si_data_len, - si_flags, - addr, - ret_data_len, - ) -} - -pub(crate) fn sock_send_file( - ctx: FunctionEnvMut, - out_fd: __wasi_fd_t, - in_fd: __wasi_fd_t, - offset: __wasi_filesize_t, - count: __wasi_filesize_t, - ret_sent: WasmPtr<__wasi_filesize_t, MemoryType>, -) -> Result<__wasi_errno_t, WasiError> { - unsafe { super::sock_send_file::(ctx, out_fd, in_fd, offset, count, ret_sent) } -} - -pub(crate) fn sock_shutdown( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, - how: __wasi_sdflags_t, -) -> __wasi_errno_t { - super::sock_shutdown(ctx, sock, how) -} - -pub(crate) fn resolve( - ctx: FunctionEnvMut, - host: WasmPtr, - host_len: MemoryOffset, - port: u16, - ips: WasmPtr<__wasi_addr_t, MemoryType>, - nips: MemoryOffset, - ret_nips: WasmPtr, -) -> __wasi_errno_t { - super::resolve::(ctx, host, host_len, port, ips, nips, ret_nips) -} diff --git a/lib/wasi/src/syscalls/wasm32.rs b/lib/wasi/src/syscalls/wasm.rs similarity index 100% rename from lib/wasi/src/syscalls/wasm32.rs rename to lib/wasi/src/syscalls/wasm.rs diff --git a/lib/wasi/tests/catsay.rs b/lib/wasi/tests/catsay.rs new file mode 100644 index 00000000000..4d4901840ba --- /dev/null +++ b/lib/wasi/tests/catsay.rs @@ -0,0 +1,146 @@ +#![cfg(feature = "sys")] +#![cfg(target_os = "linux")] +use std::{io::{Read, Write}, time::Duration}; + +#[allow(unused_imports)] +use tracing::{debug, info, metadata::LevelFilter}; +#[cfg(feature = "sys")] +use tracing_subscriber::fmt::SubscriberBuilder; +use wasmer::{Instance, Module, Store, Cranelift, EngineBuilder}; +use wasmer_wasi::{Pipe, WasiState, import_object_for_all_wasi_versions, WasiError}; + +#[cfg(feature = "sys")] +mod sys { + #[test] + fn test_catsay() { + super::test_catsay() + } +} + +#[cfg(feature = "js")] +mod js { + use wasm_bindgen_test::*; + #[wasm_bindgen_test] + fn test_catsay() { + super::test_catsay() + } +} + +fn test_catsay() { + + info!("Creating engine"); + let compiler = Cranelift::default(); + let engine = EngineBuilder::new(compiler.clone()); + + #[allow(unused_mut)] + let mut store = Store::new(engine); + + info!("Compiling module"); + let module = Module::new(&store, include_bytes!("catsay.wasm")).unwrap(); + + #[cfg(feature = "js")] + tracing_wasm::set_as_global_default_with_config({ + let mut builder = tracing_wasm::WASMLayerConfigBuilder::new(); + builder.set_console_config(tracing_wasm::ConsoleConfig::ReportWithoutConsoleColor); + builder.build() + }); + + #[cfg(feature = "sys")] + SubscriberBuilder::default() + .with_max_level(LevelFilter::TRACE) + .init(); + + + let engine = store.engine().clone(); + for _ in 0..10 { + let module = module.clone(); + run_test(store, module); + + store = Store::new(engine.clone()); + } + + // TODO: This version will SIGSEGV (users must reuse engines) + for _ in 0..10 { + let module = module.clone(); + run_test(store, module); + + let engine = EngineBuilder::new(compiler.clone()); + store = Store::new(engine); + } +} + +fn run_test(mut store: Store, module: Module) +{ + // Create the `WasiEnv`. + let mut stdout = Pipe::new(); + let mut wasi_state_builder = WasiState::new("catsay"); + + let mut stdin_pipe = Pipe::new(); + + let mut wasi_env = wasi_state_builder + .stdin(Box::new(stdin_pipe.clone())) + .stdout(Box::new(stdout.clone())) + .stderr(Box::new(stdout.clone())) + .finalize(&mut store) + .unwrap(); + + // Start a thread that will dump STDOUT to info + #[cfg(feature = "sys")] + std::thread::spawn(move || { + loop { + let mut buf = [0u8; 8192]; + if let Ok(amt) = stdout.read(&mut buf[..]) { + if amt > 0 { + let msg = String::from_utf8_lossy(&buf[0..amt]); + for line in msg.lines() { + info!("{}", line); + } + } else { + std::thread::sleep(Duration::from_millis(1)); + } + } else { + break; + } + } + }); + + // Write some text to catsay stdin + stdin_pipe.write_all("hi there".as_bytes()).unwrap(); + drop(stdin_pipe); + + // Generate an `ImportObject`. + let mut import_object = import_object_for_all_wasi_versions(&mut store, &wasi_env.env); + import_object.import_shared_memory(&module, &mut store); + + // Let's instantiate the module with the imports. + let instance = Instance::new(&mut store, &module, &import_object).unwrap(); + wasi_env.initialize(&mut store, &instance).unwrap(); + + // Let's call the `_start` function, which is our `main` function in Rust. + let start = instance.exports.get_function("_start").unwrap(); + let ret = start.call(&mut store, &[]); + if let Err(e) = ret { + match e.downcast::() { + Ok(WasiError::Exit(0)) => { } + Ok(WasiError::Exit(code)) => { + assert!(false, "The call should have returned Err(WasiError::Exit(0)) but returned {}", code); + } + Ok(WasiError::UnknownWasiVersion) => { + assert!(false, "The call should have returned Err(WasiError::Exit(0)) but returned UnknownWasiVersion"); + } + Err(err) => { + assert!(false, "The call returned an error {:?}", err); + } + } + } + + #[cfg(feature = "js")] + { + let mut stdout_str = String::new(); + stdout.read_to_string(&mut stdout_str).unwrap(); + let stdout_as_str = stdout_str.as_str(); + for line in stdout_str.lines() { + info!("{}", line); + } + } +} diff --git a/lib/wasi/tests/catsay.wasm b/lib/wasi/tests/catsay.wasm new file mode 100755 index 00000000000..bb103f01429 Binary files /dev/null and b/lib/wasi/tests/catsay.wasm differ diff --git a/lib/wasi/tests/condvar.rs b/lib/wasi/tests/condvar.rs new file mode 100644 index 00000000000..c3a9863762d --- /dev/null +++ b/lib/wasi/tests/condvar.rs @@ -0,0 +1,120 @@ +#![cfg(feature = "sys")] +#![cfg(target_os = "linux")] +use std::{io::Read, time::Duration}; + +#[allow(unused_imports)] +use tracing::{debug, info, metadata::LevelFilter}; +#[cfg(feature = "sys")] +use tracing_subscriber::fmt::SubscriberBuilder; +use wasmer::{Instance, Module, Store, Features, Cranelift, EngineBuilder}; +use wasmer_wasi::{Pipe, WasiState, import_object_for_all_wasi_versions, WasiError}; + +#[cfg(feature = "sys")] +mod sys { + #[test] + fn test_condvar() { + super::test_condvar() + } +} + +#[cfg(feature = "js")] +mod js { + use wasm_bindgen_test::*; + #[wasm_bindgen_test] + fn test_condvar() { + super::test_condvar() + } +} + +fn test_condvar() { + let mut features = Features::new(); + features + .threads(true); + + info!("Creating engine"); + let compiler = Cranelift::default(); + let engine = EngineBuilder::new(compiler) + .set_features(Some(features)); + + let store = Store::new(engine); + + info!("Compiling module"); + let module = Module::new(&store, include_bytes!("condvar.wasm")).unwrap(); + + #[cfg(feature = "js")] + tracing_wasm::set_as_global_default_with_config({ + let mut builder = tracing_wasm::WASMLayerConfigBuilder::new(); + builder.set_console_config(tracing_wasm::ConsoleConfig::ReportWithoutConsoleColor); + builder.build() + }); + + #[cfg(feature = "sys")] + SubscriberBuilder::default() + .with_max_level(LevelFilter::TRACE) + .init(); + + run_test(store, module); +} + +fn run_test(mut store: Store, module: Module) +{ + // Create the `WasiEnv`. + let mut stdout = Pipe::new(); + let mut wasi_state_builder = WasiState::new("multi-threading"); + + let mut wasi_env = wasi_state_builder + .stdout(Box::new(stdout.clone())) + .stderr(Box::new(stdout.clone())) + .finalize(&mut store) + .unwrap(); + + // Start a thread that will dump STDOUT to info + #[cfg(feature = "sys")] + std::thread::spawn(move || { + loop { + let mut buf = [0u8; 8192]; + if let Ok(amt) = stdout.read(&mut buf[..]) { + if amt > 0 { + let msg = String::from_utf8_lossy(&buf[0..amt]); + for line in msg.lines() { + info!("{}", line); + } + } else { + std::thread::sleep(Duration::from_millis(1)); + } + } else { + break; + } + } + }); + + // Generate an `ImportObject`. + let mut import_object = import_object_for_all_wasi_versions(&mut store, &wasi_env.env); + import_object.import_shared_memory(&module, &mut store); + + // Let's instantiate the module with the imports. + let instance = Instance::new(&mut store, &module, &import_object).unwrap(); + wasi_env.initialize(&mut store, &instance).unwrap(); + + // Let's call the `_start` function, which is our `main` function in Rust. + let start = instance.exports.get_function("_start").unwrap(); + let ret = start.call(&mut store, &[]); + if let Err(e) = ret { + match e.downcast::() { + Ok(WasiError::Exit(0)) => { } + _ => { + assert!(false, "The call should have returned Err(WasiError::Exit(0))"); + } + } + } + + #[cfg(feature = "js")] + { + let mut stdout_str = String::new(); + stdout.read_to_string(&mut stdout_str).unwrap(); + let stdout_as_str = stdout_str.as_str(); + for line in stdout_str.lines() { + info!("{}", line); + } + } +} diff --git a/lib/wasi/tests/condvar.wasm b/lib/wasi/tests/condvar.wasm new file mode 100755 index 00000000000..c7f0ab2561b Binary files /dev/null and b/lib/wasi/tests/condvar.wasm differ diff --git a/lib/wasi/tests/coreutils.rs b/lib/wasi/tests/coreutils.rs new file mode 100644 index 00000000000..883dca43b31 --- /dev/null +++ b/lib/wasi/tests/coreutils.rs @@ -0,0 +1,106 @@ +#![cfg(feature = "sys")] +#![cfg(target_os = "linux")] +use std::io::Read; + +#[allow(unused_imports)] +use tracing::{debug, info, metadata::LevelFilter}; +#[cfg(feature = "sys")] +use tracing_subscriber::fmt::SubscriberBuilder; +use wasmer::{Instance, Module, Store, Features, Cranelift, EngineBuilder}; +use wasmer_wasi::{Pipe, WasiState, import_object_for_all_wasi_versions, WasiError}; + +#[cfg(feature = "sys")] +mod sys { + #[test] + fn test_coreutils() { + super::test_coreutils() + } +} + +#[cfg(feature = "js")] +mod js { + use wasm_bindgen_test::*; + #[wasm_bindgen_test] + fn test_coreutils() { + super::test_coreutils() + } +} + +fn test_coreutils() { + let mut features = Features::new(); + features + .threads(true); + + info!("Creating engine"); + let compiler = Cranelift::default(); + let engine = EngineBuilder::new(compiler) + .set_features(Some(features)) + .engine(); + + let store = Store::new(engine.clone()); + + info!("Compiling module"); + let module = Module::new(&store, include_bytes!("coreutils.wasm")).unwrap(); + + #[cfg(feature = "js")] + tracing_wasm::set_as_global_default_with_config({ + let mut builder = tracing_wasm::WASMLayerConfigBuilder::new(); + builder.set_console_config(tracing_wasm::ConsoleConfig::ReportWithoutConsoleColor); + builder.build() + }); + + #[cfg(feature = "sys")] + SubscriberBuilder::default() + .with_max_level(LevelFilter::DEBUG) + .init(); + + // We do it many times (to make sure the compiled modules are reusable) + for n in 0..2 + { + let store = Store::new(engine.clone()); + let module = module.clone(); + + // Run the test itself + info!("Test Round {}", n); + run_test(store, module); + } +} + +fn run_test(mut store: Store, module: Module) +{ + // Create the `WasiEnv`. + let mut stdout = Pipe::new(); + let mut wasi_state_builder = WasiState::new("echo"); + wasi_state_builder + .args(&["apple"]); + + let mut wasi_env = wasi_state_builder + .stdout(Box::new(stdout.clone())) + .finalize(&mut store) + .unwrap(); + + // Generate an `ImportObject`. + let mut import_object = import_object_for_all_wasi_versions(&mut store, &wasi_env.env); + import_object.import_shared_memory(&module, &mut store); + + // Let's instantiate the module with the imports. + let instance = Instance::new(&mut store, &module, &import_object).unwrap(); + wasi_env.initialize(&mut store, &instance).unwrap(); + + // Let's call the `_start` function, which is our `main` function in Rust. + let start = instance.exports.get_function("_start").unwrap(); + let ret = start.call(&mut store, &[]); + if let Err(e) = ret { + match e.downcast::() { + Ok(WasiError::Exit(0)) => { } + _ => { + assert!(false, "The call should have returned Err(WasiError::Exit(0))"); + } + } + } + + let mut stdout_str = String::new(); + stdout.read_to_string(&mut stdout_str).unwrap(); + let stdout_as_str = stdout_str.as_str(); + assert_eq!(stdout_as_str, "apple\n"); +} diff --git a/lib/wasi/tests/coreutils.wasm b/lib/wasi/tests/coreutils.wasm new file mode 100755 index 00000000000..0a056a48329 Binary files /dev/null and b/lib/wasi/tests/coreutils.wasm differ diff --git a/lib/wasi/tests/multi-threading.rs b/lib/wasi/tests/multi-threading.rs new file mode 100644 index 00000000000..8a4e1f6a8e5 --- /dev/null +++ b/lib/wasi/tests/multi-threading.rs @@ -0,0 +1,119 @@ +#![cfg(feature = "sys")] +#![cfg(target_os = "linux")] +use std::{io::Read, time::Duration}; + +#[allow(unused_imports)] +use tracing::{debug, info, metadata::LevelFilter}; +#[cfg(feature = "sys")] +use tracing_subscriber::fmt::SubscriberBuilder; +use wasmer::{Instance, Module, Store, Features, Cranelift, EngineBuilder}; +use wasmer_wasi::{Pipe, WasiState, import_object_for_all_wasi_versions, WasiError}; + +mod sys { + #[test] + fn test_multithreading() { + super::test_multithreading() + } +} + +fn test_multithreading() { + let mut features = Features::new(); + features + .threads(true); + + info!("Creating engine"); + let compiler = Cranelift::default(); + let engine = EngineBuilder::new(compiler) + .set_features(Some(features)) + .engine(); + + let store = Store::new(engine.clone()); + + info!("Compiling module"); + let module = Module::new(&store, include_bytes!("multi-threading.wasm")).unwrap(); + + #[cfg(feature = "js")] + tracing_wasm::set_as_global_default_with_config({ + let mut builder = tracing_wasm::WASMLayerConfigBuilder::new(); + builder.set_console_config(tracing_wasm::ConsoleConfig::ReportWithoutConsoleColor); + builder.build() + }); + + #[cfg(feature = "sys")] + SubscriberBuilder::default() + .with_max_level(LevelFilter::TRACE) + .init(); + + // We do it many times (to make sure the compiled modules are reusable) + for n in 0..2 + { + let store = Store::new(engine.clone()); + let module = module.clone(); + + info!("Test Round {}", n); + run_test(store, module); + } +} + +fn run_test(mut store: Store, module: Module) +{ + // Create the `WasiEnv`. + let mut stdout = Pipe::new(); + let mut wasi_state_builder = WasiState::new("multi-threading"); + + let mut wasi_env = wasi_state_builder + .stdout(Box::new(stdout.clone())) + .stderr(Box::new(stdout.clone())) + .finalize(&mut store) + .unwrap(); + + // Start a thread that will dump STDOUT to info + #[cfg(feature = "sys")] + std::thread::spawn(move || { + loop { + let mut buf = [0u8; 8192]; + if let Ok(amt) = stdout.read(&mut buf[..]) { + if amt > 0 { + let msg = String::from_utf8_lossy(&buf[0..amt]); + for line in msg.lines() { + info!("{}", line); + } + } else { + std::thread::sleep(Duration::from_millis(1)); + } + } else { + break; + } + } + }); + + // Generate an `ImportObject`. + let mut import_object = import_object_for_all_wasi_versions(&mut store, &wasi_env.env); + import_object.import_shared_memory(&module, &mut store); + + // Let's instantiate the module with the imports. + let instance = Instance::new(&mut store, &module, &import_object).unwrap(); + wasi_env.initialize(&mut store, &instance).unwrap(); + + // Let's call the `_start` function, which is our `main` function in Rust. + let start = instance.exports.get_function("_start").unwrap(); + let ret = start.call(&mut store, &[]); + if let Err(e) = ret { + match e.downcast::() { + Ok(WasiError::Exit(0)) => { } + _ => { + assert!(false, "The call should have returned Err(WasiError::Exit(0))"); + } + } + } + + #[cfg(feature = "js")] + { + let mut stdout_str = String::new(); + stdout.read_to_string(&mut stdout_str).unwrap(); + let stdout_as_str = stdout_str.as_str(); + for line in stdout_str.lines() { + info!("{}", line); + } + } +} diff --git a/lib/wasi/tests/multi-threading.wasm b/lib/wasi/tests/multi-threading.wasm new file mode 100644 index 00000000000..5fcb480b7b7 Binary files /dev/null and b/lib/wasi/tests/multi-threading.wasm differ diff --git a/lib/wasi/tests/stdio.rs b/lib/wasi/tests/stdio.rs index 78b93520e1a..218a477d2b4 100644 --- a/lib/wasi/tests/stdio.rs +++ b/lib/wasi/tests/stdio.rs @@ -23,7 +23,6 @@ mod sys { #[cfg(feature = "js")] mod js { use wasm_bindgen_test::*; - #[wasm_bindgen_test] fn test_stdout() { super::test_stdout() @@ -74,7 +73,7 @@ fn test_stdout() { // Create the `WasiEnv`. let mut stdout = Pipe::default(); - let wasi_env = WasiState::new("command-name") + let mut wasi_env = WasiState::new("command-name") .args(&["Gordon"]) .stdout(Box::new(stdout.clone())) .finalize(&mut store) @@ -85,8 +84,7 @@ fn test_stdout() { // Let's instantiate the module with the imports. let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - let memory = instance.exports.get_memory("memory").unwrap(); - wasi_env.data_mut(&mut store).set_memory(memory.clone()); + wasi_env.initialize(&mut store, &instance).unwrap(); // Let's call the `_start` function, which is our `main` function in Rust. let start = instance.exports.get_function("_start").unwrap(); @@ -118,7 +116,7 @@ fn test_env() { .env("TEST", "VALUE") .env("TEST2", "VALUE2"); // panic!("envs: {:?}", wasi_state_builder.envs); - let wasi_env = wasi_state_builder + let mut wasi_env = wasi_state_builder .stdout(Box::new(stdout.clone())) .finalize(&mut store) .unwrap(); @@ -128,8 +126,7 @@ fn test_env() { // Let's instantiate the module with the imports. let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - let memory = instance.exports.get_memory("memory").unwrap(); - wasi_env.data_mut(&mut store).set_memory(memory.clone()); + wasi_env.initialize(&mut store, &instance).unwrap(); // Let's call the `_start` function, which is our `main` function in Rust. let start = instance.exports.get_function("_start").unwrap(); @@ -147,7 +144,7 @@ fn test_stdin() { // Create the `WasiEnv`. let mut stdin = Pipe::new(); - let wasi_env = WasiState::new("command-name") + let mut wasi_env = WasiState::new("command-name") .stdin(Box::new(stdin.clone())) .finalize(&mut store) .unwrap(); @@ -161,8 +158,7 @@ fn test_stdin() { // Let's instantiate the module with the imports. let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - let memory = instance.exports.get_memory("memory").unwrap(); - wasi_env.data_mut(&mut store).set_memory(memory.clone()); + wasi_env.initialize(&mut store, &instance).unwrap(); // Let's call the `_start` function, which is our `main` function in Rust. let start = instance.exports.get_function("_start").unwrap(); diff --git a/lib/wasi/wia/wasixx_32v1.txt b/lib/wasi/wia/wasixx_32v1.txt new file mode 100644 index 00000000000..da5e31e220b --- /dev/null +++ b/lib/wasi/wia/wasixx_32v1.txt @@ -0,0 +1,116 @@ +(interface "wasix_32v1" + (func (import "wasix_32v1" "args_get") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "args_sizes_get") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "environ_get") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "environ_sizes_get") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "clock_res_get") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "clock_time_get") (param i32 i64 i32) (result i32)) + (func (import "wasix_32v1" "fd_advise") (param i32 i64 i64 i32) (result i32)) + (func (import "wasix_32v1" "fd_allocate") (param i32 i64 i64) (result i32)) + (func (import "wasix_32v1" "fd_close") (param i32) (result i32)) + (func (import "wasix_32v1" "fd_datasync") (param i32) (result i32)) + (func (import "wasix_32v1" "fd_fdstat_get") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "fd_fdstat_set_flags") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "fd_fdstat_set_rights") (param i32 i64 i64) (result i32)) + (func (import "wasix_32v1" "fd_filestat_get") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "fd_filestat_set_size") (param i32 i64) (result i32)) + (func (import "wasix_32v1" "fd_filestat_set_times") (param i32 i64 i64 i32) (result i32)) + (func (import "wasix_32v1" "fd_pread") (param i32 i32 i32 i64 i32) (result i32)) + (func (import "wasix_32v1" "fd_prestat_get") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "fd_prestat_dir_name") (param i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "fd_pwrite") (param i32 i32 i32 i64 i32) (result i32)) + (func (import "wasix_32v1" "fd_read") (param i32 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "fd_readdir") (param i32 i32 i32 i64 i32) (result i32)) + (func (import "wasix_32v1" "fd_renumber") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "fd_dup") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "fd_event") (param i64 i32 i32) (result i32)) + (func (import "wasix_32v1" "fd_seek") (param i32 i64 i32 i32) (result i32)) + (func (import "wasix_32v1" "fd_sync") (param i32) (result i32)) + (func (import "wasix_32v1" "fd_tell") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "fd_write") (param i32 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "pipe") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "path_create_directory") (param i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "path_filestat_get") (param i32 i32 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "path_filestat_set_times") (param i32 i32 i32 i32 i64 i64 i32) (result i32)) + (func (import "wasix_32v1" "path_link") (param i32 i32 i32 i32 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "path_open") (param i32 i32 i32 i32 i32 i64 i64 i32 i32) (result i32)) + (func (import "wasix_32v1" "path_readlink") (param i32 i32 i32 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "path_remove_directory") (param i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "path_rename") (param i32 i32 i32 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "path_symlink") (param i32 i32 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "path_unlink_file") (param i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "poll_oneoff") (param i32 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "proc_exit") (param i32) + (func (import "wasix_32v1" "proc_raise") (param i32) (result i32)) + (func (import "wasix_32v1" "sched_yield") (result i32)) + (func (import "wasix_32v1" "random_get") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "tty_get") (param i32) (result i32)) + (func (import "wasix_32v1" "tty_set") (param i32) (result i32)) + (func (import "wasix_32v1" "getcwd") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "chdir") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "thread_spawn") (param i64 i32 i32) (result i32)) + (func (import "wasix_32v1" "thread_sleep") (param i64) (result i32)) + (func (import "wasix_32v1" "thread_id") (param i32) (result i32)) + (func (import "wasix_32v1" "thread_local_create") (param i64 i32) (result i32)) + (func (import "wasix_32v1" "thread_local_destroy") (param i32) (result i32)) + (func (import "wasix_32v1" "thread_local_set") (param i32 i64) (result i32)) + (func (import "wasix_32v1" "thread_local_get") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "thread_join") (param i32) (result i32)) + (func (import "wasix_32v1" "thread_parallelism") (param i32) (result i32)) + (func (import "wasix_32v1" "futex_wait") (param i32 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "futex_wake") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "futex_wake_all") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "getpid") (param i32) (result i32)) + (func (import "wasix_32v1" "thread_exit") (param i32) + (func (import "wasix_32v1" "process_spawn") (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "bus_open_local") (param i32 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "bus_open_remote") (param 32 i32 i32 i32 i32 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "bus_close") (param i32) (result i32)) + (func (import "wasix_32v1" "bus_call") (param i32 i32 i32 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "bus_subcall") (param i32 i32 i32 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "bus_poll") (param i64 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "call_reply") (param i64 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "call_fault") (param i64 i32) + (func (import "wasix_32v1" "call_close") (param i64) + (func (import "wasix_32v1" "ws_connect") (param i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "http_request") (param i32 i32 i32 i32 i32 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "http_status") (param i32 i32) + (func (import "wasix_32v1" "port_bridge") (param i32 i32 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "port_unbridge") (result i32)) + (func (import "wasix_32v1" "port_dhcp_acquire") (result i32)) + (func (import "wasix_32v1" "port_addr_add") (param i32) (result i32)) + (func (import "wasix_32v1" "port_addr_remove") (param i32) (result i32)) + (func (import "wasix_32v1" "port_addr_clear") (result i32)) + (func (import "wasix_32v1" "port_mac") (param i32) (result i32)) + (func (import "wasix_32v1" "port_addr_list") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "port_gateway_set") (param i32) (result i32)) + (func (import "wasix_32v1" "port_route_add") (param i32 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "port_route_remove") (param i32) (result i32)) + (func (import "wasix_32v1" "port_route_clear") (result i32)) + (func (import "wasix_32v1" "port_route_list") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "sock_shutdown") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "sock_status") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "sock_addr_local") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "sock_addr_peer") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "sock_open") (param i32 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "sock_set_opt_flag") (param i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "sock_get_opt_flag") (param i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "sock_set_opt_time") (param i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "sock_get_opt_time") (param i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "sock_set_opt_size") (param i32 i32 i64) (result i32)) + (func (import "wasix_32v1" "sock_get_opt_size") (param i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "sock_join_multicast_v4") (param i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "sock_leave_multicast_v4") (param i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "sock_join_multicast_v6") (param i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "sock_leave_multicast_v6") (param i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "sock_bind") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "sock_listen") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "sock_accept") (param i32 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "sock_connect") (param i32 i32) (result i32)) + (func (import "wasix_32v1" "sock_recv") (param i32 i32 i32 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "sock_recv_from") (param i32 i32 i32 i32 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "sock_send") (param i32 i32 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "sock_send_to") (param i32 i32 i32 i32 i32 i32) (result i32)) + (func (import "wasix_32v1" "sock_send_file") (param i32 i32 i64 i64 i64) (result i32)) + (func (import "wasix_32v1" "resolve") (param i32 i32 i32 i32 i32 i32) (result i32)) +) diff --git a/lib/wasi/wia/wasixx_64v1.txt b/lib/wasi/wia/wasixx_64v1.txt new file mode 100644 index 00000000000..e904bbb1968 --- /dev/null +++ b/lib/wasi/wia/wasixx_64v1.txt @@ -0,0 +1,116 @@ +(interface "wasix_64v1" + (func (import "wasix_64v1" "args_get") (param i64 i64) (result i32)) + (func (import "wasix_64v1" "args_sizes_get") (param i64 i64) (result i32)) + (func (import "wasix_64v1" "environ_get") (param i64 i64) (result i32)) + (func (import "wasix_64v1" "environ_sizes_get") (param i64 i64) (result i32)) + (func (import "wasix_64v1" "clock_res_get") (param i32 i64) (result i32)) + (func (import "wasix_64v1" "clock_time_get") (param i32 i64 i64) (result i32)) + (func (import "wasix_64v1" "fd_advise") (param i32 i64 i64 i32) (result i32)) + (func (import "wasix_64v1" "fd_allocate") (param i32 i64 i64) (result i32)) + (func (import "wasix_64v1" "fd_close") (param i32) (result i32)) + (func (import "wasix_64v1" "fd_datasync") (param i32) (result i32)) + (func (import "wasix_64v1" "fd_fdstat_get") (param i32 i64) (result i32)) + (func (import "wasix_64v1" "fd_fdstat_set_flags") (param i32 i32) (result i32)) + (func (import "wasix_64v1" "fd_fdstat_set_rights") (param i32 i64 i64) (result i32)) + (func (import "wasix_64v1" "fd_filestat_get") (param i32 i64) (result i32)) + (func (import "wasix_64v1" "fd_filestat_set_size") (param i32 i64) (result i32)) + (func (import "wasix_64v1" "fd_filestat_set_times") (param i32 i64 i64 i32) (result i32)) + (func (import "wasix_64v1" "fd_pread") (param i32 i64 i64 i64 i64) (result i32)) + (func (import "wasix_64v1" "fd_prestat_get") (param i32 i64) (result i32)) + (func (import "wasix_64v1" "fd_prestat_dir_name") (param i32 i64 i64) (result i32)) + (func (import "wasix_64v1" "fd_pwrite") (param i32 i64 i64 i64 i64) (result i32)) + (func (import "wasix_64v1" "fd_read") (param i32 i64 i64 i64) (result i32)) + (func (import "wasix_64v1" "fd_readdir") (param i32 i64 i64 i64 i64) (result i32)) + (func (import "wasix_64v1" "fd_renumber") (param i32 i32) (result i32)) + (func (import "wasix_64v1" "fd_dup") (param i32 i64) (result i32)) + (func (import "wasix_64v1" "fd_event") (param i64 i32 i64) (result i32)) + (func (import "wasix_64v1" "fd_seek") (param i32 i64 i32 i64) (result i32)) + (func (import "wasix_64v1" "fd_sync") (param i32) (result i32)) + (func (import "wasix_64v1" "fd_tell") (param i32 i64) (result i32)) + (func (import "wasix_64v1" "fd_write") (param i32 i64 i64 i64) (result i32)) + (func (import "wasix_64v1" "pipe") (param i64 i64) (result i32)) + (func (import "wasix_64v1" "path_create_directory") (param i32 i64 i64) (result i32)) + (func (import "wasix_64v1" "path_filestat_get") (param i32 i32 i64 i64 i64) (result i32)) + (func (import "wasix_64v1" "path_filestat_set_times") (param i32 i32 i64 i64 i64 i64 i32) (result i32)) + (func (import "wasix_64v1" "path_link") (param i32 i32 i64 i64 i32 i64 i64) (result i32)) + (func (import "wasix_64v1" "path_open") (param i32 i32 i64 i64 i32 i64 i64 i32 i64) (result i32)) + (func (import "wasix_64v1" "path_readlink") (param i32 i64 i64 i64 i64 i64) (result i32)) + (func (import "wasix_64v1" "path_remove_directory") (param i32 i64 i64) (result i32)) + (func (import "wasix_64v1" "path_rename") (param i32 i64 i64 i32 i64 i64) (result i32)) + (func (import "wasix_64v1" "path_symlink") (param i64 i64 i32 i64 i64) (result i32)) + (func (import "wasix_64v1" "path_unlink_file") (param i32 i64 i64) (result i32)) + (func (import "wasix_64v1" "poll_oneoff") (param i64 i64 i32 i64) (result i32)) + (func (import "wasix_64v1" "proc_exit") (param i32) + (func (import "wasix_64v1" "proc_raise") (param i32) (result i32)) + (func (import "wasix_64v1" "sched_yield") (result i32)) + (func (import "wasix_64v1" "random_get") (param i64 i64) (result i32)) + (func (import "wasix_64v1" "tty_get") (param i64) (result i32)) + (func (import "wasix_64v1" "tty_set") (param i64) (result i32)) + (func (import "wasix_64v1" "getcwd") (param i64 i64) (result i32)) + (func (import "wasix_64v1" "chdir") (param i64 i64) (result i32)) + (func (import "wasix_64v1" "thread_spawn") (param i64 i32 i64) (result i32)) + (func (import "wasix_64v1" "thread_sleep") (param i64) (result i32)) + (func (import "wasix_64v1" "thread_id") (param i64) (result i32)) + (func (import "wasix_64v1" "thread_local_create") (param i64 i64) (result i32)) + (func (import "wasix_64v1" "thread_local_destroy") (param i32) (result i32)) + (func (import "wasix_64v1" "thread_local_set") (param i32 i64) (result i32)) + (func (import "wasix_64v1" "thread_local_get") (param i32 i64) (result i32)) + (func (import "wasix_64v1" "thread_join") (param i32) (result i32)) + (func (import "wasix_64v1" "thread_parallelism") (param i64) (result i32)) + (func (import "wasix_64v1" "futex_wait") (param i64 i32 i64 i64) (result i32)) + (func (import "wasix_64v1" "futex_wake") (param i64 i64) (result i32)) + (func (import "wasix_64v1" "futex_wake_all") (param i64 i64) (result i32)) + (func (import "wasix_64v1" "getpid") (param i64) (result i32)) + (func (import "wasix_64v1" "thread_exit") (param i32) + (func (import "wasix_64v1" "process_spawn") (param i64 i64 i32 i64 i64 i64 i64 i32 i32 i32 i64 i64 i64) (result i32)) + (func (import "wasix_64v1" "bus_open_local") (param i64 i64 i32 i64) (result i32)) + (func (import "wasix_64v1" "bus_open_remote") (param i64 i64 i32 i64 i64 i64 i64 i64) (result i32)) + (func (import "wasix_64v1" "bus_close") (param i32) (result i32)) + (func (import "wasix_64v1" "bus_call") (param i32 i64 i32 i64 i64 i64) (result i32)) + (func (import "wasix_64v1" "bus_subcall") (param i64 i64 i32 i64 i64 i64) (result i32)) + (func (import "wasix_64v1" "bus_poll") (param i64 i64 i32 i64) (result i32)) + (func (import "wasix_64v1" "call_reply") (param i64 i32 i64 i64) (result i32)) + (func (import "wasix_64v1" "call_fault") (param i64 i32) + (func (import "wasix_64v1" "call_close") (param i64) + (func (import "wasix_64v1" "ws_connect") (param i64 i64 i64) (result i32)) + (func (import "wasix_64v1" "http_request") (param i64 i64 i64 i64 i64 i64 i32 i64) (result i32)) + (func (import "wasix_64v1" "http_status") (param i32 i64) + (func (import "wasix_64v1" "port_bridge") (param i64 i64 i64 i64 i32) (result i32)) + (func (import "wasix_64v1" "port_unbridge") (result i32)) + (func (import "wasix_64v1" "port_dhcp_acquire") (result i32)) + (func (import "wasix_64v1" "port_addr_add") (param i64) (result i32)) + (func (import "wasix_64v1" "port_addr_remove") (param i64) (result i32)) + (func (import "wasix_64v1" "port_addr_clear") (result i32)) + (func (import "wasix_64v1" "port_mac") (param i64) (result i32)) + (func (import "wasix_64v1" "port_addr_list") (param i64 i64) (result i32)) + (func (import "wasix_64v1" "port_gateway_set") (param i64) (result i32)) + (func (import "wasix_64v1" "port_route_add") (param i64 i64 i64 i64) (result i32)) + (func (import "wasix_64v1" "port_route_remove") (param i64) (result i32)) + (func (import "wasix_64v1" "port_route_clear") (result i32)) + (func (import "wasix_64v1" "port_route_list") (param i64 i64) (result i32)) + (func (import "wasix_64v1" "sock_shutdown") (param i32 i32) (result i32)) + (func (import "wasix_64v1" "sock_status") (param i32 i64) (result i32)) + (func (import "wasix_64v1" "sock_addr_local") (param i32 i64) (result i32)) + (func (import "wasix_64v1" "sock_addr_peer") (param i32 i64) (result i32)) + (func (import "wasix_64v1" "sock_open") (param i32 i32 i32 i64) (result i32)) + (func (import "wasix_64v1" "sock_set_opt_flag") (param i32 i32 i32) (result i32)) + (func (import "wasix_64v1" "sock_get_opt_flag") (param i32 i32 i64) (result i32)) + (func (import "wasix_64v1" "sock_set_opt_time") (param i32 i32 i64) (result i32)) + (func (import "wasix_64v1" "sock_get_opt_time") (param i32 i32 i64) (result i32)) + (func (import "wasix_64v1" "sock_set_opt_size") (param i32 i32 i64) (result i32)) + (func (import "wasix_64v1" "sock_get_opt_size") (param i32 i32 i64) (result i32)) + (func (import "wasix_64v1" "sock_join_multicast_v4") (param i32 i64 i64) (result i32)) + (func (import "wasix_64v1" "sock_leave_multicast_v4") (param i32 i64 i64) (result i32)) + (func (import "wasix_64v1" "sock_join_multicast_v6") (param i32 i64 i32) (result i32)) + (func (import "wasix_64v1" "sock_leave_multicast_v6") (param i32 i64 i32) (result i32)) + (func (import "wasix_64v1" "sock_bind") (param i32 i64) (result i32)) + (func (import "wasix_64v1" "sock_listen") (param i32 i32) (result i32)) + (func (import "wasix_64v1" "sock_accept") (param i32 i32 i64 i64) (result i32)) + (func (import "wasix_64v1" "sock_connect") (param i32 i64) (result i32)) + (func (import "wasix_64v1" "sock_recv") (param i32 i64 i64 i32 i64 i64) (result i32)) + (func (import "wasix_64v1" "sock_recv_from") (param i32 i64 i64 i32 i64 i64 i64) (result i32)) + (func (import "wasix_64v1" "sock_send") (param i32 i64 i64 i32 i64) (result i32)) + (func (import "wasix_64v1" "sock_send_to") (param i32 i64 i64 i32 i64 i64) (result i32)) + (func (import "wasix_64v1" "sock_send_file") (param i32 i32 i64 i64 i64) (result i32)) + (func (import "wasix_64v1" "resolve") (param i64 i64 i32 i64 i32 i64) (result i32)) +) diff --git a/lib/wasi/wia/wasm_bus.txt b/lib/wasi/wia/wasm_bus.txt new file mode 100644 index 00000000000..64d0637e4e4 --- /dev/null +++ b/lib/wasi/wia/wasm_bus.txt @@ -0,0 +1,14 @@ +(interface "wasm-bus" + (func (import "wasm-bus" "wasm_bus_drop") (param i32) + (func (import "wasm-bus" "wasm_bus_handle") (result i32)) + (func (import "wasm-bus" "wasm_bus_listen") (param i32 i32) + (func (import "wasm-bus" "wasm_bus_callback") (param i32 i32 i32 i32) + (func (import "wasm-bus" "wasm_bus_fault") (param i32 i32) + (func (import "wasm-bus" "wasm_bus_poll") + (func (import "wasm-bus" "wasm_bus_fork") + (func (import "wasm-bus" "wasm_bus_reply") (param i32 i32 i32) + (func (import "wasm-bus" "wasm_bus_reply_callback") (param i32 i32 i32 i32 i32) + (func (import "wasm-bus" "wasm_bus_call") (param i32 i32 i32 i32 i32 i32 i32 i32 i32) (result i32)) + (func (import "wasm-bus" "wasm_bus_call_instance") (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) (result i32)) + (func (import "wasm-bus" "wasm_bus_thread_id") (result i32)) +) diff --git a/tests/compilers/issues.rs b/tests/compilers/issues.rs index e8d5dfb56a6..226085ce91f 100644 --- a/tests/compilers/issues.rs +++ b/tests/compilers/issues.rs @@ -25,7 +25,7 @@ fn issue_2329(mut config: crate::Config) -> Result<()> { } pub fn read_memory(mut ctx: FunctionEnvMut, guest_ptr: u32) -> u32 { - dbg!(ctx.data_mut().memory.as_ref()); + dbg!(ctx.data().memory.as_ref()); dbg!(guest_ptr); 0 } @@ -101,7 +101,7 @@ fn call_with_static_data_pointers(mut config: crate::Config) -> Result<()> { ) -> u64 { println!("{:?}", (a, b, c, d, e, f, g, h)); let mut buf = vec![0; d as usize]; - let memory = ctx.data_mut().memory.as_ref().unwrap().clone(); + let memory = ctx.data().memory.as_ref().unwrap().clone(); memory.view(&ctx).read(e, &mut buf).unwrap(); let input_string = std::str::from_utf8(&buf).unwrap(); assert_eq!(input_string, "bananapeach"); diff --git a/tests/compilers/typed_functions.rs b/tests/compilers/typed_functions.rs index c6c09b07272..e4b48af1913 100644 --- a/tests/compilers/typed_functions.rs +++ b/tests/compilers/typed_functions.rs @@ -307,7 +307,7 @@ fn static_host_function_with_env(config: crate::Config) -> anyhow::Result<()> { let mut store = config.store(); fn f(mut env: FunctionEnvMut, a: i32, b: i64, c: f32, d: f64) -> (f64, f32, i64, i32) { - let mut guard = env.data_mut().0.lock().unwrap(); + let mut guard = env.data().0.lock().unwrap(); assert_eq!(*guard, 100); *guard = 101; @@ -321,7 +321,7 @@ fn static_host_function_with_env(config: crate::Config) -> anyhow::Result<()> { c: f32, d: f64, ) -> Result<(f64, f32, i64, i32), Infallible> { - let mut guard = env.data_mut().0.lock().unwrap(); + let mut guard = env.data().0.lock().unwrap(); assert_eq!(*guard, 100); *guard = 101; @@ -446,7 +446,7 @@ fn dynamic_host_function_with_env(config: crate::Config) -> anyhow::Result<()> { ], ), |mut env, values| { - let mut guard = env.data_mut().0.lock().unwrap(); + let mut guard = env.data().0.lock().unwrap(); assert_eq!(*guard, 100); *guard = 101; diff --git a/tests/lib/wast/src/wasi_wast.rs b/tests/lib/wast/src/wasi_wast.rs index 6b2e13aac4c..cf956eec1d2 100644 --- a/tests/lib/wast/src/wasi_wast.rs +++ b/tests/lib/wast/src/wasi_wast.rs @@ -83,16 +83,16 @@ impl<'a> WasiTest<'a> { out }; let module = Module::new(store, &wasm_bytes)?; - let (env, _tempdirs, stdout_rx, stderr_rx) = + let (mut env, _tempdirs, stdout_rx, stderr_rx) = self.create_wasi_env(store, filesystem_kind)?; let imports = self.get_imports(store, &env.env, &module)?; let instance = Instance::new(&mut store, &module, &imports)?; - let start = instance.exports.get_function("_start")?; - let memory = instance.exports.get_memory("memory")?; - let wasi_env = env.data_mut(&mut store); - wasi_env.set_memory(memory.clone()); + env.initialize(&mut store, &instance).unwrap(); + let wasi_env = env.data(&store); + let start = instance.exports.get_function("_start")?; + if let Some(stdin) = &self.stdin { let state = wasi_env.state(); let mut wasi_stdin = state.stdin().unwrap().unwrap();