moving stuff and cleaning up

This commit is contained in:
Bryan McShea
2024-04-22 14:07:08 -04:00
parent d95a73203b
commit 5d475b500c
10 changed files with 152 additions and 203 deletions

View File

@@ -2,13 +2,14 @@
use crate::{ use crate::{
println, println,
util::bits::{u32_from_bytes, Be}, util::{bits::{u32_from_bytes, Be}, lazy::LazyConst},
}; };
use core::{ use core::{
fmt::Debug, mem::{size_of, transmute}, ops::Range, slice fmt::Debug, mem::{size_of, transmute}, ops::Range, slice
}; };
const MAGIC: u32 = 0xd00dfeed; const MAGIC: u32 = 0xd00dfeed;
pub static DT: LazyConst<FDT> = LazyConst::new();
#[repr(u32)] #[repr(u32)]
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]

View File

@@ -1,126 +0,0 @@
use core::{
mem::{size_of, transmute},
ops::{Deref, DerefMut},
ptr::null_mut,
};
pub const FREE_SIZE: usize = size_of::<FreeBlockInfo>() + size_of::<FreePointer>();
pub const PTR_SIZE: usize = size_of::<FreePointer>();
pub const USED_SIZE: usize = size_of::<BlockInfo>();
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::Item> {
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),
}
}
}

View File

@@ -7,67 +7,36 @@
#![test_runner(crate::test::test_runner)] #![test_runner(crate::test::test_runner)]
#![reexport_test_harness_main = "test_main"] #![reexport_test_harness_main = "test_main"]
use crate::allocator::ALLOCATOR; use crate::mem::alloc::ALLOCATOR;
use core::ops::Range; use core::ops::Range;
use fdt::FDT; use fdt::{DT, FDT};
extern crate alloc; extern crate alloc;
pub mod allocator;
pub mod arch; pub mod arch;
pub mod dev; pub mod dev;
pub mod fdt; pub mod fdt;
pub mod heap;
pub mod log; pub mod log;
pub mod mem;
pub mod qemu; pub mod qemu;
#[cfg(test)] #[cfg(test)]
mod test; mod test;
pub mod util; pub mod util;
pub fn start(heap_mem: Range<*mut u8>, fdt: FDT) -> ! { pub fn start(heap_mem: Range<*mut u8>, fdt: FDT) -> ! {
#[cfg(test)] DT.init(fdt);
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 {}
unsafe { unsafe {
ALLOCATOR.init(heap_mem); ALLOCATOR.init(heap_mem);
} }
ALLOCATOR.print(); #[cfg(test)]
println!("----------- vec test:"); test_main();
let mut test = alloc::vec![1, 2, 3]; #[cfg(not(test))]
test.push(3); main();
let test2 = alloc::vec![-1, -2, -3, -4]; qemu::exit(0)
ALLOCATOR.print(); }
println!("{:?}", test);
println!("{:?}", test2); pub fn main() {
drop(test2); println!("we out here vibin");
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<i32> = 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}");
} }
#[panic_handler] #[panic_handler]

View File

