iceoryx2_bb_posix/
memory.rs1pub use core::alloc::Layout;
16pub use core::ptr::NonNull;
17
18use iceoryx2_bb_elementary::math::*;
19use iceoryx2_bb_elementary_traits::allocator::{
20 AllocationError, AllocationGrowError, AllocationShrinkError,
21};
22use iceoryx2_pal_posix::posix::errno::Errno;
23use iceoryx2_pal_posix::*;
24
25impl From<MemoryError> for AllocationError {
26 fn from(v: MemoryError) -> Self {
27 match v {
28 MemoryError::SizeIsZero => AllocationError::SizeIsZero,
29 MemoryError::OutOfMemory => AllocationError::OutOfMemory,
30 MemoryError::AlignmentFailure => AllocationError::AlignmentFailure,
31 MemoryError::UnknownError(_) => AllocationError::InternalError,
32 }
33 }
34}
35
36impl From<MemoryError> for AllocationGrowError {
37 fn from(v: MemoryError) -> Self {
38 match v {
39 MemoryError::SizeIsZero => AllocationGrowError::SizeIsZero,
40 MemoryError::OutOfMemory => AllocationGrowError::OutOfMemory,
41 MemoryError::AlignmentFailure => AllocationGrowError::AlignmentFailure,
42 MemoryError::UnknownError(_) => AllocationGrowError::InternalError,
43 }
44 }
45}
46
47impl From<MemoryError> for AllocationShrinkError {
48 fn from(v: MemoryError) -> Self {
49 match v {
50 MemoryError::SizeIsZero => AllocationShrinkError::SizeIsZero,
51 MemoryError::AlignmentFailure => AllocationShrinkError::AlignmentFailure,
52 _ => AllocationShrinkError::InternalError,
53 }
54 }
55}
56
57#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
58pub enum MemoryError {
59 OutOfMemory,
60 SizeIsZero,
61 AlignmentFailure,
62 UnknownError(i32),
63}
64
65pub mod heap {
67 use iceoryx2_log::fail;
68
69 use super::*;
70
71 use super::MemoryError;
72 const MEMORY_START_STORAGE_SPACE: usize = core::mem::size_of::<usize>();
73
74 fn setup_and_align(
75 msg: &str,
76 addr: usize,
77 layout: Layout,
78 ) -> Result<NonNull<[u8]>, MemoryError> {
79 if addr == 0 {
80 handle_errno!(MemoryError, from "heap::setup_and_align",
81 Errno::ENOMEM => (OutOfMemory, "{} a size of {} and an alignment of {} due to insufficient memory.", msg, layout.size(), layout.align() ),
82 v => (UnknownError(v as i32), "{} a size of {} and an alignment of {} since an unknown error occurred ({}).", msg, layout.size(), layout.align(), v)
83
84 );
85 }
86
87 let aligned_start = align(addr + MEMORY_START_STORAGE_SPACE, layout.align());
88 unsafe { *(aligned_start as *mut usize).offset(-1) = addr };
89
90 Ok(NonNull::new(core::ptr::slice_from_raw_parts_mut(
91 aligned_start as *mut u8,
92 layout.size(),
93 ))
94 .unwrap())
95 }
96
97 fn check_precondition(msg: &str, layout: Layout) -> Result<(), MemoryError> {
98 if layout.size() == 0 {
99 fail!(from "heap::check_precondition", with MemoryError::SizeIsZero,
100 "{} a size of {} and an alignment of {} since the size is 0.",
101 msg,
102 layout.size(),
103 layout.align()
104 );
105 }
106 Ok(())
107 }
108
109 unsafe fn extract_address(addr: usize) -> usize {
110 let memory = addr as *const usize;
111 *memory.offset(-1)
112 }
113
114 pub fn allocate(layout: Layout) -> Result<NonNull<[u8]>, MemoryError> {
116 let msg = "Unable to allocate heap memory with";
117 check_precondition(msg, layout)?;
118
119 let alignment_adjustment_buffer = layout.align() - 1;
120 let unaligned_start = unsafe {
121 posix::malloc(layout.size() + alignment_adjustment_buffer + MEMORY_START_STORAGE_SPACE)
122 } as usize;
123
124 setup_and_align(msg, unaligned_start, layout)
125 }
126
127 pub fn allocate_zeroed(layout: Layout) -> Result<NonNull<[u8]>, MemoryError> {
129 let msg = "Unable to allocate zeroed heap memory with";
130 check_precondition(msg, layout)?;
131
132 let alignment_adjustment_buffer = layout.align() - 1;
133 let unaligned_start = unsafe {
134 posix::calloc(
135 layout.size() + alignment_adjustment_buffer + MEMORY_START_STORAGE_SPACE,
136 1,
137 )
138 } as usize;
139
140 setup_and_align(msg, unaligned_start, layout)
141 }
142
143 pub unsafe fn resize(
153 ptr: NonNull<u8>,
154 old_layout: Layout,
155 new_layout: Layout,
156 ) -> Result<NonNull<[u8]>, MemoryError> {
157 let msg = "Unable to resize heap memory to";
158 check_precondition(msg, new_layout)?;
159
160 if old_layout.align() < new_layout.align() {
161 fail!(from "heap::resize", with MemoryError::AlignmentFailure,
162 "{} {} since the new layouts alignment was increased from {} to {}.",
163 msg,
164 new_layout.size(),
165 old_layout.align(),
166 new_layout.align()
167 );
168 }
169
170 let alignment_adjustment_buffer = new_layout.align() - 1;
171
172 let current_unaligned_start = extract_address(ptr.as_ptr() as usize);
173 let new_unaligned_start = posix::realloc(
174 current_unaligned_start as *mut posix::void,
175 new_layout.size() + alignment_adjustment_buffer + MEMORY_START_STORAGE_SPACE,
176 ) as usize;
177
178 setup_and_align(msg, new_unaligned_start, new_layout)
179 }
180
181 pub unsafe fn deallocate(ptr: NonNull<u8>, _layout: Layout) {
190 posix::free(extract_address(ptr.as_ptr() as usize) as *mut posix::void)
191 }
192}