From 0e68eaa879aa2cb8add098f4fd5bc3750067f5bd Mon Sep 17 00:00:00 2001 From: whitequark Date: Fri, 21 Apr 2017 14:48:10 +0000 Subject: [PATCH] runtime: print a heap dump on out-of-memory condition. --- artiq/firmware/liballoc_artiq/lib.rs | 36 +++++++++++++++++++++++++++- artiq/firmware/runtime/lib.rs | 9 ++++--- artiq/firmware/runtime/session.rs | 2 +- 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/artiq/firmware/liballoc_artiq/lib.rs b/artiq/firmware/liballoc_artiq/lib.rs index 37b39c561..78cc8a56d 100644 --- a/artiq/firmware/liballoc_artiq/lib.rs +++ b/artiq/firmware/liballoc_artiq/lib.rs @@ -2,7 +2,7 @@ #![no_std] #![allocator] -use core::{mem, ptr, cmp}; +use core::{mem, ptr, cmp, fmt}; // The minimum alignment guaranteed by the architecture. const MIN_ALIGN: usize = 4; @@ -122,3 +122,37 @@ pub extern fn __rust_reallocate_inplace(_ptr: *mut u8, old_size: usize, _size: u pub extern fn __rust_usable_size(size: usize, _align: usize) -> usize { size } + +pub fn debug_dump(f: &mut fmt::Write) -> fmt::Result { + unsafe { + let mut total_busy = 0; + let mut total_idle = 0; + let mut total_meta = 0; + + write!(f, "Heap view:\n")?; + + let mut curr = ROOT; + while !curr.is_null() { + total_meta += mem::size_of::
(); + + let desc = match (*curr).magic { + MAGIC_FREE => { total_idle += (*curr).size; "IDLE" }, + MAGIC_BUSY => { total_busy += (*curr).size; "BUSY" }, + _ => "!!!!" + }; + + write!(f, "{} {:p} + {:#x} + {:#x} -> {:p}\n", + desc, curr, mem::size_of::
(), (*curr).size, (*curr).next)?; + match (*curr).magic { + MAGIC_FREE | MAGIC_BUSY => (), + _ => break + } + + curr = (*curr).next; + } + + write!(f, " === busy: {:#x} idle: {:#x} meta: {:#x} total: {:#x}\n", + total_busy, total_idle, total_meta, + total_busy + total_idle + total_meta) + } +} diff --git a/artiq/firmware/runtime/lib.rs b/artiq/firmware/runtime/lib.rs index c1a745e03..f5a7a16b5 100644 --- a/artiq/firmware/runtime/lib.rs +++ b/artiq/firmware/runtime/lib.rs @@ -1,5 +1,6 @@ #![no_std] -#![feature(compiler_builtins_lib, alloc, oom, repr_simd, lang_items, const_fn)] +#![feature(compiler_builtins_lib, alloc, oom, repr_simd, lang_items, const_fn, + closure_to_fn_coercion)] extern crate compiler_builtins; extern crate alloc; @@ -169,8 +170,10 @@ pub extern fn main() -> i32 { alloc_artiq::seed(&mut _fheap as *mut u8, &_eheap as *const u8 as usize - &_fheap as *const u8 as usize); - fn oom() -> ! { panic!("out of memory") } - alloc::oom::set_oom_handler(oom); + alloc::oom::set_oom_handler(|| { + alloc_artiq::debug_dump(&mut board::uart_console::Console).unwrap(); + panic!("out of memory"); + }); static mut LOG_BUFFER: [u8; 65536] = [0; 65536]; logger_artiq::BufferLogger::new(&mut LOG_BUFFER[..]).register(startup); diff --git a/artiq/firmware/runtime/session.rs b/artiq/firmware/runtime/session.rs index d38ae8570..6cca523b5 100644 --- a/artiq/firmware/runtime/session.rs +++ b/artiq/firmware/runtime/session.rs @@ -158,7 +158,7 @@ fn kern_recv_dotrace(reply: &kern::Message) { &kern::LogSlice(_) => debug!("comm<-kern LogSlice(...)"), &kern::DmaRecordAppend(data) => { if data.len() > 100 { - debug!("comm<-kern DmaRecordAppend(...)") + debug!("comm<-kern DmaRecordAppend([_; {:#x}])", data.len()) } else { debug!("comm<-kern {:?}", reply) }