Skip to content

Commit

Permalink
chore: move allocator into separate crate, add test stage
Browse files Browse the repository at this point in the history
  • Loading branch information
marekvospel committed Oct 25, 2024
1 parent c8d5cf9 commit c9b7315
Show file tree
Hide file tree
Showing 28 changed files with 144 additions and 55 deletions.
2 changes: 1 addition & 1 deletion .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[unstable]
build-std-features = ["compiler-builtins-mem"]
build-std = ["core", "alloc", "compiler_builtins"]
build-std = ["core", "alloc", "compiler_builtins"]
8 changes: 6 additions & 2 deletions .github/workflows/makefile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,9 @@ jobs:

- uses: actions/checkout@v3

- name: Install dependencies
run: make
- name: Build
run: make all

- name: Test
run: make test

7 changes: 6 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 5 additions & 15 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,5 @@
[package]
name = "kernel"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["staticlib"]

[dependencies]
bitflags = "2.4.0"
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
multiboot2 = { version = "0.19.0", default-features = false }
spin = "0.9.8"
uart_16550 = "0.3.0"
x86_64 = "0.14.11"
[workspace]
resolver = "2"
members = [
"crates/*"
]
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,7 @@ $(iso): $(kernel) $(grub_cfg)

run: $(iso)
@qemu-system-x86_64 -cdrom $(iso) -enable-kvm -serial stdio

test:
@cargo test -p allocator --target x86_64-unknown-linux-gnu -Zbuild-std

6 changes: 6 additions & 0 deletions crates/allocator/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "allocator"
version = "0.1.0"
edition = "2021"

[dependencies]
50 changes: 22 additions & 28 deletions src/memory/allocator/mod.rs → crates/allocator/src/allocator.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,23 @@
use core::{
alloc::{GlobalAlloc, Layout},
cmp::max,
mem::size_of,
};

use self::linked_list::LinkedAllocatorNode;
use crate::println;
use crate::LinkedAllocatorNode;

pub mod linked_list;

static mut NODES: Option<&mut LinkedAllocatorNode> = None;

#[global_allocator]
static ALLOCATOR: LinkedListAllocator = LinkedListAllocator {};
pub struct LinkedListAllocator {
pub nodes: Option<*mut LinkedAllocatorNode>,
}

pub struct LinkedListAllocator {}
unsafe impl Send for LinkedListAllocator {}

