Skip to content

Commit ab4aaf0

Browse files
russell-islamroypat
authored andcommitted
atomic_bitmap: add capability to reset bits range
Currently, there is no implementation to reset a single bit or bit range for AtomicBitmap struct. This patch adds necessary function to reset a specific bit or a bit range. This use case is needed for Cloud-Hypervisor in managing page cache for Microsoft Hypervisor related to SEV-SNP guest. Rather than implementing a new one , it is helpful to add feature to this struct. Signed-off-by: Muminul Islam <[email protected]>
1 parent 236afa4 commit ab4aaf0

File tree

1 file changed

+55
-1
lines changed

1 file changed

+55
-1
lines changed

src/bitmap/backend/atomic_bitmap.rs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@ impl AtomicBitmap {
5656
/// is for the page corresponding to `start_addr`, and the last bit that we set corresponds
5757
/// to address `start_addr + len - 1`.
5858
pub fn set_addr_range(&self, start_addr: usize, len: usize) {
59+
self.set_reset_addr_range(start_addr, len, true);
60+
}
61+
62+
// Set/Reset a range of `len` bytes starting at `start_addr`
63+
// reset parameter determines whether bit will be set/reset
64+
// if set is true then the range of bits will be set to one,
65+
// otherwise zero
66+
fn set_reset_addr_range(&self, start_addr: usize, len: usize, set: bool) {
5967
// Return early in the unlikely event that `len == 0` so the `len - 1` computation
6068
// below does not underflow.
6169
if len == 0 {
@@ -71,8 +79,37 @@ impl AtomicBitmap {
7179
// Attempts to set bits beyond the end of the bitmap are simply ignored.
7280
break;
7381
}
74-
self.map[n >> 6].fetch_or(1 << (n & 63), Ordering::SeqCst);
82+
if set {
83+
self.map[n >> 6].fetch_or(1 << (n & 63), Ordering::SeqCst);
84+
} else {
85+
self.map[n >> 6].fetch_and(!(1 << (n & 63)), Ordering::SeqCst);
86+
}
87+
}
88+
}
89+
90+
/// Reset a range of `len` bytes starting at `start_addr`. The first bit set in the bitmap
91+
/// is for the page corresponding to `start_addr`, and the last bit that we set corresponds
92+
/// to address `start_addr + len - 1`.
93+
pub fn reset_addr_range(&self, start_addr: usize, len: usize) {
94+
self.set_reset_addr_range(start_addr, len, false);
95+
}
96+
97+
/// Set bit to corresponding index
98+
pub fn set_bit(&self, index: usize) {
99+
if index >= self.size {
100+
// Attempts to set bits beyond the end of the bitmap are simply ignored.
101+
return;
102+
}
103+
self.map[index >> 6].fetch_or(1 << (index & 63), Ordering::SeqCst);
104+
}
105+
106+
/// Reset bit to corresponding index
107+
pub fn reset_bit(&self, index: usize) {
108+
if index >= self.size {
109+
// Attempts to reset bits beyond the end of the bitmap are simply ignored.
110+
return;
75111
}
112+
self.map[index >> 6].fetch_and(!(1 << (index & 63)), Ordering::SeqCst);
76113
}
77114

78115
/// Get the length of the bitmap in bits (i.e. in how many pages it can represent).
@@ -208,6 +245,23 @@ mod tests {
208245
assert_eq!(v[0], 0b110);
209246
}
210247

248+
#[test]
249+
fn test_bitmap_reset() {
250+
let b = AtomicBitmap::new(1024, DEFAULT_PAGE_SIZE);
251+
assert_eq!(b.len(), 8);
252+
b.set_addr_range(128, 129);
253+
assert!(!b.is_addr_set(0));
254+
assert!(b.is_addr_set(128));
255+
assert!(b.is_addr_set(256));
256+
assert!(!b.is_addr_set(384));
257+
258+
b.reset_addr_range(128, 129);
259+
assert!(!b.is_addr_set(0));
260+
assert!(!b.is_addr_set(128));
261+
assert!(!b.is_addr_set(256));
262+
assert!(!b.is_addr_set(384));
263+
}
264+
211265
#[test]
212266
fn test_bitmap_out_of_range() {
213267
let b = AtomicBitmap::new(1024, NonZeroUsize::MIN);

0 commit comments

Comments
 (0)