forked from M-Labs/artiq
firmware: port allocator to Rust.
This commit is contained in:
parent
f512ea42dc
commit
44a9a79f96
@ -1,86 +1,119 @@
|
||||
#![feature(allocator, libc)]
|
||||
#![allow(dead_code)] // FIXME
|
||||
|
||||
#![feature(allocator)]
|
||||
#![no_std]
|
||||
#![allocator]
|
||||
|
||||
use core::{mem, ptr, cmp};
|
||||
|
||||
// The minimum alignment guaranteed by the architecture.
|
||||
const MIN_ALIGN: usize = 8;
|
||||
const MIN_ALIGN: usize = 4;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn __rust_allocate(size: usize, align: usize) -> *mut u8 {
|
||||
unsafe { imp::allocate(size, align) }
|
||||
const MAGIC_FREE: usize = 0xDEADDEAD;
|
||||
const MAGIC_BUSY: usize = 0xFEEDFEED;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Header {
|
||||
magic: usize,
|
||||
size: usize,
|
||||
next: *mut Header
|
||||
}
|
||||
|
||||
static mut ROOT: *mut Header = 0 as *mut _;
|
||||
|
||||
pub unsafe fn seed(ptr: *mut u8, size: usize) {
|
||||
let header_size = mem::size_of::<Header>();
|
||||
|
||||
if size < header_size * 2 { return }
|
||||
|
||||
let curr = ptr as *mut Header;
|
||||
(*curr).magic = MAGIC_FREE;
|
||||
(*curr).size = size - header_size;
|
||||
(*curr).next = ROOT;
|
||||
ROOT = curr;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) {
|
||||
unsafe { imp::deallocate(ptr, old_size, align) }
|
||||
}
|
||||
pub extern fn __rust_allocate(mut size: usize, align: usize) -> *mut u8 {
|
||||
assert!(align <= MIN_ALIGN);
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn __rust_reallocate(ptr: *mut u8,
|
||||
old_size: usize,
|
||||
size: usize,
|
||||
align: usize)
|
||||
-> *mut u8 {
|
||||
unsafe { imp::reallocate(ptr, old_size, size, align) }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn __rust_reallocate_inplace(ptr: *mut u8,
|
||||
old_size: usize,
|
||||
size: usize,
|
||||
align: usize)
|
||||
-> usize {
|
||||
unsafe { imp::reallocate_inplace(ptr, old_size, size, align) }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn __rust_usable_size(size: usize, align: usize) -> usize {
|
||||
imp::usable_size(size, align)
|
||||
}
|
||||
|
||||
mod imp {
|
||||
extern crate libc;
|
||||
|
||||
use core::cmp;
|
||||
use core::ptr;
|
||||
use MIN_ALIGN;
|
||||
|
||||
pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
|
||||
if align <= MIN_ALIGN {
|
||||
libc::malloc(size as libc::size_t) as *mut u8
|
||||
} else {
|
||||
aligned_malloc(size, align)
|
||||
}
|
||||
let header_size = mem::size_of::<Header>();
|
||||
if size % header_size != 0 {
|
||||
size += header_size - (size % header_size);
|
||||
}
|
||||
|
||||
unsafe fn aligned_malloc(_size: usize, _align: usize) -> *mut u8 {
|
||||
panic!("aligned_malloc not implemented")
|
||||
}
|
||||
unsafe {
|
||||
let mut curr = ROOT;
|
||||
while !curr.is_null() {
|
||||
match (*curr).magic {
|
||||
MAGIC_BUSY => (),
|
||||
MAGIC_FREE => {
|
||||
let mut next = (*curr).next;
|
||||
while !next.is_null() && (*next).magic == MAGIC_FREE {
|
||||
// Join
|
||||
(*next).magic = 0;
|
||||
(*curr).size += (*next).size + header_size;
|
||||
(*curr).next = (*next).next;
|
||||
next = (*curr).next;
|
||||
}
|
||||
|
||||
pub unsafe fn reallocate(ptr: *mut u8, old_size: usize,
|
||||
size: usize, align: usize) -> *mut u8 {
|
||||
if align <= MIN_ALIGN {
|
||||
libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8
|
||||
} else {
|
||||
let new_ptr = allocate(size, align);
|
||||
if !new_ptr.is_null() {
|
||||
ptr::copy(ptr, new_ptr, cmp::min(size, old_size));
|
||||
deallocate(ptr, old_size, align);
|
||||
if (*curr).size > size + header_size * 2 {
|
||||
// Split
|
||||
let offset = header_size + size;
|
||||
let next = (curr as *mut u8).offset(offset as isize) as *mut Header;
|
||||
(*next).magic = MAGIC_FREE;
|
||||
(*next).size = (*curr).size - offset;
|
||||
(*next).next = (*curr).next;
|
||||
(*curr).next = next;
|
||||
(*curr).size = size;
|
||||
}
|
||||
|
||||
if (*curr).size >= size {
|
||||
(*curr).magic = MAGIC_BUSY;
|
||||
return curr.offset(1) as *mut u8
|
||||
}
|
||||
},
|
||||
_ => panic!("heap corruption detected at {:p}", curr)
|
||||
}
|
||||
new_ptr
|
||||
|
||||
curr = (*curr).next;
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: usize,
|
||||
_size: usize, _align: usize) -> usize {
|
||||
old_size
|
||||
}
|
||||
ptr::null_mut()
|
||||
}
|
||||
|
||||
pub unsafe fn deallocate(ptr: *mut u8, _old_size: usize, _align: usize) {
|
||||
libc::free(ptr as *mut libc::c_void)
|
||||
}
|
||||
|
||||
pub fn usable_size(size: usize, _align: usize) -> usize {
|
||||
size
|
||||
#[no_mangle]
|
||||
pub extern fn __rust_deallocate(ptr: *mut u8, _old_size: usize, _align: usize) {
|
||||
unsafe {
|
||||
let curr = (ptr as *mut Header).offset(-1);
|
||||
if (*curr).magic != MAGIC_BUSY {
|
||||
panic!("heap corruption detected at {:p}", curr)
|
||||
}
|
||||
(*curr).magic = MAGIC_FREE;
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn __rust_reallocate(ptr: *mut u8, old_size: usize, size: usize,
|
||||
align: usize) -> *mut u8 {
|
||||
unsafe {
|
||||
let new_ptr = __rust_allocate(size, align);
|
||||
if !new_ptr.is_null() {
|
||||
ptr::copy_nonoverlapping(ptr, new_ptr, cmp::min(old_size, size));
|
||||
__rust_deallocate(ptr, old_size, align);
|
||||
}
|
||||
new_ptr
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn __rust_reallocate_inplace(_ptr: *mut u8, old_size: usize, _size: usize,
|
||||
_align: usize) -> usize {
|
||||
old_size
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn __rust_usable_size(size: usize, _align: usize) -> usize {
|
||||
size
|
||||
}
|
||||
|
@ -146,7 +146,6 @@ extern {
|
||||
fn uart_init();
|
||||
fn uart_isr();
|
||||
|
||||
fn alloc_give(ptr: *mut u8, length: usize);
|
||||
static mut _fheap: u8;
|
||||
static mut _eheap: u8;
|
||||
}
|
||||
@ -157,8 +156,8 @@ pub unsafe extern fn main() -> i32 {
|
||||
irq::set_ie(true);
|
||||
uart_init();
|
||||
|
||||
alloc_give(&mut _fheap as *mut u8,
|
||||
&_eheap as *const u8 as usize - &_fheap as *const u8 as usize);
|
||||
alloc_artiq::seed(&mut _fheap as *mut u8,
|
||||
&_eheap as *const u8 as usize - &_fheap as *const u8 as usize);
|
||||
|
||||
static mut LOG_BUFFER: [u8; 65536] = [0; 65536];
|
||||
logger_artiq::BufferLogger::new(&mut LOG_BUFFER[..]).register(startup);
|
||||
|
@ -45,6 +45,8 @@ class AMPSoC:
|
||||
|
||||
def build_artiq_soc(soc, argdict):
|
||||
builder = Builder(soc, **argdict)
|
||||
builder.add_extra_software_packages()
|
||||
builder.add_software_package("libm")
|
||||
builder.add_software_package("libdyld")
|
||||
builder.add_software_package("libunwind")
|
||||
builder.add_software_package("runtime", os.path.join(artiq_dir, "runtime"))
|
||||
builder.build()
|
||||
|
@ -118,7 +118,6 @@ def main():
|
||||
|
||||
soc = Satellite(args.config, **soc_kc705_argdict(args))
|
||||
builder = Builder(soc, **builder_argdict(args))
|
||||
builder.add_software_package("liballoc")
|
||||
builder.add_software_package("satman", os.path.join(artiq_dir, "firmware", "satman"))
|
||||
builder.build()
|
||||
|
||||
|
@ -25,7 +25,6 @@ LDFLAGS += --gc-sections \
|
||||
-L../libcompiler-rt \
|
||||
-L../libbase \
|
||||
-L../libm \
|
||||
-L../liballoc \
|
||||
-L../libunwind \
|
||||
-L../libdyld
|
||||
|
||||
@ -44,7 +43,7 @@ runtime.elf: $(RUSTOUT)/libruntime.a ksupport_data.o
|
||||
-T $(RUNTIME_DIRECTORY)/runtime.ld \
|
||||
-o $@ \
|
||||
$^ \
|
||||
-lbase-nofloat -lcompiler-rt -lalloc
|
||||
-lbase-nofloat -lcompiler-rt
|
||||
@chmod -x $@
|
||||
|
||||
.PHONY: $(RUSTOUT_KSUPPORT)/libksupport.a
|
||||
|
Loading…
Reference in New Issue
Block a user