moving stuff and cleaning up
This commit is contained in:
@@ -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<FDT> = LazyConst::new();
|
||||
|
||||
#[repr(u32)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<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}");
|
||||
#[cfg(test)]
|
||||
test_main();
|
||||
#[cfg(not(test))]
|
||||
main();
|
||||
qemu::exit(0)
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
println!("we out here vibin");
|
||||
}
|
||||
|
||||
#[panic_handler]
|
||||
|
||||
@@ -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<Heap>);
|
||||
pub struct Allocator(Mutex<Heap>);
|
||||
|
||||
// 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<Heap> {
|
||||
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)
|
||||
}
|
||||
@@ -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::<FreeBlockInfo>() + size_of::<FreePointer>();
|
||||
const PTR_SIZE: usize = size_of::<FreePointer>();
|
||||
@@ -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,
|
||||
}
|
||||
2
kernel/src/mem/mod.rs
Normal file
2
kernel/src/mem/mod.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
pub mod heap;
|
||||
pub mod alloc;
|
||||
63
kernel/src/test/mem.rs
Normal file
63
kernel/src/test/mem.rs
Normal 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();
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
45
kernel/src/util/lazy.rs
Normal file
45
kernel/src/util/lazy.rs
Normal 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)
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod bits;
|
||||
pub mod lazy;
|
||||
pub mod mutex;
|
||||
pub mod spin;
|
||||
|
||||
Reference in New Issue
Block a user