diff --git a/Cargo.lock b/Cargo.lock index d9aafe9..e669fa5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,7 +11,7 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "atomalloc" version = "0.1.0" -source = "git+https://forge.gaycatgirl.sex/hypericum/atomalloc.git?rev=6f6687429e5e89c16e813dbeab4af30e05e2e8a2#6f6687429e5e89c16e813dbeab4af30e05e2e8a2" +source = "git+https://forge.gaycatgirl.sex/hypericum/atomalloc.git?rev=c87a434ce7d3301782f1e141e39eedac467f2709#c87a434ce7d3301782f1e141e39eedac467f2709" [[package]] name = "autocfg" diff --git a/Cargo.toml b/Cargo.toml index b9fa3dd..288408e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ license = "GPL-2.0-only" [dependencies] libgoatweed = { git = "https://forge.gaycatgirl.sex/hypericum/libgoatweed.git", rev = "31ac8671a3cfb338ae66957c963a9ced72fa2251" , default-features = false } -atomalloc = { git = "https://forge.gaycatgirl.sex/hypericum/atomalloc.git", rev = "6f6687429e5e89c16e813dbeab4af30e05e2e8a2", default-features = false, features = ["no_alloc"] } +atomalloc = { git = "https://forge.gaycatgirl.sex/hypericum/atomalloc.git", rev = "c87a434ce7d3301782f1e141e39eedac467f2709", default-features = false, features = ["no_alloc"] } # bootloader info structs limine = "0.5.0" diff --git a/src/arch/amd64/memory/pmm.rs b/src/arch/amd64/memory/pmm.rs index 3e9960d..998e8d2 100644 --- a/src/arch/amd64/memory/pmm.rs +++ b/src/arch/amd64/memory/pmm.rs @@ -1,27 +1,19 @@ use crate::print; -use crate::println; -use core::ptr::slice_from_raw_parts_mut; use core::sync::atomic::{AtomicUsize, Ordering}; +use atomalloc::noalloc::AtomAlloc; use limine::memory_map::{Entry, EntryType}; use spin::{Mutex, Once}; -use x86_64::structures::paging::{FrameAllocator, FrameDeallocator, PhysFrame, Size4KiB}; use x86_64::PhysAddr; +use x86_64::structures::paging::{FrameAllocator, FrameDeallocator, PhysFrame, Size4KiB}; +use crate::println; -// TODO: remake this entire thing - -// TODO: rethink this static FRAME_ALLOCATOR: Once> = Once::new(); -// TODO: rethink this -static mut FRAME_BITMAP: [u8; BITMAP_SIZE] = [0; BITMAP_SIZE]; +pub const MAX_ATOMS: usize = 1024; +static ATOMS: Mutex> = Mutex::new(AtomAlloc::new()); -// TODO: rethink this -const BITMAP_SIZE: usize = 16384 * 4096 * 4; - -pub const MAX_REGIONS: usize = 64; static TOTAL_MEMORY: AtomicUsize = AtomicUsize::new(0); -static ALLOCATED_FRAMES: AtomicUsize = AtomicUsize::new(0); #[repr(C)] #[derive(PartialEq, Eq, Clone, Copy)] @@ -36,195 +28,74 @@ pub struct Region { pub entry_type: EntryType, } -pub struct PFrameAllocator { - usable_regions: [Option; MAX_REGIONS], - bitmap_base: u64, - last_allocated: usize, -} +pub struct PFrameAllocator {} impl PFrameAllocator { pub unsafe fn init(memory_map: &[&Entry]) { - let mut i = 0; - let mut usable_regions = [None; MAX_REGIONS]; let mut total_memory: usize = 0; - let mut min_addr = u64::MAX; + + // lock atoms so we can add to it + let mut atoms = ATOMS.lock(); for e in memory_map { - let region = Region { - base: e.base, - end: e.base + e.length, - length: e.length, - entry_type: e.entry_type, - }; - if e.entry_type == EntryType::USABLE { - usable_regions[i] = Some(region); total_memory += e.length as usize; - min_addr = min_addr.min(e.base); - i += 1; + + atoms.add_memory(e.base as usize, e.length.div_ceil(4096) as usize); } } - let bitmap_base = (min_addr / 4096) * 4096; + // we dont need it anymore, drop + drop(atoms); TOTAL_MEMORY.store(total_memory, Ordering::Relaxed); - #[allow(static_mut_refs)] - FRAME_BITMAP.fill(0); - FRAME_ALLOCATOR.call_once(|| { - Mutex::new(PFrameAllocator { - usable_regions, - bitmap_base, - last_allocated: 0, - }) + Mutex::new(PFrameAllocator {}) }); } - /// Convert physical address to bitmap index - fn addr_to_bitmap_index(&self, addr: u64) -> Option { - if addr < self.bitmap_base { - return None; - } + pub fn allocate_single_frame(&mut self) -> Option> { + let mut atoms = ATOMS.lock(); - let frame_number = (addr - self.bitmap_base) / 4096; - let bit_index = frame_number as usize; - - if bit_index >= BITMAP_SIZE * 8 { - None + let frame = if let Some(frame) = atoms.allocate(1) { + frame } else { - Some(bit_index) - } - } + // out of memory? lets defrag first + atoms.defragment(); - /// Convert bitmap index to physical address - fn bitmap_index_to_addr(&self, index: usize) -> u64 { - self.bitmap_base + (index as u64 * 4096) - } + if let Some(frame) = atoms.allocate(1) { + frame + } else { + println!("Out of memory!"); - /// Check if a frame is allocated in the bitmap - fn is_frame_allocated(&self, bit_index: usize) -> bool { - let byte_index = bit_index / 8; - let bit_offset = bit_index % 8; - - if byte_index >= BITMAP_SIZE { - return true; - } - - unsafe { - (FRAME_BITMAP[byte_index] & (1 << bit_offset)) != 0 - } - } - - /// Set a frame as allocated in the bitmap - fn set_frame_allocated(&mut self, bit_index: usize) { - let byte_index = bit_index / 8; - let bit_offset = bit_index % 8; - - if byte_index < BITMAP_SIZE { - unsafe { - FRAME_BITMAP[byte_index] |= 1 << bit_offset; + return None; } - } + }; + + drop(atoms); + + PhysFrame::from_start_address(PhysAddr::new(frame as u64)).ok() } - /// Set a frame as free in the bitmap - fn set_frame_free(&mut self, bit_index: usize) { - let byte_index = bit_index / 8; - let bit_offset = bit_index % 8; - - if byte_index < BITMAP_SIZE { - unsafe { - FRAME_BITMAP[byte_index] &= !(1 << bit_offset); - } - } + pub fn deallocate_single_frame(&mut self, frame: PhysFrame) { + ATOMS.lock().deallocate(frame.start_address().as_u64() as usize, 1) } - /// Check if an address is in any usable region - fn is_addr_usable(&self, addr: u64) -> bool { - for region_opt in &self.usable_regions { - if let Some(region) = region_opt { - if addr >= region.base && addr < region.end { - return true; - } - } - } - false - } - - fn find_free_frame(&mut self) -> Option> { - let max_frames = BITMAP_SIZE * 8; - - for offset in 0..max_frames { - let index = (self.last_allocated + offset) % max_frames; - - if !self.is_frame_allocated(index) { - let addr = self.bitmap_index_to_addr(index); - - if self.is_addr_usable(addr) { - self.last_allocated = index; - return Some(PhysFrame::containing_address(PhysAddr::new(addr))); - } - } - } - - None + pub fn total_memory() -> usize { + TOTAL_MEMORY.load(Ordering::Relaxed) } } unsafe impl FrameAllocator for PFrameAllocator { fn allocate_frame(&mut self) -> Option> { - if let Some(frame) = self.find_free_frame() { - let addr = frame.start_address().as_u64(); - - if let Some(bit_index) = self.addr_to_bitmap_index(addr) { - print!( - "Found frame at {:#x} ({} bytes)", - addr, - frame.size() - ); - - self.set_frame_allocated(bit_index); - ALLOCATED_FRAMES.fetch_add(1, Ordering::Relaxed); - - // ensure memory is cleared - unsafe { - print!("! Clearing memory..."); - slice_from_raw_parts_mut(addr as *mut u8, frame.size() as usize).as_mut()?.fill(0); - } - - print!(" Allocated!\n"); - - Some(frame) - } else { - println!("cant convert address to bitmap?"); - - None - } - } else { - println!("no free frame :("); - - None - } + self.allocate_single_frame() } } impl FrameDeallocator for PFrameAllocator { unsafe fn deallocate_frame(&mut self, frame: PhysFrame) { - let addr = frame.start_address().as_u64(); - - if !self.is_addr_usable(addr) { - return; - } - - if let Some(bit_index) = self.addr_to_bitmap_index(addr) { - if self.is_frame_allocated(bit_index) { - self.set_frame_free(bit_index); - ALLOCATED_FRAMES.fetch_sub(1, Ordering::Relaxed); - - self.last_allocated = bit_index; - } - } + self.deallocate_single_frame(frame); } }