Skip to content

Commit

Permalink
Add huge pages support.
Browse files Browse the repository at this point in the history
  • Loading branch information
ollie-etl committed Oct 10, 2023
1 parent f16835d commit 3c71286
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 7 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
### Changed
- Added `MmapOptions::huge` method to support mapping hugetlb. Linux only.
[@ollie-etl](https://github.com/ollie-etl)
[@oliverbunting](https://github.com/oliverbunting)

## [0.9.0] - 2023-10-03
### Changed
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ This is a **fork** of the [memmap-rs](https://github.com/danburkert/memmap-rs) c
- [x] read-only memory maps
- [x] stack support (`MAP_STACK` on unix)
- [x] executable memory maps
- [ ] huge page support
- [x] huge page support (linux only)

A list of supported/tested targets can be found in [Actions](https://github.com/RazrFalcon/memmap2-rs/actions).

Expand Down
28 changes: 27 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ where
pub struct MmapOptions {
offset: u64,
len: Option<usize>,
huge: Option<u8>,
stack: bool,
populate: bool,
}
Expand Down Expand Up @@ -281,6 +282,30 @@ impl MmapOptions {
self
}

/// Configures the anonymous memory map to be allocated using huge pages.
///
/// This option corresponds to the `MAP_HUGETLB` flag on Linux. It has no effect on Windows.
///
/// The size of the requested page can be specified in page bits. If not provided, the system
/// default is requested. The requested length should be a multiple of this, or the mapping
/// will fail.
///
/// This option has no effect on file-backed memory maps.
///
/// # Example
///
/// ```
/// use memmap2::MmapOptions;
///
/// # fn main() -> std::io::Result<()> {
/// let stack = MmapOptions::new().huge(Some(21)).len(2*1024*1024).map_anon();
/// # Ok(())
/// # }
/// ```
pub fn huge(&mut self, page_bits: Option<u8>) -> &mut Self {
self.huge = Some(page_bits.unwrap_or(0));
self
}
/// Populate (prefault) page tables for a mapping.
///
/// For a file mapping, this causes read-ahead on the file. This will help to reduce blocking on page faults later.
Expand Down Expand Up @@ -484,7 +509,8 @@ impl MmapOptions {
));
}

MmapInner::map_anon(len, self.stack, self.populate).map(|inner| MmapMut { inner })
MmapInner::map_anon(len, self.stack, self.populate, self.huge)
.map(|inner| MmapMut { inner })
}

/// Creates a raw memory map.
Expand Down
2 changes: 1 addition & 1 deletion src/stub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ impl MmapInner {
MmapInner::new()
}

pub fn map_anon(_: usize, _: bool, _: bool) -> io::Result<MmapInner> {
pub fn map_anon(_: usize, _: bool, _: bool, _: Option<u8>) -> io::Result<MmapInner> {
MmapInner::new()
}

Expand Down
33 changes: 30 additions & 3 deletions src/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,24 @@ const MAP_POPULATE: libc::c_int = libc::MAP_POPULATE;
#[cfg(not(any(target_os = "linux", target_os = "android")))]
const MAP_POPULATE: libc::c_int = 0;

#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "android"))]
const MAP_HUGETLB: libc::c_int = libc::MAP_HUGETLB;

#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "android"))]
const MAP_HUGE_MASK: libc::c_int = libc::MAP_HUGE_MASK;

#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "android"))]
const MAP_HUGE_SHIFT: libc::c_int = libc::MAP_HUGE_SHIFT;

#[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "android")))]
const MAP_HUGETLB: libc::c_int = 0;

#[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "android")))]
const MAP_HUGE_MASK: libc::c_int = 0;

#[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "android")))]
const MAP_HUGE_SHIFT: libc::c_int = 0;

#[cfg(any(
target_os = "android",
all(target_os = "linux", not(target_env = "musl"))
Expand Down Expand Up @@ -261,15 +279,24 @@ impl MmapInner {
}

/// Open an anonymous memory map.
pub fn map_anon(len: usize, stack: bool, populate: bool) -> io::Result<MmapInner> {
pub fn map_anon(
len: usize,
stack: bool,
populate: bool,
huge: Option<u8>,
) -> io::Result<MmapInner> {
let stack = if stack { MAP_STACK } else { 0 };
let populate = if populate { MAP_POPULATE } else { 0 };
let hugetlb = if huge.is_some() { MAP_HUGETLB } else { 0 };
let offset = huge
.map(|mask| ((mask as u64) & (MAP_HUGE_MASK as u64)) << MAP_HUGE_SHIFT)
.unwrap_or(0);
MmapInner::new(
len,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_PRIVATE | libc::MAP_ANON | stack | populate,
libc::MAP_PRIVATE | libc::MAP_ANON | stack | populate | hugetlb,
-1,
0,
offset,
)
}

Expand Down
7 changes: 6 additions & 1 deletion src/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,12 @@ impl MmapInner {
Ok(inner)
}

pub fn map_anon(len: usize, _stack: bool, _populate: bool) -> io::Result<MmapInner> {
pub fn map_anon(
len: usize,
_stack: bool,
_populate: bool,
_huge: Option<u8>,
) -> io::Result<MmapInner> {
// Ensure a non-zero length for the underlying mapping
let mapped_len = len.max(1);
unsafe {
Expand Down

0 comments on commit 3c71286

Please sign in to comment.