1 // Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 // SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause 3 4 //! Contains a generic implementation of `BitmapSlice`. 5 6 use std::fmt::{self, Debug}; 7 use std::ops::Deref; 8 use std::sync::Arc; 9 10 use crate::bitmap::{Bitmap, BitmapSlice, WithBitmapSlice}; 11 12 /// Represents a slice into a `Bitmap` object, starting at `base_offset`. 13 #[derive(Clone, Copy)] 14 pub struct BaseSlice<B> { 15 inner: B, 16 base_offset: usize, 17 } 18 19 impl<B> BaseSlice<B> { 20 /// Create a new `BitmapSlice`, starting at the specified `offset`. new(inner: B, offset: usize) -> Self21 pub fn new(inner: B, offset: usize) -> Self { 22 BaseSlice { 23 inner, 24 base_offset: offset, 25 } 26 } 27 } 28 29 impl<'a, B> WithBitmapSlice<'a> for BaseSlice<B> 30 where 31 B: Clone + Deref, 32 B::Target: Bitmap, 33 { 34 type S = Self; 35 } 36 37 impl<B> BitmapSlice for BaseSlice<B> 38 where 39 B: Clone + Deref, 40 B::Target: Bitmap, 41 { 42 } 43 44 impl<B> Bitmap for BaseSlice<B> 45 where 46 B: Clone + Deref, 47 B::Target: Bitmap, 48 { 49 /// Mark the memory range specified by the given `offset` (relative to the base offset of 50 /// the slice) and `len` as dirtied. mark_dirty(&self, offset: usize, len: usize)51 fn mark_dirty(&self, offset: usize, len: usize) { 52 // The `Bitmap` operations are supposed to accompany guest memory accesses defined by the 53 // same parameters (i.e. offset & length), so we use simple wrapping arithmetic instead of 54 // performing additional checks. If an overflow would occur, we simply end up marking some 55 // other region as dirty (which is just a false positive) instead of a region that could 56 // not have been accessed to begin with. 57 self.inner 58 .mark_dirty(self.base_offset.wrapping_add(offset), len) 59 } 60 dirty_at(&self, offset: usize) -> bool61 fn dirty_at(&self, offset: usize) -> bool { 62 self.inner.dirty_at(self.base_offset.wrapping_add(offset)) 63 } 64 65 /// Create a new `BitmapSlice` starting from the specified `offset` into the current slice. slice_at(&self, offset: usize) -> Self66 fn slice_at(&self, offset: usize) -> Self { 67 BaseSlice { 68 inner: self.inner.clone(), 69 base_offset: self.base_offset.wrapping_add(offset), 70 } 71 } 72 } 73 74 impl<B> Debug for BaseSlice<B> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 76 // Dummy impl for now. 77 write!(f, "(bitmap slice)") 78 } 79 } 80 81 impl<B: Default> Default for BaseSlice<B> { default() -> Self82 fn default() -> Self { 83 BaseSlice { 84 inner: B::default(), 85 base_offset: 0, 86 } 87 } 88 } 89 90 /// A `BitmapSlice` implementation that wraps a reference to a `Bitmap` object. 91 pub type RefSlice<'a, B> = BaseSlice<&'a B>; 92 93 /// A `BitmapSlice` implementation that uses an `Arc` handle to a `Bitmap` object. 94 pub type ArcSlice<B> = BaseSlice<Arc<B>>; 95 96 #[cfg(test)] 97 mod tests { 98 use super::*; 99 100 use crate::bitmap::tests::{range_is_clean, range_is_dirty, test_bitmap}; 101 use crate::bitmap::AtomicBitmap; 102 103 #[test] test_slice()104 fn test_slice() { 105 let bitmap_size = 0x1_0000; 106 let dirty_offset = 0x1000; 107 let dirty_len = 0x100; 108 109 { 110 let bitmap = AtomicBitmap::new(bitmap_size, 1); 111 let slice1 = bitmap.slice_at(0); 112 let slice2 = bitmap.slice_at(dirty_offset); 113 114 assert!(range_is_clean(&slice1, 0, bitmap_size)); 115 assert!(range_is_clean(&slice2, 0, dirty_len)); 116 117 bitmap.mark_dirty(dirty_offset, dirty_len); 118 119 assert!(range_is_dirty(&slice1, dirty_offset, dirty_len)); 120 assert!(range_is_dirty(&slice2, 0, dirty_len)); 121 } 122 123 { 124 let bitmap = AtomicBitmap::new(bitmap_size, 1); 125 let slice = bitmap.slice_at(0); 126 test_bitmap(&slice); 127 } 128 } 129 } 130