xref: /aosp_15_r20/external/crosvm/resources/src/address_allocator.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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