Skip to content

Commit 58d3a89

Browse files
committed
Work around yvt/rlsf#21
1 parent 806097c commit 58d3a89

File tree

1 file changed

+29
-7
lines changed

1 file changed

+29
-7
lines changed

src/tlsf.rs

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,21 +70,43 @@ impl Heap {
7070
/// This function will panic if either of the following are true:
7171
///
7272
/// - this function is called more than ONCE.
73-
/// - `size == 0`.
73+
/// - `size`, after aligning start and end to `rlsf::GRANULARITY`, is smaller than `rlsf::GRANULARITY * 2`.
7474
pub unsafe fn init(&self, start_addr: usize, size: usize) {
7575
assert!(size > 0);
7676
critical_section::with(|cs| {
7777
let mut heap = self.heap.borrow_ref_mut(cs);
7878
assert!(!heap.initialized);
79-
heap.initialized = true;
80-
let block: NonNull<[u8]> =
81-
NonNull::slice_from_raw_parts(NonNull::new_unchecked(start_addr as *mut u8), size);
82-
heap.tlsf.insert_free_block_ptr(block);
83-
heap.raw_block = Some(block);
84-
heap.raw_block_size = size;
79+
// Work around https://github.com/yvt/rlsf/pull/21 by aligning block before passing
80+
// it to `Tlsf::insert_free_block_ptr`.
81+
if let Some((aligned_start_addr, usable_size)) = Self::align(start_addr, size) {
82+
let block: NonNull<[u8]> = NonNull::slice_from_raw_parts(
83+
NonNull::new_unchecked(aligned_start_addr as *mut u8),
84+
usable_size,
85+
);
86+
if heap.tlsf.insert_free_block_ptr(block).is_some() {
87+
heap.initialized = true;
88+
heap.raw_block = Some(block);
89+
heap.raw_block_size = size;
90+
}
91+
}
92+
if !heap.initialized {
93+
panic!("Allocation too small for heap");
94+
}
8595
});
8696
}
8797

98+
/// Align `start_addr` to `rlsf::GRANULARITY` and make
99+
/// `size` a multiple of `2*rlsf::GRANULARITY`.
100+
fn align(start_addr: usize, size: usize) -> Option<(usize, usize)> {
101+
let align_offset: usize = (start_addr as *const u8).align_offset(rlsf::GRANULARITY);
102+
if align_offset >= size {
103+
return None;
104+
}
105+
let reduced_size: usize = size - align_offset;
106+
let usable_size: usize = reduced_size - (reduced_size % (rlsf::GRANULARITY * 2));
107+
Some((start_addr + align_offset, usable_size))
108+
}
109+
88110
fn alloc(&self, layout: Layout) -> Option<NonNull<u8>> {
89111
critical_section::with(|cs| self.heap.borrow_ref_mut(cs).tlsf.allocate(layout))
90112
}

0 commit comments

Comments
 (0)