1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
use crate::buddy_alloc::BuddyAlloc;
use core::alloc::{GlobalAlloc, Layout};
use core::cell::RefCell;

/// NonThreadsafeAlloc
/// perfect for single threaded devices
pub struct NonThreadsafeAlloc {
    inner: RefCell<Option<BuddyAlloc>>,
    base_addr: *const u8,
    len: usize,
}

impl NonThreadsafeAlloc {
    /// see BuddyAlloc::new
    pub const fn new(base_addr: *const u8, len: usize) -> Self {
        NonThreadsafeAlloc {
            inner: RefCell::new(None),
            base_addr,
            len,
        }
    }

    unsafe fn fetch_inner<R, F: FnOnce(&mut BuddyAlloc) -> R>(&self, f: F) -> R {
        let mut inner = self.inner.borrow_mut();
        if inner.is_none() {
            inner.replace(BuddyAlloc::new(self.base_addr, self.len));
        }
        f(inner.as_mut().expect("nerver"))
    }
}

unsafe impl GlobalAlloc for NonThreadsafeAlloc {
    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
        self.fetch_inner(|alloc| alloc.malloc(layout.size()))
    }
    unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
        self.fetch_inner(|alloc| alloc.free(ptr));
    }
}

unsafe impl Sync for NonThreadsafeAlloc {}