Skip to content

Commit 7c578be

Browse files
committed
Cleanups
1 parent c56d1bc commit 7c578be

File tree

3 files changed

+37
-119
lines changed

3 files changed

+37
-119
lines changed

src/hole.rs

Lines changed: 35 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use core::alloc::Layout;
2-
use core::convert::{TryFrom, TryInto};
2+
use core::convert::TryInto;
33
use core::mem;
44
use core::mem::{align_of, size_of};
55
use core::ptr::NonNull;
@@ -13,42 +13,20 @@ pub struct HoleList {
1313
pub(crate) first: Hole, // dummy
1414
}
1515

16-
pub struct Cursor {
16+
pub(crate) struct Cursor {
1717
prev: NonNull<Hole>,
1818
hole: NonNull<Hole>,
1919
}
2020

21-
enum Position<'a> {
22-
BeforeCurrent,
23-
BetweenCurrentNext {
24-
curr: &'a Hole,
25-
next: &'a Hole,
26-
},
27-
AfterBoth,
28-
AfterCurrentNoNext,
29-
}
30-
3121
impl Cursor {
3222
fn next(mut self) -> Option<Self> {
3323
unsafe {
34-
if let Some(nhole) = self.hole.as_mut().next {
35-
Some(Cursor {
24+
self.hole.as_mut().next.map(|nhole| {
25+
Cursor {
3626
prev: self.hole,
3727
hole: nhole,
38-
})
39-
} else {
40-
None
41-
}
42-
}
43-
}
44-
45-
fn peek_next(&self) -> Option<&Hole> {
46-
unsafe {
47-
if let Some(nhole) = self.hole.as_ref().next {
48-
Some(nhole.as_ref())
49-
} else {
50-
None
51-
}
28+
}
29+
})
5230
}
5331
}
5432

@@ -170,7 +148,6 @@ impl Cursor {
170148

171149
// As of now, the old `Hole` is no more. We are about to replace it with one or more of
172150
// the front padding, the allocation, and the back padding.
173-
drop(hole);
174151

175152
match (front_padding, back_padding) {
176153
(None, None) => {
@@ -249,7 +226,7 @@ impl HoleList {
249226
}
250227
}
251228

252-
pub fn cursor(&mut self) -> Option<Cursor> {
229+
pub(crate) fn cursor(&mut self) -> Option<Cursor> {
253230
if let Some(hole) = self.first.next {
254231
Some(Cursor {
255232
hole,
@@ -326,9 +303,7 @@ impl HoleList {
326303
size = Self::min_size();
327304
}
328305
let size = align_up_size(size, mem::align_of::<Hole>());
329-
let layout = Layout::from_size_align(size, layout.align()).unwrap();
330-
331-
layout
306+
Layout::from_size_align(size, layout.align()).unwrap()
332307
}
333308

334309
/// Searches the list for a big enough hole.
@@ -396,35 +371,13 @@ pub(crate) struct Hole {
396371
pub next: Option<NonNull<Hole>>,
397372
}
398373

399-
impl Hole {
400-
/// Returns basic information about the hole.
401-
fn info(&mut self) -> HoleInfo {
402-
HoleInfo {
403-
addr: self as *mut _ as *mut u8,
404-
size: self.size,
405-
}
406-
}
407-
408-
fn addr_u8(&self) -> *const u8 {
409-
self as *const Hole as *const u8
410-
}
411-
}
412-
413374
/// Basic information about a hole.
414375
#[derive(Debug, Clone, Copy)]
415376
struct HoleInfo {
416377
addr: *mut u8,
417378
size: usize,
418379
}
419380

420-
/// The result returned by `split_hole` and `allocate_first_fit`. Contains the address and size of
421-
/// the allocation (in the `info` field), and the front and back padding.
422-
struct Allocation {
423-
info: HoleInfo,
424-
front_padding: Option<HoleInfo>,
425-
back_padding: Option<HoleInfo>,
426-
}
427-
428381
unsafe fn make_hole(addr: *mut u8, size: usize) -> NonNull<Hole> {
429382
let hole_addr = addr.cast::<Hole>();
430383
debug_assert_eq!(addr as usize % align_of::<Hole>(), 0);
@@ -482,12 +435,11 @@ impl Cursor {
482435
}
483436
}
484437

485-
486-
// Merge the current node with an IMMEDIATELY FOLLOWING next node
487-
fn try_merge_next_two(self) {
438+
// Merge the current node with up to n following nodes
439+
fn try_merge_next_n(self, max: usize) {
488440
let Cursor { prev: _, mut hole } = self;
489441

490-
for _ in 0..2 {
442+
for _ in 0..max {
491443
// Is there a next node?
492444
let mut next = if let Some(next) = unsafe { hole.as_mut() }.next.as_ref() {
493445
*next
@@ -496,13 +448,12 @@ impl Cursor {
496448
};
497449

498450
// Can we directly merge these? e.g. are they touching?
499-
//
500-
// TODO(AJM): Should "touching" also include deltas <= node size?
501451
let hole_u8 = hole.as_ptr().cast::<u8>();
502452
let hole_sz = unsafe { hole.as_ref().size };
503453
let next_u8 = next.as_ptr().cast::<u8>();
454+
let end = hole_u8.wrapping_add(hole_sz);
504455

505-
let touching = hole_u8.wrapping_add(hole_sz) == next_u8;
456+
let touching = end == next_u8;
506457

507458
if touching {
508459
let next_sz;
@@ -531,56 +482,55 @@ impl Cursor {
531482
/// Frees the allocation given by `(addr, size)`. It starts at the given hole and walks the list to
532483
/// find the correct place (the list is sorted by address).
533484
fn deallocate(list: &mut HoleList, addr: *mut u8, size: usize) {
534-
// Start off by just making this allocation a hole.
485+
// Start off by just making this allocation a hole where it stands.
486+
// We'll attempt to merge it with other nodes once we figure out where
487+
// it should live
535488
let hole = unsafe { make_hole(addr, size) };
536489

490+
// Now, try to get a cursor to the list - this only works if we have at least
491+
// one non-"dummy" hole in the list
537492
let cursor = if let Some(cursor) = list.cursor() {
538493
cursor
539494
} else {
540-
// Oh hey, there are no holes at all. That means this just becomes the only hole!
495+
// Oh hey, there are no "real" holes at all. That means this just
496+
// becomes the only "real" hole!
541497
list.first.next = Some(hole);
542498
return;
543499
};
544500

545501
// First, check if we can just insert this node at the top of the list. If the
546502
// insertion succeeded, then our cursor now points to the NEW node, behind the
547503
// previous location the cursor was pointing to.
548-
let cursor = match cursor.try_insert_back(hole) {
504+
//
505+
// Otherwise, our cursor will point at the current non-"dummy" head of the list
506+
let (cursor, n) = match cursor.try_insert_back(hole) {
549507
Ok(cursor) => {
550-
// Yup! It lives at the front of the list. Hooray!
551-
cursor
508+
// Yup! It lives at the front of the list. Hooray! Attempt to merge
509+
// it with just ONE next node, since it is at the front of the list
510+
(cursor, 1)
552511
},
553512
Err(mut cursor) => {
554513
// Nope. It lives somewhere else. Advance the list until we find its home
555514
while let Err(()) = cursor.try_insert_after(hole) {
556515
cursor = cursor.next().unwrap();
557516
}
558-
cursor
517+
// Great! We found a home for it, our cursor is now JUST BEFORE the new
518+
// node we inserted, so we need to try to merge up to twice: One to combine
519+
// the current node to the new node, then once more to combine the new node
520+
// with the node after that.
521+
(cursor, 2)
559522
},
560523
};
561524

562525
// We now need to merge up to two times to combine the current node with the next
563526
// two nodes.
564-
cursor.try_merge_next_two();
565-
}
566-
567-
568-
/// Identity function to ease moving of references.
569-
///
570-
/// By default, references are reborrowed instead of moved (equivalent to `&mut *reference`). This
571-
/// function forces a move.
572-
///
573-
/// for more information, see section “id Forces References To Move” in:
574-
/// https://bluss.github.io/rust/fun/2015/10/11/stuff-the-identity-function-does/
575-
fn move_helper<T>(x: T) -> T {
576-
x
527+
cursor.try_merge_next_n(n);
577528
}
578529

579530
#[cfg(test)]
580531
pub mod test {
581-
use super::*;
582532
use core::alloc::Layout;
583-
use std::mem::{align_of, size_of, MaybeUninit};
533+
use std::mem::MaybeUninit;
584534
use std::prelude::v1::*;
585535
use crate::Heap;
586536

@@ -612,16 +562,13 @@ pub mod test {
612562
#[test]
613563
fn cursor() {
614564
let mut heap = new_heap();
615-
let curs = heap.holes_mut().cursor().unwrap();
565+
let curs = heap.holes.cursor().unwrap();
616566
// This is the "dummy" node
617567
assert_eq!(curs.previous().size, 0);
618568
// This is the "full" heap
619569
assert_eq!(curs.current().size, 1000);
620570
// There is no other hole
621-
assert!(curs.peek_next().is_none());
622-
623-
let reqd = Layout::from_size_align(256, 1).unwrap();
624-
let _ = curs.split_current(reqd).map_err(drop).unwrap();
571+
assert!(curs.next().is_none());
625572
}
626573

627574
#[test]

src/lib.rs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@
55
)]
66
#![no_std]
77

8-
#![allow(dead_code)]
9-
#![allow(unused_imports)]
10-
118
#[cfg(test)]
129
#[macro_use]
1310
extern crate std;
@@ -188,14 +185,6 @@ impl Heap {
188185
self.size - self.used
189186
}
190187

191-
pub(crate) fn holes(&self) -> &HoleList {
192-
&self.holes
193-
}
194-
195-
pub(crate) fn holes_mut(&mut self) -> &mut HoleList {
196-
&mut self.holes
197-
}
198-
199188
/// Extends the size of the heap by creating a new hole at the end
200189
///
201190
/// # Unsafety
@@ -276,7 +265,7 @@ unsafe impl GlobalAlloc for LockedHeap {
276265
.lock()
277266
.allocate_first_fit(layout)
278267
.ok()
279-
.map_or(0 as *mut u8, |allocation| allocation.as_ptr())
268+
.map_or(core::ptr::null_mut(), |allocation| allocation.as_ptr())
280269
}
281270

282271
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {

src/test.rs

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ fn allocate_and_free_double_usize() {
8888
*(x.as_ptr() as *mut (usize, usize)) = (0xdeafdeadbeafbabe, 0xdeafdeadbeafbabe);
8989

9090
heap.deallocate(x, layout.clone());
91-
let real_first = heap.holes().first.next.as_ref().unwrap().as_ref();
91+
let real_first = heap.holes.first.next.as_ref().unwrap().as_ref();
9292

9393
assert_eq!(real_first.size, heap.size);
9494
assert!(real_first.next.is_none());
@@ -310,21 +310,3 @@ fn extend_fragmented_heap() {
310310
// Try to allocate there
311311
assert!(heap.allocate_first_fit(layout_2.clone()).is_ok());
312312
}
313-
314-
315-
// #[test]
316-
// fn break_fragmented_heap() {
317-
// let mut heap = new_heap();
318-
319-
// let layout_1 = Layout::from_size_align(505, 1).unwrap();
320-
// let alloc1 = heap.allocate_first_fit(layout_1.clone());
321-
// assert!(alloc1.is_ok());
322-
323-
// unsafe {
324-
// heap.deallocate(alloc1.unwrap(), layout_1.clone());
325-
// }
326-
327-
// let layout_2 = Layout::from_size_align(1024, 1).unwrap();
328-
// let alloc2 = heap.allocate_first_fit(layout_2.clone());
329-
// assert!(alloc2.is_ok());
330-
// }

0 commit comments

Comments
 (0)