use std::fs;
use std::io;
use std::mem;
use std::os::unix::io::AsRawFd;
use std::ptr;
extern crate libc;
#[derive(Debug)]
pub struct PlatformData;
pub fn map_file(file: fs::File) -> io::Result<(*const u8, usize, PlatformData)> {
let fd = file.as_raw_fd();
let length = file.metadata()?.len();
if length > usize::max_value() as u64 {
return Err(io::Error::new(io::ErrorKind::Other, "file is larger than address space"));
}
if length == 0 {
return Ok((ptr::null(), 0, PlatformData));
}
let result = unsafe {
libc::mmap(ptr::null_mut(), length as usize, libc::PROT_READ, libc::MAP_PRIVATE, fd, 0)
};
if result == libc::MAP_FAILED {
Err(io::Error::last_os_error())
} else {
Ok((result as *const u8, length as usize, PlatformData))
}
}
pub fn unmap_file(buffer: *const u8, length: usize) {
let result = unsafe { libc::munmap(buffer as *mut libc::c_void, length) };
assert!(result == 0);
}
pub fn get_resident(buffer: *const u8, length: usize, residency: &mut [bool]) {
use std::thread;
let result = unsafe {
let residency_char = residency.as_mut_ptr() as *mut _;
assert_eq!(1, mem::size_of_val(&*residency_char));
libc::mincore(buffer as *mut libc::c_void, length, residency_char)
};
assert!(result == libc::EAGAIN || result == 0);
if result == libc::EAGAIN {
thread::yield_now();
get_resident(buffer, length, residency)
}
}
pub fn prefetch(buffer: *const u8, length: usize) {
let result = unsafe {
libc::madvise(buffer as *mut libc::c_void, length, libc::MADV_WILLNEED)
};
assert_eq!(0, result);
}
pub fn get_page_size() -> usize {
let page_size = unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize };
assert!(page_size != 0);
assert_eq!(0, page_size & (page_size - 1));
page_size
}