Remove dependency on the region crate (#4407)
This commit removes Wasmtime's dependency on the `region` crate. The motivation for this came about when I was updating dependencies and saw that `region` had a new major version at 3.0.0 as opposed to our currently used 2.3 track. In reviewing the use cases of `region` within Wasmtime I found two trends in particular which motivated this commit: * Some unix-specific areas of `wasmtime_runtime` use `rustix::mm::mprotect` instead of `region::protect` already. This means that the usage of `region::protect` for changing virtual memory protections was already inconsistent. * Many uses of `region::protect` were already in unix-specific regions which could make use of `rustix`. Overall I opted to remove the dependency on the `region` crate to avoid chasing its versions over time. Unix-specific changes of protections were easily changed to `rustix::mm::mprotect`. There were two locations where a windows/unix split is now required and I subjectively ruled "that seems ok". Finally removing `region` also meant that the "what is the current page size" query needed to be inlined into `wasmtime_runtime`, which I have also subjectively ruled "that seems fine". Finally one final refactoring here was that the `unix.rs` and `linux.rs` split for the pooling allocator was merged. These two files already only differed in one function so I slapped a `cfg_if!` in there to help reduce the duplication.
This commit is contained in:
@@ -30,9 +30,6 @@ cfg_if::cfg_if! {
|
||||
if #[cfg(windows)] {
|
||||
mod windows;
|
||||
use windows as imp;
|
||||
} else if #[cfg(target_os = "linux")] {
|
||||
mod linux;
|
||||
use linux as imp;
|
||||
} else {
|
||||
mod unix;
|
||||
use unix as imp;
|
||||
@@ -217,7 +214,7 @@ impl InstancePool {
|
||||
instance_limits: &InstanceLimits,
|
||||
tunables: &Tunables,
|
||||
) -> Result<Self> {
|
||||
let page_size = region::page::size();
|
||||
let page_size = crate::page_size();
|
||||
|
||||
let instance_size = round_up_to_pow2(instance_limits.size, mem::align_of::<Instance>());
|
||||
|
||||
@@ -692,7 +689,7 @@ impl MemoryPool {
|
||||
};
|
||||
|
||||
assert!(
|
||||
memory_size % region::page::size() == 0,
|
||||
memory_size % crate::page_size() == 0,
|
||||
"memory size {} is not a multiple of system page size",
|
||||
memory_size
|
||||
);
|
||||
@@ -828,7 +825,7 @@ struct TablePool {
|
||||
|
||||
impl TablePool {
|
||||
fn new(instance_limits: &InstanceLimits) -> Result<Self> {
|
||||
let page_size = region::page::size();
|
||||
let page_size = crate::page_size();
|
||||
|
||||
let table_size = round_up_to_pow2(
|
||||
mem::size_of::<*mut u8>()
|
||||
@@ -895,7 +892,9 @@ struct StackPool {
|
||||
#[cfg(all(feature = "async", unix))]
|
||||
impl StackPool {
|
||||
fn new(instance_limits: &InstanceLimits, stack_size: usize) -> Result<Self> {
|
||||
let page_size = region::page::size();
|
||||
use rustix::mm::{mprotect, MprotectFlags};
|
||||
|
||||
let page_size = crate::page_size();
|
||||
|
||||
// Add a page to the stack size for the guard page when using fiber stacks
|
||||
let stack_size = if stack_size == 0 {
|
||||
@@ -921,7 +920,7 @@ impl StackPool {
|
||||
for i in 0..max_instances {
|
||||
// Make the stack guard page inaccessible
|
||||
let bottom_of_stack = mapping.as_mut_ptr().add(i * stack_size);
|
||||
region::protect(bottom_of_stack, page_size, region::Protection::NONE)
|
||||
mprotect(bottom_of_stack.cast(), page_size, MprotectFlags::empty())
|
||||
.context("failed to protect stack guard page")?;
|
||||
}
|
||||
}
|
||||
@@ -1298,7 +1297,7 @@ mod test {
|
||||
..Default::default()
|
||||
})?;
|
||||
|
||||
let host_page_size = region::page::size();
|
||||
let host_page_size = crate::page_size();
|
||||
|
||||
assert_eq!(pool.table_size, host_page_size);
|
||||
assert_eq!(pool.max_tables, 4);
|
||||
@@ -1335,7 +1334,7 @@ mod test {
|
||||
1,
|
||||
)?;
|
||||
|
||||
let native_page_size = region::page::size();
|
||||
let native_page_size = crate::page_size();
|
||||
assert_eq!(pool.stack_size, 2 * native_page_size);
|
||||
assert_eq!(pool.max_instances, 10);
|
||||
assert_eq!(pool.page_size, native_page_size);
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
use anyhow::{Context, Result};
|
||||
|
||||
fn decommit(addr: *mut u8, len: usize, protect: bool) -> Result<()> {
|
||||
if len == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
unsafe {
|
||||
if protect {
|
||||
region::protect(addr, len, region::Protection::NONE)
|
||||
.context("failed to protect memory pages")?;
|
||||
}
|
||||
|
||||
// On Linux, this is enough to cause the kernel to initialize the pages to 0 on next access
|
||||
rustix::mm::madvise(addr as _, len, rustix::mm::Advice::LinuxDontNeed)
|
||||
.context("madvise failed to decommit: {}")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn commit_memory_pages(addr: *mut u8, len: usize) -> Result<()> {
|
||||
if len == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Just change the protection level to READ|WRITE
|
||||
unsafe {
|
||||
region::protect(addr, len, region::Protection::READ_WRITE)
|
||||
.context("failed to make linear memory pages read/write")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decommit_memory_pages(addr: *mut u8, len: usize) -> Result<()> {
|
||||
decommit(addr, len, true)
|
||||
}
|
||||
|
||||
pub fn commit_table_pages(_addr: *mut u8, _len: usize) -> Result<()> {
|
||||
// A no-op as table pages remain READ|WRITE
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn decommit_table_pages(addr: *mut u8, len: usize) -> Result<()> {
|
||||
decommit(addr, len, false)
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
pub fn commit_stack_pages(_addr: *mut u8, _len: usize) -> Result<()> {
|
||||
// A no-op as stack pages remain READ|WRITE
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
pub fn decommit_stack_pages(addr: *mut u8, len: usize) -> Result<()> {
|
||||
decommit(addr, len, false)
|
||||
}
|
||||
@@ -1,26 +1,45 @@
|
||||
use anyhow::{Context, Result};
|
||||
use rustix::mm::{mprotect, MprotectFlags};
|
||||
|
||||
fn decommit(addr: *mut u8, len: usize, protect: bool) -> Result<()> {
|
||||
if len == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// By creating a new mapping at the same location, this will discard the
|
||||
// mapping for the pages in the given range.
|
||||
// The new mapping will be to the CoW zero page, so this effectively
|
||||
// zeroes the pages.
|
||||
unsafe {
|
||||
rustix::mm::mmap_anonymous(
|
||||
addr as _,
|
||||
len,
|
||||
if protect {
|
||||
rustix::mm::ProtFlags::empty()
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_os = "linux")] {
|
||||
use rustix::mm::{madvise, Advice};
|
||||
|
||||
if protect {
|
||||
mprotect(addr.cast(), len, MprotectFlags::empty())
|
||||
.context("failed to protect memory pages")?;
|
||||
}
|
||||
|
||||
// On Linux, this is enough to cause the kernel to initialize
|
||||
// the pages to 0 on next access
|
||||
madvise(addr as _, len, Advice::LinuxDontNeed)
|
||||
.context("madvise failed to decommit: {}")?;
|
||||
} else {
|
||||
rustix::mm::ProtFlags::READ | rustix::mm::ProtFlags::WRITE
|
||||
},
|
||||
rustix::mm::MapFlags::PRIVATE | rustix::mm::MapFlags::FIXED,
|
||||
)
|
||||
.context("mmap failed to remap pages: {}")?;
|
||||
use rustix::mm::{mmap_anonymous, ProtFlags, MapFlags};
|
||||
|
||||
// By creating a new mapping at the same location, this will
|
||||
// discard the mapping for the pages in the given range.
|
||||
// The new mapping will be to the CoW zero page, so this
|
||||
// effectively zeroes the pages.
|
||||
mmap_anonymous(
|
||||
addr as _,
|
||||
len,
|
||||
if protect {
|
||||
ProtFlags::empty()
|
||||
} else {
|
||||
ProtFlags::READ | ProtFlags::WRITE
|
||||
},
|
||||
MapFlags::PRIVATE | MapFlags::FIXED,
|
||||
)
|
||||
.context("mmap failed to remap pages: {}")?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -33,7 +52,7 @@ pub fn commit_memory_pages(addr: *mut u8, len: usize) -> Result<()> {
|
||||
|
||||
// Just change the protection level to READ|WRITE
|
||||
unsafe {
|
||||
region::protect(addr, len, region::Protection::READ_WRITE)
|
||||
mprotect(addr.cast(), len, MprotectFlags::READ | MprotectFlags::WRITE)
|
||||
.context("failed to make linear memory pages read/write")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user