@@ -1,16 +1,16 @@
use super::heap::Heap;
use crate::util::mutex::{Mutex, MutexGuard};
use core::{alloc::GlobalAlloc, ops::Range}; use core::{alloc::GlobalAlloc, ops::Range};
use crate::{heap::Heap, util::mutex::Mutex};
#[global_allocator] #[global_allocator]
pub static ALLOCATOR: LockedHeap = LockedHeap::empty(); pub static ALLOCATOR: Allocator = Allocator::empty();
pub struct LockedHeap(Mutex<Heap>); pub struct Allocator(Mutex<Heap>);
// should look into why I need this, didn't see it in linked list alloc crate // 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 { pub const fn empty() -> Self {
Self(Mutex::new(Heap::empty())) Self(Mutex::new(Heap::empty()))
} }
@@ -20,9 +20,12 @@ impl LockedHeap {
pub fn print(&self) { pub fn print(&self) {
self.0.lock().print(); self.0.lock().print();
} }
pub fn heap(&self) -> MutexGuard<Heap> {
self.0.lock()
}
} }
unsafe impl GlobalAlloc for LockedHeap { unsafe impl GlobalAlloc for Allocator {
unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 { unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 {
self.0.lock().alloc(layout) self.0.lock().alloc(layout)
} }

View File

@@ -15,7 +15,7 @@ use crate::println;
const ALIGN: usize = 0b1000; const ALIGN: usize = 0b1000;
const ALIGN_MASK: usize = !(ALIGN - 1); const ALIGN_MASK: usize = !(ALIGN - 1);
struct BlockInfo(usize); pub struct BlockInfo(usize);
impl BlockInfo { impl BlockInfo {
pub const fn new(prev_used: bool, size: usize) -> Self { 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, info: BlockInfo,
prev: FreePointer, prev: FreePointer,
next: FreePointer, next: FreePointer,
@@ -52,7 +52,7 @@ impl FreeBlockInfo {
} }
} }
type FreePointer = *mut FreeBlockInfo; pub type FreePointer = *mut FreeBlockInfo;
const FREE_SIZE: usize = size_of::<FreeBlockInfo>() + size_of::<FreePointer>(); const FREE_SIZE: usize = size_of::<FreeBlockInfo>() + size_of::<FreePointer>();
const PTR_SIZE: usize = size_of::<FreePointer>(); const PTR_SIZE: usize = size_of::<FreePointer>();
@@ -146,7 +146,7 @@ impl Heap {
return null_mut(); 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 used = ptr.byte_sub(USED_SIZE) as BlockPointer;
let mut size = (*used).size(); let mut size = (*used).size();
let old_size = size; let old_size = size;
@@ -187,13 +187,13 @@ impl Heap {
(*n_block).unset_prev_used(); (*n_block).unset_prev_used();
} }
fn iter_free(&mut self) -> FreeBlockIter { pub fn iter_free(&mut self) -> FreeBlockIter {
FreeBlockIter { FreeBlockIter {
prev: &mut self.head, prev: &mut self.head,
end: &mut self.head, end: &mut self.head,
} }
} }
fn iter_block(&mut self) -> BlockIter { pub fn iter_block(&mut self) -> BlockIter {
BlockIter { BlockIter {
cur: self.start as BlockPointer, cur: self.start as BlockPointer,
end: self.end, end: self.end,
@@ -213,7 +213,11 @@ impl Heap {
if n_block as *mut u8 == self.end { if n_block as *mut u8 == self.end {
n_block = &mut self.head.info; 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!(" - {:?}: {}, size 0x{:x}", block, used, size);
} }
println!(); println!();
@@ -228,7 +232,7 @@ unsafe fn create_free(addr: FreePointer, info: FreeBlockInfo) {
*end = addr; *end = addr;
} }
struct FreeBlockIter { pub struct FreeBlockIter {
end: FreePointer, end: FreePointer,
prev: FreePointer, prev: FreePointer,
} }
@@ -245,7 +249,7 @@ impl Iterator for FreeBlockIter {
} }
} }
struct BlockIter { pub struct BlockIter {
end: *mut u8, end: *mut u8,
cur: BlockPointer, cur: BlockPointer,
} }

2
kernel/src/mem/mod.rs Normal file
View File

@@ -0,0 +1,2 @@
pub mod heap;
pub mod alloc;

63
kernel/src/test/mem.rs Normal file
View File

@@ -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<i32> = alloc::vec::Vec::with_capacity(10_000_0000);
}
// check allocator
}
pub fn check_alloc_empty() {
ALLOCATOR.heap();
}

View File

@@ -1,5 +1,7 @@
use crate::{print, println, qemu}; use crate::{print, println, qemu};
mod mem;
// SURELY I will not have threading tests that cause problems // SURELY I will not have threading tests that cause problems
// SURELY I don't need to pin the input to test_runner // SURELY I don't need to pin the input to test_runner
static mut TESTS: &[&dyn Testable] = &[]; static mut TESTS: &[&dyn Testable] = &[];
@@ -52,18 +54,3 @@ pub fn test_panic(info: &core::panic::PanicInfo) -> ! {
unsafe { FAILED += 1 }; unsafe { FAILED += 1 };
run_tests(); 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);
}

45
kernel/src/util/lazy.rs Normal file
View File

@@ -0,0 +1,45 @@
use core::{mem::zeroed, ops::Deref};
pub struct LazyConst<T> {
#[cfg(not(debug_assertions))]
value: T,
#[cfg(debug_assertions)]
value: Option<T>,
}
impl<T> Deref for LazyConst<T> {
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<T> LazyConst<T> {
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<T>(x: &T) -> &mut T {
#[allow(invalid_reference_casting)]
&mut *((x as *const T) as *mut T)
}

View File

@@ -1,3 +1,4 @@
pub mod bits; pub mod bits;
pub mod lazy;
pub mod mutex; pub mod mutex;
pub mod spin; pub mod spin;