1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/*
* setback.c - the ONLY translation unit that touches setjmp/longjmp.
*
* The caller-facing contract lives in `protect`/`recover` (lib.rs). This file
* only upholds the invariants that make setjmp/longjmp safe to drive from C:
*
* * setjmp() runs in C, never Rust, and only as a controlling
* expression (C11 7.13.1.1p4), its result is never stored.
* * Anything read after the jump is held in `volatile` temporaries, so longjmp
* cannot leave it in a clobbered caller-saved register.
* * longjmp() unwinds only this C frame back to its setjmp; the abandoned Rust
* frames above it are leaked by `protect`'s contract.
*/
/* Returned to Rust by setback_call: OK if the trampoline completed, RECOVERED
* if a longjmp came back. The cause code travels out of band in the Rust Mark. */
/* Stack reserved below the setjmp mark before the closure runs, so a fault
* handler has room to run `recover` on abandoned frames - see `protect`'s
* recovery-stack guarantee. Must equal RECOVERY_GAP_BYTES in lib.rs, multiple of 8. */
size_t
size_t
/*
* Run the closure with SETBACK_RECOVERY_GAP_BYTES reserved below the setjmp mark.
*
* Must be a separate noinline function: its frame (holding `gap`) is laid down
* when it is called, after setback_call armed the mark - that ordering is what
* puts the gap below the mark. `gap` is volatile and touched on both sides of
* the call so the reservation materializes and stays live (no tail call pops it
* early); the leading touch faults here, during setup, if headroom is already
* short on a platform with a stack monitor or guard page.
*/
static void
/*
* Arm the recovery mark, then call the Rust trampoline.
*
* jb : Rust-owned storage of >= setback_jmpbuf_size() bytes.
* tramp : extern "C" Rust fn running the closure.
* data : opaque payload threaded to the trampoline.
*
* Returns SETBACK_OK on completion, SETBACK_RECOVERED if a longjmp came back
* here. noinline so the Rust call site cannot be reordered in a way that defeats
* the returns_twice handling.
*/
int
void