Skip to content

Commit 00ebb78

Browse files
committed
Create documentation for types and functions
1 parent 9d972e8 commit 00ebb78

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

src/hole.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ use core::mem::{self, size_of};
33

44
use super::align_up;
55

6+
/// A sorted list of holes. It uses the the holes itself to store its nodes.
67
pub struct HoleList {
78
first: Hole, // dummy
89
}
910

1011
impl HoleList {
12+
/// Creates an empty `HoleList`.
1113
pub const fn empty() -> HoleList {
1214
HoleList {
1315
first: Hole {
@@ -17,6 +19,9 @@ impl HoleList {
1719
}
1820
}
1921

22+
/// Creates a `HoleList` that contains the given hole. This function is unsafe because it
23+
/// creates a hole at the given `hole_addr`. This can cause undefined behavior if this address
24+
/// is invalid or if memory from the `[hole_addr, hole_addr+size) range is used somewhere else.
2025
pub unsafe fn new(hole_addr: usize, hole_size: usize) -> HoleList {
2126
assert!(size_of::<Hole>() == Self::min_size());
2227

@@ -35,6 +40,11 @@ impl HoleList {
3540
}
3641
}
3742

43+
/// Searches the list for a big enough hole. A hole is big enough if it can hold an allocation
44+
/// of `size` bytes with the given `align`. If such a hole is found in the list, a block of the
45+
/// required size is allocated from it. Then the start address of that block is returned.
46+
/// This function uses the “first fit” strategy, so it uses the first hole that is big enough.
47+
/// Thus the runtime is in O(n) but it should be reasonably fast for small allocations.
3848
pub fn allocate_first_fit(&mut self, size: usize, align: usize) -> Option<*mut u8> {
3949
assert!(size >= Self::min_size());
4050

@@ -49,14 +59,22 @@ impl HoleList {
4959
})
5060
}
5161

62+
/// Frees the allocation given by `ptr` and `size`. `ptr` must be a pointer returned by a call
63+
/// to the `allocate_first_fit` function with identical size. Undefined behavior may occur for
64+
/// invalid arguments.
65+
/// This function walks the list and inserts the given block at the correct place. If the freed
66+
/// block is adjacent to another free block, the blocks are merged again.
67+
/// This operation is in `O(n)` since the list needs to be sorted by address.
5268
pub unsafe fn deallocate(&mut self, ptr: *mut u8, size: usize) {
5369
deallocate(&mut self.first, ptr as usize, size)
5470
}
5571

72+
/// Returns the minimal allocation size. Smaller allocations or deallocations are not allowed.
5673
pub fn min_size() -> usize {
5774
size_of::<usize>() * 2
5875
}
5976

77+
/// Returns information about the first hole for test purposes.
6078
#[cfg(test)]
6179
pub fn first_hole(&self) -> Option<(usize, usize)> {
6280
self.first.next.as_ref().map(|hole| (**hole as usize, unsafe { hole.get().size }))
@@ -77,6 +95,7 @@ pub struct Hole {
7795
}
7896

7997
impl Hole {
98+
/// Returns basic information about the hole.
8099
fn info(&self) -> HoleInfo {
81100
HoleInfo {
82101
addr: self as *const _ as usize,
@@ -105,6 +124,11 @@ struct Allocation {
105124
back_padding: Option<HoleInfo>,
106125
}
107126

127+
/// Splits the given hole into `(front_padding, hole, back_padding)` if it's big enough to allocate
128+
/// `required_size` bytes with the `required_align`. Else `None` is returned.
129+
/// Front padding occurs if the required alignment is higher than the hole's alignment. Back
130+
/// padding occurs if the required size is smaller than the size of the aligned hole. All padding
131+
/// must be at least `HoleList::min_size()` big or the hole is unusable.
108132
fn split_hole(hole: HoleInfo, required_size: usize, required_align: usize) -> Option<Allocation> {
109133
let aligned_hole = {
110134
let aligned_hole_addr = align_up(hole.addr, required_align);
@@ -156,6 +180,12 @@ fn split_hole(hole: HoleInfo, required_size: usize, required_align: usize) -> Op
156180
})
157181
}
158182

183+
/// Searches the list starting at the next hole of `previous` for a big enough hole. A hole is big
184+
/// enough if it can hold an allocation of `size` bytes with the given `align`. When a hole is used
185+
/// for an allocation, there may be some needed padding before and/or after the allocation. This
186+
/// padding is returned as part of the `Allocation`. The caller must take care of freeing it again.
187+
/// This function uses the “first fit” strategy, so it breaks as soon as a big enough hole is found
188+
/// (and returns it).
159189
fn allocate_first_fit(previous: &mut Hole, size: usize, align: usize) -> Option<Allocation> {
160190
previous.next
161191
.as_mut()

src/lib.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@ mod hole;
1212
#[cfg(test)]
1313
mod test;
1414

15+
/// A fixed size heap backed by a linked list of free memory blocks.
1516
pub struct Heap {
1617
bottom: usize,
1718
top: usize,
1819
holes: HoleList,
1920
}
2021

2122
impl Heap {
23+
/// Creates an empty heap. All allocate calls will return `None`.
2224
pub const fn empty() -> Heap {
2325
Heap {
2426
top: 0,
@@ -27,6 +29,10 @@ impl Heap {
2729
}
2830
}
2931

32+
/// Creates a new heap with the given `bottom` and `top`. Both addresses must be valid and the
33+
/// memory in the `[heap_bottom, heap_top)` range must not be used for anything else. This
34+
/// function is unsafe because it can cause undefined behavior if the given addresses are
35+
/// invalid.
3036
pub unsafe fn new(heap_bottom: usize, heap_top: usize) -> Heap {
3137
Heap {
3238
bottom: heap_bottom,
@@ -35,6 +41,11 @@ impl Heap {
3541
}
3642
}
3743

44+
/// Allocates a chunk of the given size with the given alignment. Returns a pointer to the
45+
/// beginning of that chunk if it was successful. Else it returns `None`.
46+
/// This function scans the list of free memory blocks and uses the first block that is big
47+
/// enough. The runtime is in O(n) where n is the number of free blocks, but it should be
48+
/// reasonably fast for small allocations.
3849
pub fn allocate_first_fit(&mut self, mut size: usize, align: usize) -> Option<*mut u8> {
3950
if size < HoleList::min_size() {
4051
size = HoleList::min_size();
@@ -43,26 +54,37 @@ impl Heap {
4354
self.holes.allocate_first_fit(size, align)
4455
}
4556

57+
/// Frees the given allocation. `ptr` must be a pointer returned
58+
/// by a call to the `allocate_first_fit` function with identical size and alignment. Undefined
59+
/// behavior may occur for invalid arguments, thus this function is unsafe.
60+
///
61+
/// This function walks the list of free memory blocks and inserts the freed block at the
62+
/// correct place. If the freed block is adjacent to another free block, the blocks are merged
63+
/// again. This operation is in `O(n)` since the list needs to be sorted by address.
4664
pub unsafe fn deallocate(&mut self, ptr: *mut u8, mut size: usize, _align: usize) {
4765
if size < HoleList::min_size() {
4866
size = HoleList::min_size();
4967
}
5068
self.holes.deallocate(ptr, size);
5169
}
5270

71+
/// Returns the bottom address of the heap.
5372
pub fn bottom(&self) -> usize {
5473
self.bottom
5574
}
5675

76+
/// Returns the top address of the heap.
5777
pub fn top(&self) -> usize {
5878
self.top
5979
}
6080
}
6181

82+
/// Align downwards. Returns the greatest x with alignment `align` so that x<=value.
6283
fn align_down(value: usize, align: usize) -> usize {
6384
value / align * align
6485
}
6586

87+
/// Align upwards. Returns the smallest x with alignment `align` so that value<=x.
6688
fn align_up(value: usize, align: usize) -> usize {
6789
align_down(value + align - 1, align)
6890
}

0 commit comments

Comments
 (0)