Open MPI logo

Portable Hardware Locality (hwloc) Documentation: v1.3

  |   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-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 
00044 static inline int 
00045 hwloc_get_type_or_below_depth (hwloc_topology_t topology, hwloc_obj_type_t type)
00046 {
00047   int depth = hwloc_get_type_depth(topology, type);
00048 
00049   if (depth != HWLOC_TYPE_DEPTH_UNKNOWN)
00050     return depth;
00051 
00052   /* find the highest existing level with type order >= */
00053   for(depth = hwloc_get_type_depth(topology, HWLOC_OBJ_PU); ; depth--)
00054     if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) < 0)
00055       return depth+1;
00056 
00057   /* Shouldn't ever happen, as there is always a SYSTEM level with lower order and known depth.  */
00058   /* abort(); */
00059 }
00060 
00067 static inline int 
00068 hwloc_get_type_or_above_depth (hwloc_topology_t topology, hwloc_obj_type_t type)
00069 {
00070   int depth = hwloc_get_type_depth(topology, type);
00071 
00072   if (depth != HWLOC_TYPE_DEPTH_UNKNOWN)
00073     return depth;
00074 
00075   /* find the lowest existing level with type order <= */
00076   for(depth = 0; ; depth++)
00077     if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) > 0)
00078       return depth-1;
00079 
00080   /* Shouldn't ever happen, as there is always a PU level with higher order and known depth.  */
00081   /* abort(); */
00082 }
00083 
00103 static inline hwloc_obj_t 
00104 hwloc_get_root_obj (hwloc_topology_t topology)
00105 {
00106   return hwloc_get_obj_by_depth (topology, 0, 0);
00107 }
00108 
00110 static inline hwloc_obj_t 
00111 hwloc_get_ancestor_obj_by_depth (hwloc_topology_t topology , unsigned depth, hwloc_obj_t obj)
00112 {
00113   hwloc_obj_t ancestor = obj;
00114   if (obj->depth < depth)
00115     return NULL;
00116   while (ancestor && ancestor->depth > depth)
00117     ancestor = ancestor->parent;
00118   return ancestor;
00119 }
00120 
00122 static inline hwloc_obj_t 
00123 hwloc_get_ancestor_obj_by_type (hwloc_topology_t topology , hwloc_obj_type_t type, hwloc_obj_t obj)
00124 {
00125   hwloc_obj_t ancestor = obj->parent;
00126   while (ancestor && ancestor->type != type)
00127     ancestor = ancestor->parent;
00128   return ancestor;
00129 }
00130 
00135 static inline hwloc_obj_t
00136 hwloc_get_next_obj_by_depth (hwloc_topology_t topology, unsigned depth, hwloc_obj_t prev)
00137 {
00138   if (!prev)
00139     return hwloc_get_obj_by_depth (topology, depth, 0);
00140   if (prev->depth != depth)
00141     return NULL;
00142   return prev->next_cousin;
00143 }
00144 
00151 static inline hwloc_obj_t
00152 hwloc_get_next_obj_by_type (hwloc_topology_t topology, hwloc_obj_type_t type,
00153                    hwloc_obj_t prev)
00154 {
00155   int depth = hwloc_get_type_depth(topology, type);
00156   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00157     return NULL;
00158   return hwloc_get_next_obj_by_depth (topology, depth, prev);
00159 }
00160 
00169 static inline hwloc_obj_t 
00170 hwloc_get_pu_obj_by_os_index(hwloc_topology_t topology, unsigned os_index)
00171 {
00172   hwloc_obj_t obj = NULL;
00173   while ((obj = hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_PU, obj)) != NULL)
00174     if (obj->os_index == os_index)
00175       return obj;
00176   return NULL;
00177 }
00178 
00183 static inline hwloc_obj_t
00184 hwloc_get_next_child (hwloc_topology_t topology , hwloc_obj_t parent, hwloc_obj_t prev)
00185 {
00186   if (!prev)
00187     return parent->first_child;
00188   if (prev->parent != parent)
00189     return NULL;
00190   return prev->next_sibling;
00191 }
00192 
00194 static inline hwloc_obj_t 
00195 hwloc_get_common_ancestor_obj (hwloc_topology_t topology , hwloc_obj_t obj1, hwloc_obj_t obj2)
00196 {
00197   /* the loop isn't so easy since intermediate ancestors may have
00198    * different depth, causing us to alternate between using obj1->parent
00199    * and obj2->parent. Also, even if at some point we find ancestors of
00200    * of the same depth, their ancestors may have different depth again.
00201    */
00202   while (obj1 != obj2) {
00203     while (obj1->depth > obj2->depth)
00204       obj1 = obj1->parent;
00205     while (obj2->depth > obj1->depth)
00206       obj2 = obj2->parent;
00207     if (obj1 != obj2 && obj1->depth == obj2->depth) {
00208       obj1 = obj1->parent;
00209       obj2 = obj2->parent;
00210     }
00211   }
00212   return obj1;
00213 }
00214 
00219 static inline int 
00220 hwloc_obj_is_in_subtree (hwloc_topology_t topology , hwloc_obj_t obj, hwloc_obj_t subtree_root)
00221 {
00222   return hwloc_bitmap_isincluded(obj->cpuset, subtree_root->cpuset);
00223 }
00224 
00241 static inline hwloc_obj_t
00242 hwloc_get_first_largest_obj_inside_cpuset(hwloc_topology_t topology, hwloc_const_cpuset_t set)
00243 {
00244   hwloc_obj_t obj = hwloc_get_root_obj(topology);
00245   /* FIXME: what if !root->cpuset? */
00246   if (!hwloc_bitmap_intersects(obj->cpuset, set))
00247     return NULL;
00248   while (!hwloc_bitmap_isincluded(obj->cpuset, set)) {
00249     /* while the object intersects without being included, look at its children */
00250     hwloc_obj_t child = NULL;
00251     while ((child = hwloc_get_next_child(topology, obj, child)) != NULL) {
00252       if (child->cpuset && hwloc_bitmap_intersects(child->cpuset, set))
00253         break;
00254     }
00255     if (!child)
00256       /* no child intersects, return their father */
00257       return obj;
00258     /* found one intersecting child, look at its children */
00259     obj = child;
00260   }
00261   /* obj is included, return it */
00262   return obj;
00263 }
00264 
00269  int hwloc_get_largest_objs_inside_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00270                                                  hwloc_obj_t * restrict objs, int max);
00271 
00278 static inline hwloc_obj_t
00279 hwloc_get_next_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00280                                            unsigned depth, hwloc_obj_t prev)
00281 {
00282   hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev);
00283   /* no need to check next->cpuset because objects in levels always have a cpuset */
00284   while (next && !hwloc_bitmap_isincluded(next->cpuset, set))
00285     next = next->next_cousin;
00286   return next;
00287 }
00288 
00295 static inline hwloc_obj_t
00296 hwloc_get_next_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00297                                           hwloc_obj_type_t type, hwloc_obj_t prev)
00298 {
00299   int depth = hwloc_get_type_depth(topology, type);
00300   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00301     return NULL;
00302   return hwloc_get_next_obj_inside_cpuset_by_depth(topology, set, depth, prev);
00303 }
00304 
00307 static inline hwloc_obj_t 
00308 hwloc_get_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00309                                       unsigned depth, unsigned idx)
00310 {
00311   unsigned count = 0;
00312   hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0);
00313   while (obj) {
00314     /* no need to check obj->cpuset because objects in levels always have a cpuset */
00315     if (hwloc_bitmap_isincluded(obj->cpuset, set)) {
00316       if (count == idx)
00317         return obj;
00318       count++;
00319     }
00320     obj = obj->next_cousin;
00321   }
00322   return NULL;
00323 }
00324 
00331 static inline hwloc_obj_t 
00332 hwloc_get_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00333                                      hwloc_obj_type_t type, unsigned idx)
00334 {
00335   int depth = hwloc_get_type_depth(topology, type);
00336   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00337     return NULL;
00338   return hwloc_get_obj_inside_cpuset_by_depth(topology, set, depth, idx);
00339 }
00340 
00342 static inline unsigned 
00343 hwloc_get_nbobjs_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00344                                          unsigned depth)
00345 {
00346   hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0);
00347   int count = 0;
00348   while (obj) {
00349     /* no need to check obj->cpuset because objects in levels always have a cpuset */
00350     if (hwloc_bitmap_isincluded(obj->cpuset, set))
00351       count++;
00352     obj = obj->next_cousin;
00353   }
00354   return count;
00355 }
00356 
00363 static inline int 
00364 hwloc_get_nbobjs_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00365                                         hwloc_obj_type_t type)
00366 {
00367   int depth = hwloc_get_type_depth(topology, type);
00368   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN)
00369     return 0;
00370   if (depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00371     return -1; /* FIXME: agregate nbobjs from different levels? */
00372   return hwloc_get_nbobjs_inside_cpuset_by_depth(topology, set, depth);
00373 }
00374 
00387 static inline hwloc_obj_t 
00388 hwloc_get_child_covering_cpuset (hwloc_topology_t topology , hwloc_const_cpuset_t set,
00389                                 hwloc_obj_t parent)
00390 {
00391   hwloc_obj_t child;
00392 
00393   if (hwloc_bitmap_iszero(set))
00394     return NULL;
00395 
00396   child = parent->first_child;
00397   while (child) {
00398     if (child->cpuset && hwloc_bitmap_isincluded(set, child->cpuset))
00399       return child;
00400     child = child->next_sibling;
00401   }
00402   return NULL;
00403 }
00404 
00409 static inline hwloc_obj_t 
00410 hwloc_get_obj_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set)
00411 {
00412   struct hwloc_obj *current = hwloc_get_root_obj(topology);
00413 
00414   if (hwloc_bitmap_iszero(set))
00415     return NULL;
00416 
00417   /* FIXME: what if !root->cpuset? */
00418   if (!hwloc_bitmap_isincluded(set, current->cpuset))
00419     return NULL;
00420 
00421   while (1) {
00422     hwloc_obj_t child = hwloc_get_child_covering_cpuset(topology, set, current);
00423     if (!child)
00424       return current;
00425     current = child;
00426   }
00427 }
00428 
00429 
00445 static inline hwloc_obj_t
00446 hwloc_get_next_obj_covering_cpuset_by_depth(hwloc_topology_t topology, hwloc_const_cpuset_t set,
00447                                             unsigned depth, hwloc_obj_t prev)
00448 {
00449   hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev);
00450   /* no need to check next->cpuset because objects in levels always have a cpuset */
00451   while (next && !hwloc_bitmap_intersects(set, next->cpuset))
00452     next = next->next_cousin;
00453   return next;
00454 }
00455 
00468 static inline hwloc_obj_t
00469 hwloc_get_next_obj_covering_cpuset_by_type(hwloc_topology_t topology, hwloc_const_cpuset_t set,
00470                                            hwloc_obj_type_t type, hwloc_obj_t prev)
00471 {
00472   int depth = hwloc_get_type_depth(topology, type);
00473   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00474     return NULL;
00475   return hwloc_get_next_obj_covering_cpuset_by_depth(topology, set, depth, prev);
00476 }
00477 
00490 static inline hwloc_obj_t 
00491 hwloc_get_cache_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set)
00492 {
00493   hwloc_obj_t current = hwloc_get_obj_covering_cpuset(topology, set);
00494   while (current) {
00495     if (current->type == HWLOC_OBJ_CACHE)
00496       return current;
00497     current = current->parent;
00498   }
00499   return NULL;
00500 }
00501 
00506 static inline hwloc_obj_t 
00507 hwloc_get_shared_cache_covering_obj (hwloc_topology_t topology , hwloc_obj_t obj)
00508 {
00509   hwloc_obj_t current = obj->parent;
00510   if (!obj->cpuset)
00511     return NULL;
00512   while (current && current->cpuset) {
00513     if (!hwloc_bitmap_isequal(current->cpuset, obj->cpuset)
00514         && current->type == HWLOC_OBJ_CACHE)
00515       return current;
00516     current = current->parent;
00517   }
00518   return NULL;
00519 }
00520 
00543 /* TODO: rather provide an iterator? Provide a way to know how much should be allocated? By returning the total number of objects instead? */
00544  unsigned hwloc_get_closest_objs (hwloc_topology_t topology, hwloc_obj_t src, hwloc_obj_t * restrict objs, unsigned max);
00545 
00556 static inline hwloc_obj_t 
00557 hwloc_get_obj_below_by_type (hwloc_topology_t topology,
00558                              hwloc_obj_type_t type1, unsigned idx1,
00559                              hwloc_obj_type_t type2, unsigned idx2)
00560 {
00561   hwloc_obj_t obj;
00562 
00563   obj = hwloc_get_obj_by_type (topology, type1, idx1);
00564   if (!obj)
00565     return NULL;
00566 
00567   return hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, type2, idx2);
00568 }
00569 
00585 static inline hwloc_obj_t 
00586 hwloc_get_obj_below_array_by_type (hwloc_topology_t topology, int nr, hwloc_obj_type_t *typev, unsigned *idxv)
00587 {
00588   hwloc_obj_t obj = hwloc_get_root_obj(topology);
00589   int i;
00590 
00591   /* FIXME: what if !root->cpuset? */
00592   for(i=0; i<nr; i++) {
00593     obj = hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, typev[i], idxv[i]);
00594     if (!obj)
00595       return NULL;
00596   }
00597 
00598   return obj;
00599 }
00600 
00622 static inline void
00623 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *root, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until);
00624 static inline void
00625 hwloc_distribute(hwloc_topology_t topology, hwloc_obj_t root, hwloc_cpuset_t *cpuset, unsigned n, unsigned until)
00626 {
00627   unsigned i;
00628 
00629   /* FIXME: what if !root->cpuset? */
00630   if (!root->arity || n == 1 || root->depth >= until) {
00631     /* Got to the bottom, we can't split any more, put everything there.  */
00632     for (i=0; i<n; i++)
00633       cpuset[i] = hwloc_bitmap_dup(root->cpuset);
00634     return;
00635   }
00636 
00637   hwloc_distributev(topology, root->children, root->arity, cpuset, n, until);
00638 }
00639 
00645 static inline void
00646 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *roots, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until)
00647 {
00648   unsigned i;
00649   unsigned tot_weight;
00650   hwloc_cpuset_t *cpusetp = cpuset;
00651 
00652   tot_weight = 0;
00653   for (i = 0; i < n_roots; i++)
00654     if (roots[i]->cpuset)
00655       tot_weight += hwloc_bitmap_weight(roots[i]->cpuset);
00656 
00657   for (i = 0; i < n_roots && tot_weight; i++) {
00658     /* Give to roots[i] a portion proportional to its weight */
00659     unsigned weight = roots[i]->cpuset ? hwloc_bitmap_weight(roots[i]->cpuset) : 0;
00660     unsigned chunk = (n * weight + tot_weight-1) / tot_weight;
00661     hwloc_distribute(topology, roots[i], cpusetp, chunk, until);
00662     cpusetp += chunk;
00663     tot_weight -= weight;
00664     n -= chunk;
00665   }
00666 }
00667 
00674 static inline void *
00675 hwloc_alloc_membind_policy_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
00676 {
00677   void *p = hwloc_alloc_membind_nodeset(topology, len, nodeset, policy, flags);
00678   if (p)
00679     return p;
00680   hwloc_set_membind_nodeset(topology, nodeset, policy, flags);
00681   p = hwloc_alloc(topology, len);
00682   if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH)
00683     /* Enforce the binding by touching the data */
00684     memset(p, 0, len);
00685   return p;
00686 }
00687 
00692 static inline void *
00693 hwloc_alloc_membind_policy(hwloc_topology_t topology, size_t len, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags)
00694 {
00695   void *p = hwloc_alloc_membind(topology, len, cpuset, policy, flags);
00696   if (p)
00697     return p;
00698   hwloc_set_membind(topology, cpuset, policy, flags);
00699   p = hwloc_alloc(topology, len);
00700   if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH)
00701     /* Enforce the binding by touching the data */
00702     memset(p, 0, len);
00703   return p;
00704 }
00705 
00722 static inline hwloc_const_cpuset_t 
00723 hwloc_topology_get_complete_cpuset(hwloc_topology_t topology)
00724 {
00725   return hwloc_get_root_obj(topology)->complete_cpuset;
00726 }
00727 
00738 static inline hwloc_const_cpuset_t 
00739 hwloc_topology_get_topology_cpuset(hwloc_topology_t topology)
00740 {
00741   return hwloc_get_root_obj(topology)->cpuset;
00742 }
00743 
00753 static inline hwloc_const_cpuset_t 
00754 hwloc_topology_get_online_cpuset(hwloc_topology_t topology)
00755 {
00756   return hwloc_get_root_obj(topology)->online_cpuset;
00757 }
00758 
00768 static inline hwloc_const_cpuset_t 
00769 hwloc_topology_get_allowed_cpuset(hwloc_topology_t topology)
00770 {
00771   return hwloc_get_root_obj(topology)->allowed_cpuset;
00772 }
00773 
00790 static inline hwloc_const_nodeset_t 
00791 hwloc_topology_get_complete_nodeset(hwloc_topology_t topology)
00792 {
00793   return hwloc_get_root_obj(topology)->complete_nodeset;
00794 }
00795 
00806 static inline hwloc_const_nodeset_t 
00807 hwloc_topology_get_topology_nodeset(hwloc_topology_t topology)
00808 {
00809   return hwloc_get_root_obj(topology)->nodeset;
00810 }
00811 
00821 static inline hwloc_const_nodeset_t 
00822 hwloc_topology_get_allowed_nodeset(hwloc_topology_t topology)
00823 {
00824   return hwloc_get_root_obj(topology)->allowed_nodeset;
00825 }
00826 
00857 static inline void
00858 hwloc_cpuset_to_nodeset(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset)
00859 {
00860         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
00861         hwloc_obj_t obj;
00862 
00863         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) {
00864                  if (hwloc_bitmap_iszero(cpuset))
00865                         hwloc_bitmap_zero(nodeset);
00866                 else
00867                         /* Assume the whole system */
00868                         hwloc_bitmap_fill(nodeset);
00869                 return;
00870         }
00871 
00872         hwloc_bitmap_zero(nodeset);
00873         obj = NULL;
00874         while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL)
00875                 hwloc_bitmap_set(nodeset, obj->os_index);
00876 }
00877 
00885 static inline void
00886 hwloc_cpuset_to_nodeset_strict(struct hwloc_topology *topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset)
00887 {
00888         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
00889         hwloc_obj_t obj;
00890         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN )
00891                 return;
00892         hwloc_bitmap_zero(nodeset);
00893         obj = NULL;
00894         while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL)
00895                 hwloc_bitmap_set(nodeset, obj->os_index);
00896 }
00897 
00906 static inline void
00907 hwloc_cpuset_from_nodeset(hwloc_topology_t topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset)
00908 {
00909         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
00910         hwloc_obj_t obj;
00911 
00912         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) {
00913                 if (hwloc_bitmap_iszero(nodeset))
00914                         hwloc_bitmap_zero(cpuset);
00915                 else
00916                         /* Assume the whole system */
00917                         hwloc_bitmap_fill(cpuset);
00918                 return;
00919         }
00920 
00921         hwloc_bitmap_zero(cpuset);
00922         obj = NULL;
00923         while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL) {
00924                 if (hwloc_bitmap_isset(nodeset, obj->os_index))
00925                         /* no need to check obj->cpuset because objects in levels always have a cpuset */
00926                         hwloc_bitmap_or(cpuset, cpuset, obj->cpuset);
00927         }
00928 }
00929 
00937 static inline void
00938 hwloc_cpuset_from_nodeset_strict(struct hwloc_topology *topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset)
00939 {
00940         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
00941         hwloc_obj_t obj;
00942         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN )
00943                 return;
00944         hwloc_bitmap_zero(cpuset);
00945         obj = NULL;
00946         while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL)
00947                 if (hwloc_bitmap_isset(nodeset, obj->os_index))
00948                         /* no need to check obj->cpuset because objects in levels always have a cpuset */
00949                         hwloc_bitmap_or(cpuset, cpuset, obj->cpuset);
00950 }
00951 
00979 static inline const struct hwloc_distances_s *
00980 hwloc_get_whole_distance_matrix_by_depth(hwloc_topology_t topology, unsigned depth)
00981 {
00982   hwloc_obj_t root = hwloc_get_root_obj(topology);
00983   unsigned i;
00984   for(i=0; i<root->distances_count; i++)
00985     if (root->distances[i]->relative_depth == depth)
00986       return root->distances[i];
00987   return NULL;
00988 }
00989 
01009 static inline const struct hwloc_distances_s *
01010 hwloc_get_whole_distance_matrix_by_type(hwloc_topology_t topology, hwloc_obj_type_t type)
01011 {
01012   int depth = hwloc_get_type_depth(topology, type);
01013   if (depth < 0)
01014     return NULL;
01015   return hwloc_get_whole_distance_matrix_by_depth(topology, depth);
01016 }
01017 
01031 static inline const struct hwloc_distances_s *
01032 hwloc_get_distance_matrix_covering_obj_by_depth(hwloc_topology_t topology,
01033                                                 hwloc_obj_t obj, unsigned depth,
01034                                                 unsigned *firstp)
01035 {
01036   while (obj && obj->cpuset) {
01037     unsigned i;
01038     for(i=0; i<obj->distances_count; i++)
01039       if (obj->distances[i]->relative_depth == depth - obj->depth) {
01040         if (!obj->distances[i]->nbobjs)
01041           continue;
01042         *firstp = hwloc_get_next_obj_inside_cpuset_by_depth(topology, obj->cpuset, depth, NULL)->logical_index;
01043         return obj->distances[i];
01044       }
01045     obj = obj->parent;
01046   }
01047   return NULL;
01048 }
01049 
01061 static inline int
01062 hwloc_get_latency(hwloc_topology_t topology,
01063                    hwloc_obj_t obj1, hwloc_obj_t obj2,
01064                    float *latency, float *reverse_latency)
01065 {
01066   hwloc_obj_t ancestor;
01067   const struct hwloc_distances_s * distances;
01068   unsigned first_logical ;
01069 
01070   if (obj1->depth != obj2->depth) {
01071     errno = EINVAL;
01072     return -1;
01073   }
01074 
01075   ancestor = hwloc_get_common_ancestor_obj(topology, obj1, obj2);
01076   distances = hwloc_get_distance_matrix_covering_obj_by_depth(topology, ancestor, obj1->depth, &first_logical);
01077   if (distances && distances->latency) {
01078     const float * latency_matrix = distances->latency;
01079     unsigned nbobjs = distances->nbobjs;
01080     unsigned l1 = obj1->logical_index - first_logical;
01081     unsigned l2 = obj2->logical_index - first_logical;
01082     *latency = latency_matrix[l1*nbobjs+l2];
01083     *reverse_latency = latency_matrix[l2*nbobjs+l1];
01084     return 0;
01085   }
01086 
01087   errno = ENOSYS;
01088   return -1;
01089 }
01090 
01105 static inline hwloc_obj_t
01106 hwloc_get_non_io_ancestor_obj(hwloc_topology_t topology ,
01107                               hwloc_obj_t ioobj)
01108 {
01109   hwloc_obj_t obj = ioobj;
01110   while (obj && !obj->cpuset) {
01111     obj = obj->parent;
01112   }
01113   return obj;
01114 }
01115 
01120 static inline hwloc_obj_t
01121 hwloc_get_next_pcidev(hwloc_topology_t topology, hwloc_obj_t prev)
01122 {
01123   return hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_PCI_DEVICE, prev);
01124 }
01125 
01129 static inline hwloc_obj_t
01130 hwloc_get_pcidev_by_busid(hwloc_topology_t topology,
01131                           unsigned domain, unsigned bus, unsigned dev, unsigned func)
01132 {
01133   hwloc_obj_t obj = NULL;
01134   while ((obj = hwloc_get_next_pcidev(topology, obj)) != NULL) {
01135     if (obj->attr->pcidev.domain == domain
01136         && obj->attr->pcidev.bus == bus
01137         && obj->attr->pcidev.dev == dev
01138         && obj->attr->pcidev.func == func)
01139       return obj;
01140   }
01141   return NULL;
01142 }
01143 
01147 static inline hwloc_obj_t
01148 hwloc_get_pcidev_by_busidstring(hwloc_topology_t topology, const char *busid)
01149 {
01150   unsigned domain = 0; /* default */
01151   unsigned bus, dev, func;
01152 
01153   if (sscanf(busid, "%x:%x.%x", &bus, &dev, &func) != 3
01154       && sscanf(busid, "%x:%x:%x.%x", &domain, &bus, &dev, &func) != 4) {
01155     errno = EINVAL;
01156     return NULL;
01157   }
01158 
01159   return hwloc_get_pcidev_by_busid(topology, domain, bus, dev, func);
01160 }
01161 
01166 static inline hwloc_obj_t
01167 hwloc_get_next_osdev(hwloc_topology_t topology, hwloc_obj_t prev)
01168 {
01169   return hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_OS_DEVICE, prev);
01170 }
01171 
01176 static inline hwloc_obj_t
01177 hwloc_get_next_bridge(hwloc_topology_t topology, hwloc_obj_t prev)
01178 {
01179   return hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_BRIDGE, prev);
01180 }
01181 
01182 /* \brief Checks whether a given bridge covers a given PCI bus.
01183  */
01184 static inline int
01185 hwloc_bridge_covers_pcibus(hwloc_obj_t bridge,
01186                            unsigned domain, unsigned bus)
01187 {
01188   return bridge->type == HWLOC_OBJ_BRIDGE
01189     && bridge->attr->bridge.downstream_type == HWLOC_OBJ_BRIDGE_PCI
01190     && bridge->attr->bridge.downstream.pci.domain == domain
01191     && bridge->attr->bridge.downstream.pci.secondary_bus <= bus
01192     && bridge->attr->bridge.downstream.pci.subordinate_bus >= bus;
01193 }
01194 
01200 static inline hwloc_obj_t
01201 hwloc_get_hostbridge_by_pcibus(hwloc_topology_t topology,
01202                                unsigned domain, unsigned bus)
01203 {
01204   hwloc_obj_t obj = NULL;
01205   while ((obj = hwloc_get_next_bridge(topology, obj)) != NULL) {
01206     if (hwloc_bridge_covers_pcibus(obj, domain, bus)) {
01207       /* found bridge covering this pcibus, make sure it's a hostbridge */
01208       assert(obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_HOST);
01209       assert(obj->parent->type != HWLOC_OBJ_BRIDGE);
01210       assert(obj->parent->cpuset);
01211       return obj;
01212     }
01213   }
01214   return NULL;
01215 }
01216 
01221 #ifdef __cplusplus
01222 } /* extern "C" */
01223 #endif
01224 
01225 
01226 #endif /* HWLOC_HELPER_H */