@@ -37,17 +37,15 @@ impl HoleList {
3737 pub fn allocate_first_fit ( & mut self , size : usize , align : usize ) -> Option < * mut u8 > {
3838 assert ! ( size >= Self :: min_size( ) ) ;
3939
40- if let Some ( result ) = allocate_first_fit ( & mut self . first , size, align) {
41- if let Some ( HoleInfo { addr : padding_addr , size : padding_size } ) = result . front_padding {
42- self . deallocate ( padding_addr as * mut u8 , padding_size ) ;
40+ allocate_first_fit ( & mut self . first , size, align) . map ( |allocation| {
41+ if let Some ( padding ) = allocation . front_padding {
42+ deallocate ( & mut self . first , padding . addr , padding . size ) ;
4343 }
44- if let Some ( HoleInfo { addr : padding_addr , size : padding_size } ) = result . back_padding {
45- self . deallocate ( padding_addr as * mut u8 , padding_size ) ;
44+ if let Some ( padding ) = allocation . back_padding {
45+ deallocate ( & mut self . first , padding . addr , padding . size ) ;
4646 }
47- Some ( result. hole . addr as * mut u8 )
48- } else {
49- None
50- }
47+ allocation. info . addr as * mut u8
48+ } )
5149 }
5250
5351 pub fn deallocate ( & mut self , ptr : * mut u8 , size : usize ) {
@@ -83,20 +81,29 @@ impl Hole {
8381 size : self . size ,
8482 }
8583 }
84+
85+ /// Returns a reference to the next hole. Panics if this is the last hole.
86+ fn next_unwrap ( & mut self ) -> & mut Hole {
87+ unsafe { self . next . as_mut ( ) . unwrap ( ) . get_mut ( ) }
88+ }
8689}
8790
91+ /// Basic information about a hole.
92+ #[ derive( Debug , Clone , Copy ) ]
8893struct HoleInfo {
8994 addr : usize ,
9095 size : usize ,
9196}
9297
93- struct HoleResult {
94- hole : HoleInfo ,
98+ /// The result returned by `split_hole` and `allocate_first_fit`. Contains the address and size of
99+ /// the allocation (in the `info` field), and the front and back padding.
100+ struct Allocation {
101+ info : HoleInfo ,
95102 front_padding : Option < HoleInfo > ,
96103 back_padding : Option < HoleInfo > ,
97104}
98105
99- fn split_hole ( hole : HoleInfo , required_size : usize , required_align : usize ) -> Option < HoleResult > {
106+ fn split_hole ( hole : HoleInfo , required_size : usize , required_align : usize ) -> Option < Allocation > {
100107 let aligned_hole = {
101108 let aligned_hole_addr = align_up ( hole. addr , required_align) ;
102109 if aligned_hole_addr + required_size > hole. addr + hole. size {
@@ -109,36 +116,36 @@ fn split_hole(hole: HoleInfo, required_size: usize, required_align: usize) -> Op
109116 }
110117 } ;
111118
112- let front_padding = if aligned_hole. addr > hole. addr {
113- if aligned_hole. addr < hole. addr + HoleList :: min_size ( ) {
114- // hole would cause a new, too small hole
115- return None ;
116- } else {
117- Some ( HoleInfo {
118- addr : hole. addr ,
119- size : aligned_hole. addr - hole. addr ,
120- } )
121- }
122- } else {
119+ let front_padding = if aligned_hole. addr == hole. addr {
120+ // hole has already the required alignment
123121 None
122+ } else if aligned_hole. addr < hole. addr + HoleList :: min_size ( ) {
123+ // we can't use this hole because the required padding would create a new, too small hole
124+ return None ;
125+ } else {
126+ // the required alignment causes some padding before the allocation
127+ Some ( HoleInfo {
128+ addr : hole. addr ,
129+ size : aligned_hole. addr - hole. addr ,
130+ } )
124131 } ;
125132
126- let back_padding = if aligned_hole. size > required_size {
127- if aligned_hole. size - required_size < HoleList :: min_size ( ) {
128- // hole would cause a new, too small hole
129- return None ;
130- } else {
131- Some ( HoleInfo {
132- addr : aligned_hole. addr + required_size,
133- size : aligned_hole. size - required_size,
134- } )
135- }
136- } else {
133+ let back_padding = if aligned_hole. size == required_size {
134+ // the aligned hole has exactly the size that's needed, no padding accrues
137135 None
136+ } else if aligned_hole. size - required_size < HoleList :: min_size ( ) {
137+ // we can't use this hole since its remains would form a new, too small hole
138+ return None ;
139+ } else {
140+ // the hole is bigger than necessary, so there is some padding behind the allocation
141+ Some ( HoleInfo {
142+ addr : aligned_hole. addr + required_size,
143+ size : aligned_hole. size - required_size,
144+ } )
138145 } ;
139146
140- Some ( HoleResult {
141- hole : HoleInfo {
147+ Some ( Allocation {
148+ info : HoleInfo {
142149 addr : aligned_hole. addr ,
143150 size : required_size,
144151 } ,
@@ -147,20 +154,18 @@ fn split_hole(hole: HoleInfo, required_size: usize, required_align: usize) -> Op
147154 } )
148155}
149156
150- fn allocate_first_fit ( previous : & mut Hole , size : usize , align : usize ) -> Option < HoleResult > {
151-
157+ fn allocate_first_fit ( previous : & mut Hole , size : usize , align : usize ) -> Option < Allocation > {
152158 previous. next
153159 . as_mut ( )
154160 . and_then ( |current| split_hole ( unsafe { current. get ( ) } . info ( ) , size, align) )
155- . map ( |result| {
156- previous. next = unsafe { previous. next . as_mut ( ) . unwrap ( ) . get_mut ( ) . next . take ( ) } ;
157- result
161+ . map ( |allocation| {
162+ // hole is big enough, so remove it from the list by updating the previous pointer
163+ previous. next = previous. next_unwrap ( ) . next . take ( ) ;
164+ allocation
158165 } )
159166 . or_else ( || {
160167 // hole is too small, try next hole
161- allocate_first_fit ( unsafe { previous. next . as_mut ( ) . unwrap ( ) . get_mut ( ) } ,
162- size,
163- align)
168+ allocate_first_fit ( previous. next_unwrap ( ) , size, align)
164169 } )
165170}
166171
0 commit comments