windows_topology_sys/
relation.rs1use std::io;
9
10use crate::processor_set::ProcessorSet;
11use crate::walk::{self, GroupAffinity, Record};
12
13const LTP_PC_SMT: u8 = 0x1;
18
19fn to_processor_set(masks: &[GroupAffinity]) -> ProcessorSet {
20 let mut set = ProcessorSet::empty();
21 for m in masks {
22 set = set.union(&ProcessorSet::from_group_mask(m.group, m.mask));
23 }
24 set
25}
26
27#[derive(Clone, Debug, PartialEq, Eq)]
30pub struct CoreRelation {
31 pub simultaneous_multithreading: bool,
34 pub efficiency_class: u8,
39 pub processors: ProcessorSet,
41}
42
43#[derive(Clone, Debug, PartialEq, Eq)]
45pub struct PackageRelation {
46 pub processors: ProcessorSet,
48}
49
50#[derive(Clone, Copy, Debug, PartialEq, Eq)]
57#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
58#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
59#[non_exhaustive]
60pub enum CacheKind {
61 Unified,
63 Instruction,
65 Data,
67 Trace,
69 Other(i32),
72}
73
74#[derive(Clone, Debug, PartialEq, Eq)]
76pub struct CacheRelation {
77 pub level: u8,
79 pub associativity: u8,
81 pub line_size: u16,
83 pub cache_size: u32,
85 pub cache_type: CacheKind,
87 pub processors: ProcessorSet,
89}
90
91#[derive(Clone, Debug, PartialEq, Eq)]
98pub struct NumaNodeRelation {
99 pub node_number: u32,
101 pub processors: ProcessorSet,
103}
104
105#[derive(Clone, Debug, PartialEq, Eq)]
107pub struct GroupRelation {
108 pub group: u16,
111 pub maximum_processor_count: u8,
113 pub active_processor_count: u8,
115 pub active_processors: ProcessorSet,
117}
118
119#[derive(Clone, Debug, Default, PartialEq, Eq)]
121pub struct Relations {
122 pub cores: Vec<CoreRelation>,
124 pub packages: Vec<PackageRelation>,
126 pub dies: Vec<PackageRelation>,
129 pub modules: Vec<PackageRelation>,
132 pub caches: Vec<CacheRelation>,
134 pub numa_nodes: Vec<NumaNodeRelation>,
136 pub groups: Vec<GroupRelation>,
138 pub anomalies: Vec<crate::EnumerationAnomaly>,
141}
142
143fn core_from(body: walk::ProcessorBody) -> CoreRelation {
144 CoreRelation {
145 simultaneous_multithreading: body.flags & LTP_PC_SMT != 0,
146 efficiency_class: body.efficiency_class,
147 processors: to_processor_set(&body.group_masks),
148 }
149}
150
151fn package_from(body: walk::ProcessorBody) -> PackageRelation {
152 PackageRelation {
153 processors: to_processor_set(&body.group_masks),
154 }
155}
156
157fn cache_from(body: walk::CacheBody) -> CacheRelation {
158 CacheRelation {
159 level: body.level,
160 associativity: body.associativity,
161 line_size: body.line_size,
162 cache_size: body.cache_size,
163 cache_type: walk::cache_kind_from_raw(body.cache_type),
164 processors: to_processor_set(&body.group_masks),
165 }
166}
167
168fn numa_from(body: walk::NumaNodeBody) -> NumaNodeRelation {
169 NumaNodeRelation {
170 node_number: body.node_number,
171 processors: to_processor_set(&body.group_masks),
172 }
173}
174
175fn groups_from(body: walk::GroupBody) -> Vec<GroupRelation> {
176 body.group_info
177 .into_iter()
178 .enumerate()
179 .map(|(index, info)| GroupRelation {
180 group: index as u16,
181 maximum_processor_count: info.maximum_processor_count,
182 active_processor_count: info.active_processor_count,
183 active_processors: ProcessorSet::from_group_mask(
184 index as u16,
185 info.active_processor_mask,
186 ),
187 })
188 .collect()
189}
190
191pub fn discover() -> io::Result<Relations> {
199 let mut relations = Relations::default();
200 let (walk_records, walk_anomalies) = walk::enumerate()?;
201 for record in walk_records {
202 match record {
203 Record::ProcessorCore(body) => relations.cores.push(core_from(body)),
204 Record::ProcessorPackage(body) => relations.packages.push(package_from(body)),
205 Record::ProcessorDie(body) => relations.dies.push(package_from(body)),
206 Record::ProcessorModule(body) => relations.modules.push(package_from(body)),
207 Record::Cache(body) => relations.caches.push(cache_from(body)),
208 Record::NumaNode(body) => relations.numa_nodes.push(numa_from(body)),
209 Record::Group(body) => relations.groups.extend(groups_from(body)),
210 Record::Unknown(_) => {}
211 }
212 }
213 relations.anomalies = walk_anomalies;
214 Ok(relations)
215}
216
217#[cfg(test)]
218mod tests;