buddy_alloc/
non_threadsafe_alloc.rs1use crate::buddy_alloc::{BuddyAlloc, BuddyAllocParam};
5use crate::fast_alloc::{FastAlloc, FastAllocParam, BLOCK_SIZE};
6use core::alloc::{GlobalAlloc, Layout};
7use core::cell::RefCell;
8
9const MAX_FAST_ALLOC_SIZE: usize = BLOCK_SIZE;
12
13pub struct NonThreadsafeAlloc {
16 fast_alloc_param: FastAllocParam,
17 inner_fast_alloc: RefCell<Option<FastAlloc>>,
18 buddy_alloc_param: BuddyAllocParam,
19 inner_buddy_alloc: RefCell<Option<BuddyAlloc>>,
20}
21
22impl NonThreadsafeAlloc {
23 pub const fn new(fast_alloc_param: FastAllocParam, buddy_alloc_param: BuddyAllocParam) -> Self {
25 NonThreadsafeAlloc {
26 inner_fast_alloc: RefCell::new(None),
27 inner_buddy_alloc: RefCell::new(None),
28 fast_alloc_param,
29 buddy_alloc_param,
30 }
31 }
32
33 unsafe fn with_fast_alloc<R, F: FnOnce(&mut FastAlloc) -> R>(&self, f: F) -> R {
34 let mut inner = self.inner_fast_alloc.borrow_mut();
35 let alloc = inner.get_or_insert_with(|| FastAlloc::new(self.fast_alloc_param));
36 f(alloc)
37 }
38
39 unsafe fn with_buddy_alloc<R, F: FnOnce(&mut BuddyAlloc) -> R>(&self, f: F) -> R {
40 let mut inner = self.inner_buddy_alloc.borrow_mut();
41 let alloc = inner.get_or_insert_with(|| BuddyAlloc::new(self.buddy_alloc_param));
42 f(alloc)
43 }
44}
45
46unsafe impl GlobalAlloc for NonThreadsafeAlloc {
47 unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
48 let bytes = layout.size();
49 if bytes > MAX_FAST_ALLOC_SIZE {
51 self.with_buddy_alloc(|alloc| alloc.malloc(bytes))
52 } else {
53 let mut p = self.with_fast_alloc(|alloc| alloc.malloc(bytes));
55 if p.is_null() {
56 p = self.with_buddy_alloc(|alloc| alloc.malloc(bytes));
57 }
58 p
59 }
60 }
61 unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
62 let freed = self.with_fast_alloc(|alloc| {
63 if alloc.contains_ptr(ptr) {
64 alloc.free(ptr);
65 true
66 } else {
67 false
68 }
69 });
70 if !freed {
71 self.with_buddy_alloc(|alloc| alloc.free(ptr));
72 }
73 }
74}
75
76unsafe impl Sync for NonThreadsafeAlloc {}