iceoryx2_bb_posix/
memory_lock.rs1use crate::system_configuration::SystemInfo;
18use iceoryx2_bb_elementary::enum_gen;
19use iceoryx2_log::fatal_panic;
20use iceoryx2_pal_posix::posix::errno::Errno;
21use iceoryx2_pal_posix::*;
22
23#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
24pub enum MemoryLockCreationError {
25 InvalidAddressRange,
26 UnableToLock,
27 AddressNotAMultipleOfThePageSize,
28 InsufficientPermissions,
29 UnknownError(i32),
30}
31
32#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
33pub enum MemoryLockAllError {
34 UnableToLock,
35 WouldExceedMainMemory,
36 InsufficientPermissions,
37 UnknownError(i32),
38}
39
40enum_gen! {
41 MemoryLockError
46 generalization:
47 LockFailed <= MemoryLockCreationError; MemoryLockAllError
48}
49
50#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
53#[repr(i32)]
54pub enum LockMode {
55 LockAllPagesCurrentlyMapped = posix::MCL_CURRENT,
56 LockAllPagesThatBecomeMapped = posix::MCL_FUTURE,
57}
58
59#[derive(Debug)]
63pub struct MemoryLock {
64 address: *const posix::void,
65 len: usize,
66}
67
68impl MemoryLock {
69 pub unsafe fn new(
76 address: *const posix::void,
77 len: usize,
78 ) -> Result<MemoryLock, MemoryLockCreationError> {
79 if unsafe { posix::mlock(address, len) } == 0 {
80 return Ok(MemoryLock { address, len });
81 }
82
83 let msg = "Unable to lock memory";
84 handle_errno!(MemoryLockCreationError, from "MemoryLock::new",
85 Errno::ENOMEM => (InvalidAddressRange, "{} since the specified range beginning from {:#16X} with a length of {} is not contained in the valid mapped pages in the address spaces of the current process.", msg, address as usize, len),
86 Errno::EAGAIN => (UnableToLock, "{} since some or all memory could not be locked.", msg),
87 Errno::EINVAL => (AddressNotAMultipleOfThePageSize, "{} since the address {:#16X} is not a multiple of the page-size {}.", msg, address as usize, SystemInfo::PageSize.value()),
88 Errno::EPERM => (InsufficientPermissions, "{} due to insufficient permissions.", msg),
89 v => (UnknownError(v as i32), "{} since an unknown error occurred ({}).", msg, v)
90 );
91 }
92
93 pub fn lock_all(mode: LockMode) -> Result<(), MemoryLockAllError> {
95 if unsafe { posix::mlockall(mode as i32) } != -1 {
96 return Ok(());
97 }
98
99 let msg = "Unable to lock all memory with the mode";
100 handle_errno!(MemoryLockAllError, from "MemoryLock::lock_all",
101 Errno::EAGAIN => (UnableToLock, "{} {:?} since the memory could not be locked.", msg, mode),
102 Errno::ENOMEM => (WouldExceedMainMemory, "{} {:?} due to insufficient main memory.", msg, mode),
103 Errno::EPERM => (InsufficientPermissions, "{} {:?} due to insufficient permissions.", msg, mode),
104 v => (UnknownError(v as i32), "{} {:?} since an unknown error occurred ({}).", msg, mode, v)
105 );
106 }
107
108 pub fn unlock_all() {
110 unsafe { posix::munlockall() };
111 }
112}
113
114impl Drop for MemoryLock {
115 fn drop(&mut self) {
116 if unsafe { posix::munlock(self.address, self.len) } != 0 {
117 fatal_panic!(from self, "This should never happen! Unable to unlock memory region.");
118 }
119 }
120}