Skip to content

Commit

Permalink
Fix bug, add tests
Browse files Browse the repository at this point in the history
Signed-off-by: Graham MacDonald <[email protected]>
  • Loading branch information
gmacd committed Feb 4, 2024
1 parent 59ff943 commit 1a10e98
Showing 1 changed file with 41 additions and 12 deletions.
53 changes: 41 additions & 12 deletions port/src/bitmapalloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,19 @@ impl<const NUM_BITMAPS: usize, const BITMAP_SIZE_BYTES: usize>
}
}

/// Returns number of physical bytes a single bitmap can cover.
const fn bytes_per_bitmap_byte(&self) -> usize {
8 * self.alloc_page_size
}

/// Returns number of physical bytes a single bitmap can cover.
const fn bytes_per_bitmap(&self) -> usize {
BITMAP_SIZE_BYTES * 8 * self.alloc_page_size
BITMAP_SIZE_BYTES * self.bytes_per_bitmap_byte()
}

/// Returns number of physical bytes covered by all bitmaps.
const fn max_bytes(&self) -> usize {
NUM_BITMAPS * BITMAP_SIZE_BYTES * 8 * self.alloc_page_size
NUM_BITMAPS * self.bytes_per_bitmap()
}

/// Mark the bits corresponding to the given physical range as allocated,
Expand Down Expand Up @@ -132,6 +137,7 @@ impl<const NUM_BITMAPS: usize, const BITMAP_SIZE_BYTES: usize>
+ (byteidx * 8 * self.alloc_page_size)
+ (num_leading_ones * self.alloc_page_size))
as u64;

return Ok(PhysAddr::new(pa));
}

Expand All @@ -151,10 +157,10 @@ impl<const NUM_BITMAPS: usize, const BITMAP_SIZE_BYTES: usize>
return Err(BitmapPageAllocError::OutOfBounds);
}

let (bitmap_idx, bit_idx) = self.physaddr_as_indices(pa);
let (bitmap_idx, byte_idx, bit_idx) = self.physaddr_as_indices(pa);

let bitmap = &mut self.bitmaps[bitmap_idx];
if !bitmap.is_set(bit_idx) {
if !bitmap.is_set(8 * byte_idx + bit_idx) {
return Err(BitmapPageAllocError::NotAllocated);
}
bitmap.set(bit_idx, false);
Expand All @@ -174,18 +180,25 @@ impl<const NUM_BITMAPS: usize, const BITMAP_SIZE_BYTES: usize>
(total - free_bytes, total)
}

/// For the given physaddr, returns a tuple of
/// (the bitmap containing pa, and the index of the bit within that bitmap).
fn physaddr_as_indices(&self, pa: PhysAddr) -> (usize, usize) {
/// For the given physaddr, returns a tuple of (the bitmap containing pa,
/// the index of the byte containing the pa, and the index of the bit within that byte).
fn physaddr_as_indices(&self, pa: PhysAddr) -> (usize, usize, usize) {
assert_eq!(pa.addr() % self.alloc_page_size as u64, 0);

// Get the index of the bitmap containing the pa
let bytes_per_bitmap = self.bytes_per_bitmap();
let bitmap_idx = pa.addr() as usize / bytes_per_bitmap;

// Get the bit within the bitmap representing the pa
// Get the byte within the bitmap representing the pa
let pa_offset_into_bitmap = pa.addr() as usize % bytes_per_bitmap;
let bit_idx = pa_offset_into_bitmap / self.alloc_page_size;
let bytes_per_bitmap_byte = self.bytes_per_bitmap_byte();
let byte_idx = pa_offset_into_bitmap / bytes_per_bitmap_byte;

// Finally get the bit within the byte
let bit_idx =
(pa_offset_into_bitmap - (byte_idx * bytes_per_bitmap_byte)) / self.alloc_page_size;

(bitmap_idx, bit_idx)
(bitmap_idx, byte_idx, bit_idx)
}

fn mark_range(
Expand All @@ -199,13 +212,13 @@ impl<const NUM_BITMAPS: usize, const BITMAP_SIZE_BYTES: usize>
}

for pa in range.step_by_rounded(self.alloc_page_size) {
let (bitmap_idx, bit_idx) = self.physaddr_as_indices(pa);
let (bitmap_idx, byte_idx, bit_idx) = self.physaddr_as_indices(pa);
if bitmap_idx >= self.bitmaps.len() {
return Err(BitmapPageAllocError::OutOfBounds);
}

let bitmap = &mut self.bitmaps[bitmap_idx];
bitmap.set(bit_idx, mark_allocated);
bitmap.set(8 * byte_idx + bit_idx, mark_allocated);
}
Ok(())
}
Expand Down Expand Up @@ -337,4 +350,20 @@ mod tests {

Ok(())
}

#[test]
fn physaddr_as_indices() {
let alloc = BitmapPageAlloc::<2, 4096>::new_all_allocated(4096);
let bytes_per_bitmap = alloc.bytes_per_bitmap() as u64;
assert_eq!(alloc.physaddr_as_indices(PhysAddr::new(0)), (0, 0, 0));
assert_eq!(alloc.physaddr_as_indices(PhysAddr::new(4096)), (0, 0, 1));
assert_eq!(alloc.physaddr_as_indices(PhysAddr::new(8192)), (0, 0, 2));
assert_eq!(alloc.physaddr_as_indices(PhysAddr::new(4096 * 8)), (0, 1, 0));
assert_eq!(alloc.physaddr_as_indices(PhysAddr::new(4096 * 9)), (0, 1, 1));
assert_eq!(alloc.physaddr_as_indices(PhysAddr::new(bytes_per_bitmap)), (1, 0, 0));
assert_eq!(
alloc.physaddr_as_indices(PhysAddr::new(bytes_per_bitmap + 4096 * 9)),
(1, 1, 1)
);
}
}

0 comments on commit 1a10e98

Please sign in to comment.