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]
|
#![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) }
|
|
||||||
|
#[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]
|
#[no_mangle]
|
||||||
pub extern "C" fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) {
|
pub extern fn __rust_allocate(mut size: usize, align: usize) -> *mut u8 {
|
||||||
unsafe { imp::deallocate(ptr, old_size, align) }
|
assert!(align <= MIN_ALIGN);
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
let header_size = mem::size_of::<Header>();
|
||||||
pub extern "C" fn __rust_reallocate(ptr: *mut u8,
|
if size % header_size != 0 {
|
||||||
old_size: usize,
|
size += header_size - (size % header_size);
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn aligned_malloc(_size: usize, _align: usize) -> *mut u8 {
|
unsafe {
|
||||||
panic!("aligned_malloc not implemented")
|
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,
|
if (*curr).size > size + header_size * 2 {
|
||||||
size: usize, align: usize) -> *mut u8 {
|
// Split
|
||||||
if align <= MIN_ALIGN {
|
let offset = header_size + size;
|
||||||
libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8
|
let next = (curr as *mut u8).offset(offset as isize) as *mut Header;
|
||||||
} else {
|
(*next).magic = MAGIC_FREE;
|
||||||
let new_ptr = allocate(size, align);
|
(*next).size = (*curr).size - offset;
|
||||||
if !new_ptr.is_null() {
|
(*next).next = (*curr).next;
|
||||||
ptr::copy(ptr, new_ptr, cmp::min(size, old_size));
|
(*curr).next = next;
|
||||||
deallocate(ptr, old_size, align);
|
(*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,
|
ptr::null_mut()
|
||||||
_size: usize, _align: usize) -> usize {
|
}
|
||||||
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_deallocate(ptr: *mut u8, _old_size: usize, _align: usize) {
|
||||||
}
|
unsafe {
|
||||||
|
let curr = (ptr as *mut Header).offset(-1);
|
||||||
pub fn usable_size(size: usize, _align: usize) -> usize {
|
if (*curr).magic != MAGIC_BUSY {
|
||||||
size
|
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_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,8 +156,8 @@ 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];
|
||||||
logger_artiq::BufferLogger::new(&mut LOG_BUFFER[..]).register(startup);
|
logger_artiq::BufferLogger::new(&mut LOG_BUFFER[..]).register(startup);
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue