From 351d4106cd1af3d9c76a7e5768b3c4e74cfdea46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Rachwa=C5=82?= Date: Sat, 2 Mar 2024 01:48:51 +0100 Subject: [PATCH] Extend C API with interfaces needed to use threads --- crates/c-api/include/wasmtime.h | 1 + crates/c-api/include/wasmtime/extern.h | 7 ++ crates/c-api/include/wasmtime/linker.h | 9 ++ crates/c-api/include/wasmtime/memory.h | 5 + crates/c-api/include/wasmtime/sharedmemory.h | 115 +++++++++++++++++++ crates/c-api/src/extern.rs | 24 +++- crates/c-api/src/lib.rs | 1 + crates/c-api/src/linker.rs | 7 ++ crates/c-api/src/sharedmemory.rs | 68 +++++++++++ crates/c-api/src/types/memory.rs | 5 + 10 files changed, 239 insertions(+), 3 deletions(-) create mode 100644 crates/c-api/include/wasmtime/sharedmemory.h create mode 100644 crates/c-api/src/sharedmemory.rs diff --git a/crates/c-api/include/wasmtime.h b/crates/c-api/include/wasmtime.h index 6ba3e76b8f03..cfb360b58b4e 100644 --- a/crates/c-api/include/wasmtime.h +++ b/crates/c-api/include/wasmtime.h @@ -195,6 +195,7 @@ #include #include #include +#include #include #include #include diff --git a/crates/c-api/include/wasmtime/extern.h b/crates/c-api/include/wasmtime/extern.h index 427c5ba7f969..7cb058b7d527 100644 --- a/crates/c-api/include/wasmtime/extern.h +++ b/crates/c-api/include/wasmtime/extern.h @@ -85,6 +85,11 @@ typedef uint8_t wasmtime_extern_kind_t; /// \brief Value of #wasmtime_extern_kind_t meaning that #wasmtime_extern_t is a /// memory #define WASMTIME_EXTERN_MEMORY 3 +/// \brief Value of #wasmtime_extern_kind_t meaning that #wasmtime_extern_t is a +/// shared memory +#define WASMTIME_EXTERN_SHAREDMEMORY 4 + +struct wasmtime_sharedmemory; /** * \typedef wasmtime_extern_union_t @@ -105,6 +110,8 @@ typedef union wasmtime_extern_union { wasmtime_table_t table; /// Field used if #wasmtime_extern_t::kind is #WASMTIME_EXTERN_MEMORY wasmtime_memory_t memory; + /// Field used if #wasmtime_extern_t::kind is #WASMTIME_EXTERN_SHAREDMEMORY + struct wasmtime_sharedmemory *sharedmemory; } wasmtime_extern_union_t; /** diff --git a/crates/c-api/include/wasmtime/linker.h b/crates/c-api/include/wasmtime/linker.h index c70423495603..da07db30be53 100644 --- a/crates/c-api/include/wasmtime/linker.h +++ b/crates/c-api/include/wasmtime/linker.h @@ -42,6 +42,15 @@ typedef struct wasmtime_linker wasmtime_linker_t; */ WASM_API_EXTERN wasmtime_linker_t *wasmtime_linker_new(wasm_engine_t *engine); +/** + * \brief Clones existing linker. + * + * This function does not take ownership of the linker argument, and the caller + * is expected to delete the returned linker. + */ +WASM_API_EXTERN wasmtime_linker_t * +wasmtime_linker_clone(wasmtime_linker_t *linker); + /** * \brief Deletes a linker */ diff --git a/crates/c-api/include/wasmtime/memory.h b/crates/c-api/include/wasmtime/memory.h index a22b93c97a68..53e82fcc65ed 100644 --- a/crates/c-api/include/wasmtime/memory.h +++ b/crates/c-api/include/wasmtime/memory.h @@ -54,6 +54,11 @@ WASM_API_EXTERN bool wasmtime_memorytype_maximum(const wasm_memorytype_t *ty, */ WASM_API_EXTERN bool wasmtime_memorytype_is64(const wasm_memorytype_t *ty); +/** + * \brief Returns whether this type of memory represents a shared memory. + */ +WASM_API_EXTERN bool wasmtime_memorytype_isshared(const wasm_memorytype_t *ty); + /** * \brief Creates a new WebAssembly linear memory * diff --git a/crates/c-api/include/wasmtime/sharedmemory.h b/crates/c-api/include/wasmtime/sharedmemory.h new file mode 100644 index 000000000000..0c68d7403912 --- /dev/null +++ b/crates/c-api/include/wasmtime/sharedmemory.h @@ -0,0 +1,115 @@ +/** + * \file wasmtime/sharedmemory.h + * + * Wasmtime API for interacting with wasm shared memories. + */ + +#ifndef WASMTIME_SHAREDMEMORY_H +#define WASMTIME_SHAREDMEMORY_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Interface for shared memories. + * + * For more information see the Rust documentation at: + * https://docs.wasmtime.dev/api/wasmtime/struct.SharedMemory.html + */ +typedef struct wasmtime_sharedmemory wasmtime_sharedmemory_t; + +/** + * \brief Creates a new WebAssembly shared linear memory + * + * \param engine engine that created shared memory is associated with + * \param ty the type of the memory to create + * \param ret where to store the returned memory + * + * If an error happens when creating the memory it's returned and owned by the + * caller. If an error happens then `ret` is not filled in. + */ +WASM_API_EXTERN wasmtime_error_t * +wasmtime_sharedmemory_new(const wasm_engine_t *engine, + const wasm_memorytype_t *ty, + wasmtime_sharedmemory_t **ret); + +/** + * \brief Deletes shared linear memory + * + * \param memory memory to be deleted + */ +WASM_API_EXTERN void +wasmtime_sharedmemory_delete(wasmtime_sharedmemory_t *memory); + +/** + * \brief Clones shared linear memory + * + * \param memory memory to be cloned + * + * This function makes shallow clone, ie. copy of reference counted + * memory handle. + */ +WASM_API_EXTERN wasmtime_sharedmemory_t * +wasmtime_sharedmemory_clone(const wasmtime_sharedmemory_t *memory); + +/** + * \brief Moves shared linear memory into wasmtime_extern_t object + * + * \param memory memory to be moved + * \param out where to store resulting `wasmtime_extern_t` + * + * This function moves ownership of `memory` into resulting `wasmtime_extern_t`. + */ +WASM_API_EXTERN void +wasmtime_sharedmemory_into_extern(wasmtime_sharedmemory_t *memory, + wasmtime_extern_t *out); + +/** + * \brief Returns the type of the shared memory specified + */ +WASM_API_EXTERN wasm_memorytype_t * +wasmtime_sharedmemory_type(const wasmtime_sharedmemory_t *memory); + +/** + * \brief Returns the base pointer in memory where + the shared linear memory starts. + */ +WASM_API_EXTERN uint8_t * +wasmtime_sharedmemory_data(const wasmtime_sharedmemory_t *memory); + +/** + * \brief Returns the byte length of this shared linear memory. + */ +WASM_API_EXTERN size_t +wasmtime_sharedmemory_data_size(const wasmtime_sharedmemory_t *memory); + +/** + * \brief Returns the length, in WebAssembly pages, of this shared linear memory + */ +WASM_API_EXTERN uint64_t +wasmtime_sharedmemory_size(const wasmtime_sharedmemory_t *memory); + +/** + * \brief Attempts to grow the specified shared memory by `delta` pages. + * + * \param memory the memory to grow + * \param delta the number of pages to grow by + * \param prev_size where to store the previous size of memory + * + * If memory cannot be grown then `prev_size` is left unchanged and an error is + * returned. Otherwise `prev_size` is set to the previous size of the memory, in + * WebAssembly pages, and `NULL` is returned. + */ +WASM_API_EXTERN wasmtime_error_t * +wasmtime_sharedmemory_grow(const wasmtime_sharedmemory_t *memory, + uint64_t delta, uint64_t *prev_size); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WASMTIME_SHAREDMEMORY_H diff --git a/crates/c-api/src/extern.rs b/crates/c-api/src/extern.rs index b97ba1f19f18..3fbf1d0cdf3f 100644 --- a/crates/c-api/src/extern.rs +++ b/crates/c-api/src/extern.rs @@ -3,7 +3,7 @@ use crate::{ CStoreContext, StoreRef, }; use std::mem::ManuallyDrop; -use wasmtime::{Extern, Func, Global, Memory, Table}; +use wasmtime::{Extern, Func, Global, Memory, SharedMemory, Table}; #[derive(Clone)] pub struct wasm_extern_t { @@ -82,6 +82,7 @@ pub const WASMTIME_EXTERN_FUNC: wasmtime_extern_kind_t = 0; pub const WASMTIME_EXTERN_GLOBAL: wasmtime_extern_kind_t = 1; pub const WASMTIME_EXTERN_TABLE: wasmtime_extern_kind_t = 2; pub const WASMTIME_EXTERN_MEMORY: wasmtime_extern_kind_t = 3; +pub const WASMTIME_EXTERN_SHAREDMEMORY: wasmtime_extern_kind_t = 4; #[repr(C)] pub union wasmtime_extern_union { @@ -89,6 +90,17 @@ pub union wasmtime_extern_union { pub table: Table, pub global: Global, pub memory: Memory, + pub sharedmemory: ManuallyDrop>, +} + +impl Drop for wasmtime_extern_t { + fn drop(&mut self) { + if self.kind == WASMTIME_EXTERN_SHAREDMEMORY { + unsafe { + ManuallyDrop::drop(&mut self.of.sharedmemory); + } + } + } } impl wasmtime_extern_t { @@ -98,7 +110,8 @@ impl wasmtime_extern_t { WASMTIME_EXTERN_GLOBAL => Extern::Global(self.of.global), WASMTIME_EXTERN_TABLE => Extern::Table(self.of.table), WASMTIME_EXTERN_MEMORY => Extern::Memory(self.of.memory), - other => panic!("unknown wasm_extern_kind_t: {}", other), + WASMTIME_EXTERN_SHAREDMEMORY => Extern::SharedMemory((**self.of.sharedmemory).clone()), + other => panic!("unknown wasmtime_extern_kind_t: {}", other), } } } @@ -122,7 +135,12 @@ impl From for wasmtime_extern_t { kind: WASMTIME_EXTERN_MEMORY, of: wasmtime_extern_union { memory }, }, - Extern::SharedMemory(_memory) => todo!(), + Extern::SharedMemory(sharedmemory) => wasmtime_extern_t { + kind: WASMTIME_EXTERN_SHAREDMEMORY, + of: wasmtime_extern_union { + sharedmemory: ManuallyDrop::new(Box::new(sharedmemory)), + }, + }, } } } diff --git a/crates/c-api/src/lib.rs b/crates/c-api/src/lib.rs index fa5368cdd86e..8dc1a26c84d4 100644 --- a/crates/c-api/src/lib.rs +++ b/crates/c-api/src/lib.rs @@ -29,6 +29,7 @@ mod module; #[cfg(feature = "profiling")] mod profiling; mod r#ref; +mod sharedmemory; mod store; mod table; mod trap; diff --git a/crates/c-api/src/linker.rs b/crates/c-api/src/linker.rs index 6ea36fa05388..8f97a5b652ae 100644 --- a/crates/c-api/src/linker.rs +++ b/crates/c-api/src/linker.rs @@ -21,6 +21,13 @@ pub extern "C" fn wasmtime_linker_new(engine: &wasm_engine_t) -> Box Box { + Box::new(wasmtime_linker_t { + linker: linker.linker.clone(), + }) +} + #[no_mangle] pub extern "C" fn wasmtime_linker_allow_shadowing( linker: &mut wasmtime_linker_t, diff --git a/crates/c-api/src/sharedmemory.rs b/crates/c-api/src/sharedmemory.rs new file mode 100644 index 000000000000..1521373c4ea5 --- /dev/null +++ b/crates/c-api/src/sharedmemory.rs @@ -0,0 +1,68 @@ +use crate::{handle_result, wasm_engine_t, wasm_memorytype_t, wasmtime_error_t, wasmtime_extern_t}; +use std::cell::UnsafeCell; +use std::mem::MaybeUninit; +use wasmtime::{Extern, SharedMemory}; + +type wasmtime_sharedmemory_t = SharedMemory; + +wasmtime_c_api_macros::declare_own!(wasmtime_sharedmemory_t); + +#[no_mangle] +pub extern "C" fn wasmtime_sharedmemory_new( + engine: &wasm_engine_t, + ty: &wasm_memorytype_t, + ret: &mut *mut wasmtime_sharedmemory_t, +) -> Option> { + handle_result( + SharedMemory::new(&engine.engine, ty.ty().ty.clone()), + |mem| *ret = Box::::into_raw(Box::new(mem)), + ) +} + +#[no_mangle] +pub extern "C" fn wasmtime_sharedmemory_clone( + mem: &wasmtime_sharedmemory_t, +) -> Box { + Box::new(mem.clone()) +} + +#[no_mangle] +pub extern "C" fn wasmtime_sharedmemory_into_extern( + mem: Box, + ext: &mut MaybeUninit, +) { + crate::initialize(ext, Extern::from(*mem).into()); +} + +#[no_mangle] +pub extern "C" fn wasmtime_sharedmemory_type( + mem: &wasmtime_sharedmemory_t, +) -> Box { + Box::new(wasm_memorytype_t::new(mem.ty())) +} + +#[no_mangle] +pub extern "C" fn wasmtime_sharedmemory_data( + mem: &wasmtime_sharedmemory_t, +) -> *const UnsafeCell { + mem.data().as_ptr() +} + +#[no_mangle] +pub extern "C" fn wasmtime_sharedmemory_data_size(mem: &wasmtime_sharedmemory_t) -> usize { + mem.data().len() +} + +#[no_mangle] +pub extern "C" fn wasmtime_sharedmemory_size(mem: &wasmtime_sharedmemory_t) -> u64 { + mem.size() +} + +#[no_mangle] +pub extern "C" fn wasmtime_sharedmemory_grow( + mem: &wasmtime_sharedmemory_t, + delta: u64, + prev_size: &mut u64, +) -> Option> { + handle_result(mem.grow(delta), |prev| *prev_size = prev) +} diff --git a/crates/c-api/src/types/memory.rs b/crates/c-api/src/types/memory.rs index 034bea862be6..bcdb933d7c56 100644 --- a/crates/c-api/src/types/memory.rs +++ b/crates/c-api/src/types/memory.rs @@ -108,6 +108,11 @@ pub extern "C" fn wasmtime_memorytype_is64(mt: &wasm_memorytype_t) -> bool { mt.ty().ty.is_64() } +#[no_mangle] +pub extern "C" fn wasmtime_memorytype_isshared(mt: &wasm_memorytype_t) -> bool { + mt.ty().ty.is_shared() +} + #[no_mangle] pub extern "C" fn wasm_memorytype_as_externtype(ty: &wasm_memorytype_t) -> &wasm_externtype_t { &ty.ext