diff --git a/kernel/src/fdt.rs b/kernel/src/fdt.rs index 77c680c..256a310 100644 --- a/kernel/src/fdt.rs +++ b/kernel/src/fdt.rs @@ -2,13 +2,14 @@ use crate::{ println, - util::bits::{u32_from_bytes, Be}, + util::{bits::{u32_from_bytes, Be}, lazy::LazyConst}, }; use core::{ fmt::Debug, mem::{size_of, transmute}, ops::Range, slice }; const MAGIC: u32 = 0xd00dfeed; +pub static DT: LazyConst = LazyConst::new(); #[repr(u32)] #[derive(Clone, Copy, Debug)] diff --git a/kernel/src/heap/block.rs b/kernel/src/heap/block.rs deleted file mode 100644 index 57da91e..0000000 --- a/kernel/src/heap/block.rs +++ /dev/null @@ -1,126 +0,0 @@ -use core::{ - mem::{size_of, transmute}, - ops::{Deref, DerefMut}, - ptr::null_mut, -}; - -pub const FREE_SIZE: usize = size_of::() + size_of::(); -pub const PTR_SIZE: usize = size_of::(); -pub const USED_SIZE: usize = size_of::(); - -pub struct BlockInfo(usize); - -impl BlockInfo { - pub const fn new(prev_used: bool, size: usize) -> Self { - Self(prev_used as usize | size) - } - pub fn prev_used(&self) -> bool { - self.0 & 1 == 1 - } - pub fn size(&self) -> usize { - self.0 & !1 - } -} - -pub struct UsedPointer(*mut BlockInfo); - -impl Deref for UsedPointer { - type Target = BlockInfo; - fn deref(&self) -> &Self::Target { - unsafe { transmute(self.0) } - } -} - -impl DerefMut for UsedPointer { - fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { transmute(self.0) } - } -} - -#[derive(Clone, Copy)] -pub struct FreeBlockInfo { - pub size: usize, - pub prev: FreePointer, - pub next: FreePointer, -} - -impl FreeBlockInfo { - pub fn pointer(&mut self) -> FreePointer { - FreePointer(self as *mut FreeBlockInfo) - } -} - -#[derive(Clone, Copy, PartialEq, Eq)] -pub struct FreePointer(*mut FreeBlockInfo); - -impl FreePointer { - pub const fn null() -> Self { - Self(null_mut()) - } - pub unsafe fn new(addr: *mut u8, info: FreeBlockInfo) -> Self { - let ptr = Self(addr as *mut FreeBlockInfo); - let len = info.size; - *ptr.0 = info; - let end = addr.byte_add(len).byte_sub(PTR_SIZE) as *mut FreePointer; - *end = ptr; - Self(addr as *mut FreeBlockInfo) - } - pub fn to_used(mut self) -> *mut BlockInfo { - self.prev.next = self.next; - self.next.prev = self.prev; - self.0 as *mut BlockInfo - } - pub unsafe fn insert_new(&mut self, len: usize) -> *mut BlockInfo { - let old = self.0; - let new = old.byte_add(len); - *new = *old; - self.0 = new; - self.size = self.size - len; - - self.prev.next = *self; - self.next.prev = *self; - - old as *mut BlockInfo - } -} - -impl Deref for FreePointer { - type Target = FreeBlockInfo; - fn deref(&self) -> &Self::Target { - unsafe { transmute(self.0) } - } -} - -impl DerefMut for FreePointer { - fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { transmute(self.0) } - } -} - -pub struct FreeBlockIter { - end: FreePointer, - prev: FreePointer, -} - -impl Iterator for FreeBlockIter { - // you know, I could've returned &'static mut FreeBlockInfo... - // that feels too wrong though - type Item = FreePointer; - fn next(&mut self) -> Option { - self.prev = unsafe { (*self.prev).next }; - if self.prev == self.end { - None - } else { - Some(self.prev) - } - } -} - -impl FreeBlockIter { - pub fn from(head: &mut FreeBlockInfo) -> Self { - Self { - end: FreePointer(head), - prev: FreePointer(head), - } - } -} diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 5e2fe3f..fc5d006 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -7,67 +7,36 @@ #![test_runner(crate::test::test_runner)] #![reexport_test_harness_main = "test_main"] -use crate::allocator::ALLOCATOR; +use crate::mem::alloc::ALLOCATOR; use core::ops::Range; -use fdt::FDT; +use fdt::{DT, FDT}; extern crate alloc; -pub mod allocator; pub mod arch; pub mod dev; pub mod fdt; -pub mod heap; pub mod log; +pub mod mem; pub mod qemu; #[cfg(test)] mod test; pub mod util; pub fn start(heap_mem: Range<*mut u8>, fdt: FDT) -> ! { - #[cfg(test)] - test_main(); - #[cfg(not(test))] - main(heap_mem, fdt); - qemu::exit(0) -} - -pub fn main(heap_mem: Range<*mut u8>, fdt: FDT) { - println!("we out here vibin"); - println!("memory range: {:?}", fdt.mem_range()); - for node in &fdt {} + DT.init(fdt); unsafe { ALLOCATOR.init(heap_mem); } - ALLOCATOR.print(); - println!("----------- vec test:"); - let mut test = alloc::vec![1, 2, 3]; - test.push(3); - let test2 = alloc::vec![-1, -2, -3, -4]; - ALLOCATOR.print(); - println!("{:?}", test); - println!("{:?}", test2); - drop(test2); - drop(test); - ALLOCATOR.print(); - println!("----------- vec vec test:"); - let mut test = alloc::vec::Vec::new(); - for i in 0..4 { - let n = i * 4; - test.push(alloc::vec![n, n + 1, n + 2, n + 3]); - } - ALLOCATOR.print(); - println!("{:?}", test); - drop(test); - ALLOCATOR.print(); - println!("----------- dealloc test:"); - for i in 0..1000 { - let test2: alloc::vec::Vec = alloc::vec::Vec::with_capacity(10_000_0000); - } - ALLOCATOR.print(); - // for _ in 0..40000000 {} - // let x = unsafe { *(0x10000000000 as *mut u8) }; - // println!("we got {x}"); + #[cfg(test)] + test_main(); + #[cfg(not(test))] + main(); + qemu::exit(0) +} + +pub fn main() { + println!("we out here vibin"); } #[panic_handler] diff --git a/kernel/src/allocator.rs b/kernel/src/mem/alloc.rs similarity index 66% rename from kernel/src/allocator.rs rename to kernel/src/mem/alloc.rs index 118a4f7..ee334e0 100644 --- a/kernel/src/allocator.rs +++ b/kernel/src/mem/alloc.rs @@ -1,16 +1,16 @@ +use super::heap::Heap; +use crate::util::mutex::{Mutex, MutexGuard}; use core::{alloc::GlobalAlloc, ops::Range}; -use crate::{heap::Heap, util::mutex::Mutex}; - #[global_allocator] -pub static ALLOCATOR: LockedHeap = LockedHeap::empty(); +pub static ALLOCATOR: Allocator = Allocator::empty(); -pub struct LockedHeap(Mutex); +pub struct Allocator(Mutex); // should look into why I need this, didn't see it in linked list alloc crate -unsafe impl Sync for LockedHeap {} +unsafe impl Sync for Allocator {} -impl LockedHeap { +impl Allocator { pub const fn empty() -> Self { Self(Mutex::new(Heap::empty())) } @@ -20,9 +20,12 @@ impl LockedHeap { pub fn print(&self) { self.0.lock().print(); } + pub fn heap(&self) -> MutexGuard { + self.0.lock() + } } -unsafe impl GlobalAlloc for LockedHeap { +unsafe impl GlobalAlloc for Allocator { unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 { self.0.lock().alloc(layout) } diff --git a/kernel/src/heap/mod.rs b/kernel/src/mem/heap.rs similarity index 93% rename from kernel/src/heap/mod.rs rename to kernel/src/mem/heap.rs index 412241d..fdbefbf 100644 --- a/kernel/src/heap/mod.rs +++ b/kernel/src/mem/heap.rs @@ -15,7 +15,7 @@ use crate::println; const ALIGN: usize = 0b1000; const ALIGN_MASK: usize = !(ALIGN - 1); -struct BlockInfo(usize); +pub struct BlockInfo(usize); impl BlockInfo { pub const fn new(prev_used: bool, size: usize) -> Self { @@ -35,9 +35,9 @@ impl BlockInfo { } } -type BlockPointer = *mut BlockInfo; +pub type BlockPointer = *mut BlockInfo; -struct FreeBlockInfo { +pub struct FreeBlockInfo { info: BlockInfo, prev: FreePointer, next: FreePointer, @@ -52,7 +52,7 @@ impl FreeBlockInfo { } } -type FreePointer = *mut FreeBlockInfo; +pub type FreePointer = *mut FreeBlockInfo; const FREE_SIZE: usize = size_of::() + size_of::(); const PTR_SIZE: usize = size_of::(); @@ -146,7 +146,7 @@ impl Heap { return null_mut(); } - pub unsafe fn dealloc(&mut self, ptr: *mut u8, layout: core::alloc::Layout) { + pub unsafe fn dealloc(&mut self, ptr: *mut u8, _: core::alloc::Layout) { let used = ptr.byte_sub(USED_SIZE) as BlockPointer; let mut size = (*used).size(); let old_size = size; @@ -187,13 +187,13 @@ impl Heap { (*n_block).unset_prev_used(); } - fn iter_free(&mut self) -> FreeBlockIter { + pub fn iter_free(&mut self) -> FreeBlockIter { FreeBlockIter { prev: &mut self.head, end: &mut self.head, } } - fn iter_block(&mut self) -> BlockIter { + pub fn iter_block(&mut self) -> BlockIter { BlockIter { cur: self.start as BlockPointer, end: self.end, @@ -213,7 +213,11 @@ impl Heap { if n_block as *mut u8 == self.end { n_block = &mut self.head.info; } - let used = if (*n_block).prev_used() {"used"} else {"free"}; + let used = if (*n_block).prev_used() { + "used" + } else { + "free" + }; println!(" - {:?}: {}, size 0x{:x}", block, used, size); } println!(); @@ -228,7 +232,7 @@ unsafe fn create_free(addr: FreePointer, info: FreeBlockInfo) { *end = addr; } -struct FreeBlockIter { +pub struct FreeBlockIter { end: FreePointer, prev: FreePointer, } @@ -245,7 +249,7 @@ impl Iterator for FreeBlockIter { } } -struct BlockIter { +pub struct BlockIter { end: *mut u8, cur: BlockPointer, } diff --git a/kernel/src/mem/mod.rs b/kernel/src/mem/mod.rs new file mode 100644 index 0000000..8813f78 --- /dev/null +++ b/kernel/src/mem/mod.rs @@ -0,0 +1,2 @@ +pub mod heap; +pub mod alloc; diff --git a/kernel/src/test/mem.rs b/kernel/src/test/mem.rs new file mode 100644 index 0000000..9f1285b --- /dev/null +++ b/kernel/src/test/mem.rs @@ -0,0 +1,63 @@ +use crate::ALLOCATOR; + +#[test_case] +fn memory1() { + let mut test = alloc::vec![1, 2, 3]; + assert_eq!(test[0], 1); + assert_eq!(test[1], 2); + assert_eq!(test[2], 3); + test.push(3); + assert_eq!(test[0], 1); + assert_eq!(test[1], 2); + assert_eq!(test[2], 3); + assert_eq!(test[3], 3); + // check allocator + + let test2 = alloc::vec![-1, -2, -3, -4]; + assert_eq!(test2[0], -1); + assert_eq!(test2[1], -2); + assert_eq!(test2[2], -3); + assert_eq!(test2[3], -4); + + assert_eq!(test[0], 1); + assert_eq!(test[1], 2); + assert_eq!(test[2], 3); + assert_eq!(test[3], 3); + // check allocator + + drop(test2); + drop(test); + // check allocator +} + +#[test_case] +fn memory2() { + let mut test = alloc::vec::Vec::new(); + for i in 0..4 { + let n = i * 4; + test.push(alloc::vec![n, n + 1, n + 2, n + 3]); + } + for i in 0..4 { + let n = i * 4; + assert_eq!(test[i][0], n); + assert_eq!(test[i][1], n + 1); + assert_eq!(test[i][2], n + 2); + assert_eq!(test[i][3], n + 3); + } + // check allocator + + drop(test); + // check allocator +} + +#[test_case] +fn memory_reuse() { + for _ in 0..1000 { + let _: alloc::vec::Vec = alloc::vec::Vec::with_capacity(10_000_0000); + } + // check allocator +} + +pub fn check_alloc_empty() { + ALLOCATOR.heap(); +} diff --git a/kernel/src/test.rs b/kernel/src/test/mod.rs similarity index 89% rename from kernel/src/test.rs rename to kernel/src/test/mod.rs index 4d55cb2..d1bbcf8 100644 --- a/kernel/src/test.rs +++ b/kernel/src/test/mod.rs @@ -1,5 +1,7 @@ use crate::{print, println, qemu}; +mod mem; + // SURELY I will not have threading tests that cause problems // SURELY I don't need to pin the input to test_runner static mut TESTS: &[&dyn Testable] = &[]; @@ -52,18 +54,3 @@ pub fn test_panic(info: &core::panic::PanicInfo) -> ! { unsafe { FAILED += 1 }; run_tests(); } - -#[test_case] -fn test1() { - assert_eq!(1, 1); -} - -#[test_case] -fn test2() { - assert_eq!(1, 0); -} - -#[test_case] -fn test3() { - assert_eq!(5, 4); -} diff --git a/kernel/src/util/lazy.rs b/kernel/src/util/lazy.rs new file mode 100644 index 0000000..7564be1 --- /dev/null +++ b/kernel/src/util/lazy.rs @@ -0,0 +1,45 @@ +use core::{mem::zeroed, ops::Deref}; + +pub struct LazyConst { + #[cfg(not(debug_assertions))] + value: T, + #[cfg(debug_assertions)] + value: Option, +} + +impl Deref for LazyConst { + type Target = T; + + fn deref(&self) -> &Self::Target { + #[cfg(not(debug_assertions))] + { + &self.value + } + #[cfg(debug_assertions)] + { + self.value.as_ref().expect("Value was not assigned") + } + } +} + +impl LazyConst { + pub const fn new() -> Self { + unsafe { Self { value: zeroed() } } + } + + pub fn init(&self, value: T) { + #[cfg(not(debug_assertions))] + unsafe { + as_mut(self).value = value + } + #[cfg(debug_assertions)] + unsafe { + as_mut(self).value = Some(value) + } + } +} + +pub unsafe fn as_mut(x: &T) -> &mut T { + #[allow(invalid_reference_casting)] + &mut *((x as *const T) as *mut T) +} diff --git a/kernel/src/util/mod.rs b/kernel/src/util/mod.rs index c3594e1..4348fa2 100644 --- a/kernel/src/util/mod.rs +++ b/kernel/src/util/mod.rs @@ -1,3 +1,4 @@ pub mod bits; +pub mod lazy; pub mod mutex; pub mod spin;