1 /*
2 * Copyright © 2009 CNRS
3 * Copyright © 2009-2021 Inria. All rights reserved.
4 * Copyright © 2009-2012, 2020 Université Bordeaux
5 * Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
6 *
7 * See COPYING in top-level directory.
8 */
9
10 /* Internal types and helpers. */
11
12
13 #ifdef HWLOC_INSIDE_PLUGIN
14 /*
15 * these declarations are internal only, they are not available to plugins
16 * (many functions below are internal static symbols).
17 */
18 #error This file should not be used in plugins
19 #endif
20
21
22 #ifndef HWLOC_PRIVATE_H
23 #define HWLOC_PRIVATE_H
24
25 #include "private/autogen/config.h"
26 #include "hwloc.h"
27 #include "hwloc/bitmap.h"
28 #include "private/components.h"
29 #include "private/misc.h"
30
31 #include <sys/types.h>
32 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35 #ifdef HAVE_STDINT_H
36 #include <stdint.h>
37 #endif
38 #ifdef HAVE_SYS_UTSNAME_H
39 #include <sys/utsname.h>
40 #endif
41 #include <string.h>
42
43 #define HWLOC_TOPOLOGY_ABI 0x20400 /* version of the layout of struct topology */
44
45 struct hwloc_internal_location_s {
46 enum hwloc_location_type_e type;
47 union {
48 struct {
49 hwloc_obj_t obj; /* cached between refreshes */
50 uint64_t gp_index;
51 hwloc_obj_type_t type;
52 } object; /* if type == HWLOC_LOCATION_TYPE_OBJECT */
53 hwloc_cpuset_t cpuset; /* if type == HWLOC_LOCATION_TYPE_CPUSET */
54 } location;
55 };
56
57 /*****************************************************
58 * WARNING:
59 * changes below in this structure (and its children)
60 * should cause a bump of HWLOC_TOPOLOGY_ABI.
61 *****************************************************/
62
63 struct hwloc_topology {
64 unsigned topology_abi;
65
66 unsigned nb_levels; /* Number of horizontal levels */
67 unsigned nb_levels_allocated; /* Number of levels allocated and zeroed in level_nbobjects and levels below */
68 unsigned *level_nbobjects; /* Number of objects on each horizontal level */
69 struct hwloc_obj ***levels; /* Direct access to levels, levels[l = 0 .. nblevels-1][0..level_nbobjects[l]] */
70 unsigned long flags;
71 int type_depth[HWLOC_OBJ_TYPE_MAX];
72 enum hwloc_type_filter_e type_filter[HWLOC_OBJ_TYPE_MAX];
73 int is_thissystem;
74 int is_loaded;
75 int modified; /* >0 if objects were added/removed recently, which means a reconnect is needed */
76 hwloc_pid_t pid; /* Process ID the topology is view from, 0 for self */
77 void *userdata;
78 uint64_t next_gp_index;
79
80 void *adopted_shmem_addr;
81 size_t adopted_shmem_length;
82
83 #define HWLOC_NR_SLEVELS 6
84 #define HWLOC_SLEVEL_NUMANODE 0
85 #define HWLOC_SLEVEL_BRIDGE 1
86 #define HWLOC_SLEVEL_PCIDEV 2
87 #define HWLOC_SLEVEL_OSDEV 3
88 #define HWLOC_SLEVEL_MISC 4
89 #define HWLOC_SLEVEL_MEMCACHE 5
90 /* order must match negative depth, it's asserted in setup_defaults() */
91 #define HWLOC_SLEVEL_FROM_DEPTH(x) (HWLOC_TYPE_DEPTH_NUMANODE-(x))
92 #define HWLOC_SLEVEL_TO_DEPTH(x) (HWLOC_TYPE_DEPTH_NUMANODE-(x))
93 struct hwloc_special_level_s {
94 unsigned nbobjs;
95 struct hwloc_obj **objs;
96 struct hwloc_obj *first, *last; /* Temporarily used while listing object before building the objs array */
97 } slevels[HWLOC_NR_SLEVELS];
98
99 hwloc_bitmap_t allowed_cpuset;
100 hwloc_bitmap_t allowed_nodeset;
101
102 struct hwloc_binding_hooks {
103 /* These are actually rather OS hooks since some of them are not about binding */
104 int (*set_thisproc_cpubind)(hwloc_topology_t topology, hwloc_const_cpuset_t set, int flags);
105 int (*get_thisproc_cpubind)(hwloc_topology_t topology, hwloc_cpuset_t set, int flags);
106 int (*set_thisthread_cpubind)(hwloc_topology_t topology, hwloc_const_cpuset_t set, int flags);
107 int (*get_thisthread_cpubind)(hwloc_topology_t topology, hwloc_cpuset_t set, int flags);
108 int (*set_proc_cpubind)(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_cpuset_t set, int flags);
109 int (*get_proc_cpubind)(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_cpuset_t set, int flags);
110 #ifdef hwloc_thread_t
111 int (*set_thread_cpubind)(hwloc_topology_t topology, hwloc_thread_t tid, hwloc_const_cpuset_t set, int flags);
112 int (*get_thread_cpubind)(hwloc_topology_t topology, hwloc_thread_t tid, hwloc_cpuset_t set, int flags);
113 #endif
114
115 int (*get_thisproc_last_cpu_location)(hwloc_topology_t topology, hwloc_cpuset_t set, int flags);
116 int (*get_thisthread_last_cpu_location)(hwloc_topology_t topology, hwloc_cpuset_t set, int flags);
117 int (*get_proc_last_cpu_location)(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_cpuset_t set, int flags);
118
119 int (*set_thisproc_membind)(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags);
120 int (*get_thisproc_membind)(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags);
121 int (*set_thisthread_membind)(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags);
122 int (*get_thisthread_membind)(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags);
123 int (*set_proc_membind)(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags);
124 int (*get_proc_membind)(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags);
125 int (*set_area_membind)(hwloc_topology_t topology, const void *addr, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags);
126 int (*get_area_membind)(hwloc_topology_t topology, const void *addr, size_t len, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags);
127 int (*get_area_memlocation)(hwloc_topology_t topology, const void *addr, size_t len, hwloc_nodeset_t nodeset, int flags);
128 /* This has to return the same kind of pointer as alloc_membind, so that free_membind can be used on it */
129 void *(*alloc)(hwloc_topology_t topology, size_t len);
130 /* alloc_membind has to always succeed if !(flags & HWLOC_MEMBIND_STRICT).
131 * see hwloc_alloc_or_fail which is convenient for that. */
132 void *(*alloc_membind)(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags);
133 int (*free_membind)(hwloc_topology_t topology, void *addr, size_t len);
134
135 int (*get_allowed_resources)(hwloc_topology_t topology);
136 } binding_hooks;
137
138 struct hwloc_topology_support support;
139
140 void (*userdata_export_cb)(void *reserved, struct hwloc_topology *topology, struct hwloc_obj *obj);
141 void (*userdata_import_cb)(struct hwloc_topology *topology, struct hwloc_obj *obj, const char *name, const void *buffer, size_t length);
142 int userdata_not_decoded;
143
144 struct hwloc_internal_distances_s {
145 char *name; /* FIXME: needs an API to set it from user */
146
147 unsigned id; /* to match the container id field of public distances structure
148 * not exported to XML, regenerated during _add()
149 */
150
151 /* if all objects have the same type, different_types is NULL and unique_type is valid.
152 * otherwise unique_type is HWLOC_OBJ_TYPE_NONE and different_types contains individual objects types.
153 */
154 hwloc_obj_type_t unique_type;
155 hwloc_obj_type_t *different_types;
156
157 /* add union hwloc_obj_attr_u if we ever support groups */
158 unsigned nbobjs;
159 uint64_t *indexes; /* array of OS or GP indexes before we can convert them into objs.
160 * OS indexes for distances covering only PUs or only NUMAnodes.
161 */
162 #define HWLOC_DIST_TYPE_USE_OS_INDEX(_type) ((_type) == HWLOC_OBJ_PU || (_type == HWLOC_OBJ_NUMANODE))
163 uint64_t *values; /* distance matrices, ordered according to the above indexes/objs array.
164 * distance from i to j is stored in slot i*nbnodes+j.
165 */
166 unsigned long kind;
167
168 #define HWLOC_INTERNAL_DIST_FLAG_OBJS_VALID (1U<<0) /* if the objs array is valid below */
169 #define HWLOC_INTERNAL_DIST_FLAG_NOT_COMMITTED (1U<<1) /* if the distances isn't in the list yet */
170 unsigned iflags;
171
172 /* objects are currently stored in physical_index order */
173 hwloc_obj_t *objs; /* array of objects */
174
175 struct hwloc_internal_distances_s *prev, *next;
176 } *first_dist, *last_dist;
177 unsigned next_dist_id;
178
179 /* memory attributes */
180 unsigned nr_memattrs;
181 struct hwloc_internal_memattr_s {
182 /* memattr info */
183 char *name; /* TODO unit is implicit, in the documentation of standard attributes, or in the name? */
184 unsigned long flags;
185 #define HWLOC_IMATTR_FLAG_STATIC_NAME (1U<<0) /* no need to free name */
186 #define HWLOC_IMATTR_FLAG_CACHE_VALID (1U<<1) /* target and initiator are valid */
187 #define HWLOC_IMATTR_FLAG_CONVENIENCE (1U<<2) /* convenience attribute reporting values from non-memattr attributes (R/O and no actual targets stored) */
188 unsigned iflags;
189
190 /* array of values */
191 unsigned nr_targets;
192 struct hwloc_internal_memattr_target_s {
193 /* target object */
194 hwloc_obj_t obj; /* cached between refreshes */
195 hwloc_obj_type_t type;
196 unsigned os_index; /* only used temporarily during discovery when there's no obj/gp_index yet */
197 hwloc_uint64_t gp_index;
198
199 /* value if there are no initiator for this attr */
200 hwloc_uint64_t noinitiator_value;
201 /* initiators otherwise */
202 unsigned nr_initiators;
203 struct hwloc_internal_memattr_initiator_s {
204 struct hwloc_internal_location_s initiator;
205 hwloc_uint64_t value;
206 } *initiators;
207 } *targets;
208 } *memattrs;
209
210 /* hybridcpus */
211 unsigned nr_cpukinds;
212 unsigned nr_cpukinds_allocated;
213 struct hwloc_internal_cpukind_s {
214 hwloc_cpuset_t cpuset;
215 #define HWLOC_CPUKIND_EFFICIENCY_UNKNOWN -1
216 int efficiency;
217 int forced_efficiency; /* returned by the hardware or OS if any */
218 hwloc_uint64_t ranking_value; /* internal value for ranking */
219 unsigned nr_infos;
220 struct hwloc_info_s *infos;
221 } *cpukinds;
222
223 int grouping;
224 int grouping_verbose;
225 unsigned grouping_nbaccuracies;
226 float grouping_accuracies[5];
227 unsigned grouping_next_subkind;
228
229 /* list of enabled backends. */
230 struct hwloc_backend * backends;
231 struct hwloc_backend * get_pci_busid_cpuset_backend; /* first backend that provides get_pci_busid_cpuset() callback */
232 unsigned backend_phases;
233 unsigned backend_excluded_phases;
234
235 /* memory allocator for topology objects */
236 struct hwloc_tma * tma;
237
238 /*****************************************************
239 * WARNING:
240 * changes above in this structure (and its children)
241 * should cause a bump of HWLOC_TOPOLOGY_ABI.
242 *****************************************************/
243
244 /*
245 * temporary variables during discovery
246 */
247
248 /* machine-wide memory.
249 * temporarily stored there by OSes that only provide this without NUMA information,
250 * and actually used later by the core.
251 */
252 struct hwloc_numanode_attr_s machine_memory;
253
254 /* pci stuff */
255 int pci_has_forced_locality;
256 unsigned pci_forced_locality_nr;
257 struct hwloc_pci_forced_locality_s {
258 unsigned domain;
259 unsigned bus_first, bus_last;
260 hwloc_bitmap_t cpuset;
261 } * pci_forced_locality;
262
263 /* component blacklisting */
264 unsigned nr_blacklisted_components;
265 struct hwloc_topology_forced_component_s {
266 struct hwloc_disc_component *component;
267 unsigned phases;
268 } *blacklisted_components;
269
270 /* FIXME: keep until topo destroy and reuse for finding specific buses */
271 struct hwloc_pci_locality_s {
272 unsigned domain;
273 unsigned bus_min;
274 unsigned bus_max;
275 hwloc_bitmap_t cpuset;
276 hwloc_obj_t parent;
277 struct hwloc_pci_locality_s *prev, *next;
278 } *first_pci_locality, *last_pci_locality;
279 };
280
281 extern void hwloc_alloc_root_sets(hwloc_obj_t root);
282 extern void hwloc_setup_pu_level(struct hwloc_topology *topology, unsigned nb_pus);
283 extern int hwloc_get_sysctlbyname(const char *name, int64_t *n);
284 extern int hwloc_get_sysctl(int name[], unsigned namelen, int64_t *n);
285
286 /* returns the number of CPU from the OS (only valid if thissystem) */
287 #define HWLOC_FALLBACK_NBPROCESSORS_INCLUDE_OFFLINE 1 /* by default we try to get only the online CPUs */
288 extern int hwloc_fallback_nbprocessors(unsigned flags);
289 /* returns the memory size from the OS (only valid if thissystem) */
290 extern int64_t hwloc_fallback_memsize(void);
291
292 extern int hwloc__object_cpusets_compare_first(hwloc_obj_t obj1, hwloc_obj_t obj2);
293 extern void hwloc__reorder_children(hwloc_obj_t parent);
294
295 extern void hwloc_topology_setup_defaults(struct hwloc_topology *topology);
296 extern void hwloc_topology_clear(struct hwloc_topology *topology);
297
298 /* insert memory object as memory child of normal parent */
299 extern struct hwloc_obj * hwloc__attach_memory_object(struct hwloc_topology *topology, hwloc_obj_t parent,
300 hwloc_obj_t obj, const char *reason);
301
302 extern hwloc_obj_t hwloc_get_obj_by_type_and_gp_index(hwloc_topology_t topology, hwloc_obj_type_t type, uint64_t gp_index);
303
304 extern void hwloc_pci_discovery_init(struct hwloc_topology *topology);
305 extern void hwloc_pci_discovery_prepare(struct hwloc_topology *topology);
306 extern void hwloc_pci_discovery_exit(struct hwloc_topology *topology);
307
308 /* Look for an object matching complete cpuset exactly, or insert one.
309 * Return NULL on failure.
310 * Return a good fallback (object above) on failure to insert.
311 */
312 extern hwloc_obj_t hwloc_find_insert_io_parent_by_complete_cpuset(struct hwloc_topology *topology, hwloc_cpuset_t cpuset);
313
314 extern int hwloc__add_info(struct hwloc_info_s **infosp, unsigned *countp, const char *name, const char *value);
315 extern int hwloc__add_info_nodup(struct hwloc_info_s **infosp, unsigned *countp, const char *name, const char *value, int replace);
316 extern int hwloc__move_infos(struct hwloc_info_s **dst_infosp, unsigned *dst_countp, struct hwloc_info_s **src_infosp, unsigned *src_countp);
317 extern int hwloc__tma_dup_infos(struct hwloc_tma *tma, struct hwloc_info_s **dst_infosp, unsigned *dst_countp, struct hwloc_info_s *src_infos, unsigned src_count);
318 extern void hwloc__free_infos(struct hwloc_info_s *infos, unsigned count);
319
320 /* set native OS binding hooks */
321 extern void hwloc_set_native_binding_hooks(struct hwloc_binding_hooks *hooks, struct hwloc_topology_support *support);
322 /* set either native OS binding hooks (if thissystem), or dummy ones */
323 extern void hwloc_set_binding_hooks(struct hwloc_topology *topology);
324
325 #if defined(HWLOC_LINUX_SYS)
326 extern void hwloc_set_linuxfs_hooks(struct hwloc_binding_hooks *binding_hooks, struct hwloc_topology_support *support);
327 #endif /* HWLOC_LINUX_SYS */
328
329 #if defined(HWLOC_BGQ_SYS)
330 extern void hwloc_set_bgq_hooks(struct hwloc_binding_hooks *binding_hooks, struct hwloc_topology_support *support);
331 #endif /* HWLOC_BGQ_SYS */
332
333 #ifdef HWLOC_SOLARIS_SYS
334 extern void hwloc_set_solaris_hooks(struct hwloc_binding_hooks *binding_hooks, struct hwloc_topology_support *support);
335 #endif /* HWLOC_SOLARIS_SYS */
336
337 #ifdef HWLOC_AIX_SYS
338 extern void hwloc_set_aix_hooks(struct hwloc_binding_hooks *binding_hooks, struct hwloc_topology_support *support);
339 #endif /* HWLOC_AIX_SYS */
340
341 #ifdef HWLOC_WIN_SYS
342 extern void hwloc_set_windows_hooks(struct hwloc_binding_hooks *binding_hooks, struct hwloc_topology_support *support);
343 #endif /* HWLOC_WIN_SYS */
344
345 #ifdef HWLOC_DARWIN_SYS
346 extern void hwloc_set_darwin_hooks(struct hwloc_binding_hooks *binding_hooks, struct hwloc_topology_support *support);
347 #endif /* HWLOC_DARWIN_SYS */
348
349 #ifdef HWLOC_DRAGONFLY_SYS
350 extern void hwloc_set_dragonfly_hooks(struct hwloc_binding_hooks *binding_hooks, struct hwloc_topology_support *support);
351 #endif /* HWLOC_DRAGONFLY_SYS */
352
353 #ifdef HWLOC_FREEBSD_SYS
354 extern void hwloc_set_freebsd_hooks(struct hwloc_binding_hooks *binding_hooks, struct hwloc_topology_support *support);
355 #endif /* HWLOC_FREEBSD_SYS */
356
357 #ifdef HWLOC_NETBSD_SYS
358 extern void hwloc_set_netbsd_hooks(struct hwloc_binding_hooks *binding_hooks, struct hwloc_topology_support *support);
359 #endif /* HWLOC_NETBSD_SYS */
360
361 #ifdef HWLOC_HPUX_SYS
362 extern void hwloc_set_hpux_hooks(struct hwloc_binding_hooks *binding_hooks, struct hwloc_topology_support *support);
363 #endif /* HWLOC_HPUX_SYS */
364
365 extern int hwloc_look_hardwired_fujitsu_k(struct hwloc_topology *topology);
366 extern int hwloc_look_hardwired_fujitsu_fx10(struct hwloc_topology *topology);
367 extern int hwloc_look_hardwired_fujitsu_fx100(struct hwloc_topology *topology);
368
369 /* Insert uname-specific names/values in the object infos array.
370 * If cached_uname isn't NULL, it is used as a struct utsname instead of recalling uname.
371 * Any field that starts with \0 is ignored.
372 */
373 extern void hwloc_add_uname_info(struct hwloc_topology *topology, void *cached_uname);
374
375 /* Free obj and its attributes assuming it's not linked to a parent and doesn't have any child */
376 extern void hwloc_free_unlinked_object(hwloc_obj_t obj);
377
378 /* Free obj and its children, assuming it's not linked to a parent */
379 extern void hwloc_free_object_and_children(hwloc_obj_t obj);
380
381 /* Free obj, its next siblings, and their children, assuming they're not linked to a parent */
382 extern void hwloc_free_object_siblings_and_children(hwloc_obj_t obj);
383
384 /* This can be used for the alloc field to get allocated data that can be freed by free() */
385 void *hwloc_alloc_heap(hwloc_topology_t topology, size_t len);
386
387 /* This can be used for the alloc field to get allocated data that can be freed by munmap() */
388 void *hwloc_alloc_mmap(hwloc_topology_t topology, size_t len);
389
390 /* This can be used for the free_membind field to free data using free() */
391 int hwloc_free_heap(hwloc_topology_t topology, void *addr, size_t len);
392
393 /* This can be used for the free_membind field to free data using munmap() */
394 int hwloc_free_mmap(hwloc_topology_t topology, void *addr, size_t len);
395
396 /* Allocates unbound memory or fail, depending on whether STRICT is requested
397 * or not */
398 static __hwloc_inline void *
hwloc_alloc_or_fail(hwloc_topology_t topology,size_t len,int flags)399 hwloc_alloc_or_fail(hwloc_topology_t topology, size_t len, int flags)
400 {
401 if (flags & HWLOC_MEMBIND_STRICT)
402 return NULL;
403 return hwloc_alloc(topology, len);
404 }
405
406 extern void hwloc_internal_distances_init(hwloc_topology_t topology);
407 extern void hwloc_internal_distances_prepare(hwloc_topology_t topology);
408 extern void hwloc_internal_distances_destroy(hwloc_topology_t topology);
409 extern int hwloc_internal_distances_dup(hwloc_topology_t new, hwloc_topology_t old);
410 extern void hwloc_internal_distances_refresh(hwloc_topology_t topology);
411 extern void hwloc_internal_distances_invalidate_cached_objs(hwloc_topology_t topology);
412
413 /* these distances_add() functions are higher-level than those in hwloc/plugins.h
414 * but they may change in the future, hence they are not exported to plugins.
415 */
416 extern int hwloc_internal_distances_add_by_index(hwloc_topology_t topology, const char *name, hwloc_obj_type_t unique_type, hwloc_obj_type_t *different_types, unsigned nbobjs, uint64_t *indexes, uint64_t *values, unsigned long kind, unsigned long flags);
417 extern int hwloc_internal_distances_add(hwloc_topology_t topology, const char *name, unsigned nbobjs, hwloc_obj_t *objs, uint64_t *values, unsigned long kind, unsigned long flags);
418
419 extern void hwloc_internal_memattrs_init(hwloc_topology_t topology);
420 extern void hwloc_internal_memattrs_prepare(hwloc_topology_t topology);
421 extern void hwloc_internal_memattrs_destroy(hwloc_topology_t topology);
422 extern void hwloc_internal_memattrs_need_refresh(hwloc_topology_t topology);
423 extern void hwloc_internal_memattrs_refresh(hwloc_topology_t topology);
424 extern int hwloc_internal_memattrs_dup(hwloc_topology_t new, hwloc_topology_t old);
425 extern int hwloc_internal_memattr_set_value(hwloc_topology_t topology, hwloc_memattr_id_t id, hwloc_obj_type_t target_type, hwloc_uint64_t target_gp_index, unsigned target_os_index, struct hwloc_internal_location_s *initiator, hwloc_uint64_t value);
426
427 extern void hwloc_internal_cpukinds_init(hwloc_topology_t topology);
428 extern int hwloc_internal_cpukinds_rank(hwloc_topology_t topology);
429 extern void hwloc_internal_cpukinds_destroy(hwloc_topology_t topology);
430 extern int hwloc_internal_cpukinds_dup(hwloc_topology_t new, hwloc_topology_t old);
431 #define HWLOC_CPUKINDS_REGISTER_FLAG_OVERWRITE_FORCED_EFFICIENCY (1<<0)
432 extern int hwloc_internal_cpukinds_register(hwloc_topology_t topology, hwloc_cpuset_t cpuset, int forced_efficiency, const struct hwloc_info_s *infos, unsigned nr_infos, unsigned long flags);
433 extern void hwloc_internal_cpukinds_restrict(hwloc_topology_t topology);
434
435 /* encode src buffer into target buffer.
436 * targsize must be at least 4*((srclength+2)/3)+1.
437 * target will be 0-terminated.
438 */
439 extern int hwloc_encode_to_base64(const char *src, size_t srclength, char *target, size_t targsize);
440 /* decode src buffer into target buffer.
441 * src is 0-terminated.
442 * targsize must be at least srclength*3/4+1 (srclength not including \0)
443 * but only srclength*3/4 characters will be meaningful
444 * (the next one may be partially written during decoding, but it should be ignored).
445 */
446 extern int hwloc_decode_from_base64(char const *src, char *target, size_t targsize);
447
448 /* On some systems, snprintf returns the size of written data, not the actually
449 * required size. Sometimes it returns -1 on truncation too.
450 * And sometimes it doesn't like NULL output buffers.
451 * http://www.gnu.org/software/gnulib/manual/html_node/snprintf.html
452 *
453 * hwloc_snprintf behaves properly, but it's a bit overkill on the vast majority
454 * of platforms, so don't enable it unless really needed.
455 */
456 #ifdef HWLOC_HAVE_CORRECT_SNPRINTF
457 #define hwloc_snprintf snprintf
458 #else
459 extern int hwloc_snprintf(char *str, size_t size, const char *format, ...) __hwloc_attribute_format(printf, 3, 4);
460 #endif
461
462 /* Return the name of the currently running program, if supported.
463 * If not NULL, must be freed by the caller.
464 */
465 extern char * hwloc_progname(struct hwloc_topology *topology);
466
467 /* obj->attr->group.kind internal values.
468 * the core will keep the smallest ones when merging two groups,
469 * that's why user-given kinds are first.
470 */
471 /* first, user-given groups, should remain as long as possible */
472 #define HWLOC_GROUP_KIND_USER 0 /* user-given, user may use subkind too */
473 #define HWLOC_GROUP_KIND_SYNTHETIC 10 /* subkind is group depth within synthetic description */
474 /* then, hardware-specific groups */
475 #define HWLOC_GROUP_KIND_INTEL_KNL_SUBNUMA_CLUSTER 100 /* no subkind */
476 #define HWLOC_GROUP_KIND_INTEL_EXTTOPOENUM_UNKNOWN 101 /* subkind is unknown level */
477 #define HWLOC_GROUP_KIND_INTEL_MODULE 102 /* no subkind */
478 #define HWLOC_GROUP_KIND_INTEL_TILE 103 /* no subkind */
479 #define HWLOC_GROUP_KIND_INTEL_DIE 104 /* no subkind */
480 #define HWLOC_GROUP_KIND_S390_BOOK 110 /* subkind 0 is book, subkind 1 is drawer (group of books) */
481 #define HWLOC_GROUP_KIND_AMD_COMPUTE_UNIT 120 /* no subkind */
482 /* then, OS-specific groups */
483 #define HWLOC_GROUP_KIND_SOLARIS_PG_HW_PERF 200 /* subkind is group width */
484 #define HWLOC_GROUP_KIND_AIX_SDL_UNKNOWN 210 /* subkind is SDL level */
485 #define HWLOC_GROUP_KIND_WINDOWS_PROCESSOR_GROUP 220 /* no subkind */
486 #define HWLOC_GROUP_KIND_WINDOWS_RELATIONSHIP_UNKNOWN 221 /* no subkind */
487 /* distance groups */
488 #define HWLOC_GROUP_KIND_DISTANCE 900 /* subkind is round of adding these groups during distance based grouping */
489 /* finally, hwloc-specific groups required to insert something else, should disappear as soon as possible */
490 #define HWLOC_GROUP_KIND_IO 1000 /* no subkind */
491 #define HWLOC_GROUP_KIND_MEMORY 1001 /* no subkind */
492
493 /* memory allocator for topology objects */
494 struct hwloc_tma {
495 void * (*malloc)(struct hwloc_tma *, size_t);
496 void *data;
497 int dontfree; /* when set, free() or realloc() cannot be used, and tma->malloc() cannot fail */
498 };
499
500 static __hwloc_inline void *
hwloc_tma_malloc(struct hwloc_tma * tma,size_t size)501 hwloc_tma_malloc(struct hwloc_tma *tma,
502 size_t size)
503 {
504 if (tma) {
505 return tma->malloc(tma, size);
506 } else {
507 return malloc(size);
508 }
509 }
510
511 static __hwloc_inline void *
hwloc_tma_calloc(struct hwloc_tma * tma,size_t size)512 hwloc_tma_calloc(struct hwloc_tma *tma,
513 size_t size)
514 {
515 char *ptr = hwloc_tma_malloc(tma, size);
516 if (ptr)
517 memset(ptr, 0, size);
518 return ptr;
519 }
520
521 static __hwloc_inline char *
hwloc_tma_strdup(struct hwloc_tma * tma,const char * src)522 hwloc_tma_strdup(struct hwloc_tma *tma,
523 const char *src)
524 {
525 size_t len = strlen(src);
526 char *ptr = hwloc_tma_malloc(tma, len+1);
527 if (ptr)
528 memcpy(ptr, src, len+1);
529 return ptr;
530 }
531
532 /* bitmap allocator to be used inside hwloc */
533 extern hwloc_bitmap_t hwloc_bitmap_tma_dup(struct hwloc_tma *tma, hwloc_const_bitmap_t old);
534
535 extern int hwloc__topology_dup(hwloc_topology_t *newp, hwloc_topology_t old, struct hwloc_tma *tma);
536 extern void hwloc__topology_disadopt(hwloc_topology_t topology);
537
538 #endif /* HWLOC_PRIVATE_H */
539