Skip to content

Commit 6ce2ac1

Browse files
authored
Refactor shared memory internals, expose embedder methods (#5311)
This commit refactors the internals of `wasmtime_runtime::SharedMemory` a bit to expose the necessary functions to invoke from the `wasmtime::SharedMemory` layer. Notably some items are moved out of the `RwLock` from prior, such as the type and the `VMMemoryDefinition`. Additionally the organization around the `atomic_*` methods has been redone to ensure that the `wasmtime`-layer abstraction has a single method to call into which everything else uses as well.
1 parent 0a2a044 commit 6ce2ac1

File tree

9 files changed

+373
-218
lines changed

9 files changed

+373
-218
lines changed

crates/runtime/src/instance.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -966,8 +966,8 @@ impl Instance {
966966
let def_ptr = self.memories[defined_memory_index]
967967
.as_shared_memory()
968968
.unwrap()
969-
.vmmemory_ptr_mut();
970-
ptr::write(ptr, def_ptr);
969+
.vmmemory_ptr();
970+
ptr::write(ptr, def_ptr.cast_mut());
971971
} else {
972972
ptr::write(owned_ptr, self.memories[defined_memory_index].vmmemory());
973973
ptr::write(ptr, owned_ptr);

crates/runtime/src/lib.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,17 @@ pub fn page_size() -> usize {
231231
unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }
232232
}
233233
}
234+
235+
/// Result of [`Memory::atomic_wait32`] and [`Memory::atomic_wait64`]
236+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
237+
pub enum WaitResult {
238+
/// Indicates that a `wait` completed by being awoken by a different thread.
239+
/// This means the thread went to sleep and didn't time out.
240+
Ok = 0,
241+
/// Indicates that `wait` did not complete and instead returned due to the
242+
/// value in memory not matching the expected value.
243+
Mismatch = 1,
244+
/// Indicates that `wait` completed with a timeout, meaning that the
245+
/// original value matched as expected but nothing ever called `notify`.
246+
TimedOut = 2,
247+
}

crates/runtime/src/libcalls.rs

Lines changed: 10 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
use crate::externref::VMExternRef;
5858
use crate::table::{Table, TableElementType};
5959
use crate::vmcontext::{VMCallerCheckedAnyfunc, VMContext};
60-
use crate::{SharedMemory, TrapReason};
60+
use crate::TrapReason;
6161
use anyhow::Result;
6262
use std::mem;
6363
use std::ptr::{self, NonNull};
@@ -436,25 +436,12 @@ unsafe fn memory_atomic_notify(
436436
memory_index: u32,
437437
addr_index: u64,
438438
count: u32,
439-
) -> Result<u32, TrapReason> {
439+
) -> Result<u32, Trap> {
440440
let memory = MemoryIndex::from_u32(memory_index);
441441
let instance = (*vmctx).instance_mut();
442442
instance
443-
.get_memory(memory)
444-
.validate_addr(addr_index, 4, 4)?;
445-
446-
let shared_mem = instance.get_runtime_memory(memory).as_shared_memory();
447-
448-
if count == 0 {
449-
return Ok(0);
450-
}
451-
452-
let unparked_threads = shared_mem.map_or(0, |shared_mem| {
453-
// SAFETY: checked `addr_index` above
454-
unsafe { shared_mem.unchecked_atomic_notify(addr_index, count) }
455-
});
456-
457-
Ok(unparked_threads)
443+
.get_runtime_memory(memory)
444+
.atomic_notify(addr_index, count)
458445
}
459446

460447
// Implementation of `memory.atomic.wait32` for locally defined memories.
@@ -464,24 +451,14 @@ unsafe fn memory_atomic_wait32(
464451
addr_index: u64,
465452
expected: u32,
466453
timeout: u64,
467-
) -> Result<u32, TrapReason> {
454+
) -> Result<u32, Trap> {
468455
// convert timeout to Instant, before any wait happens on locking
469456
let timeout = (timeout as i64 >= 0).then(|| Instant::now() + Duration::from_nanos(timeout));
470-
471457
let memory = MemoryIndex::from_u32(memory_index);
472458
let instance = (*vmctx).instance_mut();
473-
let addr = instance
474-
.get_memory(memory)
475-
.validate_addr(addr_index, 4, 4)?;
476-
477-
let shared_mem: SharedMemory = instance
459+
Ok(instance
478460
.get_runtime_memory(memory)
479-
.as_shared_memory()
480-
.ok_or(Trap::AtomicWaitNonSharedMemory)?;
481-
482-
// SAFETY: checked `addr_index` above
483-
let res = unsafe { shared_mem.unchecked_atomic_wait32(addr_index, addr, expected, timeout) };
484-
Ok(res)
461+
.atomic_wait32(addr_index, expected, timeout)? as u32)
485462
}
486463

487464
// Implementation of `memory.atomic.wait64` for locally defined memories.
@@ -491,24 +468,14 @@ unsafe fn memory_atomic_wait64(
491468
addr_index: u64,
492469
expected: u64,
493470
timeout: u64,
494-
) -> Result<u32, TrapReason> {
471+
) -> Result<u32, Trap> {
495472
// convert timeout to Instant, before any wait happens on locking
496473
let timeout = (timeout as i64 >= 0).then(|| Instant::now() + Duration::from_nanos(timeout));
497-
498474
let memory = MemoryIndex::from_u32(memory_index);
499475
let instance = (*vmctx).instance_mut();
500-
let addr = instance
501-
.get_memory(memory)
502-
.validate_addr(addr_index, 8, 8)?;
503-
504-
let shared_mem: SharedMemory = instance
476+
Ok(instance
505477
.get_runtime_memory(memory)
506-
.as_shared_memory()
507-
.ok_or(Trap::AtomicWaitNonSharedMemory)?;
508-
509-
// SAFETY: checked `addr_index` above
510-
let res = unsafe { shared_mem.unchecked_atomic_wait64(addr_index, addr, expected, timeout) };
511-
Ok(res)
478+
.atomic_wait64(addr_index, expected, timeout)? as u32)
512479
}
513480

514481
// Hook for when an instance runs out of fuel.

0 commit comments

Comments
 (0)