Skip to content

Commit c52e6ee

Browse files
committed
Experimental support for mapping an arena on windows.
1 parent b38896d commit c52e6ee

File tree

3 files changed

+84
-13
lines changed

3 files changed

+84
-13
lines changed

Cargo.toml

+6-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ checkpoint = ["serde", "serde_derive", "serde_json"]
2626

2727
[dependencies]
2828
cfg-if = "0.1.6"
29-
libc = "0.2.44"
3029
scoped-tls = "0.1.2"
3130

3231
# Provides a generator based runtime
@@ -42,3 +41,9 @@ futures = { version = "0.1.25", optional = true }
4241
serde = { version = "1.0.80", optional = true }
4342
serde_derive = { version = "1.0.80", optional = true }
4443
serde_json = { version = "1.0.33", optional = true }
44+
45+
[target.'cfg(unix)'.dependencies]
46+
libc = "0.2.44"
47+
48+
[target.'cfg(windows)'.dependencies]
49+
winapi = { version = "0.3.7", features = ["basetsd", "minwindef", "sysinfoapi", "winnt"] }

src/lib.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,13 @@
113113
114114
#[macro_use]
115115
extern crate cfg_if;
116-
// extern crate libc;
116+
117+
#[cfg(unix)]
118+
extern crate libc;
119+
120+
#[cfg(windows)]
121+
extern crate winapi;
122+
117123
#[macro_use]
118124
extern crate scoped_tls;
119125

src/rt/arena.rs

+71-11
Original file line numberDiff line numberDiff line change
@@ -42,25 +42,70 @@ struct Inner {
4242
cap: usize,
4343
}
4444

45+
#[cfg(unix)]
46+
fn create_mapping(capacity: usize) -> *mut u8 {
47+
let ptr = unsafe {
48+
libc::mmap(
49+
ptr::null_mut(),
50+
capacity,
51+
libc::PROT_READ | libc::PROT_WRITE,
52+
libc::MAP_ANON | libc::MAP_PRIVATE,
53+
-1,
54+
0,
55+
)
56+
};
57+
58+
ptr as *mut u8
59+
}
60+
61+
#[cfg(windows)]
62+
fn get_page_size() -> usize {
63+
use std::mem;
64+
use winapi::um::sysinfoapi::GetSystemInfo;
65+
66+
unsafe {
67+
let mut info = mem::zeroed();
68+
GetSystemInfo(&mut info);
69+
70+
info.dwPageSize as usize
71+
}
72+
}
73+
74+
#[cfg(windows)]
75+
fn create_mapping(capacity: usize) -> *mut u8 {
76+
use std::ptr;
77+
use winapi::shared::basetsd::SIZE_T;
78+
use winapi::shared::minwindef::LPVOID;
79+
use winapi::um::memoryapi::VirtualAlloc;
80+
use winapi::um::winnt::{PAGE_READWRITE, MEM_COMMIT, MEM_RESERVE};
81+
82+
let lpAddress: LPVOID = ptr::null_mut();
83+
let page_size = get_page_size();
84+
let len = if capacity % page_size == 0 {
85+
capacity
86+
} else {
87+
capacity + page_size - (capacity % page_size)
88+
};
89+
let flAllocationType = MEM_COMMIT | MEM_RESERVE;
90+
let flProtect = PAGE_READWRITE;
91+
92+
let r = unsafe {
93+
VirtualAlloc(lpAddress, len as SIZE_T, flAllocationType, flProtect)
94+
};
95+
96+
r as *mut u8
97+
}
98+
4599
impl Arena {
46100
/// Create an `Arena` with specified capacity.
47101
///
48102
/// Capacity must be a power of 2. The capacity cannot be grown after the fact.
49103
pub fn with_capacity(capacity: usize) -> Arena {
50-
let head = unsafe {
51-
libc::mmap(
52-
ptr::null_mut(),
53-
capacity,
54-
libc::PROT_READ | libc::PROT_WRITE,
55-
libc::MAP_ANON | libc::MAP_PRIVATE,
56-
-1,
57-
0,
58-
)
59-
};
104+
let head = create_mapping(capacity);
60105

61106
Arena {
62107
inner: Rc::new(Inner {
63-
head: head as *mut u8,
108+
head,
64109
pos: Cell::new(0),
65110
cap: capacity,
66111
})
@@ -127,6 +172,7 @@ fn allocate<T>(inner: &Rc<Inner>, count: usize) -> *mut T {
127172
ret
128173
}
129174

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

185+
#[cfg(windows)]
186+
impl Drop for Inner {
187+
fn drop(&mut self) {
188+
use winapi::shared::minwindef::LPVOID;
189+
use winapi::um::memoryapi::VirtualFree;
190+
use winapi::um::winnt::MEM_RELEASE;
191+
192+
let res = unsafe { VirtualFree(self.head as LPVOID, 0, MEM_RELEASE) };
193+
194+
// TODO: Do something on error
195+
debug_assert_ne!(res, 0);
196+
}
197+
}
198+
139199
impl<T> Slice<T> {
140200
pub fn iter(&self) -> Iter<T> {
141201
unsafe {

0 commit comments

Comments
 (0)