Add an allocator

This commit is contained in:
Philipp Oppermann
2015-10-09 17:52:00 +02:00
parent 97a0da1bb9
commit d790fc20e5
9 changed files with 107 additions and 9 deletions

View File

@@ -16,3 +16,6 @@ branch = "no_std"
[dependencies.multiboot2]
path = "../multiboot2"
[dependencies.allocator]
path = "src/memory/alloc/allocator"

View File

@@ -14,10 +14,12 @@
#![feature(no_std, lang_items, asm)]
#![feature(core_str_ext, const_fn, range_inclusive)]
#![feature(unique, core_intrinsics)]
#![feature(unique, core_intrinsics, alloc)]
#![no_std]
extern crate rlibc;
extern crate alloc;
extern crate allocator;
extern crate multiboot2;
#[macro_use]
extern crate bitflags;
@@ -34,6 +36,7 @@ mod memory;
pub extern fn rust_main(multiboot_address: usize) {
// ATTENTION: we have a very small stack and no guard page
use vga_buffer::{Writer, Color};
use alloc::boxed::Box;
vga_buffer::clear_screen();
if let Some(multiboot) = unsafe{multiboot2::load(multiboot_address)} {
@@ -50,6 +53,8 @@ pub extern fn rust_main(multiboot_address: usize) {
println!("{} {}", "line", 1);
print!("line {}", 2);
Box::new(42);
loop{}
}

4
src/memory/alloc/allocator/Cargo.lock generated Normal file
View File

@@ -0,0 +1,4 @@
[root]
name = "allocator"
version = "0.1.0"

View File

@@ -0,0 +1,4 @@
[package]
name = "allocator"
version = "0.1.0"
authors = ["Philipp Oppermann <dev@phil-opp.com>"]

View File

@@ -0,0 +1,14 @@
#![feature(no_std, allocator)]
#![no_std]
#![allocator]
#![allow(improper_ctypes)]
extern {
fn __rust_allocate(size: usize, align: usize) -> *mut u8;
fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize);
fn __rust_reallocate(ptr: *mut u8, old_size: usize, size: usize,
align: usize) -> *mut u8;
fn __rust_reallocate_inplace(ptr: *mut u8, old_size: usize, size: usize,
align: usize) -> usize;
fn __rust_usable_size(size: usize, align: usize) -> usize;
}

63
src/memory/alloc/mod.rs Normal file
View File

@@ -0,0 +1,63 @@
use memory::paging::{self, Page, Mapper};
use memory::frame_allocator::{FrameAllocator, DynamicFrameStack};
use core::iter::range_inclusive;
use rlibc::memcpy;
use spin::Mutex;
static ALLOCATOR: Mutex<Option<Allocator<'static, DynamicFrameStack>>> = Mutex::new(None);
const HEAD_BOTTOM: usize = 0o_001_000_000_000_0000;
struct Allocator<'a, T> where T: 'a {
heap_top: usize,
last_mapped_page: Page,
mapper: Mapper<'a, T>,
}
impl<'a, T> Allocator<'a, T> where T: FrameAllocator {
pub fn allocate(&mut self, size: usize, align: usize) -> *mut u8 {
let start_address = align_up(self.heap_top, align);
let end_address = start_address + size;
let end_page = Page::containing_address(end_address - 1).number;
let last_mapped_page = self.last_mapped_page.number;
if end_page > last_mapped_page {
for page in range_inclusive(last_mapped_page + 1, end_page).map(|n| Page{number: n}) {
self.mapper.map(page, true, false)
}
self.last_mapped_page.number = end_page;
}
self.heap_top = end_address;
start_address as *mut u8
}
pub fn reallocate(&mut self, ptr: *mut u8, old_size: usize, size: usize,
align: usize) -> *mut u8
{
let new_ptr = self.allocate(size, align);
unsafe{ memcpy(new_ptr, ptr, old_size) };
new_ptr
}
pub fn deallocate(&mut self, ptr: *mut u8, old_size: usize, align: usize) {
//TODO
}
}
fn align_up(addr: usize, align: usize) -> usize {
if addr % align == 0 {
addr
} else {
addr + align - (addr % align)
}
}
#[no_mangle]
pub extern fn __rust_allocate(size: usize, align: usize) -> *mut u8 {
ALLOCATOR.lock().as_mut().expect("no allocator").allocate(size, align)
}
#[no_mangle]
pub extern fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) {
ALLOCATOR.lock().as_mut().expect("no allocator").deallocate(ptr, old_size, align)
}

View File

@@ -69,7 +69,10 @@ impl FrameAllocator for DynamicFrameStack {
} else {
// frame stack is full, use passed frame to expand it
let page_address = unsafe{ offset(*self.head, self.capacity as isize) } as usize;
lock.mapper(self).map_to(Page::containing_address(page_address), frame, true, false);
unsafe {
lock.mapper(self).map_to(Page::containing_address(page_address), frame,
true, false);
}
self.capacity += Self::capacity_per_frame();
}
}

View File

@@ -1,6 +1,7 @@
use multiboot2::Multiboot;
use self::paging::Page;
mod alloc;
mod paging;
mod frame_allocator;
mod tlb;
@@ -34,7 +35,9 @@ pub fn init(multiboot: &Multiboot) {
}
fn identity_map_kernel_sections(multiboot: &Multiboot, mut mapper: paging::Mapper<BumpPointer>) {
fn identity_map_kernel_sections<T>(multiboot: &Multiboot, mut mapper: paging::Mapper<T>)
where T: frame_allocator::FrameAllocator,
{
use core::iter::range_inclusive;
for section in multiboot.elf_tag().expect("no section tag").sections() {

View File

@@ -54,23 +54,22 @@ pub struct Mapper<'a, A> where A: 'a {
}
impl<'a, A> Mapper<'a, A> where A: FrameAllocator {
pub fn map_to(&mut self, page: Page, frame: Frame, writable: bool, executable: bool) {
map_to(self.lock, page, frame, writable, executable, self.allocator)
}
pub fn map(&mut self, page: Page, writable: bool, executable: bool) {
let frame = self.allocator.allocate_frame(&mut self.lock)
.expect("no more frames available");
self.map_to(page, frame, writable, executable)
unsafe{ self.map_to(page, frame, writable, executable) }
}
pub fn unmap(&mut self, page: Page) {
unmap(self.lock, page, self.allocator)
}
pub unsafe fn map_to(&mut self, page: Page, frame: Frame, writable: bool, executable: bool) {
map_to(self.lock, page, frame, writable, executable, self.allocator)
}
pub unsafe fn identity_map(&mut self, page: Page, writable: bool, executable: bool) {
let frame = Frame {number: page.number};
self.map_to(page, frame, writable, executable)
}
}