More PR feedback changes.

* More use of `anyhow`.
* Change `make_accessible` into `protect_linear_memory` to better demonstrate
  what it is used for; this will make the uffd implementation make a little
  more sense.
* Remove `create_memory_map` in favor of just creating the `Mmap` instances in
  the pooling allocator. This also removes the need for `MAP_NORESERVE` in the
  uffd implementation.
* Moar comments.
* Remove `BasePointerIterator` in favor of `impl Iterator`.
* The uffd implementation now only monitors linear memory pages and will only
  receive faults on pages that could potentially be accessible and never on a
  statically known guard page.
* Stop allocating memory or table pools if the maximum limit of the memory or
  table is 0.
This commit is contained in:
Peter Huene
2021-03-04 14:01:42 -08:00
parent a464465e2f
commit ff840b3d3b
11 changed files with 484 additions and 500 deletions

View File

@@ -1,6 +1,7 @@
//! Low-level abstraction for allocating and managing zero-filled pages
//! of memory.
use anyhow::{bail, Result};
use more_asserts::assert_le;
use more_asserts::assert_lt;
use std::io;
@@ -38,7 +39,7 @@ impl Mmap {
}
/// Create a new `Mmap` pointing to at least `size` bytes of page-aligned accessible memory.
pub fn with_at_least(size: usize) -> Result<Self, String> {
pub fn with_at_least(size: usize) -> Result<Self> {
let page_size = region::page::size();
let rounded_size = round_up_to_page_size(size, page_size);
Self::accessible_reserved(rounded_size, rounded_size)
@@ -48,10 +49,7 @@ impl Mmap {
/// within a reserved mapping of `mapping_size` bytes. `accessible_size` and `mapping_size`
/// must be native page-size multiples.
#[cfg(not(target_os = "windows"))]
pub fn accessible_reserved(
accessible_size: usize,
mapping_size: usize,
) -> Result<Self, String> {
pub fn accessible_reserved(accessible_size: usize, mapping_size: usize) -> Result<Self> {
let page_size = region::page::size();
assert_le!(accessible_size, mapping_size);
assert_eq!(mapping_size & (page_size - 1), 0);
@@ -76,7 +74,7 @@ impl Mmap {
)
};
if ptr as isize == -1_isize {
return Err(io::Error::last_os_error().to_string());
bail!("mmap failed: {}", io::Error::last_os_error());
}
Self {
@@ -96,7 +94,7 @@ impl Mmap {
)
};
if ptr as isize == -1_isize {
return Err(io::Error::last_os_error().to_string());
bail!("mmap failed: {}", io::Error::last_os_error());
}
let mut result = Self {
@@ -117,10 +115,7 @@ impl Mmap {
/// within a reserved mapping of `mapping_size` bytes. `accessible_size` and `mapping_size`
/// must be native page-size multiples.
#[cfg(target_os = "windows")]
pub fn accessible_reserved(
accessible_size: usize,
mapping_size: usize,
) -> Result<Self, String> {
pub fn accessible_reserved(accessible_size: usize, mapping_size: usize) -> Result<Self> {
use winapi::um::memoryapi::VirtualAlloc;
use winapi::um::winnt::{MEM_COMMIT, MEM_RESERVE, PAGE_NOACCESS, PAGE_READWRITE};
@@ -144,7 +139,7 @@ impl Mmap {
)
};
if ptr.is_null() {
return Err(io::Error::last_os_error().to_string());
bail!("VirtualAlloc failed: {}", io::Error::last_os_error());
}
Self {
@@ -156,7 +151,7 @@ impl Mmap {
let ptr =
unsafe { VirtualAlloc(ptr::null_mut(), mapping_size, MEM_RESERVE, PAGE_NOACCESS) };
if ptr.is_null() {
return Err(io::Error::last_os_error().to_string());
bail!("VirtualAlloc failed: {}", io::Error::last_os_error());
}
let mut result = Self {
@@ -177,7 +172,7 @@ impl Mmap {
/// `start` and `len` must be native page-size multiples and describe a range within
/// `self`'s reserved memory.
#[cfg(not(target_os = "windows"))]
pub fn make_accessible(&mut self, start: usize, len: usize) -> Result<(), String> {
pub fn make_accessible(&mut self, start: usize, len: usize) -> Result<()> {
let page_size = region::page::size();
assert_eq!(start & (page_size - 1), 0);
assert_eq!(len & (page_size - 1), 0);
@@ -186,15 +181,18 @@ impl Mmap {
// Commit the accessible size.
let ptr = self.ptr as *const u8;
unsafe { region::protect(ptr.add(start), len, region::Protection::READ_WRITE) }
.map_err(|e| e.to_string())
unsafe {
region::protect(ptr.add(start), len, region::Protection::READ_WRITE)?;
}
Ok(())
}
/// Make the memory starting at `start` and extending for `len` bytes accessible.
/// `start` and `len` must be native page-size multiples and describe a range within
/// `self`'s reserved memory.
#[cfg(target_os = "windows")]
pub fn make_accessible(&mut self, start: usize, len: usize) -> Result<(), String> {
pub fn make_accessible(&mut self, start: usize, len: usize) -> Result<()> {
use winapi::ctypes::c_void;
use winapi::um::memoryapi::VirtualAlloc;
use winapi::um::winnt::{MEM_COMMIT, PAGE_READWRITE};
@@ -216,7 +214,7 @@ impl Mmap {
}
.is_null()
{
return Err(io::Error::last_os_error().to_string());
bail!("VirtualAlloc failed: {}", io::Error::last_os_error());
}
Ok(())