Skip to content

Commit

Permalink
Experimental support for mapping an arena on windows.
Browse files Browse the repository at this point in the history
  • Loading branch information
ibabushkin committed Apr 12, 2019
1 parent b38896d commit 745286b
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 13 deletions.
7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ checkpoint = ["serde", "serde_derive", "serde_json"]

[dependencies]
cfg-if = "0.1.6"
libc = "0.2.44"
scoped-tls = "0.1.2"

# Provides a generator based runtime
Expand All @@ -42,3 +41,9 @@ futures = { version = "0.1.25", optional = true }
serde = { version = "1.0.80", optional = true }
serde_derive = { version = "1.0.80", optional = true }
serde_json = { version = "1.0.33", optional = true }

[target.'cfg(unix)'.dependencies]
libc = "0.2.44"

[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3.7", features = ["basetsd", "memoryapi", "minwindef", "sysinfoapi", "winnt"] }
8 changes: 7 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,13 @@

#[macro_use]
extern crate cfg_if;
// extern crate libc;

#[cfg(unix)]
extern crate libc;

#[cfg(windows)]
extern crate winapi;

#[macro_use]
extern crate scoped_tls;

Expand Down
82 changes: 71 additions & 11 deletions src/rt/arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,25 +42,70 @@ struct Inner {
cap: usize,
}

#[cfg(unix)]
fn create_mapping(capacity: usize) -> *mut u8 {
let ptr = unsafe {
libc::mmap(
ptr::null_mut(),
capacity,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_ANON | libc::MAP_PRIVATE,
-1,
0,
)
};

ptr as *mut u8
}

#[cfg(windows)]
fn get_page_size() -> usize {
use std::mem;
use winapi::um::sysinfoapi::GetSystemInfo;

unsafe {
let mut info = mem::zeroed();
GetSystemInfo(&mut info);

info.dwPageSize as usize
}
}

#[cfg(windows)]
fn create_mapping(capacity: usize) -> *mut u8 {
use std::ptr;
use winapi::shared::basetsd::SIZE_T;
use winapi::shared::minwindef::LPVOID;
use winapi::um::memoryapi::VirtualAlloc;
use winapi::um::winnt::{PAGE_READWRITE, MEM_COMMIT, MEM_RESERVE};

let lpAddress: LPVOID = ptr::null_mut();
let page_size = get_page_size();
let len = if capacity % page_size == 0 {
capacity
} else {
capacity + page_size - (capacity % page_size)
};
let flAllocationType = MEM_COMMIT | MEM_RESERVE;
let flProtect = PAGE_READWRITE;

let r = unsafe {
VirtualAlloc(lpAddress, len as SIZE_T, flAllocationType, flProtect)
};

r as *mut u8
}

impl Arena {
/// Create an `Arena` with specified capacity.
///
/// Capacity must be a power of 2. The capacity cannot be grown after the fact.
pub fn with_capacity(capacity: usize) -> Arena {
let head = unsafe {
libc::mmap(
ptr::null_mut(),
capacity,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_ANON | libc::MAP_PRIVATE,
-1,
0,
)
};
let head = create_mapping(capacity);

Arena {
inner: Rc::new(Inner {
head: head as *mut u8,
head,
pos: Cell::new(0),
cap: capacity,
})
Expand Down Expand Up @@ -127,6 +172,7 @@ fn allocate<T>(inner: &Rc<Inner>, count: usize) -> *mut T {
ret
}

#[cfg(unix)]
impl Drop for Inner {
fn drop(&mut self) {
let res = unsafe { libc::munmap(self.head as *mut libc::c_void, self.cap) };
Expand All @@ -136,6 +182,20 @@ impl Drop for Inner {
}
}

#[cfg(windows)]
impl Drop for Inner {
fn drop(&mut self) {
use winapi::shared::minwindef::LPVOID;
use winapi::um::memoryapi::VirtualFree;
use winapi::um::winnt::MEM_RELEASE;

let res = unsafe { VirtualFree(self.head as LPVOID, 0, MEM_RELEASE) };

// TODO: Do something on error
debug_assert_ne!(res, 0);
}
}

impl<T> Slice<T> {
pub fn iter(&self) -> Iter<T> {
unsafe {
Expand Down

0 comments on commit 745286b

Please sign in to comment.