Skip to content

Commit 01cdaa3

Browse files
committed
mmap for windows
1 parent c6086cb commit 01cdaa3

File tree

1 file changed

+56
-14
lines changed

1 file changed

+56
-14
lines changed

crates/stdlib/src/mmap.rs

Lines changed: 56 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,12 @@ mod mmap {
5353
| libc::MADV_SEQUENTIAL
5454
| libc::MADV_WILLNEED
5555
| libc::MADV_DONTNEED => Ok(advice),
56-
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "ios"))]
56+
#[cfg(any(
57+
target_os = "linux",
58+
target_os = "macos",
59+
target_os = "ios",
60+
target_os = "freebsd"
61+
))]
5762
libc::MADV_FREE => Ok(advice),
5863
#[cfg(target_os = "linux")]
5964
libc::MADV_DONTFORK
@@ -66,6 +71,12 @@ mod mmap {
6671
| libc::MADV_DONTDUMP
6772
| libc::MADV_DODUMP
6873
| libc::MADV_HWPOISON => Ok(advice),
74+
#[cfg(target_os = "freebsd")]
75+
libc::MADV_NOSYNC
76+
| libc::MADV_AUTOSYNC
77+
| libc::MADV_NOCORE
78+
| libc::MADV_CORE
79+
| libc::MADV_PROTECT => Ok(advice),
6980
_ => Err(vm.new_value_error("Not a valid Advice value")),
7081
}
7182
}
@@ -96,7 +107,7 @@ mod mmap {
96107
#[pyattr]
97108
use libc::{
98109
MADV_DONTNEED, MADV_NORMAL, MADV_RANDOM, MADV_SEQUENTIAL, MADV_WILLNEED, MAP_ANON,
99-
MAP_ANONYMOUS, MAP_PRIVATE, MAP_SHARED, PROT_READ, PROT_WRITE,
110+
MAP_ANONYMOUS, MAP_PRIVATE, MAP_SHARED, PROT_EXEC, PROT_READ, PROT_WRITE,
100111
};
101112

102113
#[cfg(target_os = "macos")]
@@ -146,6 +157,16 @@ mod mmap {
146157
#[pyattr]
147158
use libc::{MAP_DENYWRITE, MAP_EXECUTABLE, MAP_POPULATE};
148159

160+
// MAP_STACK is available on Linux, OpenBSD, and NetBSD
161+
#[cfg(any(target_os = "linux", target_os = "openbsd", target_os = "netbsd"))]
162+
#[pyattr]
163+
use libc::MAP_STACK;
164+
165+
// FreeBSD-specific MADV constants
166+
#[cfg(target_os = "freebsd")]
167+
#[pyattr]
168+
use libc::{MADV_AUTOSYNC, MADV_CORE, MADV_NOCORE, MADV_NOSYNC, MADV_PROTECT};
169+
149170
#[pyattr]
150171
const ACCESS_DEFAULT: u32 = AccessMode::Default as u32;
151172
#[pyattr]
@@ -404,6 +425,15 @@ mod mmap {
404425
};
405426

406427
let fd = unsafe { crt_fd::Borrowed::try_borrow_raw(fd) };
428+
429+
// macOS: Issue #11277: fsync(2) is not enough on OS X - a special, OS X specific
430+
// fcntl(2) is necessary to force DISKSYNC and get around mmap(2) bug
431+
#[cfg(target_os = "macos")]
432+
if let Ok(fd) = fd {
433+
use std::os::fd::AsRawFd;
434+
unsafe { libc::fcntl(fd.as_raw_fd(), libc::F_FULLFSYNC) };
435+
}
436+
407437
if let Ok(fd) = fd {
408438
let metadata = fstat(fd)
409439
.map_err(|err| io::Error::from_raw_os_error(err as i32).to_pyexception(vm))?;
@@ -799,8 +829,9 @@ mod mmap {
799829

800830
let sub = &options.sub;
801831

832+
// returns start position for empty string
802833
if sub.is_empty() {
803-
return Ok(PyInt::from(0isize));
834+
return Ok(PyInt::from(start as isize));
804835
}
805836

806837
let mmap = self.check_valid(vm)?;
@@ -815,8 +846,9 @@ mod mmap {
815846
let (start, end) = self.get_find_range(options.clone());
816847

817848
let sub = &options.sub;
849+
// returns start position for empty string
818850
if sub.is_empty() {
819-
return Ok(PyInt::from(0isize));
851+
return Ok(PyInt::from(start as isize));
820852
}
821853

822854
let mmap = self.check_valid(vm)?;
@@ -850,18 +882,20 @@ mod mmap {
850882
#[cfg(all(unix, not(target_os = "redox")))]
851883
#[pymethod]
852884
fn madvise(&self, options: AdviseOptions, vm: &VirtualMachine) -> PyResult<()> {
853-
let (option, _start, _length) = options.values(self.__len__(), vm)?;
885+
let (option, start, length) = options.values(self.__len__(), vm)?;
854886
let advice = validate_advice(vm, option)?;
855887

856888
let guard = self.check_valid(vm)?;
857889
let mmap = guard.deref().as_ref().unwrap();
858-
let (ptr, len) = match mmap {
859-
MmapObj::Read(m) => (m.as_ptr(), m.len()),
860-
MmapObj::Write(m) => (m.as_ptr(), m.len()),
890+
let ptr = match mmap {
891+
MmapObj::Read(m) => m.as_ptr(),
892+
MmapObj::Write(m) => m.as_ptr(),
861893
};
862894

863-
// Call libc::madvise directly
864-
let result = unsafe { libc::madvise(ptr as *mut libc::c_void, len, advice) };
895+
// Apply madvise to the specified range (start, length)
896+
let ptr_with_offset = unsafe { ptr.add(start) };
897+
let result =
898+
unsafe { libc::madvise(ptr_with_offset as *mut libc::c_void, length, advice) };
865899
if result != 0 {
866900
return Err(io::Error::last_os_error().to_pyexception(vm));
867901
}
@@ -1063,13 +1097,14 @@ mod mmap {
10631097
// Restore original mmap on error
10641098
let err = io::Error::last_os_error();
10651099
let old_size = self.size.load();
1066-
if let Ok(mmap) = Self::create_mmap_windows(
1100+
match Self::create_mmap_windows(
10671101
handle as HANDLE,
10681102
self.offset,
10691103
old_size,
10701104
&self.access,
10711105
) {
1072-
*mmap_guard = Some(mmap);
1106+
Ok(mmap) => *mmap_guard = Some(mmap),
1107+
Err(_) => self.closed.store(true),
10731108
}
10741109
return Err(err.to_pyexception(vm));
10751110
}
@@ -1078,13 +1113,14 @@ mod mmap {
10781113
if result == 0 {
10791114
let err = io::Error::last_os_error();
10801115
let old_size = self.size.load();
1081-
if let Ok(mmap) = Self::create_mmap_windows(
1116+
match Self::create_mmap_windows(
10821117
handle as HANDLE,
10831118
self.offset,
10841119
old_size,
10851120
&self.access,
10861121
) {
1087-
*mmap_guard = Some(mmap);
1122+
Ok(mmap) => *mmap_guard = Some(mmap),
1123+
Err(_) => self.closed.store(true),
10881124
}
10891125
return Err(err.to_pyexception(vm));
10901126
}
@@ -1248,6 +1284,12 @@ mod mmap {
12481284
fn __exit__(zelf: &Py<Self>, _args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
12491285
zelf.close(vm)
12501286
}
1287+
1288+
#[cfg(windows)]
1289+
#[pymethod]
1290+
fn __sizeof__(&self) -> usize {
1291+
std::mem::size_of::<Self>()
1292+
}
12511293
}
12521294

12531295
impl PyMmap {

0 commit comments

Comments
 (0)