Open MPI logo

Portable Hardware Locality (hwloc) Documentation: v1.2

  |   Home   |   Support   |   FAQ   |  

helper.h

Go to the documentation of this file.
00001 /*
00002  * Copyright © 2009 CNRS
00003  * Copyright © 2009-2011 INRIA.  All rights reserved.
00004  * Copyright © 2009-2010 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 
00039 static inline int 
00040 hwloc_get_type_or_below_depth (hwloc_topology_t topology, hwloc_obj_type_t type)
00041 {
00042   int depth = hwloc_get_type_depth(topology, type);
00043 
00044   if (depth != HWLOC_TYPE_DEPTH_UNKNOWN)
00045     return depth;
00046 
00047   /* find the highest existing level with type order >= */
00048   for(depth = hwloc_get_type_depth(topology, HWLOC_OBJ_PU); ; depth--)
00049     if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) < 0)
00050       return depth+1;
00051 
00052   /* Shouldn't ever happen, as there is always a SYSTEM level with lower order and known depth.  */
00053   /* abort(); */
00054 }
00055 
00062 static inline int 
00063 hwloc_get_type_or_above_depth (hwloc_topology_t topology, hwloc_obj_type_t type)
00064 {
00065   int depth = hwloc_get_type_depth(topology, type);
00066 
00067   if (depth != HWLOC_TYPE_DEPTH_UNKNOWN)
00068     return depth;
00069 
00070   /* find the lowest existing level with type order <= */
00071   for(depth = 0; ; depth++)
00072     if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) > 0)
00073       return depth-1;
00074 
00075   /* Shouldn't ever happen, as there is always a PU level with higher order and known depth.  */
00076   /* abort(); */
00077 }
00078 
00093 static inline hwloc_obj_t 
00094 hwloc_get_root_obj (hwloc_topology_t topology)
00095 {
00096   return hwloc_get_obj_by_depth (topology, 0, 0);
00097 }
00098 
00100 static inline hwloc_obj_t 
00101 hwloc_get_ancestor_obj_by_depth (hwloc_topology_t topology , unsigned depth, hwloc_obj_t obj)
00102 {
00103   hwloc_obj_t ancestor = obj;
00104   if (obj->depth < depth)
00105     return NULL;
00106   while (ancestor && ancestor->depth > depth)
00107     ancestor = ancestor->parent;
00108   return ancestor;
00109 }
00110 
00112 static inline hwloc_obj_t 
00113 hwloc_get_ancestor_obj_by_type (hwloc_topology_t topology , hwloc_obj_type_t type, hwloc_obj_t obj)
00114 {
00115   hwloc_obj_t ancestor = obj->parent;
00116   while (ancestor && ancestor->type != type)
00117     ancestor = ancestor->parent;
00118   return ancestor;
00119 }
00120 
00125 static inline hwloc_obj_t
00126 hwloc_get_next_obj_by_depth (hwloc_topology_t topology, unsigned depth, hwloc_obj_t prev)
00127 {
00128   if (!prev)
00129     return hwloc_get_obj_by_depth (topology, depth, 0);
00130   if (prev->depth != depth)
00131     return NULL;
00132   return prev->next_cousin;
00133 }
00134 
00141 static inline hwloc_obj_t
00142 hwloc_get_next_obj_by_type (hwloc_topology_t topology, hwloc_obj_type_t type,
00143                    hwloc_obj_t prev)
00144 {
00145   int depth = hwloc_get_type_depth(topology, type);
00146   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00147     return NULL;
00148   return hwloc_get_next_obj_by_depth (topology, depth, prev);
00149 }
00150 
00159 static inline hwloc_obj_t 
00160 hwloc_get_pu_obj_by_os_index(hwloc_topology_t topology, unsigned os_index)
00161 {
00162   hwloc_obj_t obj = NULL;
00163   while ((obj = hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_PU, obj)) != NULL)
00164     if (obj->os_index == os_index)
00165       return obj;
00166   return NULL;
00167 }
00168 
00173 static inline hwloc_obj_t
00174 hwloc_get_next_child (hwloc_topology_t topology , hwloc_obj_t parent, hwloc_obj_t prev)
00175 {
00176   if (!prev)
00177     return parent->first_child;
00178   if (prev->parent != parent)
00179     return NULL;
00180   return prev->next_sibling;
00181 }
00182 
00184 static inline hwloc_obj_t 
00185 hwloc_get_common_ancestor_obj (hwloc_topology_t topology , hwloc_obj_t obj1, hwloc_obj_t obj2)
00186 {
00187   /* the loop isn't so easy since intermediate ancestors may have
00188    * different depth, causing us to alternate between using obj1->parent
00189    * and obj2->parent. Also, even if at some point we find ancestors of
00190    * of the same depth, their ancestors may have different depth again.
00191    */
00192   while (obj1 != obj2) {
00193     while (obj1->depth > obj2->depth)
00194       obj1 = obj1->parent;
00195     while (obj2->depth > obj1->depth)
00196       obj2 = obj2->parent;
00197     if (obj1 != obj2 && obj1->depth == obj2->depth) {
00198       obj1 = obj1->parent;
00199       obj2 = obj2->parent;
00200     }
00201   }
00202   return obj1;
00203 }
00204 
00209 static inline int 
00210 hwloc_obj_is_in_subtree (hwloc_topology_t topology , hwloc_obj_t obj, hwloc_obj_t subtree_root)
00211 {
00212   return hwloc_bitmap_isincluded(obj->cpuset, subtree_root->cpuset);
00213 }
00214 
00231 static inline hwloc_obj_t
00232 hwloc_get_first_largest_obj_inside_cpuset(hwloc_topology_t topology, hwloc_const_cpuset_t set)
00233 {
00234   hwloc_obj_t obj = hwloc_get_root_obj(topology);
00235   /* FIXME: what if !root->cpuset? */
00236   if (!hwloc_bitmap_intersects(obj->cpuset, set))
00237     return NULL;
00238   while (!hwloc_bitmap_isincluded(obj->cpuset, set)) {
00239     /* while the object intersects without being included, look at its children */
00240     hwloc_obj_t child = NULL;
00241     while ((child = hwloc_get_next_child(topology, obj, child)) != NULL) {
00242       if (child->cpuset && hwloc_bitmap_intersects(child->cpuset, set))
00243         break;
00244     }
00245     if (!child)
00246       /* no child intersects, return their father */
00247       return obj;
00248     /* found one intersecting child, look at its children */
00249     obj = child;
00250   }
00251   /* obj is included, return it */
00252   return obj;
00253 }
00254 
00259  int hwloc_get_largest_objs_inside_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00260                                                  hwloc_obj_t * restrict objs, int max);
00261 
00268 static inline hwloc_obj_t
00269 hwloc_get_next_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00270                                            unsigned depth, hwloc_obj_t prev)
00271 {
00272   hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev);
00273   /* no need to check next->cpuset because objects in levels always have a cpuset */
00274   while (next && !hwloc_bitmap_isincluded(next->cpuset, set))
00275     next = next->next_cousin;
00276   return next;
00277 }
00278 
00285 static inline hwloc_obj_t
00286 hwloc_get_next_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00287                                           hwloc_obj_type_t type, hwloc_obj_t prev)
00288 {
00289   int depth = hwloc_get_type_depth(topology, type);
00290   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00291     return NULL;
00292   return hwloc_get_next_obj_inside_cpuset_by_depth(topology, set, depth, prev);
00293 }
00294 
00297 static inline hwloc_obj_t 
00298 hwloc_get_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00299                                       unsigned depth, unsigned idx)
00300 {
00301   unsigned count = 0;
00302   hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0);
00303   while (obj) {
00304     /* no need to check obj->cpuset because objects in levels always have a cpuset */
00305     if (hwloc_bitmap_isincluded(obj->cpuset, set)) {
00306       if (count == idx)
00307         return obj;
00308       count++;
00309     }
00310     obj = obj->next_cousin;
00311   }
00312   return NULL;
00313 }
00314 
00321 static inline hwloc_obj_t 
00322 hwloc_get_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00323                                      hwloc_obj_type_t type, unsigned idx)
00324 {
00325   int depth = hwloc_get_type_depth(topology, type);
00326   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00327     return NULL;
00328   return hwloc_get_obj_inside_cpuset_by_depth(topology, set, depth, idx);
00329 }
00330 
00332 static inline unsigned 
00333 hwloc_get_nbobjs_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00334                                          unsigned depth)
00335 {
00336   hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0);
00337   int count = 0;
00338   while (obj) {
00339     /* no need to check obj->cpuset because objects in levels always have a cpuset */
00340     if (hwloc_bitmap_isincluded(obj->cpuset, set))
00341       count++;
00342     obj = obj->next_cousin;
00343   }
00344   return count;
00345 }
00346 
00353 static inline int 
00354 hwloc_get_nbobjs_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00355                                         hwloc_obj_type_t type)
00356 {
00357   int depth = hwloc_get_type_depth(topology, type);
00358   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN)
00359     return 0;
00360   if (depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00361     return -1; /* FIXME: agregate nbobjs from different levels? */
00362   return hwloc_get_nbobjs_inside_cpuset_by_depth(topology, set, depth);
00363 }
00364 
00377 static inline hwloc_obj_t 
00378 hwloc_get_child_covering_cpuset (hwloc_topology_t topology , hwloc_const_cpuset_t set,
00379                                 hwloc_obj_t parent)
00380 {
00381   hwloc_obj_t child;
00382 
00383   if (hwloc_bitmap_iszero(set))
00384     return NULL;
00385 
00386   child = parent->first_child;
00387   while (child) {
00388     if (child->cpuset && hwloc_bitmap_isincluded(set, child->cpuset))
00389       return child;
00390     child = child->next_sibling;
00391   }
00392   return NULL;
00393 }
00394 
00399 static inline hwloc_obj_t 
00400 hwloc_get_obj_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set)
00401 {
00402   struct hwloc_obj *current = hwloc_get_root_obj(topology);
00403 
00404   if (hwloc_bitmap_iszero(set))
00405     return NULL;
00406 
00407   /* FIXME: what if !root->cpuset? */
00408   if (!hwloc_bitmap_isincluded(set, current->cpuset))
00409     return NULL;
00410 
00411   while (1) {
00412     hwloc_obj_t child = hwloc_get_child_covering_cpuset(topology, set, current);
00413     if (!child)
00414       return current;
00415     current = child;
00416   }
00417 }
00418 
00419 
00435 static inline hwloc_obj_t
00436 hwloc_get_next_obj_covering_cpuset_by_depth(hwloc_topology_t topology, hwloc_const_cpuset_t set,
00437                                             unsigned depth, hwloc_obj_t prev)
00438 {
00439   hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev);
00440   /* no need to check next->cpuset because objects in levels always have a cpuset */
00441   while (next && !hwloc_bitmap_intersects(set, next->cpuset))
00442     next = next->next_cousin;
00443   return next;
00444 }
00445 
00458 static inline hwloc_obj_t
00459 hwloc_get_next_obj_covering_cpuset_by_type(hwloc_topology_t topology, hwloc_const_cpuset_t set,
00460                                            hwloc_obj_type_t type, hwloc_obj_t prev)
00461 {
00462   int depth = hwloc_get_type_depth(topology, type);
00463   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00464     return NULL;
00465   return hwloc_get_next_obj_covering_cpuset_by_depth(topology, set, depth, prev);
00466 }
00467 
00480 static inline hwloc_obj_t 
00481 hwloc_get_cache_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set)
00482 {
00483   hwloc_obj_t current = hwloc_get_obj_covering_cpuset(topology, set);
00484   while (current) {
00485     if (current->type == HWLOC_OBJ_CACHE)
00486       return current;
00487     current = current->parent;
00488   }
00489   return NULL;
00490 }
00491 
00496 static inline hwloc_obj_t 
00497 hwloc_get_shared_cache_covering_obj (hwloc_topology_t topology , hwloc_obj_t obj)
00498 {
00499   hwloc_obj_t current = obj->parent;
00500   if (!obj->cpuset)
00501     return NULL;
00502   while (current && current->cpuset) {
00503     if (!hwloc_bitmap_isequal(current->cpuset, obj->cpuset)
00504         && current->type == HWLOC_OBJ_CACHE)
00505       return current;
00506     current = current->parent;
00507   }
00508   return NULL;
00509 }
00510 
00526 /* TODO: rather provide an iterator? Provide a way to know how much should be allocated? By returning the total number of objects instead? */
00527  unsigned hwloc_get_closest_objs (hwloc_topology_t topology, hwloc_obj_t src, hwloc_obj_t * restrict objs, unsigned max);
00528 
00539 static inline hwloc_obj_t 
00540 hwloc_get_obj_below_by_type (hwloc_topology_t topology,
00541                              hwloc_obj_type_t type1, unsigned idx1,
00542                              hwloc_obj_type_t type2, unsigned idx2)
00543 {
00544   hwloc_obj_t obj;
00545 
00546   obj = hwloc_get_obj_by_type (topology, type1, idx1);
00547   if (!obj)
00548     return NULL;
00549 
00550   return hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, type2, idx2);
00551 }
00552 
00568 static inline hwloc_obj_t 
00569 hwloc_get_obj_below_array_by_type (hwloc_topology_t topology, int nr, hwloc_obj_type_t *typev, unsigned *idxv)
00570 {
00571   hwloc_obj_t obj = hwloc_get_root_obj(topology);
00572   int i;
00573 
00574   /* FIXME: what if !root->cpuset? */
00575   for(i=0; i<nr; i++) {
00576     obj = hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, typev[i], idxv[i]);
00577     if (!obj)
00578       return NULL;
00579   }
00580 
00581   return obj;
00582 }
00583 
00605 static inline void
00606 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *root, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until);
00607 static inline void
00608 hwloc_distribute(hwloc_topology_t topology, hwloc_obj_t root, hwloc_cpuset_t *cpuset, unsigned n, unsigned until)
00609 {
00610   unsigned i;
00611 
00612   /* FIXME: what if !root->cpuset? */
00613   if (!root->arity || n == 1 || root->depth >= until) {
00614     /* Got to the bottom, we can't split any more, put everything there.  */
00615     for (i=0; i<n; i++)
00616       cpuset[i] = hwloc_bitmap_dup(root->cpuset);
00617     return;
00618   }
00619 
00620   hwloc_distributev(topology, root->children, root->arity, cpuset, n, until);
00621 }
00622 
00628 static inline void
00629 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *roots, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until)
00630 {
00631   unsigned i;
00632   unsigned tot_weight;
00633   hwloc_cpuset_t *cpusetp = cpuset;
00634 
00635   tot_weight = 0;
00636   for (i = 0; i < n_roots; i++)
00637     if (roots[i]->cpuset)
00638       tot_weight += hwloc_bitmap_weight(roots[i]->cpuset);
00639 
00640   for (i = 0; i < n_roots && tot_weight; i++) {
00641     /* Give to roots[i] a portion proportional to its weight */
00642     unsigned weight = roots[i]->cpuset ? hwloc_bitmap_weight(roots[i]->cpuset) : 0;
00643     unsigned chunk = (n * weight + tot_weight-1) / tot_weight;
00644     hwloc_distribute(topology, roots[i], cpusetp, chunk, until);
00645     cpusetp += chunk;
00646     tot_weight -= weight;
00647     n -= chunk;
00648   }
00649 }
00650 
00657 static inline void *
00658 hwloc_alloc_membind_policy_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
00659 {
00660   void *p = hwloc_alloc_membind_nodeset(topology, len, nodeset, policy, flags);
00661   if (p)
00662     return p;
00663   hwloc_set_membind_nodeset(topology, nodeset, policy, flags);
00664   p = hwloc_alloc(topology, len);
00665   if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH)
00666     /* Enforce the binding by touching the data */
00667     memset(p, 0, len);
00668   return p;
00669 }
00670 
00675 static inline void *
00676 hwloc_alloc_membind_policy(hwloc_topology_t topology, size_t len, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags)
00677 {
00678   void *p = hwloc_alloc_membind(topology, len, cpuset, policy, flags);
00679   if (p)
00680     return p;
00681   hwloc_set_membind(topology, cpuset, policy, flags);
00682   p = hwloc_alloc(topology, len);
00683   if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH)
00684     /* Enforce the binding by touching the data */
00685     memset(p, 0, len);
00686   return p;
00687 }
00688 
00705 static inline hwloc_const_cpuset_t 
00706 hwloc_topology_get_complete_cpuset(hwloc_topology_t topology)
00707 {
00708   return hwloc_get_root_obj(topology)->complete_cpuset;
00709 }
00710 
00721 static inline hwloc_const_cpuset_t 
00722 hwloc_topology_get_topology_cpuset(hwloc_topology_t topology)
00723 {
00724   return hwloc_get_root_obj(topology)->cpuset;
00725 }
00726 
00736 static inline hwloc_const_cpuset_t 
00737 hwloc_topology_get_online_cpuset(hwloc_topology_t topology)
00738 {
00739   return hwloc_get_root_obj(topology)->online_cpuset;
00740 }
00741 
00751 static inline hwloc_const_cpuset_t 
00752 hwloc_topology_get_allowed_cpuset(hwloc_topology_t topology)
00753 {
00754   return hwloc_get_root_obj(topology)->allowed_cpuset;
00755 }
00756 
00773 static inline hwloc_const_nodeset_t 
00774 hwloc_topology_get_complete_nodeset(hwloc_topology_t topology)
00775 {
00776   return hwloc_get_root_obj(topology)->complete_nodeset;
00777 }
00778 
00789 static inline hwloc_const_nodeset_t 
00790 hwloc_topology_get_topology_nodeset(hwloc_topology_t topology)
00791 {
00792   return hwloc_get_root_obj(topology)->nodeset;
00793 }
00794 
00804 static inline hwloc_const_nodeset_t 
00805 hwloc_topology_get_allowed_nodeset(hwloc_topology_t topology)
00806 {
00807   return hwloc_get_root_obj(topology)->allowed_nodeset;
00808 }
00809 
00840 static inline void
00841 hwloc_cpuset_to_nodeset(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset)
00842 {
00843         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
00844         hwloc_obj_t obj;
00845 
00846         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) {
00847                  if (hwloc_bitmap_iszero(cpuset))
00848                         hwloc_bitmap_zero(nodeset);
00849                 else
00850                         /* Assume the whole system */
00851                         hwloc_bitmap_fill(nodeset);
00852                 return;
00853         }
00854 
00855         hwloc_bitmap_zero(nodeset);
00856         obj = NULL;
00857         while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL)
00858                 hwloc_bitmap_set(nodeset, obj->os_index);
00859 }
00860 
00868 static inline void
00869 hwloc_cpuset_to_nodeset_strict(struct hwloc_topology *topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset)
00870 {
00871         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
00872         hwloc_obj_t obj;
00873         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN )
00874                 return;
00875         hwloc_bitmap_zero(nodeset);
00876         obj = NULL;
00877         while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL)
00878                 hwloc_bitmap_set(nodeset, obj->os_index);
00879 }
00880 
00889 static inline void
00890 hwloc_cpuset_from_nodeset(hwloc_topology_t topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset)
00891 {
00892         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
00893         hwloc_obj_t obj;
00894 
00895         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) {
00896                 if (hwloc_bitmap_iszero(nodeset))
00897                         hwloc_bitmap_zero(cpuset);
00898                 else
00899                         /* Assume the whole system */
00900                         hwloc_bitmap_fill(cpuset);
00901                 return;
00902         }
00903 
00904         hwloc_bitmap_zero(cpuset);
00905         obj = NULL;
00906         while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL) {
00907                 if (hwloc_bitmap_isset(nodeset, obj->os_index))
00908                         /* no need to check obj->cpuset because objects in levels always have a cpuset */
00909                         hwloc_bitmap_or(cpuset, cpuset, obj->cpuset);
00910         }
00911 }
00912 
00920 static inline void
00921 hwloc_cpuset_from_nodeset_strict(struct hwloc_topology *topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset)
00922 {
00923         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
00924         hwloc_obj_t obj;
00925         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN )
00926                 return;
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 
00962 static inline const struct hwloc_distances_s *
00963 hwloc_get_whole_distance_matrix_by_depth(hwloc_topology_t topology, unsigned depth)
00964 {
00965   hwloc_obj_t root = hwloc_get_root_obj(topology);
00966   unsigned i;
00967   for(i=0; i<root->distances_count; i++)
00968     if (root->distances[i]->relative_depth == depth)
00969       return root->distances[i];
00970   return NULL;
00971 }
00972 
00992 static inline const struct hwloc_distances_s *
00993 hwloc_get_whole_distance_matrix_by_type(hwloc_topology_t topology, hwloc_obj_type_t type)
00994 {
00995   int depth = hwloc_get_type_depth(topology, type);
00996   if (depth < 0)
00997     return NULL;
00998   return hwloc_get_whole_distance_matrix_by_depth(topology, depth);
00999 }
01000 
01014 static inline const struct hwloc_distances_s *
01015 hwloc_get_distance_matrix_covering_obj_by_depth(hwloc_topology_t topology,
01016                                                 hwloc_obj_t obj, unsigned depth,
01017                                                 unsigned *firstp)
01018 {
01019   while (obj && obj->cpuset) {
01020     unsigned i;
01021     for(i=0; i<obj->distances_count; i++)
01022       if (obj->distances[i]->relative_depth == depth - obj->depth) {
01023         if (!obj->distances[i]->nbobjs)
01024           continue;
01025         *firstp = hwloc_get_next_obj_inside_cpuset_by_depth(topology, obj->cpuset, depth, NULL)->logical_index;
01026         return obj->distances[i];
01027       }
01028     obj = obj->parent;
01029   }
01030   return NULL;
01031 }
01032 
01044 static inline int
01045 hwloc_get_latency(hwloc_topology_t topology,
01046                    hwloc_obj_t obj1, hwloc_obj_t obj2,
01047                    float *latency, float *reverse_latency)
01048 {
01049   hwloc_obj_t ancestor;
01050   const struct hwloc_distances_s * distances;
01051   unsigned first_logical ;
01052 
01053   if (obj1->depth != obj2->depth) {
01054     errno = EINVAL;
01055     return -1;
01056   }
01057 
01058   ancestor = hwloc_get_common_ancestor_obj(topology, obj1, obj2);
01059   distances = hwloc_get_distance_matrix_covering_obj_by_depth(topology, ancestor, obj1->depth, &first_logical);
01060   if (distances && distances->latency) {
01061     const float * latency_matrix = distances->latency;
01062     unsigned nbobjs = distances->nbobjs;
01063     unsigned l1 = obj1->logical_index - first_logical;
01064     unsigned l2 = obj2->logical_index - first_logical;
01065     *latency = latency_matrix[l1*nbobjs+l2];
01066     *reverse_latency = latency_matrix[l2*nbobjs+l1];
01067     return 0;
01068   }
01069 
01070   errno = ENOSYS;
01071   return -1;
01072 }
01073 
01078 #ifdef __cplusplus
01079 } /* extern "C" */
01080 #endif
01081 
01082 
01083 #endif /* HWLOC_HELPER_H */