Hardware Locality (hwloc) 1.4

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List

helper.h

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