Open MPI logo

Portable Hardware Locality (hwloc) Documentation: v1.4.2

  |   Home   |   Support   |   FAQ   |  
helper.h
00001 /*
00002  * Copyright © 2009 CNRS
00003  * Copyright © 2009-2011 inria.  All rights reserved.
00004  * Copyright © 2009-2012 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 static inline int
00050 hwloc_get_type_or_below_depth (hwloc_topology_t topology, hwloc_obj_type_t type)
00051 {
00052   int depth = hwloc_get_type_depth(topology, type);
00053 
00054   if (depth != HWLOC_TYPE_DEPTH_UNKNOWN)
00055     return depth;
00056 
00057   /* find the highest existing level with type order >= */
00058   for(depth = hwloc_get_type_depth(topology, HWLOC_OBJ_PU); ; depth--)
00059     if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) < 0)
00060       return depth+1;
00061 
00062   /* Shouldn't ever happen, as there is always a SYSTEM level with lower order and known depth.  */
00063   /* abort(); */
00064 }
00065 
00075 static inline int
00076 hwloc_get_type_or_above_depth (hwloc_topology_t topology, hwloc_obj_type_t type) ;
00077 static inline int
00078 hwloc_get_type_or_above_depth (hwloc_topology_t topology, hwloc_obj_type_t type)
00079 {
00080   int depth = hwloc_get_type_depth(topology, type);
00081 
00082   if (depth != HWLOC_TYPE_DEPTH_UNKNOWN)
00083     return depth;
00084 
00085   /* find the lowest existing level with type order <= */
00086   for(depth = 0; ; depth++)
00087     if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) > 0)
00088       return depth-1;
00089 
00090   /* Shouldn't ever happen, as there is always a PU level with higher order and known depth.  */
00091   /* abort(); */
00092 }
00093 
00113 static inline hwloc_obj_t
00114 hwloc_get_root_obj (hwloc_topology_t topology) ;
00115 static inline hwloc_obj_t
00116 hwloc_get_root_obj (hwloc_topology_t topology)
00117 {
00118   return hwloc_get_obj_by_depth (topology, 0, 0);
00119 }
00120 
00122 static inline hwloc_obj_t
00123 hwloc_get_ancestor_obj_by_depth (hwloc_topology_t topology , unsigned depth, hwloc_obj_t obj) ;
00124 static inline hwloc_obj_t
00125 hwloc_get_ancestor_obj_by_depth (hwloc_topology_t topology , unsigned depth, hwloc_obj_t obj)
00126 {
00127   hwloc_obj_t ancestor = obj;
00128   if (obj->depth < depth)
00129     return NULL;
00130   while (ancestor && ancestor->depth > depth)
00131     ancestor = ancestor->parent;
00132   return ancestor;
00133 }
00134 
00136 static inline hwloc_obj_t
00137 hwloc_get_ancestor_obj_by_type (hwloc_topology_t topology , hwloc_obj_type_t type, hwloc_obj_t obj) ;
00138 static inline hwloc_obj_t
00139 hwloc_get_ancestor_obj_by_type (hwloc_topology_t topology , hwloc_obj_type_t type, hwloc_obj_t obj)
00140 {
00141   hwloc_obj_t ancestor = obj->parent;
00142   while (ancestor && ancestor->type != type)
00143     ancestor = ancestor->parent;
00144   return ancestor;
00145 }
00146 
00151 static inline hwloc_obj_t
00152 hwloc_get_next_obj_by_depth (hwloc_topology_t topology, unsigned depth, hwloc_obj_t prev)
00153 {
00154   if (!prev)
00155     return hwloc_get_obj_by_depth (topology, depth, 0);
00156   if (prev->depth != depth)
00157     return NULL;
00158   return prev->next_cousin;
00159 }
00160 
00167 static inline hwloc_obj_t
00168 hwloc_get_next_obj_by_type (hwloc_topology_t topology, hwloc_obj_type_t type,
00169                    hwloc_obj_t prev)
00170 {
00171   int depth = hwloc_get_type_depth(topology, type);
00172   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00173     return NULL;
00174   return hwloc_get_next_obj_by_depth (topology, depth, prev);
00175 }
00176 
00185 static inline hwloc_obj_t
00186 hwloc_get_pu_obj_by_os_index(hwloc_topology_t topology, unsigned os_index) ;
00187 static inline hwloc_obj_t
00188 hwloc_get_pu_obj_by_os_index(hwloc_topology_t topology, unsigned os_index)
00189 {
00190   hwloc_obj_t obj = NULL;
00191   while ((obj = hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_PU, obj)) != NULL)
00192     if (obj->os_index == os_index)
00193       return obj;
00194   return NULL;
00195 }
00196 
00201 static inline hwloc_obj_t
00202 hwloc_get_next_child (hwloc_topology_t topology , hwloc_obj_t parent, hwloc_obj_t prev)
00203 {
00204   if (!prev)
00205     return parent->first_child;
00206   if (prev->parent != parent)
00207     return NULL;
00208   return prev->next_sibling;
00209 }
00210 
00212 static inline hwloc_obj_t
00213 hwloc_get_common_ancestor_obj (hwloc_topology_t topology , hwloc_obj_t obj1, hwloc_obj_t obj2) ;
00214 static inline hwloc_obj_t
00215 hwloc_get_common_ancestor_obj (hwloc_topology_t topology , hwloc_obj_t obj1, hwloc_obj_t obj2)
00216 {
00217   /* the loop isn't so easy since intermediate ancestors may have
00218    * different depth, causing us to alternate between using obj1->parent
00219    * and obj2->parent. Also, even if at some point we find ancestors of
00220    * of the same depth, their ancestors may have different depth again.
00221    */
00222   while (obj1 != obj2) {
00223     while (obj1->depth > obj2->depth)
00224       obj1 = obj1->parent;
00225     while (obj2->depth > obj1->depth)
00226       obj2 = obj2->parent;
00227     if (obj1 != obj2 && obj1->depth == obj2->depth) {
00228       obj1 = obj1->parent;
00229       obj2 = obj2->parent;
00230     }
00231   }
00232   return obj1;
00233 }
00234 
00239 static inline int
00240 hwloc_obj_is_in_subtree (hwloc_topology_t topology , hwloc_obj_t obj, hwloc_obj_t subtree_root) ;
00241 static inline int
00242 hwloc_obj_is_in_subtree (hwloc_topology_t topology , hwloc_obj_t obj, hwloc_obj_t subtree_root)
00243 {
00244   return hwloc_bitmap_isincluded(obj->cpuset, subtree_root->cpuset);
00245 }
00246 
00266 static inline hwloc_obj_t
00267 hwloc_get_first_largest_obj_inside_cpuset(hwloc_topology_t topology, hwloc_const_cpuset_t set)
00268 {
00269   hwloc_obj_t obj = hwloc_get_root_obj(topology);
00270   if (!obj->cpuset || !hwloc_bitmap_intersects(obj->cpuset, set))
00271     return NULL;
00272   while (!hwloc_bitmap_isincluded(obj->cpuset, set)) {
00273     /* while the object intersects without being included, look at its children */
00274     hwloc_obj_t child = NULL;
00275     while ((child = hwloc_get_next_child(topology, obj, child)) != NULL) {
00276       if (child->cpuset && hwloc_bitmap_intersects(child->cpuset, set))
00277         break;
00278     }
00279     if (!child)
00280       /* no child intersects, return their father */
00281       return obj;
00282     /* found one intersecting child, look at its children */
00283     obj = child;
00284   }
00285   /* obj is included, return it */
00286   return obj;
00287 }
00288 
00296  int hwloc_get_largest_objs_inside_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00297                                                  hwloc_obj_t * restrict objs, int max);
00298 
00308 static inline hwloc_obj_t
00309 hwloc_get_next_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00310                                            unsigned depth, hwloc_obj_t prev)
00311 {
00312   hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev);
00313   if (!next || !next->cpuset)
00314     return NULL;
00315   while (next && !hwloc_bitmap_isincluded(next->cpuset, set))
00316     next = next->next_cousin;
00317   return next;
00318 }
00319 
00329 static inline hwloc_obj_t
00330 hwloc_get_next_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00331                                           hwloc_obj_type_t type, hwloc_obj_t prev)
00332 {
00333   int depth = hwloc_get_type_depth(topology, type);
00334   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00335     return NULL;
00336   return hwloc_get_next_obj_inside_cpuset_by_depth(topology, set, depth, prev);
00337 }
00338 
00344 static inline hwloc_obj_t
00345 hwloc_get_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00346                                       unsigned depth, unsigned idx) ;
00347 static inline hwloc_obj_t
00348 hwloc_get_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00349                                       unsigned depth, unsigned idx)
00350 {
00351   hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0);
00352   unsigned count = 0;
00353   if (!obj || !obj->cpuset)
00354     return NULL;
00355   while (obj) {
00356     if (hwloc_bitmap_isincluded(obj->cpuset, set)) {
00357       if (count == idx)
00358         return obj;
00359       count++;
00360     }
00361     obj = obj->next_cousin;
00362   }
00363   return NULL;
00364 }
00365 
00375 static inline hwloc_obj_t
00376 hwloc_get_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00377                                      hwloc_obj_type_t type, unsigned idx) ;
00378 static inline hwloc_obj_t
00379 hwloc_get_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00380                                      hwloc_obj_type_t type, unsigned idx)
00381 {
00382   int depth = hwloc_get_type_depth(topology, type);
00383   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00384     return NULL;
00385   return hwloc_get_obj_inside_cpuset_by_depth(topology, set, depth, idx);
00386 }
00387 
00393 static inline unsigned
00394 hwloc_get_nbobjs_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00395                                          unsigned depth) ;
00396 static inline unsigned
00397 hwloc_get_nbobjs_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00398                                          unsigned depth)
00399 {
00400   hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0);
00401   unsigned count = 0;
00402   if (!obj || !obj->cpuset)
00403     return 0;
00404   while (obj) {
00405     if (hwloc_bitmap_isincluded(obj->cpuset, set))
00406       count++;
00407     obj = obj->next_cousin;
00408   }
00409   return count;
00410 }
00411 
00421 static inline int
00422 hwloc_get_nbobjs_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00423                                         hwloc_obj_type_t type) ;
00424 static inline int
00425 hwloc_get_nbobjs_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00426                                         hwloc_obj_type_t type)
00427 {
00428   int depth = hwloc_get_type_depth(topology, type);
00429   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN)
00430     return 0;
00431   if (depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00432     return -1; /* FIXME: agregate nbobjs from different levels? */
00433   return hwloc_get_nbobjs_inside_cpuset_by_depth(topology, set, depth);
00434 }
00435 
00444 static inline int
00445 hwloc_get_obj_index_inside_cpuset (hwloc_topology_t topology , hwloc_const_cpuset_t set,
00446                                    hwloc_obj_t obj) ;
00447 static inline int
00448 hwloc_get_obj_index_inside_cpuset (hwloc_topology_t topology , hwloc_const_cpuset_t set,
00449                                    hwloc_obj_t obj)
00450 {
00451   int idx = 0;
00452   if (!hwloc_bitmap_isincluded(obj->cpuset, set))
00453     return -1;
00454   /* count how many objects are inside the cpuset on the way from us to the beginning of the level */
00455   while ((obj = obj->prev_cousin) != NULL)
00456     if (hwloc_bitmap_isincluded(obj->cpuset, set))
00457       idx++;
00458   return idx;
00459 }
00460 
00475 static inline hwloc_obj_t
00476 hwloc_get_child_covering_cpuset (hwloc_topology_t topology , hwloc_const_cpuset_t set,
00477                                 hwloc_obj_t parent) ;
00478 static inline hwloc_obj_t
00479 hwloc_get_child_covering_cpuset (hwloc_topology_t topology , hwloc_const_cpuset_t set,
00480                                 hwloc_obj_t parent)
00481 {
00482   hwloc_obj_t child;
00483   if (!parent->cpuset || hwloc_bitmap_iszero(set))
00484     return NULL;
00485   child = parent->first_child;
00486   while (child) {
00487     if (child->cpuset && hwloc_bitmap_isincluded(set, child->cpuset))
00488       return child;
00489     child = child->next_sibling;
00490   }
00491   return NULL;
00492 }
00493 
00501 static inline hwloc_obj_t
00502 hwloc_get_obj_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set) ;
00503 static inline hwloc_obj_t
00504 hwloc_get_obj_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set)
00505 {
00506   struct hwloc_obj *current = hwloc_get_root_obj(topology);
00507   if (hwloc_bitmap_iszero(set) || !current->cpuset || !hwloc_bitmap_isincluded(set, current->cpuset))
00508     return NULL;
00509   while (1) {
00510     hwloc_obj_t child = hwloc_get_child_covering_cpuset(topology, set, current);
00511     if (!child)
00512       return current;
00513     current = child;
00514   }
00515 }
00516 
00517 
00536 static inline hwloc_obj_t
00537 hwloc_get_next_obj_covering_cpuset_by_depth(hwloc_topology_t topology, hwloc_const_cpuset_t set,
00538                                             unsigned depth, hwloc_obj_t prev)
00539 {
00540   hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev);
00541   if (!next || !next->cpuset)
00542     return NULL;
00543   while (next && !hwloc_bitmap_intersects(set, next->cpuset))
00544     next = next->next_cousin;
00545   return next;
00546 }
00547 
00563 static inline hwloc_obj_t
00564 hwloc_get_next_obj_covering_cpuset_by_type(hwloc_topology_t topology, hwloc_const_cpuset_t set,
00565                                            hwloc_obj_type_t type, hwloc_obj_t prev)
00566 {
00567   int depth = hwloc_get_type_depth(topology, type);
00568   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00569     return NULL;
00570   return hwloc_get_next_obj_covering_cpuset_by_depth(topology, set, depth, prev);
00571 }
00572 
00588 static inline hwloc_obj_t
00589 hwloc_get_cache_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set) ;
00590 static inline hwloc_obj_t
00591 hwloc_get_cache_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set)
00592 {
00593   hwloc_obj_t current = hwloc_get_obj_covering_cpuset(topology, set);
00594   while (current) {
00595     if (current->type == HWLOC_OBJ_CACHE)
00596       return current;
00597     current = current->parent;
00598   }
00599   return NULL;
00600 }
00601 
00606 static inline hwloc_obj_t
00607 hwloc_get_shared_cache_covering_obj (hwloc_topology_t topology , hwloc_obj_t obj) ;
00608 static inline hwloc_obj_t
00609 hwloc_get_shared_cache_covering_obj (hwloc_topology_t topology , hwloc_obj_t obj)
00610 {
00611   hwloc_obj_t current = obj->parent;
00612   if (!obj->cpuset)
00613     return NULL;
00614   while (current && current->cpuset) {
00615     if (!hwloc_bitmap_isequal(current->cpuset, obj->cpuset)
00616         && current->type == HWLOC_OBJ_CACHE)
00617       return current;
00618     current = current->parent;
00619   }
00620   return NULL;
00621 }
00622 
00647 /* TODO: rather provide an iterator? Provide a way to know how much should be allocated? By returning the total number of objects instead? */
00648  unsigned hwloc_get_closest_objs (hwloc_topology_t topology, hwloc_obj_t src, hwloc_obj_t * restrict objs, unsigned max);
00649 
00662 static inline hwloc_obj_t
00663 hwloc_get_obj_below_by_type (hwloc_topology_t topology,
00664                              hwloc_obj_type_t type1, unsigned idx1,
00665                              hwloc_obj_type_t type2, unsigned idx2) ;
00666 static inline hwloc_obj_t
00667 hwloc_get_obj_below_by_type (hwloc_topology_t topology,
00668                              hwloc_obj_type_t type1, unsigned idx1,
00669                              hwloc_obj_type_t type2, unsigned idx2)
00670 {
00671   hwloc_obj_t obj;
00672   obj = hwloc_get_obj_by_type (topology, type1, idx1);
00673   if (!obj || !obj->cpuset)
00674     return NULL;
00675   return hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, type2, idx2);
00676 }
00677 
00696 static inline hwloc_obj_t
00697 hwloc_get_obj_below_array_by_type (hwloc_topology_t topology, int nr, hwloc_obj_type_t *typev, unsigned *idxv) ;
00698 static inline hwloc_obj_t
00699 hwloc_get_obj_below_array_by_type (hwloc_topology_t topology, int nr, hwloc_obj_type_t *typev, unsigned *idxv)
00700 {
00701   hwloc_obj_t obj = hwloc_get_root_obj(topology);
00702   int i;
00703   for(i=0; i<nr; i++) {
00704     if (!obj || !obj->cpuset)
00705       return NULL;
00706     obj = hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, typev[i], idxv[i]);
00707   }
00708   return obj;
00709 }
00710 
00734 static inline void
00735 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *root, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until);
00736 static inline void
00737 hwloc_distribute(hwloc_topology_t topology, hwloc_obj_t root, hwloc_cpuset_t *cpuset, unsigned n, unsigned until)
00738 {
00739   unsigned i;
00740   if (!root->arity || n == 1 || root->depth >= until) {
00741     /* Got to the bottom, we can't split any more, put everything there.  */
00742     for (i=0; i<n; i++)
00743       cpuset[i] = hwloc_bitmap_dup(root->cpuset);
00744     return;
00745   }
00746   hwloc_distributev(topology, root->children, root->arity, cpuset, n, until);
00747 }
00748 
00756 static inline void
00757 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *roots, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until)
00758 {
00759   unsigned i;
00760   unsigned tot_weight;
00761   hwloc_cpuset_t *cpusetp = cpuset;
00762 
00763   tot_weight = 0;
00764   for (i = 0; i < n_roots; i++)
00765     if (roots[i]->cpuset)
00766       tot_weight += hwloc_bitmap_weight(roots[i]->cpuset);
00767 
00768   for (i = 0; i < n_roots && tot_weight; i++) {
00769     /* Give to roots[i] a portion proportional to its weight */
00770     unsigned weight = roots[i]->cpuset ? hwloc_bitmap_weight(roots[i]->cpuset) : 0;
00771     unsigned chunk = (n * weight + tot_weight-1) / tot_weight;
00772     hwloc_distribute(topology, roots[i], cpusetp, chunk, until);
00773     cpusetp += chunk;
00774     tot_weight -= weight;
00775     n -= chunk;
00776   }
00777 }
00778 
00785 static inline void *
00786 hwloc_alloc_membind_policy_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
00787 {
00788   void *p = hwloc_alloc_membind_nodeset(topology, len, nodeset, policy, flags);
00789   if (p)
00790     return p;
00791   hwloc_set_membind_nodeset(topology, nodeset, policy, flags);
00792   p = hwloc_alloc(topology, len);
00793   if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH)
00794     /* Enforce the binding by touching the data */
00795     memset(p, 0, len);
00796   return p;
00797 }
00798 
00803 static inline void *
00804 hwloc_alloc_membind_policy(hwloc_topology_t topology, size_t len, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags)
00805 {
00806   void *p = hwloc_alloc_membind(topology, len, cpuset, policy, flags);
00807   if (p)
00808     return p;
00809   hwloc_set_membind(topology, cpuset, policy, flags);
00810   p = hwloc_alloc(topology, len);
00811   if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH)
00812     /* Enforce the binding by touching the data */
00813     memset(p, 0, len);
00814   return p;
00815 }
00816 
00833 static inline hwloc_const_cpuset_t
00834 hwloc_topology_get_complete_cpuset(hwloc_topology_t topology) ;
00835 static inline hwloc_const_cpuset_t
00836 hwloc_topology_get_complete_cpuset(hwloc_topology_t topology)
00837 {
00838   return hwloc_get_root_obj(topology)->complete_cpuset;
00839 }
00840 
00851 static inline hwloc_const_cpuset_t
00852 hwloc_topology_get_topology_cpuset(hwloc_topology_t topology) ;
00853 static inline hwloc_const_cpuset_t
00854 hwloc_topology_get_topology_cpuset(hwloc_topology_t topology)
00855 {
00856   return hwloc_get_root_obj(topology)->cpuset;
00857 }
00858 
00868 static inline hwloc_const_cpuset_t
00869 hwloc_topology_get_online_cpuset(hwloc_topology_t topology) ;
00870 static inline hwloc_const_cpuset_t
00871 hwloc_topology_get_online_cpuset(hwloc_topology_t topology)
00872 {
00873   return hwloc_get_root_obj(topology)->online_cpuset;
00874 }
00875 
00885 static inline hwloc_const_cpuset_t
00886 hwloc_topology_get_allowed_cpuset(hwloc_topology_t topology) ;
00887 static inline hwloc_const_cpuset_t
00888 hwloc_topology_get_allowed_cpuset(hwloc_topology_t topology)
00889 {
00890   return hwloc_get_root_obj(topology)->allowed_cpuset;
00891 }
00892 
00909 static inline hwloc_const_nodeset_t
00910 hwloc_topology_get_complete_nodeset(hwloc_topology_t topology) ;
00911 static inline hwloc_const_nodeset_t
00912 hwloc_topology_get_complete_nodeset(hwloc_topology_t topology)
00913 {
00914   return hwloc_get_root_obj(topology)->complete_nodeset;
00915 }
00916 
00927 static inline hwloc_const_nodeset_t
00928 hwloc_topology_get_topology_nodeset(hwloc_topology_t topology) ;
00929 static inline hwloc_const_nodeset_t
00930 hwloc_topology_get_topology_nodeset(hwloc_topology_t topology)
00931 {
00932   return hwloc_get_root_obj(topology)->nodeset;
00933 }
00934 
00944 static inline hwloc_const_nodeset_t
00945 hwloc_topology_get_allowed_nodeset(hwloc_topology_t topology) ;
00946 static inline hwloc_const_nodeset_t
00947 hwloc_topology_get_allowed_nodeset(hwloc_topology_t topology)
00948 {
00949   return hwloc_get_root_obj(topology)->allowed_nodeset;
00950 }
00951 
00982 static inline void
00983 hwloc_cpuset_to_nodeset(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset)
00984 {
00985         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
00986         hwloc_obj_t obj;
00987 
00988         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) {
00989                  if (hwloc_bitmap_iszero(cpuset))
00990                         hwloc_bitmap_zero(nodeset);
00991                 else
00992                         /* Assume the whole system */
00993                         hwloc_bitmap_fill(nodeset);
00994                 return;
00995         }
00996 
00997         hwloc_bitmap_zero(nodeset);
00998         obj = NULL;
00999         while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL)
01000                 hwloc_bitmap_set(nodeset, obj->os_index);
01001 }
01002 
01010 static inline void
01011 hwloc_cpuset_to_nodeset_strict(struct hwloc_topology *topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset)
01012 {
01013         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
01014         hwloc_obj_t obj;
01015         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN )
01016                 return;
01017         hwloc_bitmap_zero(nodeset);
01018         obj = NULL;
01019         while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL)
01020                 hwloc_bitmap_set(nodeset, obj->os_index);
01021 }
01022 
01031 static inline void
01032 hwloc_cpuset_from_nodeset(hwloc_topology_t topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset)
01033 {
01034         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
01035         hwloc_obj_t obj;
01036 
01037         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) {
01038                 if (hwloc_bitmap_iszero(nodeset))
01039                         hwloc_bitmap_zero(cpuset);
01040                 else
01041                         /* Assume the whole system */
01042                         hwloc_bitmap_fill(cpuset);
01043                 return;
01044         }
01045 
01046         hwloc_bitmap_zero(cpuset);
01047         obj = NULL;
01048         while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL) {
01049                 if (hwloc_bitmap_isset(nodeset, obj->os_index))
01050                         /* no need to check obj->cpuset because objects in levels always have a cpuset */
01051                         hwloc_bitmap_or(cpuset, cpuset, obj->cpuset);
01052         }
01053 }
01054 
01062 static inline void
01063 hwloc_cpuset_from_nodeset_strict(struct hwloc_topology *topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset)
01064 {
01065         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
01066         hwloc_obj_t obj;
01067         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN )
01068                 return;
01069         hwloc_bitmap_zero(cpuset);
01070         obj = NULL;
01071         while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL)
01072                 if (hwloc_bitmap_isset(nodeset, obj->os_index))
01073                         /* no need to check obj->cpuset because objects in levels always have a cpuset */
01074                         hwloc_bitmap_or(cpuset, cpuset, obj->cpuset);
01075 }
01076 
01104 static inline const struct hwloc_distances_s *
01105 hwloc_get_whole_distance_matrix_by_depth(hwloc_topology_t topology, unsigned depth)
01106 {
01107   hwloc_obj_t root = hwloc_get_root_obj(topology);
01108   unsigned i;
01109   for(i=0; i<root->distances_count; i++)
01110     if (root->distances[i]->relative_depth == depth)
01111       return root->distances[i];
01112   return NULL;
01113 }
01114 
01134 static inline const struct hwloc_distances_s *
01135 hwloc_get_whole_distance_matrix_by_type(hwloc_topology_t topology, hwloc_obj_type_t type)
01136 {
01137   int depth = hwloc_get_type_depth(topology, type);
01138   if (depth < 0)
01139     return NULL;
01140   return hwloc_get_whole_distance_matrix_by_depth(topology, depth);
01141 }
01142 
01156 static inline const struct hwloc_distances_s *
01157 hwloc_get_distance_matrix_covering_obj_by_depth(hwloc_topology_t topology,
01158                                                 hwloc_obj_t obj, unsigned depth,
01159                                                 unsigned *firstp)
01160 {
01161   while (obj && obj->cpuset) {
01162     unsigned i;
01163     for(i=0; i<obj->distances_count; i++)
01164       if (obj->distances[i]->relative_depth == depth - obj->depth) {
01165         if (!obj->distances[i]->nbobjs)
01166           continue;
01167         *firstp = hwloc_get_next_obj_inside_cpuset_by_depth(topology, obj->cpuset, depth, NULL)->logical_index;
01168         return obj->distances[i];
01169       }
01170     obj = obj->parent;
01171   }
01172   return NULL;
01173 }
01174 
01186 static inline int
01187 hwloc_get_latency(hwloc_topology_t topology,
01188                    hwloc_obj_t obj1, hwloc_obj_t obj2,
01189                    float *latency, float *reverse_latency)
01190 {
01191   hwloc_obj_t ancestor;
01192   const struct hwloc_distances_s * distances;
01193   unsigned first_logical ;
01194 
01195   if (obj1->depth != obj2->depth) {
01196     errno = EINVAL;
01197     return -1;
01198   }
01199 
01200   ancestor = hwloc_get_common_ancestor_obj(topology, obj1, obj2);
01201   distances = hwloc_get_distance_matrix_covering_obj_by_depth(topology, ancestor, obj1->depth, &first_logical);
01202   if (distances && distances->latency) {
01203     const float * latency_matrix = distances->latency;
01204     unsigned nbobjs = distances->nbobjs;
01205     unsigned l1 = obj1->logical_index - first_logical;
01206     unsigned l2 = obj2->logical_index - first_logical;
01207     *latency = latency_matrix[l1*nbobjs+l2];
01208     *reverse_latency = latency_matrix[l2*nbobjs+l1];
01209     return 0;
01210   }
01211 
01212   errno = ENOSYS;
01213   return -1;
01214 }
01215 
01230 static inline hwloc_obj_t
01231 hwloc_get_non_io_ancestor_obj(hwloc_topology_t topology ,
01232                               hwloc_obj_t ioobj)
01233 {
01234   hwloc_obj_t obj = ioobj;
01235   while (obj && !obj->cpuset) {
01236     obj = obj->parent;
01237   }
01238   return obj;
01239 }
01240 
01245 static inline hwloc_obj_t
01246 hwloc_get_next_pcidev(hwloc_topology_t topology, hwloc_obj_t prev)
01247 {
01248   return hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_PCI_DEVICE, prev);
01249 }
01250 
01254 static inline hwloc_obj_t
01255 hwloc_get_pcidev_by_busid(hwloc_topology_t topology,
01256                           unsigned domain, unsigned bus, unsigned dev, unsigned func)
01257 {
01258   hwloc_obj_t obj = NULL;
01259   while ((obj = hwloc_get_next_pcidev(topology, obj)) != NULL) {
01260     if (obj->attr->pcidev.domain == domain
01261         && obj->attr->pcidev.bus == bus
01262         && obj->attr->pcidev.dev == dev
01263         && obj->attr->pcidev.func == func)
01264       return obj;
01265   }
01266   return NULL;
01267 }
01268 
01272 static inline hwloc_obj_t
01273 hwloc_get_pcidev_by_busidstring(hwloc_topology_t topology, const char *busid)
01274 {
01275   unsigned domain = 0; /* default */
01276   unsigned bus, dev, func;
01277 
01278   if (sscanf(busid, "%x:%x.%x", &bus, &dev, &func) != 3
01279       && sscanf(busid, "%x:%x:%x.%x", &domain, &bus, &dev, &func) != 4) {
01280     errno = EINVAL;
01281     return NULL;
01282   }
01283 
01284   return hwloc_get_pcidev_by_busid(topology, domain, bus, dev, func);
01285 }
01286 
01291 static inline hwloc_obj_t
01292 hwloc_get_next_osdev(hwloc_topology_t topology, hwloc_obj_t prev)
01293 {
01294   return hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_OS_DEVICE, prev);
01295 }
01296 
01301 static inline hwloc_obj_t
01302 hwloc_get_next_bridge(hwloc_topology_t topology, hwloc_obj_t prev)
01303 {
01304   return hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_BRIDGE, prev);
01305 }
01306 
01307 /* \brief Checks whether a given bridge covers a given PCI bus.
01308  */
01309 static inline int
01310 hwloc_bridge_covers_pcibus(hwloc_obj_t bridge,
01311                            unsigned domain, unsigned bus)
01312 {
01313   return bridge->type == HWLOC_OBJ_BRIDGE
01314     && bridge->attr->bridge.downstream_type == HWLOC_OBJ_BRIDGE_PCI
01315     && bridge->attr->bridge.downstream.pci.domain == domain
01316     && bridge->attr->bridge.downstream.pci.secondary_bus <= bus
01317     && bridge->attr->bridge.downstream.pci.subordinate_bus >= bus;
01318 }
01319 
01325 static inline hwloc_obj_t
01326 hwloc_get_hostbridge_by_pcibus(hwloc_topology_t topology,
01327                                unsigned domain, unsigned bus)
01328 {
01329   hwloc_obj_t obj = NULL;
01330   while ((obj = hwloc_get_next_bridge(topology, obj)) != NULL) {
01331     if (hwloc_bridge_covers_pcibus(obj, domain, bus)) {
01332       /* found bridge covering this pcibus, make sure it's a hostbridge */
01333       assert(obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_HOST);
01334       assert(obj->parent->type != HWLOC_OBJ_BRIDGE);
01335       assert(obj->parent->cpuset);
01336       return obj;
01337     }
01338   }
01339   return NULL;
01340 }
01341 
01346 #ifdef __cplusplus
01347 } /* extern "C" */
01348 #endif
01349 
01350 
01351 #endif /* HWLOC_HELPER_H */