Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add used() API in AddressAllocator #95

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
## Upcoming version

### Added

- Added `used()` API in `AddressAllocator` to allow
getting the used memories after `allocate/free()`s

### Changed
### Fixed
### Removed
Expand Down
34 changes: 31 additions & 3 deletions src/address_allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ pub struct AddressAllocator {
// tree will represent a memory location and can have two states either
// `NodeState::Free` or `NodeState::Allocated`.
interval_tree: IntervalTree,
// Used memory space in the address space.
used: usize,
}

impl AddressAllocator {
Expand All @@ -43,6 +45,7 @@ impl AddressAllocator {
Ok(AddressAllocator {
address_space: aux_range,
interval_tree: IntervalTree::new(aux_range),
used: 0,
})
}

Expand All @@ -63,13 +66,25 @@ impl AddressAllocator {
policy: AllocPolicy,
) -> Result<RangeInclusive> {
let constraint = Constraint::new(size, alignment, policy)?;
self.interval_tree.allocate(constraint)
let allocated = self.interval_tree.allocate(constraint)?;
self.used += allocated.len() as usize;
Ok(allocated)
}

/// Deletes the specified memory slot or returns `ResourceNotAvailable` if
/// the node was not allocated before.
pub fn free(&mut self, key: &RangeInclusive) -> Result<()> {
self.interval_tree.free(key)
self.interval_tree.free(key)?;
self.used -= key.len() as usize;
Ok(())
}

/// Returns the used memory size in this allocator.
/// NOTE that due to fragmentations, it's not guaranteed that the next
/// allocate() call after querying the used memory can succeed with
/// allocating all unused memories and it may still return OOM.
pub fn used(&self) -> usize {
self.used
}
}

Expand Down Expand Up @@ -158,20 +173,27 @@ mod tests {
#[test]
fn test_allocate_with_alignment_first_ok() {
let mut pool = AddressAllocator::new(0x1000, 0x1000).unwrap();
assert_eq!(pool.used(), 0);
// Allocate 0x110
assert_eq!(
pool.allocate(0x110, 0x100, AllocPolicy::FirstMatch)
.unwrap(),
RangeInclusive::new(0x1000, 0x110F).unwrap()
);
assert_eq!(pool.used(), 0x110);
// Allocate 0x100
assert_eq!(
pool.allocate(0x100, 0x100, AllocPolicy::FirstMatch)
.unwrap(),
RangeInclusive::new(0x1200, 0x12FF).unwrap()
);
assert_eq!(pool.used(), 0x110 + 0x100);
// Allocate 0x10
assert_eq!(
pool.allocate(0x10, 0x100, AllocPolicy::FirstMatch).unwrap(),
RangeInclusive::new(0x1300, 0x130F).unwrap()
);
assert_eq!(pool.used(), 0x110 + 0x100 + 0x10);
}

#[test]
Expand Down Expand Up @@ -230,18 +252,24 @@ mod tests {
#[test]
fn test_tree_allocate_address_free_and_realloc() {
let mut pool = AddressAllocator::new(0x1000, 0x1000).unwrap();
assert_eq!(pool.used(), 0);
// Allocate 0x800
assert_eq!(
pool.allocate(0x800, 0x100, AllocPolicy::FirstMatch)
.unwrap(),
RangeInclusive::new(0x1000, 0x17FF).unwrap()
);

assert_eq!(pool.used(), 0x800);
// Free 0x800
let _ = pool.free(&RangeInclusive::new(0x1000, 0x17FF).unwrap());
assert_eq!(pool.used(), 0);
// Allocate 0x800 again
assert_eq!(
pool.allocate(0x800, 0x100, AllocPolicy::FirstMatch)
.unwrap(),
RangeInclusive::new(0x1000, 0x17FF).unwrap()
);
assert_eq!(pool.used(), 0x800);
}

#[test]
Expand Down