TestTopology

Struct TestTopology 

Source
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

Source

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.

Source

pub fn total_cpus(&self) -> usize

Total number of CPUs.

Source

pub fn num_llcs(&self) -> usize

Number of last-level caches.

Source

pub fn num_numa_nodes(&self) -> usize

Number of NUMA nodes.

Source

pub fn numa_node_ids(&self) -> &BTreeSet<usize>

NUMA node IDs as a BTreeSet.

Source

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.

Source

pub fn all_cpus(&self) -> &[usize]

All CPU IDs, sorted.

Source

pub fn all_cpuset(&self) -> BTreeSet<usize>

All CPU IDs as a BTreeSet.

Source

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.

Source

pub fn usable_cpuset(&self) -> BTreeSet<usize>

Usable CPUs as a BTreeSet.

Source

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.

Source

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).

Source

pub fn numa_aligned_cpuset(&self, node: usize) -> BTreeSet<usize>

CPUs in all LLCs belonging to NUMA node node as a BTreeSet.

Source

pub fn numa_nodes_for_cpuset(&self, cpus: &BTreeSet<usize>) -> BTreeSet<usize>

NUMA nodes covered by the given CPU set.

Source

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.

Source

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.

Source

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.

Source

pub fn split_by_llc(&self) -> Vec<BTreeSet<usize>>

One BTreeSet of CPUs per LLC.

Source

pub fn overlapping_cpusets( &self, n: usize, overlap_frac: f64, ) -> Vec<BTreeSet<usize>>

Generate n cpusets with overlap_frac overlap between adjacent sets.

Source

pub fn cpuset_string(cpus: &BTreeSet<usize>) -> String

Format a CPU set as a compact range string (e.g. "0-3,5,7-9").

Source

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.

Source

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

Source§

fn clone(&self) -> TestTopology

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for TestTopology

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl PartialEq for TestTopology

Source§

fn eq(&self, other: &TestTopology) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Eq for TestTopology

Source§

impl StructuralPartialEq for TestTopology

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<T> MaybeSend for T
where T: Send,

§

impl<T> MaybeSend for T
where T: Send,