1#![no_std]
4#![feature(naked_functions)]
5#![deny(warnings, missing_docs)]
6
7mod entire;
8mod fast;
9mod hal;
10
11pub use entire::*;
12pub use fast::*;
13pub use hal::{FlowContext, load_direct_trap_entry, reuse_stack_for_trap, soft_trap, trap_entry};
14
15use core::{
16 alloc::Layout,
17 marker::PhantomPinned,
18 mem::{MaybeUninit, align_of, forget},
19 ops::Range,
20 ptr::NonNull,
21};
22
23pub struct FreeTrapStack(NonNull<TrapHandler>);
25
26pub struct LoadedTrapStack(usize);
28
29#[derive(Debug)]
31pub struct IllegalStack;
32
33impl FreeTrapStack {
34 pub fn new(
36 range: Range<usize>,
37 drop: fn(Range<usize>),
38
39 context_ptr: NonNull<FlowContext>,
40 fast_handler: FastHandler,
41 ) -> Result<Self, IllegalStack> {
42 const LAYOUT: Layout = Layout::new::<TrapHandler>();
43 let bottom = range.start;
44 let top = range.end;
45 let ptr = (top - LAYOUT.size()) & !(LAYOUT.align() - 1);
46 if ptr >= bottom {
47 let handler = unsafe { &mut *(ptr as *mut TrapHandler) };
48 handler.range = range;
49 handler.drop = drop;
50 handler.context = context_ptr;
51 handler.fast_handler = fast_handler;
52 Ok(Self(unsafe { NonNull::new_unchecked(handler) }))
53 } else {
54 Err(IllegalStack)
55 }
56 }
57
58 #[inline]
60 pub fn load(self) -> LoadedTrapStack {
61 let scratch = hal::exchange_scratch(self.0.as_ptr() as _);
62 forget(self);
63 LoadedTrapStack(scratch)
64 }
65}
66
67impl Drop for FreeTrapStack {
68 #[inline]
69 fn drop(&mut self) {
70 unsafe {
71 let handler = self.0.as_ref();
72 (handler.drop)(handler.range.clone());
73 }
74 }
75}
76
77impl LoadedTrapStack {
78 #[inline]
80 pub const fn val(&self) -> usize {
81 self.0
82 }
83
84 #[inline]
86 pub fn unload(self) -> FreeTrapStack {
87 let ans = unsafe { self.unload_unchecked() };
88 forget(self);
89 ans
90 }
91
92 #[inline]
98 unsafe fn unload_unchecked(&self) -> FreeTrapStack {
99 let ptr = hal::exchange_scratch(self.0) as *mut TrapHandler;
100 let handler = unsafe { NonNull::new_unchecked(ptr) };
101 FreeTrapStack(handler)
102 }
103}
104
105impl Drop for LoadedTrapStack {
106 #[inline]
107 fn drop(&mut self) {
108 drop(unsafe { self.unload_unchecked() })
109 }
110}
111
112#[repr(C)]
114struct TrapHandler {
115 context: NonNull<FlowContext>,
126 fast_handler: FastHandler,
130 scratch: usize,
135
136 range: Range<usize>,
137 drop: fn(Range<usize>),
138
139 pinned: PhantomPinned,
143}
144
145impl TrapHandler {
146 #[inline]
149 fn locate_fast_mail<T>(&mut self) -> *mut MaybeUninit<T> {
150 let top = self.range.end as *mut u8;
151 let offset = top.align_offset(align_of::<T>());
152 unsafe { &mut *top.add(offset).cast() }
153 }
154}