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