-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement GlobalAlloc for ESP32? #4
Comments
I copied some code and ended up like this:
Then initial by:
Not sure if this is safe but it seems like it works |
Yes, that's the right way to implement a default allocator on unsupported targets, except that you don't need Just in case though: Locking by |
@yvt I'm using embassy and is suspectable to this. Any recommendation to mitigate locks? Of course we can't redesign TLSF to go lock-free... |
It appears Embassy is based on cooperative (non-preemptive) scheduling. In this case, if you don't need to use the allocator in interrupt handlers, If you need to use it in interrupt handlers, interrupts need to be disabled while holding a lock. The main disadvantage of this approach is an increased interrupt latency. You should remove the custom implementation of
(These " |
Just skimmed Embassy documentation, but this looks useful: |
@yvt Based on your suggestion I implemented the following instead: use core::{
alloc::{GlobalAlloc, Layout},
mem::MaybeUninit,
ptr::{self, NonNull},
};
use const_default::ConstDefault;
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
use embassy_sync::mutex::Mutex;
use riscv::interrupt;
use rlsf::Tlsf;
pub struct GlobalTlsf<'a> {
#[cfg(not(doc))]
inner: Mutex<NoopRawMutex, TheTlsf<'a>>,
}
type TheTlsf<'a> = Tlsf<'a, usize, usize, { usize::BITS as usize }, { usize::BITS as usize }>;
unsafe impl Send for GlobalTlsf<'_> {}
unsafe impl Sync for GlobalTlsf<'_> {}
impl<'a> GlobalTlsf<'a> {
#[inline]
pub const fn new() -> Self {
Self {
inner: Mutex::new(ConstDefault::DEFAULT),
}
}
pub fn init(&mut self, array: &'a mut [MaybeUninit<u8>]) {
interrupt::free(|| {
let mut inner = self.inner.try_lock().expect("deadlock detected");
inner.insert_free_block(array);
})
}
}
unsafe impl GlobalAlloc for GlobalTlsf<'_> {
#[inline]
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
interrupt::free(|| {
let mut inner = self.inner.try_lock().expect("deadlock detected");
inner
.allocate(layout)
.map(NonNull::as_ptr)
.unwrap_or(ptr::null_mut())
})
}
#[inline]
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
interrupt::free(|| {
let mut inner = self.inner.try_lock().expect("deadlock detected");
let ptr = NonNull::new_unchecked(ptr);
inner.deallocate(ptr, layout.align());
})
}
} Not sure if it should be added to main crate or just kept as an example for other to implement on their own |
Currently I put TLSF in as a global static mut with a static memory provider from
EspHeap
:It seems like EspHeap does not offer a default method either so I can't take the heap from system (so EspHeap is layered upon). I may need to directly implement a flex source. What are the pointers for me to implement a FlexSource and eventually a global allocator?
The text was updated successfully, but these errors were encountered: