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