forked from M-Labs/artiq
1
0
Fork 0

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] #![no_std]
#![allocator] #![allocator]
use core::{mem, ptr, cmp};
// The minimum alignment guaranteed by the architecture. // The minimum alignment guaranteed by the architecture.
const MIN_ALIGN: usize = 8; const MIN_ALIGN: usize = 4;
#[no_mangle] const MAGIC_FREE: usize = 0xDEADDEAD;
pub extern "C" fn __rust_allocate(size: usize, align: usize) -> *mut u8 { const MAGIC_BUSY: usize = 0xFEEDFEED;
unsafe { imp::allocate(size, align) }
}
#[no_mangle] #[derive(Debug)]
pub extern "C" fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) { struct Header {
unsafe { imp::deallocate(ptr, old_size, align) } magic: usize,
}
#[no_mangle]
pub extern "C" fn __rust_reallocate(ptr: *mut u8,
old_size: usize,
size: usize, size: usize,
align: usize) next: *mut Header
-> *mut u8 { }
unsafe { imp::reallocate(ptr, old_size, size, align) }
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] #[no_mangle]
pub extern "C" fn __rust_reallocate_inplace(ptr: *mut u8, pub extern fn __rust_allocate(mut size: usize, align: usize) -> *mut u8 {
old_size: usize, assert!(align <= MIN_ALIGN);
size: usize,
align: usize) let header_size = mem::size_of::<Header>();
-> usize { if size % header_size != 0 {
unsafe { imp::reallocate_inplace(ptr, old_size, size, align) } size += header_size - (size % header_size);
}
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;
}
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)
}
curr = (*curr).next;
}
}
ptr::null_mut()
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn __rust_usable_size(size: usize, align: usize) -> usize { pub extern fn __rust_deallocate(ptr: *mut u8, _old_size: usize, _align: usize) {
imp::usable_size(size, align) 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;
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)
} }
} }
unsafe fn aligned_malloc(_size: usize, _align: usize) -> *mut u8 { #[no_mangle]
panic!("aligned_malloc not implemented") pub extern fn __rust_reallocate(ptr: *mut u8, old_size: usize, size: usize,
} align: usize) -> *mut u8 {
unsafe {
pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, let new_ptr = __rust_allocate(size, align);
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() { if !new_ptr.is_null() {
ptr::copy(ptr, new_ptr, cmp::min(size, old_size)); ptr::copy_nonoverlapping(ptr, new_ptr, cmp::min(old_size, size));
deallocate(ptr, old_size, align); __rust_deallocate(ptr, old_size, align);
} }
new_ptr new_ptr
} }
} }
pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: usize, #[no_mangle]
_size: usize, _align: usize) -> usize { pub extern fn __rust_reallocate_inplace(_ptr: *mut u8, old_size: usize, _size: usize,
_align: usize) -> usize {
old_size old_size
} }
pub unsafe fn deallocate(ptr: *mut u8, _old_size: usize, _align: usize) { #[no_mangle]
libc::free(ptr as *mut libc::c_void) pub extern fn __rust_usable_size(size: usize, _align: usize) -> usize {
}
pub fn usable_size(size: usize, _align: usize) -> usize {
size size
} }
}

View File

@ -146,7 +146,6 @@ extern {
fn uart_init(); fn uart_init();
fn uart_isr(); fn uart_isr();
fn alloc_give(ptr: *mut u8, length: usize);
static mut _fheap: u8; static mut _fheap: u8;
static mut _eheap: u8; static mut _eheap: u8;
} }
@ -157,7 +156,7 @@ pub unsafe extern fn main() -> i32 {
irq::set_ie(true); irq::set_ie(true);
uart_init(); uart_init();
alloc_give(&mut _fheap as *mut u8, alloc_artiq::seed(&mut _fheap as *mut u8,
&_eheap as *const u8 as usize - &_fheap as *const u8 as usize); &_eheap as *const u8 as usize - &_fheap as *const u8 as usize);
static mut LOG_BUFFER: [u8; 65536] = [0; 65536]; static mut LOG_BUFFER: [u8; 65536] = [0; 65536];

View File

@ -45,6 +45,8 @@ class AMPSoC:
def build_artiq_soc(soc, argdict): def build_artiq_soc(soc, argdict):
builder = Builder(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.add_software_package("runtime", os.path.join(artiq_dir, "runtime"))
builder.build() builder.build()

View File

@ -118,7 +118,6 @@ def main():
soc = Satellite(args.config, **soc_kc705_argdict(args)) soc = Satellite(args.config, **soc_kc705_argdict(args))
builder = Builder(soc, **builder_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.add_software_package("satman", os.path.join(artiq_dir, "firmware", "satman"))
builder.build() builder.build()

View File

@ -25,7 +25,6 @@ LDFLAGS += --gc-sections \
-L../libcompiler-rt \ -L../libcompiler-rt \
-L../libbase \ -L../libbase \
-L../libm \ -L../libm \
-L../liballoc \
-L../libunwind \ -L../libunwind \
-L../libdyld -L../libdyld
@ -44,7 +43,7 @@ runtime.elf: $(RUSTOUT)/libruntime.a ksupport_data.o
-T $(RUNTIME_DIRECTORY)/runtime.ld \ -T $(RUNTIME_DIRECTORY)/runtime.ld \
-o $@ \ -o $@ \
$^ \ $^ \
-lbase-nofloat -lcompiler-rt -lalloc -lbase-nofloat -lcompiler-rt
@chmod -x $@ @chmod -x $@
.PHONY: $(RUSTOUT_KSUPPORT)/libksupport.a .PHONY: $(RUSTOUT_KSUPPORT)/libksupport.a