Skip to content

Commit 4f150ca

Browse files
committed
Try to minimize fragmentation
1 parent 2cec710 commit 4f150ca

File tree

1 file changed

+39
-17
lines changed

1 file changed

+39
-17
lines changed

src/frame_allocator.rs

+39-17
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use os_bootinfo::{MemoryMap, MemoryRegion, MemoryRegionType};
22
use x86_64::structures::paging::{PhysFrame, PAGE_SIZE};
3-
use x86_64::align_up;
3+
use x86_64::{align_up, PhysAddr};
44

55
pub(crate) struct FrameAllocator<'a> {
66
pub memory_map: &'a mut MemoryMap,
@@ -10,26 +10,48 @@ impl<'a> FrameAllocator<'a> {
1010
pub(crate) fn allocate_frame(&mut self, region_type: MemoryRegionType) -> Option<PhysFrame> {
1111
let page_size = u64::from(PAGE_SIZE);
1212
let mut frame = None;
13-
for region in self.memory_map.iter_mut() {
14-
if region.region_type != MemoryRegionType::Usable {
15-
continue;
16-
}
17-
if region.len < page_size {
18-
continue;
13+
14+
if frame.is_none() {
15+
// look for an adjacent regions of same types
16+
let mut last_region_end = PhysAddr::new(0);
17+
for region in self.memory_map.iter_mut() {
18+
if region.region_type == region_type {
19+
last_region_end = region.end_addr();
20+
} else if region.region_type == MemoryRegionType::Usable {
21+
if region.start_addr() == last_region_end {
22+
frame = Some(PhysFrame::containing_address(region.start_addr));
23+
region.start_addr += page_size;
24+
region.len -= page_size;
25+
break
26+
}
27+
}
1928
}
29+
}
2030

21-
assert_eq!(
22-
0,
23-
region.start_addr.as_u64() & 0xfff,
24-
"Region start address is not page aligned: {:?}",
25-
region
26-
);
31+
if frame.is_none() {
32+
// search all regions
33+
for region in self.memory_map.iter_mut() {
34+
if region.region_type != MemoryRegionType::Usable {
35+
continue;
36+
}
37+
if region.len < page_size {
38+
continue;
39+
}
40+
41+
assert_eq!(
42+
0,
43+
region.start_addr.as_u64() & 0xfff,
44+
"Region start address is not page aligned: {:?}",
45+
region
46+
);
2747

28-
frame = Some(PhysFrame::containing_address(region.start_addr));
29-
region.start_addr += page_size;
30-
region.len -= page_size;
31-
break;
48+
frame = Some(PhysFrame::containing_address(region.start_addr));
49+
region.start_addr += page_size;
50+
region.len -= page_size;
51+
break;
52+
}
3253
}
54+
3355
if let Some(frame) = frame {
3456
self.add_region(MemoryRegion {
3557
start_addr: frame.start_address(),

0 commit comments

Comments
 (0)