#![deny(missing_docs)]
use core::{alloc::Layout, mem::MaybeUninit, ptr::NonNull};
use consts::MAX_POOL_SIZE;
use err::FMempError;
use lazy_static::*;
use pool_buffer::PoolBuffer;
use rlsf::Tlsf;
use spin::Mutex;
mod consts;
mod err;
pub mod pool_buffer;
static mut POOL: [MaybeUninit<u8>; MAX_POOL_SIZE] = [MaybeUninit::uninit(); MAX_POOL_SIZE];
pub struct FMemp<'a> {
tlsf_ptr: Tlsf<'a, u32, u32, 32, 32>,
is_ready: bool,
}
lazy_static! {
pub static ref GLOBAL_FMEMP: Mutex<FMemp<'static>> =
Mutex::new(FMemp::new());
}
impl<'a> Default for FMemp<'a> {
fn default() -> Self {
Self::new()
}
}
impl<'a> FMemp<'a> {
pub fn new() -> Self {
Self {
tlsf_ptr: Tlsf::new(),
is_ready: false,
}
}
unsafe fn init(&mut self) {
unsafe {
self.tlsf_ptr.insert_free_block(&mut POOL[..]);
self.is_ready = true;
}
}
unsafe fn alloc_aligned(
&mut self,
size: usize,
align: usize,
) -> Result<PoolBuffer, FMempError> {
unsafe {
let layout = Layout::from_size_align_unchecked(size, align);
if let Some(result) = self.tlsf_ptr.allocate(layout) {
let buffer = PoolBuffer::new(size, result);
Ok(buffer)
} else {
Err(FMempError::BadMalloc)
}
}
}
unsafe fn dealloc(&mut self, addr: NonNull<u8>, size: usize) {
unsafe {
self.tlsf_ptr.deallocate(addr, size);
}
}
}
pub fn osa_init() {
unsafe {
GLOBAL_FMEMP.lock().init();
}
}
pub fn osa_alloc(size: usize) -> Result<PoolBuffer, FMempError> {
unsafe { GLOBAL_FMEMP.lock().alloc_aligned(size, size_of::<usize>()) }
}
pub fn osa_alloc_aligned(size: usize, align: usize) -> Result<PoolBuffer, FMempError> {
unsafe { GLOBAL_FMEMP.lock().alloc_aligned(size, align) }
}
pub fn osa_dealloc(addr: NonNull<u8>, size: usize) {
unsafe {
GLOBAL_FMEMP.lock().dealloc(addr, size);
}
}