1 use crate::prelude::*; 2 use alloc::sync::Arc; 3 use core::ops::Range; 4 use wasmtime_fiber::{RuntimeFiberStack, RuntimeFiberStackCreator}; 5 6 /// A stack creator. Can be used to provide a stack creator to wasmtime 7 /// which supplies stacks for async support. 8 /// 9 /// # Safety 10 /// 11 /// This trait is unsafe, as memory safety depends on a proper implementation 12 /// of memory management. Stacks created by the StackCreator should always be 13 /// treated as owned by an wasmtime instance, and any modification of them 14 /// outside of wasmtime invoked routines is unsafe and may lead to corruption. 15 /// 16 /// Note that this is a relatively new and experimental feature and it is 17 /// recommended to be familiar with wasmtime runtime code to use it. 18 pub unsafe trait StackCreator: Send + Sync { 19 /// Create a new `StackMemory` object with the specified size. 20 /// 21 /// The `size` parameter is the expected size of the stack without any guard pages. 22 /// 23 /// The `zeroed` parameter is whether the stack's memory should be zeroed, 24 /// as a defense-in-depth measure. 25 /// 26 /// Note there should be at least one guard page of protected memory at the bottom 27 /// of the stack to catch potential stack overflow scenarios. Additionally, stacks should be 28 /// page aligned and zero filled. new_stack(&self, size: usize, zeroed: bool) -> Result<Box<dyn StackMemory>, Error>29 fn new_stack(&self, size: usize, zeroed: bool) -> Result<Box<dyn StackMemory>, Error>; 30 } 31 32 #[derive(Clone)] 33 pub(crate) struct StackCreatorProxy(pub Arc<dyn StackCreator>); 34 35 unsafe impl RuntimeFiberStackCreator for StackCreatorProxy { new_stack(&self, size: usize, zeroed: bool) -> Result<Box<dyn RuntimeFiberStack>, Error>36 fn new_stack(&self, size: usize, zeroed: bool) -> Result<Box<dyn RuntimeFiberStack>, Error> { 37 let stack = self.0.new_stack(size, zeroed)?; 38 Ok(Box::new(FiberStackProxy(stack)) as Box<dyn RuntimeFiberStack>) 39 } 40 } 41 42 /// A stack memory. This trait provides an interface for raw memory buffers 43 /// which are used by wasmtime inside of stacks which wasmtime executes 44 /// WebAssembly in for async support. By implementing this trait together 45 /// with StackCreator, one can supply wasmtime with custom allocated host 46 /// managed stacks. 47 /// 48 /// # Safety 49 /// 50 /// The memory should be page aligned and a multiple of page size. 51 /// To prevent possible silent overflows, the memory should be protected by a 52 /// guard page. Additionally the safety concerns explained in ['Memory'], for 53 /// accessing the memory apply here as well. 54 /// 55 /// Note that this is a relatively new and experimental feature and it is 56 /// recommended to be familiar with wasmtime runtime code to use it. 57 pub unsafe trait StackMemory: Send + Sync { 58 /// The top of the allocated stack. 59 /// 60 /// This address should be page aligned. top(&self) -> *mut u861 fn top(&self) -> *mut u8; 62 /// The range of where this stack resides in memory, excluding guard pages. range(&self) -> Range<usize>63 fn range(&self) -> Range<usize>; 64 /// The range of memory where the guard region of this stack resides. guard_range(&self) -> Range<*mut u8>65 fn guard_range(&self) -> Range<*mut u8>; 66 } 67 68 pub(crate) struct FiberStackProxy(pub Box<dyn StackMemory>); 69 70 unsafe impl RuntimeFiberStack for FiberStackProxy { top(&self) -> *mut u871 fn top(&self) -> *mut u8 { 72 self.0.top() 73 } 74 range(&self) -> Range<usize>75 fn range(&self) -> Range<usize> { 76 self.0.range() 77 } 78 guard_range(&self) -> Range<*mut u8>79 fn guard_range(&self) -> Range<*mut u8> { 80 self.0.guard_range() 81 } 82 } 83