From 7ab5c87b33f1d661a2045de9bfade2bfb0219885 Mon Sep 17 00:00:00 2001 From: Piotr Czarnecki Date: Sat, 22 Feb 2014 18:56:00 +0100 Subject: [PATCH] Heap. Allocation with type arguments; overflow Created kernel::heap. Allocation functions take one type parameter. Used `mul_with_overflow` to safely allocate arrays (compare calloc.) --- kernel/heap.rs | 70 ++++++++++++++++++++++++++++++++++++++ kernel/memory/allocator.rs | 9 +++-- kernel/memory/physical.rs | 4 +-- kernel/mod.rs | 64 ++-------------------------------- kernel/sgash.rs | 8 ++--- lib.rs | 2 +- 6 files changed, 86 insertions(+), 71 deletions(-) create mode 100644 kernel/heap.rs diff --git a/kernel/heap.rs b/kernel/heap.rs new file mode 100644 index 0000000000..d483822191 --- /dev/null +++ b/kernel/heap.rs @@ -0,0 +1,70 @@ +use core::fail::out_of_memory; +use core::mem::size_of; +use core::uint::mul_with_overflow; + +use kernel::memory; +use kernel::memory::Allocator; + +pub static mut heap: memory::Alloc = memory::Alloc { + base: 0x110_000 as *mut u8, + el_size: 0, + parent: memory::BuddyAlloc { + order: 17, + tree: memory::Bitv { storage: 0x100_000 as memory::BitvStorage } + } +}; + +pub fn init() { + unsafe { + heap.parent.tree.init(); + } +} + +#[lang = "exchange_malloc"] +#[inline] +pub unsafe fn malloc_raw(size: uint) -> *mut u8 { + match heap.alloc(size) { + (_, 0) => out_of_memory(), + (ptr, _) => ptr + } +} + +#[lang = "exchange_free"] +#[inline] +pub unsafe fn free(ptr: *mut T) { + heap.free(ptr as *mut u8); +} + +#[inline] +pub unsafe fn alloc(count: uint) -> *mut T { + match mul_with_overflow(count, size_of::()) { + (_, true) => out_of_memory(), + (size, _) => malloc_raw(size) as *mut T + } +} + +#[inline] +pub unsafe fn zero_alloc(count: uint) -> *mut T { + match mul_with_overflow(count, size_of::()) { + (_, true) => out_of_memory(), + (size, _) => match heap.zero_alloc(size) { + (_, 0) => out_of_memory(), + (ptr, _) => ptr as *mut T + } + } +} + +#[inline] +pub unsafe fn realloc_raw(ptr: *mut T, count: uint) -> *mut T { + match mul_with_overflow(count, size_of::()) { + (_, true) => out_of_memory(), + (0, _) => { + free(ptr); + 0 as *mut T + } + (size, _) => match heap.realloc(ptr as *mut u8, size) { + (_, 0) => out_of_memory(), + (ptr, _) => ptr as *mut T + } + } +} diff --git a/kernel/memory/allocator.rs b/kernel/memory/allocator.rs index a3eb630b47..4c6405086c 100644 --- a/kernel/memory/allocator.rs +++ b/kernel/memory/allocator.rs @@ -72,6 +72,12 @@ impl BitvTrait for Bitv { } } +impl Bitv { + pub fn init(&self) { + unsafe { set_memory(self.to_bytes(), 0, self.size()); } + } +} + pub struct BuddyAlloc { order: uint, tree: Bitv @@ -85,8 +91,7 @@ pub struct Alloc { impl BuddyAlloc { pub fn new(order: uint, storage: Bitv) -> BuddyAlloc { - unsafe { set_memory(storage.to_bytes(), 0, storage.size()); } - + storage.init(); BuddyAlloc { order: order, tree: storage } } diff --git a/kernel/memory/physical.rs b/kernel/memory/physical.rs index 95e0875361..83cd82b3ee 100644 --- a/kernel/memory/physical.rs +++ b/kernel/memory/physical.rs @@ -1,6 +1,6 @@ use core::fail::abort; -use kernel; +use kernel::heap; use kernel::memory; use kernel::memory::Allocator; @@ -15,7 +15,7 @@ pub static mut frames: memory::Alloc = memory::Alloc { pub fn init() { unsafe { - frames.parent.tree.storage = kernel::zero_alloc(0x1000) as memory::BitvStorage; + frames.parent.tree.storage = heap::zero_alloc::(1024) as memory::BitvStorage; } } diff --git a/kernel/mod.rs b/kernel/mod.rs index 11f9c11a54..6211d047a4 100644 --- a/kernel/mod.rs +++ b/kernel/mod.rs @@ -1,30 +1,19 @@ use core::option::{Option, Some, None}; -use core::fail::out_of_memory; use platform::{cpu, io, drivers}; use cpu::interrupt; -use self::memory::Allocator; - pub mod util; pub mod memory; pub mod sgash; - -pub static mut heap: memory::Alloc = memory::Alloc { - base: 0x110_000 as *mut u8, - el_size: 0, - parent: memory::BuddyAlloc { - order: 17, - tree: memory::Bitv { storage: 0x100_000 as memory::BitvStorage } - } -}; +pub mod heap; pub static mut int_table: Option = None; #[lang="start"] #[no_mangle] pub fn main() { - memory::BuddyAlloc::new(17, memory::Bitv { storage: 0x100_000 as memory::BitvStorage }); + heap::init(); memory::physical::init(); let table = interrupt::Table::new(); unsafe { @@ -39,52 +28,3 @@ pub fn main() { io::init(640, 480); } } - -#[lang = "exchange_malloc"] -#[inline] -pub unsafe fn malloc_raw(size: uint) -> *mut u8 { - if size == 0 { - 0 as *mut u8 - } - else { - let (ptr, sz) = heap.alloc(size); - if sz == 0 { - out_of_memory(); - } - ptr - } -} - -#[lang = "exchange_free"] -#[inline] -pub unsafe fn free(ptr: *mut u8) { - heap.free(ptr); -} - -#[inline] -pub unsafe fn zero_alloc(size: uint) -> *mut u8 { - if size == 0 { - 0 as *mut u8 - } - else { - let (ptr, sz) = heap.zero_alloc(size); - if sz == 0 { - out_of_memory(); - } - ptr - } -} - -#[inline] -pub unsafe fn realloc_raw(ptr: *mut u8, size: uint) -> *mut u8 { - if size == 0 { - free(ptr); - 0 as *mut u8 - } else { - let (ptr, sz) = heap.realloc(ptr, size); - if sz == 0 { - out_of_memory() - } - ptr - } -} diff --git a/kernel/sgash.rs b/kernel/sgash.rs index d39c085437..1651f3ce4e 100644 --- a/kernel/sgash.rs +++ b/kernel/sgash.rs @@ -218,11 +218,11 @@ struct cstr { impl cstr { pub unsafe fn new(size: uint) -> cstr { // Sometimes this doesn't allocate enough memory and gets stuck... - let (x, y) = heap.alloc(size); + let p = heap::alloc(size); let this = cstr { - p: x, + p: p, p_cstr_i: 0, - max: y + max: size }; *(((this.p as uint)+this.p_cstr_i) as *mut char) = '\0'; this @@ -243,7 +243,7 @@ impl cstr { // HELP THIS DOESN'T WORK THERE IS NO GARBAGE COLLECTION!!! // -- TODO: exchange_malloc, exchange_free #[allow(dead_code)] - unsafe fn destroy(&self) { heap.free(self.p); } + unsafe fn destroy(&self) { heap::free(self.p); } unsafe fn add_char(&mut self, x: u8) -> bool{ if (self.p_cstr_i == self.max) { return false; } diff --git a/lib.rs b/lib.rs index 35dba97b07..5c14532d74 100644 --- a/lib.rs +++ b/lib.rs @@ -6,7 +6,7 @@ #[crate_type = "lib"]; // Forked from pczarn/rustboot #[no_std]; -#[feature(asm, globs, macro_rules)]; +#[feature(asm, globs, macro_rules, default_type_params)]; extern mod core;