/src/hwloc/include/hwloc/plugins.h
Line | Count | Source |
1 | | /* |
2 | | * SPDX-License-Identifier: BSD-3-Clause |
3 | | * Copyright © 2013-2026 Inria. All rights reserved. |
4 | | * Copyright © 2016 Cisco Systems, Inc. All rights reserved. |
5 | | * Copyright © 2025 Siemens Corporation and/or its affiliates. All rights reserved. |
6 | | * See COPYING in top-level directory. |
7 | | */ |
8 | | |
9 | | #ifndef HWLOC_PLUGINS_H |
10 | | #define HWLOC_PLUGINS_H |
11 | | |
12 | | /** \file |
13 | | * \brief Public interface for building hwloc plugins. |
14 | | */ |
15 | | |
16 | | struct hwloc_backend; |
17 | | |
18 | | #include "hwloc.h" |
19 | | |
20 | | #ifdef HWLOC_INSIDE_PLUGIN |
21 | | /* needed for hwloc_plugin_check_namespace() */ |
22 | | #ifdef HWLOC_HAVE_LTDL |
23 | | #include <ltdl.h> |
24 | | #elif !defined(HWLOC_WIN_SYS) |
25 | | #include <dlfcn.h> |
26 | | #endif |
27 | | #endif |
28 | | |
29 | | |
30 | | |
31 | | /** \defgroup hwlocality_disc_components Components and Plugins: Discovery components and backends |
32 | | * |
33 | | * \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified. |
34 | | * |
35 | | * @{ |
36 | | */ |
37 | | |
38 | | /** \brief Discovery component structure |
39 | | * |
40 | | * This is the major kind of components, taking care of the discovery. |
41 | | * They are registered by generic components, either statically-built or as plugins. |
42 | | */ |
43 | | struct hwloc_disc_component { |
44 | | /** \brief Name. |
45 | | * If this component is built as a plugin, this name does not have to match the plugin filename. |
46 | | */ |
47 | | const char *name; |
48 | | |
49 | | /** \brief Discovery phases performed by this component. |
50 | | * OR'ed set of ::hwloc_disc_phase_t |
51 | | */ |
52 | | unsigned phases; |
53 | | |
54 | | /** \brief Component phases to exclude, as an OR'ed set of ::hwloc_disc_phase_t. |
55 | | * |
56 | | * For a GLOBAL component, this usually includes all other phases (\c ~UL). |
57 | | * |
58 | | * Other components only exclude types that may bring conflicting |
59 | | * topology information. MISC components should likely not be excluded |
60 | | * since they usually bring non-primary additional information. |
61 | | */ |
62 | | unsigned excluded_phases; |
63 | | |
64 | | /** \brief Instantiate callback to create a backend from the component. |
65 | | * Parameters data1, data2, data3 are NULL except for components |
66 | | * that have special enabling routines such as hwloc_topology_set_xml(). */ |
67 | | struct hwloc_backend * (*instantiate)(struct hwloc_topology *topology, struct hwloc_disc_component *component, unsigned excluded_phases, const void *data1, const void *data2, const void *data3); |
68 | | |
69 | | /** \brief Component priority. |
70 | | * Used to sort topology->components, higher priority first. |
71 | | * Also used to decide between two components with the same name. |
72 | | * |
73 | | * Usual values are |
74 | | * 50 for native OS (or platform) components, |
75 | | * 45 for x86, |
76 | | * 40 for no-OS fallback, |
77 | | * 30 for global components (xml, synthetic), |
78 | | * 20 for pci, |
79 | | * 10 for other misc components (opencl etc.). |
80 | | */ |
81 | | unsigned priority; |
82 | | |
83 | | /** \brief Enabled by default. |
84 | | * If unset, if will be disabled unless explicitly requested. |
85 | | */ |
86 | | unsigned enabled_by_default; |
87 | | |
88 | | /** \private Used internally to list components by priority on topology->components |
89 | | * (the component structure is usually read-only, |
90 | | * the core copies it before using this field for queueing) |
91 | | */ |
92 | | struct hwloc_disc_component * next; |
93 | | }; |
94 | | |
95 | | /** \brief Discovery phase */ |
96 | | typedef enum hwloc_disc_phase_e { |
97 | | /** \brief xml or synthetic, platform-specific components. |
98 | | * Discovers everything including CPU, memory, I/O and everything else. |
99 | | * A component with a Global phase usually excludes all other phases. |
100 | | * \hideinitializer */ |
101 | | HWLOC_DISC_PHASE_GLOBAL = (1U<<0), |
102 | | |
103 | | /** \brief CPU discovery. |
104 | | * \hideinitializer */ |
105 | | HWLOC_DISC_PHASE_CPU = (1U<<1), |
106 | | |
107 | | /** \brief Attach memory to existing CPU objects. |
108 | | * \hideinitializer */ |
109 | | HWLOC_DISC_PHASE_MEMORY = (1U<<2), |
110 | | |
111 | | /** \brief Attach PCI devices and bridges to existing CPU objects. |
112 | | * \hideinitializer */ |
113 | | HWLOC_DISC_PHASE_PCI = (1U<<3), |
114 | | |
115 | | /** \brief I/O discovery that requires PCI devices (OS devices such as OpenCL, CUDA, etc.). |
116 | | * \hideinitializer */ |
117 | | HWLOC_DISC_PHASE_IO = (1U<<4), |
118 | | |
119 | | /** \brief Misc objects that gets added below anything else. |
120 | | * \hideinitializer */ |
121 | | HWLOC_DISC_PHASE_MISC = (1U<<5), |
122 | | |
123 | | /** \brief Annotating existing objects, adding distances, etc. |
124 | | * \hideinitializer */ |
125 | | HWLOC_DISC_PHASE_ANNOTATE = (1U<<6), |
126 | | |
127 | | /** \brief Annotating existing objects with a OS/hardware independent things, |
128 | | * for instance converting PCI vendor/model IDs into strings. |
129 | | * \hideinitializer */ |
130 | | HWLOC_DISC_PHASE_ANNOTATE_INDEPENDENT = (1U<<7), |
131 | | |
132 | | /** \brief Final tweaks to a ready-to-use topology. |
133 | | * This phase runs once the topology is loaded, before it is returned to the topology. |
134 | | * Hence it may only use the main hwloc API for modifying the topology, |
135 | | * for instance by restricting it, adding info attributes, etc. |
136 | | * \hideinitializer */ |
137 | | HWLOC_DISC_PHASE_TWEAK = (1U<<8) |
138 | | } hwloc_disc_phase_t; |
139 | | |
140 | | /** \brief Discovery status flags */ |
141 | | enum hwloc_disc_status_flag_e { |
142 | | /** \brief The sets of allowed resources were already retrieved \hideinitializer */ |
143 | | HWLOC_DISC_STATUS_FLAG_GOT_ALLOWED_RESOURCES = (1UL<<1) |
144 | | }; |
145 | | |
146 | | /** \brief Discovery status structure |
147 | | * |
148 | | * Used by the core and backends to inform about what has been/is being done |
149 | | * during the discovery process. |
150 | | */ |
151 | | struct hwloc_disc_status { |
152 | | /** \brief The current discovery phase that is performed. |
153 | | * Must match one of the phases in the component phases field. |
154 | | */ |
155 | | hwloc_disc_phase_t phase; |
156 | | |
157 | | /** \brief Dynamically excluded phases. |
158 | | * If a component decides during discovery that some phases are no longer needed. |
159 | | */ |
160 | | unsigned excluded_phases; |
161 | | |
162 | | /** \brief OR'ed set of ::hwloc_disc_status_flag_e */ |
163 | | unsigned long flags; |
164 | | }; |
165 | | |
166 | | /** \brief Discovery backend structure |
167 | | * |
168 | | * A backend is the instantiation of a discovery component. |
169 | | * When a component gets enabled for a topology, |
170 | | * its instantiate() callback creates a backend. |
171 | | * |
172 | | * hwloc_backend_alloc() initializes all fields to default values |
173 | | * that the component may change (except "component" and "next") |
174 | | * before enabling the backend with hwloc_backend_enable(). |
175 | | * |
176 | | * Most backends assume that the topology is_thissystem flag is |
177 | | * set because they talk to the underlying operating system. |
178 | | * However they may still be used in topologies without the |
179 | | * is_thissystem flag for debugging reasons. |
180 | | * In practice, they are usually auto-disabled in such cases |
181 | | * (excluded by xml or synthetic backends, or by environment |
182 | | * variables when changing the Linux fsroot or the x86 cpuid path). |
183 | | */ |
184 | | struct hwloc_backend { |
185 | | /** \private Reserved for the core, set by hwloc_backend_alloc() */ |
186 | | struct hwloc_disc_component * component; |
187 | | /** \private Reserved for the core, set by hwloc_backend_enable() */ |
188 | | struct hwloc_topology * topology; |
189 | | /** \private Reserved for the core. Set to 1 if forced through envvar, 0 otherwise. */ |
190 | | int envvar_forced; |
191 | | /** \private Reserved for the core. Used internally to list backends topology->backends. */ |
192 | | struct hwloc_backend * next; |
193 | | |
194 | | /** \brief Discovery phases performed by this component, possibly without some of them if excluded by other components. |
195 | | * OR'ed set of ::hwloc_disc_phase_t |
196 | | */ |
197 | | unsigned phases; |
198 | | |
199 | | /** \brief Backend flags, currently always 0. */ |
200 | | unsigned long flags; |
201 | | |
202 | | /** \brief Backend-specific 'is_thissystem' property. |
203 | | * Set to 0 if the backend disables the thissystem flag for this topology |
204 | | * (e.g. loading from xml or synthetic string, |
205 | | * or using a different fsroot on Linux, or a x86 CPUID dump). |
206 | | * Set to -1 if the backend doesn't care (default). |
207 | | */ |
208 | | int is_thissystem; |
209 | | |
210 | | /** \brief Callback for freeing things stored inside the private data. |
211 | | * May be NULL. |
212 | | */ |
213 | | void (*disable)(struct hwloc_backend *backend); |
214 | | |
215 | | /** \brief Main discovery callback. |
216 | | * returns -1 on error, either because it couldn't add its objects ot the existing topology, |
217 | | * or because of an actual discovery/gathering failure. |
218 | | * May be NULL. |
219 | | */ |
220 | | int (*discover)(struct hwloc_backend *backend, struct hwloc_disc_status *status); |
221 | | |
222 | | /** \brief Callback to retrieve the locality of a PCI object. |
223 | | * Called by the PCI core when attaching PCI hierarchy to CPU objects. |
224 | | * May be NULL. |
225 | | */ |
226 | | int (*get_pci_busid_cpuset)(struct hwloc_backend *backend, struct hwloc_pcidev_attr_s *busid, hwloc_bitmap_t cpuset); |
227 | | }; |
228 | | |
229 | | /** \brief Return the private data pointer at the end of a backend structure. */ |
230 | | #define HWLOC_BACKEND_PRIVATE_DATA(_backend) (void*)(((char*)(_backend)) + sizeof(struct hwloc_backend)) |
231 | | |
232 | | /** \brief Allocate a backend structure, set good default values, initialize backend->component and topology, etc. |
233 | | * The caller will then modify whatever needed, and call hwloc_backend_enable(). |
234 | | * If \p private_data_size is positive, additional space is allocated at the end |
235 | | * of the structure for storing backend private data. That space may be obtained |
236 | | * with HWLOC_BACKEND_PRIVATE_DATA() and may be freely modified by the backend. |
237 | | */ |
238 | | HWLOC_DECLSPEC struct hwloc_backend * hwloc_backend_alloc(struct hwloc_topology *topology, struct hwloc_disc_component *component, unsigned long private_data_size); |
239 | | |
240 | | /** \brief Enable a previously allocated and setup backend. */ |
241 | | HWLOC_DECLSPEC int hwloc_backend_enable(struct hwloc_backend *backend); |
242 | | |
243 | | /** @} */ |
244 | | |
245 | | |
246 | | |
247 | | |
248 | | /** \defgroup hwlocality_generic_components Components and Plugins: Generic components |
249 | | * |
250 | | * \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified. |
251 | | * |
252 | | * @{ |
253 | | */ |
254 | | |
255 | | /** \brief Generic component type */ |
256 | | typedef enum hwloc_component_type_e { |
257 | | /** \brief The data field must point to a struct hwloc_disc_component. */ |
258 | | HWLOC_COMPONENT_TYPE_DISC, |
259 | | |
260 | | /** \brief The data field must point to a struct hwloc_xml_component. */ |
261 | | HWLOC_COMPONENT_TYPE_XML |
262 | | } hwloc_component_type_t; |
263 | | |
264 | | /** \brief Generic component structure |
265 | | * |
266 | | * Generic components structure, either statically listed by configure in static-components.h |
267 | | * or dynamically loaded as a plugin. |
268 | | */ |
269 | | struct hwloc_component { |
270 | | /** \brief Component ABI version, set to ::HWLOC_COMPONENT_ABI */ |
271 | | unsigned abi; |
272 | | |
273 | | /** \brief Process-wide component initialization callback. |
274 | | * |
275 | | * This optional callback is called when the component is registered |
276 | | * to the hwloc core (after loading the plugin). |
277 | | * |
278 | | * When the component is built as a plugin, this callback |
279 | | * should call hwloc_check_plugin_namespace() |
280 | | * and return an negative error code on error. |
281 | | * |
282 | | * \p flags is always 0 for now. |
283 | | * |
284 | | * \return 0 on success, or a negative code on error. |
285 | | * |
286 | | * \note If the component uses ltdl for loading its own plugins, |
287 | | * it should load/unload them only in init() and finalize(), |
288 | | * to avoid race conditions with hwloc's use of ltdl. |
289 | | */ |
290 | | int (*init)(unsigned long flags); |
291 | | |
292 | | /** \brief Process-wide component termination callback. |
293 | | * |
294 | | * This optional callback is called after unregistering the component |
295 | | * from the hwloc core (before unloading the plugin). |
296 | | * |
297 | | * \p flags is always 0 for now. |
298 | | * |
299 | | * \note If the component uses ltdl for loading its own plugins, |
300 | | * it should load/unload them only in init() and finalize(), |
301 | | * to avoid race conditions with hwloc's use of ltdl. |
302 | | */ |
303 | | void (*finalize)(unsigned long flags); |
304 | | |
305 | | /** \brief Component type */ |
306 | | hwloc_component_type_t type; |
307 | | |
308 | | /** \brief Component flags, unused for now */ |
309 | | unsigned long flags; |
310 | | |
311 | | /** \brief Component data, pointing to a struct hwloc_disc_component or struct hwloc_xml_component. */ |
312 | | void * data; |
313 | | }; |
314 | | |
315 | | /** \brief Make sure that plugins can lookup core symbols. |
316 | | * |
317 | | * This is a sanity check to avoid lazy-lookup failures when libhwloc |
318 | | * is loaded within a plugin, and later tries to load its own plugins. |
319 | | * This may fail (and abort the program) if libhwloc symbols are in a |
320 | | * private namespace. |
321 | | * |
322 | | * \return 0 on success. |
323 | | * \return -1 if the plugin cannot be successfully loaded. The caller |
324 | | * plugin init() callback should return a negative error code as well. |
325 | | * |
326 | | * Plugins should call this function in their init() callback to avoid |
327 | | * later crashes if lazy symbol resolution is used by the upper layer that |
328 | | * loaded hwloc (e.g. OpenCL implementations using dlopen with RTLD_LAZY). |
329 | | * |
330 | | * \note The build system must define HWLOC_INSIDE_PLUGIN if and only if |
331 | | * building the caller as a plugin. |
332 | | * |
333 | | * \note This function should remain inline so plugins can call it even |
334 | | * when they cannot find libhwloc symbols. |
335 | | */ |
336 | | static __hwloc_inline int |
337 | | hwloc_plugin_check_namespace(const char *pluginname __hwloc_attribute_unused, const char *symbol __hwloc_attribute_unused) |
338 | 0 | { |
339 | 0 | #ifdef HWLOC_INSIDE_PLUGIN |
340 | 0 | void *sym; |
341 | 0 | #ifdef HWLOC_HAVE_LTDL |
342 | 0 | lt_dlhandle handle = lt_dlopen(NULL); |
343 | 0 | #elif defined(HWLOC_WIN_SYS) |
344 | 0 | HMODULE handle = GetModuleHandleA(NULL); |
345 | 0 | #else |
346 | 0 | void *handle = dlopen(NULL, RTLD_NOW|RTLD_LOCAL); |
347 | 0 | #endif |
348 | 0 | if (!handle) |
349 | 0 | /* cannot check, assume things will work */ |
350 | 0 | return 0; |
351 | 0 | #ifdef HWLOC_HAVE_LTDL |
352 | 0 | sym = lt_dlsym(handle, symbol); |
353 | 0 | lt_dlclose(handle); |
354 | 0 | #elif defined(HWLOC_WIN_SYS) |
355 | 0 | sym = GetModuleHandleA("hwloc.dll"); |
356 | 0 | FreeLibrary(handle); |
357 | 0 | #else |
358 | 0 | sym = dlsym(handle, symbol); |
359 | 0 | dlclose(handle); |
360 | 0 | #endif |
361 | 0 | if (!sym) { |
362 | 0 | static int verboseenv_checked = 0; |
363 | 0 | static int verboseenv_value = 0; |
364 | 0 | if (!verboseenv_checked) { |
365 | 0 | const char *verboseenv = getenv("HWLOC_PLUGINS_VERBOSE"); |
366 | 0 | verboseenv_value = verboseenv ? atoi(verboseenv) : 0; |
367 | 0 | verboseenv_checked = 1; |
368 | 0 | } |
369 | 0 | if (verboseenv_value) |
370 | 0 | fprintf(stderr, "Plugin `%s' disabling itself because it cannot find the `%s' core symbol.\n", |
371 | 0 | pluginname, symbol); |
372 | 0 | return -1; |
373 | 0 | } |
374 | 0 | #endif /* HWLOC_INSIDE_PLUGIN */ |
375 | 0 | return 0; |
376 | 0 | } Unexecuted instantiation: hwloc_fuzzer.c:hwloc_plugin_check_namespace Unexecuted instantiation: base64.c:hwloc_plugin_check_namespace |
377 | | |
378 | | /** @} */ |
379 | | |
380 | | |
381 | | |
382 | | |
383 | | /** \defgroup hwlocality_components_core_funcs Components and Plugins: Core functions to be used by components |
384 | | * |
385 | | * \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified. |
386 | | * |
387 | | * @{ |
388 | | */ |
389 | | |
390 | | /** \brief Get the mask of error messages to display |
391 | | * |
392 | | * The mask is a OR'ed set of HWLOC_SHOWMSG_* as defined below. |
393 | | * |
394 | | * By default, only critical errors are shown. |
395 | | * May be configured with the HWLOC_SHOW_ERRORS environment variable |
396 | | * lstopo enables all error messages (HWLOC_SHOW_ERRORS=all). |
397 | | * hwloc-bind enables binding error messages (HWLOC_SHOW_ERRORS=bind). |
398 | | * See \ref envvar_verbose |
399 | | * |
400 | | * Callers should rather use HWLOC_SHOW_ERRORS() to directly check |
401 | | * if some kind of messages are enabled. |
402 | | */ |
403 | | HWLOC_DECLSPEC unsigned long hwloc_show_errors_mask(void); |
404 | | |
405 | | #define HWLOC_SHOW_ERRORS(_flag) (hwloc_show_errors_mask() & (_flag)) |
406 | | |
407 | | #define HWLOC_SHOWMSG_CRITICAL (1UL<<0) |
408 | | /* Kinds of messages: failure to initialize CUDA, etc. |
409 | | * At least one of these should be passed to HWLOC_SHOW_ERRORS() */ |
410 | | #define HWLOC_SHOWMSG_BIND (1UL<<1) /* binding */ |
411 | | #define HWLOC_SHOWMSG_SYNTHETIC (1UL<<2) /* synthetic */ |
412 | | #define HWLOC_SHOWMSG_XML (1UL<<3) /* XML */ |
413 | | #define HWLOC_SHOWMSG_COMPONENTS (1UL<<4) /* Components */ |
414 | | #define HWLOC_SHOWMSG_PLUGINS (1UL<<5) /* Plugins */ |
415 | | #define HWLOC_SHOWMSG_RSMI (1UL<<6) /* RSMI */ |
416 | | #define HWLOC_SHOWMSG_CUDA (1UL<<7) /* CUDA */ |
417 | | #define HWLOC_SHOWMSG_NVML (1UL<<8) /* NVML */ |
418 | | #define HWLOC_SHOWMSG_L0 (1UL<<9) /* L0 */ |
419 | | #define HWLOC_SHOWMSG_OPENCL (1UL<<10) /* OpenCL */ |
420 | | #define HWLOC_SHOWMSG_GL (1UL<<11) /* GL */ |
421 | | #define HWLOC_SHOWMSG_OS (1UL<<12) /* Operating system */ |
422 | | #define HWLOC_SHOWMSG_PCI (1UL<<13) /* PCI */ |
423 | | #define HWLOC_SHOWMSG_CORE (1UL<<14) /* Issues in hwloc core */ |
424 | | #define HWLOC_SHOWMSG_MISC (1UL<<15) /* Misc messages that don't belong anywhere else */ |
425 | | #define HWLOC_SHOWMSG_USER (1UL<<16) /* Error caused by invalid user-given information (environment variables, etc) */ |
426 | | /* all messages */ |
427 | | #define HWLOC_SHOWMSG_ALL (~0UL) |
428 | | |
429 | | |
430 | | /** \brief Add an object to the topology. |
431 | | * |
432 | | * Insert new object \p obj in the topology starting under existing object \p root |
433 | | * (if \c NULL, the topology root object is used). |
434 | | * |
435 | | * It is sorted along the tree of other objects according to the inclusion of |
436 | | * cpusets, to eventually be added as a child of the smallest object including |
437 | | * this object. |
438 | | * |
439 | | * If the cpuset is empty, the type of the object (and maybe some attributes) |
440 | | * must be enough to find where to insert the object. This is especially true |
441 | | * for NUMA nodes with memory and no CPUs. |
442 | | * |
443 | | * The given object should not have children. |
444 | | * |
445 | | * This shall only be called before levels are built. |
446 | | * |
447 | | * The caller should check whether the object type is filtered-out before calling this function. |
448 | | * |
449 | | * The topology cpuset/nodesets will be enlarged to include the object sets. |
450 | | * |
451 | | * \p reason is a unique string identifying where and why this insertion call was performed |
452 | | * (it will be displayed in case of internal insertion error). |
453 | | * |
454 | | * Returns the object on success. |
455 | | * Returns NULL and frees obj on error. |
456 | | * Returns another object and frees obj if it was merged with an identical pre-existing object. |
457 | | */ |
458 | | HWLOC_DECLSPEC hwloc_obj_t |
459 | | hwloc__insert_object_by_cpuset(struct hwloc_topology *topology, hwloc_obj_t root, |
460 | | hwloc_obj_t obj, const char *reason); |
461 | | |
462 | | /** \brief Insert an object somewhere in the topology. |
463 | | * |
464 | | * It is added as the last child of the given parent. |
465 | | * The cpuset is completely ignored, so strange objects such as I/O devices should |
466 | | * preferably be inserted with this. |
467 | | * |
468 | | * When used for "normal" children with cpusets (when importing from XML |
469 | | * when duplicating a topology), the caller should make sure that: |
470 | | * - children are inserted in order, |
471 | | * - children cpusets do not intersect. |
472 | | * |
473 | | * The given object may have normal, I/O or Misc children, as long as they are in order as well. |
474 | | * These children must have valid parent and next_sibling pointers. |
475 | | * |
476 | | * The caller should check whether the object type is filtered-out before calling this function. |
477 | | */ |
478 | | HWLOC_DECLSPEC void hwloc_insert_object_by_parent(struct hwloc_topology *topology, hwloc_obj_t parent, hwloc_obj_t obj); |
479 | | |
480 | | /** \brief Allocate and initialize an object of the given type and physical index. |
481 | | * |
482 | | * If \p os_index is unknown or irrelevant, use \c HWLOC_UNKNOWN_INDEX. |
483 | | */ |
484 | | HWLOC_DECLSPEC hwloc_obj_t hwloc_alloc_setup_object(hwloc_topology_t topology, hwloc_obj_type_t type, unsigned os_index); |
485 | | |
486 | | /** \brief Setup object cpusets/nodesets by OR'ing its children. |
487 | | * |
488 | | * Used when adding an object late in the topology. |
489 | | * Will update the new object by OR'ing all its new children sets. |
490 | | * |
491 | | * Used when PCI backend adds a hostbridge parent, when distances |
492 | | * add a new Group, etc. |
493 | | */ |
494 | | HWLOC_DECLSPEC int hwloc_obj_add_children_sets(hwloc_obj_t obj); |
495 | | |
496 | | /** \brief Request a reconnection of children and levels in the topology. |
497 | | * |
498 | | * May be used by backends during discovery if they need arrays or lists |
499 | | * of object within levels or children to be fully connected. |
500 | | * |
501 | | * \p flags is currently unused, must 0. |
502 | | */ |
503 | | HWLOC_DECLSPEC int hwloc_topology_reconnect(hwloc_topology_t topology, unsigned long flags __hwloc_attribute_unused); |
504 | | |
505 | | /** @} */ |
506 | | |
507 | | |
508 | | |
509 | | |
510 | | /** \defgroup hwlocality_components_filtering Components and Plugins: Filtering objects |
511 | | * |
512 | | * \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified. |
513 | | * |
514 | | * @{ |
515 | | */ |
516 | | |
517 | | /** \brief Check whether the given PCI device classid is important. |
518 | | * |
519 | | * \return 1 if important, 0 otherwise. |
520 | | */ |
521 | | static __hwloc_inline int |
522 | | hwloc_filter_check_pcidev_subtype_important(unsigned classid) |
523 | 0 | { |
524 | 0 | unsigned baseclass = classid >> 8; |
525 | 0 | return (baseclass == 0x03 /* PCI_BASE_CLASS_DISPLAY */ |
526 | 0 | || baseclass == 0x02 /* PCI_BASE_CLASS_NETWORK */ |
527 | 0 | || baseclass == 0x01 /* PCI_BASE_CLASS_STORAGE */ |
528 | 0 | || baseclass == 0x00 /* Unclassified, for Atos/Bull BXI */ |
529 | 0 | || baseclass == 0x0b /* PCI_BASE_CLASS_PROCESSOR */ |
530 | 0 | || classid == 0x0c04 /* PCI_CLASS_SERIAL_FIBER */ |
531 | 0 | || classid == 0x0c06 /* PCI_CLASS_SERIAL_INFINIBAND */ |
532 | 0 | || classid == 0x0502 /* PCI_CLASS_MEMORY_CXL */ |
533 | 0 | || baseclass == 0x06 /* PCI_BASE_CLASS_BRIDGE with non-PCI downstream. the core will drop the useless ones later */ |
534 | 0 | || baseclass == 0x12 /* Processing Accelerators */); |
535 | 0 | } Unexecuted instantiation: hwloc_fuzzer.c:hwloc_filter_check_pcidev_subtype_important Unexecuted instantiation: base64.c:hwloc_filter_check_pcidev_subtype_important |
536 | | |
537 | | /** \brief Check whether the given OS device subtype is important. |
538 | | * |
539 | | * \return 1 if important, 0 otherwise. |
540 | | */ |
541 | | static __hwloc_inline int |
542 | | hwloc_filter_check_osdev_subtype_important(hwloc_obj_osdev_types_t subtype) |
543 | 0 | { |
544 | 0 | return (subtype && subtype != HWLOC_OBJ_OSDEV_DMA); |
545 | 0 | } Unexecuted instantiation: hwloc_fuzzer.c:hwloc_filter_check_osdev_subtype_important Unexecuted instantiation: base64.c:hwloc_filter_check_osdev_subtype_important |
546 | | |
547 | | /** \brief Check whether a non-I/O object type should be filtered-out. |
548 | | * |
549 | | * Cannot be used for I/O objects. |
550 | | * |
551 | | * \return 1 if the object type should be kept, 0 otherwise. |
552 | | */ |
553 | | static __hwloc_inline int |
554 | | hwloc_filter_check_keep_object_type(hwloc_topology_t topology, hwloc_obj_type_t type) |
555 | 0 | { |
556 | 0 | enum hwloc_type_filter_e filter = HWLOC_TYPE_FILTER_KEEP_NONE; |
557 | 0 | hwloc_topology_get_type_filter(topology, type, &filter); |
558 | 0 | assert(filter != HWLOC_TYPE_FILTER_KEEP_IMPORTANT); /* IMPORTANT only used for I/O */ |
559 | 0 | return filter == HWLOC_TYPE_FILTER_KEEP_NONE ? 0 : 1; |
560 | 0 | } Unexecuted instantiation: hwloc_fuzzer.c:hwloc_filter_check_keep_object_type Unexecuted instantiation: base64.c:hwloc_filter_check_keep_object_type |
561 | | |
562 | | /** \brief Check whether the given object should be filtered-out. |
563 | | * |
564 | | * \return 1 if the object type should be kept, 0 otherwise. |
565 | | */ |
566 | | static __hwloc_inline int |
567 | | hwloc_filter_check_keep_object(hwloc_topology_t topology, hwloc_obj_t obj) |
568 | 0 | { |
569 | 0 | hwloc_obj_type_t type = obj->type; |
570 | 0 | enum hwloc_type_filter_e filter = HWLOC_TYPE_FILTER_KEEP_NONE; |
571 | 0 | hwloc_topology_get_type_filter(topology, type, &filter); |
572 | 0 | if (filter == HWLOC_TYPE_FILTER_KEEP_NONE) |
573 | 0 | return 0; |
574 | 0 | if (filter == HWLOC_TYPE_FILTER_KEEP_IMPORTANT) { |
575 | 0 | if (type == HWLOC_OBJ_PCI_DEVICE) |
576 | 0 | return hwloc_filter_check_pcidev_subtype_important(obj->attr->pcidev.class_id); |
577 | 0 | if (type == HWLOC_OBJ_OS_DEVICE) |
578 | 0 | return hwloc_filter_check_osdev_subtype_important(obj->attr->osdev.types); |
579 | 0 | } |
580 | 0 | return 1; |
581 | 0 | } Unexecuted instantiation: hwloc_fuzzer.c:hwloc_filter_check_keep_object Unexecuted instantiation: base64.c:hwloc_filter_check_keep_object |
582 | | |
583 | | /** @} */ |
584 | | |
585 | | |
586 | | |
587 | | |
588 | | /** \defgroup hwlocality_components_pcidisc Components and Plugins: helpers for PCI discovery |
589 | | * |
590 | | * \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified. |
591 | | * |
592 | | * @{ |
593 | | */ |
594 | | |
595 | | /** \brief Return the offset of the given capability in the PCI config space buffer |
596 | | * |
597 | | * This function requires a 256-bytes config space. Unknown/unavailable bytes should be set to 0xff. |
598 | | */ |
599 | | HWLOC_DECLSPEC unsigned hwloc_pcidisc_find_cap(const unsigned char *config, unsigned cap); |
600 | | |
601 | | /** \brief Fill linkspeed by reading the PCI config space where PCI_CAP_ID_EXP is at position offset. |
602 | | * |
603 | | * Needs 20 bytes of EXP capability block starting at offset in the config space |
604 | | * for registers up to link status. |
605 | | */ |
606 | | HWLOC_DECLSPEC int hwloc_pcidisc_find_linkspeed(const unsigned char *config, unsigned offset, float *linkspeed); |
607 | | |
608 | | /** \brief Return the hwloc object type (PCI device or Bridge) for the given class and configuration space. |
609 | | * |
610 | | * This function requires 16 bytes of common configuration header at the beginning of config. |
611 | | */ |
612 | | HWLOC_DECLSPEC hwloc_obj_type_t hwloc_pcidisc_check_bridge_type(unsigned device_class, const unsigned char *config); |
613 | | |
614 | | /** \brief Fills the attributes of the given PCI bridge using the given PCI config space. |
615 | | * |
616 | | * This function requires 32 bytes of common configuration header at the beginning of config. |
617 | | * |
618 | | * Returns -1 and destroys /p obj if bridge fields are invalid. |
619 | | */ |
620 | | HWLOC_DECLSPEC int hwloc_pcidisc_find_bridge_buses(unsigned domain, unsigned bus, unsigned dev, unsigned func, |
621 | | unsigned *secondary_busp, unsigned *subordinate_busp, |
622 | | const unsigned char *config); |
623 | | |
624 | | /** \brief Insert a PCI object in the given PCI tree by looking at PCI bus IDs. |
625 | | * |
626 | | * If \p treep points to \c NULL, the new object is inserted there. |
627 | | */ |
628 | | HWLOC_DECLSPEC void hwloc_pcidisc_tree_insert_by_busid(struct hwloc_obj **treep, struct hwloc_obj *obj); |
629 | | |
630 | | /** \brief Add some hostbridges on top of the given tree of PCI objects and attach them to the topology. |
631 | | * |
632 | | * Other backends may lookup PCI objects or localities (for instance to attach OS devices) |
633 | | * by using hwloc_pcidisc_find_by_busid() or hwloc_pcidisc_find_busid_parent(). |
634 | | */ |
635 | | HWLOC_DECLSPEC int hwloc_pcidisc_tree_attach(struct hwloc_topology *topology, struct hwloc_obj *tree); |
636 | | |
637 | | /** @} */ |
638 | | |
639 | | |
640 | | |
641 | | |
642 | | /** \defgroup hwlocality_components_pcifind Components and Plugins: finding PCI objects during other discoveries |
643 | | * |
644 | | * \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified. |
645 | | * |
646 | | * @{ |
647 | | */ |
648 | | |
649 | | /** \brief Find the object or a parent of a PCI bus ID. |
650 | | * |
651 | | * When attaching a new object (typically an OS device) whose locality |
652 | | * is specified by PCI bus ID, this function returns the PCI object |
653 | | * to use as a parent for attaching. |
654 | | * |
655 | | * If the exact PCI device with this bus ID exists, it is returned. |
656 | | * Otherwise (for instance if it was filtered out), the function returns |
657 | | * another object with similar locality (for instance a parent bridge, |
658 | | * or the local CPU Package). |
659 | | */ |
660 | | HWLOC_DECLSPEC struct hwloc_obj * hwloc_pci_find_parent_by_busid(struct hwloc_topology *topology, unsigned domain, unsigned bus, unsigned dev, unsigned func); |
661 | | |
662 | | /** \brief Find the PCI device or bridge matching a PCI bus ID exactly. |
663 | | * |
664 | | * This is useful for adding specific information about some objects |
665 | | * based on their PCI id. When it comes to attaching objects based on |
666 | | * PCI locality, hwloc_pci_find_parent_by_busid() should be preferred. |
667 | | */ |
668 | | HWLOC_DECLSPEC struct hwloc_obj * hwloc_pci_find_by_busid(struct hwloc_topology *topology, unsigned domain, unsigned bus, unsigned dev, unsigned func); |
669 | | |
670 | | |
671 | | /** @} */ |
672 | | |
673 | | |
674 | | |
675 | | |
676 | | /** \defgroup hwlocality_components_distances Components and Plugins: distances |
677 | | * |
678 | | * \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified. |
679 | | * |
680 | | * @{ |
681 | | */ |
682 | | |
683 | | /** \brief Handle to a new distances structure during its addition to the topology. */ |
684 | | typedef void * hwloc_backend_distances_add_handle_t; |
685 | | |
686 | | /** \brief Create a new empty distances structure. |
687 | | * |
688 | | * This is identical to hwloc_distances_add_create() |
689 | | * but this variant is designed for backend inserting |
690 | | * distances during topology discovery. |
691 | | */ |
692 | | HWLOC_DECLSPEC hwloc_backend_distances_add_handle_t |
693 | | hwloc_backend_distances_add_create(hwloc_topology_t topology, |
694 | | const char *name, unsigned long kind, |
695 | | unsigned long flags); |
696 | | |
697 | | /** \brief Specify the objects and values in a new empty distances structure. |
698 | | * |
699 | | * This is similar to hwloc_distances_add_values() |
700 | | * but this variant is designed for backend inserting |
701 | | * distances during topology discovery. |
702 | | * |
703 | | * The only semantical difference is that \p objs and \p values |
704 | | * are not duplicated, but directly attached to the topology. |
705 | | * On success, these arrays are given to the core and should not |
706 | | * ever be freed by the caller anymore. |
707 | | */ |
708 | | HWLOC_DECLSPEC int |
709 | | hwloc_backend_distances_add_values(hwloc_topology_t topology, |
710 | | hwloc_backend_distances_add_handle_t handle, |
711 | | unsigned nbobjs, hwloc_obj_t *objs, |
712 | | hwloc_uint64_t *values, |
713 | | unsigned long flags); |
714 | | |
715 | | /** \brief Commit a new distances structure. |
716 | | * |
717 | | * This is similar to hwloc_distances_add_commit() |
718 | | * but this variant is designed for backend inserting |
719 | | * distances during topology discovery. |
720 | | */ |
721 | | HWLOC_DECLSPEC int |
722 | | hwloc_backend_distances_add_commit(hwloc_topology_t topology, |
723 | | hwloc_backend_distances_add_handle_t handle, |
724 | | unsigned long flags); |
725 | | |
726 | | /** @} */ |
727 | | |
728 | | |
729 | | |
730 | | |
731 | | #endif /* HWLOC_PLUGINS_H */ |