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 */