Coverage Report

Created: 2025-11-16 06:34

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