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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
//! What a guest module may spend: the time of one call and the memory of its
//! instance.
//!
//! **Time.** A call to a guest gets, by default, the time left in the step
//! that makes it ([`Engine::set_step_budget`]), so the guest calls of one step
//! cannot together outlast it; a call made outside any step gets
//! [`DEFAULT_CALL_BUDGET`]. A module's [`GuestLimits::call_budget`] tightens
//! the step's, and outside a step replaces the default. A guest still
//! running at its deadline is interrupted: a thread advances an epoch counter
//! every [`EPOCH`], and at each tick a running guest's store compares its
//! deadline with the wall clock, so a call is interrupted at the first tick
//! past its deadline, never before it. Time a guest spends in a host
//! function, a WASI wait or a call to another module, is not interrupted:
//! the guest is, once the host function returns. Its call fails with
//! [`DispatchError::Trap`], naming the module, the function and the budget,
//! and the module refuses its later calls until it is reloaded: an
//! interrupted call can leave its state half updated.
//!
//! At a device's 15 Hz, one step's guest calls share 66.7 ms; at 60 Hz,
//! 16.7 ms. Loading a module (its `_initialize`, a component's `functions`)
//! runs under [`DEFAULT_CALL_BUDGET`].
//!
//! A call with no time left before its deadline is not made: it fails
//! with [`DispatchError::Trap`], and its module, never entered, serves its
//! later calls, rather than refusing them for a deadline another call used
//! up.
//!
//! A guest's call to another guest ends by its caller's deadline, a guest
//! loading counting as a call to its callees. A module called back while its
//! call is under way ends by that call's deadline, or its caller's if
//! earlier: the call under way is never extended. A caller whose callee ran
//! past the caller's deadline is interrupted once the call returns.
//!
//! **Memory.** Each linear memory of a guest's instance may hold up to
//! [`GuestLimits::memory`] bytes, [`DEFAULT_MEMORY`] by default: a
//! `memory.grow` past it fails inside the guest, which sees the grow return
//! -1, and the host grows nothing. A core module has one memory; a component
//! can hold several, each under the cap.
//!
//! **In the browser** a guest runs on the JS thread, which nothing
//! interrupts: the browser executors bound neither a call's time nor, beyond
//! the maximum a module's memory declares, its memory.
//!
//! [`Engine::set_step_budget`]: crate::engine::Engine::set_step_budget
//! [`DispatchError::Trap`]: crate::module::DispatchError::Trap
use Duration;
/// The time a call to a guest gets when no step bounds it: a call made
/// outside a device's step, or a module loading.
pub const DEFAULT_CALL_BUDGET: Duration = from_secs;
/// The linear memory a guest's instance may hold unless its module says
/// otherwise: 256 MiB.
pub const DEFAULT_MEMORY: usize = 256 << 20;
/// How often a running guest's deadline is checked: a call overruns its
/// deadline by about this much, as the thread advancing the epoch is
/// scheduled.
pub const EPOCH: Duration = from_millis;
/// What one guest module may spend.
/// Bound the calls into `store` by the deadline `deadline_of` reads from its
/// data, which [`Module::set_call_deadline`](crate::module::Module::set_call_deadline)
/// sets before each call. At each tick of the engine's epoch, the store's
/// callback compares the deadline with the wall clock: a call is interrupted
/// at the first tick past its deadline, never before it, whatever ticks the
/// counter has or has not made.
pub
/// What a store does at a tick of its engine's epoch, at `now`, to end its
/// call by `deadline`: interrupt it once the deadline has passed, else check
/// again at the next tick.
/// Advance `engine`'s epoch every [`EPOCH`], from a thread of its own, for the
/// life of the process. Called once per wasmtime engine, when it is created.
pub
/// The message of a call not made because no time was left before its
/// deadline: the step's guest calls, or its caller, used it up.
pub
/// The message of a call interrupted at its deadline.
pub