Skip to content

Commit d96b165

Browse files
killme2008youknowone
authored andcommitted
Impl madvise method
1 parent d4f001f commit d96b165

File tree

1 file changed

+82
-4
lines changed

1 file changed

+82
-4
lines changed

stdlib/src/mmap.rs

Lines changed: 82 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,46 @@ mod mmap {
1212
FromArgs, PyObject, PyPayload, PyRef, PyResult, TryFromBorrowedObject, VirtualMachine,
1313
};
1414
use crossbeam_utils::atomic::AtomicCell;
15-
use memmap2::{Mmap, MmapMut, MmapOptions};
15+
use memmap2::{Advice, Mmap, MmapMut, MmapOptions};
1616
use nix::unistd;
1717
use std::fs::File;
1818
use std::ops::Deref;
1919
#[cfg(all(unix, not(target_os = "redox")))]
2020
use std::os::unix::io::{FromRawFd, IntoRawFd, RawFd};
2121

22+
fn advice_try_from_i32(vm: &VirtualMachine, i: i32) -> PyResult<Advice> {
23+
Ok(match i {
24+
libc::MADV_NORMAL => Advice::Normal,
25+
libc::MADV_RANDOM => Advice::Random,
26+
libc::MADV_SEQUENTIAL => Advice::Sequential,
27+
libc::MADV_WILLNEED => Advice::WillNeed,
28+
libc::MADV_DONTNEED => Advice::DontNeed,
29+
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "ios"))]
30+
libc::MADV_FREE => Advice::Free,
31+
#[cfg(target_os = "linux")]
32+
libc::MADV_DONTFORK => Advice::DontFork,
33+
#[cfg(target_os = "linux")]
34+
libc::MADV_DOFORK => Advice::DoFork,
35+
#[cfg(target_os = "linux")]
36+
libc::MADV_MERGEABLE => Advice::Mergeable,
37+
#[cfg(target_os = "linux")]
38+
libc::MADV_UNMERGEABLE => Advice::Unmergeable,
39+
#[cfg(target_os = "linux")]
40+
libc::MADV_HUGEPAGE => Advice::HugePage,
41+
#[cfg(target_os = "linux")]
42+
libc::MADV_NOHUGEPAGE => Advice::NoHugePage,
43+
#[cfg(target_os = "linux")]
44+
libc::MADV_REMOVE => Advice::Remove,
45+
#[cfg(target_os = "linux")]
46+
libc::MADV_DONTDUMP => Advice::DontDump,
47+
#[cfg(target_os = "linux")]
48+
libc::MADV_DODUMP => Advice::DoDump,
49+
#[cfg(target_os = "linux")]
50+
libc::MADV_HWPOISON => Advice::HwPoison,
51+
_ => return Err(vm.new_value_error("Not a valid Advice value".to_owned())),
52+
})
53+
}
54+
2255
#[repr(C)]
2356
#[derive(PartialEq, Eq, Debug)]
2457
enum AccessMode {
@@ -51,12 +84,24 @@ mod mmap {
5184
#[pyattr]
5285
use libc::{MADV_FREE_REUSABLE, MADV_FREE_REUSE};
5386

87+
#[cfg(any(
88+
target_os = "android",
89+
target_os = "dragonfly",
90+
target_os = "fuchsia",
91+
target_os = "freebsd",
92+
target_os = "linux",
93+
target_os = "netbsd",
94+
target_os = "openbsd",
95+
target_vendor = "apple"
96+
))]
97+
#[pyattr]
98+
use libc::MADV_FREE;
99+
54100
#[cfg(target_os = "linux")]
55101
#[pyattr]
56102
use libc::{
57-
MADV_DODUMP, MADV_DOFORK, MADV_DONTDUMP, MADV_DONTFORK, MADV_FREE, MADV_HUGEPAGE,
58-
MADV_HWPOISON, MADV_MERGEABLE, MADV_NOHUGEPAGE, MADV_REMOVE, MADV_SOFT_OFFLINE,
59-
MADV_UNMERGEABLE,
103+
MADV_DODUMP, MADV_DOFORK, MADV_DONTDUMP, MADV_DONTFORK, MADV_HUGEPAGE, MADV_HWPOISON,
104+
MADV_MERGEABLE, MADV_NOHUGEPAGE, MADV_REMOVE, MADV_SOFT_OFFLINE, MADV_UNMERGEABLE,
60105
};
61106

62107
#[cfg(all(target_os = "linux", target_arch = "x86_64", target_env = "gnu"))]
@@ -437,6 +482,39 @@ mod mmap {
437482
Ok(())
438483
}
439484

485+
#[allow(unused_assignments)]
486+
#[pymethod]
487+
fn madvise(&self, options: AdviseOptions, vm: &VirtualMachine) -> PyResult<()> {
488+
let start = options.start.unwrap_or(0);
489+
let mut length = options.length.unwrap_or_else(|| self.inner_size());
490+
491+
if start < 0 || start >= self.inner_size() {
492+
return Err(vm.new_value_error("madvise start out of bounds".to_owned()));
493+
}
494+
if length < 0 {
495+
return Err(vm.new_value_error("madvise length invalid".to_owned()));
496+
}
497+
498+
if isize::MAX - start < length {
499+
return Err(vm.new_overflow_error("madvise length too large".to_owned()));
500+
}
501+
502+
if start + length > self.inner_size() {
503+
length = self.inner_size() - start;
504+
}
505+
506+
let advice = advice_try_from_i32(vm, options.option)?;
507+
508+
//TODO: memmap2 doesn't support madvise range right now.
509+
match self.check_valid(vm)?.deref().as_ref().unwrap() {
510+
MmapObj::Read(mmap) => mmap.advise(advice),
511+
MmapObj::Write(mmap) => mmap.advise(advice),
512+
}
513+
.map_err(|e| vm.new_os_error(e.to_string()))?;
514+
515+
Ok(())
516+
}
517+
440518
#[pymethod]
441519
fn size(&self, vm: &VirtualMachine) -> PyResult<PyIntRef> {
442520
let new_fd = unistd::dup(self.fd).map_err(|e| vm.new_os_error(e.to_string()))?;

0 commit comments

Comments
 (0)