Skip to content

Commit ce2562d

Browse files
author
Jonathan Pallant (42 Technology)
committed
Clean up allocators.
They were basically the same, so now there's one function which is given the specific heap to use.
1 parent 62c6fdb commit ce2562d

File tree

1 file changed

+60
-82
lines changed

1 file changed

+60
-82
lines changed

src/ffi.rs

Lines changed: 60 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ type NrfxIpcHandler = extern "C" fn(event_mask: u32, ptr: *mut u8);
3333
#[derive(Debug, Copy, Clone)]
3434
pub enum NrfxErr {
3535
///< Operation performed successfully.
36-
Success = (0x0BAD0000 + 0),
36+
Success = 0x0BAD0000,
3737
///< Internal error.
3838
ErrorInternal = (0x0BAD0000 + 1),
3939
///< No memory for operation.
@@ -147,33 +147,7 @@ pub extern "C" fn nrf_modem_irrecoverable_error_handler(err: u32) -> ! {
147147
/// memory regions. This function allocates dynamic memory for the library.
148148
#[no_mangle]
149149
pub extern "C" fn nrf_modem_os_alloc(num_bytes_requested: usize) -> *mut u8 {
150-
let usize_size = core::mem::size_of::<usize>();
151-
let mut result = core::ptr::null_mut();
152-
unsafe {
153-
cortex_m::interrupt::free(|cs| {
154-
let num_bytes_allocated = num_bytes_requested + usize_size;
155-
let layout =
156-
core::alloc::Layout::from_size_align_unchecked(num_bytes_allocated, usize_size);
157-
if let Some(ref mut allocator) = *crate::GENERIC_ALLOCATOR.borrow(cs).borrow_mut() {
158-
match allocator.allocate_first_fit(layout) {
159-
Ok(real_block) => {
160-
let real_ptr = real_block.as_ptr();
161-
// We need the block size to run the de-allocation. Store it in the first four bytes.
162-
core::ptr::write_volatile::<usize>(
163-
real_ptr as *mut usize,
164-
num_bytes_allocated,
165-
);
166-
// Give them the rest of the block
167-
result = real_ptr.offset(usize_size as isize);
168-
}
169-
Err(_e) => {
170-
// Ignore
171-
}
172-
}
173-
}
174-
});
175-
}
176-
result
150+
unsafe { generic_alloc(num_bytes_requested, &crate::LIBRARY_ALLOCATOR) }
177151
}
178152

179153
/// The Modem library needs to dynamically allocate memory (a heap) for proper
@@ -184,20 +158,8 @@ pub extern "C" fn nrf_modem_os_alloc(num_bytes_requested: usize) -> *mut u8 {
184158
/// memory regions. This function allocates dynamic memory for the library.
185159
#[no_mangle]
186160
pub extern "C" fn nrf_modem_os_free(ptr: *mut u8) {
187-
let usize_size = core::mem::size_of::<usize>() as isize;
188161
unsafe {
189-
cortex_m::interrupt::free(|cs| {
190-
// Fetch the size from the previous four bytes
191-
let real_ptr = ptr.offset(-usize_size);
192-
let num_bytes_allocated = core::ptr::read_volatile::<usize>(real_ptr as *const usize);
193-
let layout = core::alloc::Layout::from_size_align_unchecked(
194-
num_bytes_allocated,
195-
usize_size as usize,
196-
);
197-
if let Some(ref mut allocator) = *crate::GENERIC_ALLOCATOR.borrow(cs).borrow_mut() {
198-
allocator.deallocate(core::ptr::NonNull::new_unchecked(real_ptr), layout);
199-
}
200-
});
162+
generic_free(ptr, &crate::LIBRARY_ALLOCATOR);
201163
}
202164
}
203165

@@ -207,54 +169,16 @@ pub extern "C" fn nrf_modem_os_free(ptr: *mut u8) {
207169
/// @return pointer to allocated memory
208170
#[no_mangle]
209171
pub extern "C" fn nrf_modem_os_shm_tx_alloc(num_bytes_requested: usize) -> *mut u8 {
210-
let usize_size = core::mem::size_of::<usize>();
211-
let mut result = core::ptr::null_mut();
212-
unsafe {
213-
cortex_m::interrupt::free(|cs| {
214-
let num_bytes_allocated = num_bytes_requested + usize_size;
215-
let layout =
216-
core::alloc::Layout::from_size_align_unchecked(num_bytes_allocated, usize_size);
217-
if let Some(ref mut allocator) = *crate::TX_ALLOCATOR.borrow(cs).borrow_mut() {
218-
match allocator.allocate_first_fit(layout) {
219-
Ok(real_block) => {
220-
let real_ptr = real_block.as_ptr();
221-
// We need the block size to run the de-allocation. Store it in the first four bytes.
222-
core::ptr::write_volatile::<usize>(
223-
real_ptr as *mut usize,
224-
num_bytes_allocated,
225-
);
226-
// Give them the rest of the block
227-
result = real_ptr.offset(usize_size as isize);
228-
}
229-
Err(_e) => {
230-
// Ignore
231-
}
232-
}
233-
}
234-
});
235-
}
236-
result
172+
unsafe { generic_alloc(num_bytes_requested, &crate::TX_ALLOCATOR) }
237173
}
238174

239175
/// Free a shared memory buffer in the TX area.
240176
///
241177
/// @param ptr Th buffer to free.
242178
#[no_mangle]
243179
pub extern "C" fn nrf_modem_os_shm_tx_free(ptr: *mut u8) {
244-
let usize_size = core::mem::size_of::<usize>() as isize;
245180
unsafe {
246-
cortex_m::interrupt::free(|cs| {
247-
// Fetch the size from the previous four bytes
248-
let real_ptr = ptr.offset(-usize_size);
249-
let num_bytes_allocated = core::ptr::read_volatile::<usize>(real_ptr as *const usize);
250-
let layout = core::alloc::Layout::from_size_align_unchecked(
251-
num_bytes_allocated,
252-
usize_size as usize,
253-
);
254-
if let Some(ref mut allocator) = *crate::TX_ALLOCATOR.borrow(cs).borrow_mut() {
255-
allocator.deallocate(core::ptr::NonNull::new_unchecked(real_ptr), layout);
256-
}
257-
});
181+
generic_free(ptr, &crate::TX_ALLOCATOR);
258182
}
259183
}
260184

@@ -302,7 +226,7 @@ pub extern "C" fn nrfx_ipc_init(
302226
let irq_num = usize::from(irq.number());
303227
unsafe {
304228
cortex_m::peripheral::NVIC::unmask(irq);
305-
(*cortex_m::peripheral::NVIC::ptr()).ipr[irq_num].write(irq_priority.into());
229+
(*cortex_m::peripheral::NVIC::ptr()).ipr[irq_num].write(irq_priority);
306230
}
307231
IPC_CONTEXT.store(p_context, core::sync::atomic::Ordering::SeqCst);
308232
IPC_HANDLER.store(handler as usize, core::sync::atomic::Ordering::SeqCst);
@@ -316,6 +240,60 @@ pub extern "C" fn nrfx_ipc_uninit() {
316240
unimplemented!();
317241
}
318242

243+
/// Allocate some memory from the given heap.
244+
///
245+
/// We allocate four extra bytes so that we can store the number of bytes
246+
/// requested. This will be needed later when the memory is freed.
247+
///
248+
/// This function is safe to call from an ISR.
249+
unsafe fn generic_alloc(num_bytes_requested: usize, heap: &crate::WrappedHeap) -> *mut u8 {
250+
let sizeof_usize = core::mem::size_of::<usize>();
251+
let mut result = core::ptr::null_mut();
252+
cortex_m::interrupt::free(|cs| {
253+
let num_bytes_allocated = num_bytes_requested + sizeof_usize;
254+
let layout =
255+
core::alloc::Layout::from_size_align_unchecked(num_bytes_allocated, sizeof_usize);
256+
if let Some(ref mut inner_alloc) = *heap.borrow(cs).borrow_mut() {
257+
match inner_alloc.allocate_first_fit(layout) {
258+
Ok(real_block) => {
259+
let real_ptr = real_block.as_ptr();
260+
// We need the block size to run the de-allocation. Store it in the first four bytes.
261+
core::ptr::write_volatile::<usize>(real_ptr as *mut usize, num_bytes_allocated);
262+
// Give them the rest of the block
263+
result = real_ptr.add(sizeof_usize);
264+
}
265+
Err(_e) => {
266+
// Ignore
267+
}
268+
}
269+
}
270+
});
271+
result
272+
}
273+
274+
/// Free some memory back on to the given heap.
275+
///
276+
/// First we must wind the pointer back four bytes to recover the `usize` we
277+
/// stashed during the allocation. We use this to recreate the `Layout` required
278+
/// for the `deallocate` function.
279+
///
280+
/// This function is safe to call from an ISR.
281+
unsafe fn generic_free(ptr: *mut u8, heap: &crate::WrappedHeap) {
282+
let sizeof_usize = core::mem::size_of::<usize>() as isize;
283+
cortex_m::interrupt::free(|cs| {
284+
// Fetch the size from the previous four bytes
285+
let real_ptr = ptr.offset(-sizeof_usize);
286+
let num_bytes_allocated = core::ptr::read_volatile::<usize>(real_ptr as *const usize);
287+
let layout = core::alloc::Layout::from_size_align_unchecked(
288+
num_bytes_allocated,
289+
sizeof_usize as usize,
290+
);
291+
if let Some(ref mut inner_alloc) = *heap.borrow(cs).borrow_mut() {
292+
inner_alloc.deallocate(core::ptr::NonNull::new_unchecked(real_ptr), layout);
293+
}
294+
});
295+
}
296+
319297
/// Call this when we have an IPC IRQ. Not `extern C` as its not called by the
320298
/// library, only our interrupt handler code.
321299
pub unsafe fn ipc_irq_handler() {

0 commit comments

Comments
 (0)