Implemented shared memory for Wasmer in preparation for multithreading

Fixed linter

Fixed clippy

Cleaned up some merge leftover
This commit is contained in:
John Sharratt's Shared Account
2022-08-17 17:45:48 +10:00
committed by ptitSeb
parent 0928629051
commit a5f641b4b0
10 changed files with 190 additions and 29 deletions

View File

@@ -12,6 +12,7 @@ use std::cell::UnsafeCell;
use std::convert::TryInto;
use std::ptr::NonNull;
use std::slice;
use std::sync::{Arc, RwLock};
use wasmer_types::{Bytes, MemoryError, MemoryStyle, MemoryType, Pages};
// The memory mapped area
@@ -156,6 +157,18 @@ pub struct VMOwnedMemory {
unsafe impl Send for VMOwnedMemory {}
unsafe impl Sync for VMOwnedMemory {}
/// A shared linear memory instance.
#[derive(Debug, Clone)]
pub struct VMSharedMemory {
// The underlying allocation.
mmap: Arc<RwLock<WasmMmap>>,
// Configuration of this memory
config: VMMemoryConfig,
}
unsafe impl Send for VMSharedMemory {}
unsafe impl Sync for VMSharedMemory {}
impl VMOwnedMemory {
/// Create a new linear memory instance with specified minimum and maximum number of wasm pages.
///
@@ -259,6 +272,16 @@ impl VMOwnedMemory {
}
}
impl VMOwnedMemory {
/// Converts this owned memory into shared memory
pub fn to_shared(self) -> VMSharedMemory {
VMSharedMemory {
mmap: Arc::new(RwLock::new(self.mmap)),
config: self.config,
}
}
}
impl LinearMemory for VMOwnedMemory {
/// Returns the type for this memory.
fn ty(&self) -> MemoryType {
@@ -295,12 +318,85 @@ impl LinearMemory for VMOwnedMemory {
}
}
impl VMSharedMemory {
/// Create a new linear memory instance with specified minimum and maximum number of wasm pages.
///
/// This creates a `Memory` with owned metadata: this can be used to create a memory
/// that will be imported into Wasm modules.
pub fn new(memory: &MemoryType, style: &MemoryStyle) -> Result<Self, MemoryError> {
Ok(VMOwnedMemory::new(memory, style)?.to_shared())
}
/// Create a new linear memory instance with specified minimum and maximum number of wasm pages.
///
/// This creates a `Memory` with metadata owned by a VM, pointed to by
/// `vm_memory_location`: this can be used to create a local memory.
///
/// # Safety
/// - `vm_memory_location` must point to a valid location in VM memory.
pub unsafe fn from_definition(
memory: &MemoryType,
style: &MemoryStyle,
vm_memory_location: NonNull<VMMemoryDefinition>,
) -> Result<Self, MemoryError> {
Ok(VMOwnedMemory::from_definition(memory, style, vm_memory_location)?.to_shared())
}
}
impl LinearMemory for VMSharedMemory {
/// Returns the type for this memory.
fn ty(&self) -> MemoryType {
let minimum = {
let guard = self.mmap.read().unwrap();
guard.size()
};
self.config.ty(minimum)
}
/// Returns the size of hte memory in pages
fn size(&self) -> Pages {
let guard = self.mmap.read().unwrap();
guard.size()
}
/// Returns the memory style for this memory.
fn style(&self) -> MemoryStyle {
self.config.style()
}
/// Grow memory by the specified amount of wasm pages.
///
/// Returns `None` if memory can't be grown by the specified amount
/// of wasm pages.
fn grow(&mut self, delta: Pages) -> Result<Pages, MemoryError> {
let mut guard = self.mmap.write().unwrap();
guard.grow(delta, self.config.clone())
}
/// Return a `VMMemoryDefinition` for exposing the memory to compiled wasm code.
fn vmmemory(&self) -> NonNull<VMMemoryDefinition> {
let guard = self.mmap.read().unwrap();
guard.vm_memory_definition.as_ptr()
}
/// Owned memory can not be cloned (this will always return None)
fn try_clone(&self) -> Option<Box<dyn LinearMemory + 'static>> {
None
}
}
impl From<VMOwnedMemory> for VMMemory {
fn from(mem: VMOwnedMemory) -> Self {
Self(Box::new(mem))
}
}
impl From<VMSharedMemory> for VMMemory {
fn from(mem: VMSharedMemory) -> Self {
Self(Box::new(mem))
}
}
/// Represents linear memory that can be either owned or shared
#[derive(Debug)]
pub struct VMMemory(pub Box<dyn LinearMemory + 'static>);
@@ -357,8 +453,12 @@ impl VMMemory {
///
/// This creates a `Memory` with owned metadata: this can be used to create a memory
/// that will be imported into Wasm modules.
pub fn new(memory: &MemoryType, style: &MemoryStyle) -> Result<Self, MemoryError> {
Ok(Self(Box::new(VMOwnedMemory::new(memory, style)?)))
pub fn new(memory: &MemoryType, style: &MemoryStyle) -> Result<VMMemory, MemoryError> {
Ok(if memory.shared {
Self(Box::new(VMSharedMemory::new(memory, style)?))
} else {
Self(Box::new(VMOwnedMemory::new(memory, style)?))
})
}
/// Returns the number of pages in the allocated memory block
@@ -377,12 +477,20 @@ impl VMMemory {
memory: &MemoryType,
style: &MemoryStyle,
vm_memory_location: NonNull<VMMemoryDefinition>,
) -> Result<Self, MemoryError> {
Ok(Self(Box::new(VMOwnedMemory::from_definition(
memory,
style,
vm_memory_location,
)?)))
) -> Result<VMMemory, MemoryError> {
Ok(if memory.shared {
Self(Box::new(VMSharedMemory::from_definition(
memory,
style,
vm_memory_location,
)?))
} else {
Self(Box::new(VMOwnedMemory::from_definition(
memory,
style,
vm_memory_location,
)?))
})
}
/// Creates VMMemory from a custom implementation - the following into implementations