Skip to content

Commit

Permalink
Heap. Allocation with type arguments; overflow
Browse files Browse the repository at this point in the history
Created kernel::heap. Allocation functions take one type parameter.
Used `mul_with_overflow` to safely allocate arrays (compare calloc.)
  • Loading branch information
pczarn committed Mar 25, 2014
1 parent 382274f commit 7ab5c87
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 71 deletions.
70 changes: 70 additions & 0 deletions kernel/heap.rs
Original file line number Diff line number Diff line change
@@ -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<T>(ptr: *mut T) {
heap.free(ptr as *mut u8);
}

#[inline]
pub unsafe fn alloc<T = u8>(count: uint) -> *mut T {
match mul_with_overflow(count, size_of::<T>()) {
(_, true) => out_of_memory(),
(size, _) => malloc_raw(size) as *mut T
}
}

#[inline]
pub unsafe fn zero_alloc<T = u8>(count: uint) -> *mut T {
match mul_with_overflow(count, size_of::<T>()) {
(_, 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<T>(ptr: *mut T, count: uint) -> *mut T {
match mul_with_overflow(count, size_of::<T>()) {
(_, 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
}
}
}
9 changes: 7 additions & 2 deletions kernel/memory/allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 }
}

Expand Down
4 changes: 2 additions & 2 deletions kernel/memory/physical.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use core::fail::abort;

use kernel;
use kernel::heap;
use kernel::memory;
use kernel::memory::Allocator;

Expand All @@ -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::<u32>(1024) as memory::BitvStorage;
}
}

Expand Down
64 changes: 2 additions & 62 deletions kernel/mod.rs
Original file line number Diff line number Diff line change
@@ -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<interrupt::Table> = 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 {
Expand All @@ -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
}
}
8 changes: 4 additions & 4 deletions kernel/sgash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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; }
Expand Down
2 changes: 1 addition & 1 deletion lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down

0 comments on commit 7ab5c87

Please sign in to comment.