Fix Wait/Notify opcode, the waiters hashmap is now on the Memory itself (#3723)

* Fix Wait/Notify opcode, the waiters hashmap is now on the Memory itself

* Refactored for clarity

* Use WAIT_ERROR everywhere

* Change from WAIT_ERROR to Option

* Added some unit test for threadconditions

* Switch from `Mutex<HashMap<...>>` to `DashMap<...>` for the NotifyMap

* Use FnvHasher for Dashmap

* Change timeout value in unit test to leave more margin to the system to react.

* Consolidate code, avoid duplication

* Put test in a test module

* Use an Result with custom error instead of an option for waiter
This commit is contained in:
ptitSeb
2023-04-13 17:36:41 +02:00
committed by GitHub
parent 60107df769
commit b2170e3e4f
6 changed files with 346 additions and 124 deletions

View File

@@ -5,6 +5,8 @@
//!
//! `Memory` is to WebAssembly linear memories what `Table` is to WebAssembly tables.
use crate::threadconditions::ThreadConditions;
pub use crate::threadconditions::{NotifyLocation, WaiterError};
use crate::trap::Trap;
use crate::{mmap::Mmap, store::MaybeInstanceOwned, vmcontext::VMMemoryDefinition};
use more_asserts::assert_ge;
@@ -13,6 +15,7 @@ use std::convert::TryInto;
use std::ptr::NonNull;
use std::slice;
use std::sync::{Arc, RwLock};
use std::time::Duration;
use wasmer_types::{Bytes, MemoryError, MemoryStyle, MemoryType, Pages};
// The memory mapped area
@@ -285,6 +288,7 @@ impl VMOwnedMemory {
VMSharedMemory {
mmap: Arc::new(RwLock::new(self.mmap)),
config: self.config,
conditions: ThreadConditions::new(),
}
}
@@ -346,6 +350,8 @@ pub struct VMSharedMemory {
mmap: Arc<RwLock<WasmMmap>>,
// Configuration of this memory
config: VMMemoryConfig,
// waiters list for this memory
conditions: ThreadConditions,
}
unsafe impl Send for VMSharedMemory {}
@@ -381,6 +387,7 @@ impl VMSharedMemory {
Ok(Self {
mmap: Arc::new(RwLock::new(guard.duplicate()?)),
config: self.config.clone(),
conditions: ThreadConditions::new(),
})
}
}
@@ -431,6 +438,20 @@ impl LinearMemory for VMSharedMemory {
let forked = Self::duplicate(self)?;
Ok(Box::new(forked))
}
// Add current thread to waiter list
fn do_wait(
&mut self,
dst: NotifyLocation,
timeout: Option<Duration>,
) -> Result<u32, WaiterError> {
self.conditions.do_wait(dst, timeout)
}
/// Notify waiters from the wait list. Return the number of waiters notified
fn do_notify(&mut self, dst: NotifyLocation, count: u32) -> u32 {
self.conditions.do_notify(dst, count)
}
}
impl From<VMOwnedMemory> for VMMemory {
@@ -498,6 +519,20 @@ impl LinearMemory for VMMemory {
fn duplicate(&mut self) -> Result<Box<dyn LinearMemory + 'static>, MemoryError> {
self.0.duplicate()
}
// Add current thread to waiter list
fn do_wait(
&mut self,
dst: NotifyLocation,
timeout: Option<Duration>,
) -> Result<u32, WaiterError> {
self.0.do_wait(dst, timeout)
}
/// Notify waiters from the wait list. Return the number of waiters notified
fn do_notify(&mut self, dst: NotifyLocation, count: u32) -> u32 {
self.0.do_notify(dst, count)
}
}
impl VMMemory {
@@ -616,4 +651,19 @@ where
/// Copies this memory to a new memory
fn duplicate(&mut self) -> Result<Box<dyn LinearMemory + 'static>, MemoryError>;
/// Add current thread to the waiter hash, and wait until notified or timout.
/// Return 0 if the waiter has been notified, 2 if the timeout occured, or None if en error happened
fn do_wait(
&mut self,
_dst: NotifyLocation,
_timeout: Option<Duration>,
) -> Result<u32, WaiterError> {
Err(WaiterError::Unimplemented)
}
/// Notify waiters from the wait list. Return the number of waiters notified
fn do_notify(&mut self, _dst: NotifyLocation, _count: u32) -> u32 {
0
}
}