From 7cdf6c09182eead1edafcc82e1c4baca65bc662d Mon Sep 17 00:00:00 2001 From: Astro Date: Mon, 28 Oct 2019 00:43:57 +0100 Subject: [PATCH] start implementation of a StaticAllocator --- src/main.rs | 1 + src/ram.rs | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 src/ram.rs diff --git a/src/main.rs b/src/main.rs index 27d351f..c98314e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,6 +20,7 @@ mod regs; mod cortex_a9; mod stdio; mod zynq; +mod ram; use crate::regs::{RegisterR, RegisterW}; use crate::cortex_a9::{asm, regs::*, mmu}; diff --git a/src/ram.rs b/src/ram.rs new file mode 100644 index 0000000..767392b --- /dev/null +++ b/src/ram.rs @@ -0,0 +1,75 @@ +use core::mem::{align_of, size_of}; + +pub trait RAM { + #[inline(always)] + fn addr(&self) -> usize; + #[inline(always)] + fn size(&self) -> usize; + + #[inline(always)] + fn into_memory_region(&self) -> MemoryRegion { + MemoryRegion { + addr: self.addr(), + size: self.size(), + } + } + +} + +pub struct MemoryRegion { + addr: usize, + size: usize, +} + +impl MemoryRegion { + #[inline(always)] + fn split(&mut self, offset: usize) -> MemoryRegion { + if offset > self.size { + panic!("StaticAllocator: unable to split {}/{} bytes", offset, self.size); + } + + let result = MemoryRegion { + addr: self.addr, + size: offset, + }; + self.addr += offset; + self.size -= offset; + result + } + + unsafe fn clear(self) -> *mut T { + let result = self.addr as *mut T; + for b in core::slice::from_raw_parts_mut::(result as *mut u8, self.size) { + *b = 0; + } + result + } + + pub fn align(&mut self, alignment: usize) { + let mask = alignment - 1; + let addr = (self.addr | mask) + 1; + self.size -= addr - self.addr; + self.addr = addr; + } +} + +pub struct StaticAllocator { + free: MemoryRegion, +} + +impl StaticAllocator { + pub fn new(r: R) -> Self { + StaticAllocator { + free: r.into_memory_region(), + } + } + + pub fn alloc<'a: 'b, 'b, T: Sized>(&'a mut self) -> &'b mut T { + self.free.align(align_of::()); + + let size = size_of::(); + let region = self.free.split(size); + + unsafe { &mut *region.clear() } + } +}