dusk_wasmtime/runtime/stack.rs
1use std::{ops::Range, sync::Arc};
2
3use anyhow::Error;
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 /// 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)]
30pub(crate) struct StackCreatorProxy(pub Arc<dyn StackCreator>);
31
32unsafe 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.
54pub 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}
62
63pub(crate) struct FiberStackProxy(pub Box<dyn StackMemory>);
64
65unsafe impl RuntimeFiberStack for FiberStackProxy {
66 fn top(&self) -> *mut u8 {
67 self.0.top()
68 }
69
70 fn range(&self) -> Range<usize> {
71 self.0.range()
72 }
73}