Hardware Locality (hwloc)
1.4.1
|
00001 /* 00002 * Copyright © 2009 CNRS 00003 * Copyright © 2009-2011 inria. All rights reserved. 00004 * Copyright © 2009-2012 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 00047 static inline int 00048 hwloc_get_type_or_below_depth (hwloc_topology_t topology, hwloc_obj_type_t type) ; 00049 static inline int 00050 hwloc_get_type_or_below_depth (hwloc_topology_t topology, hwloc_obj_type_t type) 00051 { 00052 int depth = hwloc_get_type_depth(topology, type); 00053 00054 if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) 00055 return depth; 00056 00057 /* find the highest existing level with type order >= */ 00058 for(depth = hwloc_get_type_depth(topology, HWLOC_OBJ_PU); ; depth--) 00059 if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) < 0) 00060 return depth+1; 00061 00062 /* Shouldn't ever happen, as there is always a SYSTEM level with lower order and known depth. */ 00063 /* abort(); */ 00064 } 00065 00075 static inline int 00076 hwloc_get_type_or_above_depth (hwloc_topology_t topology, hwloc_obj_type_t type) ; 00077 static inline int 00078 hwloc_get_type_or_above_depth (hwloc_topology_t topology, hwloc_obj_type_t type) 00079 { 00080 int depth = hwloc_get_type_depth(topology, type); 00081 00082 if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) 00083 return depth; 00084 00085 /* find the lowest existing level with type order <= */ 00086 for(depth = 0; ; depth++) 00087 if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) > 0) 00088 return depth-1; 00089 00090 /* Shouldn't ever happen, as there is always a PU level with higher order and known depth. */ 00091 /* abort(); */ 00092 } 00093 00113 static inline hwloc_obj_t 00114 hwloc_get_root_obj (hwloc_topology_t topology) ; 00115 static inline hwloc_obj_t 00116 hwloc_get_root_obj (hwloc_topology_t topology) 00117 { 00118 return hwloc_get_obj_by_depth (topology, 0, 0); 00119 } 00120 00122 static inline hwloc_obj_t 00123 hwloc_get_ancestor_obj_by_depth (hwloc_topology_t topology , unsigned depth, hwloc_obj_t obj) ; 00124 static inline hwloc_obj_t 00125 hwloc_get_ancestor_obj_by_depth (hwloc_topology_t topology , unsigned depth, hwloc_obj_t obj) 00126 { 00127 hwloc_obj_t ancestor = obj; 00128 if (obj->depth < depth) 00129 return NULL; 00130 while (ancestor && ancestor->depth > depth) 00131 ancestor = ancestor->parent; 00132 return ancestor; 00133 } 00134 00136 static inline hwloc_obj_t 00137 hwloc_get_ancestor_obj_by_type (hwloc_topology_t topology , hwloc_obj_type_t type, hwloc_obj_t obj) ; 00138 static inline hwloc_obj_t 00139 hwloc_get_ancestor_obj_by_type (hwloc_topology_t topology , hwloc_obj_type_t type, hwloc_obj_t obj) 00140 { 00141 hwloc_obj_t ancestor = obj->parent; 00142 while (ancestor && ancestor->type != type) 00143 ancestor = ancestor->parent; 00144 return ancestor; 00145 } 00146 00151 static inline hwloc_obj_t 00152 hwloc_get_next_obj_by_depth (hwloc_topology_t topology, unsigned depth, hwloc_obj_t prev) 00153 { 00154 if (!prev) 00155 return hwloc_get_obj_by_depth (topology, depth, 0); 00156 if (prev->depth != depth) 00157 return NULL; 00158 return prev->next_cousin; 00159 } 00160 00167 static inline hwloc_obj_t 00168 hwloc_get_next_obj_by_type (hwloc_topology_t topology, hwloc_obj_type_t type, 00169 hwloc_obj_t prev) 00170 { 00171 int depth = hwloc_get_type_depth(topology, type); 00172 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00173 return NULL; 00174 return hwloc_get_next_obj_by_depth (topology, depth, prev); 00175 } 00176 00185 static inline hwloc_obj_t 00186 hwloc_get_pu_obj_by_os_index(hwloc_topology_t topology, unsigned os_index) ; 00187 static inline hwloc_obj_t 00188 hwloc_get_pu_obj_by_os_index(hwloc_topology_t topology, unsigned os_index) 00189 { 00190 hwloc_obj_t obj = NULL; 00191 while ((obj = hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_PU, obj)) != NULL) 00192 if (obj->os_index == os_index) 00193 return obj; 00194 return NULL; 00195 } 00196 00201 static inline hwloc_obj_t 00202 hwloc_get_next_child (hwloc_topology_t topology , hwloc_obj_t parent, hwloc_obj_t prev) 00203 { 00204 if (!prev) 00205 return parent->first_child; 00206 if (prev->parent != parent) 00207 return NULL; 00208 return prev->next_sibling; 00209 } 00210 00212 static inline hwloc_obj_t 00213 hwloc_get_common_ancestor_obj (hwloc_topology_t topology , hwloc_obj_t obj1, hwloc_obj_t obj2) ; 00214 static inline hwloc_obj_t 00215 hwloc_get_common_ancestor_obj (hwloc_topology_t topology , hwloc_obj_t obj1, hwloc_obj_t obj2) 00216 { 00217 /* the loop isn't so easy since intermediate ancestors may have 00218 * different depth, causing us to alternate between using obj1->parent 00219 * and obj2->parent. Also, even if at some point we find ancestors of 00220 * of the same depth, their ancestors may have different depth again. 00221 */ 00222 while (obj1 != obj2) { 00223 while (obj1->depth > obj2->depth) 00224 obj1 = obj1->parent; 00225 while (obj2->depth > obj1->depth) 00226 obj2 = obj2->parent; 00227 if (obj1 != obj2 && obj1->depth == obj2->depth) { 00228 obj1 = obj1->parent; 00229 obj2 = obj2->parent; 00230 } 00231 } 00232 return obj1; 00233 } 00234 00239 static inline int 00240 hwloc_obj_is_in_subtree (hwloc_topology_t topology , hwloc_obj_t obj, hwloc_obj_t subtree_root) ; 00241 static inline int 00242 hwloc_obj_is_in_subtree (hwloc_topology_t topology , hwloc_obj_t obj, hwloc_obj_t subtree_root) 00243 { 00244 return hwloc_bitmap_isincluded(obj->cpuset, subtree_root->cpuset); 00245 } 00246 00266 static inline hwloc_obj_t 00267 hwloc_get_first_largest_obj_inside_cpuset(hwloc_topology_t topology, hwloc_const_cpuset_t set) 00268 { 00269 hwloc_obj_t obj = hwloc_get_root_obj(topology); 00270 if (!obj->cpuset || !hwloc_bitmap_intersects(obj->cpuset, set)) 00271 return NULL; 00272 while (!hwloc_bitmap_isincluded(obj->cpuset, set)) { 00273 /* while the object intersects without being included, look at its children */ 00274 hwloc_obj_t child = NULL; 00275 while ((child = hwloc_get_next_child(topology, obj, child)) != NULL) { 00276 if (child->cpuset && hwloc_bitmap_intersects(child->cpuset, set)) 00277 break; 00278 } 00279 if (!child) 00280 /* no child intersects, return their father */ 00281 return obj; 00282 /* found one intersecting child, look at its children */ 00283 obj = child; 00284 } 00285 /* obj is included, return it */ 00286 return obj; 00287 } 00288 00296 int hwloc_get_largest_objs_inside_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00297 hwloc_obj_t * restrict objs, int max); 00298 00308 static inline hwloc_obj_t 00309 hwloc_get_next_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00310 unsigned depth, hwloc_obj_t prev) 00311 { 00312 hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev); 00313 if (!next || !next->cpuset) 00314 return NULL; 00315 while (next && !hwloc_bitmap_isincluded(next->cpuset, set)) 00316 next = next->next_cousin; 00317 return next; 00318 } 00319 00329 static inline hwloc_obj_t 00330 hwloc_get_next_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00331 hwloc_obj_type_t type, hwloc_obj_t prev) 00332 { 00333 int depth = hwloc_get_type_depth(topology, type); 00334 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00335 return NULL; 00336 return hwloc_get_next_obj_inside_cpuset_by_depth(topology, set, depth, prev); 00337 } 00338 00344 static inline hwloc_obj_t 00345 hwloc_get_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00346 unsigned depth, unsigned idx) ; 00347 static inline hwloc_obj_t 00348 hwloc_get_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00349 unsigned depth, unsigned idx) 00350 { 00351 hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0); 00352 unsigned count = 0; 00353 if (!obj || !obj->cpuset) 00354 return NULL; 00355 while (obj) { 00356 if (hwloc_bitmap_isincluded(obj->cpuset, set)) { 00357 if (count == idx) 00358 return obj; 00359 count++; 00360 } 00361 obj = obj->next_cousin; 00362 } 00363 return NULL; 00364 } 00365 00375 static inline hwloc_obj_t 00376 hwloc_get_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00377 hwloc_obj_type_t type, unsigned idx) ; 00378 static inline hwloc_obj_t 00379 hwloc_get_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00380 hwloc_obj_type_t type, unsigned idx) 00381 { 00382 int depth = hwloc_get_type_depth(topology, type); 00383 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00384 return NULL; 00385 return hwloc_get_obj_inside_cpuset_by_depth(topology, set, depth, idx); 00386 } 00387 00393 static inline unsigned 00394 hwloc_get_nbobjs_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00395 unsigned depth) ; 00396 static inline unsigned 00397 hwloc_get_nbobjs_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00398 unsigned depth) 00399 { 00400 hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0); 00401 unsigned count = 0; 00402 if (!obj || !obj->cpuset) 00403 return 0; 00404 while (obj) { 00405 if (hwloc_bitmap_isincluded(obj->cpuset, set)) 00406 count++; 00407 obj = obj->next_cousin; 00408 } 00409 return count; 00410 } 00411 00421 static inline int 00422 hwloc_get_nbobjs_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00423 hwloc_obj_type_t type) ; 00424 static inline int 00425 hwloc_get_nbobjs_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00426 hwloc_obj_type_t type) 00427 { 00428 int depth = hwloc_get_type_depth(topology, type); 00429 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) 00430 return 0; 00431 if (depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00432 return -1; /* FIXME: agregate nbobjs from different levels? */ 00433 return hwloc_get_nbobjs_inside_cpuset_by_depth(topology, set, depth); 00434 } 00435 00444 static inline int 00445 hwloc_get_obj_index_inside_cpuset (hwloc_topology_t topology , hwloc_const_cpuset_t set, 00446 hwloc_obj_t obj) ; 00447 static inline int 00448 hwloc_get_obj_index_inside_cpuset (hwloc_topology_t topology , hwloc_const_cpuset_t set, 00449 hwloc_obj_t obj) 00450 { 00451 int index = 0; 00452 if (!hwloc_bitmap_isincluded(obj->cpuset, set)) 00453 return -1; 00454 /* count how many objects are inside the cpuset on the way from us to the beginning of the level */ 00455 while ((obj = obj->prev_cousin) != NULL) 00456 if (hwloc_bitmap_isincluded(obj->cpuset, set)) 00457 index++; 00458 return index; 00459 } 00460 00475 static inline hwloc_obj_t 00476 hwloc_get_child_covering_cpuset (hwloc_topology_t topology , hwloc_const_cpuset_t set, 00477 hwloc_obj_t parent) ; 00478 static inline hwloc_obj_t 00479 hwloc_get_child_covering_cpuset (hwloc_topology_t topology , hwloc_const_cpuset_t set, 00480 hwloc_obj_t parent) 00481 { 00482 hwloc_obj_t child; 00483 if (!parent->cpuset || hwloc_bitmap_iszero(set)) 00484 return NULL; 00485 child = parent->first_child; 00486 while (child) { 00487 if (child->cpuset && hwloc_bitmap_isincluded(set, child->cpuset)) 00488 return child; 00489 child = child->next_sibling; 00490 } 00491 return NULL; 00492 } 00493 00501 static inline hwloc_obj_t 00502 hwloc_get_obj_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set) ; 00503 static inline hwloc_obj_t 00504 hwloc_get_obj_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set) 00505 { 00506 struct hwloc_obj *current = hwloc_get_root_obj(topology); 00507 if (hwloc_bitmap_iszero(set) || !current->cpuset || !hwloc_bitmap_isincluded(set, current->cpuset)) 00508 return NULL; 00509 while (1) { 00510 hwloc_obj_t child = hwloc_get_child_covering_cpuset(topology, set, current); 00511 if (!child) 00512 return current; 00513 current = child; 00514 } 00515 } 00516 00517 00536 static inline hwloc_obj_t 00537 hwloc_get_next_obj_covering_cpuset_by_depth(hwloc_topology_t topology, hwloc_const_cpuset_t set, 00538 unsigned depth, hwloc_obj_t prev) 00539 { 00540 hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev); 00541 if (!next || !next->cpuset) 00542 return NULL; 00543 while (next && !hwloc_bitmap_intersects(set, next->cpuset)) 00544 next = next->next_cousin; 00545 return next; 00546 } 00547 00563 static inline hwloc_obj_t 00564 hwloc_get_next_obj_covering_cpuset_by_type(hwloc_topology_t topology, hwloc_const_cpuset_t set, 00565 hwloc_obj_type_t type, hwloc_obj_t prev) 00566 { 00567 int depth = hwloc_get_type_depth(topology, type); 00568 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00569 return NULL; 00570 return hwloc_get_next_obj_covering_cpuset_by_depth(topology, set, depth, prev); 00571 } 00572 00588 static inline hwloc_obj_t 00589 hwloc_get_cache_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set) ; 00590 static inline hwloc_obj_t 00591 hwloc_get_cache_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set) 00592 { 00593 hwloc_obj_t current = hwloc_get_obj_covering_cpuset(topology, set); 00594 while (current) { 00595 if (current->type == HWLOC_OBJ_CACHE) 00596 return current; 00597 current = current->parent; 00598 } 00599 return NULL; 00600 } 00601 00606 static inline hwloc_obj_t 00607 hwloc_get_shared_cache_covering_obj (hwloc_topology_t topology , hwloc_obj_t obj) ; 00608 static inline hwloc_obj_t 00609 hwloc_get_shared_cache_covering_obj (hwloc_topology_t topology , hwloc_obj_t obj) 00610 { 00611 hwloc_obj_t current = obj->parent; 00612 if (!obj->cpuset) 00613 return NULL; 00614 while (current && current->cpuset) { 00615 if (!hwloc_bitmap_isequal(current->cpuset, obj->cpuset) 00616 && current->type == HWLOC_OBJ_CACHE) 00617 return current; 00618 current = current->parent; 00619 } 00620 return NULL; 00621 } 00622 00647 /* TODO: rather provide an iterator? Provide a way to know how much should be allocated? By returning the total number of objects instead? */ 00648 unsigned hwloc_get_closest_objs (hwloc_topology_t topology, hwloc_obj_t src, hwloc_obj_t * restrict objs, unsigned max); 00649 00662 static inline hwloc_obj_t 00663 hwloc_get_obj_below_by_type (hwloc_topology_t topology, 00664 hwloc_obj_type_t type1, unsigned idx1, 00665 hwloc_obj_type_t type2, unsigned idx2) ; 00666 static inline hwloc_obj_t 00667 hwloc_get_obj_below_by_type (hwloc_topology_t topology, 00668 hwloc_obj_type_t type1, unsigned idx1, 00669 hwloc_obj_type_t type2, unsigned idx2) 00670 { 00671 hwloc_obj_t obj; 00672 obj = hwloc_get_obj_by_type (topology, type1, idx1); 00673 if (!obj || !obj->cpuset) 00674 return NULL; 00675 return hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, type2, idx2); 00676 } 00677 00696 static inline hwloc_obj_t 00697 hwloc_get_obj_below_array_by_type (hwloc_topology_t topology, int nr, hwloc_obj_type_t *typev, unsigned *idxv) ; 00698 static inline hwloc_obj_t 00699 hwloc_get_obj_below_array_by_type (hwloc_topology_t topology, int nr, hwloc_obj_type_t *typev, unsigned *idxv) 00700 { 00701 hwloc_obj_t obj = hwloc_get_root_obj(topology); 00702 int i; 00703 for(i=0; i<nr; i++) { 00704 if (!obj || !obj->cpuset) 00705 return NULL; 00706 obj = hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, typev[i], idxv[i]); 00707 } 00708 return obj; 00709 } 00710 00734 static inline void 00735 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *root, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until); 00736 static inline void 00737 hwloc_distribute(hwloc_topology_t topology, hwloc_obj_t root, hwloc_cpuset_t *cpuset, unsigned n, unsigned until) 00738 { 00739 unsigned i; 00740 if (!root->arity || n == 1 || root->depth >= until) { 00741 /* Got to the bottom, we can't split any more, put everything there. */ 00742 for (i=0; i<n; i++) 00743 cpuset[i] = hwloc_bitmap_dup(root->cpuset); 00744 return; 00745 } 00746 hwloc_distributev(topology, root->children, root->arity, cpuset, n, until); 00747 } 00748 00756 static inline void 00757 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *roots, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until) 00758 { 00759 unsigned i; 00760 unsigned tot_weight; 00761 hwloc_cpuset_t *cpusetp = cpuset; 00762 00763 tot_weight = 0; 00764 for (i = 0; i < n_roots; i++) 00765 if (roots[i]->cpuset) 00766 tot_weight += hwloc_bitmap_weight(roots[i]->cpuset); 00767 00768 for (i = 0; i < n_roots && tot_weight; i++) { 00769 /* Give to roots[i] a portion proportional to its weight */ 00770 unsigned weight = roots[i]->cpuset ? hwloc_bitmap_weight(roots[i]->cpuset) : 0; 00771 unsigned chunk = (n * weight + tot_weight-1) / tot_weight; 00772 hwloc_distribute(topology, roots[i], cpusetp, chunk, until); 00773 cpusetp += chunk; 00774 tot_weight -= weight; 00775 n -= chunk; 00776 } 00777 } 00778 00785 static inline void * 00786 hwloc_alloc_membind_policy_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) 00787 { 00788 void *p = hwloc_alloc_membind_nodeset(topology, len, nodeset, policy, flags); 00789 if (p) 00790 return p; 00791 hwloc_set_membind_nodeset(topology, nodeset, policy, flags); 00792 p = hwloc_alloc(topology, len); 00793 if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH) 00794 /* Enforce the binding by touching the data */ 00795 memset(p, 0, len); 00796 return p; 00797 } 00798 00803 static inline void * 00804 hwloc_alloc_membind_policy(hwloc_topology_t topology, size_t len, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags) 00805 { 00806 void *p = hwloc_alloc_membind(topology, len, cpuset, policy, flags); 00807 if (p) 00808 return p; 00809 hwloc_set_membind(topology, cpuset, policy, flags); 00810 p = hwloc_alloc(topology, len); 00811 if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH) 00812 /* Enforce the binding by touching the data */ 00813 memset(p, 0, len); 00814 return p; 00815 } 00816 00833 static inline hwloc_const_cpuset_t 00834 hwloc_topology_get_complete_cpuset(hwloc_topology_t topology) ; 00835 static inline hwloc_const_cpuset_t 00836 hwloc_topology_get_complete_cpuset(hwloc_topology_t topology) 00837 { 00838 return hwloc_get_root_obj(topology)->complete_cpuset; 00839 } 00840 00851 static inline hwloc_const_cpuset_t 00852 hwloc_topology_get_topology_cpuset(hwloc_topology_t topology) ; 00853 static inline hwloc_const_cpuset_t 00854 hwloc_topology_get_topology_cpuset(hwloc_topology_t topology) 00855 { 00856 return hwloc_get_root_obj(topology)->cpuset; 00857 } 00858 00868 static inline hwloc_const_cpuset_t 00869 hwloc_topology_get_online_cpuset(hwloc_topology_t topology) ; 00870 static inline hwloc_const_cpuset_t 00871 hwloc_topology_get_online_cpuset(hwloc_topology_t topology) 00872 { 00873 return hwloc_get_root_obj(topology)->online_cpuset; 00874 } 00875 00885 static inline hwloc_const_cpuset_t 00886 hwloc_topology_get_allowed_cpuset(hwloc_topology_t topology) ; 00887 static inline hwloc_const_cpuset_t 00888 hwloc_topology_get_allowed_cpuset(hwloc_topology_t topology) 00889 { 00890 return hwloc_get_root_obj(topology)->allowed_cpuset; 00891 } 00892 00909 static inline hwloc_const_nodeset_t 00910 hwloc_topology_get_complete_nodeset(hwloc_topology_t topology) ; 00911 static inline hwloc_const_nodeset_t 00912 hwloc_topology_get_complete_nodeset(hwloc_topology_t topology) 00913 { 00914 return hwloc_get_root_obj(topology)->complete_nodeset; 00915 } 00916 00927 static inline hwloc_const_nodeset_t 00928 hwloc_topology_get_topology_nodeset(hwloc_topology_t topology) ; 00929 static inline hwloc_const_nodeset_t 00930 hwloc_topology_get_topology_nodeset(hwloc_topology_t topology) 00931 { 00932 return hwloc_get_root_obj(topology)->nodeset; 00933 } 00934 00944 static inline hwloc_const_nodeset_t 00945 hwloc_topology_get_allowed_nodeset(hwloc_topology_t topology) ; 00946 static inline hwloc_const_nodeset_t 00947 hwloc_topology_get_allowed_nodeset(hwloc_topology_t topology) 00948 { 00949 return hwloc_get_root_obj(topology)->allowed_nodeset; 00950 } 00951 00982 static inline void 00983 hwloc_cpuset_to_nodeset(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset) 00984 { 00985 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 00986 hwloc_obj_t obj; 00987 00988 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) { 00989 if (hwloc_bitmap_iszero(cpuset)) 00990 hwloc_bitmap_zero(nodeset); 00991 else 00992 /* Assume the whole system */ 00993 hwloc_bitmap_fill(nodeset); 00994 return; 00995 } 00996 00997 hwloc_bitmap_zero(nodeset); 00998 obj = NULL; 00999 while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL) 01000 hwloc_bitmap_set(nodeset, obj->os_index); 01001 } 01002 01010 static inline void 01011 hwloc_cpuset_to_nodeset_strict(struct hwloc_topology *topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset) 01012 { 01013 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 01014 hwloc_obj_t obj; 01015 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) 01016 return; 01017 hwloc_bitmap_zero(nodeset); 01018 obj = NULL; 01019 while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL) 01020 hwloc_bitmap_set(nodeset, obj->os_index); 01021 } 01022 01031 static inline void 01032 hwloc_cpuset_from_nodeset(hwloc_topology_t topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset) 01033 { 01034 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 01035 hwloc_obj_t obj; 01036 01037 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) { 01038 if (hwloc_bitmap_iszero(nodeset)) 01039 hwloc_bitmap_zero(cpuset); 01040 else 01041 /* Assume the whole system */ 01042 hwloc_bitmap_fill(cpuset); 01043 return; 01044 } 01045 01046 hwloc_bitmap_zero(cpuset); 01047 obj = NULL; 01048 while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL) { 01049 if (hwloc_bitmap_isset(nodeset, obj->os_index)) 01050 /* no need to check obj->cpuset because objects in levels always have a cpuset */ 01051 hwloc_bitmap_or(cpuset, cpuset, obj->cpuset); 01052 } 01053 } 01054 01062 static inline void 01063 hwloc_cpuset_from_nodeset_strict(struct hwloc_topology *topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset) 01064 { 01065 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 01066 hwloc_obj_t obj; 01067 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) 01068 return; 01069 hwloc_bitmap_zero(cpuset); 01070 obj = NULL; 01071 while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL) 01072 if (hwloc_bitmap_isset(nodeset, obj->os_index)) 01073 /* no need to check obj->cpuset because objects in levels always have a cpuset */ 01074 hwloc_bitmap_or(cpuset, cpuset, obj->cpuset); 01075 } 01076 01104 static inline const struct hwloc_distances_s * 01105 hwloc_get_whole_distance_matrix_by_depth(hwloc_topology_t topology, unsigned depth) 01106 { 01107 hwloc_obj_t root = hwloc_get_root_obj(topology); 01108 unsigned i; 01109 for(i=0; i<root->distances_count; i++) 01110 if (root->distances[i]->relative_depth == depth) 01111 return root->distances[i]; 01112 return NULL; 01113 } 01114 01134 static inline const struct hwloc_distances_s * 01135 hwloc_get_whole_distance_matrix_by_type(hwloc_topology_t topology, hwloc_obj_type_t type) 01136 { 01137 int depth = hwloc_get_type_depth(topology, type); 01138 if (depth < 0) 01139 return NULL; 01140 return hwloc_get_whole_distance_matrix_by_depth(topology, depth); 01141 } 01142 01156 static inline const struct hwloc_distances_s * 01157 hwloc_get_distance_matrix_covering_obj_by_depth(hwloc_topology_t topology, 01158 hwloc_obj_t obj, unsigned depth, 01159 unsigned *firstp) 01160 { 01161 while (obj && obj->cpuset) { 01162 unsigned i; 01163 for(i=0; i<obj->distances_count; i++) 01164 if (obj->distances[i]->relative_depth == depth - obj->depth) { 01165 if (!obj->distances[i]->nbobjs) 01166 continue; 01167 *firstp = hwloc_get_next_obj_inside_cpuset_by_depth(topology, obj->cpuset, depth, NULL)->logical_index; 01168 return obj->distances[i]; 01169 } 01170 obj = obj->parent; 01171 } 01172 return NULL; 01173 } 01174 01186 static inline int 01187 hwloc_get_latency(hwloc_topology_t topology, 01188 hwloc_obj_t obj1, hwloc_obj_t obj2, 01189 float *latency, float *reverse_latency) 01190 { 01191 hwloc_obj_t ancestor; 01192 const struct hwloc_distances_s * distances; 01193 unsigned first_logical ; 01194 01195 if (obj1->depth != obj2->depth) { 01196 errno = EINVAL; 01197 return -1; 01198 } 01199 01200 ancestor = hwloc_get_common_ancestor_obj(topology, obj1, obj2); 01201 distances = hwloc_get_distance_matrix_covering_obj_by_depth(topology, ancestor, obj1->depth, &first_logical); 01202 if (distances && distances->latency) { 01203 const float * latency_matrix = distances->latency; 01204 unsigned nbobjs = distances->nbobjs; 01205 unsigned l1 = obj1->logical_index - first_logical; 01206 unsigned l2 = obj2->logical_index - first_logical; 01207 *latency = latency_matrix[l1*nbobjs+l2]; 01208 *reverse_latency = latency_matrix[l2*nbobjs+l1]; 01209 return 0; 01210 } 01211 01212 errno = ENOSYS; 01213 return -1; 01214 } 01215 01230 static inline hwloc_obj_t 01231 hwloc_get_non_io_ancestor_obj(hwloc_topology_t topology , 01232 hwloc_obj_t ioobj) 01233 { 01234 hwloc_obj_t obj = ioobj; 01235 while (obj && !obj->cpuset) { 01236 obj = obj->parent; 01237 } 01238 return obj; 01239 } 01240 01245 static inline hwloc_obj_t 01246 hwloc_get_next_pcidev(hwloc_topology_t topology, hwloc_obj_t prev) 01247 { 01248 return hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_PCI_DEVICE, prev); 01249 } 01250 01254 static inline hwloc_obj_t 01255 hwloc_get_pcidev_by_busid(hwloc_topology_t topology, 01256 unsigned domain, unsigned bus, unsigned dev, unsigned func) 01257 { 01258 hwloc_obj_t obj = NULL; 01259 while ((obj = hwloc_get_next_pcidev(topology, obj)) != NULL) { 01260 if (obj->attr->pcidev.domain == domain 01261 && obj->attr->pcidev.bus == bus 01262 && obj->attr->pcidev.dev == dev 01263 && obj->attr->pcidev.func == func) 01264 return obj; 01265 } 01266 return NULL; 01267 } 01268 01272 static inline hwloc_obj_t 01273 hwloc_get_pcidev_by_busidstring(hwloc_topology_t topology, const char *busid) 01274 { 01275 unsigned domain = 0; /* default */ 01276 unsigned bus, dev, func; 01277 01278 if (sscanf(busid, "%x:%x.%x", &bus, &dev, &func) != 3 01279 && sscanf(busid, "%x:%x:%x.%x", &domain, &bus, &dev, &func) != 4) { 01280 errno = EINVAL; 01281 return NULL; 01282 } 01283 01284 return hwloc_get_pcidev_by_busid(topology, domain, bus, dev, func); 01285 } 01286 01291 static inline hwloc_obj_t 01292 hwloc_get_next_osdev(hwloc_topology_t topology, hwloc_obj_t prev) 01293 { 01294 return hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_OS_DEVICE, prev); 01295 } 01296 01301 static inline hwloc_obj_t 01302 hwloc_get_next_bridge(hwloc_topology_t topology, hwloc_obj_t prev) 01303 { 01304 return hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_BRIDGE, prev); 01305 } 01306 01307 /* \brief Checks whether a given bridge covers a given PCI bus. 01308 */ 01309 static inline int 01310 hwloc_bridge_covers_pcibus(hwloc_obj_t bridge, 01311 unsigned domain, unsigned bus) 01312 { 01313 return bridge->type == HWLOC_OBJ_BRIDGE 01314 && bridge->attr->bridge.downstream_type == HWLOC_OBJ_BRIDGE_PCI 01315 && bridge->attr->bridge.downstream.pci.domain == domain 01316 && bridge->attr->bridge.downstream.pci.secondary_bus <= bus 01317 && bridge->attr->bridge.downstream.pci.subordinate_bus >= bus; 01318 } 01319 01325 static inline hwloc_obj_t 01326 hwloc_get_hostbridge_by_pcibus(hwloc_topology_t topology, 01327 unsigned domain, unsigned bus) 01328 { 01329 hwloc_obj_t obj = NULL; 01330 while ((obj = hwloc_get_next_bridge(topology, obj)) != NULL) { 01331 if (hwloc_bridge_covers_pcibus(obj, domain, bus)) { 01332 /* found bridge covering this pcibus, make sure it's a hostbridge */ 01333 assert(obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_HOST); 01334 assert(obj->parent->type != HWLOC_OBJ_BRIDGE); 01335 assert(obj->parent->cpuset); 01336 return obj; 01337 } 01338 } 01339 return NULL; 01340 } 01341 01346 #ifdef __cplusplus 01347 } /* extern "C" */ 01348 #endif 01349 01350 01351 #endif /* HWLOC_HELPER_H */