mirror of
https://github.com/iceHtwoO/novaOS.git
synced 2026-04-16 20:22:26 +00:00
Fix first fit implementation of heap
This commit is contained in:
@@ -61,7 +61,7 @@ impl Heap {
|
|||||||
unsafe fn find_first_fit(&self, size: usize) -> Result<*mut HeapHeader, NovaError> {
|
unsafe fn find_first_fit(&self, size: usize) -> Result<*mut HeapHeader, NovaError> {
|
||||||
let mut current = self.start_address;
|
let mut current = self.start_address;
|
||||||
while !fits(size, current) {
|
while !fits(size, current) {
|
||||||
if let Some(next) = (*self.start_address).next {
|
if let Some(next) = (*current).next {
|
||||||
current = next;
|
current = next;
|
||||||
} else {
|
} else {
|
||||||
return Err(NovaError::HeapFull);
|
return Err(NovaError::HeapFull);
|
||||||
@@ -122,9 +122,11 @@ impl Heap {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
(*current).next = Some(new_address);
|
unsafe {
|
||||||
(*current).free = false;
|
(*current).next = Some(new_address);
|
||||||
(*current).size = size;
|
(*current).free = false;
|
||||||
|
(*current).size = size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn free(&self, pointer: *mut u8) -> Result<(), NovaError> {
|
pub fn free(&self, pointer: *mut u8) -> Result<(), NovaError> {
|
||||||
|
|||||||
@@ -88,38 +88,78 @@ fn test_freeing_root() {
|
|||||||
assert_eq!((*root_header).size, root_header_start_size);
|
assert_eq!((*root_header).size, root_header_start_size);
|
||||||
assert!((*root_header).next.is_none());
|
assert!((*root_header).next.is_none());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn test_merging_free_sections() {
|
#[test]
|
||||||
let heap_vector = Box::new([0u8; HEAP_SIZE]);
|
fn test_merging_free_sections() {
|
||||||
let mut heap = Heap::empty();
|
let heap_vector = Box::new([0u8; HEAP_SIZE]);
|
||||||
heap.init(
|
let mut heap = Heap::empty();
|
||||||
&heap_vector[0] as *const u8 as usize,
|
heap.init(
|
||||||
&heap_vector[HEAP_SIZE - 1] as *const u8 as usize,
|
&heap_vector[0] as *const u8 as usize,
|
||||||
|
&heap_vector[HEAP_SIZE - 1] as *const u8 as usize,
|
||||||
|
);
|
||||||
|
|
||||||
|
let root_header = heap.start_address;
|
||||||
|
let root_header_start_size = unsafe { (*root_header).size };
|
||||||
|
|
||||||
|
let malloc1 = heap.malloc(MIN_BLOCK_SIZE).unwrap();
|
||||||
|
let malloc_header_before = unsafe { *Heap::get_header_ref_from_data_pointer(malloc1) };
|
||||||
|
let malloc2 = heap.malloc(MIN_BLOCK_SIZE).unwrap();
|
||||||
|
let _ = heap.malloc(MIN_BLOCK_SIZE).unwrap();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
assert!(heap.free(malloc1).is_ok());
|
||||||
|
|
||||||
|
let malloc_header_free = *Heap::get_header_ref_from_data_pointer(malloc1);
|
||||||
|
assert_ne!(malloc_header_before.free, malloc_header_free.free);
|
||||||
|
assert_eq!(malloc_header_before.size, malloc_header_free.size);
|
||||||
|
|
||||||
|
assert!(heap.free(malloc2).is_ok());
|
||||||
|
let malloc_header_merge = *Heap::get_header_ref_from_data_pointer(malloc1);
|
||||||
|
|
||||||
|
assert!(malloc_header_merge.free);
|
||||||
|
assert_eq!(
|
||||||
|
malloc_header_merge.size,
|
||||||
|
malloc_header_free.size + MIN_BLOCK_SIZE + HEAP_HEADER_SIZE
|
||||||
);
|
);
|
||||||
|
}
|
||||||
let root_header = heap.start_address;
|
}
|
||||||
let root_header_start_size = unsafe { (*root_header).size };
|
|
||||||
|
#[test]
|
||||||
let malloc1 = heap.malloc(MIN_BLOCK_SIZE).unwrap();
|
fn test_first_fit() {
|
||||||
let malloc_header_before = unsafe { *Heap::get_header_ref_from_data_pointer(malloc1) };
|
let heap_vector = Box::new([0u8; HEAP_SIZE]);
|
||||||
let malloc2 = heap.malloc(MIN_BLOCK_SIZE).unwrap();
|
let mut heap = Heap::empty();
|
||||||
let malloc3 = heap.malloc(MIN_BLOCK_SIZE).unwrap();
|
heap.init(
|
||||||
|
&heap_vector[0] as *const u8 as usize,
|
||||||
unsafe {
|
&heap_vector[HEAP_SIZE - 1] as *const u8 as usize,
|
||||||
assert!(heap.free(malloc1).is_ok());
|
);
|
||||||
|
|
||||||
let malloc_header_free = *Heap::get_header_ref_from_data_pointer(malloc1);
|
let root_header = heap.start_address;
|
||||||
assert_ne!(malloc_header_before.free, malloc_header_free.free);
|
let root_header_start_size = unsafe { (*root_header).size };
|
||||||
assert_eq!(malloc_header_before.size, malloc_header_free.size);
|
|
||||||
|
let malloc1 = heap.malloc(MIN_BLOCK_SIZE).unwrap();
|
||||||
assert!(heap.free(malloc2).is_ok());
|
let malloc2 = heap.malloc(MIN_BLOCK_SIZE).unwrap();
|
||||||
let malloc_header_merge = *Heap::get_header_ref_from_data_pointer(malloc1);
|
let malloc3 = heap.malloc(MIN_BLOCK_SIZE * 3).unwrap();
|
||||||
|
let malloc4 = heap.malloc(MIN_BLOCK_SIZE).unwrap();
|
||||||
assert!(malloc_header_merge.free);
|
|
||||||
assert_eq!(
|
unsafe {
|
||||||
malloc_header_merge.size,
|
assert!(heap.free(malloc1).is_ok());
|
||||||
malloc_header_free.size + MIN_BLOCK_SIZE + HEAP_HEADER_SIZE
|
assert!(heap.free(malloc3).is_ok());
|
||||||
);
|
let malloc5 = heap.malloc(MIN_BLOCK_SIZE * 2).unwrap();
|
||||||
}
|
let malloc1_header = unsafe { *Heap::get_header_ref_from_data_pointer(malloc1) };
|
||||||
|
|
||||||
|
// First free block stays empty
|
||||||
|
assert!(malloc1_header.free);
|
||||||
|
|
||||||
|
// New allocation takes the first fit aka. malloc3
|
||||||
|
assert_eq!(malloc5, malloc3);
|
||||||
|
|
||||||
|
// If no free slot could be found, append to the end
|
||||||
|
let malloc6 = heap.malloc(MIN_BLOCK_SIZE * 2).unwrap();
|
||||||
|
assert!(malloc6 > malloc4);
|
||||||
|
|
||||||
|
// Malloc7 takes slot of Malloc1
|
||||||
|
let malloc7 = heap.malloc(MIN_BLOCK_SIZE).unwrap();
|
||||||
|
assert_eq!(malloc1, malloc7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user