Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-10-04 09:11:02

0001 /*
0002  * SPDX-License-Identifier: BSD-3-Clause
0003  * Copyright © 2013-2024 Inria.  All rights reserved.
0004  * See COPYING in top-level directory.
0005  */
0006 
0007 /** \file
0008  * \brief Topology differences.
0009  */
0010 
0011 #ifndef HWLOC_DIFF_H
0012 #define HWLOC_DIFF_H
0013 
0014 #ifndef HWLOC_H
0015 #error Please include the main hwloc.h instead
0016 #endif
0017 
0018 
0019 #ifdef __cplusplus
0020 extern "C" {
0021 #elif 0
0022 }
0023 #endif
0024 
0025 
0026 /** \defgroup hwlocality_diff Topology differences
0027  *
0028  * Applications that manipulate many similar topologies, for instance
0029  * one for each node of a homogeneous cluster, may want to compress
0030  * topologies to reduce the memory footprint.
0031  *
0032  * This file offers a way to manipulate the difference between topologies
0033  * and export/import it to/from XML.
0034  * Compression may therefore be achieved by storing one topology
0035  * entirely while the others are only described by their differences
0036  * with the former.
0037  * The actual topology can be reconstructed when actually needed by
0038  * applying the precomputed difference to the reference topology.
0039  *
0040  * This interface targets very similar nodes.
0041  * Only very simple differences between topologies are actually
0042  * supported, for instance a change in the memory size, the name
0043  * of the object, or some info attribute.
0044  * More complex differences such as adding or removing objects cannot
0045  * be represented in the difference structures and therefore return
0046  * errors.
0047  * Differences between object sets or topology-wide allowed sets,
0048  * cannot be represented either.
0049  *
0050  * It means that there is no need to apply the difference when
0051  * looking at the tree organization (how many levels, how many
0052  * objects per level, what kind of objects, CPU and node sets, etc)
0053  * and when binding to objects.
0054  * However the difference must be applied when looking at object
0055  * attributes such as the name, the memory size or info attributes.
0056  *
0057  * @{
0058  */
0059 
0060 
0061 /** \brief Type of one object attribute difference.
0062  */
0063 typedef enum hwloc_topology_diff_obj_attr_type_e {
0064   /** \brief The object local memory is modified.
0065    * The union is a hwloc_topology_diff_obj_attr_u::hwloc_topology_diff_obj_attr_uint64_s
0066    * (and the index field is ignored).
0067    */
0068   HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_SIZE,
0069 
0070   /** \brief The object name is modified.
0071    * The union is a hwloc_topology_diff_obj_attr_u::hwloc_topology_diff_obj_attr_string_s
0072    * (and the name field is ignored).
0073    */
0074 
0075   HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_NAME,
0076   /** \brief the value of an info attribute is modified.
0077    * The union is a hwloc_topology_diff_obj_attr_u::hwloc_topology_diff_obj_attr_string_s.
0078    */
0079   HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_INFO
0080 } hwloc_topology_diff_obj_attr_type_t;
0081 
0082 /** \brief One object attribute difference.
0083  */
0084 union hwloc_topology_diff_obj_attr_u {
0085   struct hwloc_topology_diff_obj_attr_generic_s {
0086     /* each part of the union must start with these */
0087     hwloc_topology_diff_obj_attr_type_t type;
0088   } generic;
0089 
0090   /** \brief Integer attribute modification with an optional index. */
0091   struct hwloc_topology_diff_obj_attr_uint64_s {
0092     /* used for storing integer attributes */
0093     hwloc_topology_diff_obj_attr_type_t type;
0094     hwloc_uint64_t index; /* not used for SIZE */
0095     hwloc_uint64_t oldvalue;
0096     hwloc_uint64_t newvalue;
0097   } uint64;
0098 
0099   /** \brief String attribute modification with an optional name */
0100   struct hwloc_topology_diff_obj_attr_string_s {
0101     /* used for storing name and info pairs */
0102     hwloc_topology_diff_obj_attr_type_t type;
0103     char *name; /* not used for NAME */
0104     char *oldvalue;
0105     char *newvalue;
0106   } string;
0107 };
0108 
0109 
0110 /** \brief Type of one element of a difference list.
0111  */
0112 typedef enum hwloc_topology_diff_type_e {
0113   /** \brief An object attribute was changed.
0114    * The union is a hwloc_topology_diff_u::hwloc_topology_diff_obj_attr_s.
0115    */
0116   HWLOC_TOPOLOGY_DIFF_OBJ_ATTR,
0117 
0118   /** \brief The difference is too complex,
0119    * it cannot be represented. The difference below
0120    * this object has not been checked.
0121    * hwloc_topology_diff_build() will return 1.
0122    *
0123    * The union is a hwloc_topology_diff_u::hwloc_topology_diff_too_complex_s.
0124    */
0125   HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX
0126 } hwloc_topology_diff_type_t;
0127 
0128 /** \brief One element of a difference list between two topologies.
0129  */
0130 typedef union hwloc_topology_diff_u {
0131   struct hwloc_topology_diff_generic_s {
0132     /* each part of the union must start with these */
0133     hwloc_topology_diff_type_t type;
0134     union hwloc_topology_diff_u * next; /* pointer to the next element of the list, or NULL */
0135   } generic;
0136 
0137   /* A difference in an object attribute. */
0138   struct hwloc_topology_diff_obj_attr_s {
0139     hwloc_topology_diff_type_t type; /* must be ::HWLOC_TOPOLOGY_DIFF_OBJ_ATTR */
0140     union hwloc_topology_diff_u * next;
0141     /* List of attribute differences for a single object */
0142     int obj_depth;
0143     unsigned obj_index;
0144     union hwloc_topology_diff_obj_attr_u diff;
0145   } obj_attr;
0146 
0147   /* A difference that is too complex. */
0148   struct hwloc_topology_diff_too_complex_s {
0149     hwloc_topology_diff_type_t type; /* must be ::HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX */
0150     union hwloc_topology_diff_u * next;
0151     /* Where we had to stop computing the diff in the first topology */
0152     int obj_depth;
0153     unsigned obj_index;
0154   } too_complex;
0155 } * hwloc_topology_diff_t;
0156 
0157 
0158 /** \brief Compute the difference between 2 topologies.
0159  *
0160  * The difference is stored as a list of ::hwloc_topology_diff_t entries
0161  * starting at \p diff.
0162  * It is computed by doing a depth-first traversal of both topology trees
0163  * simultaneously.
0164  *
0165  * If the difference between 2 objects is too complex to be represented
0166  * (for instance if some objects have different types, or different numbers
0167  * of children), a special diff entry of type ::HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX
0168  * is queued.
0169  * The computation of the diff does not continue below these objects.
0170  * So each such diff entry means that the difference between two subtrees
0171  * could not be computed.
0172  *
0173  * \return 0 if the difference can be represented properly.
0174  *
0175  * \return 0 with \p diff pointing to NULL if there is no difference
0176  * between the topologies.
0177  *
0178  * \return 1 if the difference is too complex (see above). Some entries in
0179  * the list will be of type ::HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX.
0180  *
0181  * \return -1 on any other error.
0182  *
0183  * \note \p flags is currently not used. It should be 0.
0184  *
0185  * \note The output diff has to be freed with hwloc_topology_diff_destroy().
0186  *
0187  * \note The output diff can only be exported to XML or passed to
0188  * hwloc_topology_diff_apply() if 0 was returned, i.e. if no entry of type
0189  * ::HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX is listed.
0190  *
0191  * \note The output diff may be modified by removing some entries from
0192  * the list. The removed entries should be freed by passing them to
0193  * to hwloc_topology_diff_destroy() (possible as another list).
0194 */
0195 HWLOC_DECLSPEC int hwloc_topology_diff_build(hwloc_topology_t topology, hwloc_topology_t newtopology, unsigned long flags, hwloc_topology_diff_t *diff);
0196 
0197 /** \brief Flags to be given to hwloc_topology_diff_apply().
0198  */
0199 enum hwloc_topology_diff_apply_flags_e {
0200   /** \brief Apply topology diff in reverse direction.
0201    * \hideinitializer
0202    */
0203   HWLOC_TOPOLOGY_DIFF_APPLY_REVERSE = (1UL<<0)
0204 };
0205 
0206 /** \brief Apply a topology diff to an existing topology.
0207  *
0208  * \p flags is an OR'ed set of ::hwloc_topology_diff_apply_flags_e.
0209  *
0210  * The new topology is modified in place. hwloc_topology_dup()
0211  * may be used to duplicate it before patching.
0212  *
0213  * If the difference cannot be applied entirely, all previous applied
0214  * elements are unapplied before returning.
0215  *
0216  * \return 0 on success.
0217  *
0218  * \return -N if applying the difference failed while trying
0219  * to apply the N-th part of the difference. For instance -1
0220  * is returned if the very first difference element could not
0221  * be applied.
0222  */
0223 HWLOC_DECLSPEC int hwloc_topology_diff_apply(hwloc_topology_t topology, hwloc_topology_diff_t diff, unsigned long flags);
0224 
0225 /** \brief Destroy a list of topology differences.
0226  *
0227  * \return 0.
0228  */
0229 HWLOC_DECLSPEC int hwloc_topology_diff_destroy(hwloc_topology_diff_t diff);
0230 
0231 /** \brief Load a list of topology differences from a XML file.
0232  *
0233  * If not \c NULL, \p refname will be filled with the identifier
0234  * string of the reference topology for the difference file,
0235  * if any was specified in the XML file.
0236  * This identifier is usually the name of the other XML file
0237  * that contains the reference topology.
0238  *
0239  * \return 0 on success, -1 on error.
0240  *
0241  * \note the pointer returned in refname should later be freed
0242  * by the caller.
0243  */
0244 HWLOC_DECLSPEC int hwloc_topology_diff_load_xml(const char *xmlpath, hwloc_topology_diff_t *diff, char **refname);
0245 
0246 /** \brief Export a list of topology differences to a XML file.
0247  *
0248  * If not \c NULL, \p refname defines an identifier string
0249  * for the reference topology which was used as a base when
0250  * computing this difference.
0251  * This identifier is usually the name of the other XML file
0252  * that contains the reference topology.
0253  * This attribute is given back when reading the diff from XML.
0254  *
0255  * \return 0 on success, -1 on error.
0256  */
0257 HWLOC_DECLSPEC int hwloc_topology_diff_export_xml(hwloc_topology_diff_t diff, const char *refname, const char *xmlpath);
0258 
0259 /** \brief Load a list of topology differences from a XML buffer.
0260  *
0261  * Build a list of differences from the XML memory buffer given
0262  * at \p xmlbuffer and of length \p buflen (including an ending \c \0).
0263  * This buffer may have been filled earlier with
0264  * hwloc_topology_diff_export_xmlbuffer().
0265  *
0266  * If not \c NULL, \p refname will be filled with the identifier
0267  * string of the reference topology for the difference file,
0268  * if any was specified in the XML file.
0269  * This identifier is usually the name of the other XML file
0270  * that contains the reference topology.
0271  *
0272  * \return 0 on success, -1 on error.
0273  *
0274  * \note the pointer returned in refname should later be freed
0275  * by the caller.
0276   */
0277 HWLOC_DECLSPEC int hwloc_topology_diff_load_xmlbuffer(const char *xmlbuffer, int buflen, hwloc_topology_diff_t *diff, char **refname);
0278 
0279 /** \brief Export a list of topology differences to a XML buffer.
0280  *
0281  * If not \c NULL, \p refname defines an identifier string
0282  * for the reference topology which was used as a base when
0283  * computing this difference.
0284  * This identifier is usually the name of the other XML file
0285  * that contains the reference topology.
0286  * This attribute is given back when reading the diff from XML.
0287  *
0288  * The returned buffer ends with a \c \0 that is included in the returned
0289  * length.
0290  *
0291  * \return 0 on success, -1 on error.
0292  *
0293  * \note The XML buffer should later be freed with hwloc_free_xmlbuffer().
0294  */
0295 HWLOC_DECLSPEC int hwloc_topology_diff_export_xmlbuffer(hwloc_topology_diff_t diff, const char *refname, char **xmlbuffer, int *buflen);
0296 
0297 /** @} */
0298 
0299 
0300 #ifdef __cplusplus
0301 } /* extern "C" */
0302 #endif
0303 
0304 
0305 #endif /* HWLOC_DIFF_H */