blob: 14dbfa1bca9a5f8fd7b8f7d4fcb860b9dbd95df7 [file] [log] [blame] [edit]
use crate::Allocator;
use core::ptr;
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
}