- 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
    00032 static __hwloc_inline int __hwloc_attribute_pure
    00033 hwloc_get_type_or_below_depth (hwloc_topology_t topology, hwloc_obj_type_t type)
    00034 {
    00035   int depth = hwloc_get_type_depth(topology, type);
    00036
    00037   if (depth != HWLOC_TYPE_DEPTH_UNKNOWN)
    00038     return depth;
    00039
    00040   /* find the highest existing level with type order >= */
    00041   for(depth = hwloc_get_type_depth(topology, HWLOC_OBJ_PU); ; depth--)
    00042     if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) < 0)
    00043       return depth+1;
    00044
    00045   /* Shouldn't ever happen, as there is always a SYSTEM level with lower order and known depth.  */
    00046   /* abort(); */
    00047 }
    00048
    00055 static __hwloc_inline int __hwloc_attribute_pure
    00056 hwloc_get_type_or_above_depth (hwloc_topology_t topology, hwloc_obj_type_t type)
    00057 {
    00058   int depth = hwloc_get_type_depth(topology, type);
    00059
    00060   if (depth != HWLOC_TYPE_DEPTH_UNKNOWN)
    00061     return depth;
    00062
    00063   /* find the lowest existing level with type order <= */
    00064   for(depth = 0; ; depth++)
    00065     if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) > 0)
    00066       return depth-1;
    00067
    00068   /* Shouldn't ever happen, as there is always a PU level with higher order and known depth.  */
    00069   /* abort(); */
    00070 }
    00071
    00086 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00087 hwloc_get_root_obj (hwloc_topology_t topology)
    00088 {
    00089   return hwloc_get_obj_by_depth (topology, 0, 0);
    00090 }
    00091
    00093 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00094 hwloc_get_ancestor_obj_by_depth (hwloc_topology_t topology __hwloc_attribute_unused, unsigned depth, hwloc_obj_t obj)
    00095 {
    00096   hwloc_obj_t ancestor = obj;
    00097   if (obj->depth < depth)
    00098     return NULL;
    00099   while (ancestor && ancestor->depth > depth)
    00100     ancestor = ancestor->parent;
    00101   return ancestor;
    00102 }
    00103
    00105 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00106 hwloc_get_ancestor_obj_by_type (hwloc_topology_t topology __hwloc_attribute_unused, hwloc_obj_type_t type, hwloc_obj_t obj)
    00107 {
    00108   hwloc_obj_t ancestor = obj->parent;
    00109   while (ancestor && ancestor->type != type)
    00110     ancestor = ancestor->parent;
    00111   return ancestor;
    00112 }
    00113
    00118 static __hwloc_inline hwloc_obj_t
    00119 hwloc_get_next_obj_by_depth (hwloc_topology_t topology, unsigned depth, hwloc_obj_t prev)
    00120 {
    00121   if (!prev)
    00122     return hwloc_get_obj_by_depth (topology, depth, 0);
    00123   if (prev->depth != depth)
    00124     return NULL;
    00125   return prev->next_cousin;
    00126 }
    00127
    00134 static __hwloc_inline hwloc_obj_t
    00135 hwloc_get_next_obj_by_type (hwloc_topology_t topology, hwloc_obj_type_t type,
    00136                    hwloc_obj_t prev)
    00137 {
    00138   int depth = hwloc_get_type_depth(topology, type);
    00139   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
    00140     return NULL;
    00141   return hwloc_get_next_obj_by_depth (topology, depth, prev);
    00142 }
    00143
    00152 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00153 hwloc_get_pu_obj_by_os_index(hwloc_topology_t topology, unsigned os_index)
    00154 {
    00155   hwloc_obj_t obj = NULL;
    00156   while ((obj = hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_PU, obj)) != NULL)
    00157     if (obj->os_index == os_index)
    00158       return obj;
    00159   return NULL;
    00160 }
    00161
    00166 static __hwloc_inline hwloc_obj_t
    00167 hwloc_get_next_child (hwloc_topology_t topology __hwloc_attribute_unused, hwloc_obj_t parent, hwloc_obj_t prev)
    00168 {
    00169   if (!prev)
    00170     return parent->first_child;
    00171   if (prev->parent != parent)
    00172     return NULL;
    00173   return prev->next_sibling;
    00174 }
    00175
    00177 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00178 hwloc_get_common_ancestor_obj (hwloc_topology_t topology __hwloc_attribute_unused, hwloc_obj_t obj1, hwloc_obj_t obj2)
    00179 {
    00180   while (obj1->depth > obj2->depth)
    00181     obj1 = obj1->parent;
    00182   while (obj2->depth > obj1->depth)
    00183     obj2 = obj2->parent;
    00184   while (obj1 != obj2) {
    00185     obj1 = obj1->parent;
    00186     obj2 = obj2->parent;
    00187   }
    00188   return obj1;
    00189 }
    00190
    00193 static __hwloc_inline int __hwloc_attribute_pure
    00194 hwloc_obj_is_in_subtree (hwloc_topology_t topology __hwloc_attribute_unused, hwloc_obj_t obj, hwloc_obj_t subtree_root)
    00195 {
    00196   return hwloc_cpuset_isincluded(obj->cpuset, subtree_root->cpuset);
    00197 }
    00198
    00215 static __hwloc_inline hwloc_obj_t
    00216 hwloc_get_first_largest_obj_inside_cpuset(hwloc_topology_t topology, hwloc_const_cpuset_t set)
    00217 {
    00218   hwloc_obj_t obj = hwloc_get_root_obj(topology);
    00219   if (!hwloc_cpuset_intersects(obj->cpuset, set))
    00220     return NULL;
    00221   while (!hwloc_cpuset_isincluded(obj->cpuset, set)) {
    00222     /* while the object intersects without being included, look at its children */
    00223     hwloc_obj_t child = NULL;
    00224     while ((child = hwloc_get_next_child(topology, obj, child)) != NULL) {
    00225       if (hwloc_cpuset_intersects(child->cpuset, set))
    00226         break;
    00227     }
    00228     if (!child)
    00229       /* no child intersects, return their father */
    00230       return obj;
    00231     /* found one intersecting child, look at its children */
    00232     obj = child;
    00233   }
    00234   /* obj is included, return it */
    00235   return obj;
    00236 }
    00237
    00242 HWLOC_DECLSPEC int hwloc_get_largest_objs_inside_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set,
    00243                                                  hwloc_obj_t * __hwloc_restrict objs, int max);
    00244
    00251 static __hwloc_inline hwloc_obj_t
    00252 hwloc_get_next_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
    00253                                            unsigned depth, hwloc_obj_t prev)
    00254 {
    00255   hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev);
    00256   while (next && !hwloc_cpuset_isincluded(next->cpuset, set))
    00257     next = next->next_cousin;
    00258   return next;
    00259 }
    00260
    00267 static __hwloc_inline hwloc_obj_t
    00268 hwloc_get_next_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
    00269                                           hwloc_obj_type_t type, hwloc_obj_t prev)
    00270 {
    00271   int depth = hwloc_get_type_depth(topology, type);
    00272   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
    00273     return NULL;
    00274   return hwloc_get_next_obj_inside_cpuset_by_depth(topology, set, depth, prev);
    00275 }
    00276
    00279 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00280 hwloc_get_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
    00281                                       unsigned depth, unsigned idx)
    00282 {
    00283   unsigned count = 0;
    00284   hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0);
    00285   while (obj) {
    00286     if (hwloc_cpuset_isincluded(obj->cpuset, set)) {
    00287       if (count == idx)
    00288         return obj;
    00289       count++;
    00290     }
    00291     obj = obj->next_cousin;
    00292   }
    00293   return NULL;
    00294 }
    00295
    00302 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00303 hwloc_get_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
    00304                                      hwloc_obj_type_t type, unsigned idx)
    00305 {
    00306   int depth = hwloc_get_type_depth(topology, type);
    00307   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
    00308     return NULL;
    00309   return hwloc_get_obj_inside_cpuset_by_depth(topology, set, depth, idx);
    00310 }
    00311
    00313 static __hwloc_inline unsigned __hwloc_attribute_pure
    00314 hwloc_get_nbobjs_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
    00315                                          unsigned depth)
    00316 {
    00317   hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0);
    00318   int count = 0;
    00319   while (obj) {
    00320     if (hwloc_cpuset_isincluded(obj->cpuset, set))
    00321       count++;
    00322     obj = obj->next_cousin;
    00323   }
    00324   return count;
    00325 }
    00326
    00333 static __hwloc_inline int __hwloc_attribute_pure
    00334 hwloc_get_nbobjs_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
    00335                                         hwloc_obj_type_t type)
    00336 {
    00337   int depth = hwloc_get_type_depth(topology, type);
    00338   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN)
    00339     return 0;
    00340   if (depth == HWLOC_TYPE_DEPTH_MULTIPLE)
    00341     return -1; /* FIXME: agregate nbobjs from different levels? */
    00342   return hwloc_get_nbobjs_inside_cpuset_by_depth(topology, set, depth);
    00343 }
    00344
    00357 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00358 hwloc_get_child_covering_cpuset (hwloc_topology_t topology __hwloc_attribute_unused, hwloc_const_cpuset_t set,
    00359                                 hwloc_obj_t parent)
    00360 {
    00361   hwloc_obj_t child;
    00362
    00363   if (hwloc_cpuset_iszero(set))
    00364     return NULL;
    00365
    00366   child = parent->first_child;
    00367   while (child) {
    00368     if (hwloc_cpuset_isincluded(set, child->cpuset))
    00369       return child;
    00370     child = child->next_sibling;
    00371   }
    00372   return NULL;
    00373 }
    00374
    00379 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00380 hwloc_get_obj_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set)
    00381 {
    00382   struct hwloc_obj *current = hwloc_get_root_obj(topology);
    00383
    00384   if (hwloc_cpuset_iszero(set))
    00385     return NULL;
    00386
    00387   if (!hwloc_cpuset_isincluded(set, current->cpuset))
    00388     return NULL;
    00389
    00390   while (1) {
    00391     hwloc_obj_t child = hwloc_get_child_covering_cpuset(topology, set, current);
    00392     if (!child)
    00393       return current;
    00394     current = child;
    00395   }
    00396 }
    00397
    00398
    00414 static __hwloc_inline hwloc_obj_t
    00415 hwloc_get_next_obj_covering_cpuset_by_depth(hwloc_topology_t topology, hwloc_const_cpuset_t set,
    00416                                             unsigned depth, hwloc_obj_t prev)
    00417 {
    00418   hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev);
    00419   while (next && !hwloc_cpuset_intersects(set, next->cpuset))
    00420     next = next->next_cousin;
    00421   return next;
    00422 }
    00423
    00436 static __hwloc_inline hwloc_obj_t
    00437 hwloc_get_next_obj_covering_cpuset_by_type(hwloc_topology_t topology, hwloc_const_cpuset_t set,
    00438                                            hwloc_obj_type_t type, hwloc_obj_t prev)
    00439 {
    00440   int depth = hwloc_get_type_depth(topology, type);
    00441   if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
    00442     return NULL;
    00443   return hwloc_get_next_obj_covering_cpuset_by_depth(topology, set, depth, prev);
    00444 }
    00445
    00458 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00459 hwloc_get_cache_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set)
    00460 {
    00461   hwloc_obj_t current = hwloc_get_obj_covering_cpuset(topology, set);
    00462   while (current) {
    00463     if (current->type == HWLOC_OBJ_CACHE)
    00464       return current;
    00465     current = current->parent;
    00466   }
    00467   return NULL;
    00468 }
    00469
    00474 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00475 hwloc_get_shared_cache_covering_obj (hwloc_topology_t topology __hwloc_attribute_unused, hwloc_obj_t obj)
    00476 {
    00477   hwloc_obj_t current = obj->parent;
    00478   while (current) {
    00479     if (!hwloc_cpuset_isequal(current->cpuset, obj->cpuset)
    00480         && current->type == HWLOC_OBJ_CACHE)
    00481       return current;
    00482     current = current->parent;
    00483   }
    00484   return NULL;
    00485 }
    00486
    00502 /* TODO: rather provide an iterator? Provide a way to know how much should be allocated? By returning the total number of objects instead? */
    00503 HWLOC_DECLSPEC unsigned hwloc_get_closest_objs (hwloc_topology_t topology, hwloc_obj_t src, hwloc_obj_t * __hwloc_restrict objs, unsigned max);
    00504
    00515 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00516 hwloc_get_obj_below_by_type (hwloc_topology_t topology,
    00517                              hwloc_obj_type_t type1, unsigned idx1,
    00518                              hwloc_obj_type_t type2, unsigned idx2)
    00519 {
    00520   hwloc_obj_t obj;
    00521
    00522   obj = hwloc_get_obj_by_type (topology, type1, idx1);
    00523   if (!obj)
    00524     return NULL;
    00525
    00526   return hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, type2, idx2);
    00527 }
    00528
    00544 static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
    00545 hwloc_get_obj_below_array_by_type (hwloc_topology_t topology, int nr, hwloc_obj_type_t *typev, unsigned *idxv)
    00546 {
    00547   hwloc_obj_t obj = hwloc_get_root_obj(topology);
    00548   int i;
    00549
    00550   for(i=0; i<nr; i++) {
    00551     obj = hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, typev[i], idxv[i]);
    00552     if (!obj)
    00553       return NULL;
    00554   }
    00555
    00556   return obj;
    00557 }
    00558
    00579 static __hwloc_inline void
    00580 hwloc_distribute(hwloc_topology_t topology, hwloc_obj_t root, hwloc_cpuset_t *cpuset, unsigned n)
    00581 {
    00582   unsigned i;
    00583   unsigned u;
    00584   unsigned chunk_size, complete_chunks;
    00585   hwloc_cpuset_t *cpusetp;
    00586
    00587   if (!root->arity || n == 1) {
    00588     /* Got to the bottom, we can't split any more, put everything there.  */
    00589     for (i=0; i<n; i++)
    00590       cpuset[i] = hwloc_cpuset_dup(root->cpuset);
    00591     return;
    00592   }
    00593
    00594   /* Divide n in root->arity chunks.  */
    00595   chunk_size = (n + root->arity - 1) / root->arity;
    00596   complete_chunks = n % root->arity;
    00597   if (!complete_chunks)
    00598     complete_chunks = root->arity;
    00599
    00600   /* Allocate complete chunks first.  */
    00601   for (cpusetp = cpuset, i = 0;
    00602        i < complete_chunks;
    00603        i ++, cpusetp += chunk_size)
    00604     hwloc_distribute(topology, root->children[i], cpusetp, chunk_size);
    00605
    00606   /* Now allocate not-so-complete chunks.  */
    00607   for (u = i;
    00608        u < root->arity;
    00609        u++, cpusetp += chunk_size-1)
    00610     hwloc_distribute(topology, root->children[u], cpusetp, chunk_size-1);
    00611 }
    00612
    00618 /* \brief Get complete CPU set
    00619  *
    00620  * \return the complete CPU set of logical processors of the system. If the
    00621  * topology is the result of a combination of several systems, NULL is
    00622  * returned.
    00623  *
    00624  * \note The returned cpuset is not newly allocated and should thus not be
    00625  * changed or freed; hwloc_cpuset_dup must be used to obtain a local copy.
    00626  */
    00627 static __hwloc_inline hwloc_const_cpuset_t __hwloc_attribute_pure
    00628 hwloc_topology_get_complete_cpuset(hwloc_topology_t topology)
    00629 {
    00630   return hwloc_get_root_obj(topology)->complete_cpuset;
    00631 }
    00632
    00633 /* \brief Get topology CPU set
    00634  *
    00635  * \return the CPU set of logical processors of the system for which hwloc
    00636  * provides topology information. This is equivalent to the cpuset of the
    00637  * system object. If the topology is the result of a combination of several
    00638  * systems, NULL is returned.
    00639  *
    00640  * \note The returned cpuset is not newly allocated and should thus not be
    00641  * changed or freed; hwloc_cpuset_dup must be used to obtain a local copy.
    00642  */
    00643 static __hwloc_inline hwloc_const_cpuset_t __hwloc_attribute_pure
    00644 hwloc_topology_get_topology_cpuset(hwloc_topology_t topology)
    00645 {
    00646   return hwloc_get_root_obj(topology)->cpuset;
    00647 }
    00648
    00658 static __hwloc_inline hwloc_const_cpuset_t __hwloc_attribute_pure
    00659 hwloc_topology_get_online_cpuset(hwloc_topology_t topology)
    00660 {
    00661   return hwloc_get_root_obj(topology)->online_cpuset;
    00662 }
    00663
    00673 static __hwloc_inline hwloc_const_cpuset_t __hwloc_attribute_pure
    00674 hwloc_topology_get_allowed_cpuset(hwloc_topology_t topology)
    00675 {
    00676   return hwloc_get_root_obj(topology)->allowed_cpuset;
    00677 }
    00678
    00679
    00682 #endif /* HWLOC_HELPER_H */