Skip to content

Commit fdb2fb6

Browse files
addrian-77eva-cosma
authored andcommitted
feat: reshuffle with mixed apps
Signed-off-by: Adrian Lungu <lunguadrian30@gmail.com>
1 parent d103051 commit fdb2fb6

1 file changed

Lines changed: 212 additions & 112 deletions

File tree

tockloader-lib/src/command_impl/reshuffle_apps.rs

Lines changed: 212 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,119 @@ pub fn reshuffle_apps(
188188
// addresses can be used. Otherwise, the algorithm will just look for the next
189189
// available address, leaving a lot of space in the front. This can happen
190190
// after uninstalling a rust app
191+
192+
for app in &rust_apps {
193+
print!("rust app address(es): ");
194+
for address in &app.compatible_addresses {
195+
if address.is_some() {
196+
print!("[{:#x}, {:#x}]", address.unwrap().0, address.unwrap().1);
197+
}
198+
}
199+
println!();
200+
}
201+
191202
rust_apps.sort_by_key(|app| app.compatible_addresses[0].unwrap().0);
203+
204+
let mut initial_configuration: Vec<Index> = Vec::new();
205+
let mut new_rust_app: Option<&FixedApp> = None;
206+
for app in &rust_apps {
207+
if app.installed {
208+
initial_configuration.push(app.as_index(
209+
Some(app.compatible_addresses[0].unwrap().1),
210+
app.compatible_addresses[0].unwrap().0,
211+
));
212+
} else {
213+
new_rust_app = Some(app);
214+
}
215+
}
216+
217+
log::info!("first intial configuration: ");
218+
for app in &initial_configuration {
219+
log::info!(
220+
"app idx {}, addr {:#x}, size {}",
221+
app.idx.unwrap(),
222+
app.address,
223+
app.size
224+
);
225+
}
226+
227+
if let Some(new_app) = new_rust_app {
228+
let mut found: bool = false;
229+
for candidate in new_app.compatible_addresses.iter().flatten() {
230+
let (flash_addr, ram_addr) = *candidate;
231+
let new_start = flash_addr;
232+
let new_end = flash_addr + new_app.size;
233+
log::info!(
234+
"checking for new_start {:#x}, new_end {:#x}",
235+
new_start,
236+
new_end
237+
);
238+
239+
// Check before first element
240+
if initial_configuration.is_empty() {
241+
initial_configuration.push(new_app.as_index(Some(ram_addr), flash_addr));
242+
found = true;
243+
break;
244+
}
245+
246+
// Check gap before first installed app
247+
let first = &initial_configuration[0];
248+
if new_end <= first.address {
249+
initial_configuration.insert(0, new_app.as_index(Some(ram_addr), flash_addr));
250+
found = true;
251+
break;
252+
}
253+
254+
// Check gaps between apps
255+
for i in 0..initial_configuration.len() - 1 {
256+
let current = &initial_configuration[i];
257+
let next = &initial_configuration[i + 1];
258+
259+
let gap_start = current.address + current.size;
260+
let gap_end = next.address;
261+
262+
if new_start >= gap_start && new_end <= gap_end {
263+
initial_configuration
264+
.insert(i + 1, new_app.as_index(Some(ram_addr), flash_addr));
265+
found = true;
266+
break;
267+
}
268+
}
269+
270+
// Check after last app
271+
let last = initial_configuration.last().unwrap();
272+
let gap_start = last.address + last.size;
273+
274+
log::info!(
275+
"checking for last gap {:#x}, obtained with addr {:#x}, size {}",
276+
gap_start,
277+
last.address,
278+
last.size
279+
);
280+
281+
if new_start >= gap_start {
282+
initial_configuration.push(new_app.as_index(Some(ram_addr), flash_addr));
283+
found = true;
284+
break;
285+
}
286+
}
287+
288+
if !found {
289+
warn!("No suitable space found for new app");
290+
return None;
291+
}
292+
}
293+
294+
println!("final intial configuration: ");
295+
for app in &initial_configuration {
296+
println!(
297+
"app idx {}, addr {:#x}, size {}",
298+
app.idx.unwrap(),
299+
app.address,
300+
app.size
301+
);
302+
}
303+
192304
log::info!("sorted rust apps {:#x?}", rust_apps);
193305
// panic!();
194306

@@ -211,136 +323,123 @@ pub fn reshuffle_apps(
211323
let mut total_padding: usize = 0;
212324
let mut permutation_index: usize = 0;
213325
let mut rust_index: usize = 0;
214-
let mut reordered_apps: Vec<Index> = Vec::new();
326+
let mut reordered_apps: Vec<Index> = initial_configuration.clone();
215327
let mut compatible_index: usize = 0;
216-
loop {
217-
let insert_c: bool; // every iteration will insert an app, or break if there are none left
218-
219-
// start either where the last app ends, or at start address if there are no apps
220-
let address = reordered_apps
221-
.last()
222-
.map_or(settings.start_address, |app| app.address + app.size);
223-
224-
if order.get(permutation_index).is_some() {
225-
// we have a C app
226-
if rust_apps.get(rust_index).is_some() {
227-
// we also have a rust app, insert C app only if it fits
228-
loop {
229-
if rust_apps[rust_index].compatible_addresses[compatible_index]
230-
.expect("No available binary (idk)")
231-
.0
232-
>= address
233-
{
234-
break;
235-
} else {
236-
compatible_index += 1;
237-
}
238-
}
239-
insert_c = c_apps[order[permutation_index]].size
240-
<= rust_apps[rust_index].compatible_addresses[compatible_index]
241-
.expect("No candidate (1)")
242-
.0
243-
- address;
328+
329+
for index in order {
330+
let c_app = &c_apps[index];
331+
let insert_size = c_app.size;
332+
333+
if reordered_apps.is_empty() {
334+
reordered_apps.push(c_app.as_index(None, settings.start_address));
335+
336+
continue;
337+
}
338+
339+
log::info!("checking for intermediate");
340+
let mut inserted = false;
341+
342+
for i in 0..reordered_apps.len() - 1 {
343+
let base = reordered_apps[i].address + reordered_apps[i].size;
344+
let gap = reordered_apps[i + 1].address - base;
345+
346+
let needed_padding = if !base.is_multiple_of(settings.page_size) {
347+
settings.page_size - base % settings.page_size
244348
} else {
245-
// we have only a C app, insert it accordingly
246-
insert_c = true;
247-
}
248-
} else {
249-
// we don't have a c app
250-
if rust_apps.get(rust_index).is_some() {
251-
loop {
252-
log::info!(
253-
"comparing rust app addr {:#x?} and address {:#x?}",
254-
rust_apps[rust_index].compatible_addresses[compatible_index]
255-
.unwrap()
256-
.0,
257-
address
349+
0
350+
};
351+
352+
let final_addr = base + needed_padding;
353+
354+
if insert_size + needed_padding <= gap {
355+
if needed_padding > 0 {
356+
total_padding += needed_padding as usize;
357+
358+
reordered_apps.insert(
359+
i + 1,
360+
Index {
361+
installed: false,
362+
idx: None,
363+
fixed: false,
364+
ram_address: None,
365+
address: base,
366+
size: needed_padding,
367+
},
258368
);
259-
if rust_apps[rust_index].compatible_addresses[compatible_index]
260-
.expect("No available binary (idk)")
261-
.0
262-
>= address
263-
{
264-
break;
265-
} else {
266-
compatible_index += 1;
267-
}
369+
370+
reordered_apps.insert(i + 2, c_app.as_index(None, final_addr));
371+
} else {
372+
reordered_apps.insert(i + 1, c_app.as_index(None, final_addr));
268373
}
269-
// we have a rust app, insert it
270-
insert_c = false;
271-
} else {
272-
// we don't have any app, break?
374+
375+
inserted = true;
273376
break;
274377
}
275378
}
276379

277-
let mut start_address = reordered_apps
278-
.last()
279-
.map_or(settings.start_address, |app| app.address + app.size);
380+
if !inserted {
381+
let last = reordered_apps.last().unwrap();
382+
let gap_start = last.address + last.size;
383+
384+
log::info!(
385+
"checking for last gap {:#x}, obtained with addr {:#x}, size {}",
386+
gap_start,
387+
last.address,
388+
last.size
389+
);
280390

281-
let needed_padding = if insert_c {
282-
if !start_address.is_multiple_of(settings.page_size) {
391+
let needed_padding = if !gap_start.is_multiple_of(settings.page_size) {
283392
// c app needs to be inserted at a multiple of page_size
284-
settings.page_size - start_address % settings.page_size
393+
settings.page_size - gap_start % settings.page_size
285394
} else {
286395
0
396+
};
397+
398+
if needed_padding > 0 {
399+
// insert a padding
400+
total_padding += needed_padding as usize;
401+
reordered_apps.push(Index {
402+
installed: false,
403+
idx: None,
404+
fixed: false,
405+
ram_address: None,
406+
address: settings.start_address + insert_size,
407+
size: needed_padding,
408+
});
409+
reordered_apps.push(c_app.as_index(None, gap_start + needed_padding));
410+
total_padding += needed_padding as usize;
411+
} else {
412+
reordered_apps.push(c_app.as_index(None, gap_start));
287413
}
288-
} else {
289-
// rust app needs to be inserted at a fixed address, pad until there
290-
rust_apps[rust_index].compatible_addresses[compatible_index]
291-
.expect("No compatible address! (3)")
292-
.0
293-
- start_address
294-
};
295-
296-
if needed_padding > 0 {
297-
// insert a padding
298-
total_padding += needed_padding as usize;
299-
reordered_apps.push(Index {
300-
installed: false,
301-
idx: None,
302-
fixed: false,
303-
ram_address: None,
304-
address: start_address,
305-
size: needed_padding,
306-
});
307-
308-
start_address += needed_padding as u64;
309414
}
415+
}
310416

311-
if insert_c {
312-
// insert the c app, also change its address
313-
let c_app = c_apps[order[permutation_index]].as_index(None, start_address);
314-
if c_app.idx.is_none() {
315-
panic!("C app has no index assigned!");
316-
}
417+
log::info!(
418+
"obtained config before padding check {:#x?}",
419+
reordered_apps
420+
);
317421

318-
reordered_apps.push(c_app);
319-
permutation_index += 1;
320-
} else {
321-
// insert the rust app, don't change its address because it is fixed
322-
let rust_app = rust_apps[rust_index].as_index(
323-
Some(
324-
rust_apps[rust_index].compatible_addresses[compatible_index]
325-
.expect("No compatible address! (4)")
326-
.1,
327-
),
328-
rust_apps[rust_index].compatible_addresses[compatible_index]
329-
.expect("No compatible address! (4)")
330-
.0,
422+
let mut i = 0;
423+
while i < reordered_apps.len() - 1 {
424+
let gap = reordered_apps[i + 1].address
425+
- (reordered_apps[i].address + reordered_apps[i].size);
426+
427+
if gap > 0 {
428+
reordered_apps.insert(
429+
i + 1,
430+
Index {
431+
installed: false,
432+
idx: None,
433+
fixed: false,
434+
ram_address: None,
435+
address: reordered_apps[i].address + reordered_apps[i].size,
436+
size: gap,
437+
},
331438
);
332-
log::debug!(
333-
"rust app flash {:#x?}, rust app ram {:#x?}",
334-
rust_app.address,
335-
rust_app.ram_address
336-
);
337-
if rust_app.idx.is_none() {
338-
panic!("Rust app has no index assigned!");
339-
}
340-
341-
reordered_apps.push(rust_app);
342-
rust_index += 1;
439+
i += 1; // skip over inserted padding
343440
}
441+
442+
i += 1;
344443
}
345444

346445
// find the configuration that uses the minimum padding
@@ -356,6 +455,7 @@ pub fn reshuffle_apps(
356455
}
357456
}
358457
log::info!("obtained config {:#x?}", saved_configuration);
458+
// panic!();
359459
Some(saved_configuration)
360460
}
361461

0 commit comments

Comments
 (0)