unsafe impl<'a> GlobalAlloc for LinkedListAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
if NODES.is_none() {
if self.nodes.is_none() {
panic!("LinkedListAllocator has not been initialized yet");
}

let start_node = NODES.as_deref_mut().unwrap();
let start_node = &mut *(self.nodes_mut().unwrap());

for node in start_node.as_iter() {
if !node.free {
Expand Down Expand Up @@ -65,7 +60,7 @@ unsafe impl<'a> GlobalAlloc for LinkedListAllocator {
let new_node = &mut *((aligned_addr) as *mut LinkedAllocatorNode);
new_node.size = layout.size();
new_node.free = false;
if (empty_node.is_some()) {
if empty_node.is_some() {
new_node.next = empty_node;
} else {
new_node.next = node.next;
Expand All @@ -74,7 +69,7 @@ unsafe impl<'a> GlobalAlloc for LinkedListAllocator {
// TODO: handle this, possibly a rush condition, fuck locks but im too lazy to write
// actual atomic allocator xd
if node.size != 0 {
println!("! Weird stuff happening not good, mod.rs:54");
// println!("! Weird stuff happening not good, mod.rs:54");
}

// Successful alloc
Expand All @@ -88,17 +83,17 @@ unsafe impl<'a> GlobalAlloc for LinkedListAllocator {
}

unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
if NODES.is_none() {
if self.nodes.is_none() {
panic!("LinkedListAllocator has not been initialized yet");
}

// Min alloc size is size of LinkedListAllocator, so when deallocating, the Node tag can be inserted
let start_node = NODES.as_deref_mut().unwrap();
let start_node = &mut *(self.nodes_mut().unwrap());

let mut last_node = &mut *(start_node as *mut LinkedAllocatorNode);
let mut iter = start_node.as_iter();
while let Some(node) = iter.next() {
if (ptr as usize == node.start_address()) {
if ptr as usize == node.start_address() {
let mut next_node = iter.next();
node.free = true;

Expand Down Expand Up @@ -127,20 +122,19 @@ unsafe impl<'a> GlobalAlloc for LinkedListAllocator {
}
}

pub unsafe fn print_nodes() {
if NODES.is_none() {
panic!("LinkedListAllocator has not been initialized yet");
impl LinkedListAllocator {
pub const fn new() -> LinkedListAllocator {
LinkedListAllocator { nodes: None }
}

let start_node = NODES.as_deref_mut().unwrap();
for node in start_node.as_iter() {
println!("0x{:x}: Node: {node:?}", node as *const _ as usize);
pub fn init(&mut self, node: &'static mut LinkedAllocatorNode) {
if self.nodes.is_some() {
panic!("LinkedListAllocator is already initialized");
}
self.nodes = Some(node as *mut _);
}
}

pub unsafe fn init(node: &'static mut LinkedAllocatorNode) {
if NODES.is_some() {
panic!("LinkedListAllocator is already initialized");
pub(crate) unsafe fn nodes_mut(&self) -> Option<*mut LinkedAllocatorNode> {
self.nodes.map(|n| n as *mut _)
}
NODES = Some(node);
}
7 changes: 7 additions & 0 deletions crates/allocator/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#![cfg_attr(not(test), no_std)]

pub use self::allocator::LinkedListAllocator;
pub use self::linked_list::{LinkedAllocatorIter, LinkedAllocatorNode};

pub(crate) mod allocator;
pub(crate) mod linked_list;
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use core::mem::size_of;

#[derive(Debug)]
pub struct LinkedAllocatorNode {
pub(crate) size: usize,
pub(crate) free: bool,
pub(crate) next: Option<*mut Self>,
pub size: usize,
pub free: bool,
pub next: Option<*mut Self>,
}

impl LinkedAllocatorNode {
Expand Down
62 changes: 62 additions & 0 deletions crates/allocator/tests/alloc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use allocator::*;
use core::alloc::{GlobalAlloc, Layout};

pub unsafe fn print_nodes(alloc: &LinkedListAllocator) {
if alloc.nodes.is_none() {
panic!("LinkedListAllocator has not been initialized yet");
}

let start_node = &mut *alloc.nodes.unwrap();
for node in start_node.as_iter() {
println!("0x{:x}: Node: {node:?}", node as *const _ as usize);
}
}

fn create_node(ptr: usize, size: usize) -> *mut LinkedAllocatorNode {
let node: &mut LinkedAllocatorNode = unsafe { std::mem::transmute(ptr) };
node.next = None;
node.size = size - size_of::<LinkedAllocatorNode>();
node.free = true;
node as *mut _
}

#[test]
fn should_initialize_allocator_once() {
const SIZE: usize = 256;
let mut buf = [0u8; SIZE];
let node = unsafe { &mut *create_node(&mut buf[0] as *const _ as usize, SIZE) };

let mut allocator = LinkedListAllocator::new();
allocator.init(node);

unsafe {
let ptr = allocator.alloc(Layout::from_size_align_unchecked(32, 1));
allocator.dealloc(ptr, Layout::from_size_align_unchecked(32, 1));
}
}

#[test]
fn should_merge_with_previous_node() {
const SIZE: usize = 256;
let mut buf = [0u8; SIZE];
let node = create_node(&mut buf[0] as *const _ as usize, SIZE);

let init_node = unsafe { &mut *node };
let node = unsafe { &mut *node };

let mut allocator = LinkedListAllocator::new();
allocator.init(init_node);

assert!(node.free);
assert_eq!(node.size, 256 - size_of::<LinkedAllocatorNode>());
assert_eq!(node.next, None);

unsafe {
let ptr = allocator.alloc(Layout::from_size_align_unchecked(32, 1));
allocator.dealloc(ptr, Layout::from_size_align_unchecked(32, 1));
}

assert!(node.free);
assert_eq!(node.size, 256 - size_of::<LinkedAllocatorNode>());
assert_eq!(node.next, None);
}
17 changes: 17 additions & 0 deletions crates/libkernel/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "kernel"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["staticlib"]

[dependencies]
bitflags = "2.4.0"
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
multiboot2 = { version = "0.19.0", default-features = false }
spin = "0.9.8"
uart_16550 = "0.3.0"
x86_64 = "0.14.11"

allocator = { path = "../allocator" }
File renamed without changes.
File renamed without changes.
1 change: 0 additions & 1 deletion src/lib.rs → crates/libkernel/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#![no_std]
#![no_main]
#![feature(const_mut_refs)]
#![feature(abi_x86_interrupt)]
#![feature(let_chains)]

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
9 changes: 5 additions & 4 deletions src/memory/mod.rs → crates/libkernel/src/memory/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use core::ops::RangeInclusive;

use crate::memory::allocator::linked_list::LinkedAllocatorNode;
use crate::memory::allocator::print_nodes;
use crate::memory::frames::bump_alloc::BumpAllocator;
use crate::memory::frames::{FrameIter, PhysicalFrame, PAGE_SIZE};
use crate::memory::paging::entry::EntryFlags;
Expand All @@ -17,8 +15,8 @@ use x86_64::registers::model_specific::{Efer, EferFlags};
use self::frames::FrameAlloc;
use self::paging::inactive::InactivePageTable;
use self::paging::temporary::TemporaryPage;
use allocator::{LinkedAllocatorNode, LinkedListAllocator};

pub mod allocator;
pub mod frames;
pub mod paging;

Expand All @@ -27,6 +25,9 @@ pub type VirtualAddress = u64;

pub const TABLE_SIZE: usize = 512;

#[global_allocator]
static mut ALLOCATOR: LinkedListAllocator = LinkedListAllocator::new();

pub(super) fn init(boot_info: &BootInformation) -> () {
enable_write_protect_bit();
enable_nxe_bit();
Expand Down Expand Up @@ -57,7 +58,7 @@ pub(super) fn init(boot_info: &BootInformation) -> () {

*node = LinkedAllocatorNode::new(PAGE_SIZE as usize);

unsafe { allocator::init(node) };
unsafe { ALLOCATOR.init(node) };

println!("[OK] Linked list allocator initialized!");
}
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit c9b7315

Please sign in to comment.