use crate::error::Result;
#[cfg(all(unix, feature = "lock"))]
mod platform {
use crate::error::{Error, Result};
use core::ffi::{c_int, c_void};
extern "C" {
fn mlock(addr: *const c_void, len: usize) -> c_int;
fn munlock(addr: *const c_void, len: usize) -> c_int;
}
#[inline]
pub unsafe fn lock(addr: *const u8, len: usize) -> Result<()> {
if len == 0 {
return Ok(());
}
let ret = mlock(addr as *const c_void, len);
if ret != 0 {
Err(Error::LockFailed)
} else {
Ok(())
}
}
#[inline]
pub unsafe fn unlock(addr: *const u8, len: usize) -> Result<()> {
if len == 0 {
return Ok(());
}
let ret = munlock(addr as *const c_void, len);
if ret != 0 {
Err(Error::UnlockFailed)
} else {
Ok(())
}
}
}
#[cfg(all(windows, feature = "lock"))]
mod platform {
use crate::error::{Error, Result};
#[link(name = "kernel32")]
extern "system" {
fn VirtualLock(addr: *const core::ffi::c_void, len: usize) -> i32;
fn VirtualUnlock(addr: *const core::ffi::c_void, len: usize) -> i32;
}
#[inline]
pub unsafe fn lock(addr: *const u8, len: usize) -> Result<()> {
if len == 0 {
return Ok(());
}
let ret = VirtualLock(addr as *const core::ffi::c_void, len);
if ret == 0 {
Err(Error::LockFailed)
} else {
Ok(())
}
}
#[inline]
pub unsafe fn unlock(addr: *const u8, len: usize) -> Result<()> {
if len == 0 {
return Ok(());
}
let ret = VirtualUnlock(addr as *const core::ffi::c_void, len);
if ret == 0 {
Err(Error::UnlockFailed)
} else {
Ok(())
}
}
}
#[cfg(not(any(all(unix, feature = "lock"), all(windows, feature = "lock"))))]
mod platform {
use crate::error::Result;
#[inline]
pub unsafe fn lock(_addr: *const u8, _len: usize) -> Result<()> {
Ok(())
}
#[inline]
pub unsafe fn unlock(_addr: *const u8, _len: usize) -> Result<()> {
Ok(())
}
}
#[inline]
pub unsafe fn lock(addr: *const u8, len: usize) -> Result<()> {
platform::lock(addr, len)
}
#[inline]
pub unsafe fn unlock(addr: *const u8, len: usize) -> Result<()> {
platform::unlock(addr, len)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[cfg_attr(miri, ignore)]
fn lock_unlock_roundtrip() {
let mut buf = [0u8; 4096];
let ptr = buf.as_mut_ptr();
unsafe {
if lock(ptr, 4096).is_ok() {
assert!(unlock(ptr, 4096).is_ok());
}
}
}
#[test]
fn zero_length_is_ok() {
let buf: [u8; 0] = [];
unsafe {
assert!(lock(buf.as_ptr(), 0).is_ok());
assert!(unlock(buf.as_ptr(), 0).is_ok());
}
}
}