From 44a9a79f96027fe53b60529fefd0cdba530941eb Mon Sep 17 00:00:00 2001 From: whitequark Date: Thu, 2 Feb 2017 10:38:57 +0000 Subject: [PATCH] firmware: port allocator to Rust. --- artiq/firmware/liballoc_artiq/lib.rs | 167 +++++++++++------- artiq/firmware/runtime/lib.rs | 5 +- artiq/gateware/amp/soc.py | 4 +- .../gateware/targets/kc705_drtio_satellite.py | 1 - artiq/runtime/Makefile | 3 +- 5 files changed, 106 insertions(+), 74 deletions(-) diff --git a/artiq/firmware/liballoc_artiq/lib.rs b/artiq/firmware/liballoc_artiq/lib.rs index 28063a5e2..6e4278da4 100644 --- a/artiq/firmware/liballoc_artiq/lib.rs +++ b/artiq/firmware/liballoc_artiq/lib.rs @@ -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::
(); + + 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::
(); + 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 +} diff --git a/artiq/firmware/runtime/lib.rs b/artiq/firmware/runtime/lib.rs index 8c6c371f7..2a4bc19f6 100644 --- a/artiq/firmware/runtime/lib.rs +++ b/artiq/firmware/runtime/lib.rs @@ -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); diff --git a/artiq/gateware/amp/soc.py b/artiq/gateware/amp/soc.py index 859c7acc0..6924e2548 100644 --- a/artiq/gateware/amp/soc.py +++ b/artiq/gateware/amp/soc.py @@ -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() diff --git a/artiq/gateware/targets/kc705_drtio_satellite.py b/artiq/gateware/targets/kc705_drtio_satellite.py index 02ca30455..1bed87451 100755 --- a/artiq/gateware/targets/kc705_drtio_satellite.py +++ b/artiq/gateware/targets/kc705_drtio_satellite.py @@ -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() diff --git a/artiq/runtime/Makefile b/artiq/runtime/Makefile index 43ee5f437..f759d8d9b 100644 --- a/artiq/runtime/Makefile +++ b/artiq/runtime/Makefile @@ -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