1 /*
2  * Copyright © 2009      CNRS
3  * Copyright © 2009-2018 Inria.  All rights reserved.
4  * Copyright © 2009-2012 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 #include <sys/types.h>
31 #ifdef HAVE_UNISTD_H
32 #include <unistd.h>
33 #endif
34 #ifdef HAVE_STDINT_H
35 #include <stdint.h>
36 #endif
37 #ifdef HAVE_SYS_UTSNAME_H
38 #include <sys/utsname.h>
39 #endif
40 #include <string.h>
41 
42 #define HWLOC_TOPOLOGY_ABI 0x20000 /* version of the layout of struct topology */
43 
44 /*****************************************************
45  * WARNING:
46  * changes below in this structure (and its children)
47  * should cause a bump of HWLOC_TOPOLOGY_ABI.
48  *****************************************************/
49 
50 struct hwloc_topology {
51   unsigned topology_abi;
52 
53   unsigned nb_levels;					/* Number of horizontal levels */
54   unsigned nb_levels_allocated;				/* Number of levels allocated and zeroed in level_nbobjects and levels below */
55   unsigned *level_nbobjects; 				/* Number of objects on each horizontal level */
56   struct hwloc_obj ***levels;				/* Direct access to levels, levels[l = 0 .. nblevels-1][0..level_nbobjects[l]] */
57   unsigned long flags;
58   int type_depth[HWLOC_OBJ_TYPE_MAX];
59   enum hwloc_type_filter_e type_filter[HWLOC_OBJ_TYPE_MAX];
60   int is_thissystem;
61   int is_loaded;
62   int modified;                                         /* >0 if objects were added/removed recently, which means a reconnect is needed */
63   hwloc_pid_t pid;                                      /* Process ID the topology is view from, 0 for self */
64   void *userdata;
65   uint64_t next_gp_index;
66 
67   void *adopted_shmem_addr;
68   size_t adopted_shmem_length;
69 
70 #define HWLOC_NR_SLEVELS 5
71 #define HWLOC_SLEVEL_NUMANODE 0
72 #define HWLOC_SLEVEL_BRIDGE 1
73 #define HWLOC_SLEVEL_PCIDEV 2
74 #define HWLOC_SLEVEL_OSDEV 3
75 #define HWLOC_SLEVEL_MISC 4
76   /* order must match negative depth, it's asserted in setup_defaults() */
77 #define HWLOC_SLEVEL_FROM_DEPTH(x) (HWLOC_TYPE_DEPTH_NUMANODE-(x))
78 #define HWLOC_SLEVEL_TO_DEPTH(x) (HWLOC_TYPE_DEPTH_NUMANODE-(x))
79   struct hwloc_special_level_s {
80     unsigned nbobjs;
81     struct hwloc_obj **objs;
82     struct hwloc_obj *first, *last; /* Temporarily used while listing object before building the objs array */
83   } slevels[HWLOC_NR_SLEVELS];
84 
85   hwloc_bitmap_t allowed_cpuset;
86   hwloc_bitmap_t allowed_nodeset;
87 
88   struct hwloc_binding_hooks {
89     int (*set_thisproc_cpubind)(hwloc_topology_t topology, hwloc_const_cpuset_t set, int flags);
90     int (*get_thisproc_cpubind)(hwloc_topology_t topology, hwloc_cpuset_t set, int flags);
91     int (*set_thisthread_cpubind)(hwloc_topology_t topology, hwloc_const_cpuset_t set, int flags);
92     int (*get_thisthread_cpubind)(hwloc_topology_t topology, hwloc_cpuset_t set, int flags);
93     int (*set_proc_cpubind)(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_cpuset_t set, int flags);
94     int (*get_proc_cpubind)(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_cpuset_t set, int flags);
95 #ifdef hwloc_thread_t
96     int (*set_thread_cpubind)(hwloc_topology_t topology, hwloc_thread_t tid, hwloc_const_cpuset_t set, int flags);
97     int (*get_thread_cpubind)(hwloc_topology_t topology, hwloc_thread_t tid, hwloc_cpuset_t set, int flags);
98 #endif
99 
100     int (*get_thisproc_last_cpu_location)(hwloc_topology_t topology, hwloc_cpuset_t set, int flags);
101     int (*get_thisthread_last_cpu_location)(hwloc_topology_t topology, hwloc_cpuset_t set, int flags);
102     int (*get_proc_last_cpu_location)(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_cpuset_t set, int flags);
103 
104     int (*set_thisproc_membind)(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags);
105     int (*get_thisproc_membind)(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags);
106     int (*set_thisthread_membind)(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags);
107     int (*get_thisthread_membind)(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags);
108     int (*set_proc_membind)(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags);
109     int (*get_proc_membind)(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags);
110     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);
111     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);
112     int (*get_area_memlocation)(hwloc_topology_t topology, const void *addr, size_t len, hwloc_nodeset_t nodeset, int flags);
113     /* This has to return the same kind of pointer as alloc_membind, so that free_membind can be used on it */
114     void *(*alloc)(hwloc_topology_t topology, size_t len);
115     /* alloc_membind has to always succeed if !(flags & HWLOC_MEMBIND_STRICT).
116      * see hwloc_alloc_or_fail which is convenient for that.  */
117     void *(*alloc_membind)(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags);
118     int (*free_membind)(hwloc_topology_t topology, void *addr, size_t len);
119 
120     int (*get_allowed_resources)(hwloc_topology_t topology);
121   } binding_hooks;
122 
123   struct hwloc_topology_support support;
124 
125   void (*userdata_export_cb)(void *reserved, struct hwloc_topology *topology, struct hwloc_obj *obj);
126   void (*userdata_import_cb)(struct hwloc_topology *topology, struct hwloc_obj *obj, const char *name, const void *buffer, size_t length);
127   int userdata_not_decoded;
128 
129   struct hwloc_internal_distances_s {
130     hwloc_obj_type_t type;
131     /* add union hwloc_obj_attr_u if we ever support groups */
132     unsigned nbobjs;
133     uint64_t *indexes; /* array of OS or GP indexes before we can convert them into objs. */
134     uint64_t *values; /* distance matrices, ordered according to the above indexes/objs array.
135 		       * distance from i to j is stored in slot i*nbnodes+j.
136 		       */
137     unsigned long kind;
138 
139     /* objects are currently stored in physical_index order */
140     hwloc_obj_t *objs; /* array of objects */
141     int objs_are_valid; /* set to 1 if the array objs is still valid, 0 if needs refresh */
142 
143     unsigned id; /* to match the container id field of public distances structure */
144     struct hwloc_internal_distances_s *prev, *next;
145   } *first_dist, *last_dist;
146   unsigned next_dist_id;
147 
148   int grouping;
149   int grouping_verbose;
150   unsigned grouping_nbaccuracies;
151   float grouping_accuracies[5];
152   unsigned grouping_next_subkind;
153 
154   /* list of enabled backends. */
155   struct hwloc_backend * backends;
156   struct hwloc_backend * get_pci_busid_cpuset_backend;
157   unsigned backend_excludes;
158 
159   /* memory allocator for topology objects */
160   struct hwloc_tma * tma;
161 
162 /*****************************************************
163  * WARNING:
164  * changes above in this structure (and its children)
165  * should cause a bump of HWLOC_TOPOLOGY_ABI.
166  *****************************************************/
167 
168   /*
169    * temporary variables during discovery
170    */
171 
172   /* machine-wide memory.
173    * temporarily stored there by OSes that only provide this without NUMA information,
174    * and actually used later by the core.
175    */
176   struct hwloc_numanode_attr_s machine_memory;
177 
178   /* pci stuff */
179   int need_pci_belowroot_apply_locality;
180   int pci_has_forced_locality;
181   unsigned pci_forced_locality_nr;
182   struct hwloc_pci_forced_locality_s {
183     unsigned domain;
184     unsigned bus_first, bus_last;
185     hwloc_bitmap_t cpuset;
186   } * pci_forced_locality;
187 
188 };
189 
190 extern void hwloc_alloc_root_sets(hwloc_obj_t root);
191 extern void hwloc_setup_pu_level(struct hwloc_topology *topology, unsigned nb_pus);
192 extern int hwloc_get_sysctlbyname(const char *name, int64_t *n);
193 extern int hwloc_get_sysctl(int name[], unsigned namelen, int *n);
194 extern int hwloc_fallback_nbprocessors(struct hwloc_topology *topology);
195 
196 extern int hwloc__object_cpusets_compare_first(hwloc_obj_t obj1, hwloc_obj_t obj2);
197 extern void hwloc__reorder_children(hwloc_obj_t parent);
198 
199 extern void hwloc_topology_setup_defaults(struct hwloc_topology *topology);
200 extern void hwloc_topology_clear(struct hwloc_topology *topology);
201 
202 /* insert memory object as memory child of normal parent */
203 extern struct hwloc_obj * hwloc__attach_memory_object(struct hwloc_topology *topology, hwloc_obj_t parent,
204 						      hwloc_obj_t obj,
205 						      hwloc_report_error_t report_error);
206 
207 extern void hwloc_pci_discovery_init(struct hwloc_topology *topology);
208 extern void hwloc_pci_discovery_prepare(struct hwloc_topology *topology);
209 extern void hwloc_pci_discovery_exit(struct hwloc_topology *topology);
210 
211 /* Look for an object matching complete cpuset exactly, or insert one.
212  * Return NULL on failure.
213  * Return a good fallback (object above) on failure to insert.
214  */
215 extern hwloc_obj_t hwloc_find_insert_io_parent_by_complete_cpuset(struct hwloc_topology *topology, hwloc_cpuset_t cpuset);
216 
217 /* Move PCI objects currently attached to the root object ot their actual location.
218  * Called by the core at the end of hwloc_topology_load().
219  * Prior to this call, all PCI objects may be found below the root object.
220  * After this call and a reconnect of levels, all PCI objects are available through levels.
221  */
222 extern int hwloc_pci_belowroot_apply_locality(struct hwloc_topology *topology);
223 
224 extern int hwloc__add_info(struct hwloc_info_s **infosp, unsigned *countp, const char *name, const char *value);
225 extern int hwloc__add_info_nodup(struct hwloc_info_s **infosp, unsigned *countp, const char *name, const char *value, int replace);
226 extern int hwloc__move_infos(struct hwloc_info_s **dst_infosp, unsigned *dst_countp, struct hwloc_info_s **src_infosp, unsigned *src_countp);
227 extern void hwloc__free_infos(struct hwloc_info_s *infos, unsigned count);
228 
229 /* set native OS binding hooks */
230 extern void hwloc_set_native_binding_hooks(struct hwloc_binding_hooks *hooks, struct hwloc_topology_support *support);
231 /* set either native OS binding hooks (if thissystem), or dummy ones */
232 extern void hwloc_set_binding_hooks(struct hwloc_topology *topology);
233 
234 #if defined(HWLOC_LINUX_SYS)
235 extern void hwloc_set_linuxfs_hooks(struct hwloc_binding_hooks *binding_hooks, struct hwloc_topology_support *support);
236 #endif /* HWLOC_LINUX_SYS */
237 
238 #if defined(HWLOC_BGQ_SYS)
239 extern void hwloc_set_bgq_hooks(struct hwloc_binding_hooks *binding_hooks, struct hwloc_topology_support *support);
240 #endif /* HWLOC_BGQ_SYS */
241 
242 #ifdef HWLOC_SOLARIS_SYS
243 extern void hwloc_set_solaris_hooks(struct hwloc_binding_hooks *binding_hooks, struct hwloc_topology_support *support);
244 #endif /* HWLOC_SOLARIS_SYS */
245 
246 #ifdef HWLOC_AIX_SYS
247 extern void hwloc_set_aix_hooks(struct hwloc_binding_hooks *binding_hooks, struct hwloc_topology_support *support);
248 #endif /* HWLOC_AIX_SYS */
249 
250 #ifdef HWLOC_WIN_SYS
251 extern void hwloc_set_windows_hooks(struct hwloc_binding_hooks *binding_hooks, struct hwloc_topology_support *support);
252 #endif /* HWLOC_WIN_SYS */
253 
254 #ifdef HWLOC_DARWIN_SYS
255 extern void hwloc_set_darwin_hooks(struct hwloc_binding_hooks *binding_hooks, struct hwloc_topology_support *support);
256 #endif /* HWLOC_DARWIN_SYS */
257 
258 #ifdef HWLOC_FREEBSD_SYS
259 extern void hwloc_set_freebsd_hooks(struct hwloc_binding_hooks *binding_hooks, struct hwloc_topology_support *support);
260 #endif /* HWLOC_FREEBSD_SYS */
261 
262 #ifdef HWLOC_NETBSD_SYS
263 extern void hwloc_set_netbsd_hooks(struct hwloc_binding_hooks *binding_hooks, struct hwloc_topology_support *support);
264 #endif /* HWLOC_NETBSD_SYS */
265 
266 #ifdef HWLOC_HPUX_SYS
267 extern void hwloc_set_hpux_hooks(struct hwloc_binding_hooks *binding_hooks, struct hwloc_topology_support *support);
268 #endif /* HWLOC_HPUX_SYS */
269 
270 extern int hwloc_look_hardwired_fujitsu_k(struct hwloc_topology *topology);
271 extern int hwloc_look_hardwired_fujitsu_fx10(struct hwloc_topology *topology);
272 extern int hwloc_look_hardwired_fujitsu_fx100(struct hwloc_topology *topology);
273 
274 /* Insert uname-specific names/values in the object infos array.
275  * If cached_uname isn't NULL, it is used as a struct utsname instead of recalling uname.
276  * Any field that starts with \0 is ignored.
277  */
278 extern void hwloc_add_uname_info(struct hwloc_topology *topology, void *cached_uname);
279 
280 /* Free obj and its attributes assuming it's not linked to a parent and doesn't have any child */
281 extern void hwloc_free_unlinked_object(hwloc_obj_t obj);
282 
283 /* Free obj and its children, assuming it's not linked to a parent */
284 extern void hwloc_free_object_and_children(hwloc_obj_t obj);
285 
286 /* Free obj, its next siblings, and their children, assuming they're not linked to a parent */
287 extern void hwloc_free_object_siblings_and_children(hwloc_obj_t obj);
288 
289 /* This can be used for the alloc field to get allocated data that can be freed by free() */
290 void *hwloc_alloc_heap(hwloc_topology_t topology, size_t len);
291 
292 /* This can be used for the alloc field to get allocated data that can be freed by munmap() */
293 void *hwloc_alloc_mmap(hwloc_topology_t topology, size_t len);
294 
295 /* This can be used for the free_membind field to free data using free() */
296 int hwloc_free_heap(hwloc_topology_t topology, void *addr, size_t len);
297 
298 /* This can be used for the free_membind field to free data using munmap() */
299 int hwloc_free_mmap(hwloc_topology_t topology, void *addr, size_t len);
300 
301 /* Allocates unbound memory or fail, depending on whether STRICT is requested
302  * or not */
303 static __hwloc_inline void *
hwloc_alloc_or_fail(hwloc_topology_t topology,size_t len,int flags)304 hwloc_alloc_or_fail(hwloc_topology_t topology, size_t len, int flags)
305 {
306   if (flags & HWLOC_MEMBIND_STRICT)
307     return NULL;
308   return hwloc_alloc(topology, len);
309 }
310 
311 extern void hwloc_internal_distances_init(hwloc_topology_t topology);
312 extern void hwloc_internal_distances_prepare(hwloc_topology_t topology);
313 extern void hwloc_internal_distances_destroy(hwloc_topology_t topology);
314 extern int hwloc_internal_distances_dup(hwloc_topology_t new, hwloc_topology_t old);
315 extern void hwloc_internal_distances_refresh(hwloc_topology_t topology);
316 extern int hwloc_internal_distances_add(hwloc_topology_t topology, unsigned nbobjs, hwloc_obj_t *objs, uint64_t *values, unsigned long kind, unsigned long flags);
317 extern int hwloc_internal_distances_add_by_index(hwloc_topology_t topology, hwloc_obj_type_t type, unsigned nbobjs, uint64_t *indexes, uint64_t *values, unsigned long kind, unsigned long flags);
318 extern void hwloc_internal_distances_invalidate_cached_objs(hwloc_topology_t topology);
319 
320 /* encode src buffer into target buffer.
321  * targsize must be at least 4*((srclength+2)/3)+1.
322  * target will be 0-terminated.
323  */
324 extern int hwloc_encode_to_base64(const char *src, size_t srclength, char *target, size_t targsize);
325 /* decode src buffer into target buffer.
326  * src is 0-terminated.
327  * targsize must be at least srclength*3/4+1 (srclength not including \0)
328  * but only srclength*3/4 characters will be meaningful
329  * (the next one may be partially written during decoding, but it should be ignored).
330  */
331 extern int hwloc_decode_from_base64(char const *src, char *target, size_t targsize);
332 
333 /* Check whether needle matches the beginning of haystack, at least n, and up
334  * to a colon or \0 */
335 extern int hwloc_namecoloncmp(const char *haystack, const char *needle, size_t n);
336 
337 /* On some systems, snprintf returns the size of written data, not the actually
338  * required size.  hwloc_snprintf always report the actually required size. */
339 extern int hwloc_snprintf(char *str, size_t size, const char *format, ...) __hwloc_attribute_format(printf, 3, 4);
340 
341 /* Return the name of the currently running program, if supported.
342  * If not NULL, must be freed by the caller.
343  */
344 extern char * hwloc_progname(struct hwloc_topology *topology);
345 
346 /* obj->attr->group.kind internal values.
347  * the core will keep the smallest ones when merging two groups,
348  * that's why user-given kinds are first.
349  */
350 /* first, user-given groups, should remain as long as possible */
351 #define HWLOC_GROUP_KIND_USER				0	/* user-given, user may use subkind too */
352 #define HWLOC_GROUP_KIND_SYNTHETIC			10	/* subkind is group depth within synthetic description */
353 /* then, hardware-specific groups */
354 #define HWLOC_GROUP_KIND_INTEL_KNL_SUBNUMA_CLUSTER	100	/* no subkind */
355 #define HWLOC_GROUP_KIND_INTEL_X2APIC_UNKNOWN		101	/* subkind is x2APIC unknown level */
356 #define HWLOC_GROUP_KIND_S390_BOOK			110	/* no subkind */
357 #define HWLOC_GROUP_KIND_AMD_COMPUTE_UNIT		120	/* no subkind */
358 /* then, OS-specific groups */
359 #define HWLOC_GROUP_KIND_SOLARIS_PG_HW_PERF		200	/* subkind is group width */
360 #define HWLOC_GROUP_KIND_AIX_SDL_UNKNOWN		210	/* subkind is SDL level */
361 #define HWLOC_GROUP_KIND_WINDOWS_PROCESSOR_GROUP	220	/* no subkind */
362 #define HWLOC_GROUP_KIND_WINDOWS_RELATIONSHIP_UNKNOWN	221	/* no subkind */
363 /* distance groups */
364 #define HWLOC_GROUP_KIND_DISTANCE			900	/* subkind is round of adding these groups during distance based grouping */
365 /* finally, hwloc-specific groups required to insert something else, should disappear as soon as possible */
366 #define HWLOC_GROUP_KIND_IO				1000	/* no subkind */
367 #define HWLOC_GROUP_KIND_MEMORY				1001	/* no subkind */
368 
369 /* memory allocator for topology objects */
370 struct hwloc_tma {
371   void * (*malloc)(struct hwloc_tma *, size_t);
372   void *data;
373   int dontfree; /* when set, free() or realloc() cannot be used, and tma->malloc() cannot fail */
374 };
375 
376 static __hwloc_inline void *
hwloc_tma_malloc(struct hwloc_tma * tma,size_t size)377 hwloc_tma_malloc(struct hwloc_tma *tma,
378 		 size_t size)
379 {
380   if (tma) {
381     return tma->malloc(tma, size);
382   } else {
383     return malloc(size);
384   }
385 }
386 
387 static __hwloc_inline void *
hwloc_tma_calloc(struct hwloc_tma * tma,size_t size)388 hwloc_tma_calloc(struct hwloc_tma *tma,
389 		 size_t size)
390 {
391   char *ptr = hwloc_tma_malloc(tma, size);
392   if (ptr)
393     memset(ptr, 0, size);
394   return ptr;
395 }
396 
397 static __hwloc_inline char *
hwloc_tma_strdup(struct hwloc_tma * tma,const char * src)398 hwloc_tma_strdup(struct hwloc_tma *tma,
399 		 const char *src)
400 {
401   size_t len = strlen(src);
402   char *ptr = hwloc_tma_malloc(tma, len+1);
403   if (ptr)
404     memcpy(ptr, src, len+1);
405   return ptr;
406 }
407 
408 /* bitmap allocator to be used inside hwloc */
409 extern hwloc_bitmap_t hwloc_bitmap_tma_dup(struct hwloc_tma *tma, hwloc_const_bitmap_t old);
410 
411 extern int hwloc__topology_dup(hwloc_topology_t *newp, hwloc_topology_t old, struct hwloc_tma *tma);
412 extern void hwloc__topology_disadopt(hwloc_topology_t  topology);
413 
414 #endif /* HWLOC_PRIVATE_H */
415