xref: /wasmtime-44.0.1/crates/c-api/src/async.rs (revision cc8d04f4)
137cf8e1eSTyler Rockwood use std::ffi::c_void;
237cf8e1eSTyler Rockwood use std::future::Future;
337cf8e1eSTyler Rockwood use std::mem::{self, MaybeUninit};
485c0a2dfSTyler Rockwood use std::num::NonZeroU64;
5e6ff8411STyler Rockwood use std::ops::Range;
637cf8e1eSTyler Rockwood use std::pin::Pin;
7e6ff8411STyler Rockwood use std::sync::Arc;
8*d41b0a71SAlex Crichton use std::task::{Context, Poll, Waker};
937cf8e1eSTyler Rockwood use std::{ptr, str};
109187f2d9SAlex Crichton use wasmtime::{
119187f2d9SAlex Crichton     AsContextMut, Func, Instance, Result, RootScope, StackCreator, StackMemory, Trap, Val,
129187f2d9SAlex Crichton };
1337cf8e1eSTyler Rockwood 
1437cf8e1eSTyler Rockwood use crate::{
1590ac295eSAlex Crichton     WASMTIME_I32, WasmtimeCaller, WasmtimeStoreContextMut, bad_utf8, handle_result, to_str,
1690ac295eSAlex Crichton     translate_args, wasm_config_t, wasm_functype_t, wasm_trap_t, wasmtime_caller_t,
1790ac295eSAlex Crichton     wasmtime_error_t, wasmtime_instance_pre_t, wasmtime_linker_t, wasmtime_module_t,
1890ac295eSAlex Crichton     wasmtime_val_t, wasmtime_val_union,
1937cf8e1eSTyler Rockwood };
2037cf8e1eSTyler Rockwood 
21ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasmtime_config_async_stack_size_set(c: &mut wasm_config_t, size: usize)2237cf8e1eSTyler Rockwood pub extern "C" fn wasmtime_config_async_stack_size_set(c: &mut wasm_config_t, size: usize) {
2337cf8e1eSTyler Rockwood     c.config.async_stack_size(size);
2437cf8e1eSTyler Rockwood }
2537cf8e1eSTyler Rockwood 
26ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasmtime_context_epoch_deadline_async_yield_and_update( mut store: WasmtimeStoreContextMut<'_>, delta: u64, )2737cf8e1eSTyler Rockwood pub extern "C" fn wasmtime_context_epoch_deadline_async_yield_and_update(
28420fc3d1SNick Fitzgerald     mut store: WasmtimeStoreContextMut<'_>,
2937cf8e1eSTyler Rockwood     delta: u64,
3037cf8e1eSTyler Rockwood ) {
3137cf8e1eSTyler Rockwood     store.epoch_deadline_async_yield_and_update(delta);
3237cf8e1eSTyler Rockwood }
3337cf8e1eSTyler Rockwood 
34ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasmtime_context_fuel_async_yield_interval( mut store: WasmtimeStoreContextMut<'_>, interval: Option<NonZeroU64>, ) -> Option<Box<wasmtime_error_t>>3585c0a2dfSTyler Rockwood pub extern "C" fn wasmtime_context_fuel_async_yield_interval(
36420fc3d1SNick Fitzgerald     mut store: WasmtimeStoreContextMut<'_>,
3785c0a2dfSTyler Rockwood     interval: Option<NonZeroU64>,
3885c0a2dfSTyler Rockwood ) -> Option<Box<wasmtime_error_t>> {
3985c0a2dfSTyler Rockwood     handle_result(
4085c0a2dfSTyler Rockwood         store.fuel_async_yield_interval(interval.map(|n| n.get())),
4185c0a2dfSTyler Rockwood         |()| {},
4285c0a2dfSTyler Rockwood     )
4337cf8e1eSTyler Rockwood }
4437cf8e1eSTyler Rockwood 
4537cf8e1eSTyler Rockwood pub type wasmtime_func_async_callback_t = extern "C" fn(
4637cf8e1eSTyler Rockwood     *mut c_void,
4737cf8e1eSTyler Rockwood     *mut wasmtime_caller_t,
4837cf8e1eSTyler Rockwood     *const wasmtime_val_t,
4937cf8e1eSTyler Rockwood     usize,
5037cf8e1eSTyler Rockwood     *mut wasmtime_val_t,
5137cf8e1eSTyler Rockwood     usize,
5237cf8e1eSTyler Rockwood     &mut Option<Box<wasm_trap_t>>,
5337cf8e1eSTyler Rockwood     &mut wasmtime_async_continuation_t,
5437cf8e1eSTyler Rockwood );
5537cf8e1eSTyler Rockwood 
5637cf8e1eSTyler Rockwood #[repr(C)]
5737cf8e1eSTyler Rockwood pub struct wasmtime_async_continuation_t {
5837cf8e1eSTyler Rockwood     pub callback: wasmtime_func_async_continuation_callback_t,
5937cf8e1eSTyler Rockwood     pub env: *mut c_void,
6037cf8e1eSTyler Rockwood     pub finalizer: Option<extern "C" fn(*mut c_void)>,
6137cf8e1eSTyler Rockwood }
6237cf8e1eSTyler Rockwood 
6337cf8e1eSTyler Rockwood unsafe impl Send for wasmtime_async_continuation_t {}
6437cf8e1eSTyler Rockwood unsafe impl Sync for wasmtime_async_continuation_t {}
6537cf8e1eSTyler Rockwood impl Drop for wasmtime_async_continuation_t {
drop(&mut self)6637cf8e1eSTyler Rockwood     fn drop(&mut self) {
6737cf8e1eSTyler Rockwood         if let Some(f) = self.finalizer {
6837cf8e1eSTyler Rockwood             f(self.env);
6937cf8e1eSTyler Rockwood         }
7037cf8e1eSTyler Rockwood     }
7137cf8e1eSTyler Rockwood }
7237cf8e1eSTyler Rockwood impl Future for wasmtime_async_continuation_t {
7337cf8e1eSTyler Rockwood     type Output = ();
poll(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Self::Output>7437cf8e1eSTyler Rockwood     fn poll(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Self::Output> {
7537cf8e1eSTyler Rockwood         let this = self.get_mut();
7637cf8e1eSTyler Rockwood         let cb = this.callback;
7737cf8e1eSTyler Rockwood         if cb(this.env) {
7837cf8e1eSTyler Rockwood             Poll::Ready(())
7937cf8e1eSTyler Rockwood         } else {
8037cf8e1eSTyler Rockwood             Poll::Pending
8137cf8e1eSTyler Rockwood         }
8237cf8e1eSTyler Rockwood     }
8337cf8e1eSTyler Rockwood }
8437cf8e1eSTyler Rockwood 
8528fd6bf3STyler Rockwood /// Internal structure to add Send/Sync to a c_void member.
8628fd6bf3STyler Rockwood ///
8728fd6bf3STyler Rockwood /// This is useful in closures that need to capture some C data.
8828fd6bf3STyler Rockwood #[derive(Debug)]
8928fd6bf3STyler Rockwood struct CallbackDataPtr {
9028fd6bf3STyler Rockwood     pub ptr: *mut std::ffi::c_void,
9137cf8e1eSTyler Rockwood }
9228fd6bf3STyler Rockwood 
9328fd6bf3STyler Rockwood unsafe impl Send for CallbackDataPtr {}
9428fd6bf3STyler Rockwood unsafe impl Sync for CallbackDataPtr {}
9528fd6bf3STyler Rockwood 
9628fd6bf3STyler Rockwood pub type wasmtime_func_async_continuation_callback_t = extern "C" fn(*mut c_void) -> bool;
9737cf8e1eSTyler Rockwood 
invoke_c_async_callback<'a>( cb: wasmtime_func_async_callback_t, data: CallbackDataPtr, mut caller: WasmtimeCaller<'a>, params: &'a [Val], results: &'a mut [Val], ) -> Result<()>9837cf8e1eSTyler Rockwood async fn invoke_c_async_callback<'a>(
9937cf8e1eSTyler Rockwood     cb: wasmtime_func_async_callback_t,
10028fd6bf3STyler Rockwood     data: CallbackDataPtr,
101420fc3d1SNick Fitzgerald     mut caller: WasmtimeCaller<'a>,
10237cf8e1eSTyler Rockwood     params: &'a [Val],
10337cf8e1eSTyler Rockwood     results: &'a mut [Val],
10437cf8e1eSTyler Rockwood ) -> Result<()> {
10537cf8e1eSTyler Rockwood     // Convert `params/results` to `wasmtime_val_t`. Use the previous
10637cf8e1eSTyler Rockwood     // storage in `hostcall_val_storage` to help avoid allocations all the
10737cf8e1eSTyler Rockwood     // time.
10837cf8e1eSTyler Rockwood     let mut hostcall_val_storage = mem::take(&mut caller.data_mut().hostcall_val_storage);
10937cf8e1eSTyler Rockwood     debug_assert!(hostcall_val_storage.is_empty());
11037cf8e1eSTyler Rockwood     hostcall_val_storage.reserve(params.len() + results.len());
111bd2ea901SNick Fitzgerald     hostcall_val_storage.extend(
112bd2ea901SNick Fitzgerald         params
113bd2ea901SNick Fitzgerald             .iter()
114bd2ea901SNick Fitzgerald             .cloned()
1159187f2d9SAlex Crichton             .map(|p| wasmtime_val_t::from_val_unscoped(&mut caller, p)),
116bd2ea901SNick Fitzgerald     );
11737cf8e1eSTyler Rockwood     hostcall_val_storage.extend((0..results.len()).map(|_| wasmtime_val_t {
11837cf8e1eSTyler Rockwood         kind: WASMTIME_I32,
11937cf8e1eSTyler Rockwood         of: wasmtime_val_union { i32: 0 },
12037cf8e1eSTyler Rockwood     }));
12137cf8e1eSTyler Rockwood     let (params, out_results) = hostcall_val_storage.split_at_mut(params.len());
12237cf8e1eSTyler Rockwood 
12337cf8e1eSTyler Rockwood     // Invoke the C function pointer.
124e2664e55SBruce Mitchener     // The result will be a continuation which we will wrap in a Future.
12537cf8e1eSTyler Rockwood     let mut caller = wasmtime_caller_t { caller };
12637cf8e1eSTyler Rockwood     let mut trap = None;
12737cf8e1eSTyler Rockwood     extern "C" fn panic_callback(_: *mut c_void) -> bool {
12837cf8e1eSTyler Rockwood         panic!("callback must be set")
12937cf8e1eSTyler Rockwood     }
13037cf8e1eSTyler Rockwood     let mut continuation = wasmtime_async_continuation_t {
13137cf8e1eSTyler Rockwood         callback: panic_callback,
13237cf8e1eSTyler Rockwood         env: ptr::null_mut(),
13337cf8e1eSTyler Rockwood         finalizer: None,
13437cf8e1eSTyler Rockwood     };
13537cf8e1eSTyler Rockwood     cb(
13628fd6bf3STyler Rockwood         data.ptr,
13737cf8e1eSTyler Rockwood         &mut caller,
13837cf8e1eSTyler Rockwood         params.as_ptr(),
13937cf8e1eSTyler Rockwood         params.len(),
14037cf8e1eSTyler Rockwood         out_results.as_mut_ptr(),
14137cf8e1eSTyler Rockwood         out_results.len(),
14237cf8e1eSTyler Rockwood         &mut trap,
14337cf8e1eSTyler Rockwood         &mut continuation,
14437cf8e1eSTyler Rockwood     );
14537cf8e1eSTyler Rockwood     continuation.await;
14637cf8e1eSTyler Rockwood 
14737cf8e1eSTyler Rockwood     if let Some(trap) = trap {
14837cf8e1eSTyler Rockwood         return Err(trap.error);
14937cf8e1eSTyler Rockwood     }
15037cf8e1eSTyler Rockwood 
15137cf8e1eSTyler Rockwood     // Translate the `wasmtime_val_t` results into the `results` space
15237cf8e1eSTyler Rockwood     for (i, result) in out_results.iter().enumerate() {
15337cf8e1eSTyler Rockwood         unsafe {
1549187f2d9SAlex Crichton             results[i] = result.to_val_unscoped(&mut caller.caller);
15537cf8e1eSTyler Rockwood         }
15637cf8e1eSTyler Rockwood     }
15737cf8e1eSTyler Rockwood     // Move our `vals` storage back into the store now that we no longer
15837cf8e1eSTyler Rockwood     // need it. This'll get picked up by the next hostcall and reuse our
15937cf8e1eSTyler Rockwood     // same storage.
16037cf8e1eSTyler Rockwood     hostcall_val_storage.truncate(0);
16137cf8e1eSTyler Rockwood     caller.caller.data_mut().hostcall_val_storage = hostcall_val_storage;
16237cf8e1eSTyler Rockwood     Ok(())
16337cf8e1eSTyler Rockwood }
16437cf8e1eSTyler Rockwood 
c_async_callback_to_rust_fn( callback: wasmtime_func_async_callback_t, data: *mut c_void, finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>, ) -> impl for<'a> Fn( WasmtimeCaller<'a>, &'a [Val], &'a mut [Val], ) -> Box<dyn Future<Output = Result<()>> + Send + 'a> + Send + Sync + 'static16537cf8e1eSTyler Rockwood unsafe fn c_async_callback_to_rust_fn(
16637cf8e1eSTyler Rockwood     callback: wasmtime_func_async_callback_t,
16737cf8e1eSTyler Rockwood     data: *mut c_void,
16837cf8e1eSTyler Rockwood     finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>,
16937cf8e1eSTyler Rockwood ) -> impl for<'a> Fn(
170420fc3d1SNick Fitzgerald     WasmtimeCaller<'a>,
17137cf8e1eSTyler Rockwood     &'a [Val],
17237cf8e1eSTyler Rockwood     &'a mut [Val],
17337cf8e1eSTyler Rockwood ) -> Box<dyn Future<Output = Result<()>> + Send + 'a>
17437cf8e1eSTyler Rockwood + Send
17537cf8e1eSTyler Rockwood + Sync
17637cf8e1eSTyler Rockwood + 'static {
17737cf8e1eSTyler Rockwood     let foreign = crate::ForeignData { data, finalizer };
17837cf8e1eSTyler Rockwood     move |caller, params, results| {
17937cf8e1eSTyler Rockwood         let _ = &foreign; // move entire foreign into this closure
18028fd6bf3STyler Rockwood         let data = CallbackDataPtr { ptr: foreign.data };
18137cf8e1eSTyler Rockwood         Box::new(invoke_c_async_callback(
18237cf8e1eSTyler Rockwood             callback, data, caller, params, results,
18337cf8e1eSTyler Rockwood         ))
18437cf8e1eSTyler Rockwood     }
18537cf8e1eSTyler Rockwood }
18637cf8e1eSTyler Rockwood 
18737cf8e1eSTyler Rockwood #[repr(transparent)]
18837cf8e1eSTyler Rockwood pub struct wasmtime_call_future_t<'a> {
18937cf8e1eSTyler Rockwood     underlying: Pin<Box<dyn Future<Output = ()> + 'a>>,
19037cf8e1eSTyler Rockwood }
19137cf8e1eSTyler Rockwood 
192ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasmtime_call_future_delete(_future: Box<wasmtime_call_future_t>)19337cf8e1eSTyler Rockwood pub extern "C" fn wasmtime_call_future_delete(_future: Box<wasmtime_call_future_t>) {}
19437cf8e1eSTyler Rockwood 
195ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasmtime_call_future_poll(future: &mut wasmtime_call_future_t) -> bool19637cf8e1eSTyler Rockwood pub extern "C" fn wasmtime_call_future_poll(future: &mut wasmtime_call_future_t) -> bool {
197*d41b0a71SAlex Crichton     match future
198*d41b0a71SAlex Crichton         .underlying
199*d41b0a71SAlex Crichton         .as_mut()
200*d41b0a71SAlex Crichton         .poll(&mut Context::from_waker(Waker::noop()))
201*d41b0a71SAlex Crichton     {
20237cf8e1eSTyler Rockwood         Poll::Ready(()) => true,
20337cf8e1eSTyler Rockwood         Poll::Pending => false,
20437cf8e1eSTyler Rockwood     }
20537cf8e1eSTyler Rockwood }
20637cf8e1eSTyler Rockwood 
handle_call_error( err: wasmtime::Error, trap_ret: &mut *mut wasm_trap_t, err_ret: &mut *mut wasmtime_error_t, )20737cf8e1eSTyler Rockwood fn handle_call_error(
20837cf8e1eSTyler Rockwood     err: wasmtime::Error,
20937cf8e1eSTyler Rockwood     trap_ret: &mut *mut wasm_trap_t,
21037cf8e1eSTyler Rockwood     err_ret: &mut *mut wasmtime_error_t,
21137cf8e1eSTyler Rockwood ) {
21237cf8e1eSTyler Rockwood     if err.is::<Trap>() {
21337cf8e1eSTyler Rockwood         *trap_ret = Box::into_raw(Box::new(wasm_trap_t::new(err)));
21437cf8e1eSTyler Rockwood     } else {
21537cf8e1eSTyler Rockwood         *err_ret = Box::into_raw(Box::new(wasmtime_error_t::from(err)));
21637cf8e1eSTyler Rockwood     }
21737cf8e1eSTyler Rockwood }
21837cf8e1eSTyler Rockwood 
do_func_call_async( mut store: RootScope<WasmtimeStoreContextMut<'_>>, func: &Func, args: impl ExactSizeIterator<Item = Val>, results: &mut [MaybeUninit<wasmtime_val_t>], trap_ret: &mut *mut wasm_trap_t, err_ret: &mut *mut wasmtime_error_t, )21937cf8e1eSTyler Rockwood async fn do_func_call_async(
2209187f2d9SAlex Crichton     mut store: RootScope<WasmtimeStoreContextMut<'_>>,
22137cf8e1eSTyler Rockwood     func: &Func,
22237cf8e1eSTyler Rockwood     args: impl ExactSizeIterator<Item = Val>,
22337cf8e1eSTyler Rockwood     results: &mut [MaybeUninit<wasmtime_val_t>],
22437cf8e1eSTyler Rockwood     trap_ret: &mut *mut wasm_trap_t,
22537cf8e1eSTyler Rockwood     err_ret: &mut *mut wasmtime_error_t,
22637cf8e1eSTyler Rockwood ) {
2279187f2d9SAlex Crichton     let mut params = mem::take(&mut store.as_context_mut().data_mut().wasm_val_storage);
22837cf8e1eSTyler Rockwood     let (wt_params, wt_results) = translate_args(&mut params, args, results.len());
22937cf8e1eSTyler Rockwood     let result = func.call_async(&mut store, wt_params, wt_results).await;
23037cf8e1eSTyler Rockwood 
23137cf8e1eSTyler Rockwood     match result {
23237cf8e1eSTyler Rockwood         Ok(()) => {
23337cf8e1eSTyler Rockwood             for (slot, val) in results.iter_mut().zip(wt_results.iter()) {
2340c0153c1SNick Fitzgerald                 crate::initialize(slot, wasmtime_val_t::from_val(&mut store, *val));
23537cf8e1eSTyler Rockwood             }
23637cf8e1eSTyler Rockwood             params.truncate(0);
2379187f2d9SAlex Crichton             store.as_context_mut().data_mut().wasm_val_storage = params;
23837cf8e1eSTyler Rockwood         }
23937cf8e1eSTyler Rockwood         Err(err) => handle_call_error(err, trap_ret, err_ret),
24037cf8e1eSTyler Rockwood     }
24137cf8e1eSTyler Rockwood }
24237cf8e1eSTyler Rockwood 
243ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasmtime_func_call_async<'a>( store: WasmtimeStoreContextMut<'a>, func: &'a Func, args: *const wasmtime_val_t, nargs: usize, results: *mut MaybeUninit<wasmtime_val_t>, nresults: usize, trap_ret: &'a mut *mut wasm_trap_t, err_ret: &'a mut *mut wasmtime_error_t, ) -> Box<wasmtime_call_future_t<'a>>24437cf8e1eSTyler Rockwood pub unsafe extern "C" fn wasmtime_func_call_async<'a>(
2459187f2d9SAlex Crichton     store: WasmtimeStoreContextMut<'a>,
24637cf8e1eSTyler Rockwood     func: &'a Func,
24737cf8e1eSTyler Rockwood     args: *const wasmtime_val_t,
24837cf8e1eSTyler Rockwood     nargs: usize,
24937cf8e1eSTyler Rockwood     results: *mut MaybeUninit<wasmtime_val_t>,
25037cf8e1eSTyler Rockwood     nresults: usize,
25137cf8e1eSTyler Rockwood     trap_ret: &'a mut *mut wasm_trap_t,
25237cf8e1eSTyler Rockwood     err_ret: &'a mut *mut wasmtime_error_t,
25337cf8e1eSTyler Rockwood ) -> Box<wasmtime_call_future_t<'a>> {
2549187f2d9SAlex Crichton     let mut scope = RootScope::new(store);
25537cf8e1eSTyler Rockwood     let args = crate::slice_from_raw_parts(args, nargs)
25637cf8e1eSTyler Rockwood         .iter()
2579187f2d9SAlex Crichton         .map(|i| i.to_val(&mut scope))
258bd2ea901SNick Fitzgerald         .collect::<Vec<_>>();
25937cf8e1eSTyler Rockwood     let results = crate::slice_from_raw_parts_mut(results, nresults);
26037cf8e1eSTyler Rockwood     let fut = Box::pin(do_func_call_async(
2619187f2d9SAlex Crichton         scope,
262bd2ea901SNick Fitzgerald         func,
263bd2ea901SNick Fitzgerald         args.into_iter(),
264bd2ea901SNick Fitzgerald         results,
265bd2ea901SNick Fitzgerald         trap_ret,
266bd2ea901SNick Fitzgerald         err_ret,
26737cf8e1eSTyler Rockwood     ));
26837cf8e1eSTyler Rockwood     Box::new(wasmtime_call_future_t { underlying: fut })
26937cf8e1eSTyler Rockwood }
27037cf8e1eSTyler Rockwood 
271ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasmtime_linker_define_async_func( linker: &mut wasmtime_linker_t, module: *const u8, module_len: usize, name: *const u8, name_len: usize, ty: &wasm_functype_t, callback: crate::wasmtime_func_async_callback_t, data: *mut c_void, finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>, ) -> Option<Box<wasmtime_error_t>>27237cf8e1eSTyler Rockwood pub unsafe extern "C" fn wasmtime_linker_define_async_func(
27337cf8e1eSTyler Rockwood     linker: &mut wasmtime_linker_t,
27437cf8e1eSTyler Rockwood     module: *const u8,
27537cf8e1eSTyler Rockwood     module_len: usize,
27637cf8e1eSTyler Rockwood     name: *const u8,
27737cf8e1eSTyler Rockwood     name_len: usize,
27837cf8e1eSTyler Rockwood     ty: &wasm_functype_t,
27937cf8e1eSTyler Rockwood     callback: crate::wasmtime_func_async_callback_t,
28037cf8e1eSTyler Rockwood     data: *mut c_void,
28137cf8e1eSTyler Rockwood     finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>,
28237cf8e1eSTyler Rockwood ) -> Option<Box<wasmtime_error_t>> {
2838652011fSNick Fitzgerald     let ty = ty.ty().ty(linker.linker.engine());
28437cf8e1eSTyler Rockwood     let module = to_str!(module, module_len);
28537cf8e1eSTyler Rockwood     let name = to_str!(name, name_len);
28637cf8e1eSTyler Rockwood     let cb = c_async_callback_to_rust_fn(callback, data, finalizer);
28737cf8e1eSTyler Rockwood 
28837cf8e1eSTyler Rockwood     handle_result(
28937cf8e1eSTyler Rockwood         linker.linker.func_new_async(module, name, ty, cb),
29037cf8e1eSTyler Rockwood         |_linker| (),
29137cf8e1eSTyler Rockwood     )
29237cf8e1eSTyler Rockwood }
29337cf8e1eSTyler Rockwood 
do_linker_instantiate_async( linker: &wasmtime_linker_t, store: WasmtimeStoreContextMut<'_>, module: &wasmtime_module_t, instance_ptr: &mut Instance, trap_ret: &mut *mut wasm_trap_t, err_ret: &mut *mut wasmtime_error_t, )29437cf8e1eSTyler Rockwood async fn do_linker_instantiate_async(
29537cf8e1eSTyler Rockwood     linker: &wasmtime_linker_t,
296420fc3d1SNick Fitzgerald     store: WasmtimeStoreContextMut<'_>,
29737cf8e1eSTyler Rockwood     module: &wasmtime_module_t,
29837cf8e1eSTyler Rockwood     instance_ptr: &mut Instance,
29937cf8e1eSTyler Rockwood     trap_ret: &mut *mut wasm_trap_t,
30037cf8e1eSTyler Rockwood     err_ret: &mut *mut wasmtime_error_t,
30137cf8e1eSTyler Rockwood ) {
30237cf8e1eSTyler Rockwood     let result = linker.linker.instantiate_async(store, &module.module).await;
30337cf8e1eSTyler Rockwood     match result {
30437cf8e1eSTyler Rockwood         Ok(instance) => *instance_ptr = instance,
30537cf8e1eSTyler Rockwood         Err(err) => handle_call_error(err, trap_ret, err_ret),
30637cf8e1eSTyler Rockwood     }
30737cf8e1eSTyler Rockwood }
30837cf8e1eSTyler Rockwood 
309ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasmtime_linker_instantiate_async<'a>( linker: &'a wasmtime_linker_t, store: WasmtimeStoreContextMut<'a>, module: &'a wasmtime_module_t, instance_ptr: &'a mut Instance, trap_ret: &'a mut *mut wasm_trap_t, err_ret: &'a mut *mut wasmtime_error_t, ) -> Box<crate::wasmtime_call_future_t<'a>>31037cf8e1eSTyler Rockwood pub extern "C" fn wasmtime_linker_instantiate_async<'a>(
31137cf8e1eSTyler Rockwood     linker: &'a wasmtime_linker_t,
312420fc3d1SNick Fitzgerald     store: WasmtimeStoreContextMut<'a>,
31337cf8e1eSTyler Rockwood     module: &'a wasmtime_module_t,
31437cf8e1eSTyler Rockwood     instance_ptr: &'a mut Instance,
31537cf8e1eSTyler Rockwood     trap_ret: &'a mut *mut wasm_trap_t,
31637cf8e1eSTyler Rockwood     err_ret: &'a mut *mut wasmtime_error_t,
31737cf8e1eSTyler Rockwood ) -> Box<crate::wasmtime_call_future_t<'a>> {
31837cf8e1eSTyler Rockwood     let fut = Box::pin(do_linker_instantiate_async(
31937cf8e1eSTyler Rockwood         linker,
32037cf8e1eSTyler Rockwood         store,
32137cf8e1eSTyler Rockwood         module,
32237cf8e1eSTyler Rockwood         instance_ptr,
32337cf8e1eSTyler Rockwood         trap_ret,
32437cf8e1eSTyler Rockwood         err_ret,
32537cf8e1eSTyler Rockwood     ));
32637cf8e1eSTyler Rockwood     Box::new(crate::wasmtime_call_future_t { underlying: fut })
32737cf8e1eSTyler Rockwood }
328ec07c89bSTyler Rockwood 
do_instance_pre_instantiate_async( instance_pre: &wasmtime_instance_pre_t, store: WasmtimeStoreContextMut<'_>, instance_ptr: &mut Instance, trap_ret: &mut *mut wasm_trap_t, err_ret: &mut *mut wasmtime_error_t, )329ec07c89bSTyler Rockwood async fn do_instance_pre_instantiate_async(
330ec07c89bSTyler Rockwood     instance_pre: &wasmtime_instance_pre_t,
331420fc3d1SNick Fitzgerald     store: WasmtimeStoreContextMut<'_>,
332ec07c89bSTyler Rockwood     instance_ptr: &mut Instance,
333ec07c89bSTyler Rockwood     trap_ret: &mut *mut wasm_trap_t,
334ec07c89bSTyler Rockwood     err_ret: &mut *mut wasmtime_error_t,
335ec07c89bSTyler Rockwood ) {
336ec07c89bSTyler Rockwood     let result = instance_pre.underlying.instantiate_async(store).await;
337ec07c89bSTyler Rockwood     match result {
338ec07c89bSTyler Rockwood         Ok(instance) => *instance_ptr = instance,
339ec07c89bSTyler Rockwood         Err(err) => handle_call_error(err, trap_ret, err_ret),
340ec07c89bSTyler Rockwood     }
341ec07c89bSTyler Rockwood }
342ec07c89bSTyler Rockwood 
343ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasmtime_instance_pre_instantiate_async<'a>( instance_pre: &'a wasmtime_instance_pre_t, store: WasmtimeStoreContextMut<'a>, instance_ptr: &'a mut Instance, trap_ret: &'a mut *mut wasm_trap_t, err_ret: &'a mut *mut wasmtime_error_t, ) -> Box<crate::wasmtime_call_future_t<'a>>344ec07c89bSTyler Rockwood pub extern "C" fn wasmtime_instance_pre_instantiate_async<'a>(
345ec07c89bSTyler Rockwood     instance_pre: &'a wasmtime_instance_pre_t,
346420fc3d1SNick Fitzgerald     store: WasmtimeStoreContextMut<'a>,
347ec07c89bSTyler Rockwood     instance_ptr: &'a mut Instance,
348ec07c89bSTyler Rockwood     trap_ret: &'a mut *mut wasm_trap_t,
349ec07c89bSTyler Rockwood     err_ret: &'a mut *mut wasmtime_error_t,
350ec07c89bSTyler Rockwood ) -> Box<crate::wasmtime_call_future_t<'a>> {
351ec07c89bSTyler Rockwood     let fut = Box::pin(do_instance_pre_instantiate_async(
352ec07c89bSTyler Rockwood         instance_pre,
353ec07c89bSTyler Rockwood         store,
354ec07c89bSTyler Rockwood         instance_ptr,
355ec07c89bSTyler Rockwood         trap_ret,
356ec07c89bSTyler Rockwood         err_ret,
357ec07c89bSTyler Rockwood     ));
358ec07c89bSTyler Rockwood     Box::new(crate::wasmtime_call_future_t { underlying: fut })
359ec07c89bSTyler Rockwood }
360e6ff8411STyler Rockwood 
361e6ff8411STyler Rockwood pub type wasmtime_stack_memory_get_callback_t =
362e6ff8411STyler Rockwood     extern "C" fn(env: *mut std::ffi::c_void, out_len: &mut usize) -> *mut u8;
363e6ff8411STyler Rockwood 
364e6ff8411STyler Rockwood #[repr(C)]
365e6ff8411STyler Rockwood pub struct wasmtime_stack_memory_t {
366e6ff8411STyler Rockwood     env: *mut std::ffi::c_void,
367e6ff8411STyler Rockwood     get_stack_memory: wasmtime_stack_memory_get_callback_t,
368e6ff8411STyler Rockwood     finalizer: Option<extern "C" fn(arg1: *mut std::ffi::c_void)>,
369e6ff8411STyler Rockwood }
370e6ff8411STyler Rockwood 
371e6ff8411STyler Rockwood struct CHostStackMemory {
372e6ff8411STyler Rockwood     foreign: crate::ForeignData,
373e6ff8411STyler Rockwood     get_memory: wasmtime_stack_memory_get_callback_t,
374e6ff8411STyler Rockwood }
375e6ff8411STyler Rockwood unsafe impl Send for CHostStackMemory {}
376e6ff8411STyler Rockwood unsafe impl Sync for CHostStackMemory {}
377e6ff8411STyler Rockwood unsafe impl StackMemory for CHostStackMemory {
top(&self) -> *mut u8378e6ff8411STyler Rockwood     fn top(&self) -> *mut u8 {
379e6ff8411STyler Rockwood         let mut len = 0;
380e6ff8411STyler Rockwood         let cb = self.get_memory;
381e6ff8411STyler Rockwood         cb(self.foreign.data, &mut len)
382e6ff8411STyler Rockwood     }
range(&self) -> Range<usize>383e6ff8411STyler Rockwood     fn range(&self) -> Range<usize> {
384e6ff8411STyler Rockwood         let mut len = 0;
385e6ff8411STyler Rockwood         let cb = self.get_memory;
386e6ff8411STyler Rockwood         let top = cb(self.foreign.data, &mut len);
387e6ff8411STyler Rockwood         let base = unsafe { top.sub(len) as usize };
388e6ff8411STyler Rockwood         base..base + len
389e6ff8411STyler Rockwood     }
guard_range(&self) -> Range<*mut u8>390110e70f3SAlex Crichton     fn guard_range(&self) -> Range<*mut u8> {
391110e70f3SAlex Crichton         std::ptr::null_mut()..std::ptr::null_mut()
392110e70f3SAlex Crichton     }
393e6ff8411STyler Rockwood }
394e6ff8411STyler Rockwood 
395e6ff8411STyler Rockwood pub type wasmtime_new_stack_memory_callback_t = extern "C" fn(
396e6ff8411STyler Rockwood     env: *mut std::ffi::c_void,
397e6ff8411STyler Rockwood     size: usize,
398980a136eSNick Fitzgerald     zeroed: bool,
399e6ff8411STyler Rockwood     stack_ret: &mut wasmtime_stack_memory_t,
400e6ff8411STyler Rockwood ) -> Option<Box<wasmtime_error_t>>;
401e6ff8411STyler Rockwood 
402e6ff8411STyler Rockwood #[repr(C)]
403e6ff8411STyler Rockwood pub struct wasmtime_stack_creator_t {
404e6ff8411STyler Rockwood     env: *mut std::ffi::c_void,
405e6ff8411STyler Rockwood     new_stack: wasmtime_new_stack_memory_callback_t,
406e6ff8411STyler Rockwood     finalizer: Option<extern "C" fn(arg1: *mut std::ffi::c_void)>,
407e6ff8411STyler Rockwood }
408e6ff8411STyler Rockwood 
409e6ff8411STyler Rockwood struct CHostStackCreator {
410e6ff8411STyler Rockwood     foreign: crate::ForeignData,
411e6ff8411STyler Rockwood     new_stack: wasmtime_new_stack_memory_callback_t,
412e6ff8411STyler Rockwood }
413e6ff8411STyler Rockwood unsafe impl Send for CHostStackCreator {}
414e6ff8411STyler Rockwood unsafe impl Sync for CHostStackCreator {}
415e6ff8411STyler Rockwood unsafe impl StackCreator for CHostStackCreator {
new_stack(&self, size: usize, zeroed: bool) -> Result<Box<dyn wasmtime::StackMemory>>416980a136eSNick Fitzgerald     fn new_stack(&self, size: usize, zeroed: bool) -> Result<Box<dyn wasmtime::StackMemory>> {
417e6ff8411STyler Rockwood         extern "C" fn panic_callback(_env: *mut std::ffi::c_void, _out_len: &mut usize) -> *mut u8 {
418e6ff8411STyler Rockwood             panic!("a callback must be set");
419e6ff8411STyler Rockwood         }
420e6ff8411STyler Rockwood         let mut out = wasmtime_stack_memory_t {
421e6ff8411STyler Rockwood             env: ptr::null_mut(),
422e6ff8411STyler Rockwood             get_stack_memory: panic_callback,
423e6ff8411STyler Rockwood             finalizer: None,
424e6ff8411STyler Rockwood         };
425e6ff8411STyler Rockwood         let cb = self.new_stack;
426980a136eSNick Fitzgerald         let result = cb(self.foreign.data, size, zeroed, &mut out);
427e6ff8411STyler Rockwood         match result {
428e6ff8411STyler Rockwood             Some(error) => Err((*error).into()),
429e6ff8411STyler Rockwood             None => Ok(Box::new(CHostStackMemory {
430e6ff8411STyler Rockwood                 foreign: crate::ForeignData {
431e6ff8411STyler Rockwood                     data: out.env,
432e6ff8411STyler Rockwood                     finalizer: out.finalizer,
433e6ff8411STyler Rockwood                 },
434e6ff8411STyler Rockwood                 get_memory: out.get_stack_memory,
435e6ff8411STyler Rockwood             })),
436e6ff8411STyler Rockwood         }
437e6ff8411STyler Rockwood     }
438e6ff8411STyler Rockwood }
439e6ff8411STyler Rockwood 
440ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasmtime_config_host_stack_creator_set( c: &mut wasm_config_t, creator: &wasmtime_stack_creator_t, )441e6ff8411STyler Rockwood pub unsafe extern "C" fn wasmtime_config_host_stack_creator_set(
442e6ff8411STyler Rockwood     c: &mut wasm_config_t,
443e6ff8411STyler Rockwood     creator: &wasmtime_stack_creator_t,
444e6ff8411STyler Rockwood ) {
445e6ff8411STyler Rockwood     c.config.with_host_stack(Arc::new(CHostStackCreator {
446e6ff8411STyler Rockwood         foreign: crate::ForeignData {
447e6ff8411STyler Rockwood             data: creator.env,
448e6ff8411STyler Rockwood             finalizer: creator.finalizer,
449e6ff8411STyler Rockwood         },
450e6ff8411STyler Rockwood         new_stack: creator.new_stack,
451e6ff8411STyler Rockwood     }));
452e6ff8411STyler Rockwood }
453