pub struct TestTopology { /* private fields */ }Expand description
CPU topology abstraction for test configuration.
Provides LLC-aware CPU partitioning, cpuset generation, NUMA
distance queries, and per-node memory introspection. Built from
sysfs (from_system), a VM spec
(from_vm_topology — takes a
crate::vmm::topology::Topology built via
Topology::new(numa, llcs, cores, threads)), or synthetic
parameters (synthetic, test-only).
Implementations§
Source§impl TestTopology
impl TestTopology
Sourcepub fn from_system() -> Result<Self>
pub fn from_system() -> Result<Self>
Discover topology from sysfs (reads /sys/devices/system/cpu/).
Intersects sysfs’s online-CPU set with the calling task’s
sched_getaffinity(0) cpuset so the resulting TestTopology
only enumerates CPUs the process can actually run on. In a
cgroup-cpuset-namespaced container /sys/devices/system/cpu
reports the full host CPU set (not cgroup-filtered per the
kernel’s drivers/base/cpu.c registration model), but
sched_setaffinity to CPUs outside the cgroup-allowed set
later fails with EPERM. Without this intersection an operator
running ktstr inside such a container sees confusing
affinity-EPERM errors far from the topology read; with it the
restriction surfaces at construction with a warn that names
the dropped CPUs.
Sourcepub fn total_cpus(&self) -> usize
pub fn total_cpus(&self) -> usize
Total number of CPUs.
Sourcepub fn num_numa_nodes(&self) -> usize
pub fn num_numa_nodes(&self) -> usize
Number of NUMA nodes.
Sourcepub fn numa_node_ids(&self) -> &BTreeSet<usize>
pub fn numa_node_ids(&self) -> &BTreeSet<usize>
NUMA node IDs as a BTreeSet.
Sourcepub fn llcs(&self) -> &[LlcInfo]
pub fn llcs(&self) -> &[LlcInfo]
All LLC domains.
§Ordering
Returned slice is ordered by LLC id (ascending), not by
first-CPU. Both from_system and
from_vm_topology build the LLC
list by iterating a BTreeMap<llc_id, LlcInfo>::into_values(),
so the result is deterministic and stable across runs. When
sysfs assigns non-contiguous LLC ids (cache id file, or
shared_cpu_list.min() fallback), the slice order can differ
from CPU order — callers that need CPU-sorted LLCs must
sort by llc.cpus()[0] themselves.
Sourcepub fn all_cpuset(&self) -> BTreeSet<usize>
pub fn all_cpuset(&self) -> BTreeSet<usize>
All CPU IDs as a BTreeSet.
Sourcepub fn usable_cpus(&self) -> &[usize]
pub fn usable_cpus(&self) -> &[usize]
CPUs available for workload placement. When the topology has more than 2 CPUs, the last CPU is reserved for the root cgroup (cgroup 0); with 2 or fewer CPUs, every CPU is returned.
Sourcepub fn usable_cpuset(&self) -> BTreeSet<usize>
pub fn usable_cpuset(&self) -> BTreeSet<usize>
Usable CPUs as a BTreeSet.
Sourcepub fn cpus_in_llc(&self, idx: usize) -> &[usize]
pub fn cpus_in_llc(&self, idx: usize) -> &[usize]
CPUs belonging to LLC at index idx.
Out-of-range indices return an empty slice rather than
panicking. Construction guarantees at least one LLC (see
TestTopology::from_vm_topology_with_memory), so the only
way to hit the out-of-range branch is passing an index larger
than num_llcs — a caller bug that used to
crash the whole scheduler test run.
Sourcepub fn llc_aligned_cpuset(&self, idx: usize) -> BTreeSet<usize>
pub fn llc_aligned_cpuset(&self, idx: usize) -> BTreeSet<usize>
CPUs in LLC idx as a BTreeSet. See cpus_in_llc
for the out-of-range behavior (returns an empty set).
Sourcepub fn numa_aligned_cpuset(&self, node: usize) -> BTreeSet<usize>
pub fn numa_aligned_cpuset(&self, node: usize) -> BTreeSet<usize>
CPUs in all LLCs belonging to NUMA node node as a BTreeSet.
Sourcepub fn numa_nodes_for_cpuset(&self, cpus: &BTreeSet<usize>) -> BTreeSet<usize>
pub fn numa_nodes_for_cpuset(&self, cpus: &BTreeSet<usize>) -> BTreeSet<usize>
NUMA nodes covered by the given CPU set.
Sourcepub fn node_meminfo(&self, node_id: usize) -> Option<&NodeMemInfo>
pub fn node_meminfo(&self, node_id: usize) -> Option<&NodeMemInfo>
Per-node memory info. Returns None when the node ID is not
present or meminfo is unavailable.
Sourcepub fn numa_distance(&self, from: usize, to: usize) -> u8
pub fn numa_distance(&self, from: usize, to: usize) -> u8
Inter-node NUMA distance. Returns 255 when either node ID is not present, matching the kernel’s unreachable distance.
Sourcepub fn is_memory_only(&self, node_id: usize) -> bool
pub fn is_memory_only(&self, node_id: usize) -> bool
Whether the node is memory-only (has RAM but no CPUs). Typical for CXL-attached memory tiers.
Sourcepub fn split_by_llc(&self) -> Vec<BTreeSet<usize>>
pub fn split_by_llc(&self) -> Vec<BTreeSet<usize>>
One BTreeSet of CPUs per LLC.
Sourcepub fn overlapping_cpusets(
&self,
n: usize,
overlap_frac: f64,
) -> Vec<BTreeSet<usize>>
pub fn overlapping_cpusets( &self, n: usize, overlap_frac: f64, ) -> Vec<BTreeSet<usize>>
Generate n cpusets with overlap_frac overlap between adjacent sets.
Sourcepub fn cpuset_string(cpus: &BTreeSet<usize>) -> String
pub fn cpuset_string(cpus: &BTreeSet<usize>) -> String
Format a CPU set as a compact range string (e.g. "0-3,5,7-9").
Sourcepub fn from_vm_topology(topo: &Topology) -> Self
pub fn from_vm_topology(topo: &Topology) -> Self
Build a TestTopology from a Topology.
Populates LLCs, NUMA nodes, distances, per-node memory info,
and memory-only node flags from the VM spec. Handles both
uniform and explicit-node topologies. For uniform topologies,
pass total_memory_mib to populate per-node memory info; when
None, memory info is omitted.
§Signature asymmetry with from_system
from_system returns Result because sysfs I/O is a
runtime-failable operation (unreadable files, cgroup-restricted
views, non-Linux hosts). from_vm_topology infallibly returns
Self because its input is already validated: every
Topology reaches this
function via Topology::new, which asserts llcs > 0,
cores_per_llc > 0, threads_per_core > 0, and
numa_nodes > 0 at construction time. The remaining asserts
inside this function guard against hand-constructed Topology
struct literals that bypass Topology::new; they never fire
for any Topology obtained through the normal constructor.
§Panics
Panics if topo was constructed via struct literal
(bypassing Topology::new) with llcs == 0,
cores_per_llc == 0, threads_per_core == 0, or
numa_nodes == 0. Inputs obtained through Topology::new
satisfy the invariants and cannot trigger these asserts.
Sourcepub fn from_vm_topology_with_memory(
topo: &Topology,
total_memory_mib: Option<u32>,
) -> Self
pub fn from_vm_topology_with_memory( topo: &Topology, total_memory_mib: Option<u32>, ) -> Self
Build a TestTopology with optional total memory for uniform topologies.
§Panics
Panics if topo was constructed via struct literal
(bypassing Topology::new) with llcs == 0,
cores_per_llc == 0, threads_per_core == 0, or
numa_nodes == 0. Inputs obtained through Topology::new
satisfy the invariants and cannot trigger these asserts.
Trait Implementations§
Source§impl Clone for TestTopology
impl Clone for TestTopology
Source§fn clone(&self) -> TestTopology
fn clone(&self) -> TestTopology
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for TestTopology
impl Debug for TestTopology
Source§impl PartialEq for TestTopology
impl PartialEq for TestTopology
impl Eq for TestTopology
impl StructuralPartialEq for TestTopology
Auto Trait Implementations§
impl Freeze for TestTopology
impl RefUnwindSafe for TestTopology
impl Send for TestTopology
impl Sync for TestTopology
impl Unpin for TestTopology
impl UnwindSafe for TestTopology
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more