Hardware Locality (hwloc) 1.1.2
|
00001 /* 00002 * Copyright © 2009 CNRS 00003 * Copyright © 2009-2011 INRIA. All rights reserved. 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 00209 static inline int 00210 hwloc_obj_is_in_subtree (hwloc_topology_t topology , hwloc_obj_t obj, hwloc_obj_t subtree_root) 00211 { 00212 return hwloc_bitmap_isincluded(obj->cpuset, subtree_root->cpuset); 00213 } 00214 00231 static inline hwloc_obj_t 00232 hwloc_get_first_largest_obj_inside_cpuset(hwloc_topology_t topology, hwloc_const_cpuset_t set) 00233 { 00234 hwloc_obj_t obj = hwloc_get_root_obj(topology); 00235 if (!hwloc_bitmap_intersects(obj->cpuset, set)) 00236 return NULL; 00237 while (!hwloc_bitmap_isincluded(obj->cpuset, set)) { 00238 /* while the object intersects without being included, look at its children */ 00239 hwloc_obj_t child = NULL; 00240 while ((child = hwloc_get_next_child(topology, obj, child)) != NULL) { 00241 if (hwloc_bitmap_intersects(child->cpuset, set)) 00242 break; 00243 } 00244 if (!child) 00245 /* no child intersects, return their father */ 00246 return obj; 00247 /* found one intersecting child, look at its children */ 00248 obj = child; 00249 } 00250 /* obj is included, return it */ 00251 return obj; 00252 } 00253 00258 int hwloc_get_largest_objs_inside_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00259 hwloc_obj_t * restrict objs, int max); 00260 00267 static inline hwloc_obj_t 00268 hwloc_get_next_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00269 unsigned depth, hwloc_obj_t prev) 00270 { 00271 hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev); 00272 while (next && !hwloc_bitmap_isincluded(next->cpuset, set)) 00273 next = next->next_cousin; 00274 return next; 00275 } 00276 00283 static inline hwloc_obj_t 00284 hwloc_get_next_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00285 hwloc_obj_type_t type, hwloc_obj_t prev) 00286 { 00287 int depth = hwloc_get_type_depth(topology, type); 00288 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00289 return NULL; 00290 return hwloc_get_next_obj_inside_cpuset_by_depth(topology, set, depth, prev); 00291 } 00292 00295 static inline hwloc_obj_t 00296 hwloc_get_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00297 unsigned depth, unsigned idx) 00298 { 00299 unsigned count = 0; 00300 hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0); 00301 while (obj) { 00302 if (hwloc_bitmap_isincluded(obj->cpuset, set)) { 00303 if (count == idx) 00304 return obj; 00305 count++; 00306 } 00307 obj = obj->next_cousin; 00308 } 00309 return NULL; 00310 } 00311 00318 static inline hwloc_obj_t 00319 hwloc_get_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00320 hwloc_obj_type_t type, unsigned idx) 00321 { 00322 int depth = hwloc_get_type_depth(topology, type); 00323 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00324 return NULL; 00325 return hwloc_get_obj_inside_cpuset_by_depth(topology, set, depth, idx); 00326 } 00327 00329 static inline unsigned 00330 hwloc_get_nbobjs_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00331 unsigned depth) 00332 { 00333 hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0); 00334 int count = 0; 00335 while (obj) { 00336 if (hwloc_bitmap_isincluded(obj->cpuset, set)) 00337 count++; 00338 obj = obj->next_cousin; 00339 } 00340 return count; 00341 } 00342 00349 static inline int 00350 hwloc_get_nbobjs_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00351 hwloc_obj_type_t type) 00352 { 00353 int depth = hwloc_get_type_depth(topology, type); 00354 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) 00355 return 0; 00356 if (depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00357 return -1; /* FIXME: agregate nbobjs from different levels? */ 00358 return hwloc_get_nbobjs_inside_cpuset_by_depth(topology, set, depth); 00359 } 00360 00373 static inline hwloc_obj_t 00374 hwloc_get_child_covering_cpuset (hwloc_topology_t topology , hwloc_const_cpuset_t set, 00375 hwloc_obj_t parent) 00376 { 00377 hwloc_obj_t child; 00378 00379 if (hwloc_bitmap_iszero(set)) 00380 return NULL; 00381 00382 child = parent->first_child; 00383 while (child) { 00384 if (hwloc_bitmap_isincluded(set, child->cpuset)) 00385 return child; 00386 child = child->next_sibling; 00387 } 00388 return NULL; 00389 } 00390 00395 static inline hwloc_obj_t 00396 hwloc_get_obj_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set) 00397 { 00398 struct hwloc_obj *current = hwloc_get_root_obj(topology); 00399 00400 if (hwloc_bitmap_iszero(set)) 00401 return NULL; 00402 00403 if (!hwloc_bitmap_isincluded(set, current->cpuset)) 00404 return NULL; 00405 00406 while (1) { 00407 hwloc_obj_t child = hwloc_get_child_covering_cpuset(topology, set, current); 00408 if (!child) 00409 return current; 00410 current = child; 00411 } 00412 } 00413 00414 00430 static inline hwloc_obj_t 00431 hwloc_get_next_obj_covering_cpuset_by_depth(hwloc_topology_t topology, hwloc_const_cpuset_t set, 00432 unsigned depth, hwloc_obj_t prev) 00433 { 00434 hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev); 00435 while (next && !hwloc_bitmap_intersects(set, next->cpuset)) 00436 next = next->next_cousin; 00437 return next; 00438 } 00439 00452 static inline hwloc_obj_t 00453 hwloc_get_next_obj_covering_cpuset_by_type(hwloc_topology_t topology, hwloc_const_cpuset_t set, 00454 hwloc_obj_type_t type, hwloc_obj_t prev) 00455 { 00456 int depth = hwloc_get_type_depth(topology, type); 00457 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00458 return NULL; 00459 return hwloc_get_next_obj_covering_cpuset_by_depth(topology, set, depth, prev); 00460 } 00461 00474 static inline hwloc_obj_t 00475 hwloc_get_cache_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set) 00476 { 00477 hwloc_obj_t current = hwloc_get_obj_covering_cpuset(topology, set); 00478 while (current) { 00479 if (current->type == HWLOC_OBJ_CACHE) 00480 return current; 00481 current = current->parent; 00482 } 00483 return NULL; 00484 } 00485 00490 static inline hwloc_obj_t 00491 hwloc_get_shared_cache_covering_obj (hwloc_topology_t topology , hwloc_obj_t obj) 00492 { 00493 hwloc_obj_t current = obj->parent; 00494 while (current) { 00495 if (!hwloc_bitmap_isequal(current->cpuset, obj->cpuset) 00496 && current->type == HWLOC_OBJ_CACHE) 00497 return current; 00498 current = current->parent; 00499 } 00500 return NULL; 00501 } 00502 00518 /* TODO: rather provide an iterator? Provide a way to know how much should be allocated? By returning the total number of objects instead? */ 00519 unsigned hwloc_get_closest_objs (hwloc_topology_t topology, hwloc_obj_t src, hwloc_obj_t * restrict objs, unsigned max); 00520 00531 static inline hwloc_obj_t 00532 hwloc_get_obj_below_by_type (hwloc_topology_t topology, 00533 hwloc_obj_type_t type1, unsigned idx1, 00534 hwloc_obj_type_t type2, unsigned idx2) 00535 { 00536 hwloc_obj_t obj; 00537 00538 obj = hwloc_get_obj_by_type (topology, type1, idx1); 00539 if (!obj) 00540 return NULL; 00541 00542 return hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, type2, idx2); 00543 } 00544 00560 static inline hwloc_obj_t 00561 hwloc_get_obj_below_array_by_type (hwloc_topology_t topology, int nr, hwloc_obj_type_t *typev, unsigned *idxv) 00562 { 00563 hwloc_obj_t obj = hwloc_get_root_obj(topology); 00564 int i; 00565 00566 for(i=0; i<nr; i++) { 00567 obj = hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, typev[i], idxv[i]); 00568 if (!obj) 00569 return NULL; 00570 } 00571 00572 return obj; 00573 } 00574 00596 static inline void 00597 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *root, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until); 00598 static inline void 00599 hwloc_distribute(hwloc_topology_t topology, hwloc_obj_t root, hwloc_cpuset_t *cpuset, unsigned n, unsigned until) 00600 { 00601 unsigned i; 00602 00603 if (!root->arity || n == 1 || root->depth >= until) { 00604 /* Got to the bottom, we can't split any more, put everything there. */ 00605 for (i=0; i<n; i++) 00606 cpuset[i] = hwloc_bitmap_dup(root->cpuset); 00607 return; 00608 } 00609 00610 hwloc_distributev(topology, root->children, root->arity, cpuset, n, until); 00611 } 00612 00618 static inline void 00619 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *roots, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until) 00620 { 00621 unsigned i; 00622 unsigned tot_weight; 00623 hwloc_cpuset_t *cpusetp = cpuset; 00624 00625 tot_weight = 0; 00626 for (i = 0; i < n_roots; i++) 00627 tot_weight += hwloc_bitmap_weight(roots[i]->cpuset); 00628 00629 for (i = 0; i < n_roots; i++) { 00630 /* Give to roots[i] a portion proportional to its weight */ 00631 unsigned weight = hwloc_bitmap_weight(roots[i]->cpuset); 00632 unsigned chunk = (n * weight + tot_weight-1) / tot_weight; 00633 hwloc_distribute(topology, roots[i], cpusetp, chunk, until); 00634 cpusetp += chunk; 00635 tot_weight -= weight; 00636 n -= chunk; 00637 } 00638 } 00639 00646 static inline void * 00647 hwloc_alloc_membind_policy_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) 00648 { 00649 void *p = hwloc_alloc_membind_nodeset(topology, len, nodeset, policy, flags); 00650 if (p) 00651 return p; 00652 hwloc_set_membind_nodeset(topology, nodeset, policy, flags); 00653 p = hwloc_alloc(topology, len); 00654 if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH) 00655 /* Enforce the binding by touching the data */ 00656 memset(p, 0, len); 00657 return p; 00658 } 00659 00664 static inline void * 00665 hwloc_alloc_membind_policy(hwloc_topology_t topology, size_t len, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags) 00666 { 00667 void *p = hwloc_alloc_membind(topology, len, cpuset, policy, flags); 00668 if (p) 00669 return p; 00670 hwloc_set_membind(topology, cpuset, policy, flags); 00671 p = hwloc_alloc(topology, len); 00672 if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH) 00673 /* Enforce the binding by touching the data */ 00674 memset(p, 0, len); 00675 return p; 00676 } 00677 00694 static inline hwloc_const_cpuset_t 00695 hwloc_topology_get_complete_cpuset(hwloc_topology_t topology) 00696 { 00697 return hwloc_get_root_obj(topology)->complete_cpuset; 00698 } 00699 00710 static inline hwloc_const_cpuset_t 00711 hwloc_topology_get_topology_cpuset(hwloc_topology_t topology) 00712 { 00713 return hwloc_get_root_obj(topology)->cpuset; 00714 } 00715 00725 static inline hwloc_const_cpuset_t 00726 hwloc_topology_get_online_cpuset(hwloc_topology_t topology) 00727 { 00728 return hwloc_get_root_obj(topology)->online_cpuset; 00729 } 00730 00740 static inline hwloc_const_cpuset_t 00741 hwloc_topology_get_allowed_cpuset(hwloc_topology_t topology) 00742 { 00743 return hwloc_get_root_obj(topology)->allowed_cpuset; 00744 } 00745 00762 static inline hwloc_const_nodeset_t 00763 hwloc_topology_get_complete_nodeset(hwloc_topology_t topology) 00764 { 00765 return hwloc_get_root_obj(topology)->complete_nodeset; 00766 } 00767 00778 static inline hwloc_const_nodeset_t 00779 hwloc_topology_get_topology_nodeset(hwloc_topology_t topology) 00780 { 00781 return hwloc_get_root_obj(topology)->nodeset; 00782 } 00783 00793 static inline hwloc_const_nodeset_t 00794 hwloc_topology_get_allowed_nodeset(hwloc_topology_t topology) 00795 { 00796 return hwloc_get_root_obj(topology)->allowed_nodeset; 00797 } 00798 00829 static inline void 00830 hwloc_cpuset_to_nodeset(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset) 00831 { 00832 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 00833 hwloc_obj_t obj; 00834 00835 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) { 00836 if (hwloc_bitmap_iszero(cpuset)) 00837 hwloc_bitmap_zero(nodeset); 00838 else 00839 /* Assume the whole system */ 00840 hwloc_bitmap_fill(nodeset); 00841 return; 00842 } 00843 00844 hwloc_bitmap_zero(nodeset); 00845 obj = NULL; 00846 while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL) 00847 hwloc_bitmap_set(nodeset, obj->os_index); 00848 } 00849 00857 static inline void 00858 hwloc_cpuset_to_nodeset_strict(struct hwloc_topology *topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset) 00859 { 00860 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 00861 hwloc_obj_t obj; 00862 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) 00863 return; 00864 hwloc_bitmap_zero(nodeset); 00865 obj = NULL; 00866 while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL) 00867 hwloc_bitmap_set(nodeset, obj->os_index); 00868 } 00869 00878 static inline void 00879 hwloc_cpuset_from_nodeset(hwloc_topology_t topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset) 00880 { 00881 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 00882 hwloc_obj_t obj; 00883 00884 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) { 00885 if (hwloc_bitmap_iszero(nodeset)) 00886 hwloc_bitmap_zero(cpuset); 00887 else 00888 /* Assume the whole system */ 00889 hwloc_bitmap_fill(cpuset); 00890 return; 00891 } 00892 00893 hwloc_bitmap_zero(cpuset); 00894 obj = NULL; 00895 while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL) { 00896 if (hwloc_bitmap_isset(nodeset, obj->os_index)) 00897 hwloc_bitmap_or(cpuset, cpuset, obj->cpuset); 00898 } 00899 } 00900 00908 static inline void 00909 hwloc_cpuset_from_nodeset_strict(struct hwloc_topology *topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset) 00910 { 00911 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 00912 hwloc_obj_t obj; 00913 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) 00914 return; 00915 hwloc_bitmap_zero(cpuset); 00916 obj = NULL; 00917 while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL) 00918 if (hwloc_bitmap_isset(nodeset, obj->os_index)) 00919 hwloc_bitmap_or(cpuset, cpuset, obj->cpuset); 00920 } 00921 00926 #ifdef __cplusplus 00927 } /* extern "C" */ 00928 #endif 00929 00930 00931 #endif /* HWLOC_HELPER_H */