use crate::{print_msg, putc};
use core::alloc::{GlobalAlloc, Layout};
pub struct FeAllocator;
#[repr(C)]
pub struct LayoutFFI {
pub size: usize,
pub align: usize,
}
extern "C" {
fn do_alloc(layout: LayoutFFI) -> *mut u8;
fn do_dealloc(ptr: *mut u8, layout: LayoutFFI) -> usize;
fn do_get_heap_remaining() -> usize;
}
pub fn get_heap_remaining() -> usize {
unsafe { do_get_heap_remaining() }
}
unsafe impl GlobalAlloc for FeAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
let layout_ffi: LayoutFFI = LayoutFFI {
size: layout.size(),
align: layout.align(),
};
do_alloc(layout_ffi)
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
let layout_ffi: LayoutFFI = LayoutFFI {
size: layout.size(),
align: layout.align(),
};
do_dealloc(ptr, layout_ffi);
}
}
fn usize_to_chars(char_slice: &mut [u8], num: usize) -> usize {
let mut i = char_slice.len() - 1;
let mut val = num;
loop {
char_slice[i] = ((val % 10) + 0x30) as u8;
val /= 10;
if val == 0 || i == 0 {
break;
}
i -= 1;
}
i
}
#[alloc_error_handler]
fn error_handler(layout: Layout) -> ! {
let mut digits: [u8; 20] = [0; 20];
print_msg("Out of memory!\n");
print_msg("Size: ");
let start_idx = usize_to_chars(&mut digits, layout.size());
print_msg(core::str::from_utf8(&digits[start_idx..]).unwrap());
print_msg(" Alignment: ");
let start_idx = usize_to_chars(&mut digits, layout.align());
print_msg(core::str::from_utf8(&digits[start_idx..]).unwrap());
putc('\n');
crate::exit();
loop {}
}