summaryrefslogtreecommitdiff
path: root/crates/alloc_buddy/src/bitvec.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/alloc_buddy/src/bitvec.rs')
-rw-r--r--crates/alloc_buddy/src/bitvec.rs77
1 files changed, 77 insertions, 0 deletions
diff --git a/crates/alloc_buddy/src/bitvec.rs b/crates/alloc_buddy/src/bitvec.rs
new file mode 100644
index 0000000..5cabc5e
--- /dev/null
+++ b/crates/alloc_buddy/src/bitvec.rs
@@ -0,0 +1,77 @@
+use contracts::requires;
+use core::{fmt, mem::transmute};
+
+/// A fixed-length vector of bits used for determining whether a subregion is in the free lists or
+/// not.
+pub struct Bitset([usize]);
+
+impl Bitset {
+ fn from_mut(words: &mut [usize]) -> &mut Bitset {
+ // SAFETY: The types have a newtype relationship.
+ unsafe { transmute(words) }
+ }
+
+ fn from_ref(words: &[usize]) -> &Bitset {
+ // SAFETY: The types have a newtype relationship.
+ unsafe { transmute(words) }
+ }
+
+ /// Retrieves the value of a bit from the Bitset.
+ #[requires(i < self.len())]
+ pub fn get(&self, i: usize) -> SubregionStatus {
+ let word_index = i / usize::BITS as usize;
+ let subword_index = i % usize::BITS as usize;
+ let one_hot = 1 << subword_index;
+ if (self.0[word_index] & one_hot) == 0 {
+ SubregionStatus::NotInFreeList
+ } else {
+ SubregionStatus::InFreeList
+ }
+ }
+
+ /// Returns whether the Bitset is empty.
+ pub fn is_empty(&self) -> bool {
+ self.0.is_empty()
+ }
+
+ /// Returns the number of bits in the Bitset.
+ pub fn len(&self) -> usize {
+ self.0.len() * usize::BITS as usize
+ }
+
+ /// Sets the value of a bit in the Bitset.
+ #[requires(i < self.len())]
+ pub fn set(&mut self, i: usize, status: SubregionStatus) {
+ let word_index = i / usize::BITS as usize;
+ let subword_index = i % usize::BITS as usize;
+ let one_hot = 1 << subword_index;
+ match status {
+ SubregionStatus::NotInFreeList => {
+ self.0[word_index] &= !one_hot;
+ }
+ SubregionStatus::InFreeList => {
+ self.0[word_index] |= one_hot;
+ }
+ }
+ }
+}
+
+impl fmt::Debug for Bitset {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ write!(fmt, "Bitset(")?;
+ for word in &self.0 {
+ write!(fmt, "{word:064b}")?;
+ }
+ write!(fmt, ")")
+ }
+}
+
+/// The status of a subregion, as tracked by `Bitset`.
+#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
+pub enum SubregionStatus {
+ /// The region is not in the free list.
+ NotInFreeList = 0,
+
+ /// The region is in the free list.
+ InFreeList = 1,
+}