Fixed MemoryMap on Windows.

This commit is contained in:
Vadim Chugunov 2013-08-28 01:41:26 -07:00
parent 546e2ae850
commit 99345d8d17

View File

@ -1418,12 +1418,12 @@ pub fn page_size() -> uint {
pub fn page_size() -> uint { pub fn page_size() -> uint {
#[fixed_stack_segment]; #[inline(never)]; #[fixed_stack_segment]; #[inline(never)];
unsafe { unsafe {
let mut info = libc::SYSTEM_INFO::new(); let mut info = libc::SYSTEM_INFO::new();
libc::GetSystemInfo(&mut info); libc::GetSystemInfo(&mut info);
return info.dwPageSize as uint; return info.dwPageSize as uint;
} }
} }
pub struct MemoryMap { pub struct MemoryMap {
@ -1458,7 +1458,6 @@ pub enum MapError {
// Windows-specific errors // Windows-specific errors
ErrUnsupProt, ErrUnsupProt,
ErrUnsupOffset, ErrUnsupOffset,
ErrNeedRW,
ErrAlreadyExists, ErrAlreadyExists,
ErrVirtualAlloc(uint), ErrVirtualAlloc(uint),
ErrCreateFileMappingW(uint), ErrCreateFileMappingW(uint),
@ -1477,7 +1476,6 @@ impl to_str::ToStr for MapError {
ErrUnknown(code) => fmt!("Unknown error=%?", code), ErrUnknown(code) => fmt!("Unknown error=%?", code),
ErrUnsupProt => ~"Protection mode unsupported", ErrUnsupProt => ~"Protection mode unsupported",
ErrUnsupOffset => ~"Offset in virtual memory mode is unsupported", ErrUnsupOffset => ~"Offset in virtual memory mode is unsupported",
ErrNeedRW => ~"File mapping should be at least readable/writable",
ErrAlreadyExists => ~"File mapping for specified file already exists", ErrAlreadyExists => ~"File mapping for specified file already exists",
ErrVirtualAlloc(code) => fmt!("VirtualAlloc failure=%?", code), ErrVirtualAlloc(code) => fmt!("VirtualAlloc failure=%?", code),
ErrCreateFileMappingW(code) => fmt!("CreateFileMappingW failure=%?", code), ErrCreateFileMappingW(code) => fmt!("CreateFileMappingW failure=%?", code),
@ -1542,6 +1540,10 @@ impl MemoryMap {
}) })
} }
} }
pub fn granularity() -> uint {
page_size()
}
} }
#[cfg(unix)] #[cfg(unix)]
@ -1617,21 +1619,21 @@ impl MemoryMap {
}) })
} }
} else { } else {
let dwDesiredAccess = match (readable, writable) { let dwDesiredAccess = match (executable, readable, writable) {
(true, true) => libc::FILE_MAP_ALL_ACCESS, (false, true, false) => libc::FILE_MAP_READ,
(true, false) => libc::FILE_MAP_READ, (false, true, true) => libc::FILE_MAP_WRITE,
(false, true) => libc::FILE_MAP_WRITE, (true, true, false) => libc::FILE_MAP_READ | libc::FILE_MAP_EXECUTE,
_ => { (true, true, true) => libc::FILE_MAP_WRITE | libc::FILE_MAP_EXECUTE,
return Err(ErrNeedRW); _ => return Err(ErrUnsupProt) // Actually, because of the check above,
} // we should never get here.
}; };
unsafe { unsafe {
let hFile = libc::get_osfhandle(fd) as HANDLE; let hFile = libc::get_osfhandle(fd) as HANDLE;
let mapping = libc::CreateFileMappingW(hFile, let mapping = libc::CreateFileMappingW(hFile,
ptr::mut_null(), ptr::mut_null(),
flProtect, flProtect,
(len >> 32) as DWORD, 0,
(len & 0xffff_ffff) as DWORD, 0,
ptr::null()); ptr::null());
if mapping == ptr::mut_null() { if mapping == ptr::mut_null() {
return Err(ErrCreateFileMappingW(errno())); return Err(ErrCreateFileMappingW(errno()));
@ -1641,7 +1643,7 @@ impl MemoryMap {
} }
let r = libc::MapViewOfFile(mapping, let r = libc::MapViewOfFile(mapping,
dwDesiredAccess, dwDesiredAccess,
(offset >> 32) as DWORD, ((len as u64) >> 32) as DWORD,
(offset & 0xffff_ffff) as DWORD, (offset & 0xffff_ffff) as DWORD,
0); 0);
match r as uint { match r as uint {
@ -1655,6 +1657,19 @@ impl MemoryMap {
} }
} }
} }
/// Granularity of MapAddr() and MapOffset() parameter values.
/// This may be greater than the value returned by page_size().
pub fn granularity() -> uint {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
let mut info = libc::SYSTEM_INFO::new();
libc::GetSystemInfo(&mut info);
return info.dwAllocationGranularity as uint;
}
}
} }
#[cfg(windows)] #[cfg(windows)]
@ -1663,20 +1678,22 @@ impl Drop for MemoryMap {
#[fixed_stack_segment]; #[inline(never)]; #[fixed_stack_segment]; #[inline(never)];
use libc::types::os::arch::extra::{LPCVOID, HANDLE}; use libc::types::os::arch::extra::{LPCVOID, HANDLE};
use libc::consts::os::extra::FALSE;
unsafe { unsafe {
match self.kind { match self.kind {
MapVirtual => match libc::VirtualFree(self.data as *mut c_void, MapVirtual => {
self.len, if libc::VirtualFree(self.data as *mut c_void,
libc::MEM_RELEASE) { self.len,
0 => error!(fmt!("VirtualFree failed: %?", errno())), libc::MEM_RELEASE) == FALSE {
_ => () error!(fmt!("VirtualFree failed: %?", errno()));
}
}, },
MapFile(mapping) => { MapFile(mapping) => {
if libc::UnmapViewOfFile(self.data as LPCVOID) != 0 { if libc::UnmapViewOfFile(self.data as LPCVOID) == FALSE {
error!(fmt!("UnmapViewOfFile failed: %?", errno())); error!(fmt!("UnmapViewOfFile failed: %?", errno()));
} }
if libc::CloseHandle(mapping as HANDLE) != 0 { if libc::CloseHandle(mapping as HANDLE) == FALSE {
error!(fmt!("CloseHandle failed: %?", errno())); error!(fmt!("CloseHandle failed: %?", errno()));
} }
} }
@ -2108,7 +2125,7 @@ mod tests {
} }
let path = tmpdir().push("mmap_file.tmp"); let path = tmpdir().push("mmap_file.tmp");
let size = page_size() * 2; let size = MemoryMap::granularity() * 2;
remove_file(&path); remove_file(&path);
let fd = unsafe { let fd = unsafe {