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