• 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 */

Generated on Thu Dec 16 2010 06:44:16 for Hardware Locality (hwloc) by  doxygen 1.7.1