From 68a78861c055b61b24bc5c2dc004eb8c330dc5e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Neuh=C3=A4user?= Date: Sat, 20 Dec 2025 17:31:00 +0100 Subject: [PATCH] Fix merge issues --- src/heap.rs | 216 ---------------------------------------------------- src/lib.rs | 1 - 2 files changed, 217 deletions(-) delete mode 100644 src/heap.rs diff --git a/src/heap.rs b/src/heap.rs deleted file mode 100644 index 65d7351..0000000 --- a/src/heap.rs +++ /dev/null @@ -1,216 +0,0 @@ -#![allow(static_mut_refs)] - -use core::{ - alloc::GlobalAlloc, - ptr::{self, null_mut, read_volatile}, -}; - -use crate::NovaError; -extern crate alloc; - -extern "C" { - static mut __heap_start: u8; - static mut __heap_end: u8; -} - -#[repr(C, align(16))] -pub struct HeapHeader { - pub next: *mut HeapHeader, - before: *mut HeapHeader, - pub size: usize, - free: bool, -} - -const HEAP_HEADER_SIZE: usize = size_of::(); -const MIN_BLOCK_SIZE: usize = 16; - -// TODO: This implementation has to be reevaluated when implementing multiprocessing -// Spinlock could be a solution but has its issues: -// https://matklad.github.io/2020/01/02/spinlocks-considered-harmful.html -pub static mut HEAP: Heap = Heap { - start_address: &raw mut __heap_start as *mut HeapHeader, - end_address: &raw mut __heap_end as *mut HeapHeader, - raw_size: 0, -}; - -// TODO: investigate if there is a better alternative to this -pub unsafe fn init_global_heap() { - HEAP.init(); -} - -#[derive(Default)] -pub struct Novalloc; - -unsafe impl GlobalAlloc for Novalloc { - unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 { - HEAP.malloc(layout.size()).unwrap() - } - - unsafe fn dealloc(&self, ptr: *mut u8, _: core::alloc::Layout) { - HEAP.free(ptr).unwrap(); - } -} - -#[global_allocator] -static GLOBAL_ALLOCATOR: Novalloc = Novalloc; - -pub struct Heap { - start_address: *mut HeapHeader, - end_address: *mut HeapHeader, - raw_size: usize, -} -impl Heap { - pub fn new(heap_start: usize, heap_end: usize) -> Self { - let mut instance = Self { - start_address: &raw const heap_start as *mut HeapHeader, - end_address: &raw const heap_end as *mut HeapHeader, - raw_size: heap_end - heap_start, - }; - instance.init(); - instance - } - - fn init(&mut self) { - self.raw_size = self.end_address as usize - self.start_address as usize; - - unsafe { - ptr::write( - self.start_address, - HeapHeader { - next: null_mut(), - before: null_mut(), - size: self.raw_size - HEAP_HEADER_SIZE, - free: true, - }, - ); - } - } - - unsafe fn find_first_fit(&self, size: usize) -> Result<*mut HeapHeader, NovaError> { - let mut current = self.start_address; - while !fits(size, current) { - if (*self.start_address).next.is_null() { - return Err(NovaError::HeapFull); - } - current = (*current).next; - } - Ok(current) - } - - pub fn malloc(&self, mut size: usize) -> Result<*mut u8, NovaError> { - if size == 0 { - return Err(NovaError::EmptyHeapSegmentNotAllowed); - } - - if size < MIN_BLOCK_SIZE { - size = MIN_BLOCK_SIZE; - } - - // Align size to the next 16 bytes - size += (16 - (size % 16)) % 16; - - unsafe { - // Find First-Fit memory segment - let current = self.find_first_fit(size)?; - - // Return entire block WITHOUT generating a new header - // if the current block doesn't have enough space to hold: requested size + HEAP_HEADER_SIZE + MIN_BLOCK_SIZE - if (*current).size < size + HEAP_HEADER_SIZE + MIN_BLOCK_SIZE { - (*current).free = false; - return Ok(current.byte_add(HEAP_HEADER_SIZE) as *mut u8); - } - - Self::fragment_segment(current, size); - - let data_start_address = current.byte_add(HEAP_HEADER_SIZE); - - Ok(data_start_address as *mut u8) - } - } - - unsafe fn fragment_segment(current: *mut HeapHeader, size: usize) { - let byte_offset = HEAP_HEADER_SIZE + size; - let new_address = current.byte_add(byte_offset); - - // Handle case where fragmenting center free space - let next = (*current).next; - if !(*current).next.is_null() { - (*next).before = new_address; - } - - ptr::write( - new_address as *mut HeapHeader, - HeapHeader { - next, - before: current, - size: (*current).size - size - HEAP_HEADER_SIZE, - free: true, - }, - ); - (*current).next = new_address; - (*current).free = false; - (*current).size = size; - } - - pub fn free(&self, pointer: *mut u8) -> Result<(), NovaError> { - let mut segment = unsafe { pointer.sub(HEAP_HEADER_SIZE) as *mut HeapHeader }; - unsafe { - // IF prev is free: - // Delete header, add size to previous and fix pointers. - // Move Head left - if !(*segment).before.is_null() && (*(*segment).before).free { - let before_head = (*segment).before; - (*before_head).size += (*segment).size + HEAP_HEADER_SIZE; - delete_header(segment); - segment = before_head; - } - // IF next is free: - // Delete next header and merge size, fix pointers - if !(*segment).next.is_null() && (*(*segment).next).free { - let next_head = (*segment).next; - (*segment).size += (*next_head).size + HEAP_HEADER_SIZE; - delete_header(next_head); - } - - // Neither: Set free - (*segment).free = true; - } - - Ok(()) - } - - pub fn traverse_heap(&self) { - let mut pointer_address = self.start_address; - loop { - let head = unsafe { read_volatile(pointer_address) }; - println!("Header {:#x}", pointer_address as u32); - println!("free: {}", head.free); - println!("size: {}", head.size); - println!("hasNext: {}", !head.next.is_null()); - println!(""); - if !head.next.is_null() { - pointer_address = head.next; - } else { - println!("---------------"); - return; - } - } - } -} - -unsafe fn fits(size: usize, header: *mut HeapHeader) -> bool { - (*header).free && size <= (*header).size -} - -unsafe fn delete_header(header: *mut HeapHeader) { - let before = (*header).before; - let next = (*header).next; - - if !before.is_null() { - (*before).next = next; - } - - if !next.is_null() { - (*next).before = before; - } -} diff --git a/src/lib.rs b/src/lib.rs index fe482c1..20b3758 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -51,7 +51,6 @@ pub mod peripherals; pub mod configuration; pub mod framebuffer; -pub mod heap; pub mod irq_interrupt; pub mod mailbox; pub mod timer;