cache page_size

page_size is used in every nearly every pointer calculation in os.rs,
and the Stack methods are called fairly often. It's definitely not worth
spilling registers for to call out to a libc function.
With this change, page_size becomes effectively free. It is cached in an
atomic usize, with relaxed ordering, so no actual atomic operations are
involved.

Benchmark:
```
test bench_page_size        ... bench:         5 ns/iter (+/- 1)
test bench_page_size_cached ... bench:         0 ns/iter (+/- 0)
```
This commit is contained in:
edef 2015-04-16 05:50:54 -04:00
parent 52c0c92cd8
commit cbc10fd311
2 changed files with 20 additions and 2 deletions

View File

@ -1,5 +1,20 @@
pub use self::imp::*;
use core::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
pub use self::imp::{map_stack, protect_stack, unmap_stack};
use self::imp::sys_page_size;
#[cfg(unix)]
#[path = "unix.rs"]
mod imp;
static PAGE_SIZE_CACHE: AtomicUsize = ATOMIC_USIZE_INIT;
pub fn page_size() -> usize {
match PAGE_SIZE_CACHE.load(Ordering::Relaxed) {
0 => {
let page_size = sys_page_size();
PAGE_SIZE_CACHE.store(page_size, Ordering::Relaxed);
page_size
}
page_size => page_size
}
}

View File

@ -3,10 +3,13 @@ use core::prelude::*;
use self::libc::{c_void, c_int, size_t};
use self::libc::{mmap, mprotect, munmap};
use self::libc::MAP_FAILED;
use super::page_size;
use core::ptr;
pub fn page_size() -> usize {
#[cold]
#[inline(never)]
pub fn sys_page_size() -> usize {
unsafe {
libc::sysconf(libc::_SC_PAGESIZE) as usize
}