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

- File List

# helper.h

    00001 /*
    00002  * Copyright © 2009 CNRS, INRIA, Université Bordeaux 1
    00003  * Copyright © 2009-2010 Cisco Systems, Inc.  All rights reserved.
    00004  * See COPYING in top-level directory.
    00005  */
    00006
    00011 #ifndef HWLOC_HELPER_H
    00012 #define HWLOC_HELPER_H
    00013
    00014 #ifndef HWLOC_H
    00015 #error Please include the main hwloc.h instead
    00016 #endif
    00017
    00018 #include <stdlib.h>
    00019 #include <errno.h>
    00020
    00021
    00022 #ifdef __cplusplus
    00023 extern "C" {
    00024 #endif
    00025
    00026
    00037 static __hwloc_inline int __hwloc_attribute_pure
    00038 hwloc_get_type_or_below_depth (hwloc_topology_t topology, hwloc_obj_type_t type)
    00039 {
    00040   int depth = hwloc_get_type_depth(topology, type);
    00041
    00042   if (depth != HWLOC_TYPE_DEPTH_UNKNOWN)
    00043     return depth;
    00044
    00045   /* find the highest existing level with type order >= */
    00046   for(depth = hwloc_get_type_depth(topology, HWLOC_OBJ_PU); ; depth--)
    00047     if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) < 0)
    00048       return depth+1;
    00049
    00050   /* Shouldn't ever happen, as there is always a SYSTEM level with lower order and known depth.  */
    00051   /* abort(); */
    00052 }
    00053
    00060 static __hwloc_inline int __hwloc_attribute_pure
    00061 hwloc_get_type_or_above_depth (hwloc_topology_t topology, hwloc_obj_type_t type)
    00062 {
    00063   int depth = hwloc_get_type_depth(topology, type);
    00064
    00065   if (depth != HWLOC_TYPE_DEPTH_UNKNOWN)
    00066     return depth;
    00067
    00068   /* find the lowest existing level with type order <= */
    00069   for(depth = 0; ; depth++)
    00070     if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) > 0)
    00071       return depth-1;
    00072
    00073   /* Shouldn't ever happen, as there is always a PU level with higher order and known depth.  */
    00074   /* abort(); */
    00075 }
    00076
    00091 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00092 hwloc_get_root_obj (hwloc_topology_t topology)
    00093 {
    00094   return hwloc_get_obj_by_depth (topology, 0, 0);
    00095 }
    00096
    00098 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00099 hwloc_get_ancestor_obj_by_depth (hwloc_topology_t topology __hwloc_attribute_unused, unsigned depth, hwloc_obj_t obj)
    00100 {
    00101   hwloc_obj_t ancestor = obj;
    00102   if (obj->depth < depth)
    00103     return NULL;
    00104   while (ancestor && ancestor->depth > depth)
    00105     ancestor = ancestor->parent;
    00106   return ancestor;
    00107 }
    00108
    00110 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00111 hwloc_get_ancestor_obj_by_type (hwloc_topology_t topology __hwloc_attribute_unused, hwloc_obj_type_t type, hwloc_obj_t obj)
    00112 {
    00113   hwloc_obj_t ancestor = obj->parent;
    00114   while (ancestor && ancestor->type != type)
    00115     ancestor = ancestor->parent;
    00116   return ancestor;
    00117 }
    00118
    00123 static __hwloc_inline hwloc_obj_t
    00124 hwloc_get_next_obj_by_depth (hwloc_topology_t topology, unsigned depth, hwloc_obj_t prev)
    00125 {
    00126   if (!prev)
    00127     return hwloc_get_obj_by_depth (topology, depth, 0);
    00128   if (prev->depth != depth)
    00129     return NULL;
    00130   return prev->next_cousin;
    00131 }
    00132
    00139 static __hwloc_inline hwloc_obj_t
    00140 hwloc_get_next_obj_by_type (hwloc_topology_t topology, hwloc_obj_type_t type,
    00141                    hwloc_obj_t prev)
    00142 {
    00143   int depth = hwloc_get_type_depth(topology, type);
    00144   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
    00145     return NULL;
    00146   return hwloc_get_next_obj_by_depth (topology, depth, prev);
    00147 }
    00148
    00157 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00158 hwloc_get_pu_obj_by_os_index(hwloc_topology_t topology, unsigned os_index)
    00159 {
    00160   hwloc_obj_t obj = NULL;
    00161   while ((obj = hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_PU, obj)) != NULL)
    00162     if (obj->os_index == os_index)
    00163       return obj;
    00164   return NULL;
    00165 }
    00166
    00171 static __hwloc_inline hwloc_obj_t
    00172 hwloc_get_next_child (hwloc_topology_t topology __hwloc_attribute_unused, hwloc_obj_t parent, hwloc_obj_t prev)
    00173 {
    00174   if (!prev)
    00175     return parent->first_child;
    00176   if (prev->parent != parent)
    00177     return NULL;
    00178   return prev->next_sibling;
    00179 }
    00180
    00182 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00183 hwloc_get_common_ancestor_obj (hwloc_topology_t topology __hwloc_attribute_unused, hwloc_obj_t obj1, hwloc_obj_t obj2)
    00184 {
    00185   /* the loop isn't so easy since intermediate ancestors may have
    00186    * different depth, causing us to alternate between using obj1->parent
    00187    * and obj2->parent. Also, even if at some point we find ancestors of
    00188    * of the same depth, their ancestors may have different depth again.
    00189    */
    00190   while (obj1 != obj2) {
    00191     while (obj1->depth > obj2->depth)
    00192       obj1 = obj1->parent;
    00193     while (obj2->depth > obj1->depth)
    00194       obj2 = obj2->parent;
    00195     if (obj1 != obj2 && obj1->depth == obj2->depth) {
    00196       obj1 = obj1->parent;
    00197       obj2 = obj2->parent;
    00198     }
    00199   }
    00200   return obj1;
    00201 }
    00202
    00205 static __hwloc_inline int __hwloc_attribute_pure
    00206 hwloc_obj_is_in_subtree (hwloc_topology_t topology __hwloc_attribute_unused, hwloc_obj_t obj, hwloc_obj_t subtree_root)
    00207 {
    00208   return hwloc_cpuset_isincluded(obj->cpuset, subtree_root->cpuset);
    00209 }
    00210
    00227 static __hwloc_inline hwloc_obj_t
    00228 hwloc_get_first_largest_obj_inside_cpuset(hwloc_topology_t topology, hwloc_const_cpuset_t set)
    00229 {
    00230   hwloc_obj_t obj = hwloc_get_root_obj(topology);
    00231   if (!hwloc_cpuset_intersects(obj->cpuset, set))
    00232     return NULL;
    00233   while (!hwloc_cpuset_isincluded(obj->cpuset, set)) {
    00234     /* while the object intersects without being included, look at its children */
    00235     hwloc_obj_t child = NULL;
    00236     while ((child = hwloc_get_next_child(topology, obj, child)) != NULL) {
    00237       if (hwloc_cpuset_intersects(child->cpuset, set))
    00238         break;
    00239     }
    00240     if (!child)
    00241       /* no child intersects, return their father */
    00242       return obj;
    00243     /* found one intersecting child, look at its children */
    00244     obj = child;
    00245   }
    00246   /* obj is included, return it */
    00247   return obj;
    00248 }
    00249
    00254 HWLOC_DECLSPEC int hwloc_get_largest_objs_inside_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set,
    00255                                                  hwloc_obj_t * __hwloc_restrict objs, int max);
    00256
    00263 static __hwloc_inline hwloc_obj_t
    00264 hwloc_get_next_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
    00265                                            unsigned depth, hwloc_obj_t prev)
    00266 {
    00267   hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev);
    00268   while (next && !hwloc_cpuset_isincluded(next->cpuset, set))
    00269     next = next->next_cousin;
    00270   return next;
    00271 }
    00272
    00279 static __hwloc_inline hwloc_obj_t
    00280 hwloc_get_next_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
    00281                                           hwloc_obj_type_t type, hwloc_obj_t prev)
    00282 {
    00283   int depth = hwloc_get_type_depth(topology, type);
    00284   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
    00285     return NULL;
    00286   return hwloc_get_next_obj_inside_cpuset_by_depth(topology, set, depth, prev);
    00287 }
    00288
    00291 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00292 hwloc_get_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
    00293                                       unsigned depth, unsigned idx)
    00294 {
    00295   unsigned count = 0;
    00296   hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0);
    00297   while (obj) {
    00298     if (hwloc_cpuset_isincluded(obj->cpuset, set)) {
    00299       if (count == idx)
    00300         return obj;
    00301       count++;
    00302     }
    00303     obj = obj->next_cousin;
    00304   }
    00305   return NULL;
    00306 }
    00307
    00314 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00315 hwloc_get_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
    00316                                      hwloc_obj_type_t type, unsigned idx)
    00317 {
    00318   int depth = hwloc_get_type_depth(topology, type);
    00319   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
    00320     return NULL;
    00321   return hwloc_get_obj_inside_cpuset_by_depth(topology, set, depth, idx);
    00322 }
    00323
    00325 static __hwloc_inline unsigned __hwloc_attribute_pure
    00326 hwloc_get_nbobjs_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
    00327                                          unsigned depth)
    00328 {
    00329   hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0);
    00330   int count = 0;
    00331   while (obj) {
    00332     if (hwloc_cpuset_isincluded(obj->cpuset, set))
    00333       count++;
    00334     obj = obj->next_cousin;
    00335   }
    00336   return count;
    00337 }
    00338
    00345 static __hwloc_inline int __hwloc_attribute_pure
    00346 hwloc_get_nbobjs_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
    00347                                         hwloc_obj_type_t type)
    00348 {
    00349   int depth = hwloc_get_type_depth(topology, type);
    00350   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN)
    00351     return 0;
    00352   if (depth == HWLOC_TYPE_DEPTH_MULTIPLE)
    00353     return -1; /* FIXME: agregate nbobjs from different levels? */
    00354   return hwloc_get_nbobjs_inside_cpuset_by_depth(topology, set, depth);
    00355 }
    00356
    00369 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00370 hwloc_get_child_covering_cpuset (hwloc_topology_t topology __hwloc_attribute_unused, hwloc_const_cpuset_t set,
    00371                                 hwloc_obj_t parent)
    00372 {
    00373   hwloc_obj_t child;
    00374
    00375   if (hwloc_cpuset_iszero(set))
    00376     return NULL;
    00377
    00378   child = parent->first_child;
    00379   while (child) {
    00380     if (hwloc_cpuset_isincluded(set, child->cpuset))
    00381       return child;
    00382     child = child->next_sibling;
    00383   }
    00384   return NULL;
    00385 }
    00386
    00391 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00392 hwloc_get_obj_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set)
    00393 {
    00394   struct hwloc_obj *current = hwloc_get_root_obj(topology);
    00395
    00396   if (hwloc_cpuset_iszero(set))
    00397     return NULL;
    00398
    00399   if (!hwloc_cpuset_isincluded(set, current->cpuset))
    00400     return NULL;
    00401
    00402   while (1) {
    00403     hwloc_obj_t child = hwloc_get_child_covering_cpuset(topology, set, current);
    00404     if (!child)
    00405       return current;
    00406     current = child;
    00407   }
    00408 }
    00409
    00410
    00426 static __hwloc_inline hwloc_obj_t
    00427 hwloc_get_next_obj_covering_cpuset_by_depth(hwloc_topology_t topology, hwloc_const_cpuset_t set,
    00428                                             unsigned depth, hwloc_obj_t prev)
    00429 {
    00430   hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev);
    00431   while (next && !hwloc_cpuset_intersects(set, next->cpuset))
    00432     next = next->next_cousin;
    00433   return next;
    00434 }
    00435
    00448 static __hwloc_inline hwloc_obj_t
    00449 hwloc_get_next_obj_covering_cpuset_by_type(hwloc_topology_t topology, hwloc_const_cpuset_t set,
    00450                                            hwloc_obj_type_t type, hwloc_obj_t prev)
    00451 {
    00452   int depth = hwloc_get_type_depth(topology, type);
    00453   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
    00454     return NULL;
    00455   return hwloc_get_next_obj_covering_cpuset_by_depth(topology, set, depth, prev);
    00456 }
    00457
    00470 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00471 hwloc_get_cache_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set)
    00472 {
    00473   hwloc_obj_t current = hwloc_get_obj_covering_cpuset(topology, set);
    00474   while (current) {
    00475     if (current->type == HWLOC_OBJ_CACHE)
    00476       return current;
    00477     current = current->parent;
    00478   }
    00479   return NULL;
    00480 }
    00481
    00486 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00487 hwloc_get_shared_cache_covering_obj (hwloc_topology_t topology __hwloc_attribute_unused, hwloc_obj_t obj)
    00488 {
    00489   hwloc_obj_t current = obj->parent;
    00490   while (current) {
    00491     if (!hwloc_cpuset_isequal(current->cpuset, obj->cpuset)
    00492         && current->type == HWLOC_OBJ_CACHE)
    00493       return current;
    00494     current = current->parent;
    00495   }
    00496   return NULL;
    00497 }
    00498
    00514 /* TODO: rather provide an iterator? Provide a way to know how much should be allocated? By returning the total number of objects instead? */
    00515 HWLOC_DECLSPEC unsigned hwloc_get_closest_objs (hwloc_topology_t topology, hwloc_obj_t src, hwloc_obj_t * __hwloc_restrict objs, unsigned max);
    00516
    00527 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00528 hwloc_get_obj_below_by_type (hwloc_topology_t topology,
    00529                              hwloc_obj_type_t type1, unsigned idx1,
    00530                              hwloc_obj_type_t type2, unsigned idx2)
    00531 {
    00532   hwloc_obj_t obj;
    00533
    00534   obj = hwloc_get_obj_by_type (topology, type1, idx1);
    00535   if (!obj)
    00536     return NULL;
    00537
    00538   return hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, type2, idx2);
    00539 }
    00540
    00556 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00557 hwloc_get_obj_below_array_by_type (hwloc_topology_t topology, int nr, hwloc_obj_type_t *typev, unsigned *idxv)
    00558 {
    00559   hwloc_obj_t obj = hwloc_get_root_obj(topology);
    00560   int i;
    00561
    00562   for(i=0; i<nr; i++) {
    00563     obj = hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, typev[i], idxv[i]);
    00564     if (!obj)
    00565       return NULL;
    00566   }
    00567
    00568   return obj;
    00569 }
    00570
    00591 static __hwloc_inline void
    00592 hwloc_distribute(hwloc_topology_t topology, hwloc_obj_t root, hwloc_cpuset_t *cpuset, unsigned n)
    00593 {
    00594   unsigned i;
    00595   unsigned u;
    00596   unsigned chunk_size, complete_chunks;
    00597   hwloc_cpuset_t *cpusetp;
    00598
    00599   if (!root->arity || n == 1) {
    00600     /* Got to the bottom, we can't split any more, put everything there.  */
    00601     for (i=0; i<n; i++)
    00602       cpuset[i] = hwloc_cpuset_dup(root->cpuset);
    00603     return;
    00604   }
    00605
    00606   /* Divide n in root->arity chunks.  */
    00607   chunk_size = (n + root->arity - 1) / root->arity;
    00608   complete_chunks = n % root->arity;
    00609   if (!complete_chunks)
    00610     complete_chunks = root->arity;
    00611
    00612   /* Allocate complete chunks first.  */
    00613   for (cpusetp = cpuset, i = 0;
    00614        i < complete_chunks;
    00615        i ++, cpusetp += chunk_size)
    00616     hwloc_distribute(topology, root->children[i], cpusetp, chunk_size);
    00617
    00618   /* Now allocate not-so-complete chunks.  */
    00619   for (u = i;
    00620        u < root->arity;
    00621        u++, cpusetp += chunk_size-1)
    00622     hwloc_distribute(topology, root->children[u], cpusetp, chunk_size-1);
    00623 }
    00624
    00630 /* \brief Get complete CPU set
    00631  *
    00632  * \return the complete CPU set of logical processors of the system. If the
    00633  * topology is the result of a combination of several systems, NULL is
    00634  * returned.
    00635  *
    00636  * \note The returned cpuset is not newly allocated and should thus not be
    00637  * changed or freed; hwloc_cpuset_dup must be used to obtain a local copy.
    00638  */
    00639 static __hwloc_inline hwloc_const_cpuset_t __hwloc_attribute_pure
    00640 hwloc_topology_get_complete_cpuset(hwloc_topology_t topology)
    00641 {
    00642   return hwloc_get_root_obj(topology)->complete_cpuset;
    00643 }
    00644
    00645 /* \brief Get topology CPU set
    00646  *
    00647  * \return the CPU set of logical processors of the system for which hwloc
    00648  * provides topology information. This is equivalent to the cpuset of the
    00649  * system object. If the topology is the result of a combination of several
    00650  * systems, NULL is returned.
    00651  *
    00652  * \note The returned cpuset is not newly allocated and should thus not be
    00653  * changed or freed; hwloc_cpuset_dup must be used to obtain a local copy.
    00654  */
    00655 static __hwloc_inline hwloc_const_cpuset_t __hwloc_attribute_pure
    00656 hwloc_topology_get_topology_cpuset(hwloc_topology_t topology)
    00657 {
    00658   return hwloc_get_root_obj(topology)->cpuset;
    00659 }
    00660
    00670 static __hwloc_inline hwloc_const_cpuset_t __hwloc_attribute_pure
    00671 hwloc_topology_get_online_cpuset(hwloc_topology_t topology)
    00672 {
    00673   return hwloc_get_root_obj(topology)->online_cpuset;
    00674 }
    00675
    00685 static __hwloc_inline hwloc_const_cpuset_t __hwloc_attribute_pure
    00686 hwloc_topology_get_allowed_cpuset(hwloc_topology_t topology)
    00687 {
    00688   return hwloc_get_root_obj(topology)->allowed_cpuset;
    00689 }
    00690
    00691
    00695 #ifdef __cplusplus
    00696 } /* extern "C" */
    00697 #endif
    00698
    00699
    00700 #endif /* HWLOC_HELPER_H */