pub(crate) enum RawAdvice {
#[cfg(target_vendor = "apple")]
Libc(i32),
#[cfg(not(target_vendor = "apple"))]
Rustix(rustix::mm::Advice),
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum Advice {
Normal,
Random,
Sequential,
WillNeed,
#[cfg(target_os = "linux")]
DontFork,
#[cfg(target_os = "linux")]
DoFork,
#[cfg(target_os = "linux")]
Mergeable,
#[cfg(target_os = "linux")]
Unmergeable,
#[cfg(target_os = "linux")]
HugePage,
#[cfg(target_os = "linux")]
NoHugePage,
#[cfg(target_os = "linux")]
DontDump,
#[cfg(target_os = "linux")]
DoDump,
#[cfg(target_os = "linux")]
HwPoison,
#[cfg(target_os = "linux")]
PopulateRead,
#[cfg(target_os = "linux")]
PopulateWrite,
#[cfg(target_vendor = "apple")]
ZeroWiredPages,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum UncheckedAdvice {
DontNeed,
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
Free,
#[cfg(target_os = "linux")]
Remove,
#[cfg(target_vendor = "apple")]
FreeReusable,
#[cfg(target_vendor = "apple")]
FreeReuse,
}
#[cfg(target_vendor = "apple")]
impl Advice {
pub(crate) fn to_raw(self) -> RawAdvice {
RawAdvice::Libc(match self {
Advice::Normal => libc::MADV_NORMAL,
Advice::Random => libc::MADV_RANDOM,
Advice::Sequential => libc::MADV_SEQUENTIAL,
Advice::WillNeed => libc::MADV_WILLNEED,
Advice::ZeroWiredPages => libc::MADV_ZERO_WIRED_PAGES,
})
}
}
#[cfg(not(target_vendor = "apple"))]
impl Advice {
pub(crate) fn to_raw(self) -> RawAdvice {
use rustix::mm::Advice as R;
RawAdvice::Rustix(match self {
Advice::Normal => R::Normal,
Advice::Random => R::Random,
Advice::Sequential => R::Sequential,
Advice::WillNeed => R::WillNeed,
#[cfg(target_os = "linux")]
Advice::DontFork => R::LinuxDontFork,
#[cfg(target_os = "linux")]
Advice::DoFork => R::LinuxDoFork,
#[cfg(target_os = "linux")]
Advice::Mergeable => R::LinuxMergeable,
#[cfg(target_os = "linux")]
Advice::Unmergeable => R::LinuxUnmergeable,
#[cfg(target_os = "linux")]
Advice::HugePage => R::LinuxHugepage,
#[cfg(target_os = "linux")]
Advice::NoHugePage => R::LinuxNoHugepage,
#[cfg(target_os = "linux")]
Advice::DontDump => R::LinuxDontDump,
#[cfg(target_os = "linux")]
Advice::DoDump => R::LinuxDoDump,
#[cfg(target_os = "linux")]
Advice::HwPoison => R::LinuxHwPoison,
#[cfg(target_os = "linux")]
Advice::PopulateRead => R::LinuxPopulateRead,
#[cfg(target_os = "linux")]
Advice::PopulateWrite => R::LinuxPopulateWrite,
})
}
}
#[cfg(target_vendor = "apple")]
impl UncheckedAdvice {
pub(crate) fn to_raw(self) -> RawAdvice {
RawAdvice::Libc(match self {
UncheckedAdvice::DontNeed => libc::MADV_DONTNEED,
UncheckedAdvice::Free => libc::MADV_FREE,
UncheckedAdvice::FreeReusable => libc::MADV_FREE_REUSABLE,
UncheckedAdvice::FreeReuse => libc::MADV_FREE_REUSE,
})
}
}
#[cfg(not(target_vendor = "apple"))]
impl UncheckedAdvice {
pub(crate) fn to_raw(self) -> RawAdvice {
use rustix::mm::Advice as R;
RawAdvice::Rustix(match self {
#[cfg(target_os = "linux")]
UncheckedAdvice::DontNeed => R::LinuxDontNeed,
#[cfg(not(target_os = "linux"))]
UncheckedAdvice::DontNeed => R::DontNeed,
#[cfg(target_os = "linux")]
UncheckedAdvice::Free => R::LinuxFree,
#[cfg(target_os = "linux")]
UncheckedAdvice::Remove => R::LinuxRemove,
})
}
}
#[cfg(target_os = "linux")]
impl Advice {
pub fn is_supported(self) -> bool {
let RawAdvice::Rustix(advice) = self.to_raw();
unsafe { rustix::mm::madvise(std::ptr::null_mut(), 0, advice).is_ok() }
}
}
#[cfg(target_os = "linux")]
impl UncheckedAdvice {
pub fn is_supported(self) -> bool {
let RawAdvice::Rustix(advice) = self.to_raw();
unsafe { rustix::mm::madvise(std::ptr::null_mut(), 0, advice).is_ok() }
}
}
#[cfg(test)]
mod tests {
#[cfg(target_os = "linux")]
#[test]
fn test_is_supported() {
use super::*;
assert!(Advice::Normal.is_supported());
assert!(Advice::Random.is_supported());
assert!(Advice::Sequential.is_supported());
assert!(Advice::WillNeed.is_supported());
assert!(UncheckedAdvice::DontNeed.is_supported());
}
}