Open MPI logo

Portable Hardware Locality (hwloc) Documentation: v1.3.2

  |   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 
00247 static inline hwloc_obj_t
00248 hwloc_get_first_largest_obj_inside_cpuset(hwloc_topology_t topology, hwloc_const_cpuset_t set)
00249 {
00250   hwloc_obj_t obj = hwloc_get_root_obj(topology);
00251   /* FIXME: what if !root->cpuset? */
00252   if (!hwloc_bitmap_intersects(obj->cpuset, set))
00253     return NULL;
00254   while (!hwloc_bitmap_isincluded(obj->cpuset, set)) {
00255     /* while the object intersects without being included, look at its children */
00256     hwloc_obj_t child = NULL;
00257     while ((child = hwloc_get_next_child(topology, obj, child)) != NULL) {
00258       if (child->cpuset && hwloc_bitmap_intersects(child->cpuset, set))
00259         break;
00260     }
00261     if (!child)
00262       /* no child intersects, return their father */
00263       return obj;
00264     /* found one intersecting child, look at its children */
00265     obj = child;
00266   }
00267   /* obj is included, return it */
00268   return obj;
00269 }
00270 
00275  int hwloc_get_largest_objs_inside_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00276                                                  hwloc_obj_t * restrict objs, int max);
00277 
00284 static inline hwloc_obj_t
00285 hwloc_get_next_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00286                                            unsigned depth, hwloc_obj_t prev)
00287 {
00288   hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev);
00289   /* no need to check next->cpuset because objects in levels always have a cpuset */
00290   while (next && !hwloc_bitmap_isincluded(next->cpuset, set))
00291     next = next->next_cousin;
00292   return next;
00293 }
00294 
00301 static inline hwloc_obj_t
00302 hwloc_get_next_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00303                                           hwloc_obj_type_t type, hwloc_obj_t prev)
00304 {
00305   int depth = hwloc_get_type_depth(topology, type);
00306   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00307     return NULL;
00308   return hwloc_get_next_obj_inside_cpuset_by_depth(topology, set, depth, prev);
00309 }
00310 
00313 static inline hwloc_obj_t 
00314 hwloc_get_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00315                                       unsigned depth, unsigned idx)
00316 {
00317   unsigned count = 0;
00318   hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0);
00319   while (obj) {
00320     /* no need to check obj->cpuset because objects in levels always have a cpuset */
00321     if (hwloc_bitmap_isincluded(obj->cpuset, set)) {
00322       if (count == idx)
00323         return obj;
00324       count++;
00325     }
00326     obj = obj->next_cousin;
00327   }
00328   return NULL;
00329 }
00330 
00337 static inline hwloc_obj_t 
00338 hwloc_get_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00339                                      hwloc_obj_type_t type, unsigned idx)
00340 {
00341   int depth = hwloc_get_type_depth(topology, type);
00342   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00343     return NULL;
00344   return hwloc_get_obj_inside_cpuset_by_depth(topology, set, depth, idx);
00345 }
00346 
00348 static inline unsigned 
00349 hwloc_get_nbobjs_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00350                                          unsigned depth)
00351 {
00352   hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0);
00353   int count = 0;
00354   while (obj) {
00355     /* no need to check obj->cpuset because objects in levels always have a cpuset */
00356     if (hwloc_bitmap_isincluded(obj->cpuset, set))
00357       count++;
00358     obj = obj->next_cousin;
00359   }
00360   return count;
00361 }
00362 
00369 static inline int 
00370 hwloc_get_nbobjs_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00371                                         hwloc_obj_type_t type)
00372 {
00373   int depth = hwloc_get_type_depth(topology, type);
00374   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN)
00375     return 0;
00376   if (depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00377     return -1; /* FIXME: agregate nbobjs from different levels? */
00378   return hwloc_get_nbobjs_inside_cpuset_by_depth(topology, set, depth);
00379 }
00380 
00393 static inline hwloc_obj_t 
00394 hwloc_get_child_covering_cpuset (hwloc_topology_t topology , hwloc_const_cpuset_t set,
00395                                 hwloc_obj_t parent)
00396 {
00397   hwloc_obj_t child;
00398 
00399   if (hwloc_bitmap_iszero(set))
00400     return NULL;
00401 
00402   child = parent->first_child;
00403   while (child) {
00404     if (child->cpuset && hwloc_bitmap_isincluded(set, child->cpuset))
00405       return child;
00406     child = child->next_sibling;
00407   }
00408   return NULL;
00409 }
00410 
00415 static inline hwloc_obj_t 
00416 hwloc_get_obj_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set)
00417 {
00418   struct hwloc_obj *current = hwloc_get_root_obj(topology);
00419 
00420   if (hwloc_bitmap_iszero(set))
00421     return NULL;
00422 
00423   /* FIXME: what if !root->cpuset? */
00424   if (!hwloc_bitmap_isincluded(set, current->cpuset))
00425     return NULL;
00426 
00427   while (1) {
00428     hwloc_obj_t child = hwloc_get_child_covering_cpuset(topology, set, current);
00429     if (!child)
00430       return current;
00431     current = child;
00432   }
00433 }
00434 
00435 
00451 static inline hwloc_obj_t
00452 hwloc_get_next_obj_covering_cpuset_by_depth(hwloc_topology_t topology, hwloc_const_cpuset_t set,
00453                                             unsigned depth, hwloc_obj_t prev)
00454 {
00455   hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev);
00456   /* no need to check next->cpuset because objects in levels always have a cpuset */
00457   while (next && !hwloc_bitmap_intersects(set, next->cpuset))
00458     next = next->next_cousin;
00459   return next;
00460 }
00461 
00474 static inline hwloc_obj_t
00475 hwloc_get_next_obj_covering_cpuset_by_type(hwloc_topology_t topology, hwloc_const_cpuset_t set,
00476                                            hwloc_obj_type_t type, hwloc_obj_t prev)
00477 {
00478   int depth = hwloc_get_type_depth(topology, type);
00479   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00480     return NULL;
00481   return hwloc_get_next_obj_covering_cpuset_by_depth(topology, set, depth, prev);
00482 }
00483 
00496 static inline hwloc_obj_t 
00497 hwloc_get_cache_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set)
00498 {
00499   hwloc_obj_t current = hwloc_get_obj_covering_cpuset(topology, set);
00500   while (current) {
00501     if (current->type == HWLOC_OBJ_CACHE)
00502       return current;
00503     current = current->parent;
00504   }
00505   return NULL;
00506 }
00507 
00512 static inline hwloc_obj_t 
00513 hwloc_get_shared_cache_covering_obj (hwloc_topology_t topology , hwloc_obj_t obj)
00514 {
00515   hwloc_obj_t current = obj->parent;
00516   if (!obj->cpuset)
00517     return NULL;
00518   while (current && current->cpuset) {
00519     if (!hwloc_bitmap_isequal(current->cpuset, obj->cpuset)
00520         && current->type == HWLOC_OBJ_CACHE)
00521       return current;
00522     current = current->parent;
00523   }
00524   return NULL;
00525 }
00526 
00549 /* TODO: rather provide an iterator? Provide a way to know how much should be allocated? By returning the total number of objects instead? */
00550  unsigned hwloc_get_closest_objs (hwloc_topology_t topology, hwloc_obj_t src, hwloc_obj_t * restrict objs, unsigned max);
00551 
00562 static inline hwloc_obj_t 
00563 hwloc_get_obj_below_by_type (hwloc_topology_t topology,
00564                              hwloc_obj_type_t type1, unsigned idx1,
00565                              hwloc_obj_type_t type2, unsigned idx2)
00566 {
00567   hwloc_obj_t obj;
00568 
00569   obj = hwloc_get_obj_by_type (topology, type1, idx1);
00570   if (!obj)
00571     return NULL;
00572 
00573   return hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, type2, idx2);
00574 }
00575 
00591 static inline hwloc_obj_t 
00592 hwloc_get_obj_below_array_by_type (hwloc_topology_t topology, int nr, hwloc_obj_type_t *typev, unsigned *idxv)
00593 {
00594   hwloc_obj_t obj = hwloc_get_root_obj(topology);
00595   int i;
00596 
00597   /* FIXME: what if !root->cpuset? */
00598   for(i=0; i<nr; i++) {
00599     obj = hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, typev[i], idxv[i]);
00600     if (!obj)
00601       return NULL;
00602   }
00603 
00604   return obj;
00605 }
00606 
00628 static inline void
00629 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *root, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until);
00630 static inline void
00631 hwloc_distribute(hwloc_topology_t topology, hwloc_obj_t root, hwloc_cpuset_t *cpuset, unsigned n, unsigned until)
00632 {
00633   unsigned i;
00634 
00635   /* FIXME: what if !root->cpuset? */
00636   if (!root->arity || n == 1 || root->depth >= until) {
00637     /* Got to the bottom, we can't split any more, put everything there.  */
00638     for (i=0; i<n; i++)
00639       cpuset[i] = hwloc_bitmap_dup(root->cpuset);
00640     return;
00641   }
00642 
00643   hwloc_distributev(topology, root->children, root->arity, cpuset, n, until);
00644 }
00645 
00651 static inline void
00652 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *roots, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until)
00653 {
00654   unsigned i;
00655   unsigned tot_weight;
00656   hwloc_cpuset_t *cpusetp = cpuset;
00657 
00658   tot_weight = 0;
00659   for (i = 0; i < n_roots; i++)
00660     if (roots[i]->cpuset)
00661       tot_weight += hwloc_bitmap_weight(roots[i]->cpuset);
00662 
00663   for (i = 0; i < n_roots && tot_weight; i++) {
00664     /* Give to roots[i] a portion proportional to its weight */
00665     unsigned weight = roots[i]->cpuset ? hwloc_bitmap_weight(roots[i]->cpuset) : 0;
00666     unsigned chunk = (n * weight + tot_weight-1) / tot_weight;
00667     hwloc_distribute(topology, roots[i], cpusetp, chunk, until);
00668     cpusetp += chunk;
00669     tot_weight -= weight;
00670     n -= chunk;
00671   }
00672 }
00673 
00680 static inline void *
00681 hwloc_alloc_membind_policy_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
00682 {
00683   void *p = hwloc_alloc_membind_nodeset(topology, len, nodeset, policy, flags);
00684   if (p)
00685     return p;
00686   hwloc_set_membind_nodeset(topology, nodeset, policy, flags);
00687   p = hwloc_alloc(topology, len);
00688   if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH)
00689     /* Enforce the binding by touching the data */
00690     memset(p, 0, len);
00691   return p;
00692 }
00693 
00698 static inline void *
00699 hwloc_alloc_membind_policy(hwloc_topology_t topology, size_t len, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags)
00700 {
00701   void *p = hwloc_alloc_membind(topology, len, cpuset, policy, flags);
00702   if (p)
00703     return p;
00704   hwloc_set_membind(topology, cpuset, policy, flags);
00705   p = hwloc_alloc(topology, len);
00706   if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH)
00707     /* Enforce the binding by touching the data */
00708     memset(p, 0, len);
00709   return p;
00710 }
00711 
00728 static inline hwloc_const_cpuset_t 
00729 hwloc_topology_get_complete_cpuset(hwloc_topology_t topology)
00730 {
00731   return hwloc_get_root_obj(topology)->complete_cpuset;
00732 }
00733 
00744 static inline hwloc_const_cpuset_t 
00745 hwloc_topology_get_topology_cpuset(hwloc_topology_t topology)
00746 {
00747   return hwloc_get_root_obj(topology)->cpuset;
00748 }
00749 
00759 static inline hwloc_const_cpuset_t 
00760 hwloc_topology_get_online_cpuset(hwloc_topology_t topology)
00761 {
00762   return hwloc_get_root_obj(topology)->online_cpuset;
00763 }
00764 
00774 static inline hwloc_const_cpuset_t 
00775 hwloc_topology_get_allowed_cpuset(hwloc_topology_t topology)
00776 {
00777   return hwloc_get_root_obj(topology)->allowed_cpuset;
00778 }
00779 
00796 static inline hwloc_const_nodeset_t 
00797 hwloc_topology_get_complete_nodeset(hwloc_topology_t topology)
00798 {
00799   return hwloc_get_root_obj(topology)->complete_nodeset;
00800 }
00801 
00812 static inline hwloc_const_nodeset_t 
00813 hwloc_topology_get_topology_nodeset(hwloc_topology_t topology)
00814 {
00815   return hwloc_get_root_obj(topology)->nodeset;
00816 }
00817 
00827 static inline hwloc_const_nodeset_t 
00828 hwloc_topology_get_allowed_nodeset(hwloc_topology_t topology)
00829 {
00830   return hwloc_get_root_obj(topology)->allowed_nodeset;
00831 }
00832 
00863 static inline void
00864 hwloc_cpuset_to_nodeset(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset)
00865 {
00866         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
00867         hwloc_obj_t obj;
00868 
00869         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) {
00870                  if (hwloc_bitmap_iszero(cpuset))
00871                         hwloc_bitmap_zero(nodeset);
00872                 else
00873                         /* Assume the whole system */
00874                         hwloc_bitmap_fill(nodeset);
00875                 return;
00876         }
00877 
00878         hwloc_bitmap_zero(nodeset);
00879         obj = NULL;
00880         while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL)
00881                 hwloc_bitmap_set(nodeset, obj->os_index);
00882 }
00883 
00891 static inline void
00892 hwloc_cpuset_to_nodeset_strict(struct hwloc_topology *topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset)
00893 {
00894         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
00895         hwloc_obj_t obj;
00896         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN )
00897                 return;
00898         hwloc_bitmap_zero(nodeset);
00899         obj = NULL;
00900         while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL)
00901                 hwloc_bitmap_set(nodeset, obj->os_index);
00902 }
00903 
00912 static inline void
00913 hwloc_cpuset_from_nodeset(hwloc_topology_t topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset)
00914 {
00915         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
00916         hwloc_obj_t obj;
00917 
00918         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) {
00919                 if (hwloc_bitmap_iszero(nodeset))
00920                         hwloc_bitmap_zero(cpuset);
00921                 else
00922                         /* Assume the whole system */
00923                         hwloc_bitmap_fill(cpuset);
00924                 return;
00925         }
00926 
00927         hwloc_bitmap_zero(cpuset);
00928         obj = NULL;
00929         while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL) {
00930                 if (hwloc_bitmap_isset(nodeset, obj->os_index))
00931                         /* no need to check obj->cpuset because objects in levels always have a cpuset */
00932                         hwloc_bitmap_or(cpuset, cpuset, obj->cpuset);
00933         }
00934 }
00935 
00943 static inline void
00944 hwloc_cpuset_from_nodeset_strict(struct hwloc_topology *topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset)
00945 {
00946         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
00947         hwloc_obj_t obj;
00948         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN )
00949                 return;
00950         hwloc_bitmap_zero(cpuset);
00951         obj = NULL;
00952         while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL)
00953                 if (hwloc_bitmap_isset(nodeset, obj->os_index))
00954                         /* no need to check obj->cpuset because objects in levels always have a cpuset */
00955                         hwloc_bitmap_or(cpuset, cpuset, obj->cpuset);
00956 }
00957 
00985 static inline const struct hwloc_distances_s *
00986 hwloc_get_whole_distance_matrix_by_depth(hwloc_topology_t topology, unsigned depth)
00987 {
00988   hwloc_obj_t root = hwloc_get_root_obj(topology);
00989   unsigned i;
00990   for(i=0; i<root->distances_count; i++)
00991     if (root->distances[i]->relative_depth == depth)
00992       return root->distances[i];
00993   return NULL;
00994 }
00995 
01015 static inline const struct hwloc_distances_s *
01016 hwloc_get_whole_distance_matrix_by_type(hwloc_topology_t topology, hwloc_obj_type_t type)
01017 {
01018   int depth = hwloc_get_type_depth(topology, type);
01019   if (depth < 0)
01020     return NULL;
01021   return hwloc_get_whole_distance_matrix_by_depth(topology, depth);
01022 }
01023 
01037 static inline const struct hwloc_distances_s *
01038 hwloc_get_distance_matrix_covering_obj_by_depth(hwloc_topology_t topology,
01039                                                 hwloc_obj_t obj, unsigned depth,
01040                                                 unsigned *firstp)
01041 {
01042   while (obj && obj->cpuset) {
01043     unsigned i;
01044     for(i=0; i<obj->distances_count; i++)
01045       if (obj->distances[i]->relative_depth == depth - obj->depth) {
01046         if (!obj->distances[i]->nbobjs)
01047           continue;
01048         *firstp = hwloc_get_next_obj_inside_cpuset_by_depth(topology, obj->cpuset, depth, NULL)->logical_index;
01049         return obj->distances[i];
01050       }
01051     obj = obj->parent;
01052   }
01053   return NULL;
01054 }
01055 
01067 static inline int
01068 hwloc_get_latency(hwloc_topology_t topology,
01069                    hwloc_obj_t obj1, hwloc_obj_t obj2,
01070                    float *latency, float *reverse_latency)
01071 {
01072   hwloc_obj_t ancestor;
01073   const struct hwloc_distances_s * distances;
01074   unsigned first_logical ;
01075 
01076   if (obj1->depth != obj2->depth) {
01077     errno = EINVAL;
01078     return -1;
01079   }
01080 
01081   ancestor = hwloc_get_common_ancestor_obj(topology, obj1, obj2);
01082   distances = hwloc_get_distance_matrix_covering_obj_by_depth(topology, ancestor, obj1->depth, &first_logical);
01083   if (distances && distances->latency) {
01084     const float * latency_matrix = distances->latency;
01085     unsigned nbobjs = distances->nbobjs;
01086     unsigned l1 = obj1->logical_index - first_logical;
01087     unsigned l2 = obj2->logical_index - first_logical;
01088     *latency = latency_matrix[l1*nbobjs+l2];
01089     *reverse_latency = latency_matrix[l2*nbobjs+l1];
01090     return 0;
01091   }
01092 
01093   errno = ENOSYS;
01094   return -1;
01095 }
01096 
01111 static inline hwloc_obj_t
01112 hwloc_get_non_io_ancestor_obj(hwloc_topology_t topology ,
01113                               hwloc_obj_t ioobj)
01114 {
01115   hwloc_obj_t obj = ioobj;
01116   while (obj && !obj->cpuset) {
01117     obj = obj->parent;
01118   }
01119   return obj;
01120 }
01121 
01126 static inline hwloc_obj_t
01127 hwloc_get_next_pcidev(hwloc_topology_t topology, hwloc_obj_t prev)
01128 {
01129   return hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_PCI_DEVICE, prev);
01130 }
01131 
01135 static inline hwloc_obj_t
01136 hwloc_get_pcidev_by_busid(hwloc_topology_t topology,
01137                           unsigned domain, unsigned bus, unsigned dev, unsigned func)
01138 {
01139   hwloc_obj_t obj = NULL;
01140   while ((obj = hwloc_get_next_pcidev(topology, obj)) != NULL) {
01141     if (obj->attr->pcidev.domain == domain
01142         && obj->attr->pcidev.bus == bus
01143         && obj->attr->pcidev.dev == dev
01144         && obj->attr->pcidev.func == func)
01145       return obj;
01146   }
01147   return NULL;
01148 }
01149 
01153 static inline hwloc_obj_t
01154 hwloc_get_pcidev_by_busidstring(hwloc_topology_t topology, const char *busid)
01155 {
01156   unsigned domain = 0; /* default */
01157   unsigned bus, dev, func;
01158 
01159   if (sscanf(busid, "%x:%x.%x", &bus, &dev, &func) != 3
01160       && sscanf(busid, "%x:%x:%x.%x", &domain, &bus, &dev, &func) != 4) {
01161     errno = EINVAL;
01162     return NULL;
01163   }
01164 
01165   return hwloc_get_pcidev_by_busid(topology, domain, bus, dev, func);
01166 }
01167 
01172 static inline hwloc_obj_t
01173 hwloc_get_next_osdev(hwloc_topology_t topology, hwloc_obj_t prev)
01174 {
01175   return hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_OS_DEVICE, prev);
01176 }
01177 
01182 static inline hwloc_obj_t
01183 hwloc_get_next_bridge(hwloc_topology_t topology, hwloc_obj_t prev)
01184 {
01185   return hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_BRIDGE, prev);
01186 }
01187 
01188 /* \brief Checks whether a given bridge covers a given PCI bus.
01189  */
01190 static inline int
01191 hwloc_bridge_covers_pcibus(hwloc_obj_t bridge,
01192                            unsigned domain, unsigned bus)
01193 {
01194   return bridge->type == HWLOC_OBJ_BRIDGE
01195     && bridge->attr->bridge.downstream_type == HWLOC_OBJ_BRIDGE_PCI
01196     && bridge->attr->bridge.downstream.pci.domain == domain
01197     && bridge->attr->bridge.downstream.pci.secondary_bus <= bus
01198     && bridge->attr->bridge.downstream.pci.subordinate_bus >= bus;
01199 }
01200 
01206 static inline hwloc_obj_t
01207 hwloc_get_hostbridge_by_pcibus(hwloc_topology_t topology,
01208                                unsigned domain, unsigned bus)
01209 {
01210   hwloc_obj_t obj = NULL;
01211   while ((obj = hwloc_get_next_bridge(topology, obj)) != NULL) {
01212     if (hwloc_bridge_covers_pcibus(obj, domain, bus)) {
01213       /* found bridge covering this pcibus, make sure it's a hostbridge */
01214       assert(obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_HOST);
01215       assert(obj->parent->type != HWLOC_OBJ_BRIDGE);
01216       assert(obj->parent->cpuset);
01217       return obj;
01218     }
01219   }
01220   return NULL;
01221 }
01222 
01227 #ifdef __cplusplus
01228 } /* extern "C" */
01229 #endif
01230 
01231 
01232 #endif /* HWLOC_HELPER_H */