use crate::topology::cpu::parse_cpu_list;
pub(super) const CPU_TYPE_NAMES: [&str; 2] = ["intel_atom", "intel_core"];
pub(super) fn capacities_from_cpu_types(
type_lists: &[Option<&str>],
logical_processors: usize,
) -> Option<Vec<u32>> {
let mut capacities = vec![None; logical_processors];
for (type_index, list) in type_lists.iter().enumerate() {
let Some(list) = list else { continue };
let raw = u32::try_from(type_index).ok()?;
for processor in parse_cpu_list(list) {
let slot = capacities.get_mut(usize::try_from(processor).ok()?)?;
if slot.is_some() {
return None;
}
*slot = Some(raw);
}
}
capacities.into_iter().collect()
}
pub(super) fn capacities_from_cpu_capacity(capacity_files: &[Option<&str>]) -> Option<Vec<u32>> {
if capacity_files.is_empty() {
return None;
}
capacity_files
.iter()
.map(|contents| {
let value = (*contents)?.trim().parse::<u32>().ok()?;
(value > 0).then_some(value)
})
.collect()
}
#[cfg(test)]
mod tests {
use super::{capacities_from_cpu_capacity, capacities_from_cpu_types, CPU_TYPE_NAMES};
#[test]
fn cpu_type_order_is_the_ranking_least_performant_first() {
assert_eq!(CPU_TYPE_NAMES, ["intel_atom", "intel_core"]);
let capacities = capacities_from_cpu_types(&[Some("0"), Some("1")], 2)
.expect("both type lists cover every processor");
let atom_index = 0;
let core_index = 1;
assert!(
capacities[atom_index] < capacities[core_index],
"{} must rank below {}",
CPU_TYPE_NAMES[atom_index],
CPU_TYPE_NAMES[core_index]
);
}
#[test]
fn intel_type_lists_rank_atom_below_core() {
let capacities = capacities_from_cpu_types(&[Some("4-7"), Some("0-3")], 8)
.expect("both type lists cover every processor");
assert_eq!(capacities, vec![1, 1, 1, 1, 0, 0, 0, 0]);
}
#[test]
fn a_single_cpu_type_covering_every_processor_is_homogeneous() {
let capacities = capacities_from_cpu_types(&[None, Some("0-3")], 4)
.expect("one type list covers every processor");
assert_eq!(capacities, vec![1, 1, 1, 1]);
}
#[test]
fn partial_overlapping_and_out_of_range_type_lists_are_absent() {
assert_eq!(
capacities_from_cpu_types(&[Some("0,1"), Some("2")], 4),
None
);
assert_eq!(
capacities_from_cpu_types(&[Some("0,1"), Some("1,2,3")], 4),
None
);
assert_eq!(capacities_from_cpu_types(&[None, Some("0-7")], 4), None);
assert_eq!(capacities_from_cpu_types(&[None, None], 4), None);
assert_eq!(capacities_from_cpu_types(&[], 4), None);
}
#[test]
fn cpu_capacity_values_are_read_verbatim_for_ranking() {
let capacities = capacities_from_cpu_capacity(&[
Some("462\n"),
Some("462\n"),
Some("462\n"),
Some("462\n"),
Some("1024\n"),
Some("1024\n"),
Some("1024\n"),
Some("1024\n"),
])
.expect("every processor reports a capacity");
assert_eq!(capacities, vec![462, 462, 462, 462, 1024, 1024, 1024, 1024]);
}
#[test]
fn a_uniform_cpu_capacity_is_homogeneous_not_absent() {
assert_eq!(
capacities_from_cpu_capacity(&[Some("1024"), Some("1024")]),
Some(vec![1024, 1024])
);
}
#[test]
fn missing_malformed_and_zero_capacities_are_absent() {
assert_eq!(capacities_from_cpu_capacity(&[Some("1024"), None]), None);
assert_eq!(
capacities_from_cpu_capacity(&[Some("1024"), Some("not-a-number")]),
None
);
assert_eq!(
capacities_from_cpu_capacity(&[Some("1024"), Some("0")]),
None
);
assert_eq!(
capacities_from_cpu_capacity(&[Some("1024"), Some("")]),
None
);
assert_eq!(capacities_from_cpu_capacity(&[]), None);
}
}