1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
//! Exporting topologies to Synthetic
//!
//! Synthetic topologies are a very simple textual representation that may only
//! model certain topologies (they must be symmetric among other things, i.e.
//! all CPU cores should be equal), and only some aspects of them (e.g. no I/O
//! devices), but does so extremely concisely.
#[cfg(doc)]
use crate::topology::builder::TopologyBuilder;
use crate::{
errors::{self, RawHwlocError},
ffi::int,
topology::Topology,
};
use bitflags::bitflags;
use hwlocality_sys::{
hwloc_topology_export_synthetic_flags_e, HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_IGNORE_MEMORY,
HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_ATTRS,
HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_EXTENDED_TYPES,
HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_V1,
};
#[allow(unused)]
#[cfg(test)]
use similar_asserts::assert_eq;
use std::ffi::{c_char, CString};
/// # Exporting Topologies to Synthetic
//
// --- Implementation details ---
//
// Upstream docs: https://hwloc.readthedocs.io/en/v2.9/group__hwlocality__syntheticexport.html
impl Topology {
/// Export the topology as a synthetic string
///
/// This string may be loaded later using
/// [`TopologyBuilder::from_synthetic()`].
///
/// I/O and Misc children are ignored, the synthetic string only describes
/// normal children.
///
/// By default, the exported topology is only meant to be compatible with
/// the latest hwloc version. You may want to set some of the `flags` to be
/// compatible with older hwloc releases, at the cost of dropping support
/// for newer features.
///
/// # Errors
///
/// Synthetic topologies cannot express the full range of hardware
/// topologies supported by hwloc, for example they don't support asymmetric
/// topologies. An error will be returned if the current topology cannot be
/// expressed as a synthetic topology.
#[allow(clippy::missing_errors_doc)]
#[doc(alias = "hwloc_topology_export_synthetic")]
pub fn export_synthetic(&self, flags: SyntheticExportFlags) -> Result<String, RawHwlocError> {
let mut buf = vec![0u8; 1024];
loop {
let len =
// SAFETY: - Topology is trusted to contain a valid ptr (type invariant)
// - hwloc ops are trusted not to modify *const parameters
// - buffer and buflen are in sync (same vector)
// - flags only allows values supported by the active
// hwloc version
errors::call_hwloc_int_normal("hwloc_topology_export_synthetic", || unsafe {
hwlocality_sys::hwloc_topology_export_synthetic(
self.as_ptr(),
buf.as_mut_ptr().cast::<c_char>(),
buf.len(),
flags.bits(),
)
})?;
if int::expect_usize(len) == buf.len() - 1 {
// hwloc exactly filled the buffer, which suggests the
// output was truncated. Try a larget buffer.
buf.resize(2 * buf.len(), 0);
continue;
} else {
// Buffer seems alright, return it
return Ok(CString::from_vec_with_nul(buf)
.expect("Missing NUL from hwloc")
.into_string()
.expect("Synthetic export should yield an ASCII string"));
}
}
}
}
bitflags! {
/// Flags to be given to [`Topology::export_synthetic()`]
#[derive(Copy, Clone, Debug, Default, Eq, Hash, PartialEq)]
#[doc(alias = "hwloc_topology_export_synthetic_flags_e")]
pub struct SyntheticExportFlags: hwloc_topology_export_synthetic_flags_e {
/// Export extended types such as L2dcache as basic types such as Cache
///
/// This is required if loading the synthetic description with hwloc
/// < 1.9.
#[doc(alias = "HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_EXTENDED_TYPES")]
const NO_EXTENDED_TYPES = HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_EXTENDED_TYPES;
/// Do not export level attributes
///
/// Ignore level attributes such as memory/cache sizes or PU indices.
///
/// This is required if loading the synthetic description with hwloc
/// < 1.10.
#[doc(alias = "HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_ATTRS")]
const NO_ATTRIBUTES = HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_ATTRS;
/// Export the memory hierarchy as expected in hwloc 1.x
///
/// Instead of attaching memory children to levels, export single NUMA
/// node children as normal intermediate levels, when possible.
///
/// This is required if loading the synthetic description with hwloc
/// 1.x. However this may fail if some objects have multiple local NUMA
/// nodes.
#[doc(alias = "HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_V1")]
const V1 = HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_V1;
/// Do not export memory information
///
/// Only export the actual hierarchy of normal CPU-side objects and
/// ignore where memory is attached.
///
/// This is useful for when the hierarchy of CPUs is what really matters,
/// but it behaves as if there was a single machine-wide NUMA node.
#[doc(alias = "HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_IGNORE_MEMORY")]
const IGNORE_MEMORY = HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_IGNORE_MEMORY;
}
}
//
crate::impl_arbitrary_for_bitflags!(
SyntheticExportFlags,
hwloc_topology_export_synthetic_flags_e
);