1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2018 The ChromiumOS Authors 2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file. 4*bb4ee6a4SAndroid Build Coastguard Worker 5*bb4ee6a4SAndroid Build Coastguard Worker use std::cmp; 6*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeSet; 7*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::HashMap; 8*bb4ee6a4SAndroid Build Coastguard Worker use std::ops::Bound; 9*bb4ee6a4SAndroid Build Coastguard Worker 10*bb4ee6a4SAndroid Build Coastguard Worker use crate::AddressRange; 11*bb4ee6a4SAndroid Build Coastguard Worker use crate::Alloc; 12*bb4ee6a4SAndroid Build Coastguard Worker use crate::Error; 13*bb4ee6a4SAndroid Build Coastguard Worker use crate::Result; 14*bb4ee6a4SAndroid Build Coastguard Worker 15*bb4ee6a4SAndroid Build Coastguard Worker /// Manages allocating address ranges. 16*bb4ee6a4SAndroid Build Coastguard Worker /// Use `AddressAllocator` whenever an address range needs to be allocated to different users. 17*bb4ee6a4SAndroid Build Coastguard Worker /// Allocations must be uniquely tagged with an Alloc enum, which can be used for lookup. 18*bb4ee6a4SAndroid Build Coastguard Worker /// An human-readable tag String must also be provided for debugging / reference. 19*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Eq, PartialEq)] 20*bb4ee6a4SAndroid Build Coastguard Worker pub struct AddressAllocator { 21*bb4ee6a4SAndroid Build Coastguard Worker /// The list of pools from which address are allocated. The union 22*bb4ee6a4SAndroid Build Coastguard Worker /// of all regions from |allocs| and |regions| equals the pools. 23*bb4ee6a4SAndroid Build Coastguard Worker pools: Vec<AddressRange>, 24*bb4ee6a4SAndroid Build Coastguard Worker min_align: u64, 25*bb4ee6a4SAndroid Build Coastguard Worker preferred_align: u64, 26*bb4ee6a4SAndroid Build Coastguard Worker /// The region that is allocated. 27*bb4ee6a4SAndroid Build Coastguard Worker allocs: HashMap<Alloc, (AddressRange, String)>, 28*bb4ee6a4SAndroid Build Coastguard Worker /// The region that is not allocated yet. 29*bb4ee6a4SAndroid Build Coastguard Worker regions: BTreeSet<AddressRange>, 30*bb4ee6a4SAndroid Build Coastguard Worker } 31*bb4ee6a4SAndroid Build Coastguard Worker 32*bb4ee6a4SAndroid Build Coastguard Worker impl AddressAllocator { 33*bb4ee6a4SAndroid Build Coastguard Worker /// Creates a new `AddressAllocator` for managing a range of addresses. 34*bb4ee6a4SAndroid Build Coastguard Worker /// Can return an error if `pool` is empty or if alignment isn't a power of two. 35*bb4ee6a4SAndroid Build Coastguard Worker /// 36*bb4ee6a4SAndroid Build Coastguard Worker /// * `pool` - The address range to allocate from. 37*bb4ee6a4SAndroid Build Coastguard Worker /// * `min_align` - The minimum size of an address region to align to, defaults to four. 38*bb4ee6a4SAndroid Build Coastguard Worker /// * `preferred_align` - The preferred alignment of an address region, used if possible. 39*bb4ee6a4SAndroid Build Coastguard Worker /// 40*bb4ee6a4SAndroid Build Coastguard Worker /// If an allocation cannot be satisfied with the preferred alignment, the minimum alignment 41*bb4ee6a4SAndroid Build Coastguard Worker /// will be used instead. new( pool: AddressRange, min_align: Option<u64>, preferred_align: Option<u64>, ) -> Result<Self>42*bb4ee6a4SAndroid Build Coastguard Worker pub fn new( 43*bb4ee6a4SAndroid Build Coastguard Worker pool: AddressRange, 44*bb4ee6a4SAndroid Build Coastguard Worker min_align: Option<u64>, 45*bb4ee6a4SAndroid Build Coastguard Worker preferred_align: Option<u64>, 46*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<Self> { 47*bb4ee6a4SAndroid Build Coastguard Worker Self::new_from_list(vec![pool], min_align, preferred_align) 48*bb4ee6a4SAndroid Build Coastguard Worker } 49*bb4ee6a4SAndroid Build Coastguard Worker 50*bb4ee6a4SAndroid Build Coastguard Worker /// Creates a new `AddressAllocator` for managing a range of addresses. 51*bb4ee6a4SAndroid Build Coastguard Worker /// Can return `None` if all pools are empty alignment isn't a power of two. 52*bb4ee6a4SAndroid Build Coastguard Worker /// 53*bb4ee6a4SAndroid Build Coastguard Worker /// * `pools` - The list of pools to initialize the allocator with. 54*bb4ee6a4SAndroid Build Coastguard Worker /// * `min_align` - The minimum size of an address region to align to, defaults to four. 55*bb4ee6a4SAndroid Build Coastguard Worker /// * `preferred_align` - The preferred alignment of an address region, used if possible. 56*bb4ee6a4SAndroid Build Coastguard Worker /// 57*bb4ee6a4SAndroid Build Coastguard Worker /// If an allocation cannot be satisfied with the preferred alignment, the minimum alignment 58*bb4ee6a4SAndroid Build Coastguard Worker /// will be used instead. new_from_list<T>( pools: T, min_align: Option<u64>, preferred_align: Option<u64>, ) -> Result<Self> where T: IntoIterator<Item = AddressRange>,59*bb4ee6a4SAndroid Build Coastguard Worker pub fn new_from_list<T>( 60*bb4ee6a4SAndroid Build Coastguard Worker pools: T, 61*bb4ee6a4SAndroid Build Coastguard Worker min_align: Option<u64>, 62*bb4ee6a4SAndroid Build Coastguard Worker preferred_align: Option<u64>, 63*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<Self> 64*bb4ee6a4SAndroid Build Coastguard Worker where 65*bb4ee6a4SAndroid Build Coastguard Worker T: IntoIterator<Item = AddressRange>, 66*bb4ee6a4SAndroid Build Coastguard Worker { 67*bb4ee6a4SAndroid Build Coastguard Worker let pools: Vec<AddressRange> = pools.into_iter().filter(|p| !p.is_empty()).collect(); 68*bb4ee6a4SAndroid Build Coastguard Worker 69*bb4ee6a4SAndroid Build Coastguard Worker let min_align = min_align.unwrap_or(4); 70*bb4ee6a4SAndroid Build Coastguard Worker if !min_align.is_power_of_two() || min_align == 0 { 71*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::BadAlignment); 72*bb4ee6a4SAndroid Build Coastguard Worker } 73*bb4ee6a4SAndroid Build Coastguard Worker 74*bb4ee6a4SAndroid Build Coastguard Worker let preferred_align = preferred_align.unwrap_or(min_align); 75*bb4ee6a4SAndroid Build Coastguard Worker if !preferred_align.is_power_of_two() || preferred_align < min_align { 76*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::BadAlignment); 77*bb4ee6a4SAndroid Build Coastguard Worker } 78*bb4ee6a4SAndroid Build Coastguard Worker 79*bb4ee6a4SAndroid Build Coastguard Worker let mut regions = BTreeSet::new(); 80*bb4ee6a4SAndroid Build Coastguard Worker for r in pools.iter() { 81*bb4ee6a4SAndroid Build Coastguard Worker regions.insert(*r); 82*bb4ee6a4SAndroid Build Coastguard Worker } 83*bb4ee6a4SAndroid Build Coastguard Worker Ok(AddressAllocator { 84*bb4ee6a4SAndroid Build Coastguard Worker pools, 85*bb4ee6a4SAndroid Build Coastguard Worker min_align, 86*bb4ee6a4SAndroid Build Coastguard Worker preferred_align, 87*bb4ee6a4SAndroid Build Coastguard Worker allocs: HashMap::new(), 88*bb4ee6a4SAndroid Build Coastguard Worker regions, 89*bb4ee6a4SAndroid Build Coastguard Worker }) 90*bb4ee6a4SAndroid Build Coastguard Worker } 91*bb4ee6a4SAndroid Build Coastguard Worker 92*bb4ee6a4SAndroid Build Coastguard Worker /// Gets the regions managed by the allocator. 93*bb4ee6a4SAndroid Build Coastguard Worker /// 94*bb4ee6a4SAndroid Build Coastguard Worker /// This returns the original `pools` value provided to `AddressAllocator::new()`. pools(&self) -> &[AddressRange]95*bb4ee6a4SAndroid Build Coastguard Worker pub fn pools(&self) -> &[AddressRange] { 96*bb4ee6a4SAndroid Build Coastguard Worker &self.pools 97*bb4ee6a4SAndroid Build Coastguard Worker } 98*bb4ee6a4SAndroid Build Coastguard Worker internal_allocate_from_slot( &mut self, slot: AddressRange, range: AddressRange, alloc: Alloc, tag: String, ) -> Result<u64>99*bb4ee6a4SAndroid Build Coastguard Worker fn internal_allocate_from_slot( 100*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 101*bb4ee6a4SAndroid Build Coastguard Worker slot: AddressRange, 102*bb4ee6a4SAndroid Build Coastguard Worker range: AddressRange, 103*bb4ee6a4SAndroid Build Coastguard Worker alloc: Alloc, 104*bb4ee6a4SAndroid Build Coastguard Worker tag: String, 105*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<u64> { 106*bb4ee6a4SAndroid Build Coastguard Worker let slot_was_present = self.regions.remove(&slot); 107*bb4ee6a4SAndroid Build Coastguard Worker assert!(slot_was_present); 108*bb4ee6a4SAndroid Build Coastguard Worker 109*bb4ee6a4SAndroid Build Coastguard Worker let (before, after) = slot.non_overlapping_ranges(range); 110*bb4ee6a4SAndroid Build Coastguard Worker 111*bb4ee6a4SAndroid Build Coastguard Worker if !before.is_empty() { 112*bb4ee6a4SAndroid Build Coastguard Worker self.regions.insert(before); 113*bb4ee6a4SAndroid Build Coastguard Worker } 114*bb4ee6a4SAndroid Build Coastguard Worker if !after.is_empty() { 115*bb4ee6a4SAndroid Build Coastguard Worker self.regions.insert(after); 116*bb4ee6a4SAndroid Build Coastguard Worker } 117*bb4ee6a4SAndroid Build Coastguard Worker 118*bb4ee6a4SAndroid Build Coastguard Worker self.allocs.insert(alloc, (range, tag)); 119*bb4ee6a4SAndroid Build Coastguard Worker Ok(range.start) 120*bb4ee6a4SAndroid Build Coastguard Worker } 121*bb4ee6a4SAndroid Build Coastguard Worker internal_allocate_with_align( &mut self, size: u64, alloc: Alloc, tag: String, alignment: u64, reverse: bool, ) -> Result<u64>122*bb4ee6a4SAndroid Build Coastguard Worker fn internal_allocate_with_align( 123*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 124*bb4ee6a4SAndroid Build Coastguard Worker size: u64, 125*bb4ee6a4SAndroid Build Coastguard Worker alloc: Alloc, 126*bb4ee6a4SAndroid Build Coastguard Worker tag: String, 127*bb4ee6a4SAndroid Build Coastguard Worker alignment: u64, 128*bb4ee6a4SAndroid Build Coastguard Worker reverse: bool, 129*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<u64> { 130*bb4ee6a4SAndroid Build Coastguard Worker let alignment = cmp::max(self.min_align, alignment); 131*bb4ee6a4SAndroid Build Coastguard Worker 132*bb4ee6a4SAndroid Build Coastguard Worker if self.allocs.contains_key(&alloc) { 133*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::ExistingAlloc(alloc)); 134*bb4ee6a4SAndroid Build Coastguard Worker } 135*bb4ee6a4SAndroid Build Coastguard Worker if size == 0 { 136*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::AllocSizeZero); 137*bb4ee6a4SAndroid Build Coastguard Worker } 138*bb4ee6a4SAndroid Build Coastguard Worker if !alignment.is_power_of_two() { 139*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::BadAlignment); 140*bb4ee6a4SAndroid Build Coastguard Worker } 141*bb4ee6a4SAndroid Build Coastguard Worker 142*bb4ee6a4SAndroid Build Coastguard Worker let region = if !reverse { 143*bb4ee6a4SAndroid Build Coastguard Worker // finds first region matching alignment and size. 144*bb4ee6a4SAndroid Build Coastguard Worker self.regions 145*bb4ee6a4SAndroid Build Coastguard Worker .iter() 146*bb4ee6a4SAndroid Build Coastguard Worker .find(|range| { 147*bb4ee6a4SAndroid Build Coastguard Worker match range.start % alignment { 148*bb4ee6a4SAndroid Build Coastguard Worker 0 => range.start.checked_add(size - 1), 149*bb4ee6a4SAndroid Build Coastguard Worker r => range.start.checked_add(size - 1 + alignment - r), 150*bb4ee6a4SAndroid Build Coastguard Worker } 151*bb4ee6a4SAndroid Build Coastguard Worker .map_or(false, |end| end <= range.end) 152*bb4ee6a4SAndroid Build Coastguard Worker }) 153*bb4ee6a4SAndroid Build Coastguard Worker .cloned() 154*bb4ee6a4SAndroid Build Coastguard Worker } else { 155*bb4ee6a4SAndroid Build Coastguard Worker // finds last region matching alignment and size. 156*bb4ee6a4SAndroid Build Coastguard Worker self.regions 157*bb4ee6a4SAndroid Build Coastguard Worker .iter() 158*bb4ee6a4SAndroid Build Coastguard Worker .rev() 159*bb4ee6a4SAndroid Build Coastguard Worker .find(|range| { 160*bb4ee6a4SAndroid Build Coastguard Worker range 161*bb4ee6a4SAndroid Build Coastguard Worker .end 162*bb4ee6a4SAndroid Build Coastguard Worker .checked_sub(size - 1) 163*bb4ee6a4SAndroid Build Coastguard Worker .map_or(false, |start| start & !(alignment - 1) >= range.start) 164*bb4ee6a4SAndroid Build Coastguard Worker }) 165*bb4ee6a4SAndroid Build Coastguard Worker .cloned() 166*bb4ee6a4SAndroid Build Coastguard Worker }; 167*bb4ee6a4SAndroid Build Coastguard Worker 168*bb4ee6a4SAndroid Build Coastguard Worker match region { 169*bb4ee6a4SAndroid Build Coastguard Worker Some(slot) => { 170*bb4ee6a4SAndroid Build Coastguard Worker let start = if !reverse { 171*bb4ee6a4SAndroid Build Coastguard Worker match slot.start % alignment { 172*bb4ee6a4SAndroid Build Coastguard Worker 0 => slot.start, 173*bb4ee6a4SAndroid Build Coastguard Worker r => slot.start + alignment - r, 174*bb4ee6a4SAndroid Build Coastguard Worker } 175*bb4ee6a4SAndroid Build Coastguard Worker } else { 176*bb4ee6a4SAndroid Build Coastguard Worker (slot.end - (size - 1)) & !(alignment - 1) 177*bb4ee6a4SAndroid Build Coastguard Worker }; 178*bb4ee6a4SAndroid Build Coastguard Worker let end = start + size - 1; 179*bb4ee6a4SAndroid Build Coastguard Worker let range = AddressRange { start, end }; 180*bb4ee6a4SAndroid Build Coastguard Worker 181*bb4ee6a4SAndroid Build Coastguard Worker self.internal_allocate_from_slot(slot, range, alloc, tag) 182*bb4ee6a4SAndroid Build Coastguard Worker } 183*bb4ee6a4SAndroid Build Coastguard Worker None => Err(Error::OutOfSpace), 184*bb4ee6a4SAndroid Build Coastguard Worker } 185*bb4ee6a4SAndroid Build Coastguard Worker } 186*bb4ee6a4SAndroid Build Coastguard Worker 187*bb4ee6a4SAndroid Build Coastguard Worker /// Allocates a range of addresses from the reverse managed region with an optional tag 188*bb4ee6a4SAndroid Build Coastguard Worker /// and minimal alignment. Returns allocated_address. (allocated_address, size, tag) 189*bb4ee6a4SAndroid Build Coastguard Worker /// can be retrieved through the `get` method. reverse_allocate_with_align( &mut self, size: u64, alloc: Alloc, tag: String, alignment: u64, ) -> Result<u64>190*bb4ee6a4SAndroid Build Coastguard Worker pub fn reverse_allocate_with_align( 191*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 192*bb4ee6a4SAndroid Build Coastguard Worker size: u64, 193*bb4ee6a4SAndroid Build Coastguard Worker alloc: Alloc, 194*bb4ee6a4SAndroid Build Coastguard Worker tag: String, 195*bb4ee6a4SAndroid Build Coastguard Worker alignment: u64, 196*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<u64> { 197*bb4ee6a4SAndroid Build Coastguard Worker self.internal_allocate_with_align(size, alloc, tag, alignment, true) 198*bb4ee6a4SAndroid Build Coastguard Worker } 199*bb4ee6a4SAndroid Build Coastguard Worker 200*bb4ee6a4SAndroid Build Coastguard Worker /// Allocates a range of addresses, preferring to allocate from high rather than low addresses. reverse_allocate(&mut self, size: u64, alloc: Alloc, tag: String) -> Result<u64>201*bb4ee6a4SAndroid Build Coastguard Worker pub fn reverse_allocate(&mut self, size: u64, alloc: Alloc, tag: String) -> Result<u64> { 202*bb4ee6a4SAndroid Build Coastguard Worker if let Ok(pref_alloc) = 203*bb4ee6a4SAndroid Build Coastguard Worker self.reverse_allocate_with_align(size, alloc, tag.clone(), self.preferred_align) 204*bb4ee6a4SAndroid Build Coastguard Worker { 205*bb4ee6a4SAndroid Build Coastguard Worker return Ok(pref_alloc); 206*bb4ee6a4SAndroid Build Coastguard Worker } 207*bb4ee6a4SAndroid Build Coastguard Worker self.reverse_allocate_with_align(size, alloc, tag, self.min_align) 208*bb4ee6a4SAndroid Build Coastguard Worker } 209*bb4ee6a4SAndroid Build Coastguard Worker 210*bb4ee6a4SAndroid Build Coastguard Worker /// Allocates a range of addresses from the managed region with an optional tag 211*bb4ee6a4SAndroid Build Coastguard Worker /// and minimal alignment. Returns allocated_address. (allocated_address, size, tag) 212*bb4ee6a4SAndroid Build Coastguard Worker /// can be retrieved through the `get` method. allocate_with_align( &mut self, size: u64, alloc: Alloc, tag: String, alignment: u64, ) -> Result<u64>213*bb4ee6a4SAndroid Build Coastguard Worker pub fn allocate_with_align( 214*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 215*bb4ee6a4SAndroid Build Coastguard Worker size: u64, 216*bb4ee6a4SAndroid Build Coastguard Worker alloc: Alloc, 217*bb4ee6a4SAndroid Build Coastguard Worker tag: String, 218*bb4ee6a4SAndroid Build Coastguard Worker alignment: u64, 219*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<u64> { 220*bb4ee6a4SAndroid Build Coastguard Worker self.internal_allocate_with_align(size, alloc, tag, alignment, false) 221*bb4ee6a4SAndroid Build Coastguard Worker } 222*bb4ee6a4SAndroid Build Coastguard Worker allocate(&mut self, size: u64, alloc: Alloc, tag: String) -> Result<u64>223*bb4ee6a4SAndroid Build Coastguard Worker pub fn allocate(&mut self, size: u64, alloc: Alloc, tag: String) -> Result<u64> { 224*bb4ee6a4SAndroid Build Coastguard Worker if let Ok(pref_alloc) = 225*bb4ee6a4SAndroid Build Coastguard Worker self.allocate_with_align(size, alloc, tag.clone(), self.preferred_align) 226*bb4ee6a4SAndroid Build Coastguard Worker { 227*bb4ee6a4SAndroid Build Coastguard Worker return Ok(pref_alloc); 228*bb4ee6a4SAndroid Build Coastguard Worker } 229*bb4ee6a4SAndroid Build Coastguard Worker self.allocate_with_align(size, alloc, tag, self.min_align) 230*bb4ee6a4SAndroid Build Coastguard Worker } 231*bb4ee6a4SAndroid Build Coastguard Worker 232*bb4ee6a4SAndroid Build Coastguard Worker /// Allocates a range of addresses from the managed region with an optional tag 233*bb4ee6a4SAndroid Build Coastguard Worker /// and required location. Allocation alignment is not enforced. 234*bb4ee6a4SAndroid Build Coastguard Worker /// Returns OutOfSpace if requested range is not available or ExistingAlloc if the requested 235*bb4ee6a4SAndroid Build Coastguard Worker /// range overlaps an existing allocation. allocate_at(&mut self, range: AddressRange, alloc: Alloc, tag: String) -> Result<()>236*bb4ee6a4SAndroid Build Coastguard Worker pub fn allocate_at(&mut self, range: AddressRange, alloc: Alloc, tag: String) -> Result<()> { 237*bb4ee6a4SAndroid Build Coastguard Worker if self.allocs.contains_key(&alloc) { 238*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::ExistingAlloc(alloc)); 239*bb4ee6a4SAndroid Build Coastguard Worker } 240*bb4ee6a4SAndroid Build Coastguard Worker 241*bb4ee6a4SAndroid Build Coastguard Worker if range.is_empty() { 242*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::AllocSizeZero); 243*bb4ee6a4SAndroid Build Coastguard Worker } 244*bb4ee6a4SAndroid Build Coastguard Worker 245*bb4ee6a4SAndroid Build Coastguard Worker match self 246*bb4ee6a4SAndroid Build Coastguard Worker .regions 247*bb4ee6a4SAndroid Build Coastguard Worker .iter() 248*bb4ee6a4SAndroid Build Coastguard Worker .find(|avail_range| avail_range.contains_range(range)) 249*bb4ee6a4SAndroid Build Coastguard Worker { 250*bb4ee6a4SAndroid Build Coastguard Worker Some(&slot) => { 251*bb4ee6a4SAndroid Build Coastguard Worker let _address = self.internal_allocate_from_slot(slot, range, alloc, tag)?; 252*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 253*bb4ee6a4SAndroid Build Coastguard Worker } 254*bb4ee6a4SAndroid Build Coastguard Worker None => { 255*bb4ee6a4SAndroid Build Coastguard Worker if let Some(existing_alloc) = self.find_overlapping(range) { 256*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::ExistingAlloc(existing_alloc)) 257*bb4ee6a4SAndroid Build Coastguard Worker } else { 258*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::OutOfSpace) 259*bb4ee6a4SAndroid Build Coastguard Worker } 260*bb4ee6a4SAndroid Build Coastguard Worker } 261*bb4ee6a4SAndroid Build Coastguard Worker } 262*bb4ee6a4SAndroid Build Coastguard Worker } 263*bb4ee6a4SAndroid Build Coastguard Worker 264*bb4ee6a4SAndroid Build Coastguard Worker /// Releases exising allocation back to free pool and returns the range that was released. release(&mut self, alloc: Alloc) -> Result<AddressRange>265*bb4ee6a4SAndroid Build Coastguard Worker pub fn release(&mut self, alloc: Alloc) -> Result<AddressRange> { 266*bb4ee6a4SAndroid Build Coastguard Worker if let Some((range, _tag)) = self.allocs.remove(&alloc) { 267*bb4ee6a4SAndroid Build Coastguard Worker self.insert_at(range)?; 268*bb4ee6a4SAndroid Build Coastguard Worker Ok(range) 269*bb4ee6a4SAndroid Build Coastguard Worker } else { 270*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::BadAlloc(alloc)) 271*bb4ee6a4SAndroid Build Coastguard Worker } 272*bb4ee6a4SAndroid Build Coastguard Worker } 273*bb4ee6a4SAndroid Build Coastguard Worker 274*bb4ee6a4SAndroid Build Coastguard Worker /// Release a allocation contains the value. release_containing(&mut self, value: u64) -> Result<AddressRange>275*bb4ee6a4SAndroid Build Coastguard Worker pub fn release_containing(&mut self, value: u64) -> Result<AddressRange> { 276*bb4ee6a4SAndroid Build Coastguard Worker if let Some(alloc) = self.find_overlapping(AddressRange { 277*bb4ee6a4SAndroid Build Coastguard Worker start: value, 278*bb4ee6a4SAndroid Build Coastguard Worker end: value, 279*bb4ee6a4SAndroid Build Coastguard Worker }) { 280*bb4ee6a4SAndroid Build Coastguard Worker self.release(alloc) 281*bb4ee6a4SAndroid Build Coastguard Worker } else { 282*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::OutOfSpace) 283*bb4ee6a4SAndroid Build Coastguard Worker } 284*bb4ee6a4SAndroid Build Coastguard Worker } 285*bb4ee6a4SAndroid Build Coastguard Worker 286*bb4ee6a4SAndroid Build Coastguard Worker // Find an existing allocation that overlaps the region defined by `range`. If more 287*bb4ee6a4SAndroid Build Coastguard Worker // than one allocation overlaps the given region, any of them may be returned, since the HashMap 288*bb4ee6a4SAndroid Build Coastguard Worker // iterator is not ordered in any particular way. find_overlapping(&self, range: AddressRange) -> Option<Alloc>289*bb4ee6a4SAndroid Build Coastguard Worker fn find_overlapping(&self, range: AddressRange) -> Option<Alloc> { 290*bb4ee6a4SAndroid Build Coastguard Worker if range.is_empty() { 291*bb4ee6a4SAndroid Build Coastguard Worker return None; 292*bb4ee6a4SAndroid Build Coastguard Worker } 293*bb4ee6a4SAndroid Build Coastguard Worker 294*bb4ee6a4SAndroid Build Coastguard Worker self.allocs 295*bb4ee6a4SAndroid Build Coastguard Worker .iter() 296*bb4ee6a4SAndroid Build Coastguard Worker .find(|(_, &(alloc_range, _))| alloc_range.overlaps(range)) 297*bb4ee6a4SAndroid Build Coastguard Worker .map(|(&alloc, _)| alloc) 298*bb4ee6a4SAndroid Build Coastguard Worker } 299*bb4ee6a4SAndroid Build Coastguard Worker 300*bb4ee6a4SAndroid Build Coastguard Worker // Return the max address of the allocated address ranges. get_max_addr(&self) -> u64301*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_max_addr(&self) -> u64 { 302*bb4ee6a4SAndroid Build Coastguard Worker self.regions.iter().fold(0, |x, range| x.max(range.end)) 303*bb4ee6a4SAndroid Build Coastguard Worker } 304*bb4ee6a4SAndroid Build Coastguard Worker 305*bb4ee6a4SAndroid Build Coastguard Worker /// Returns allocation associated with `alloc`, or None if no such allocation exists. get(&self, alloc: &Alloc) -> Option<&(AddressRange, String)>306*bb4ee6a4SAndroid Build Coastguard Worker pub fn get(&self, alloc: &Alloc) -> Option<&(AddressRange, String)> { 307*bb4ee6a4SAndroid Build Coastguard Worker self.allocs.get(alloc) 308*bb4ee6a4SAndroid Build Coastguard Worker } 309*bb4ee6a4SAndroid Build Coastguard Worker 310*bb4ee6a4SAndroid Build Coastguard Worker /// Insert range of addresses into the pool, coalescing neighboring regions. insert_at(&mut self, mut slot: AddressRange) -> Result<()>311*bb4ee6a4SAndroid Build Coastguard Worker fn insert_at(&mut self, mut slot: AddressRange) -> Result<()> { 312*bb4ee6a4SAndroid Build Coastguard Worker if slot.is_empty() { 313*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::AllocSizeZero); 314*bb4ee6a4SAndroid Build Coastguard Worker } 315*bb4ee6a4SAndroid Build Coastguard Worker 316*bb4ee6a4SAndroid Build Coastguard Worker // Find the region with the highest starting address that is at most 317*bb4ee6a4SAndroid Build Coastguard Worker // |slot.start|. Check if it overlaps with |slot|, or if it is adjacent to 318*bb4ee6a4SAndroid Build Coastguard Worker // (and thus can be coalesced with) |slot|. 319*bb4ee6a4SAndroid Build Coastguard Worker let mut smaller_merge = None; 320*bb4ee6a4SAndroid Build Coastguard Worker if let Some(smaller) = self 321*bb4ee6a4SAndroid Build Coastguard Worker .regions 322*bb4ee6a4SAndroid Build Coastguard Worker .range((Bound::Unbounded, Bound::Included(slot))) 323*bb4ee6a4SAndroid Build Coastguard Worker .max() 324*bb4ee6a4SAndroid Build Coastguard Worker { 325*bb4ee6a4SAndroid Build Coastguard Worker // If there is overflow, then |smaller| covers up through u64::MAX 326*bb4ee6a4SAndroid Build Coastguard Worker let next_addr = smaller 327*bb4ee6a4SAndroid Build Coastguard Worker .end 328*bb4ee6a4SAndroid Build Coastguard Worker .checked_add(1) 329*bb4ee6a4SAndroid Build Coastguard Worker .ok_or(Error::RegionOverlap(slot))?; 330*bb4ee6a4SAndroid Build Coastguard Worker match next_addr.cmp(&slot.start) { 331*bb4ee6a4SAndroid Build Coastguard Worker cmp::Ordering::Less => (), 332*bb4ee6a4SAndroid Build Coastguard Worker cmp::Ordering::Equal => smaller_merge = Some(*smaller), 333*bb4ee6a4SAndroid Build Coastguard Worker cmp::Ordering::Greater => return Err(Error::RegionOverlap(slot)), 334*bb4ee6a4SAndroid Build Coastguard Worker } 335*bb4ee6a4SAndroid Build Coastguard Worker } 336*bb4ee6a4SAndroid Build Coastguard Worker 337*bb4ee6a4SAndroid Build Coastguard Worker // Find the region with the smallest starting address that is greater than 338*bb4ee6a4SAndroid Build Coastguard Worker // |slot.start|. Check if it overlaps with |slot|, or if it is adjacent to 339*bb4ee6a4SAndroid Build Coastguard Worker // (and thus can be coalesced with) |slot|. 340*bb4ee6a4SAndroid Build Coastguard Worker let mut larger_merge = None; 341*bb4ee6a4SAndroid Build Coastguard Worker if let Some(larger) = self 342*bb4ee6a4SAndroid Build Coastguard Worker .regions 343*bb4ee6a4SAndroid Build Coastguard Worker .range((Bound::Excluded(slot), Bound::Unbounded)) 344*bb4ee6a4SAndroid Build Coastguard Worker .min() 345*bb4ee6a4SAndroid Build Coastguard Worker { 346*bb4ee6a4SAndroid Build Coastguard Worker // If there is underflow, then |larger| covers down through 0 347*bb4ee6a4SAndroid Build Coastguard Worker let prev_addr = larger 348*bb4ee6a4SAndroid Build Coastguard Worker .start 349*bb4ee6a4SAndroid Build Coastguard Worker .checked_sub(1) 350*bb4ee6a4SAndroid Build Coastguard Worker .ok_or(Error::RegionOverlap(slot))?; 351*bb4ee6a4SAndroid Build Coastguard Worker match slot.end.cmp(&prev_addr) { 352*bb4ee6a4SAndroid Build Coastguard Worker cmp::Ordering::Less => (), 353*bb4ee6a4SAndroid Build Coastguard Worker cmp::Ordering::Equal => larger_merge = Some(*larger), 354*bb4ee6a4SAndroid Build Coastguard Worker cmp::Ordering::Greater => return Err(Error::RegionOverlap(slot)), 355*bb4ee6a4SAndroid Build Coastguard Worker } 356*bb4ee6a4SAndroid Build Coastguard Worker } 357*bb4ee6a4SAndroid Build Coastguard Worker 358*bb4ee6a4SAndroid Build Coastguard Worker if let Some(smaller) = smaller_merge { 359*bb4ee6a4SAndroid Build Coastguard Worker self.regions.remove(&smaller); 360*bb4ee6a4SAndroid Build Coastguard Worker slot.start = smaller.start; 361*bb4ee6a4SAndroid Build Coastguard Worker } 362*bb4ee6a4SAndroid Build Coastguard Worker if let Some(larger) = larger_merge { 363*bb4ee6a4SAndroid Build Coastguard Worker self.regions.remove(&larger); 364*bb4ee6a4SAndroid Build Coastguard Worker slot.end = larger.end; 365*bb4ee6a4SAndroid Build Coastguard Worker } 366*bb4ee6a4SAndroid Build Coastguard Worker self.regions.insert(slot); 367*bb4ee6a4SAndroid Build Coastguard Worker 368*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 369*bb4ee6a4SAndroid Build Coastguard Worker } 370*bb4ee6a4SAndroid Build Coastguard Worker 371*bb4ee6a4SAndroid Build Coastguard Worker /// Returns an address from associated PCI `alloc` given an allocation offset and size. address_from_pci_offset(&self, alloc: Alloc, offset: u64, size: u64) -> Result<u64>372*bb4ee6a4SAndroid Build Coastguard Worker pub fn address_from_pci_offset(&self, alloc: Alloc, offset: u64, size: u64) -> Result<u64> { 373*bb4ee6a4SAndroid Build Coastguard Worker match alloc { 374*bb4ee6a4SAndroid Build Coastguard Worker Alloc::PciBar { .. } => (), 375*bb4ee6a4SAndroid Build Coastguard Worker _ => return Err(Error::InvalidAlloc(alloc)), 376*bb4ee6a4SAndroid Build Coastguard Worker }; 377*bb4ee6a4SAndroid Build Coastguard Worker 378*bb4ee6a4SAndroid Build Coastguard Worker match self.allocs.get(&alloc) { 379*bb4ee6a4SAndroid Build Coastguard Worker Some((pci_bar_range, _)) => { 380*bb4ee6a4SAndroid Build Coastguard Worker let address = pci_bar_range 381*bb4ee6a4SAndroid Build Coastguard Worker .start 382*bb4ee6a4SAndroid Build Coastguard Worker .checked_add(offset) 383*bb4ee6a4SAndroid Build Coastguard Worker .ok_or(Error::OutOfBounds)?; 384*bb4ee6a4SAndroid Build Coastguard Worker let offset_range = 385*bb4ee6a4SAndroid Build Coastguard Worker AddressRange::from_start_and_size(address, size).ok_or(Error::OutOfBounds)?; 386*bb4ee6a4SAndroid Build Coastguard Worker if pci_bar_range.contains_range(offset_range) { 387*bb4ee6a4SAndroid Build Coastguard Worker Ok(address) 388*bb4ee6a4SAndroid Build Coastguard Worker } else { 389*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::OutOfBounds) 390*bb4ee6a4SAndroid Build Coastguard Worker } 391*bb4ee6a4SAndroid Build Coastguard Worker } 392*bb4ee6a4SAndroid Build Coastguard Worker None => Err(Error::InvalidAlloc(alloc)), 393*bb4ee6a4SAndroid Build Coastguard Worker } 394*bb4ee6a4SAndroid Build Coastguard Worker } 395*bb4ee6a4SAndroid Build Coastguard Worker } 396*bb4ee6a4SAndroid Build Coastguard Worker 397*bb4ee6a4SAndroid Build Coastguard Worker /// Contains a set of `AddressAllocator`s for allocating address ranges. 398*bb4ee6a4SAndroid Build Coastguard Worker /// When attempting an allocation, each allocator will be tried in order until 399*bb4ee6a4SAndroid Build Coastguard Worker /// the allocation is successful. 400*bb4ee6a4SAndroid Build Coastguard Worker /// See `AddressAllocator` for function documentation. 401*bb4ee6a4SAndroid Build Coastguard Worker pub struct AddressAllocatorSet<'a> { 402*bb4ee6a4SAndroid Build Coastguard Worker allocators: &'a mut [AddressAllocator], 403*bb4ee6a4SAndroid Build Coastguard Worker } 404*bb4ee6a4SAndroid Build Coastguard Worker 405*bb4ee6a4SAndroid Build Coastguard Worker impl<'a> AddressAllocatorSet<'a> { new(allocators: &'a mut [AddressAllocator]) -> Self406*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(allocators: &'a mut [AddressAllocator]) -> Self { 407*bb4ee6a4SAndroid Build Coastguard Worker AddressAllocatorSet { allocators } 408*bb4ee6a4SAndroid Build Coastguard Worker } 409*bb4ee6a4SAndroid Build Coastguard Worker allocate_with_align( &mut self, size: u64, alloc: Alloc, tag: String, alignment: u64, ) -> Result<u64>410*bb4ee6a4SAndroid Build Coastguard Worker pub fn allocate_with_align( 411*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 412*bb4ee6a4SAndroid Build Coastguard Worker size: u64, 413*bb4ee6a4SAndroid Build Coastguard Worker alloc: Alloc, 414*bb4ee6a4SAndroid Build Coastguard Worker tag: String, 415*bb4ee6a4SAndroid Build Coastguard Worker alignment: u64, 416*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<u64> { 417*bb4ee6a4SAndroid Build Coastguard Worker let mut last_res = Err(Error::OutOfSpace); 418*bb4ee6a4SAndroid Build Coastguard Worker for allocator in self.allocators.iter_mut() { 419*bb4ee6a4SAndroid Build Coastguard Worker last_res = allocator.allocate_with_align(size, alloc, tag.clone(), alignment); 420*bb4ee6a4SAndroid Build Coastguard Worker if last_res.is_ok() { 421*bb4ee6a4SAndroid Build Coastguard Worker return last_res; 422*bb4ee6a4SAndroid Build Coastguard Worker } 423*bb4ee6a4SAndroid Build Coastguard Worker } 424*bb4ee6a4SAndroid Build Coastguard Worker last_res 425*bb4ee6a4SAndroid Build Coastguard Worker } 426*bb4ee6a4SAndroid Build Coastguard Worker allocate(&mut self, size: u64, alloc: Alloc, tag: String) -> Result<u64>427*bb4ee6a4SAndroid Build Coastguard Worker pub fn allocate(&mut self, size: u64, alloc: Alloc, tag: String) -> Result<u64> { 428*bb4ee6a4SAndroid Build Coastguard Worker let mut last_res = Err(Error::OutOfSpace); 429*bb4ee6a4SAndroid Build Coastguard Worker for allocator in self.allocators.iter_mut() { 430*bb4ee6a4SAndroid Build Coastguard Worker last_res = allocator.allocate(size, alloc, tag.clone()); 431*bb4ee6a4SAndroid Build Coastguard Worker if last_res.is_ok() { 432*bb4ee6a4SAndroid Build Coastguard Worker return last_res; 433*bb4ee6a4SAndroid Build Coastguard Worker } 434*bb4ee6a4SAndroid Build Coastguard Worker } 435*bb4ee6a4SAndroid Build Coastguard Worker last_res 436*bb4ee6a4SAndroid Build Coastguard Worker } 437*bb4ee6a4SAndroid Build Coastguard Worker allocate_at(&mut self, range: AddressRange, alloc: Alloc, tag: String) -> Result<()>438*bb4ee6a4SAndroid Build Coastguard Worker pub fn allocate_at(&mut self, range: AddressRange, alloc: Alloc, tag: String) -> Result<()> { 439*bb4ee6a4SAndroid Build Coastguard Worker let mut last_res = Err(Error::OutOfSpace); 440*bb4ee6a4SAndroid Build Coastguard Worker for allocator in self.allocators.iter_mut() { 441*bb4ee6a4SAndroid Build Coastguard Worker last_res = allocator.allocate_at(range, alloc, tag.clone()); 442*bb4ee6a4SAndroid Build Coastguard Worker if last_res.is_ok() { 443*bb4ee6a4SAndroid Build Coastguard Worker return last_res; 444*bb4ee6a4SAndroid Build Coastguard Worker } 445*bb4ee6a4SAndroid Build Coastguard Worker } 446*bb4ee6a4SAndroid Build Coastguard Worker last_res 447*bb4ee6a4SAndroid Build Coastguard Worker } 448*bb4ee6a4SAndroid Build Coastguard Worker release(&mut self, alloc: Alloc) -> Result<AddressRange>449*bb4ee6a4SAndroid Build Coastguard Worker pub fn release(&mut self, alloc: Alloc) -> Result<AddressRange> { 450*bb4ee6a4SAndroid Build Coastguard Worker let mut last_res = Err(Error::OutOfSpace); 451*bb4ee6a4SAndroid Build Coastguard Worker for allocator in self.allocators.iter_mut() { 452*bb4ee6a4SAndroid Build Coastguard Worker last_res = allocator.release(alloc); 453*bb4ee6a4SAndroid Build Coastguard Worker if last_res.is_ok() { 454*bb4ee6a4SAndroid Build Coastguard Worker return last_res; 455*bb4ee6a4SAndroid Build Coastguard Worker } 456*bb4ee6a4SAndroid Build Coastguard Worker } 457*bb4ee6a4SAndroid Build Coastguard Worker last_res 458*bb4ee6a4SAndroid Build Coastguard Worker } 459*bb4ee6a4SAndroid Build Coastguard Worker get(&self, alloc: &Alloc) -> Option<&(AddressRange, String)>460*bb4ee6a4SAndroid Build Coastguard Worker pub fn get(&self, alloc: &Alloc) -> Option<&(AddressRange, String)> { 461*bb4ee6a4SAndroid Build Coastguard Worker for allocator in self.allocators.iter() { 462*bb4ee6a4SAndroid Build Coastguard Worker let opt = allocator.get(alloc); 463*bb4ee6a4SAndroid Build Coastguard Worker if opt.is_some() { 464*bb4ee6a4SAndroid Build Coastguard Worker return opt; 465*bb4ee6a4SAndroid Build Coastguard Worker } 466*bb4ee6a4SAndroid Build Coastguard Worker } 467*bb4ee6a4SAndroid Build Coastguard Worker None 468*bb4ee6a4SAndroid Build Coastguard Worker } 469*bb4ee6a4SAndroid Build Coastguard Worker address_from_pci_offset(&self, alloc: Alloc, offset: u64, size: u64) -> Result<u64>470*bb4ee6a4SAndroid Build Coastguard Worker pub fn address_from_pci_offset(&self, alloc: Alloc, offset: u64, size: u64) -> Result<u64> { 471*bb4ee6a4SAndroid Build Coastguard Worker let mut last_res = Err(Error::OutOfSpace); 472*bb4ee6a4SAndroid Build Coastguard Worker for allocator in self.allocators.iter() { 473*bb4ee6a4SAndroid Build Coastguard Worker last_res = allocator.address_from_pci_offset(alloc, offset, size); 474*bb4ee6a4SAndroid Build Coastguard Worker if last_res.is_ok() { 475*bb4ee6a4SAndroid Build Coastguard Worker return last_res; 476*bb4ee6a4SAndroid Build Coastguard Worker } 477*bb4ee6a4SAndroid Build Coastguard Worker } 478*bb4ee6a4SAndroid Build Coastguard Worker last_res 479*bb4ee6a4SAndroid Build Coastguard Worker } 480*bb4ee6a4SAndroid Build Coastguard Worker } 481*bb4ee6a4SAndroid Build Coastguard Worker 482*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)] 483*bb4ee6a4SAndroid Build Coastguard Worker mod tests { 484*bb4ee6a4SAndroid Build Coastguard Worker use super::*; 485*bb4ee6a4SAndroid Build Coastguard Worker 486*bb4ee6a4SAndroid Build Coastguard Worker #[test] example()487*bb4ee6a4SAndroid Build Coastguard Worker fn example() { 488*bb4ee6a4SAndroid Build Coastguard Worker // Anon is used for brevity. Don't manually instantiate Anon allocs! 489*bb4ee6a4SAndroid Build Coastguard Worker let mut pool = AddressAllocator::new( 490*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 491*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1000, 492*bb4ee6a4SAndroid Build Coastguard Worker end: 0xFFFF, 493*bb4ee6a4SAndroid Build Coastguard Worker }, 494*bb4ee6a4SAndroid Build Coastguard Worker Some(0x100), 495*bb4ee6a4SAndroid Build Coastguard Worker None, 496*bb4ee6a4SAndroid Build Coastguard Worker ) 497*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 498*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 499*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate(0x110, Alloc::Anon(0), "caps".to_string()), 500*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1000) 501*bb4ee6a4SAndroid Build Coastguard Worker ); 502*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 503*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate(0x100, Alloc::Anon(1), "cache".to_string()), 504*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1200) 505*bb4ee6a4SAndroid Build Coastguard Worker ); 506*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 507*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate(0x100, Alloc::Anon(2), "etc".to_string()), 508*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1300) 509*bb4ee6a4SAndroid Build Coastguard Worker ); 510*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 511*bb4ee6a4SAndroid Build Coastguard Worker pool.get(&Alloc::Anon(1)), 512*bb4ee6a4SAndroid Build Coastguard Worker Some(&( 513*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 514*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1200, 515*bb4ee6a4SAndroid Build Coastguard Worker end: 0x12FF 516*bb4ee6a4SAndroid Build Coastguard Worker }, 517*bb4ee6a4SAndroid Build Coastguard Worker "cache".to_string() 518*bb4ee6a4SAndroid Build Coastguard Worker )) 519*bb4ee6a4SAndroid Build Coastguard Worker ); 520*bb4ee6a4SAndroid Build Coastguard Worker } 521*bb4ee6a4SAndroid Build Coastguard Worker 522*bb4ee6a4SAndroid Build Coastguard Worker #[test] empty_allocator()523*bb4ee6a4SAndroid Build Coastguard Worker fn empty_allocator() { 524*bb4ee6a4SAndroid Build Coastguard Worker let mut pool = AddressAllocator::new_from_list(Vec::new(), None, None).unwrap(); 525*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(pool.pools(), &[]); 526*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 527*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate(1, Alloc::Anon(0), "test".to_string()), 528*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::OutOfSpace) 529*bb4ee6a4SAndroid Build Coastguard Worker ); 530*bb4ee6a4SAndroid Build Coastguard Worker } 531*bb4ee6a4SAndroid Build Coastguard Worker 532*bb4ee6a4SAndroid Build Coastguard Worker #[test] new_fails_alignment_zero()533*bb4ee6a4SAndroid Build Coastguard Worker fn new_fails_alignment_zero() { 534*bb4ee6a4SAndroid Build Coastguard Worker assert!(AddressAllocator::new( 535*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 536*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1000, 537*bb4ee6a4SAndroid Build Coastguard Worker end: 0xFFFF 538*bb4ee6a4SAndroid Build Coastguard Worker }, 539*bb4ee6a4SAndroid Build Coastguard Worker Some(0), 540*bb4ee6a4SAndroid Build Coastguard Worker None 541*bb4ee6a4SAndroid Build Coastguard Worker ) 542*bb4ee6a4SAndroid Build Coastguard Worker .is_err()); 543*bb4ee6a4SAndroid Build Coastguard Worker } 544*bb4ee6a4SAndroid Build Coastguard Worker 545*bb4ee6a4SAndroid Build Coastguard Worker #[test] new_fails_alignment_non_power_of_two()546*bb4ee6a4SAndroid Build Coastguard Worker fn new_fails_alignment_non_power_of_two() { 547*bb4ee6a4SAndroid Build Coastguard Worker assert!(AddressAllocator::new( 548*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 549*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1000, 550*bb4ee6a4SAndroid Build Coastguard Worker end: 0xFFFF 551*bb4ee6a4SAndroid Build Coastguard Worker }, 552*bb4ee6a4SAndroid Build Coastguard Worker Some(200), 553*bb4ee6a4SAndroid Build Coastguard Worker None 554*bb4ee6a4SAndroid Build Coastguard Worker ) 555*bb4ee6a4SAndroid Build Coastguard Worker .is_err()); 556*bb4ee6a4SAndroid Build Coastguard Worker } 557*bb4ee6a4SAndroid Build Coastguard Worker 558*bb4ee6a4SAndroid Build Coastguard Worker #[test] allocate_fails_exising_alloc()559*bb4ee6a4SAndroid Build Coastguard Worker fn allocate_fails_exising_alloc() { 560*bb4ee6a4SAndroid Build Coastguard Worker let mut pool = AddressAllocator::new( 561*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 562*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1000, 563*bb4ee6a4SAndroid Build Coastguard Worker end: 0x1FFF, 564*bb4ee6a4SAndroid Build Coastguard Worker }, 565*bb4ee6a4SAndroid Build Coastguard Worker Some(0x100), 566*bb4ee6a4SAndroid Build Coastguard Worker None, 567*bb4ee6a4SAndroid Build Coastguard Worker ) 568*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 569*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 570*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate(0x800, Alloc::Anon(0), String::from("bar0")), 571*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1000) 572*bb4ee6a4SAndroid Build Coastguard Worker ); 573*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 574*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate(0x800, Alloc::Anon(0), String::from("bar0")), 575*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::ExistingAlloc(Alloc::Anon(0))) 576*bb4ee6a4SAndroid Build Coastguard Worker ); 577*bb4ee6a4SAndroid Build Coastguard Worker } 578*bb4ee6a4SAndroid Build Coastguard Worker 579*bb4ee6a4SAndroid Build Coastguard Worker #[test] allocate_fails_not_enough_space()580*bb4ee6a4SAndroid Build Coastguard Worker fn allocate_fails_not_enough_space() { 581*bb4ee6a4SAndroid Build Coastguard Worker let mut pool = AddressAllocator::new( 582*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 583*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1000, 584*bb4ee6a4SAndroid Build Coastguard Worker end: 0x1FFF, 585*bb4ee6a4SAndroid Build Coastguard Worker }, 586*bb4ee6a4SAndroid Build Coastguard Worker Some(0x100), 587*bb4ee6a4SAndroid Build Coastguard Worker None, 588*bb4ee6a4SAndroid Build Coastguard Worker ) 589*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 590*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 591*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate(0x800, Alloc::Anon(0), String::from("bar0")), 592*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1000) 593*bb4ee6a4SAndroid Build Coastguard Worker ); 594*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 595*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate(0x900, Alloc::Anon(1), String::from("bar1")), 596*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::OutOfSpace) 597*bb4ee6a4SAndroid Build Coastguard Worker ); 598*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 599*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate(0x800, Alloc::Anon(2), String::from("bar2")), 600*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1800) 601*bb4ee6a4SAndroid Build Coastguard Worker ); 602*bb4ee6a4SAndroid Build Coastguard Worker } 603*bb4ee6a4SAndroid Build Coastguard Worker 604*bb4ee6a4SAndroid Build Coastguard Worker #[test] allocate_with_special_alignment()605*bb4ee6a4SAndroid Build Coastguard Worker fn allocate_with_special_alignment() { 606*bb4ee6a4SAndroid Build Coastguard Worker let mut pool = AddressAllocator::new( 607*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 608*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1000, 609*bb4ee6a4SAndroid Build Coastguard Worker end: 0x1FFF, 610*bb4ee6a4SAndroid Build Coastguard Worker }, 611*bb4ee6a4SAndroid Build Coastguard Worker Some(0x100), 612*bb4ee6a4SAndroid Build Coastguard Worker None, 613*bb4ee6a4SAndroid Build Coastguard Worker ) 614*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 615*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 616*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate(0x10, Alloc::Anon(0), String::from("bar0")), 617*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1000) 618*bb4ee6a4SAndroid Build Coastguard Worker ); 619*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 620*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate_at( 621*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 622*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1200, 623*bb4ee6a4SAndroid Build Coastguard Worker end: 0x13ff, 624*bb4ee6a4SAndroid Build Coastguard Worker }, 625*bb4ee6a4SAndroid Build Coastguard Worker Alloc::Anon(1), 626*bb4ee6a4SAndroid Build Coastguard Worker String::from("bar1") 627*bb4ee6a4SAndroid Build Coastguard Worker ), 628*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 629*bb4ee6a4SAndroid Build Coastguard Worker ); 630*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 631*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate_with_align(0x800, Alloc::Anon(2), String::from("bar2"), 0x800), 632*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1800) 633*bb4ee6a4SAndroid Build Coastguard Worker ); 634*bb4ee6a4SAndroid Build Coastguard Worker } 635*bb4ee6a4SAndroid Build Coastguard Worker 636*bb4ee6a4SAndroid Build Coastguard Worker #[test] allocate_and_split_allocate_at()637*bb4ee6a4SAndroid Build Coastguard Worker fn allocate_and_split_allocate_at() { 638*bb4ee6a4SAndroid Build Coastguard Worker let mut pool = AddressAllocator::new( 639*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 640*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1000, 641*bb4ee6a4SAndroid Build Coastguard Worker end: 0x1fff, 642*bb4ee6a4SAndroid Build Coastguard Worker }, 643*bb4ee6a4SAndroid Build Coastguard Worker Some(1), 644*bb4ee6a4SAndroid Build Coastguard Worker None, 645*bb4ee6a4SAndroid Build Coastguard Worker ) 646*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 647*bb4ee6a4SAndroid Build Coastguard Worker // 0x1200..0x1a00 648*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 649*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate_at( 650*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 651*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1200, 652*bb4ee6a4SAndroid Build Coastguard Worker end: 0x19ff, 653*bb4ee6a4SAndroid Build Coastguard Worker }, 654*bb4ee6a4SAndroid Build Coastguard Worker Alloc::Anon(0), 655*bb4ee6a4SAndroid Build Coastguard Worker String::from("bar0") 656*bb4ee6a4SAndroid Build Coastguard Worker ), 657*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 658*bb4ee6a4SAndroid Build Coastguard Worker ); 659*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 660*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate(0x800, Alloc::Anon(1), String::from("bar1")), 661*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::OutOfSpace) 662*bb4ee6a4SAndroid Build Coastguard Worker ); 663*bb4ee6a4SAndroid Build Coastguard Worker // 0x600..0x2000 664*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 665*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate(0x600, Alloc::Anon(2), String::from("bar2")), 666*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1a00) 667*bb4ee6a4SAndroid Build Coastguard Worker ); 668*bb4ee6a4SAndroid Build Coastguard Worker // 0x1000..0x1200 669*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 670*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate(0x200, Alloc::Anon(3), String::from("bar3")), 671*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1000) 672*bb4ee6a4SAndroid Build Coastguard Worker ); 673*bb4ee6a4SAndroid Build Coastguard Worker // 0x1b00..0x1c00 (overlaps with 0x600..0x2000) 674*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 675*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate_at( 676*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 677*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1b00, 678*bb4ee6a4SAndroid Build Coastguard Worker end: 0x1bff, 679*bb4ee6a4SAndroid Build Coastguard Worker }, 680*bb4ee6a4SAndroid Build Coastguard Worker Alloc::Anon(4), 681*bb4ee6a4SAndroid Build Coastguard Worker String::from("bar4") 682*bb4ee6a4SAndroid Build Coastguard Worker ), 683*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::ExistingAlloc(Alloc::Anon(2))) 684*bb4ee6a4SAndroid Build Coastguard Worker ); 685*bb4ee6a4SAndroid Build Coastguard Worker // 0x1fff..0x2000 (overlaps with 0x600..0x2000) 686*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 687*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate_at( 688*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 689*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1fff, 690*bb4ee6a4SAndroid Build Coastguard Worker end: 0x1fff, 691*bb4ee6a4SAndroid Build Coastguard Worker }, 692*bb4ee6a4SAndroid Build Coastguard Worker Alloc::Anon(5), 693*bb4ee6a4SAndroid Build Coastguard Worker String::from("bar5") 694*bb4ee6a4SAndroid Build Coastguard Worker ), 695*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::ExistingAlloc(Alloc::Anon(2))) 696*bb4ee6a4SAndroid Build Coastguard Worker ); 697*bb4ee6a4SAndroid Build Coastguard Worker // 0x1200..0x1201 (overlaps with 0x1200..0x1a00) 698*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 699*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate_at( 700*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 701*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1200, 702*bb4ee6a4SAndroid Build Coastguard Worker end: 0x1200, 703*bb4ee6a4SAndroid Build Coastguard Worker }, 704*bb4ee6a4SAndroid Build Coastguard Worker Alloc::Anon(6), 705*bb4ee6a4SAndroid Build Coastguard Worker String::from("bar6") 706*bb4ee6a4SAndroid Build Coastguard Worker ), 707*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::ExistingAlloc(Alloc::Anon(0))) 708*bb4ee6a4SAndroid Build Coastguard Worker ); 709*bb4ee6a4SAndroid Build Coastguard Worker // 0x11ff..0x1200 (overlaps with 0x1000..0x1200) 710*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 711*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate_at( 712*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 713*bb4ee6a4SAndroid Build Coastguard Worker start: 0x11ff, 714*bb4ee6a4SAndroid Build Coastguard Worker end: 0x11ff, 715*bb4ee6a4SAndroid Build Coastguard Worker }, 716*bb4ee6a4SAndroid Build Coastguard Worker Alloc::Anon(7), 717*bb4ee6a4SAndroid Build Coastguard Worker String::from("bar7") 718*bb4ee6a4SAndroid Build Coastguard Worker ), 719*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::ExistingAlloc(Alloc::Anon(3))) 720*bb4ee6a4SAndroid Build Coastguard Worker ); 721*bb4ee6a4SAndroid Build Coastguard Worker // 0x1100..0x1300 (overlaps with 0x1000..0x1200 and 0x1200..0x1a00) 722*bb4ee6a4SAndroid Build Coastguard Worker match pool.allocate_at( 723*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 724*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1100, 725*bb4ee6a4SAndroid Build Coastguard Worker end: 0x12ff, 726*bb4ee6a4SAndroid Build Coastguard Worker }, 727*bb4ee6a4SAndroid Build Coastguard Worker Alloc::Anon(8), 728*bb4ee6a4SAndroid Build Coastguard Worker String::from("bar8"), 729*bb4ee6a4SAndroid Build Coastguard Worker ) { 730*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::ExistingAlloc(Alloc::Anon(0) | Alloc::Anon(3))) => {} 731*bb4ee6a4SAndroid Build Coastguard Worker x => panic!("unexpected result {:?}", x), 732*bb4ee6a4SAndroid Build Coastguard Worker } 733*bb4ee6a4SAndroid Build Coastguard Worker } 734*bb4ee6a4SAndroid Build Coastguard Worker 735*bb4ee6a4SAndroid Build Coastguard Worker #[test] allocate_alignment()736*bb4ee6a4SAndroid Build Coastguard Worker fn allocate_alignment() { 737*bb4ee6a4SAndroid Build Coastguard Worker let mut pool = AddressAllocator::new( 738*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 739*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1000, 740*bb4ee6a4SAndroid Build Coastguard Worker end: 0xFFFF, 741*bb4ee6a4SAndroid Build Coastguard Worker }, 742*bb4ee6a4SAndroid Build Coastguard Worker Some(0x100), 743*bb4ee6a4SAndroid Build Coastguard Worker None, 744*bb4ee6a4SAndroid Build Coastguard Worker ) 745*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 746*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 747*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate(0x110, Alloc::Anon(0), String::from("bar0")), 748*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1000) 749*bb4ee6a4SAndroid Build Coastguard Worker ); 750*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 751*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate(0x100, Alloc::Anon(1), String::from("bar1")), 752*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1200) 753*bb4ee6a4SAndroid Build Coastguard Worker ); 754*bb4ee6a4SAndroid Build Coastguard Worker } 755*bb4ee6a4SAndroid Build Coastguard Worker 756*bb4ee6a4SAndroid Build Coastguard Worker #[test] allocate_retrieve_alloc()757*bb4ee6a4SAndroid Build Coastguard Worker fn allocate_retrieve_alloc() { 758*bb4ee6a4SAndroid Build Coastguard Worker let mut pool = AddressAllocator::new( 759*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 760*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1000, 761*bb4ee6a4SAndroid Build Coastguard Worker end: 0xFFFF, 762*bb4ee6a4SAndroid Build Coastguard Worker }, 763*bb4ee6a4SAndroid Build Coastguard Worker Some(0x100), 764*bb4ee6a4SAndroid Build Coastguard Worker None, 765*bb4ee6a4SAndroid Build Coastguard Worker ) 766*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 767*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 768*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate(0x110, Alloc::Anon(0), String::from("bar0")), 769*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1000) 770*bb4ee6a4SAndroid Build Coastguard Worker ); 771*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 772*bb4ee6a4SAndroid Build Coastguard Worker pool.get(&Alloc::Anon(0)), 773*bb4ee6a4SAndroid Build Coastguard Worker Some(&( 774*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 775*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1000, 776*bb4ee6a4SAndroid Build Coastguard Worker end: 0x110f, 777*bb4ee6a4SAndroid Build Coastguard Worker }, 778*bb4ee6a4SAndroid Build Coastguard Worker String::from("bar0") 779*bb4ee6a4SAndroid Build Coastguard Worker )) 780*bb4ee6a4SAndroid Build Coastguard Worker ); 781*bb4ee6a4SAndroid Build Coastguard Worker } 782*bb4ee6a4SAndroid Build Coastguard Worker 783*bb4ee6a4SAndroid Build Coastguard Worker #[test] allocate_with_alignment_allocator_alignment()784*bb4ee6a4SAndroid Build Coastguard Worker fn allocate_with_alignment_allocator_alignment() { 785*bb4ee6a4SAndroid Build Coastguard Worker let mut pool = AddressAllocator::new( 786*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 787*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1000, 788*bb4ee6a4SAndroid Build Coastguard Worker end: 0xFFFF, 789*bb4ee6a4SAndroid Build Coastguard Worker }, 790*bb4ee6a4SAndroid Build Coastguard Worker Some(0x100), 791*bb4ee6a4SAndroid Build Coastguard Worker None, 792*bb4ee6a4SAndroid Build Coastguard Worker ) 793*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 794*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 795*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate_with_align(0x110, Alloc::Anon(0), String::from("bar0"), 0x1), 796*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1000) 797*bb4ee6a4SAndroid Build Coastguard Worker ); 798*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 799*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate_with_align(0x100, Alloc::Anon(1), String::from("bar1"), 0x1), 800*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1200) 801*bb4ee6a4SAndroid Build Coastguard Worker ); 802*bb4ee6a4SAndroid Build Coastguard Worker } 803*bb4ee6a4SAndroid Build Coastguard Worker 804*bb4ee6a4SAndroid Build Coastguard Worker #[test] allocate_with_alignment_custom_alignment()805*bb4ee6a4SAndroid Build Coastguard Worker fn allocate_with_alignment_custom_alignment() { 806*bb4ee6a4SAndroid Build Coastguard Worker let mut pool = AddressAllocator::new( 807*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 808*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1000, 809*bb4ee6a4SAndroid Build Coastguard Worker end: 0xFFFF, 810*bb4ee6a4SAndroid Build Coastguard Worker }, 811*bb4ee6a4SAndroid Build Coastguard Worker Some(0x4), 812*bb4ee6a4SAndroid Build Coastguard Worker None, 813*bb4ee6a4SAndroid Build Coastguard Worker ) 814*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 815*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 816*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate_with_align(0x110, Alloc::Anon(0), String::from("bar0"), 0x100), 817*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1000) 818*bb4ee6a4SAndroid Build Coastguard Worker ); 819*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 820*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate_with_align(0x100, Alloc::Anon(1), String::from("bar1"), 0x100), 821*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1200) 822*bb4ee6a4SAndroid Build Coastguard Worker ); 823*bb4ee6a4SAndroid Build Coastguard Worker } 824*bb4ee6a4SAndroid Build Coastguard Worker 825*bb4ee6a4SAndroid Build Coastguard Worker #[test] allocate_with_alignment_no_allocator_alignment()826*bb4ee6a4SAndroid Build Coastguard Worker fn allocate_with_alignment_no_allocator_alignment() { 827*bb4ee6a4SAndroid Build Coastguard Worker let mut pool = AddressAllocator::new( 828*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 829*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1000, 830*bb4ee6a4SAndroid Build Coastguard Worker end: 0xFFFF, 831*bb4ee6a4SAndroid Build Coastguard Worker }, 832*bb4ee6a4SAndroid Build Coastguard Worker None, 833*bb4ee6a4SAndroid Build Coastguard Worker None, 834*bb4ee6a4SAndroid Build Coastguard Worker ) 835*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 836*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 837*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate_with_align(0x110, Alloc::Anon(0), String::from("bar0"), 0x100), 838*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1000) 839*bb4ee6a4SAndroid Build Coastguard Worker ); 840*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 841*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate_with_align(0x100, Alloc::Anon(1), String::from("bar1"), 0x100), 842*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1200) 843*bb4ee6a4SAndroid Build Coastguard Worker ); 844*bb4ee6a4SAndroid Build Coastguard Worker } 845*bb4ee6a4SAndroid Build Coastguard Worker 846*bb4ee6a4SAndroid Build Coastguard Worker #[test] allocate_with_alignment_alignment_non_power_of_two()847*bb4ee6a4SAndroid Build Coastguard Worker fn allocate_with_alignment_alignment_non_power_of_two() { 848*bb4ee6a4SAndroid Build Coastguard Worker let mut pool = AddressAllocator::new( 849*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 850*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1000, 851*bb4ee6a4SAndroid Build Coastguard Worker end: 0xFFFF, 852*bb4ee6a4SAndroid Build Coastguard Worker }, 853*bb4ee6a4SAndroid Build Coastguard Worker None, 854*bb4ee6a4SAndroid Build Coastguard Worker None, 855*bb4ee6a4SAndroid Build Coastguard Worker ) 856*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 857*bb4ee6a4SAndroid Build Coastguard Worker assert!(pool 858*bb4ee6a4SAndroid Build Coastguard Worker .allocate_with_align(0x110, Alloc::Anon(0), String::from("bar0"), 200) 859*bb4ee6a4SAndroid Build Coastguard Worker .is_err()); 860*bb4ee6a4SAndroid Build Coastguard Worker } 861*bb4ee6a4SAndroid Build Coastguard Worker 862*bb4ee6a4SAndroid Build Coastguard Worker #[test] allocate_with_release()863*bb4ee6a4SAndroid Build Coastguard Worker fn allocate_with_release() { 864*bb4ee6a4SAndroid Build Coastguard Worker let mut pool = AddressAllocator::new( 865*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 866*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1000, 867*bb4ee6a4SAndroid Build Coastguard Worker end: 0x1FFF, 868*bb4ee6a4SAndroid Build Coastguard Worker }, 869*bb4ee6a4SAndroid Build Coastguard Worker None, 870*bb4ee6a4SAndroid Build Coastguard Worker None, 871*bb4ee6a4SAndroid Build Coastguard Worker ) 872*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 873*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 874*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate_with_align(0x100, Alloc::Anon(0), String::from("bar0"), 0x100), 875*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1000) 876*bb4ee6a4SAndroid Build Coastguard Worker ); 877*bb4ee6a4SAndroid Build Coastguard Worker assert!(pool.release(Alloc::Anon(0)).is_ok()); 878*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 879*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate_with_align(0x1000, Alloc::Anon(0), String::from("bar0"), 0x100), 880*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1000) 881*bb4ee6a4SAndroid Build Coastguard Worker ); 882*bb4ee6a4SAndroid Build Coastguard Worker } 883*bb4ee6a4SAndroid Build Coastguard Worker 884*bb4ee6a4SAndroid Build Coastguard Worker #[test] coalescing_and_overlap()885*bb4ee6a4SAndroid Build Coastguard Worker fn coalescing_and_overlap() { 886*bb4ee6a4SAndroid Build Coastguard Worker let mut pool = AddressAllocator::new( 887*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 888*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1000, 889*bb4ee6a4SAndroid Build Coastguard Worker end: 0x1FFF, 890*bb4ee6a4SAndroid Build Coastguard Worker }, 891*bb4ee6a4SAndroid Build Coastguard Worker None, 892*bb4ee6a4SAndroid Build Coastguard Worker None, 893*bb4ee6a4SAndroid Build Coastguard Worker ) 894*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 895*bb4ee6a4SAndroid Build Coastguard Worker assert!(pool 896*bb4ee6a4SAndroid Build Coastguard Worker .insert_at(AddressRange { 897*bb4ee6a4SAndroid Build Coastguard Worker start: 0x3000, 898*bb4ee6a4SAndroid Build Coastguard Worker end: 0x3fff, 899*bb4ee6a4SAndroid Build Coastguard Worker }) 900*bb4ee6a4SAndroid Build Coastguard Worker .is_ok()); 901*bb4ee6a4SAndroid Build Coastguard Worker assert!(pool 902*bb4ee6a4SAndroid Build Coastguard Worker .insert_at(AddressRange { 903*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1fff, 904*bb4ee6a4SAndroid Build Coastguard Worker end: 0x201e, 905*bb4ee6a4SAndroid Build Coastguard Worker }) 906*bb4ee6a4SAndroid Build Coastguard Worker .is_err()); 907*bb4ee6a4SAndroid Build Coastguard Worker assert!(pool 908*bb4ee6a4SAndroid Build Coastguard Worker .insert_at(AddressRange { 909*bb4ee6a4SAndroid Build Coastguard Worker start: 0x2ff1, 910*bb4ee6a4SAndroid Build Coastguard Worker end: 0x3000, 911*bb4ee6a4SAndroid Build Coastguard Worker }) 912*bb4ee6a4SAndroid Build Coastguard Worker .is_err()); 913*bb4ee6a4SAndroid Build Coastguard Worker assert!(pool 914*bb4ee6a4SAndroid Build Coastguard Worker .insert_at(AddressRange { 915*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1800, 916*bb4ee6a4SAndroid Build Coastguard Worker end: 0x27ff, 917*bb4ee6a4SAndroid Build Coastguard Worker }) 918*bb4ee6a4SAndroid Build Coastguard Worker .is_err()); 919*bb4ee6a4SAndroid Build Coastguard Worker assert!(pool 920*bb4ee6a4SAndroid Build Coastguard Worker .insert_at(AddressRange { 921*bb4ee6a4SAndroid Build Coastguard Worker start: 0x2000, 922*bb4ee6a4SAndroid Build Coastguard Worker end: 0x2fff, 923*bb4ee6a4SAndroid Build Coastguard Worker }) 924*bb4ee6a4SAndroid Build Coastguard Worker .is_ok()); 925*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 926*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate(0x3000, Alloc::Anon(0), String::from("bar0")), 927*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1000) 928*bb4ee6a4SAndroid Build Coastguard Worker ); 929*bb4ee6a4SAndroid Build Coastguard Worker } 930*bb4ee6a4SAndroid Build Coastguard Worker 931*bb4ee6a4SAndroid Build Coastguard Worker #[test] coalescing_single_addresses()932*bb4ee6a4SAndroid Build Coastguard Worker fn coalescing_single_addresses() { 933*bb4ee6a4SAndroid Build Coastguard Worker let mut pool = AddressAllocator::new( 934*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 935*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1000, 936*bb4ee6a4SAndroid Build Coastguard Worker end: 0x1FFF, 937*bb4ee6a4SAndroid Build Coastguard Worker }, 938*bb4ee6a4SAndroid Build Coastguard Worker None, 939*bb4ee6a4SAndroid Build Coastguard Worker None, 940*bb4ee6a4SAndroid Build Coastguard Worker ) 941*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 942*bb4ee6a4SAndroid Build Coastguard Worker assert!(pool 943*bb4ee6a4SAndroid Build Coastguard Worker .insert_at(AddressRange { 944*bb4ee6a4SAndroid Build Coastguard Worker start: 0x2001, 945*bb4ee6a4SAndroid Build Coastguard Worker end: 0x2001, 946*bb4ee6a4SAndroid Build Coastguard Worker }) 947*bb4ee6a4SAndroid Build Coastguard Worker .is_ok()); 948*bb4ee6a4SAndroid Build Coastguard Worker assert!(pool 949*bb4ee6a4SAndroid Build Coastguard Worker .insert_at(AddressRange { 950*bb4ee6a4SAndroid Build Coastguard Worker start: 0x2003, 951*bb4ee6a4SAndroid Build Coastguard Worker end: 0x2003, 952*bb4ee6a4SAndroid Build Coastguard Worker }) 953*bb4ee6a4SAndroid Build Coastguard Worker .is_ok()); 954*bb4ee6a4SAndroid Build Coastguard Worker assert!(pool 955*bb4ee6a4SAndroid Build Coastguard Worker .insert_at(AddressRange { 956*bb4ee6a4SAndroid Build Coastguard Worker start: 0x2000, 957*bb4ee6a4SAndroid Build Coastguard Worker end: 0x2000, 958*bb4ee6a4SAndroid Build Coastguard Worker }) 959*bb4ee6a4SAndroid Build Coastguard Worker .is_ok()); 960*bb4ee6a4SAndroid Build Coastguard Worker assert!(pool 961*bb4ee6a4SAndroid Build Coastguard Worker .insert_at(AddressRange { 962*bb4ee6a4SAndroid Build Coastguard Worker start: 0x2002, 963*bb4ee6a4SAndroid Build Coastguard Worker end: 0x2002, 964*bb4ee6a4SAndroid Build Coastguard Worker }) 965*bb4ee6a4SAndroid Build Coastguard Worker .is_ok()); 966*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 967*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate(0x1004, Alloc::Anon(0), String::from("bar0")), 968*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1000) 969*bb4ee6a4SAndroid Build Coastguard Worker ); 970*bb4ee6a4SAndroid Build Coastguard Worker } 971*bb4ee6a4SAndroid Build Coastguard Worker 972*bb4ee6a4SAndroid Build Coastguard Worker #[test] coalescing_u64_limits()973*bb4ee6a4SAndroid Build Coastguard Worker fn coalescing_u64_limits() { 974*bb4ee6a4SAndroid Build Coastguard Worker let mut pool = AddressAllocator::new( 975*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 976*bb4ee6a4SAndroid Build Coastguard Worker start: 0, 977*bb4ee6a4SAndroid Build Coastguard Worker end: u64::MAX - 1, 978*bb4ee6a4SAndroid Build Coastguard Worker }, 979*bb4ee6a4SAndroid Build Coastguard Worker None, 980*bb4ee6a4SAndroid Build Coastguard Worker None, 981*bb4ee6a4SAndroid Build Coastguard Worker ) 982*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 983*bb4ee6a4SAndroid Build Coastguard Worker assert!(pool 984*bb4ee6a4SAndroid Build Coastguard Worker .insert_at(AddressRange { 985*bb4ee6a4SAndroid Build Coastguard Worker start: u64::MAX, 986*bb4ee6a4SAndroid Build Coastguard Worker end: u64::MAX, 987*bb4ee6a4SAndroid Build Coastguard Worker }) 988*bb4ee6a4SAndroid Build Coastguard Worker .is_ok()); 989*bb4ee6a4SAndroid Build Coastguard Worker assert!(pool 990*bb4ee6a4SAndroid Build Coastguard Worker .insert_at(AddressRange { 991*bb4ee6a4SAndroid Build Coastguard Worker start: u64::MAX, 992*bb4ee6a4SAndroid Build Coastguard Worker end: u64::MAX, 993*bb4ee6a4SAndroid Build Coastguard Worker }) 994*bb4ee6a4SAndroid Build Coastguard Worker .is_err()); 995*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 996*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate(u64::MAX, Alloc::Anon(0), String::from("bar0")), 997*bb4ee6a4SAndroid Build Coastguard Worker Ok(0) 998*bb4ee6a4SAndroid Build Coastguard Worker ); 999*bb4ee6a4SAndroid Build Coastguard Worker 1000*bb4ee6a4SAndroid Build Coastguard Worker let mut pool = AddressAllocator::new( 1001*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 1002*bb4ee6a4SAndroid Build Coastguard Worker start: 1, 1003*bb4ee6a4SAndroid Build Coastguard Worker end: u64::MAX, 1004*bb4ee6a4SAndroid Build Coastguard Worker }, 1005*bb4ee6a4SAndroid Build Coastguard Worker None, 1006*bb4ee6a4SAndroid Build Coastguard Worker None, 1007*bb4ee6a4SAndroid Build Coastguard Worker ) 1008*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 1009*bb4ee6a4SAndroid Build Coastguard Worker assert!(pool.insert_at(AddressRange { start: 0, end: 0 }).is_ok()); 1010*bb4ee6a4SAndroid Build Coastguard Worker assert!(pool.insert_at(AddressRange { start: 0, end: 0 }).is_err()); 1011*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 1012*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate(u64::MAX, Alloc::Anon(0), String::from("bar0")), 1013*bb4ee6a4SAndroid Build Coastguard Worker Ok(0) 1014*bb4ee6a4SAndroid Build Coastguard Worker ); 1015*bb4ee6a4SAndroid Build Coastguard Worker } 1016*bb4ee6a4SAndroid Build Coastguard Worker 1017*bb4ee6a4SAndroid Build Coastguard Worker #[test] allocate_and_verify_pci_offset()1018*bb4ee6a4SAndroid Build Coastguard Worker fn allocate_and_verify_pci_offset() { 1019*bb4ee6a4SAndroid Build Coastguard Worker let mut pool = AddressAllocator::new( 1020*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 1021*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1000, 1022*bb4ee6a4SAndroid Build Coastguard Worker end: 0xFFFF, 1023*bb4ee6a4SAndroid Build Coastguard Worker }, 1024*bb4ee6a4SAndroid Build Coastguard Worker None, 1025*bb4ee6a4SAndroid Build Coastguard Worker None, 1026*bb4ee6a4SAndroid Build Coastguard Worker ) 1027*bb4ee6a4SAndroid Build Coastguard Worker .unwrap(); 1028*bb4ee6a4SAndroid Build Coastguard Worker let pci_bar0 = Alloc::PciBar { 1029*bb4ee6a4SAndroid Build Coastguard Worker bus: 1, 1030*bb4ee6a4SAndroid Build Coastguard Worker dev: 2, 1031*bb4ee6a4SAndroid Build Coastguard Worker func: 0, 1032*bb4ee6a4SAndroid Build Coastguard Worker bar: 0, 1033*bb4ee6a4SAndroid Build Coastguard Worker }; 1034*bb4ee6a4SAndroid Build Coastguard Worker let pci_bar1 = Alloc::PciBar { 1035*bb4ee6a4SAndroid Build Coastguard Worker bus: 1, 1036*bb4ee6a4SAndroid Build Coastguard Worker dev: 2, 1037*bb4ee6a4SAndroid Build Coastguard Worker func: 0, 1038*bb4ee6a4SAndroid Build Coastguard Worker bar: 1, 1039*bb4ee6a4SAndroid Build Coastguard Worker }; 1040*bb4ee6a4SAndroid Build Coastguard Worker let pci_bar2 = Alloc::PciBar { 1041*bb4ee6a4SAndroid Build Coastguard Worker bus: 1, 1042*bb4ee6a4SAndroid Build Coastguard Worker dev: 2, 1043*bb4ee6a4SAndroid Build Coastguard Worker func: 0, 1044*bb4ee6a4SAndroid Build Coastguard Worker bar: 2, 1045*bb4ee6a4SAndroid Build Coastguard Worker }; 1046*bb4ee6a4SAndroid Build Coastguard Worker let anon = Alloc::Anon(1); 1047*bb4ee6a4SAndroid Build Coastguard Worker 1048*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 1049*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate(0x800, pci_bar0, String::from("bar0")), 1050*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1000) 1051*bb4ee6a4SAndroid Build Coastguard Worker ); 1052*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 1053*bb4ee6a4SAndroid Build Coastguard Worker pool.allocate(0x800, pci_bar1, String::from("bar1")), 1054*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1800) 1055*bb4ee6a4SAndroid Build Coastguard Worker ); 1056*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(pool.allocate(0x800, anon, String::from("anon")), Ok(0x2000)); 1057*bb4ee6a4SAndroid Build Coastguard Worker 1058*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 1059*bb4ee6a4SAndroid Build Coastguard Worker pool.address_from_pci_offset(pci_bar0, 0x600, 0x100), 1060*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1600) 1061*bb4ee6a4SAndroid Build Coastguard Worker ); 1062*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 1063*bb4ee6a4SAndroid Build Coastguard Worker pool.address_from_pci_offset(pci_bar1, 0x600, 0x100), 1064*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x1E00) 1065*bb4ee6a4SAndroid Build Coastguard Worker ); 1066*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 1067*bb4ee6a4SAndroid Build Coastguard Worker pool.address_from_pci_offset(pci_bar0, 0x7FE, 0x001), 1068*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x17FE) 1069*bb4ee6a4SAndroid Build Coastguard Worker ); 1070*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 1071*bb4ee6a4SAndroid Build Coastguard Worker pool.address_from_pci_offset(pci_bar0, 0x7FF, 0x001), 1072*bb4ee6a4SAndroid Build Coastguard Worker Ok(0x17FF) 1073*bb4ee6a4SAndroid Build Coastguard Worker ); 1074*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 1075*bb4ee6a4SAndroid Build Coastguard Worker pool.address_from_pci_offset(pci_bar0, 0x800, 0x001), 1076*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::OutOfBounds) 1077*bb4ee6a4SAndroid Build Coastguard Worker ); 1078*bb4ee6a4SAndroid Build Coastguard Worker 1079*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 1080*bb4ee6a4SAndroid Build Coastguard Worker pool.address_from_pci_offset(pci_bar2, 0x7FF, 0x001), 1081*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::InvalidAlloc(pci_bar2)) 1082*bb4ee6a4SAndroid Build Coastguard Worker ); 1083*bb4ee6a4SAndroid Build Coastguard Worker 1084*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!( 1085*bb4ee6a4SAndroid Build Coastguard Worker pool.address_from_pci_offset(anon, 0x600, 0x100), 1086*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::InvalidAlloc(anon)) 1087*bb4ee6a4SAndroid Build Coastguard Worker ); 1088*bb4ee6a4SAndroid Build Coastguard Worker } 1089*bb4ee6a4SAndroid Build Coastguard Worker 1090*bb4ee6a4SAndroid Build Coastguard Worker #[test] get_max_address_of_ranges()1091*bb4ee6a4SAndroid Build Coastguard Worker fn get_max_address_of_ranges() { 1092*bb4ee6a4SAndroid Build Coastguard Worker let ranges = vec![ 1093*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 1094*bb4ee6a4SAndroid Build Coastguard Worker start: 0x1000, 1095*bb4ee6a4SAndroid Build Coastguard Worker end: 0xFFFF, 1096*bb4ee6a4SAndroid Build Coastguard Worker }, 1097*bb4ee6a4SAndroid Build Coastguard Worker AddressRange { 1098*bb4ee6a4SAndroid Build Coastguard Worker start: 0x20000, 1099*bb4ee6a4SAndroid Build Coastguard Worker end: 0xFFFFF, 1100*bb4ee6a4SAndroid Build Coastguard Worker }, 1101*bb4ee6a4SAndroid Build Coastguard Worker ]; 1102*bb4ee6a4SAndroid Build Coastguard Worker let pool = AddressAllocator::new_from_list(ranges, None, None).unwrap(); 1103*bb4ee6a4SAndroid Build Coastguard Worker 1104*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(pool.get_max_addr(), 0xFFFFF); 1105*bb4ee6a4SAndroid Build Coastguard Worker } 1106*bb4ee6a4SAndroid Build Coastguard Worker } 1107