mirror of
https://github.com/phil-opp/blog_os.git
synced 2025-12-16 14:27:49 +00:00
Add an allocator
This commit is contained in:
@@ -16,3 +16,6 @@ branch = "no_std"
|
||||
|
||||
[dependencies.multiboot2]
|
||||
path = "../multiboot2"
|
||||
|
||||
[dependencies.allocator]
|
||||
path = "src/memory/alloc/allocator"
|
||||
|
||||
@@ -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
4
src/memory/alloc/allocator/Cargo.lock
generated
Normal file
@@ -0,0 +1,4 @@
|
||||
[root]
|
||||
name = "allocator"
|
||||
version = "0.1.0"
|
||||
|
||||
4
src/memory/alloc/allocator/Cargo.toml
Normal file
4
src/memory/alloc/allocator/Cargo.toml
Normal file
@@ -0,0 +1,4 @@
|
||||
[package]
|
||||
name = "allocator"
|
||||
version = "0.1.0"
|
||||
authors = ["Philipp Oppermann <dev@phil-opp.com>"]
|
||||
14
src/memory/alloc/allocator/src/lib.rs
Normal file
14
src/memory/alloc/allocator/src/lib.rs
Normal 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
63
src/memory/alloc/mod.rs
Normal 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)
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user