@@ -34,7 +34,35 @@ use crate::mem::paging::align_up;
3434use crate :: utils:: bitmap:: Bitmap ;
3535use crate :: utils:: sync:: Mutex ;
3636
37- static BUDDY_SIZE : [ u64 ; 3 ] = [ Size4KiB :: SIZE , Size4KiB :: SIZE * 4 , Size2MiB :: SIZE ] ;
37+ const BUDDY_SIZE : [ u64 ; 10 ] = [
38+ Size4KiB :: SIZE , // 4 KiB
39+ Size4KiB :: SIZE * 2 , // 8 KiB
40+ Size4KiB :: SIZE * 4 , // 16 KiB
41+ Size4KiB :: SIZE * 8 , // 32 KiB
42+ Size4KiB :: SIZE * 16 , // 64 KiB
43+ Size4KiB :: SIZE * 32 , // 128 KiB
44+ Size4KiB :: SIZE * 64 , // 256 KiB
45+ Size4KiB :: SIZE * 128 , // 512 KiB
46+ Size4KiB :: SIZE * 256 , // 1 MiB
47+ Size2MiB :: SIZE , // 2 MiB
48+ ] ;
49+
50+ const fn order_from_size ( size : u64 ) -> usize {
51+ // UNSTABLE: We cannot make an iterator from `BUDDY_SIZE` or use a for loop
52+ // in const context.
53+ let mut order = 0 ;
54+
55+ while order < BUDDY_SIZE . len ( ) {
56+ let buddy_size = BUDDY_SIZE [ order] ;
57+ if buddy_size >= size {
58+ return order;
59+ }
60+
61+ order += 1 ;
62+ }
63+
64+ unreachable ! ( )
65+ }
3866
3967pub struct LockedFrameAllocator ( Once < Mutex < GlobalFrameAllocator > > ) ;
4068
@@ -60,8 +88,12 @@ unsafe impl FrameAllocator<Size4KiB> for LockedFrameAllocator {
6088
6189 self . 0 . get ( ) . map ( |m| {
6290 m. lock_irq ( )
63- . allocate_frame_inner ( 0 )
64- . map ( |f| PhysFrame :: containing_address ( f) )
91+ . allocate_frame_inner ( order_from_size ( Size4KiB :: SIZE ) )
92+ . map ( |f| {
93+ let frame = PhysFrame :: containing_address ( f) ;
94+ frame. as_slice_mut ( ) . fill ( 0 ) ;
95+ frame
96+ } )
6597 } ) ?
6698 }
6799
@@ -70,10 +102,13 @@ unsafe impl FrameAllocator<Size4KiB> for LockedFrameAllocator {
70102 // let caller = core::panic::Location::caller();
71103 // log::debug!("deallocation request of 4KiB by {:?}", caller);
72104
73- // self.0
74- // .get()
75- // .map(|m| m.lock().deallocate_frame_inner(frame.start_address(), 0))
76- // .unwrap_or(());
105+ self . 0
106+ . get ( )
107+ . map ( |m| {
108+ m. lock_irq ( )
109+ . deallocate_frame_inner ( frame. start_address ( ) , order_from_size ( Size4KiB :: SIZE ) )
110+ } )
111+ . unwrap_or ( ( ) ) ;
77112 }
78113}
79114
@@ -85,7 +120,7 @@ unsafe impl FrameAllocator<Size2MiB> for LockedFrameAllocator {
85120
86121 self . 0 . get ( ) . map ( |m| {
87122 m. lock_irq ( )
88- . allocate_frame_inner ( 2 )
123+ . allocate_frame_inner ( order_from_size ( Size2MiB :: SIZE ) )
89124 . map ( |f| PhysFrame :: containing_address ( f) )
90125 } ) ?
91126 }
@@ -99,7 +134,7 @@ unsafe impl FrameAllocator<Size2MiB> for LockedFrameAllocator {
99134 . get ( )
100135 . map ( |m| {
101136 m. lock_irq ( )
102- . deallocate_frame_inner ( frame. start_address ( ) , 2 )
137+ . deallocate_frame_inner ( frame. start_address ( ) , order_from_size ( Size2MiB :: SIZE ) )
103138 } )
104139 . unwrap_or ( ( ) ) ;
105140 }
@@ -150,7 +185,7 @@ impl<'a> Iterator for RangeMemoryIter<'a> {
150185#[ repr( usize ) ]
151186pub enum BuddyOrdering {
152187 Size4KiB = 0 ,
153- Size8KiB = 2 ,
188+ Size8KiB = 1 ,
154189}
155190
156191// FIXME: REMOVE THIS FUNCTION
@@ -247,35 +282,32 @@ unsafe impl Send for BootAllocRef {}
247282
248283static VM_FRAMES : Once < Vec < VmFrame > > = Once :: new ( ) ;
249284
250- /// Buddy allocator combines power-of-two allocator with free buffer
251- /// coalescing.
285+ /// Buddy allocator combines power-of-two allocator with free buffer coalescing.
252286///
253287/// ## Overview
254288///
255289/// Overview of the buddy allocation algorithm:
256290///
257- /// * Memory is broken up into large blocks of pages where each block
258- /// is a power of two number of pages.
291+ /// * Memory is broken up into large blocks of pages where each block is a power of two number of
292+ /// pages.
259293///
260- /// * If a block of the desired size is not available, a larger block is
261- /// broken up in half and the two blocks are marked as buddies then one half
262- /// is used for the allocation and the other half is marked free.
294+ /// * If a block of the desired size is not available, a larger block is broken up in half and the
295+ /// two blocks are marked as buddies then one half is used for the allocation and the other half
296+ /// is marked free.
263297///
264- /// * The blocks are continuously halved as necessary until a block of the
265- /// desired size is available.
298+ /// * The blocks are continuously halved as necessary until a block of the desired size is
299+ /// available.
266300///
267- /// * When a block is later freed, the buddy is examined and the two coalesced
268- /// if it is free.
301+ /// * When a block is later freed, the buddy is examined and the two coalesced if it is free.
269302pub struct GlobalFrameAllocator {
270- buddies : [ Bitmap < BootAllocRef > ; 3 ] ,
271- free : [ usize ; 3 ] ,
303+ buddies : [ Bitmap < BootAllocRef > ; 10 ] ,
304+ free : [ usize ; 10 ] ,
272305
273306 base : PhysAddr ,
274307 end : PhysAddr ,
275308}
276309
277310impl GlobalFrameAllocator {
278- /// Create a new global frame allocator from the memory map provided by the bootloader.
279311 fn new ( memory_map : & mut [ NonNullPtr < LimineMemmapEntry > ] ) -> Self {
280312 // Find a memory map entry that is big enough to fit all of the items in
281313 // range memory iter.
@@ -350,8 +382,15 @@ impl GlobalFrameAllocator {
350382 Bitmap :: empty ( bref. clone ( ) ) ,
351383 Bitmap :: empty ( bref. clone ( ) ) ,
352384 Bitmap :: empty ( bref. clone ( ) ) ,
385+ Bitmap :: empty ( bref. clone ( ) ) ,
386+ Bitmap :: empty ( bref. clone ( ) ) ,
387+ Bitmap :: empty ( bref. clone ( ) ) ,
388+ Bitmap :: empty ( bref. clone ( ) ) ,
389+ Bitmap :: empty ( bref. clone ( ) ) ,
390+ Bitmap :: empty ( bref. clone ( ) ) ,
391+ Bitmap :: empty ( bref. clone ( ) ) ,
353392 ] ,
354- free : [ 0 ; 3 ] ,
393+ free : [ 0 ; 10 ] ,
355394 } ;
356395
357396 let size = this. end - this. base ;
@@ -455,7 +494,7 @@ impl GlobalFrameAllocator {
455494 let idx = self . get_bit_idx ( addr, order) ;
456495
457496 let buddy = & mut self . buddies [ order] ;
458- let change = buddy. is_set ( idx) == true ;
497+ let change = buddy. is_set ( idx) ;
459498
460499 if change {
461500 buddy. set ( idx, false ) ;
0 commit comments