@@ -34,7 +34,35 @@ use crate::mem::paging::align_up;
34
34
use crate :: utils:: bitmap:: Bitmap ;
35
35
use crate :: utils:: sync:: Mutex ;
36
36
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
+ }
38
66
39
67
pub struct LockedFrameAllocator ( Once < Mutex < GlobalFrameAllocator > > ) ;
40
68
@@ -60,8 +88,12 @@ unsafe impl FrameAllocator<Size4KiB> for LockedFrameAllocator {
60
88
61
89
self . 0 . get ( ) . map ( |m| {
62
90
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
+ } )
65
97
} ) ?
66
98
}
67
99
@@ -70,10 +102,13 @@ unsafe impl FrameAllocator<Size4KiB> for LockedFrameAllocator {
70
102
// let caller = core::panic::Location::caller();
71
103
// log::debug!("deallocation request of 4KiB by {:?}", caller);
72
104
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 ( ( ) ) ;
77
112
}
78
113
}
79
114
@@ -85,7 +120,7 @@ unsafe impl FrameAllocator<Size2MiB> for LockedFrameAllocator {
85
120
86
121
self . 0 . get ( ) . map ( |m| {
87
122
m. lock_irq ( )
88
- . allocate_frame_inner ( 2 )
123
+ . allocate_frame_inner ( order_from_size ( Size2MiB :: SIZE ) )
89
124
. map ( |f| PhysFrame :: containing_address ( f) )
90
125
} ) ?
91
126
}
@@ -99,7 +134,7 @@ unsafe impl FrameAllocator<Size2MiB> for LockedFrameAllocator {
99
134
. get ( )
100
135
. map ( |m| {
101
136
m. lock_irq ( )
102
- . deallocate_frame_inner ( frame. start_address ( ) , 2 )
137
+ . deallocate_frame_inner ( frame. start_address ( ) , order_from_size ( Size2MiB :: SIZE ) )
103
138
} )
104
139
. unwrap_or ( ( ) ) ;
105
140
}
@@ -150,7 +185,7 @@ impl<'a> Iterator for RangeMemoryIter<'a> {
150
185
#[ repr( usize ) ]
151
186
pub enum BuddyOrdering {
152
187
Size4KiB = 0 ,
153
- Size8KiB = 2 ,
188
+ Size8KiB = 1 ,
154
189
}
155
190
156
191
// FIXME: REMOVE THIS FUNCTION
@@ -247,35 +282,32 @@ unsafe impl Send for BootAllocRef {}
247
282
248
283
static VM_FRAMES : Once < Vec < VmFrame > > = Once :: new ( ) ;
249
284
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.
252
286
///
253
287
/// ## Overview
254
288
///
255
289
/// Overview of the buddy allocation algorithm:
256
290
///
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.
259
293
///
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.
263
297
///
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.
266
300
///
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.
269
302
pub struct GlobalFrameAllocator {
270
- buddies : [ Bitmap < BootAllocRef > ; 3 ] ,
271
- free : [ usize ; 3 ] ,
303
+ buddies : [ Bitmap < BootAllocRef > ; 10 ] ,
304
+ free : [ usize ; 10 ] ,
272
305
273
306
base : PhysAddr ,
274
307
end : PhysAddr ,
275
308
}
276
309
277
310
impl GlobalFrameAllocator {
278
- /// Create a new global frame allocator from the memory map provided by the bootloader.
279
311
fn new ( memory_map : & mut [ NonNullPtr < LimineMemmapEntry > ] ) -> Self {
280
312
// Find a memory map entry that is big enough to fit all of the items in
281
313
// range memory iter.
@@ -350,8 +382,15 @@ impl GlobalFrameAllocator {
350
382
Bitmap :: empty ( bref. clone ( ) ) ,
351
383
Bitmap :: empty ( bref. clone ( ) ) ,
352
384
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 ( ) ) ,
353
392
] ,
354
- free : [ 0 ; 3 ] ,
393
+ free : [ 0 ; 10 ] ,
355
394
} ;
356
395
357
396
let size = this. end - this. base ;
@@ -455,7 +494,7 @@ impl GlobalFrameAllocator {
455
494
let idx = self . get_bit_idx ( addr, order) ;
456
495
457
496
let buddy = & mut self . buddies [ order] ;
458
- let change = buddy. is_set ( idx) == true ;
497
+ let change = buddy. is_set ( idx) ;
459
498
460
499
if change {
461
500
buddy. set ( idx, false ) ;
0 commit comments