use core::ptr; use Allocator; pub struct System { _priv: (), } impl System { pub const fn new() -> System { System { _priv: () } } } #[cfg(target_arch = "riscv32")] mod sys { use core::arch::asm; pub fn increase_heap(length: usize) -> Result<(usize, usize), ()> { let syscall_no_increase_heap = 10usize; let memory_flags_read_write = 2usize | 4usize; let mut a0 = syscall_no_increase_heap; let mut a1 = length; let mut a2 = memory_flags_read_write; unsafe { asm!( "ecall", inlateout("a0") a0, inlateout("a1") a1, inlateout("a2") a2, out("a3") _, out("a4") _, out("a5") _, out("a6") _, out("a7") _, ) }; let result = a0; let address = a1; let length = a2; // 3 is the "MemoryRange" type, and the result is only valid // if we get nonzero address and length. if result == 3 && address != 0 && length != 0 { Ok((address, length)) } else { Err(()) } } } unsafe impl Allocator for System { /// Allocate an additional `size` bytes on the heap, and return a new /// chunk of memory, as well as the size of the allocation and some /// flags. Since flags are unused on this platform, they will always /// be `0`. fn alloc(&self, size: usize) -> (*mut u8, usize, u32) { let size = if size == 0 { 4096 } else if size & 4095 == 0 { size } else { size + (4096 - (size & 4095)) }; if let Ok((address, length)) = sys::increase_heap(size) { let start = address - size + length; (start as *mut u8, size, 0) } else { (ptr::null_mut(), 0, 0) } } fn remap(&self, _ptr: *mut u8, _oldsize: usize, _newsize: usize, _can_move: bool) -> *mut u8 { // TODO ptr::null_mut() } fn free_part(&self, _ptr: *mut u8, _oldsize: usize, _newsize: usize) -> bool { false } fn free(&self, _ptr: *mut u8, _size: usize) -> bool { false } fn can_release_part(&self, _flags: u32) -> bool { false } fn allocates_zeros(&self) -> bool { true } fn page_size(&self) -> usize { 4 * 1024 } } #[cfg(feature = "global")] pub fn acquire_global_lock() { // global feature should not be enabled unimplemented!() } #[cfg(feature = "global")] pub fn release_global_lock() { // global feature should not be enabled unimplemented!() } #[cfg(feature = "global")] pub unsafe fn enable_alloc_after_fork() { // platform does not support `fork()` call }