firmware: port allocator to Rust.

This commit is contained in:
whitequark 2017-02-02 10:38:57 +00:00
parent f512ea42dc
commit 44a9a79f96
5 changed files with 106 additions and 74 deletions

View File

@ -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
}

View File

@ -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);

View File

@ -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()

View File

@ -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()

View File

@ -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