Skip to content

Commit acd9867

Browse files
authored
Merge front/back padding after allocate current hole (#54)
When we allocate a memory chunk, there may be some memory paddings in front/back of the allocated chunk. Before this change, these paddings are dealed by calling function deallocate. However the implementation is inefficient since deallocate function will search from the beginning of the linked-list and find the right place to insert these paddings. With this change, the paddings are linked to linked-list right after they are generated. We don't have to deal with merge continuous since paddings are guaranteed to be separated between them and to previous and next holes.
1 parent e578033 commit acd9867

File tree

1 file changed

+32
-15
lines changed

1 file changed

+32
-15
lines changed

src/hole.rs

+32-15
Original file line numberDiff line numberDiff line change
@@ -92,16 +92,9 @@ impl HoleList {
9292
pub fn allocate_first_fit(&mut self, layout: Layout) -> Result<(NonNull<u8>, Layout), ()> {
9393
let aligned_layout = Self::align_layout(layout);
9494

95-
allocate_first_fit(&mut self.first, aligned_layout).map(|allocation| {
96-
if let Some(padding) = allocation.front_padding {
97-
deallocate(&mut self.first, padding.addr, padding.size);
98-
}
99-
if let Some(padding) = allocation.back_padding {
100-
deallocate(&mut self.first, padding.addr, padding.size);
101-
}
102-
95+
allocate_first_fit(&mut self.first, aligned_layout).map(|holeinfo| {
10396
(
104-
NonNull::new(allocation.info.addr as *mut u8).unwrap(),
97+
NonNull::new(holeinfo.addr as *mut u8).unwrap(),
10598
aligned_layout,
10699
)
107100
})
@@ -242,23 +235,47 @@ fn split_hole(hole: HoleInfo, required_layout: Layout) -> Option<Allocation> {
242235
}
243236

244237
/// Searches the list starting at the next hole of `previous` for a big enough hole. A hole is big
245-
/// enough if it can hold an allocation of `layout.size()` bytes with the given `layou.align()`.
238+
/// enough if it can hold an allocation of `layout.size()` bytes with the given `layout.align()`.
246239
/// When a hole is used for an allocation, there may be some needed padding before and/or after
247-
/// the allocation. This padding is returned as part of the `Allocation`. The caller must take
248-
/// care of freeing it again.
240+
/// the allocation. The padding will then merge back to linked-list
249241
/// This function uses the “first fit” strategy, so it breaks as soon as a big enough hole is
250242
/// found (and returns it).
251-
fn allocate_first_fit(mut previous: &mut Hole, layout: Layout) -> Result<Allocation, ()> {
243+
fn allocate_first_fit(mut previous: &mut Hole, layout: Layout) -> Result<HoleInfo, ()> {
252244
loop {
253245
let allocation: Option<Allocation> = previous
254246
.next
255247
.as_mut()
256248
.and_then(|current| split_hole(current.info(), layout.clone()));
257249
match allocation {
258250
Some(allocation) => {
259-
// hole is big enough, so remove it from the list by updating the previous pointer
251+
// link the front/back padding
252+
// Note that there must be no hole between following pair:
253+
// previous - front_padding
254+
// front_padding - back_padding
255+
// back_padding - previous.next
260256
previous.next = previous.next.as_mut().unwrap().next.take();
261-
return Ok(allocation);
257+
if let Some(padding) = allocation.front_padding {
258+
let ptr = padding.addr as *mut Hole;
259+
unsafe {
260+
ptr.write(Hole {
261+
size: padding.size,
262+
next: previous.next.take(),
263+
})
264+
}
265+
previous.next = Some(unsafe { &mut *ptr });
266+
previous = move_helper(previous).next.as_mut().unwrap();
267+
}
268+
if let Some(padding) = allocation.back_padding {
269+
let ptr = padding.addr as *mut Hole;
270+
unsafe {
271+
ptr.write(Hole {
272+
size: padding.size,
273+
next: previous.next.take(),
274+
})
275+
}
276+
previous.next = Some(unsafe { &mut *ptr });
277+
}
278+
return Ok(allocation.info);
262279
}
263280
None if previous.next.is_some() => {
264281
// try next hole

0 commit comments

Comments
 (0)