1 /**
2  * \file wasmtime/async.h
3  *
4  * \brief Wasmtime async functionality
5  *
6  * Async functionality in Wasmtime is well documented here:
7  * https://docs.wasmtime.dev/api/wasmtime/#async
8  *
9  * All WebAssembly executes synchronously, but an async support enables the Wasm
10  * code be executed on a separate stack, so it can be paused and resumed. There
11  * are three mechanisms for yielding control from wasm to the caller: fuel,
12  * epochs, and async host functions.
13  *
14  * When WebAssembly is executed, a `wasmtime_call_future_t` is returned. This
15  * struct represents the state of the execution and each call to
16  * `wasmtime_call_future_poll` will execute the WebAssembly code on a separate
17  * stack until the function returns or yields control back to the caller.
18  *
19  * It's expected these futures are pulled in a loop until completed, at which
20  * point the future should be deleted. Functions that return a
21  * `wasmtime_call_future_t` are special in that all parameters to that function
22  * should not be modified in any way and must be kept alive until the future is
23  * deleted. This includes concurrent calls for a single store - another function
24  * on a store should not be called while there is a `wasmtime_call_future_t`
25  * alive.
26  *
27  * As for asynchronous host calls - the reverse contract is upheld. Wasmtime
28  * will keep all parameters to the function alive and unmodified until the
29  * `wasmtime_func_async_continuation_callback_t` returns true.
30  *
31  */
32 
33 #ifndef WASMTIME_ASYNC_H
34 #define WASMTIME_ASYNC_H
35 
36 #include <wasm.h>
37 #include <wasmtime/conf.h>
38 #include <wasmtime/config.h>
39 #include <wasmtime/error.h>
40 #include <wasmtime/func.h>
41 #include <wasmtime/linker.h>
42 #include <wasmtime/store.h>
43 
44 #ifdef WASMTIME_FEATURE_ASYNC
45 
46 #ifdef __cplusplus
47 extern "C" {
48 #endif
49 
50 /**
51  * \brief Configures the size of the stacks used for asynchronous execution.
52  *
53  * This setting configures the size of the stacks that are allocated for
54  * asynchronous execution.
55  *
56  * The value cannot be less than max_wasm_stack.
57  *
58  * The amount of stack space guaranteed for host functions is async_stack_size -
59  * max_wasm_stack, so take care not to set these two values close to one
60  * another; doing so may cause host functions to overflow the stack and abort
61  * the process.
62  *
63  * By default this option is 2 MiB.
64  *
65  * For more information see the Rust documentation at
66  * https://docs.wasmtime.dev/api/wasmtime/struct.Config.html#method.async_stack_size
67  */
68 WASMTIME_CONFIG_PROP(void, async_stack_size, uint64_t)
69 
70 /**
71  * \brief Configures a Store to yield execution of async WebAssembly code
72  * periodically.
73  *
74  * When a Store is configured to consume fuel with
75  * `wasmtime_config_consume_fuel` this method will configure what happens when
76  * fuel runs out. Specifically executing WebAssembly will be suspended and
77  * control will be yielded back to the caller.
78  *
79  * This is only suitable with use of a store associated with an async config
80  * because only then are futures used and yields are possible.
81  *
82  * \param context the context for the store to configure.
83  * \param interval the amount of fuel at which to yield. A value of 0 will
84  *        disable yielding.
85  */
86 WASM_API_EXTERN wasmtime_error_t *
87 wasmtime_context_fuel_async_yield_interval(wasmtime_context_t *context,
88                                            uint64_t interval);
89 
90 /**
91  * \brief Configures epoch-deadline expiration to yield to the async caller and
92  * the update the deadline.
93  *
94  * This is only suitable with use of a store associated with an async config
95  * because only then are futures used and yields are possible.
96  *
97  * See the Rust documentation for more:
98  * https://docs.wasmtime.dev/api/wasmtime/struct.Store.html#method.epoch_deadline_async_yield_and_update
99  */
100 WASM_API_EXTERN wasmtime_error_t *
101 wasmtime_context_epoch_deadline_async_yield_and_update(
102     wasmtime_context_t *context, uint64_t delta);
103 
104 /**
105  * The callback to determine a continuation's current state.
106  *
107  * Return true if the host call has completed, otherwise false will
108  * continue to yield WebAssembly execution.
109  */
110 typedef bool (*wasmtime_func_async_continuation_callback_t)(void *env);
111 
112 /**
113  * A continuation for the current state of the host function's execution.
114  */
115 typedef struct wasmtime_async_continuation_t {
116   /// Callback for if the async function has completed.
117   wasmtime_func_async_continuation_callback_t callback;
118   /// User-provided argument to pass to the callback.
119   void *env;
120   /// A finalizer for the user-provided *env
121   void (*finalizer)(void *);
122 } wasmtime_async_continuation_t;
123 
124 /**
125  * \brief Callback signature for #wasmtime_linker_define_async_func.
126  *
127  * This is a host function that returns a continuation to be called later.
128  *
129  * All the arguments to this function will be kept alive until the continuation
130  * returns that it has errored or has completed.
131  *
132  * \param env user-provided argument passed to
133  *        #wasmtime_linker_define_async_func
134  * \param caller a temporary object that can only be used during this function
135  *        call. Used to acquire #wasmtime_context_t or caller's state
136  * \param args the arguments provided to this function invocation
137  * \param nargs how many arguments are provided
138  * \param results where to write the results of this function
139  * \param nresults how many results must be produced
140  * \param trap_ret if assigned a not `NULL` value then the called
141  *        function will trap with the returned error. Note that ownership of
142  *        trap is transferred to wasmtime.
143  * \param continuation_ret the returned continuation
144  *        that determines when the async function has completed executing.
145  *
146  * Only supported for async stores.
147  *
148  * See #wasmtime_func_callback_t for more information.
149  */
150 typedef void (*wasmtime_func_async_callback_t)(
151     void *env, wasmtime_caller_t *caller, const wasmtime_val_t *args,
152     size_t nargs, wasmtime_val_t *results, size_t nresults,
153     wasm_trap_t **trap_ret, wasmtime_async_continuation_t *continuation_ret);
154 
155 /**
156  * \brief The structure representing a asynchronously running function.
157  *
158  * This structure is always owned by the caller and must be deleted using
159  * #wasmtime_call_future_delete.
160  *
161  * Functions that return this type require that the parameters to the function
162  * are unmodified until this future is destroyed.
163  */
164 typedef struct wasmtime_call_future wasmtime_call_future_t;
165 
166 /**
167  * \brief Executes WebAssembly in the function.
168  *
169  * Returns true if the function call has completed. After this function returns
170  * true, it should *not* be called again for a given future.
171  *
172  * This function returns false if execution has yielded either due to being out
173  * of fuel (see wasmtime_context_fuel_async_yield_interval), or the epoch has
174  * been incremented enough (see
175  * wasmtime_context_epoch_deadline_async_yield_and_update). The function may
176  * also return false if asynchronous host functions have been called, which then
177  * calling this  function will call the continuation from the async host
178  * function.
179  *
180  * For more see the information at
181  * https://docs.wasmtime.dev/api/wasmtime/struct.Config.html#asynchronous-wasm
182  *
183  */
184 WASM_API_EXTERN bool wasmtime_call_future_poll(wasmtime_call_future_t *future);
185 
186 /**
187  * /brief Frees the underlying memory for a future.
188  *
189  * All wasmtime_call_future_t are owned by the caller and should be deleted
190  * using this function.
191  */
192 WASM_API_EXTERN void
193 wasmtime_call_future_delete(wasmtime_call_future_t *future);
194 
195 /**
196  * \brief Invokes this function with the params given, returning the results
197  * asynchronously.
198  *
199  * This function is the same as wasmtime_func_call except that it is
200  * asynchronous. This is only compatible with stores associated with an
201  * asynchronous config.
202  *
203  * The result is a future that is owned by the caller and must be deleted via
204  * #wasmtime_call_future_delete.
205  *
206  * The `args` and `results` pointers may be `NULL` if the corresponding length
207  * is zero. The `trap_ret` and `error_ret` pointers may *not* be `NULL`.
208  *
209  * Does not take ownership of #wasmtime_val_t arguments or #wasmtime_val_t
210  * results, and all parameters to this function must be kept alive and not
211  * modified until the returned #wasmtime_call_future_t is deleted. This includes
212  * the context and store parameters. Only a single future can be alive for a
213  * given store at a single time (meaning only call this function after the
214  * previous call's future was deleted).
215  *
216  * See the header documentation for for more information.
217  *
218  * For more information see the Rust documentation at
219  * https://docs.wasmtime.dev/api/wasmtime/struct.Func.html#method.call_async
220  */
221 WASM_API_EXTERN wasmtime_call_future_t *wasmtime_func_call_async(
222     wasmtime_context_t *context, const wasmtime_func_t *func,
223     const wasmtime_val_t *args, size_t nargs, wasmtime_val_t *results,
224     size_t nresults, wasm_trap_t **trap_ret, wasmtime_error_t **error_ret);
225 
226 /**
227  * \brief Defines a new async function in this linker.
228  *
229  * This function behaves similar to #wasmtime_linker_define_func, except it
230  * supports async callbacks.
231  *
232  * The callback `cb` will be invoked on another stack (fiber for Windows).
233  */
234 WASM_API_EXTERN wasmtime_error_t *wasmtime_linker_define_async_func(
235     wasmtime_linker_t *linker, const char *module, size_t module_len,
236     const char *name, size_t name_len, const wasm_functype_t *ty,
237     wasmtime_func_async_callback_t cb, void *data, void (*finalizer)(void *));
238 
239 /**
240  * \brief Instantiates a #wasm_module_t with the items defined in this linker
241  * for an async store.
242  *
243  * This is the same as #wasmtime_linker_instantiate but used for async stores
244  * (which requires functions are called asynchronously). The returning
245  * #wasmtime_call_future_t must be polled using #wasmtime_call_future_poll, and
246  * is owned and must be deleted using #wasmtime_call_future_delete.
247  *
248  * The `trap_ret` and `error_ret` pointers may *not* be `NULL` and the returned
249  * memory is owned by the caller.
250  *
251  * All arguments to this function must outlive the returned future and be
252  * unmodified until the future is deleted.
253  */
254 WASM_API_EXTERN wasmtime_call_future_t *wasmtime_linker_instantiate_async(
255     const wasmtime_linker_t *linker, wasmtime_context_t *store,
256     const wasmtime_module_t *module, wasmtime_instance_t *instance,
257     wasm_trap_t **trap_ret, wasmtime_error_t **error_ret);
258 
259 /**
260  * \brief Instantiates instance within the given store.
261  *
262  * This will also run the function's startup function, if there is one.
263  *
264  * For more information on async instantiation see
265  * #wasmtime_linker_instantiate_async.
266  *
267  * \param instance_pre the pre-initialized instance
268  * \param store the store in which to create the instance
269  * \param instance where to store the returned instance
270  * \param trap_ret where to store the returned trap
271  * \param error_ret where to store the returned trap
272  *
273  * The `trap_ret` and `error_ret` pointers may *not* be `NULL` and the returned
274  * memory is owned by the caller.
275  *
276  * All arguments to this function must outlive the returned future and be
277  * unmodified until the future is deleted.
278  */
279 WASM_API_EXTERN wasmtime_call_future_t *wasmtime_instance_pre_instantiate_async(
280     const wasmtime_instance_pre_t *instance_pre, wasmtime_context_t *store,
281     wasmtime_instance_t *instance, wasm_trap_t **trap_ret,
282     wasmtime_error_t **error_ret);
283 
284 /**
285  * A callback to get the top of the stack address and the length of the stack,
286  * excluding guard pages.
287  *
288  * For more information about the parameters see the Rust documentation at
289  * https://docs.wasmtime.dev/api/wasmtime/trait.StackMemory.html
290  */
291 typedef uint8_t *(*wasmtime_stack_memory_get_callback_t)(void *env,
292                                                          size_t *out_len);
293 
294 /**
295  * A Stack instance created from a #wasmtime_new_stack_memory_callback_t.
296  *
297  * For more information see the Rust documentation at
298  * https://docs.wasmtime.dev/api/wasmtime/trait.StackMemory.html
299  */
300 typedef struct {
301   /// User provided value to be passed to get_memory and grow_memory
302   void *env;
303   /// Callback to get the memory and size of this LinearMemory
304   wasmtime_stack_memory_get_callback_t get_stack_memory;
305   /// An optional finalizer for env
306   void (*finalizer)(void *);
307 } wasmtime_stack_memory_t;
308 
309 /**
310  * A callback to create a new StackMemory from the specified parameters.
311  *
312  * The result should be written to `stack_ret` and wasmtime will own the values
313  * written into that struct.
314  *
315  * This callback must be thread-safe.
316  *
317  * For more information about the parameters see the Rust documentation at
318  * https://docs.wasmtime.dev/api/wasmtime/trait.StackCreator.html#tymethod.new_stack
319  */
320 typedef wasmtime_error_t *(*wasmtime_new_stack_memory_callback_t)(
321     void *env, size_t size, bool zeroed, wasmtime_stack_memory_t *stack_ret);
322 
323 /**
324  * A representation of custom stack creator.
325  *
326  * For more information see the Rust documentation at
327  * https://docs.wasmtime.dev/api/wasmtime/trait.StackCreator.html
328  */
329 typedef struct {
330   /// User provided value to be passed to new_stack
331   void *env;
332   /// The callback to create a new stack, must be thread safe
333   wasmtime_new_stack_memory_callback_t new_stack;
334   /// An optional finalizer for env.
335   void (*finalizer)(void *);
336 } wasmtime_stack_creator_t;
337 
338 /**
339  * Sets a custom stack creator.
340  *
341  * Custom memory creators are used when creating creating async instance stacks
342  * for the on-demand instance allocation strategy.
343  *
344  * The config does **not** take ownership of the #wasmtime_stack_creator_t
345  * passed in, but instead copies all the values in the struct.
346  *
347  * For more information see the Rust documentation at
348  * https://docs.wasmtime.dev/api/wasmtime/struct.Config.html#method.with_host_stack
349  */
350 WASM_API_EXTERN void
351 wasmtime_config_host_stack_creator_set(wasm_config_t *,
352                                        wasmtime_stack_creator_t *);
353 
354 #ifdef __cplusplus
355 } // extern "C"
356 #endif
357 
358 #endif // WASMTIME_FEATURE_ASYNC
359 
360 #endif // WASMTIME_ASYNC_H
361