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