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 /// Note there should be at least one guard page of protected memory at the bottom 24 /// of the stack to catch potential stack overflow scenarios. Additionally, stacks should be 25 /// page aligned and zero filled. 26 fn new_stack(&self, size: usize) -> Result<Box<dyn StackMemory>, Error>; 27 } 28 29 #[derive(Clone)] 30 pub(crate) struct StackCreatorProxy(pub Arc<dyn StackCreator>); 31 32 unsafe impl RuntimeFiberStackCreator for StackCreatorProxy { 33 fn new_stack(&self, size: usize) -> Result<Box<dyn RuntimeFiberStack>, Error> { 34 let stack = self.0.new_stack(size)?; 35 Ok(Box::new(FiberStackProxy(stack)) as Box<dyn RuntimeFiberStack>) 36 } 37 } 38 39 /// A stack memory. This trait provides an interface for raw memory buffers 40 /// which are used by wasmtime inside of stacks which wasmtime executes 41 /// WebAssembly in for async support. By implementing this trait together 42 /// with StackCreator, one can supply wasmtime with custom allocated host 43 /// managed stacks. 44 /// 45 /// # Safety 46 /// 47 /// The memory should be page aligned and a multiple of page size. 48 /// To prevent possible silent overflows, the memory should be protected by a 49 /// guard page. Additionally the safety concerns explained in ['Memory'], for 50 /// accessing the memory apply here as well. 51 /// 52 /// Note that this is a relatively new and experimental feature and it is 53 /// recommended to be familiar with wasmtime runtime code to use it. 54 pub unsafe trait StackMemory: Send + Sync { 55 /// The top of the allocated stack. 56 /// 57 /// This address should be page aligned. 58 fn top(&self) -> *mut u8; 59 /// The range of where this stack resides in memory, excluding guard pages. 60 fn range(&self) -> Range<usize>; 61 /// The range of memory where the guard region of this stack resides. 62 fn guard_range(&self) -> Range<*mut u8>; 63 } 64 65 pub(crate) struct FiberStackProxy(pub Box<dyn StackMemory>); 66 67 unsafe impl RuntimeFiberStack for FiberStackProxy { 68 fn top(&self) -> *mut u8 { 69 self.0.top() 70 } 71 72 fn range(&self) -> Range<usize> { 73 self.0.range() 74 } 75 76 fn guard_range(&self) -> Range<*mut u8> { 77 self.0.guard_range() 78 } 79 } 80