Open MPI logo

Portable Hardware Locality (hwloc) Documentation: v1.4

  |   Home   |   Support   |   FAQ   |  
helper.h
00001 /*
00002  * Copyright © 2009 CNRS
00003  * Copyright © 2009-2011 inria.  All rights reserved.
00004  * Copyright © 2009-2011 Université Bordeaux 1
00005  * Copyright © 2009-2010 Cisco Systems, Inc.  All rights reserved.
00006  * See COPYING in top-level directory.
00007  */
00008 
00013 #ifndef HWLOC_HELPER_H
00014 #define HWLOC_HELPER_H
00015 
00016 #ifndef HWLOC_H
00017 #error Please include the main hwloc.h instead
00018 #endif
00019 
00020 #include <stdlib.h>
00021 #include <errno.h>
00022 
00023 
00024 #ifdef __cplusplus
00025 extern "C" {
00026 #endif
00027 
00028 
00047 static inline int 
00048 hwloc_get_type_or_below_depth (hwloc_topology_t topology, hwloc_obj_type_t type)
00049 {
00050   int depth = hwloc_get_type_depth(topology, type);
00051 
00052   if (depth != HWLOC_TYPE_DEPTH_UNKNOWN)
00053     return depth;
00054 
00055   /* find the highest existing level with type order >= */
00056   for(depth = hwloc_get_type_depth(topology, HWLOC_OBJ_PU); ; depth--)
00057     if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) < 0)
00058       return depth+1;
00059 
00060   /* Shouldn't ever happen, as there is always a SYSTEM level with lower order and known depth.  */
00061   /* abort(); */
00062 }
00063 
00073 static inline int 
00074 hwloc_get_type_or_above_depth (hwloc_topology_t topology, hwloc_obj_type_t type)
00075 {
00076   int depth = hwloc_get_type_depth(topology, type);
00077 
00078   if (depth != HWLOC_TYPE_DEPTH_UNKNOWN)
00079     return depth;
00080 
00081   /* find the lowest existing level with type order <= */
00082   for(depth = 0; ; depth++)
00083     if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) > 0)
00084       return depth-1;
00085 
00086   /* Shouldn't ever happen, as there is always a PU level with higher order and known depth.  */
00087   /* abort(); */
00088 }
00089 
00109 static inline hwloc_obj_t 
00110 hwloc_get_root_obj (hwloc_topology_t topology)
00111 {
00112   return hwloc_get_obj_by_depth (topology, 0, 0);
00113 }
00114 
00116 static inline hwloc_obj_t 
00117 hwloc_get_ancestor_obj_by_depth (hwloc_topology_t topology , unsigned depth, hwloc_obj_t obj)
00118 {
00119   hwloc_obj_t ancestor = obj;
00120   if (obj->depth < depth)
00121     return NULL;
00122   while (ancestor && ancestor->depth > depth)
00123     ancestor = ancestor->parent;
00124   return ancestor;
00125 }
00126 
00128 static inline hwloc_obj_t 
00129 hwloc_get_ancestor_obj_by_type (hwloc_topology_t topology , hwloc_obj_type_t type, hwloc_obj_t obj)
00130 {
00131   hwloc_obj_t ancestor = obj->parent;
00132   while (ancestor && ancestor->type != type)
00133     ancestor = ancestor->parent;
00134   return ancestor;
00135 }
00136 
00141 static inline hwloc_obj_t
00142 hwloc_get_next_obj_by_depth (hwloc_topology_t topology, unsigned depth, hwloc_obj_t prev)
00143 {
00144   if (!prev)
00145     return hwloc_get_obj_by_depth (topology, depth, 0);
00146   if (prev->depth != depth)
00147     return NULL;
00148   return prev->next_cousin;
00149 }
00150 
00157 static inline hwloc_obj_t
00158 hwloc_get_next_obj_by_type (hwloc_topology_t topology, hwloc_obj_type_t type,
00159                    hwloc_obj_t prev)
00160 {
00161   int depth = hwloc_get_type_depth(topology, type);
00162   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00163     return NULL;
00164   return hwloc_get_next_obj_by_depth (topology, depth, prev);
00165 }
00166 
00175 static inline hwloc_obj_t 
00176 hwloc_get_pu_obj_by_os_index(hwloc_topology_t topology, unsigned os_index)
00177 {
00178   hwloc_obj_t obj = NULL;
00179   while ((obj = hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_PU, obj)) != NULL)
00180     if (obj->os_index == os_index)
00181       return obj;
00182   return NULL;
00183 }
00184 
00189 static inline hwloc_obj_t
00190 hwloc_get_next_child (hwloc_topology_t topology , hwloc_obj_t parent, hwloc_obj_t prev)
00191 {
00192   if (!prev)
00193     return parent->first_child;
00194   if (prev->parent != parent)
00195     return NULL;
00196   return prev->next_sibling;
00197 }
00198 
00200 static inline hwloc_obj_t 
00201 hwloc_get_common_ancestor_obj (hwloc_topology_t topology , hwloc_obj_t obj1, hwloc_obj_t obj2)
00202 {
00203   /* the loop isn't so easy since intermediate ancestors may have
00204    * different depth, causing us to alternate between using obj1->parent
00205    * and obj2->parent. Also, even if at some point we find ancestors of
00206    * of the same depth, their ancestors may have different depth again.
00207    */
00208   while (obj1 != obj2) {
00209     while (obj1->depth > obj2->depth)
00210       obj1 = obj1->parent;
00211     while (obj2->depth > obj1->depth)
00212       obj2 = obj2->parent;
00213     if (obj1 != obj2 && obj1->depth == obj2->depth) {
00214       obj1 = obj1->parent;
00215       obj2 = obj2->parent;
00216     }
00217   }
00218   return obj1;
00219 }
00220 
00225 static inline int 
00226 hwloc_obj_is_in_subtree (hwloc_topology_t topology , hwloc_obj_t obj, hwloc_obj_t subtree_root)
00227 {
00228   return hwloc_bitmap_isincluded(obj->cpuset, subtree_root->cpuset);
00229 }
00230 
00250 static inline hwloc_obj_t
00251 hwloc_get_first_largest_obj_inside_cpuset(hwloc_topology_t topology, hwloc_const_cpuset_t set)
00252 {
00253   hwloc_obj_t obj = hwloc_get_root_obj(topology);
00254   if (!obj->cpuset || !hwloc_bitmap_intersects(obj->cpuset, set))
00255     return NULL;
00256   while (!hwloc_bitmap_isincluded(obj->cpuset, set)) {
00257     /* while the object intersects without being included, look at its children */
00258     hwloc_obj_t child = NULL;
00259     while ((child = hwloc_get_next_child(topology, obj, child)) != NULL) {
00260       if (child->cpuset && hwloc_bitmap_intersects(child->cpuset, set))
00261         break;
00262     }
00263     if (!child)
00264       /* no child intersects, return their father */
00265       return obj;
00266     /* found one intersecting child, look at its children */
00267     obj = child;
00268   }
00269   /* obj is included, return it */
00270   return obj;
00271 }
00272 
00280  int hwloc_get_largest_objs_inside_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00281                                                  hwloc_obj_t * restrict objs, int max);
00282 
00292 static inline hwloc_obj_t
00293 hwloc_get_next_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00294                                            unsigned depth, hwloc_obj_t prev)
00295 {
00296   hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev);
00297   if (!next || !next->cpuset)
00298     return NULL;
00299   while (next && !hwloc_bitmap_isincluded(next->cpuset, set))
00300     next = next->next_cousin;
00301   return next;
00302 }
00303 
00313 static inline hwloc_obj_t
00314 hwloc_get_next_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00315                                           hwloc_obj_type_t type, hwloc_obj_t prev)
00316 {
00317   int depth = hwloc_get_type_depth(topology, type);
00318   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00319     return NULL;
00320   return hwloc_get_next_obj_inside_cpuset_by_depth(topology, set, depth, prev);
00321 }
00322 
00328 static inline hwloc_obj_t 
00329 hwloc_get_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00330                                       unsigned depth, unsigned idx)
00331 {
00332   hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0);
00333   unsigned count = 0;
00334   if (!obj || !obj->cpuset)
00335     return NULL;
00336   while (obj) {
00337     if (hwloc_bitmap_isincluded(obj->cpuset, set)) {
00338       if (count == idx)
00339         return obj;
00340       count++;
00341     }
00342     obj = obj->next_cousin;
00343   }
00344   return NULL;
00345 }
00346 
00356 static inline hwloc_obj_t 
00357 hwloc_get_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00358                                      hwloc_obj_type_t type, unsigned idx)
00359 {
00360   int depth = hwloc_get_type_depth(topology, type);
00361   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00362     return NULL;
00363   return hwloc_get_obj_inside_cpuset_by_depth(topology, set, depth, idx);
00364 }
00365 
00371 static inline unsigned 
00372 hwloc_get_nbobjs_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00373                                          unsigned depth)
00374 {
00375   hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0);
00376   unsigned count = 0;
00377   if (!obj || !obj->cpuset)
00378     return 0;
00379   while (obj) {
00380     if (hwloc_bitmap_isincluded(obj->cpuset, set))
00381       count++;
00382     obj = obj->next_cousin;
00383   }
00384   return count;
00385 }
00386 
00396 static inline int 
00397 hwloc_get_nbobjs_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00398                                         hwloc_obj_type_t type)
00399 {
00400   int depth = hwloc_get_type_depth(topology, type);
00401   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN)
00402     return 0;
00403   if (depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00404     return -1; /* FIXME: agregate nbobjs from different levels? */
00405   return hwloc_get_nbobjs_inside_cpuset_by_depth(topology, set, depth);
00406 }
00407 
00416 static inline int 
00417 hwloc_get_obj_index_inside_cpuset (hwloc_topology_t topology , hwloc_const_cpuset_t set,
00418                                    hwloc_obj_t obj)
00419 {
00420   int index = 0;
00421   if (!hwloc_bitmap_isincluded(obj->cpuset, set))
00422     return -1;
00423   /* count how many objects are inside the cpuset on the way from us to the beginning of the level */
00424   while ((obj = obj->prev_cousin) != NULL)
00425     if (hwloc_bitmap_isincluded(obj->cpuset, set))
00426       index++;
00427   return index;
00428 }
00429 
00444 static inline hwloc_obj_t 
00445 hwloc_get_child_covering_cpuset (hwloc_topology_t topology , hwloc_const_cpuset_t set,
00446                                 hwloc_obj_t parent)
00447 {
00448   hwloc_obj_t child;
00449   if (!parent->cpuset || hwloc_bitmap_iszero(set))
00450     return NULL;
00451   child = parent->first_child;
00452   while (child) {
00453     if (child->cpuset && hwloc_bitmap_isincluded(set, child->cpuset))
00454       return child;
00455     child = child->next_sibling;
00456   }
00457   return NULL;
00458 }
00459 
00467 static inline hwloc_obj_t 
00468 hwloc_get_obj_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set)
00469 {
00470   struct hwloc_obj *current = hwloc_get_root_obj(topology);
00471   if (hwloc_bitmap_iszero(set) || !current->cpuset || !hwloc_bitmap_isincluded(set, current->cpuset))
00472     return NULL;
00473   while (1) {
00474     hwloc_obj_t child = hwloc_get_child_covering_cpuset(topology, set, current);
00475     if (!child)
00476       return current;
00477     current = child;
00478   }
00479 }
00480 
00481 
00500 static inline hwloc_obj_t
00501 hwloc_get_next_obj_covering_cpuset_by_depth(hwloc_topology_t topology, hwloc_const_cpuset_t set,
00502                                             unsigned depth, hwloc_obj_t prev)
00503 {
00504   hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev);
00505   if (!next || !next->cpuset)
00506     return NULL;
00507   while (next && !hwloc_bitmap_intersects(set, next->cpuset))
00508     next = next->next_cousin;
00509   return next;
00510 }
00511 
00527 static inline hwloc_obj_t
00528 hwloc_get_next_obj_covering_cpuset_by_type(hwloc_topology_t topology, hwloc_const_cpuset_t set,
00529                                            hwloc_obj_type_t type, hwloc_obj_t prev)
00530 {
00531   int depth = hwloc_get_type_depth(topology, type);
00532   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00533     return NULL;
00534   return hwloc_get_next_obj_covering_cpuset_by_depth(topology, set, depth, prev);
00535 }
00536 
00552 static inline hwloc_obj_t 
00553 hwloc_get_cache_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set)
00554 {
00555   hwloc_obj_t current = hwloc_get_obj_covering_cpuset(topology, set);
00556   while (current) {
00557     if (current->type == HWLOC_OBJ_CACHE)
00558       return current;
00559     current = current->parent;
00560   }
00561   return NULL;
00562 }
00563 
00568 static inline hwloc_obj_t 
00569 hwloc_get_shared_cache_covering_obj (hwloc_topology_t topology , hwloc_obj_t obj)
00570 {
00571   hwloc_obj_t current = obj->parent;
00572   if (!obj->cpuset)
00573     return NULL;
00574   while (current && current->cpuset) {
00575     if (!hwloc_bitmap_isequal(current->cpuset, obj->cpuset)
00576         && current->type == HWLOC_OBJ_CACHE)
00577       return current;
00578     current = current->parent;
00579   }
00580   return NULL;
00581 }
00582 
00607 /* TODO: rather provide an iterator? Provide a way to know how much should be allocated? By returning the total number of objects instead? */
00608  unsigned hwloc_get_closest_objs (hwloc_topology_t topology, hwloc_obj_t src, hwloc_obj_t * restrict objs, unsigned max);
00609 
00622 static inline hwloc_obj_t 
00623 hwloc_get_obj_below_by_type (hwloc_topology_t topology,
00624                              hwloc_obj_type_t type1, unsigned idx1,
00625                              hwloc_obj_type_t type2, unsigned idx2)
00626 {
00627   hwloc_obj_t obj;
00628   obj = hwloc_get_obj_by_type (topology, type1, idx1);
00629   if (!obj || !obj->cpuset)
00630     return NULL;
00631   return hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, type2, idx2);
00632 }
00633 
00652 static inline hwloc_obj_t 
00653 hwloc_get_obj_below_array_by_type (hwloc_topology_t topology, int nr, hwloc_obj_type_t *typev, unsigned *idxv)
00654 {
00655   hwloc_obj_t obj = hwloc_get_root_obj(topology);
00656   int i;
00657   for(i=0; i<nr; i++) {
00658     if (!obj || !obj->cpuset)
00659       return NULL;
00660     obj = hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, typev[i], idxv[i]);
00661   }
00662   return obj;
00663 }
00664 
00688 static inline void
00689 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *root, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until);
00690 static inline void
00691 hwloc_distribute(hwloc_topology_t topology, hwloc_obj_t root, hwloc_cpuset_t *cpuset, unsigned n, unsigned until)
00692 {
00693   unsigned i;
00694   if (!root->arity || n == 1 || root->depth >= until) {
00695     /* Got to the bottom, we can't split any more, put everything there.  */
00696     for (i=0; i<n; i++)
00697       cpuset[i] = hwloc_bitmap_dup(root->cpuset);
00698     return;
00699   }
00700   hwloc_distributev(topology, root->children, root->arity, cpuset, n, until);
00701 }
00702 
00710 static inline void
00711 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *roots, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until)
00712 {
00713   unsigned i;
00714   unsigned tot_weight;
00715   hwloc_cpuset_t *cpusetp = cpuset;
00716 
00717   tot_weight = 0;
00718   for (i = 0; i < n_roots; i++)
00719     if (roots[i]->cpuset)
00720       tot_weight += hwloc_bitmap_weight(roots[i]->cpuset);
00721 
00722   for (i = 0; i < n_roots && tot_weight; i++) {
00723     /* Give to roots[i] a portion proportional to its weight */
00724     unsigned weight = roots[i]->cpuset ? hwloc_bitmap_weight(roots[i]->cpuset) : 0;
00725     unsigned chunk = (n * weight + tot_weight-1) / tot_weight;
00726     hwloc_distribute(topology, roots[i], cpusetp, chunk, until);
00727     cpusetp += chunk;
00728     tot_weight -= weight;
00729     n -= chunk;
00730   }
00731 }
00732 
00739 static inline void *
00740 hwloc_alloc_membind_policy_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
00741 {
00742   void *p = hwloc_alloc_membind_nodeset(topology, len, nodeset, policy, flags);
00743   if (p)
00744     return p;
00745   hwloc_set_membind_nodeset(topology, nodeset, policy, flags);
00746   p = hwloc_alloc(topology, len);
00747   if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH)
00748     /* Enforce the binding by touching the data */
00749     memset(p, 0, len);
00750   return p;
00751 }
00752 
00757 static inline void *
00758 hwloc_alloc_membind_policy(hwloc_topology_t topology, size_t len, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags)
00759 {
00760   void *p = hwloc_alloc_membind(topology, len, cpuset, policy, flags);
00761   if (p)
00762     return p;
00763   hwloc_set_membind(topology, cpuset, policy, flags);
00764   p = hwloc_alloc(topology, len);
00765   if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH)
00766     /* Enforce the binding by touching the data */
00767     memset(p, 0, len);
00768   return p;
00769 }
00770 
00787 static inline hwloc_const_cpuset_t 
00788 hwloc_topology_get_complete_cpuset(hwloc_topology_t topology)
00789 {
00790   return hwloc_get_root_obj(topology)->complete_cpuset;
00791 }
00792 
00803 static inline hwloc_const_cpuset_t 
00804 hwloc_topology_get_topology_cpuset(hwloc_topology_t topology)
00805 {
00806   return hwloc_get_root_obj(topology)->cpuset;
00807 }
00808 
00818 static inline hwloc_const_cpuset_t 
00819 hwloc_topology_get_online_cpuset(hwloc_topology_t topology)
00820 {
00821   return hwloc_get_root_obj(topology)->online_cpuset;
00822 }
00823 
00833 static inline hwloc_const_cpuset_t 
00834 hwloc_topology_get_allowed_cpuset(hwloc_topology_t topology)
00835 {
00836   return hwloc_get_root_obj(topology)->allowed_cpuset;
00837 }
00838 
00855 static inline hwloc_const_nodeset_t 
00856 hwloc_topology_get_complete_nodeset(hwloc_topology_t topology)
00857 {
00858   return hwloc_get_root_obj(topology)->complete_nodeset;
00859 }
00860 
00871 static inline hwloc_const_nodeset_t 
00872 hwloc_topology_get_topology_nodeset(hwloc_topology_t topology)
00873 {
00874   return hwloc_get_root_obj(topology)->nodeset;
00875 }
00876 
00886 static inline hwloc_const_nodeset_t 
00887 hwloc_topology_get_allowed_nodeset(hwloc_topology_t topology)
00888 {
00889   return hwloc_get_root_obj(topology)->allowed_nodeset;
00890 }
00891 
00922 static inline void
00923 hwloc_cpuset_to_nodeset(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset)
00924 {
00925         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
00926         hwloc_obj_t obj;
00927 
00928         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) {
00929                  if (hwloc_bitmap_iszero(cpuset))
00930                         hwloc_bitmap_zero(nodeset);
00931                 else
00932                         /* Assume the whole system */
00933                         hwloc_bitmap_fill(nodeset);
00934                 return;
00935         }
00936 
00937         hwloc_bitmap_zero(nodeset);
00938         obj = NULL;
00939         while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL)
00940                 hwloc_bitmap_set(nodeset, obj->os_index);
00941 }
00942 
00950 static inline void
00951 hwloc_cpuset_to_nodeset_strict(struct hwloc_topology *topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset)
00952 {
00953         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
00954         hwloc_obj_t obj;
00955         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN )
00956                 return;
00957         hwloc_bitmap_zero(nodeset);
00958         obj = NULL;
00959         while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL)
00960                 hwloc_bitmap_set(nodeset, obj->os_index);
00961 }
00962 
00971 static inline void
00972 hwloc_cpuset_from_nodeset(hwloc_topology_t topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset)
00973 {
00974         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
00975         hwloc_obj_t obj;
00976 
00977         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) {
00978                 if (hwloc_bitmap_iszero(nodeset))
00979                         hwloc_bitmap_zero(cpuset);
00980                 else
00981                         /* Assume the whole system */
00982                         hwloc_bitmap_fill(cpuset);
00983                 return;
00984         }
00985 
00986         hwloc_bitmap_zero(cpuset);
00987         obj = NULL;
00988         while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL) {
00989                 if (hwloc_bitmap_isset(nodeset, obj->os_index))
00990                         /* no need to check obj->cpuset because objects in levels always have a cpuset */
00991                         hwloc_bitmap_or(cpuset, cpuset, obj->cpuset);
00992         }
00993 }
00994 
01002 static inline void
01003 hwloc_cpuset_from_nodeset_strict(struct hwloc_topology *topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset)
01004 {
01005         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
01006         hwloc_obj_t obj;
01007         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN )
01008                 return;
01009         hwloc_bitmap_zero(cpuset);
01010         obj = NULL;
01011         while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL)
01012                 if (hwloc_bitmap_isset(nodeset, obj->os_index))
01013                         /* no need to check obj->cpuset because objects in levels always have a cpuset */
01014                         hwloc_bitmap_or(cpuset, cpuset, obj->cpuset);
01015 }
01016 
01044 static inline const struct hwloc_distances_s *
01045 hwloc_get_whole_distance_matrix_by_depth(hwloc_topology_t topology, unsigned depth)
01046 {
01047   hwloc_obj_t root = hwloc_get_root_obj(topology);
01048   unsigned i;
01049   for(i=0; i<root->distances_count; i++)
01050     if (root->distances[i]->relative_depth == depth)
01051       return root->distances[i];
01052   return NULL;
01053 }
01054 
01074 static inline const struct hwloc_distances_s *
01075 hwloc_get_whole_distance_matrix_by_type(hwloc_topology_t topology, hwloc_obj_type_t type)
01076 {
01077   int depth = hwloc_get_type_depth(topology, type);
01078   if (depth < 0)
01079     return NULL;
01080   return hwloc_get_whole_distance_matrix_by_depth(topology, depth);
01081 }
01082 
01096 static inline const struct hwloc_distances_s *
01097 hwloc_get_distance_matrix_covering_obj_by_depth(hwloc_topology_t topology,
01098                                                 hwloc_obj_t obj, unsigned depth,
01099                                                 unsigned *firstp)
01100 {
01101   while (obj && obj->cpuset) {
01102     unsigned i;
01103     for(i=0; i<obj->distances_count; i++)
01104       if (obj->distances[i]->relative_depth == depth - obj->depth) {
01105         if (!obj->distances[i]->nbobjs)
01106           continue;
01107         *firstp = hwloc_get_next_obj_inside_cpuset_by_depth(topology, obj->cpuset, depth, NULL)->logical_index;
01108         return obj->distances[i];
01109       }
01110     obj = obj->parent;
01111   }
01112   return NULL;
01113 }
01114 
01126 static inline int
01127 hwloc_get_latency(hwloc_topology_t topology,
01128                    hwloc_obj_t obj1, hwloc_obj_t obj2,
01129                    float *latency, float *reverse_latency)
01130 {
01131   hwloc_obj_t ancestor;
01132   const struct hwloc_distances_s * distances;
01133   unsigned first_logical ;
01134 
01135   if (obj1->depth != obj2->depth) {
01136     errno = EINVAL;
01137     return -1;
01138   }
01139 
01140   ancestor = hwloc_get_common_ancestor_obj(topology, obj1, obj2);
01141   distances = hwloc_get_distance_matrix_covering_obj_by_depth(topology, ancestor, obj1->depth, &first_logical);
01142   if (distances && distances->latency) {
01143     const float * latency_matrix = distances->latency;
01144     unsigned nbobjs = distances->nbobjs;
01145     unsigned l1 = obj1->logical_index - first_logical;
01146     unsigned l2 = obj2->logical_index - first_logical;
01147     *latency = latency_matrix[l1*nbobjs+l2];
01148     *reverse_latency = latency_matrix[l2*nbobjs+l1];
01149     return 0;
01150   }
01151 
01152   errno = ENOSYS;
01153   return -1;
01154 }
01155 
01170 static inline hwloc_obj_t
01171 hwloc_get_non_io_ancestor_obj(hwloc_topology_t topology ,
01172                               hwloc_obj_t ioobj)
01173 {
01174   hwloc_obj_t obj = ioobj;
01175   while (obj && !obj->cpuset) {
01176     obj = obj->parent;
01177   }
01178   return obj;
01179 }
01180 
01185 static inline hwloc_obj_t
01186 hwloc_get_next_pcidev(hwloc_topology_t topology, hwloc_obj_t prev)
01187 {
01188   return hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_PCI_DEVICE, prev);
01189 }
01190 
01194 static inline hwloc_obj_t
01195 hwloc_get_pcidev_by_busid(hwloc_topology_t topology,
01196                           unsigned domain, unsigned bus, unsigned dev, unsigned func)
01197 {
01198   hwloc_obj_t obj = NULL;
01199   while ((obj = hwloc_get_next_pcidev(topology, obj)) != NULL) {
01200     if (obj->attr->pcidev.domain == domain
01201         && obj->attr->pcidev.bus == bus
01202         && obj->attr->pcidev.dev == dev
01203         && obj->attr->pcidev.func == func)
01204       return obj;
01205   }
01206   return NULL;
01207 }
01208 
01212 static inline hwloc_obj_t
01213 hwloc_get_pcidev_by_busidstring(hwloc_topology_t topology, const char *busid)
01214 {
01215   unsigned domain = 0; /* default */
01216   unsigned bus, dev, func;
01217 
01218   if (sscanf(busid, "%x:%x.%x", &bus, &dev, &func) != 3
01219       && sscanf(busid, "%x:%x:%x.%x", &domain, &bus, &dev, &func) != 4) {
01220     errno = EINVAL;
01221     return NULL;
01222   }
01223 
01224   return hwloc_get_pcidev_by_busid(topology, domain, bus, dev, func);
01225 }
01226 
01231 static inline hwloc_obj_t
01232 hwloc_get_next_osdev(hwloc_topology_t topology, hwloc_obj_t prev)
01233 {
01234   return hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_OS_DEVICE, prev);
01235 }
01236 
01241 static inline hwloc_obj_t
01242 hwloc_get_next_bridge(hwloc_topology_t topology, hwloc_obj_t prev)
01243 {
01244   return hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_BRIDGE, prev);
01245 }
01246 
01247 /* \brief Checks whether a given bridge covers a given PCI bus.
01248  */
01249 static inline int
01250 hwloc_bridge_covers_pcibus(hwloc_obj_t bridge,
01251                            unsigned domain, unsigned bus)
01252 {
01253   return bridge->type == HWLOC_OBJ_BRIDGE
01254     && bridge->attr->bridge.downstream_type == HWLOC_OBJ_BRIDGE_PCI
01255     && bridge->attr->bridge.downstream.pci.domain == domain
01256     && bridge->attr->bridge.downstream.pci.secondary_bus <= bus
01257     && bridge->attr->bridge.downstream.pci.subordinate_bus >= bus;
01258 }
01259 
01265 static inline hwloc_obj_t
01266 hwloc_get_hostbridge_by_pcibus(hwloc_topology_t topology,
01267                                unsigned domain, unsigned bus)
01268 {
01269   hwloc_obj_t obj = NULL;
01270   while ((obj = hwloc_get_next_bridge(topology, obj)) != NULL) {
01271     if (hwloc_bridge_covers_pcibus(obj, domain, bus)) {
01272       /* found bridge covering this pcibus, make sure it's a hostbridge */
01273       assert(obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_HOST);
01274       assert(obj->parent->type != HWLOC_OBJ_BRIDGE);
01275       assert(obj->parent->cpuset);
01276       return obj;
01277     }
01278   }
01279   return NULL;
01280 }
01281 
01286 #ifdef __cplusplus
01287 } /* extern "C" */
01288 #endif
01289 
01290 
01291 #endif /* HWLOC_HELPER_H */