Skip to content

Commit 5763204

Browse files
committed
Improve construct_memory_map implementation
simplify the overlap check into single if condition and move to interative implementation
1 parent 3326e7a commit 5763204

File tree

1 file changed

+40
-71
lines changed

1 file changed

+40
-71
lines changed

common/src/legacy_memory_region.rs

Lines changed: 40 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use bootloader_api::info::{MemoryRegion, MemoryRegionKind};
22
use core::{
3+
cmp,
34
iter::{empty, Empty},
45
mem::MaybeUninit,
56
};
@@ -235,93 +236,61 @@ where
235236

236237
// TODO unit test
237238
fn split_and_add_region<'a, U>(
238-
region: MemoryRegion,
239+
mut region: MemoryRegion,
239240
regions: &mut [MaybeUninit<MemoryRegion>],
240241
next_index: &mut usize,
241242
used_slices: U,
242243
) where
243244
U: Iterator<Item = UsedMemorySlice> + Clone,
244245
{
245246
assert!(region.kind == MemoryRegionKind::Usable);
246-
if region.start == region.end {
247-
// skip zero sized regions
248-
return;
249-
}
250-
251-
for slice in used_slices.clone() {
252-
let slice_end = slice.start + slice.end;
253-
if region.end <= slice.start || region.start >= slice_end {
254-
// region and slice don't overlap
255-
continue;
256-
}
257-
258-
if region.start >= slice.start && region.end <= slice_end {
259-
// region is completly covered by slice
260-
let bootloader = MemoryRegion {
261-
start: region.start,
262-
end: region.end,
263-
kind: MemoryRegionKind::Bootloader,
264-
};
265-
Self::add_region(bootloader, regions, next_index);
266-
return;
267-
}
268-
if region.start < slice.start && region.end <= slice_end {
269-
// there is a usable region before the bootloader slice
270-
let before = MemoryRegion {
271-
start: region.start,
272-
end: slice.start,
273-
kind: MemoryRegionKind::Usable,
274-
};
275-
276-
let bootloader = MemoryRegion {
277-
start: slice.start,
278-
end: region.end,
279-
kind: MemoryRegionKind::Bootloader,
280-
};
281-
Self::split_and_add_region(before, regions, next_index, used_slices);
282-
Self::add_region(bootloader, regions, next_index);
283-
return;
284-
} else if region.start < slice.start && region.end > slice_end {
285-
// there is usable region before and after the bootloader slice
286-
let before = MemoryRegion {
247+
// Each loop iteration takes a chunk of `region` and adds it to
248+
// `regions`. Do this until `region` is empty.
249+
while region.start != region.end {
250+
// Check if there is overlap between `region` and `used_slices`.
251+
if let Some((overlap_start, overlap_end)) = used_slices
252+
.clone()
253+
.map(|slice| {
254+
// Calculate the start and end points of the overlap
255+
// between `slice` and `region`. If `slice` and `region`
256+
// don't overlap, the range will be ill-formed
257+
// (overlap_start > overlap_end).
258+
let overlap_start = cmp::max(region.start, slice.start);
259+
let overlap_end = cmp::min(region.end, slice.end);
260+
(overlap_start, overlap_end)
261+
})
262+
.filter(|(overlap_start, overlap_end)| {
263+
// Only consider non-empty overlap.
264+
overlap_start < overlap_end
265+
})
266+
.min_by_key(|&(overlap_start, _)| {
267+
// Find the earliest overlap.
268+
overlap_start
269+
})
270+
{
271+
// There's no overlapping used slice before `overlap_start`, so
272+
// we know that memory between `region.start` and
273+
// `overlap_start` is usable.
274+
let usable = MemoryRegion {
287275
start: region.start,
288-
end: slice.start,
276+
end: overlap_start,
289277
kind: MemoryRegionKind::Usable,
290278
};
291279
let bootloader = MemoryRegion {
292-
start: slice.start,
293-
end: slice_end,
280+
start: overlap_start,
281+
end: overlap_end,
294282
kind: MemoryRegionKind::Bootloader,
295283
};
296-
let after = MemoryRegion {
297-
start: slice_end,
298-
end: region.end,
299-
kind: MemoryRegionKind::Usable,
300-
};
301-
Self::split_and_add_region(before, regions, next_index, used_slices.clone());
284+
Self::add_region(usable, regions, next_index);
302285
Self::add_region(bootloader, regions, next_index);
303-
Self::split_and_add_region(after, regions, next_index, used_slices.clone());
304-
return;
305-
}
306-
if region.start >= slice.start && region.end > slice_end {
307-
// there is a usable region after the bootloader slice
308-
let bootloader = MemoryRegion {
309-
start: region.start,
310-
end: slice_end,
311-
kind: MemoryRegionKind::Bootloader,
312-
};
313-
let after = MemoryRegion {
314-
start: slice_end,
315-
end: region.end,
316-
kind: MemoryRegionKind::Usable,
317-
};
318-
Self::add_region(bootloader, regions, next_index);
319-
Self::split_and_add_region(after, regions, next_index, used_slices);
320-
return;
286+
// Continue after the overlapped region.
287+
region.start = overlap_end;
288+
} else {
289+
// There's no overlap. We can add the whole region.
290+
Self::add_region(region, regions, next_index);
291+
break;
321292
}
322293
}
323-
// region is not coverd by any slice
324-
Self::add_region(region, regions, next_index);
325294
}
326295

327296
fn add_region(

0 commit comments

Comments
 (0)