wasmtime/runtime/
stack.rs

1use crate::prelude::*;
2use alloc::sync::Arc;
3use core::ops::Range;
4use 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.
18pub 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.
29    fn new_stack(&self, size: usize, zeroed: bool) -> Result<Box<dyn StackMemory>, Error>;
30}
31
32#[derive(Clone)]
33pub(crate) struct StackCreatorProxy(pub Arc<dyn StackCreator>);
34
35unsafe impl RuntimeFiberStackCreator for StackCreatorProxy {
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.
57pub unsafe trait StackMemory: Send + Sync {
58    /// The top of the allocated stack.
59    ///
60    /// This address should be page aligned.
61    fn top(&self) -> *mut u8;
62    /// The range of where this stack resides in memory, excluding guard pages.
63    fn range(&self) -> Range<usize>;
64    /// The range of memory where the guard region of this stack resides.
65    fn guard_range(&self) -> Range<*mut u8>;
66}
67
68pub(crate) struct FiberStackProxy(pub Box<dyn StackMemory>);
69
70unsafe impl RuntimeFiberStack for FiberStackProxy {
71    fn top(&self) -> *mut u8 {
72        self.0.top()
73    }
74
75    fn range(&self) -> Range<usize> {
76        self.0.range()
77    }
78
79    fn guard_range(&self) -> Range<*mut u8> {
80        self.0.guard_range()
81    }
82}