Skip to main content

windows_topology_sys/
lib.rs

1// Copyright (c) 2026 Mike Grier
2//! Safe enumeration of Windows processor, cache, and memory topology, with a
3//! JSON-describable schema for discovered or synthetic topologies.
4//!
5//! # What this crate is
6//!
7//! Two things, deliberately separated:
8//!
9//! - **[`MachineMemoryTopology::discover`]** reads the running system's processor groups,
10//!   cores, caches, and NUMA nodes safely, via
11//!   [`GetLogicalProcessorInformationEx`][gpi].
12//! - **[`MachineMemoryTopology`]**, [`Domain`], and friends are plain data. They need no
13//!   Windows *API call* to construct: build one by hand, or (with the `serde`
14//!   feature) deserialize one from JSON written for a machine you do not
15//!   have. See [`examples/print_topology.rs`] for the shape a description
16//!   takes.
17//!
18//!   That is a claim about not calling the platform, **not** about other
19//!   platforms: this crate is Windows-only and does not build elsewhere. An
20//!   earlier version of these docs said it degraded to an empty shell on other
21//!   targets, which was never true and never built in CI -- raised in PR #56
22//!   review. That correction reached the prose but not the code, leaving two
23//!   modules ungated and the crate genuinely buildable off Windows with a
24//!   two-type API; a `compile_error!` now enforces the claim -- raised in
25//!   PR #61 review. Depend on it under
26//!   `[target.'cfg(windows)'.dependencies]`.
27//!
28//! [gpi]: https://learn.microsoft.com/windows/win32/api/sysinfoapi/nf-sysinfoapi-getlogicalprocessorinformationex
29//! [`examples/print_topology.rs`]: https://github.com/MikeGrier/windows-threadpool-sys/blob/main/crates/windows-topology-sys/examples/print_topology.rs
30//!
31//! # What this crate is not
32//!
33//! **Not a topology renderer.** It hands back faithful records and an
34//! open-kinded [`Domain`] over a set of processors; it does not decide what
35//! a "locality domain worth partitioning by" is. That decision -- by NUMA
36//! node, by last-level cache, by processor package -- belongs to the
37//! consumer, because the right answer depends on the workload and on
38//! hardware this crate cannot see (see `DESIGN-NOTES.md`'s "Why the NUMA
39//! node is the wrong key").
40//!
41//! **Not a partitioning policy.** This crate never decides how many rings,
42//! threads, or buffer pools a consumer should create. It exists to serve
43//! [`windows-ioring-sys`](https://docs.rs/windows-ioring-sys)'s locality
44//! story without that crate having to own such a policy either.
45//!
46//! **Not a device topology.** Domains cover processors and memory; nothing
47//! here names an NVMe controller, a NIC, or a GPU as a topology participant,
48//! and there is no per-initiator, per-target attributed-distance model
49//! (HMAT). Both were considered and explicitly declined for now -- see D-9 in
50//! `DESIGN-NOTES.md` for the reasoning and what would justify revisiting it.
51//! If your question is "which device sits close to which processor," this
52//! crate does not answer it.
53//!
54//! # Availability
55//!
56//! **Windows 11 / Windows Server 2025 and later.**
57//!
58//! That is the floor this crate claims, and it is a claim about what is
59//! *tested* rather than the oldest version the APIs might work on.
60//! `GetLogicalProcessorInformationEx` is documented back to Vista, and an
61//! earlier version of this section said so -- but [`MachineMemoryTopology::discover`]
62//! also calls `GetSystemCpuSetInformation`, which is documented only from
63//! Windows 10 / Server 2016, and this crate imports it statically. A down-level
64//! system would therefore fail to *load* the process, not merely get a poorer
65//! answer. Raised in PR #56 review.
66//!
67//! The floor is stated at Windows 11 / Server 2025 rather than at the older
68//! version the imports would technically permit, because nothing below that is
69//! tested here and an untested floor is a guess presented as a guarantee.
70//! Server 2025 is the server release built on the Windows 11 codebase; Server
71//! 2022 is not, despite the adjacent version numbers.
72//!
73//! Nothing here is gated on a runtime capability probe the way
74//! `windows-ioring-sys` needs one.
75//!
76//! # The JSON schema is not semver-covered
77//!
78//! With the `serde` feature, [`MachineMemoryTopology`] and [`Domain`] serialize to and
79//! deserialize from a JSON shape documented on [`Domain`] itself. That shape
80//! is **not** covered by this crate's semver contract (D-8 in
81//! `DESIGN-NOTES.md`), even though the Rust types that produce it are, as
82//! always. This is what makes the deferrals in D-9 safe to defer rather than
83//! merely convenient: extending the schema later is a schema evolution, not
84//! a breaking change to a promise never made.
85
86#![warn(missing_docs)]
87
88// The docs above claim this crate does not build off Windows. Until now that
89// was prose only: every module was `cfg(windows)` except `observed` and
90// `provenance`, so the crate really did build for a Linux target and hand back
91// a two-type API. Confirmed by building it, not by reading it.
92//
93// Enforced here rather than by gating those two modules, because gating alone
94// would leave a crate that compiles to nothing on other targets -- which is
95// the "empty shell" description a PR #56 review round already rejected as
96// false. A crate that will not build is the claim actually being made, so the
97// compiler should be the one making it. Raised in the PR #61 review.
98#[cfg(not(windows))]
99compile_error!(
100    "windows-topology-sys is Windows-only: it enumerates Windows processor, cache, and \
101     memory topology and has no meaning on another platform. Gate it in your manifest \
102     with [target.'cfg(windows)'.dependencies]."
103);
104
105#[cfg(windows)]
106mod anomaly;
107
108#[cfg(windows)]
109mod cpu_set;
110#[cfg(windows)]
111mod domain;
112#[cfg(windows)]
113mod granularity;
114#[cfg(windows)]
115mod observation;
116/// Absence with its reason attached.
117#[cfg(windows)]
118mod observed;
119#[cfg(windows)]
120mod processor_set;
121/// Where a topology's content came from.
122#[cfg(windows)]
123mod provenance;
124
125#[cfg(windows)]
126mod records;
127#[cfg(windows)]
128mod relation;
129#[cfg(windows)]
130mod topology;
131#[cfg(windows)]
132mod walk;
133
134#[cfg(windows)]
135pub use anomaly::{AnomalyKind, EnumerationAnomaly};
136#[cfg(windows)]
137pub use cpu_set::CpuSet;
138#[cfg(windows)]
139pub use domain::{AttributeValue, Domain, DomainKind, Processor, ProcessorFacts, ProcessorId};
140#[cfg(windows)]
141pub use granularity::{Granularity, Proximity};
142#[cfg(windows)]
143pub use observation::{AttributeObservation, Observation, ProcessorAttribute, Source};
144#[cfg(windows)]
145pub use observed::Observed;
146#[cfg(windows)]
147pub use processor_set::ProcessorSet;
148#[cfg(windows)]
149pub use provenance::Provenance;
150#[cfg(windows)]
151pub use relation::{
152    CacheKind, CacheRelation, CoreRelation, GroupRelation, NumaNodeRelation, PackageRelation,
153    Relations, discover,
154};
155#[cfg(windows)]
156pub use topology::{Coherence, MachineMemoryTopology};
157
158// The crate's markdown documentation is compiled as doctests, so an example that
159// a contract change invalidates breaks the build instead of quietly teaching the
160// old answer. `cfg(doctest)` means these items exist only while rustdoc collects
161// tests, so they cost an ordinary build nothing.
162#[cfg(all(doctest, windows))]
163#[doc = include_str!("../README.md")]
164struct ReadmeDoctests;