Use std::alloc::alloc instead of libc::posix_memalign.
This makes Cranelift use the Rust `alloc` API its allocations, rather than directly calling into `libc`, which makes it respect the `#[global_allocator]` configuration. Also, use `region::page::ceil` instead of having our own copies of that logic.
This commit is contained in:
@@ -1,20 +1,13 @@
|
|||||||
#[cfg(not(any(feature = "selinux-fix", windows)))]
|
|
||||||
use libc;
|
|
||||||
|
|
||||||
#[cfg(feature = "selinux-fix")]
|
#[cfg(feature = "selinux-fix")]
|
||||||
use memmap2::MmapMut;
|
use memmap2::MmapMut;
|
||||||
|
|
||||||
use region;
|
#[cfg(not(any(feature = "selinux-fix", windows)))]
|
||||||
|
use std::alloc;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
/// Round `size` up to the nearest multiple of `page_size`.
|
|
||||||
fn round_up_to_page_size(size: usize, page_size: usize) -> usize {
|
|
||||||
(size + (page_size - 1)) & !(page_size - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A simple struct consisting of a pointer and length.
|
/// A simple struct consisting of a pointer and length.
|
||||||
struct PtrLen {
|
struct PtrLen {
|
||||||
#[cfg(feature = "selinux-fix")]
|
#[cfg(feature = "selinux-fix")]
|
||||||
@@ -40,8 +33,7 @@ impl PtrLen {
|
|||||||
/// suitably sized and aligned for memory protection.
|
/// suitably sized and aligned for memory protection.
|
||||||
#[cfg(all(not(target_os = "windows"), feature = "selinux-fix"))]
|
#[cfg(all(not(target_os = "windows"), feature = "selinux-fix"))]
|
||||||
fn with_size(size: usize) -> io::Result<Self> {
|
fn with_size(size: usize) -> io::Result<Self> {
|
||||||
let page_size = region::page::size();
|
let alloc_size = region::page::ceil(size);
|
||||||
let alloc_size = round_up_to_page_size(size, page_size);
|
|
||||||
MmapMut::map_anon(alloc_size).map(|mut mmap| {
|
MmapMut::map_anon(alloc_size).map(|mut mmap| {
|
||||||
// The order here is important; we assign the pointer first to get
|
// The order here is important; we assign the pointer first to get
|
||||||
// around compile time borrow errors.
|
// around compile time borrow errors.
|
||||||
@@ -55,21 +47,17 @@ impl PtrLen {
|
|||||||
|
|
||||||
#[cfg(all(not(target_os = "windows"), not(feature = "selinux-fix")))]
|
#[cfg(all(not(target_os = "windows"), not(feature = "selinux-fix")))]
|
||||||
fn with_size(size: usize) -> io::Result<Self> {
|
fn with_size(size: usize) -> io::Result<Self> {
|
||||||
let mut ptr = ptr::null_mut();
|
assert_ne!(size, 0);
|
||||||
let page_size = region::page::size();
|
let page_size = region::page::size();
|
||||||
let alloc_size = round_up_to_page_size(size, page_size);
|
let alloc_size = region::page::ceil(size);
|
||||||
unsafe {
|
let layout = alloc::Layout::from_size_align(alloc_size, page_size).unwrap();
|
||||||
let err = libc::posix_memalign(&mut ptr, page_size, alloc_size);
|
// Safety: We assert that the size is non-zero above.
|
||||||
|
let ptr = unsafe { alloc::alloc(layout) };
|
||||||
|
|
||||||
if err == 0 {
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
ptr: ptr as *mut u8,
|
ptr,
|
||||||
len: alloc_size,
|
len: alloc_size,
|
||||||
})
|
})
|
||||||
} else {
|
|
||||||
Err(io::Error::from_raw_os_error(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
@@ -77,8 +65,6 @@ impl PtrLen {
|
|||||||
use winapi::um::memoryapi::VirtualAlloc;
|
use winapi::um::memoryapi::VirtualAlloc;
|
||||||
use winapi::um::winnt::{MEM_COMMIT, MEM_RESERVE, PAGE_READWRITE};
|
use winapi::um::winnt::{MEM_COMMIT, MEM_RESERVE, PAGE_READWRITE};
|
||||||
|
|
||||||
let page_size = region::page::size();
|
|
||||||
|
|
||||||
// VirtualAlloc always rounds up to the next multiple of the page size
|
// VirtualAlloc always rounds up to the next multiple of the page size
|
||||||
let ptr = unsafe {
|
let ptr = unsafe {
|
||||||
VirtualAlloc(
|
VirtualAlloc(
|
||||||
@@ -91,7 +77,7 @@ impl PtrLen {
|
|||||||
if !ptr.is_null() {
|
if !ptr.is_null() {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
ptr: ptr as *mut u8,
|
ptr: ptr as *mut u8,
|
||||||
len: round_up_to_page_size(size, page_size),
|
len: region::page::ceil(size),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(io::Error::last_os_error())
|
Err(io::Error::last_os_error())
|
||||||
@@ -104,10 +90,12 @@ impl PtrLen {
|
|||||||
impl Drop for PtrLen {
|
impl Drop for PtrLen {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if !self.ptr.is_null() {
|
if !self.ptr.is_null() {
|
||||||
|
let page_size = region::page::size();
|
||||||
|
let layout = alloc::Layout::from_size_align(self.len, page_size).unwrap();
|
||||||
unsafe {
|
unsafe {
|
||||||
region::protect(self.ptr, self.len, region::Protection::READ_WRITE)
|
region::protect(self.ptr, self.len, region::Protection::READ_WRITE)
|
||||||
.expect("unable to unprotect memory");
|
.expect("unable to unprotect memory");
|
||||||
libc::free(self.ptr as _);
|
alloc::dealloc(self.ptr, layout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -237,16 +225,3 @@ impl Drop for Memory {
|
|||||||
.for_each(mem::forget);
|
.for_each(mem::forget);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_round_up_to_page_size() {
|
|
||||||
assert_eq!(round_up_to_page_size(0, 4096), 0);
|
|
||||||
assert_eq!(round_up_to_page_size(1, 4096), 4096);
|
|
||||||
assert_eq!(round_up_to_page_size(4096, 4096), 4096);
|
|
||||||
assert_eq!(round_up_to_page_size(4097, 4096), 8192);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -12,11 +12,6 @@ use std::path::Path;
|
|||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
|
||||||
/// Round `size` up to the nearest multiple of `page_size`.
|
|
||||||
fn round_up_to_page_size(size: usize, page_size: usize) -> usize {
|
|
||||||
(size + (page_size - 1)) & !(page_size - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A simple struct consisting of a page-aligned pointer to page-aligned
|
/// A simple struct consisting of a page-aligned pointer to page-aligned
|
||||||
/// and initially-zeroed memory and a length.
|
/// and initially-zeroed memory and a length.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -46,8 +41,7 @@ impl Mmap {
|
|||||||
|
|
||||||
/// Create a new `Mmap` pointing to at least `size` bytes of page-aligned accessible memory.
|
/// Create a new `Mmap` pointing to at least `size` bytes of page-aligned accessible memory.
|
||||||
pub fn with_at_least(size: usize) -> Result<Self> {
|
pub fn with_at_least(size: usize) -> Result<Self> {
|
||||||
let page_size = region::page::size();
|
let rounded_size = region::page::ceil(size);
|
||||||
let rounded_size = round_up_to_page_size(size, page_size);
|
|
||||||
Self::accessible_reserved(rounded_size, rounded_size)
|
Self::accessible_reserved(rounded_size, rounded_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,16 +466,3 @@ fn _assert() {
|
|||||||
fn _assert_send_sync<T: Send + Sync>() {}
|
fn _assert_send_sync<T: Send + Sync>() {}
|
||||||
_assert_send_sync::<Mmap>();
|
_assert_send_sync::<Mmap>();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_round_up_to_page_size() {
|
|
||||||
assert_eq!(round_up_to_page_size(0, 4096), 0);
|
|
||||||
assert_eq!(round_up_to_page_size(1, 4096), 4096);
|
|
||||||
assert_eq!(round_up_to_page_size(4096, 4096), 4096);
|
|
||||||
assert_eq!(round_up_to_page_size(4097, 4096), 8192);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user