• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List

helper.h

00001 /*
00002  * Copyright © 2009 CNRS
00003  * Copyright © 2009-2010 INRIA
00004  * Copyright © 2009-2010 Université Bordeaux 1
00005  * Copyright © 2009-2010 Cisco Systems, Inc.  All rights reserved.
00006  * See COPYING in top-level directory.
00007  */
00008 
00013 #ifndef HWLOC_HELPER_H
00014 #define HWLOC_HELPER_H
00015 
00016 #ifndef HWLOC_H
00017 #error Please include the main hwloc.h instead
00018 #endif
00019 
00020 #include <stdlib.h>
00021 #include <errno.h>
00022 
00023 
00024 #ifdef __cplusplus
00025 extern "C" {
00026 #endif
00027 
00028 
00039 static inline int 
00040 hwloc_get_type_or_below_depth (hwloc_topology_t topology, hwloc_obj_type_t type)
00041 {
00042   int depth = hwloc_get_type_depth(topology, type);
00043 
00044   if (depth != HWLOC_TYPE_DEPTH_UNKNOWN)
00045     return depth;
00046 
00047   /* find the highest existing level with type order >= */
00048   for(depth = hwloc_get_type_depth(topology, HWLOC_OBJ_PU); ; depth--)
00049     if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) < 0)
00050       return depth+1;
00051 
00052   /* Shouldn't ever happen, as there is always a SYSTEM level with lower order and known depth.  */
00053   /* abort(); */
00054 }
00055 
00062 static inline int 
00063 hwloc_get_type_or_above_depth (hwloc_topology_t topology, hwloc_obj_type_t type)
00064 {
00065   int depth = hwloc_get_type_depth(topology, type);
00066 
00067   if (depth != HWLOC_TYPE_DEPTH_UNKNOWN)
00068     return depth;
00069 
00070   /* find the lowest existing level with type order <= */
00071   for(depth = 0; ; depth++)
00072     if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) > 0)
00073       return depth-1;
00074 
00075   /* Shouldn't ever happen, as there is always a PU level with higher order and known depth.  */
00076   /* abort(); */
00077 }
00078 
00093 static inline hwloc_obj_t 
00094 hwloc_get_root_obj (hwloc_topology_t topology)
00095 {
00096   return hwloc_get_obj_by_depth (topology, 0, 0);
00097 }
00098 
00100 static inline hwloc_obj_t 
00101 hwloc_get_ancestor_obj_by_depth (hwloc_topology_t topology , unsigned depth, hwloc_obj_t obj)
00102 {
00103   hwloc_obj_t ancestor = obj;
00104   if (obj->depth < depth)
00105     return NULL;
00106   while (ancestor && ancestor->depth > depth)
00107     ancestor = ancestor->parent;
00108   return ancestor;
00109 }
00110 
00112 static inline hwloc_obj_t 
00113 hwloc_get_ancestor_obj_by_type (hwloc_topology_t topology , hwloc_obj_type_t type, hwloc_obj_t obj)
00114 {
00115   hwloc_obj_t ancestor = obj->parent;
00116   while (ancestor && ancestor->type != type)
00117     ancestor = ancestor->parent;
00118   return ancestor;
00119 }
00120 
00125 static inline hwloc_obj_t
00126 hwloc_get_next_obj_by_depth (hwloc_topology_t topology, unsigned depth, hwloc_obj_t prev)
00127 {
00128   if (!prev)
00129     return hwloc_get_obj_by_depth (topology, depth, 0);
00130   if (prev->depth != depth)
00131     return NULL;
00132   return prev->next_cousin;
00133 }
00134 
00141 static inline hwloc_obj_t
00142 hwloc_get_next_obj_by_type (hwloc_topology_t topology, hwloc_obj_type_t type,
00143                    hwloc_obj_t prev)
00144 {
00145   int depth = hwloc_get_type_depth(topology, type);
00146   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00147     return NULL;
00148   return hwloc_get_next_obj_by_depth (topology, depth, prev);
00149 }
00150 
00159 static inline hwloc_obj_t 
00160 hwloc_get_pu_obj_by_os_index(hwloc_topology_t topology, unsigned os_index)
00161 {
00162   hwloc_obj_t obj = NULL;
00163   while ((obj = hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_PU, obj)) != NULL)
00164     if (obj->os_index == os_index)
00165       return obj;
00166   return NULL;
00167 }
00168 
00173 static inline hwloc_obj_t
00174 hwloc_get_next_child (hwloc_topology_t topology , hwloc_obj_t parent, hwloc_obj_t prev)
00175 {
00176   if (!prev)
00177     return parent->first_child;
00178   if (prev->parent != parent)
00179     return NULL;
00180   return prev->next_sibling;
00181 }
00182 
00184 static inline hwloc_obj_t 
00185 hwloc_get_common_ancestor_obj (hwloc_topology_t topology , hwloc_obj_t obj1, hwloc_obj_t obj2)
00186 {
00187   /* the loop isn't so easy since intermediate ancestors may have
00188    * different depth, causing us to alternate between using obj1->parent
00189    * and obj2->parent. Also, even if at some point we find ancestors of
00190    * of the same depth, their ancestors may have different depth again.
00191    */
00192   while (obj1 != obj2) {
00193     while (obj1->depth > obj2->depth)
00194       obj1 = obj1->parent;
00195     while (obj2->depth > obj1->depth)
00196       obj2 = obj2->parent;
00197     if (obj1 != obj2 && obj1->depth == obj2->depth) {
00198       obj1 = obj1->parent;
00199       obj2 = obj2->parent;
00200     }
00201   }
00202   return obj1;
00203 }
00204 
00207 static inline int 
00208 hwloc_obj_is_in_subtree (hwloc_topology_t topology , hwloc_obj_t obj, hwloc_obj_t subtree_root)
00209 {
00210   return hwloc_bitmap_isincluded(obj->cpuset, subtree_root->cpuset);
00211 }
00212 
00229 static inline hwloc_obj_t
00230 hwloc_get_first_largest_obj_inside_cpuset(hwloc_topology_t topology, hwloc_const_cpuset_t set)
00231 {
00232   hwloc_obj_t obj = hwloc_get_root_obj(topology);
00233   if (!hwloc_bitmap_intersects(obj->cpuset, set))
00234     return NULL;
00235   while (!hwloc_bitmap_isincluded(obj->cpuset, set)) {
00236     /* while the object intersects without being included, look at its children */
00237     hwloc_obj_t child = NULL;
00238     while ((child = hwloc_get_next_child(topology, obj, child)) != NULL) {
00239       if (hwloc_bitmap_intersects(child->cpuset, set))
00240         break;
00241     }
00242     if (!child)
00243       /* no child intersects, return their father */
00244       return obj;
00245     /* found one intersecting child, look at its children */
00246     obj = child;
00247   }
00248   /* obj is included, return it */
00249   return obj;
00250 }
00251 
00256  int hwloc_get_largest_objs_inside_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00257                                                  hwloc_obj_t * restrict objs, int max);
00258 
00265 static inline hwloc_obj_t
00266 hwloc_get_next_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00267                                            unsigned depth, hwloc_obj_t prev)
00268 {
00269   hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev);
00270   while (next && !hwloc_bitmap_isincluded(next->cpuset, set))
00271     next = next->next_cousin;
00272   return next;
00273 }
00274 
00281 static inline hwloc_obj_t
00282 hwloc_get_next_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00283                                           hwloc_obj_type_t type, hwloc_obj_t prev)
00284 {
00285   int depth = hwloc_get_type_depth(topology, type);
00286   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00287     return NULL;
00288   return hwloc_get_next_obj_inside_cpuset_by_depth(topology, set, depth, prev);
00289 }
00290 
00293 static inline hwloc_obj_t 
00294 hwloc_get_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00295                                       unsigned depth, unsigned idx)
00296 {
00297   unsigned count = 0;
00298   hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0);
00299   while (obj) {
00300     if (hwloc_bitmap_isincluded(obj->cpuset, set)) {
00301       if (count == idx)
00302         return obj;
00303       count++;
00304     }
00305     obj = obj->next_cousin;
00306   }
00307   return NULL;
00308 }
00309 
00316 static inline hwloc_obj_t 
00317 hwloc_get_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00318                                      hwloc_obj_type_t type, unsigned idx)
00319 {
00320   int depth = hwloc_get_type_depth(topology, type);
00321   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00322     return NULL;
00323   return hwloc_get_obj_inside_cpuset_by_depth(topology, set, depth, idx);
00324 }
00325 
00327 static inline unsigned 
00328 hwloc_get_nbobjs_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00329                                          unsigned depth)
00330 {
00331   hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0);
00332   int count = 0;
00333   while (obj) {
00334     if (hwloc_bitmap_isincluded(obj->cpuset, set))
00335       count++;
00336     obj = obj->next_cousin;
00337   }
00338   return count;
00339 }
00340 
00347 static inline int 
00348 hwloc_get_nbobjs_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
00349                                         hwloc_obj_type_t type)
00350 {
00351   int depth = hwloc_get_type_depth(topology, type);
00352   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN)
00353     return 0;
00354   if (depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00355     return -1; /* FIXME: agregate nbobjs from different levels? */
00356   return hwloc_get_nbobjs_inside_cpuset_by_depth(topology, set, depth);
00357 }
00358 
00371 static inline hwloc_obj_t 
00372 hwloc_get_child_covering_cpuset (hwloc_topology_t topology , hwloc_const_cpuset_t set,
00373                                 hwloc_obj_t parent)
00374 {
00375   hwloc_obj_t child;
00376 
00377   if (hwloc_bitmap_iszero(set))
00378     return NULL;
00379 
00380   child = parent->first_child;
00381   while (child) {
00382     if (hwloc_bitmap_isincluded(set, child->cpuset))
00383       return child;
00384     child = child->next_sibling;
00385   }
00386   return NULL;
00387 }
00388 
00393 static inline hwloc_obj_t 
00394 hwloc_get_obj_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set)
00395 {
00396   struct hwloc_obj *current = hwloc_get_root_obj(topology);
00397 
00398   if (hwloc_bitmap_iszero(set))
00399     return NULL;
00400 
00401   if (!hwloc_bitmap_isincluded(set, current->cpuset))
00402     return NULL;
00403 
00404   while (1) {
00405     hwloc_obj_t child = hwloc_get_child_covering_cpuset(topology, set, current);
00406     if (!child)
00407       return current;
00408     current = child;
00409   }
00410 }
00411 
00412 
00428 static inline hwloc_obj_t
00429 hwloc_get_next_obj_covering_cpuset_by_depth(hwloc_topology_t topology, hwloc_const_cpuset_t set,
00430                                             unsigned depth, hwloc_obj_t prev)
00431 {
00432   hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev);
00433   while (next && !hwloc_bitmap_intersects(set, next->cpuset))
00434     next = next->next_cousin;
00435   return next;
00436 }
00437 
00450 static inline hwloc_obj_t
00451 hwloc_get_next_obj_covering_cpuset_by_type(hwloc_topology_t topology, hwloc_const_cpuset_t set,
00452                                            hwloc_obj_type_t type, hwloc_obj_t prev)
00453 {
00454   int depth = hwloc_get_type_depth(topology, type);
00455   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
00456     return NULL;
00457   return hwloc_get_next_obj_covering_cpuset_by_depth(topology, set, depth, prev);
00458 }
00459 
00472 static inline hwloc_obj_t 
00473 hwloc_get_cache_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set)
00474 {
00475   hwloc_obj_t current = hwloc_get_obj_covering_cpuset(topology, set);
00476   while (current) {
00477     if (current->type == HWLOC_OBJ_CACHE)
00478       return current;
00479     current = current->parent;
00480   }
00481   return NULL;
00482 }
00483 
00488 static inline hwloc_obj_t 
00489 hwloc_get_shared_cache_covering_obj (hwloc_topology_t topology , hwloc_obj_t obj)
00490 {
00491   hwloc_obj_t current = obj->parent;
00492   while (current) {
00493     if (!hwloc_bitmap_isequal(current->cpuset, obj->cpuset)
00494         && current->type == HWLOC_OBJ_CACHE)
00495       return current;
00496     current = current->parent;
00497   }
00498   return NULL;
00499 }
00500 
00516 /* TODO: rather provide an iterator? Provide a way to know how much should be allocated? By returning the total number of objects instead? */
00517  unsigned hwloc_get_closest_objs (hwloc_topology_t topology, hwloc_obj_t src, hwloc_obj_t * restrict objs, unsigned max);
00518 
00529 static inline hwloc_obj_t 
00530 hwloc_get_obj_below_by_type (hwloc_topology_t topology,
00531                              hwloc_obj_type_t type1, unsigned idx1,
00532                              hwloc_obj_type_t type2, unsigned idx2)
00533 {
00534   hwloc_obj_t obj;
00535 
00536   obj = hwloc_get_obj_by_type (topology, type1, idx1);
00537   if (!obj)
00538     return NULL;
00539 
00540   return hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, type2, idx2);
00541 }
00542 
00558 static inline hwloc_obj_t 
00559 hwloc_get_obj_below_array_by_type (hwloc_topology_t topology, int nr, hwloc_obj_type_t *typev, unsigned *idxv)
00560 {
00561   hwloc_obj_t obj = hwloc_get_root_obj(topology);
00562   int i;
00563 
00564   for(i=0; i<nr; i++) {
00565     obj = hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, typev[i], idxv[i]);
00566     if (!obj)
00567       return NULL;
00568   }
00569 
00570   return obj;
00571 }
00572 
00594 static inline void
00595 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *root, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until);
00596 static inline void
00597 hwloc_distribute(hwloc_topology_t topology, hwloc_obj_t root, hwloc_cpuset_t *cpuset, unsigned n, unsigned until)
00598 {
00599   unsigned i;
00600 
00601   if (!root->arity || n == 1 || root->depth >= until) {
00602     /* Got to the bottom, we can't split any more, put everything there.  */
00603     for (i=0; i<n; i++)
00604       cpuset[i] = hwloc_bitmap_dup(root->cpuset);
00605     return;
00606   }
00607 
00608   hwloc_distributev(topology, root->children, root->arity, cpuset, n, until);
00609 }
00610 
00616 static inline void
00617 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *roots, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until)
00618 {
00619   unsigned i;
00620   unsigned tot_weight;
00621   hwloc_cpuset_t *cpusetp = cpuset;
00622 
00623   tot_weight = 0;
00624   for (i = 0; i < n_roots; i++)
00625     tot_weight += hwloc_bitmap_weight(roots[i]->cpuset);
00626 
00627   for (i = 0; i < n_roots; i++) {
00628     /* Give to roots[i] a portion proportional to its weight */
00629     unsigned weight = hwloc_bitmap_weight(roots[i]->cpuset);
00630     unsigned chunk = (n * weight + tot_weight-1) / tot_weight;
00631     hwloc_distribute(topology, roots[i], cpusetp, chunk, until);
00632     cpusetp += chunk;
00633     tot_weight -= weight;
00634     n -= chunk;
00635   }
00636 }
00637 
00644 static inline void *
00645 hwloc_alloc_membind_policy_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
00646 {
00647   void *p = hwloc_alloc_membind_nodeset(topology, len, nodeset, policy, flags);
00648   if (p)
00649     return p;
00650   hwloc_set_membind_nodeset(topology, nodeset, policy, flags);
00651   p = hwloc_alloc(topology, len);
00652   if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH)
00653     /* Enforce the binding by touching the data */
00654     memset(p, 0, len);
00655   return p;
00656 }
00657 
00662 static inline void *
00663 hwloc_alloc_membind_policy(hwloc_topology_t topology, size_t len, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags)
00664 {
00665   void *p = hwloc_alloc_membind(topology, len, cpuset, policy, flags);
00666   if (p)
00667     return p;
00668   hwloc_set_membind(topology, cpuset, policy, flags);
00669   p = hwloc_alloc(topology, len);
00670   if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH)
00671     /* Enforce the binding by touching the data */
00672     memset(p, 0, len);
00673   return p;
00674 }
00675 
00692 static inline hwloc_const_cpuset_t 
00693 hwloc_topology_get_complete_cpuset(hwloc_topology_t topology)
00694 {
00695   return hwloc_get_root_obj(topology)->complete_cpuset;
00696 }
00697 
00708 static inline hwloc_const_cpuset_t 
00709 hwloc_topology_get_topology_cpuset(hwloc_topology_t topology)
00710 {
00711   return hwloc_get_root_obj(topology)->cpuset;
00712 }
00713 
00723 static inline hwloc_const_cpuset_t 
00724 hwloc_topology_get_online_cpuset(hwloc_topology_t topology)
00725 {
00726   return hwloc_get_root_obj(topology)->online_cpuset;
00727 }
00728 
00738 static inline hwloc_const_cpuset_t 
00739 hwloc_topology_get_allowed_cpuset(hwloc_topology_t topology)
00740 {
00741   return hwloc_get_root_obj(topology)->allowed_cpuset;
00742 }
00743 
00760 static inline hwloc_const_nodeset_t 
00761 hwloc_topology_get_complete_nodeset(hwloc_topology_t topology)
00762 {
00763   return hwloc_get_root_obj(topology)->complete_nodeset;
00764 }
00765 
00776 static inline hwloc_const_nodeset_t 
00777 hwloc_topology_get_topology_nodeset(hwloc_topology_t topology)
00778 {
00779   return hwloc_get_root_obj(topology)->nodeset;
00780 }
00781 
00791 static inline hwloc_const_nodeset_t 
00792 hwloc_topology_get_allowed_nodeset(hwloc_topology_t topology)
00793 {
00794   return hwloc_get_root_obj(topology)->allowed_nodeset;
00795 }
00796 
00827 static inline void
00828 hwloc_cpuset_to_nodeset(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset)
00829 {
00830         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
00831         hwloc_obj_t obj;
00832 
00833         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) {
00834                  if (hwloc_bitmap_iszero(cpuset))
00835                         hwloc_bitmap_zero(nodeset);
00836                 else
00837                         /* Assume the whole system */
00838                         hwloc_bitmap_fill(nodeset);
00839                 return;
00840         }
00841 
00842         hwloc_bitmap_zero(nodeset);
00843         obj = NULL;
00844         while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL)
00845                 hwloc_bitmap_set(nodeset, obj->os_index);
00846 }
00847 
00855 static inline void
00856 hwloc_cpuset_to_nodeset_strict(struct hwloc_topology *topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset)
00857 {
00858         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
00859         hwloc_obj_t obj;
00860         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN )
00861                 return;
00862         hwloc_bitmap_zero(nodeset);
00863         obj = NULL;
00864         while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL)
00865                 hwloc_bitmap_set(nodeset, obj->os_index);
00866 }
00867 
00876 static inline void
00877 hwloc_cpuset_from_nodeset(hwloc_topology_t topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset)
00878 {
00879         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
00880         hwloc_obj_t obj;
00881 
00882         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) {
00883                 if (hwloc_bitmap_iszero(nodeset))
00884                         hwloc_bitmap_zero(cpuset);
00885                 else
00886                         /* Assume the whole system */
00887                         hwloc_bitmap_fill(cpuset);
00888                 return;
00889         }
00890 
00891         hwloc_bitmap_zero(cpuset);
00892         obj = NULL;
00893         while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL) {
00894                 if (hwloc_bitmap_isset(nodeset, obj->os_index))
00895                         hwloc_bitmap_or(cpuset, cpuset, obj->cpuset);
00896         }
00897 }
00898 
00906 static inline void
00907 hwloc_cpuset_from_nodeset_strict(struct hwloc_topology *topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset)
00908 {
00909         int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
00910         hwloc_obj_t obj;
00911         if (depth == HWLOC_TYPE_DEPTH_UNKNOWN )
00912                 return;
00913         hwloc_bitmap_zero(cpuset);
00914         obj = NULL;
00915         while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL)
00916                 if (hwloc_bitmap_isset(nodeset, obj->os_index))
00917                         hwloc_bitmap_or(cpuset, cpuset, obj->cpuset);
00918 }
00919 
00924 #ifdef __cplusplus
00925 } /* extern "C" */
00926 #endif
00927 
00928 
00929 #endif /* HWLOC_HELPER_H */

Generated on Mon Jan 24 2011 17:12:07 for Hardware Locality (hwloc) by  doxygen 1.7.2