From cfb506ba1e32036bc97360fe6cfb20b970ea461f Mon Sep 17 00:00:00 2001 From: theothergraham Date: Tue, 9 May 2023 13:21:12 -0400 Subject: [PATCH] add C API for epoch_deadline_callback and wasmtime_error_t creation (#6359) * add C API for epoch_dead_callback and wasmtime_error_t creation * revise C API wasmtime_error_new msg encoding --- crates/c-api/include/wasmtime/error.h | 5 ++++ crates/c-api/include/wasmtime/store.h | 21 ++++++++++++-- crates/c-api/src/error.rs | 14 +++++++++ crates/c-api/src/store.rs | 42 +++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 3 deletions(-) diff --git a/crates/c-api/include/wasmtime/error.h b/crates/c-api/include/wasmtime/error.h index cfa0c9690e..5177552067 100644 --- a/crates/c-api/include/wasmtime/error.h +++ b/crates/c-api/include/wasmtime/error.h @@ -30,6 +30,11 @@ extern "C" { */ typedef struct wasmtime_error wasmtime_error_t; +/** + * \brief Creates a new error with the provided message. + */ +WASM_API_EXTERN wasmtime_error_t *wasmtime_error_new(const char*); + /** * \brief Deletes an error. */ diff --git a/crates/c-api/include/wasmtime/store.h b/crates/c-api/include/wasmtime/store.h index ba1d74a943..f07f9a7a2f 100644 --- a/crates/c-api/include/wasmtime/store.h +++ b/crates/c-api/include/wasmtime/store.h @@ -206,15 +206,30 @@ WASM_API_EXTERN wasmtime_error_t *wasmtime_context_set_wasi(wasmtime_context_t * /** * \brief Configures the relative deadline at which point WebAssembly code will - * trap. + * trap or invoke the callback function. * * This function configures the store-local epoch deadline after which point - * WebAssembly code will trap. + * WebAssembly code will trap or invoke the callback function. * - * See also #wasmtime_config_epoch_interruption_set. + * See also #wasmtime_config_epoch_interruption_set and + * #wasmtime_store_epoch_deadline_callback. */ WASM_API_EXTERN void wasmtime_context_set_epoch_deadline(wasmtime_context_t *context, uint64_t ticks_beyond_current); +/** + * \brief Configures epoch deadline callback to C function. + * + * This function configures a store-local callback function that will be + * called when the running WebAssembly function has exceeded its epoch + * deadline. That function can return a #wasmtime_error_t to terminate + * the function, or set the delta argument and return NULL to update the + * epoch deadline and resume function execution. + * + * See also #wasmtime_config_epoch_interruption_set and + * #wasmtime_context_set_epoch_deadline. + */ +WASM_API_EXTERN void wasmtime_store_epoch_deadline_callback(wasmtime_store_t *store, wasmtime_error_t* (*func)(wasmtime_context_t*, void*, uint64_t*), void *data); + #ifdef __cplusplus } // extern "C" #endif diff --git a/crates/c-api/src/error.rs b/crates/c-api/src/error.rs index e1e066531a..5b320ad4fd 100644 --- a/crates/c-api/src/error.rs +++ b/crates/c-api/src/error.rs @@ -14,6 +14,20 @@ impl From for wasmtime_error_t { } } +impl Into for wasmtime_error_t { + fn into(self) -> Error { + self.error + } +} + +#[no_mangle] +pub extern "C" fn wasmtime_error_new( + msg: *const std::ffi::c_char, +) -> Option> { + let msg_string = String::from_utf8_lossy(unsafe { std::ffi::CStr::from_ptr(msg).to_bytes() }); + Some(Box::new(wasmtime_error_t::from(anyhow!(msg_string)))) +} + pub(crate) fn handle_result( result: Result, ok: impl FnOnce(T), diff --git a/crates/c-api/src/store.rs b/crates/c-api/src/store.rs index 3949d46b0e..dbaf1ab0c5 100644 --- a/crates/c-api/src/store.rs +++ b/crates/c-api/src/store.rs @@ -106,6 +106,48 @@ pub extern "C" fn wasmtime_store_new( }) } +// Internal structure to add Send/Sync to the c_void member. +#[derive(Debug)] +pub struct CallbackDataPtr { + pub ptr: *mut c_void, +} + +impl CallbackDataPtr { + fn as_mut_ptr(&self) -> *mut c_void { + self.ptr + } +} + +unsafe impl Send for CallbackDataPtr {} +unsafe impl Sync for CallbackDataPtr {} + +#[no_mangle] +pub extern "C" fn wasmtime_store_epoch_deadline_callback( + store: &mut wasmtime_store_t, + func: extern "C" fn( + CStoreContextMut<'_>, + *mut c_void, + *mut u64, + ) -> Option>, + data: *mut c_void, +) { + let sendable = CallbackDataPtr { ptr: data }; + store.store.epoch_deadline_callback(move |mut store_ctx| { + let mut delta: u64 = 0; + let result = (func)( + store_ctx.as_context_mut(), + sendable.as_mut_ptr(), + &mut delta as *mut u64, + ); + match result { + Some(err) => Err(wasmtime::Error::from(>::into(*err))), + None => Ok(delta), + } + }); +} + #[no_mangle] pub extern "C" fn wasmtime_store_context(store: &mut wasmtime_store_t) -> CStoreContextMut<'_> { store.store.as_context_mut()