You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
70 lines
2.1 KiB
70 lines
2.1 KiB
use super::{get_block_cache, BlockDevice, BLOCK_SZ};
|
|
use alloc::sync::Arc;
|
|
|
|
type BitmapBlock = [u64; 64];
|
|
|
|
const BLOCK_BITS: usize = BLOCK_SZ * 8;
|
|
|
|
pub struct Bitmap {
|
|
start_block_id: usize,
|
|
blocks: usize,
|
|
}
|
|
|
|
/// Return (block_pos, bits64_pos, inner_pos)
|
|
fn decomposition(mut bit: usize) -> (usize, usize, usize) {
|
|
let block_pos = bit / BLOCK_BITS;
|
|
bit %= BLOCK_BITS;
|
|
(block_pos, bit / 64, bit % 64)
|
|
}
|
|
|
|
impl Bitmap {
|
|
pub fn new(start_block_id: usize, blocks: usize) -> Self {
|
|
Self {
|
|
start_block_id,
|
|
blocks,
|
|
}
|
|
}
|
|
|
|
pub fn alloc(&self, block_device: &Arc<dyn BlockDevice>) -> Option<usize> {
|
|
for block_id in 0..self.blocks {
|
|
let pos = get_block_cache(
|
|
block_id + self.start_block_id as usize,
|
|
Arc::clone(block_device),
|
|
)
|
|
.lock()
|
|
.modify(0, |bitmap_block: &mut BitmapBlock| {
|
|
if let Some((bits64_pos, inner_pos)) = bitmap_block
|
|
.iter()
|
|
.enumerate()
|
|
.find(|(_, bits64)| **bits64 != u64::MAX)
|
|
.map(|(bits64_pos, bits64)| (bits64_pos, bits64.trailing_ones() as usize))
|
|
{
|
|
// modify cache
|
|
bitmap_block[bits64_pos] |= 1u64 << inner_pos;
|
|
Some(block_id * BLOCK_BITS + bits64_pos * 64 + inner_pos as usize)
|
|
} else {
|
|
None
|
|
}
|
|
});
|
|
if pos.is_some() {
|
|
return pos;
|
|
}
|
|
}
|
|
None
|
|
}
|
|
|
|
pub fn dealloc(&self, block_device: &Arc<dyn BlockDevice>, bit: usize) {
|
|
let (block_pos, bits64_pos, inner_pos) = decomposition(bit);
|
|
get_block_cache(block_pos + self.start_block_id, Arc::clone(block_device))
|
|
.lock()
|
|
.modify(0, |bitmap_block: &mut BitmapBlock| {
|
|
assert!(bitmap_block[bits64_pos] & (1u64 << inner_pos) > 0);
|
|
bitmap_block[bits64_pos] -= 1u64 << inner_pos;
|
|
});
|
|
}
|
|
|
|
pub fn maximum(&self) -> usize {
|
|
self.blocks * BLOCK_BITS
|
|
}
|
|
}
|