Open MPI logo

Portable Hardware Locality (hwloc) Documentation: v1.3

  |   Home   |   Support   |   FAQ   |  
hwloc.h
Go to the documentation of this file.
00001 /*
00002  * Copyright © 2009 CNRS
00003  * Copyright © 2009-2011 INRIA.  All rights reserved.
00004  * Copyright © 2009-2011 Université Bordeaux 1
00005  * Copyright © 2009-2011 Cisco Systems, Inc.  All rights reserved.
00006  * See COPYING in top-level directory.
00007  */
00008 
00009 /*=====================================================================
00010  *                 PLEASE GO READ THE DOCUMENTATION!
00011  *         ------------------------------------------------
00012  *               $tarball_directory/doc/doxygen-doc/
00013  *                                or                            
00014  *           http://www.open-mpi.org/projects/hwloc/doc/
00015  *=====================================================================
00016  *
00017  * FAIR WARNING: Do NOT expect to be able to figure out all the
00018  * subtleties of hwloc by simply reading function prototypes and
00019  * constant descrptions here in this file.
00020  *
00021  * Hwloc has wonderful documentation in both PDF and HTML formats for
00022  * your reading pleasure.  The formal documentation explains a LOT of
00023  * hwloc-specific concepts, provides definitions, and discusses the
00024  * "big picture" for many of the things that you'll find here in this
00025  * header file.
00026  *
00027  * The PDF/HTML documentation was generated via Doxygen; much of what
00028  * you'll see in there is also here in this file.  BUT THERE IS A LOT
00029  * THAT IS IN THE PDF/HTML THAT IS ***NOT*** IN hwloc.h!
00030  *
00031  * There are entire paragraph-length descriptions, discussions, and
00032  * pretty prictures to explain subtle corner cases, provide concrete
00033  * examples, etc.
00034  *
00035  * Please, go read the documentation.  :-)
00036  *
00037  *=====================================================================*/
00038 
00046 #ifndef HWLOC_H
00047 #define HWLOC_H
00048 
00049 #include <hwloc/autogen/config.h>
00050 #include <sys/types.h>
00051 #include <stdio.h>
00052 #include <string.h>
00053 #include <limits.h>
00054 
00055 /*
00056  * Symbol transforms
00057  */
00058 #include <hwloc/rename.h>
00059 
00060 /*
00061  * Bitmap definitions
00062  */
00063 
00064 #include <hwloc/bitmap.h>
00065 #include <hwloc/cpuset.h>
00066 
00067 
00068 #ifdef __cplusplus
00069 extern "C" {
00070 #endif
00071 
00072 
00078 #define HWLOC_API_VERSION 0x00010300
00079 
00081  unsigned hwloc_get_api_version(void);
00082 
00091 struct hwloc_topology;
00096 typedef struct hwloc_topology * hwloc_topology_t;
00097 
00128 typedef hwloc_bitmap_t hwloc_cpuset_t;
00130 typedef hwloc_const_bitmap_t hwloc_const_cpuset_t;
00131 
00145 typedef hwloc_bitmap_t hwloc_nodeset_t;
00148 typedef hwloc_const_bitmap_t hwloc_const_nodeset_t;
00149 
00164 typedef enum {
00165     /* ***************************************************************
00166        WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
00167 
00168        If new enum values are added here, you MUST also go update the
00169        obj_type_order[] and obj_order_type[] arrays in src/topology.c.
00170 
00171        WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
00172        *************************************************************** */
00173 
00174   HWLOC_OBJ_SYSTEM,     
00179   HWLOC_OBJ_MACHINE,    
00184   HWLOC_OBJ_NODE,       
00188   HWLOC_OBJ_SOCKET,     
00192   HWLOC_OBJ_CACHE,      
00195   HWLOC_OBJ_CORE,       
00199   HWLOC_OBJ_PU,         
00208   HWLOC_OBJ_GROUP,      
00220   HWLOC_OBJ_MISC,       
00225   HWLOC_OBJ_BRIDGE,     
00232   HWLOC_OBJ_PCI_DEVICE, 
00237   HWLOC_OBJ_OS_DEVICE,  
00243   HWLOC_OBJ_TYPE_MAX    
00245     /* ***************************************************************
00246        WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
00247 
00248        If new enum values are added here, you MUST also go update the
00249        obj_type_order[] and obj_order_type[] arrays in src/topology.c.
00250 
00251        WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
00252        *************************************************************** */
00253 } hwloc_obj_type_t;
00254 
00256 typedef enum hwloc_obj_bridge_type_e {
00257   HWLOC_OBJ_BRIDGE_HOST,        
00258   HWLOC_OBJ_BRIDGE_PCI          
00259 } hwloc_obj_bridge_type_t;
00260 
00262 typedef enum hwloc_obj_osdev_type_e {
00263   HWLOC_OBJ_OSDEV_BLOCK,        
00265   HWLOC_OBJ_OSDEV_GPU,          
00267   HWLOC_OBJ_OSDEV_NETWORK,      
00269   HWLOC_OBJ_OSDEV_OPENFABRICS,  
00271   HWLOC_OBJ_OSDEV_DMA           
00273 } hwloc_obj_osdev_type_t;
00274 
00292  int hwloc_compare_types (hwloc_obj_type_t type1, hwloc_obj_type_t type2) ;
00293 
00294 enum hwloc_compare_types_e {
00295     HWLOC_TYPE_UNORDERED = INT_MAX      
00296 };
00297 
00306 union hwloc_obj_attr_u;
00307 
00309 struct hwloc_obj_memory_s {
00310   hwloc_uint64_t total_memory; 
00311   hwloc_uint64_t local_memory; 
00313   unsigned page_types_len; 
00319   struct hwloc_obj_memory_page_type_s {
00320     hwloc_uint64_t size;        
00321     hwloc_uint64_t count;       
00322   } * page_types;
00323 };
00324 
00329 struct hwloc_obj {
00330   /* physical information */
00331   hwloc_obj_type_t type;                
00332   unsigned os_index;                    
00333   char *name;                           
00335   struct hwloc_obj_memory_s memory;     
00337   union hwloc_obj_attr_u *attr;         
00340   /* global position */
00341   unsigned depth;                       
00342   unsigned logical_index;               
00344   signed os_level;                      
00346   /* cousins are all objects of the same type (and depth) across the entire topology */
00347   struct hwloc_obj *next_cousin;        
00348   struct hwloc_obj *prev_cousin;        
00350   /* children of the same parent are siblings, even if they may have different type and depth */
00351   struct hwloc_obj *parent;             
00352   unsigned sibling_rank;                
00353   struct hwloc_obj *next_sibling;       
00354   struct hwloc_obj *prev_sibling;       
00356   /* children array below this object */
00357   unsigned arity;                       
00358   struct hwloc_obj **children;          
00359   struct hwloc_obj *first_child;        
00360   struct hwloc_obj *last_child;         
00362   /* misc */
00363   void *userdata;                       
00365   /* cpusets and nodesets */
00366   hwloc_cpuset_t cpuset;                
00379   hwloc_cpuset_t complete_cpuset;       
00390   hwloc_cpuset_t online_cpuset;         
00398   hwloc_cpuset_t allowed_cpuset;        
00409   hwloc_nodeset_t nodeset;              
00426   hwloc_nodeset_t complete_nodeset;     
00440   hwloc_nodeset_t allowed_nodeset;      
00453   struct hwloc_distances_s **distances; 
00454   unsigned distances_count;
00455 
00456   struct hwloc_obj_info_s *infos;       
00457   unsigned infos_count;                 
00458 };
00462 typedef struct hwloc_obj * hwloc_obj_t;
00463 
00465 union hwloc_obj_attr_u {
00467   struct hwloc_cache_attr_s {
00468     hwloc_uint64_t size;                          
00469     unsigned depth;                       
00470     unsigned linesize;                    
00471     int associativity;                    
00473   } cache;
00475   struct hwloc_group_attr_s {
00476     unsigned depth;                       
00477   } group;
00479   struct hwloc_pcidev_attr_s {
00480     unsigned short domain;
00481     unsigned char bus, dev, func;
00482     unsigned short class_id;
00483     unsigned short vendor_id, device_id, subvendor_id, subdevice_id;
00484     unsigned char revision;
00485     float linkspeed; /* in GB/s */
00486   } pcidev;
00488   struct hwloc_bridge_attr_s {
00489     union {
00490       struct hwloc_pcidev_attr_s pci;
00491     } upstream;
00492     hwloc_obj_bridge_type_t upstream_type;
00493     union {
00494       struct {
00495         unsigned short domain;
00496         unsigned char secondary_bus, subordinate_bus;
00497       } pci;
00498     } downstream;
00499     hwloc_obj_bridge_type_t downstream_type;
00500     unsigned depth;
00501   } bridge;
00503   struct hwloc_osdev_attr_s {
00504     hwloc_obj_osdev_type_t type;
00505   } osdev;
00506 };
00507 
00522 struct hwloc_distances_s {
00523   unsigned relative_depth;      
00525   unsigned nbobjs;              
00530   float *latency;               
00535   float latency_max;            
00536   float latency_base;           
00540 };
00541 
00543 struct hwloc_obj_info_s {
00544   char *name;   
00545   char *value;  
00546 };
00547 
00562  int hwloc_topology_init (hwloc_topology_t *topologyp);
00563 
00576  int hwloc_topology_load(hwloc_topology_t topology);
00577 
00582  void hwloc_topology_destroy (hwloc_topology_t topology);
00583 
00595  void hwloc_topology_check(hwloc_topology_t topology);
00596 
00631  int hwloc_topology_ignore_type(hwloc_topology_t topology, hwloc_obj_type_t type);
00632 
00641  int hwloc_topology_ignore_type_keep_structure(hwloc_topology_t topology, hwloc_obj_type_t type);
00642 
00650  int hwloc_topology_ignore_all_keep_structure(hwloc_topology_t topology);
00651 
00656 enum hwloc_topology_flags_e {
00657   HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM = (1<<0),
00666   HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM = (1<<1),
00686   /* \brief Detect PCI devices.
00687    *
00688    * By default, I/O devices are ignored. This flag enables I/O device
00689    * detection using the libpci backend. Only the common PCI devices (GPUs,
00690    * NICs, block devices, ...) and host bridges (objects that connect the host
00691    * objects to an I/O subsystem) will be added to the topology.
00692    * Uncommon devices and other bridges (such as PCI-to-PCI bridges) will be
00693    * ignored.
00694    */
00695   HWLOC_TOPOLOGY_FLAG_IO_DEVICES = (1<<2),
00696 
00697   /* \brief Detect PCI bridges.
00698    *
00699    * This flag should be combined with HWLOC_TOPOLOGY_FLAG_IO_DEVICES to enable
00700    * the detection of both common devices and of all useful bridges (bridges that
00701    * have at least one device behind them).
00702    */
00703   HWLOC_TOPOLOGY_FLAG_IO_BRIDGES = (1<<3),
00704 
00705   /* \brief Detect the whole PCI hierarchy.
00706    *
00707    * This flag enables detection of all I/O devices (even the uncommon ones)
00708    * and bridges (even those that have no device behind them) using the libpci
00709    * backend.
00710    */
00711   HWLOC_TOPOLOGY_FLAG_WHOLE_IO = (1<<4)
00712 };
00713 
00718  int hwloc_topology_set_flags (hwloc_topology_t topology, unsigned long flags);
00719 
00738  int hwloc_topology_set_fsroot(hwloc_topology_t restrict topology, const char * restrict fsroot_path);
00739 
00753  int hwloc_topology_set_pid(hwloc_topology_t restrict topology, hwloc_pid_t pid);
00754 
00777  int hwloc_topology_set_synthetic(hwloc_topology_t restrict topology, const char * restrict description);
00778 
00795  int hwloc_topology_set_xml(hwloc_topology_t restrict topology, const char * restrict xmlpath);
00796 
00810  int hwloc_topology_set_xmlbuffer(hwloc_topology_t restrict topology, const char * restrict buffer, int size);
00811 
00827  int hwloc_topology_set_distance_matrix(hwloc_topology_t restrict topology,
00828                                                       hwloc_obj_type_t type, unsigned nbobjs,
00829                                                       unsigned *os_index, float *distances);
00830 
00832 struct hwloc_topology_discovery_support {
00834   unsigned char pu;
00835 };
00836 
00838 struct hwloc_topology_cpubind_support {
00840   unsigned char set_thisproc_cpubind;
00842   unsigned char get_thisproc_cpubind;
00844   unsigned char set_proc_cpubind;
00846   unsigned char get_proc_cpubind;
00848   unsigned char set_thisthread_cpubind;
00850   unsigned char get_thisthread_cpubind;
00852   unsigned char set_thread_cpubind;
00854   unsigned char get_thread_cpubind;
00856   unsigned char get_thisproc_last_cpu_location;
00858   unsigned char get_proc_last_cpu_location;
00860   unsigned char get_thisthread_last_cpu_location;
00861 };
00862 
00864 struct hwloc_topology_membind_support {
00866   unsigned char set_thisproc_membind;
00868   unsigned char get_thisproc_membind;
00870   unsigned char set_proc_membind;
00872   unsigned char get_proc_membind;
00874   unsigned char set_thisthread_membind;
00876   unsigned char get_thisthread_membind;
00878   unsigned char set_area_membind;
00880   unsigned char get_area_membind;
00882   unsigned char alloc_membind;
00884   unsigned char firsttouch_membind;
00886   unsigned char bind_membind;
00888   unsigned char interleave_membind;
00890   unsigned char replicate_membind;
00892   unsigned char nexttouch_membind;
00893 
00895   unsigned char migrate_membind;
00896 };
00897 
00904 struct hwloc_topology_support {
00905   struct hwloc_topology_discovery_support *discovery;
00906   struct hwloc_topology_cpubind_support *cpubind;
00907   struct hwloc_topology_membind_support *membind;
00908 };
00909 
00911  const struct hwloc_topology_support *hwloc_topology_get_support(hwloc_topology_t restrict topology);
00912 
00927  int hwloc_topology_export_xml(hwloc_topology_t topology, const char *xmlpath);
00928 
00938  int hwloc_topology_export_xmlbuffer(hwloc_topology_t topology, char **xmlbuffer, int *buflen);
00939 
00941  void hwloc_free_xmlbuffer(hwloc_topology_t topology, char *xmlbuffer);
00942 
00954  hwloc_obj_t hwloc_topology_insert_misc_object_by_cpuset(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset, const char *name);
00955 
00968  hwloc_obj_t hwloc_topology_insert_misc_object_by_parent(hwloc_topology_t topology, hwloc_obj_t parent, const char *name);
00969 
00971 enum hwloc_restrict_flags_e {
00972   HWLOC_RESTRICT_FLAG_ADAPT_DISTANCES = (1<<0),
00977   HWLOC_RESTRICT_FLAG_ADAPT_MISC = (1<<1),
00982   HWLOC_RESTRICT_FLAG_ADAPT_IO = (1<<2)
00987 };
00988 
01001  int hwloc_topology_restrict(hwloc_topology_t restrict topology, hwloc_const_cpuset_t cpuset, unsigned long flags);
01002 
01020  unsigned hwloc_topology_get_depth(hwloc_topology_t restrict topology) ;
01021 
01041  int hwloc_get_type_depth (hwloc_topology_t topology, hwloc_obj_type_t type);
01042 
01043 enum hwloc_get_type_depth_e {
01044     HWLOC_TYPE_DEPTH_UNKNOWN = -1,    
01045     HWLOC_TYPE_DEPTH_MULTIPLE = -2,   
01046     HWLOC_TYPE_DEPTH_BRIDGE = -3,     
01047     HWLOC_TYPE_DEPTH_PCI_DEVICE = -4, 
01048     HWLOC_TYPE_DEPTH_OS_DEVICE = -5   
01049 };
01050 
01055  hwloc_obj_type_t hwloc_get_depth_type (hwloc_topology_t topology, unsigned depth) ;
01056 
01059  unsigned hwloc_get_nbobjs_by_depth (hwloc_topology_t topology, unsigned depth) ;
01060 
01066 static inline int 
01067 hwloc_get_nbobjs_by_type (hwloc_topology_t topology, hwloc_obj_type_t type)
01068 {
01069         int depth = hwloc_get_type_depth(topology, type);
01070         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN)
01071                 return 0;
01072         if (depth == HWLOC_TYPE_DEPTH_MULTIPLE)
01073                 return -1; /* FIXME: agregate nbobjs from different levels? */
01074         return hwloc_get_nbobjs_by_depth(topology, depth);
01075 }
01076 
01084  int hwloc_topology_is_thissystem(hwloc_topology_t  restrict topology) ;
01085 
01100  hwloc_obj_t hwloc_get_obj_by_depth (hwloc_topology_t topology, unsigned depth, unsigned idx) ;
01101 
01108 static inline hwloc_obj_t 
01109 hwloc_get_obj_by_type (hwloc_topology_t topology, hwloc_obj_type_t type, unsigned idx)
01110 {
01111   int depth = hwloc_get_type_depth(topology, type);
01112   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN)
01113     return NULL;
01114   if (depth == HWLOC_TYPE_DEPTH_MULTIPLE)
01115     return NULL;
01116   return hwloc_get_obj_by_depth(topology, depth, idx);
01117 }
01118 
01128  const char * hwloc_obj_type_string (hwloc_obj_type_t type) ;
01129 
01134  hwloc_obj_type_t hwloc_obj_type_of_string (const char * string) ;
01135 
01146  int hwloc_obj_type_snprintf(char * restrict string, size_t size, hwloc_obj_t obj,
01147                                    int verbose);
01148 
01160  int hwloc_obj_attr_snprintf(char * restrict string, size_t size, hwloc_obj_t obj, const char * restrict separator,
01161                                    int verbose);
01162 
01183  int hwloc_obj_snprintf(char * restrict string, size_t size,
01184                              hwloc_topology_t topology, hwloc_obj_t obj,
01185                              const char * restrict indexprefix, int verbose);
01186 
01194  int hwloc_obj_cpuset_snprintf(char * restrict str, size_t size, size_t nobj, const hwloc_obj_t * restrict objs);
01195 
01202 static inline char * 
01203 hwloc_obj_get_info_by_name(hwloc_obj_t obj, const char *name)
01204 {
01205   unsigned i;
01206   for(i=0; i<obj->infos_count; i++)
01207     if (!strcmp(obj->infos[i].name, name))
01208       return obj->infos[i].value;
01209   return NULL;
01210 }
01211 
01219  void hwloc_obj_add_info(hwloc_obj_t obj, const char *name, const char *value);
01220 
01278 typedef enum {
01279   HWLOC_CPUBIND_PROCESS = (1<<0), 
01282   HWLOC_CPUBIND_THREAD = (1<<1),  
01284   HWLOC_CPUBIND_STRICT = (1<<2),  
01312   HWLOC_CPUBIND_NOMEMBIND = (1<<3)
01332 } hwloc_cpubind_flags_t;
01333 
01339  int hwloc_set_cpubind(hwloc_topology_t topology, hwloc_const_cpuset_t set, int flags);
01340 
01346  int hwloc_get_cpubind(hwloc_topology_t topology, hwloc_cpuset_t set, int flags);
01347 
01355  int hwloc_set_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_cpuset_t set, int flags);
01356 
01368  int hwloc_get_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_cpuset_t set, int flags);
01369 
01370 #ifdef hwloc_thread_t
01371 
01378  int hwloc_set_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t thread, hwloc_const_cpuset_t set, int flags);
01379 #endif
01380 
01381 #ifdef hwloc_thread_t
01382 
01389  int hwloc_get_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t tid, hwloc_cpuset_t set, int flags);
01390 #endif
01391 
01399  int hwloc_get_last_cpu_location(hwloc_topology_t topology, hwloc_cpuset_t set, int flags);
01400 
01414  int hwloc_get_proc_last_cpu_location(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_cpuset_t set, int flags);
01415 
01475 typedef enum {
01476   HWLOC_MEMBIND_DEFAULT =       0,      
01478   HWLOC_MEMBIND_FIRSTTOUCH =    1,      
01489   HWLOC_MEMBIND_BIND =          2,      
01491   HWLOC_MEMBIND_INTERLEAVE =    3,      
01506   HWLOC_MEMBIND_REPLICATE =     4,      
01528   HWLOC_MEMBIND_NEXTTOUCH =     5,      
01538   HWLOC_MEMBIND_MIXED = -1              
01543 } hwloc_membind_policy_t;
01544 
01556 typedef enum {
01557   HWLOC_MEMBIND_PROCESS =       (1<<0), 
01564   HWLOC_MEMBIND_THREAD =        (1<<1), 
01570   HWLOC_MEMBIND_STRICT =        (1<<2), 
01581   HWLOC_MEMBIND_MIGRATE =       (1<<3), 
01589   HWLOC_MEMBIND_NOCPUBIND =     (1<<4)  
01612 } hwloc_membind_flags_t;
01613 
01626  int hwloc_set_membind_nodeset(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags);
01627 
01641  int hwloc_set_membind(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags);
01642 
01683  int hwloc_get_membind_nodeset(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags);
01684 
01730  int hwloc_get_membind(hwloc_topology_t topology, hwloc_cpuset_t cpuset, hwloc_membind_policy_t * policy, int flags);
01731 
01738  int hwloc_set_proc_membind_nodeset(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags);
01739 
01746  int hwloc_set_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags);
01747 
01781  int hwloc_get_proc_membind_nodeset(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags);
01782 
01819  int hwloc_get_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_cpuset_t cpuset, hwloc_membind_policy_t * policy, int flags);
01820 
01827  int hwloc_set_area_membind_nodeset(hwloc_topology_t topology, const void *addr, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags);
01828 
01835  int hwloc_set_area_membind(hwloc_topology_t topology, const void *addr, size_t len, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags);
01836 
01859  int hwloc_get_area_membind_nodeset(hwloc_topology_t topology, const void *addr, size_t len, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags);
01860 
01885  int hwloc_get_area_membind(hwloc_topology_t topology, const void *addr, size_t len, hwloc_cpuset_t cpuset, hwloc_membind_policy_t * policy, int flags);
01886 
01894  void *hwloc_alloc(hwloc_topology_t topology, size_t len);
01895 
01905  void *hwloc_alloc_membind_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) ;
01906 
01916  void *hwloc_alloc_membind(hwloc_topology_t topology, size_t len, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags) ;
01917 
01921  int hwloc_free(hwloc_topology_t topology, void *addr, size_t len);
01922 
01927 #ifdef __cplusplus
01928 } /* extern "C" */
01929 #endif
01930 
01931 
01932 /* high-level helpers */
01933 #include <hwloc/helper.h>
01934 
01935 
01936 #endif /* HWLOC_H */