Skip to content

Commit 77ed691

Browse files
committed
Add a method on Store to draw an MMU-based epoch to a close.
Keep the guts of the page-protecting operation on `VMStoreContext` next to where the page is mapped and unmapped.
1 parent 1d94a21 commit 77ed691

2 files changed

Lines changed: 21 additions & 1 deletion

File tree

crates/wasmtime/src/runtime/store.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,6 +1030,12 @@ impl<T> Store<T> {
10301030
) {
10311031
self.inner.epoch_deadline_callback(Box::new(callback));
10321032
}
1033+
1034+
/// Trigger the ending of the current "epoch" as soon as possible, if using
1035+
/// [`Config::epoch_interruption_via_mmu()`]. Panic if not.
1036+
pub fn end_epoch_via_mmu(&mut self) {
1037+
self.inner.inner.vm_store_context.protect_interrupt_page()
1038+
}
10331039
}
10341040

10351041
impl<'a, T> StoreContext<'a, T> {

crates/wasmtime/src/runtime/vm/vmcontext.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use core::mem::{self, MaybeUninit};
1616
use core::ops::Range;
1717
use core::ptr::{self, NonNull};
1818
use core::sync::atomic::{AtomicUsize, Ordering};
19-
use rustix::mm::{MapFlags, ProtFlags, mmap_anonymous, munmap};
19+
use rustix::mm::{MapFlags, MprotectFlags, ProtFlags, mmap_anonymous, mprotect, munmap};
2020
use rustix::param::page_size;
2121
use wasmtime_environ::{
2222
BuiltinFunctionIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex,
@@ -1227,6 +1227,20 @@ impl VMStoreContext {
12271227
ret
12281228
}
12291229

1230+
/// Twiddles MMU access control bits such that reads from the interrupt page
1231+
/// will cause a segfault. This effectively ends the epoch, as running wasm
1232+
/// will soon execute such reads.
1233+
pub fn protect_interrupt_page(&self) {
1234+
if let Some(page_ptr) = self.epoch_interrupt_page_ptr {
1235+
unsafe {
1236+
mprotect(page_ptr.as_ptr(), page_size(), MprotectFlags::empty())
1237+
.expect("any error from mprotect is a programming error")
1238+
}
1239+
} else {
1240+
panic!("called protect_interrupt_page though epoch-interruption-via-mmu was not on")
1241+
}
1242+
}
1243+
12301244
/// Disposes of any allocated epoch interrupt page. This must be called if
12311245
/// [`VMStoreContext::with_interrupt_page()`] was used to construct this
12321246
/// instance, lest we leak a page.

0 commit comments

Comments
 (0)