Hardware Locality (hwloc) 1.3.1
|
00001 /* 00002 * Copyright © 2009 CNRS 00003 * Copyright © 2009-2011 INRIA. All rights reserved. 00004 * Copyright © 2009-2011 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 { 00050 int depth = hwloc_get_type_depth(topology, type); 00051 00052 if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) 00053 return depth; 00054 00055 /* find the highest existing level with type order >= */ 00056 for(depth = hwloc_get_type_depth(topology, HWLOC_OBJ_PU); ; depth--) 00057 if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) < 0) 00058 return depth+1; 00059 00060 /* Shouldn't ever happen, as there is always a SYSTEM level with lower order and known depth. */ 00061 /* abort(); */ 00062 } 00063 00073 static inline int 00074 hwloc_get_type_or_above_depth (hwloc_topology_t topology, hwloc_obj_type_t type) 00075 { 00076 int depth = hwloc_get_type_depth(topology, type); 00077 00078 if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) 00079 return depth; 00080 00081 /* find the lowest existing level with type order <= */ 00082 for(depth = 0; ; depth++) 00083 if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) > 0) 00084 return depth-1; 00085 00086 /* Shouldn't ever happen, as there is always a PU level with higher order and known depth. */ 00087 /* abort(); */ 00088 } 00089 00109 static inline hwloc_obj_t 00110 hwloc_get_root_obj (hwloc_topology_t topology) 00111 { 00112 return hwloc_get_obj_by_depth (topology, 0, 0); 00113 } 00114 00116 static inline hwloc_obj_t 00117 hwloc_get_ancestor_obj_by_depth (hwloc_topology_t topology , unsigned depth, hwloc_obj_t obj) 00118 { 00119 hwloc_obj_t ancestor = obj; 00120 if (obj->depth < depth) 00121 return NULL; 00122 while (ancestor && ancestor->depth > depth) 00123 ancestor = ancestor->parent; 00124 return ancestor; 00125 } 00126 00128 static inline hwloc_obj_t 00129 hwloc_get_ancestor_obj_by_type (hwloc_topology_t topology , hwloc_obj_type_t type, hwloc_obj_t obj) 00130 { 00131 hwloc_obj_t ancestor = obj->parent; 00132 while (ancestor && ancestor->type != type) 00133 ancestor = ancestor->parent; 00134 return ancestor; 00135 } 00136 00141 static inline hwloc_obj_t 00142 hwloc_get_next_obj_by_depth (hwloc_topology_t topology, unsigned depth, hwloc_obj_t prev) 00143 { 00144 if (!prev) 00145 return hwloc_get_obj_by_depth (topology, depth, 0); 00146 if (prev->depth != depth) 00147 return NULL; 00148 return prev->next_cousin; 00149 } 00150 00157 static inline hwloc_obj_t 00158 hwloc_get_next_obj_by_type (hwloc_topology_t topology, hwloc_obj_type_t type, 00159 hwloc_obj_t prev) 00160 { 00161 int depth = hwloc_get_type_depth(topology, type); 00162 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00163 return NULL; 00164 return hwloc_get_next_obj_by_depth (topology, depth, prev); 00165 } 00166 00175 static inline hwloc_obj_t 00176 hwloc_get_pu_obj_by_os_index(hwloc_topology_t topology, unsigned os_index) 00177 { 00178 hwloc_obj_t obj = NULL; 00179 while ((obj = hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_PU, obj)) != NULL) 00180 if (obj->os_index == os_index) 00181 return obj; 00182 return NULL; 00183 } 00184 00189 static inline hwloc_obj_t 00190 hwloc_get_next_child (hwloc_topology_t topology , hwloc_obj_t parent, hwloc_obj_t prev) 00191 { 00192 if (!prev) 00193 return parent->first_child; 00194 if (prev->parent != parent) 00195 return NULL; 00196 return prev->next_sibling; 00197 } 00198 00200 static inline hwloc_obj_t 00201 hwloc_get_common_ancestor_obj (hwloc_topology_t topology , hwloc_obj_t obj1, hwloc_obj_t obj2) 00202 { 00203 /* the loop isn't so easy since intermediate ancestors may have 00204 * different depth, causing us to alternate between using obj1->parent 00205 * and obj2->parent. Also, even if at some point we find ancestors of 00206 * of the same depth, their ancestors may have different depth again. 00207 */ 00208 while (obj1 != obj2) { 00209 while (obj1->depth > obj2->depth) 00210 obj1 = obj1->parent; 00211 while (obj2->depth > obj1->depth) 00212 obj2 = obj2->parent; 00213 if (obj1 != obj2 && obj1->depth == obj2->depth) { 00214 obj1 = obj1->parent; 00215 obj2 = obj2->parent; 00216 } 00217 } 00218 return obj1; 00219 } 00220 00225 static inline int 00226 hwloc_obj_is_in_subtree (hwloc_topology_t topology , hwloc_obj_t obj, hwloc_obj_t subtree_root) 00227 { 00228 return hwloc_bitmap_isincluded(obj->cpuset, subtree_root->cpuset); 00229 } 00230 00247 static inline hwloc_obj_t 00248 hwloc_get_first_largest_obj_inside_cpuset(hwloc_topology_t topology, hwloc_const_cpuset_t set) 00249 { 00250 hwloc_obj_t obj = hwloc_get_root_obj(topology); 00251 /* FIXME: what if !root->cpuset? */ 00252 if (!hwloc_bitmap_intersects(obj->cpuset, set)) 00253 return NULL; 00254 while (!hwloc_bitmap_isincluded(obj->cpuset, set)) { 00255 /* while the object intersects without being included, look at its children */ 00256 hwloc_obj_t child = NULL; 00257 while ((child = hwloc_get_next_child(topology, obj, child)) != NULL) { 00258 if (child->cpuset && hwloc_bitmap_intersects(child->cpuset, set)) 00259 break; 00260 } 00261 if (!child) 00262 /* no child intersects, return their father */ 00263 return obj; 00264 /* found one intersecting child, look at its children */ 00265 obj = child; 00266 } 00267 /* obj is included, return it */ 00268 return obj; 00269 } 00270 00275 int hwloc_get_largest_objs_inside_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00276 hwloc_obj_t * restrict objs, int max); 00277 00284 static inline hwloc_obj_t 00285 hwloc_get_next_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00286 unsigned depth, hwloc_obj_t prev) 00287 { 00288 hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev); 00289 /* no need to check next->cpuset because objects in levels always have a cpuset */ 00290 while (next && !hwloc_bitmap_isincluded(next->cpuset, set)) 00291 next = next->next_cousin; 00292 return next; 00293 } 00294 00301 static inline hwloc_obj_t 00302 hwloc_get_next_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00303 hwloc_obj_type_t type, hwloc_obj_t prev) 00304 { 00305 int depth = hwloc_get_type_depth(topology, type); 00306 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00307 return NULL; 00308 return hwloc_get_next_obj_inside_cpuset_by_depth(topology, set, depth, prev); 00309 } 00310 00313 static inline hwloc_obj_t 00314 hwloc_get_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00315 unsigned depth, unsigned idx) 00316 { 00317 unsigned count = 0; 00318 hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0); 00319 while (obj) { 00320 /* no need to check obj->cpuset because objects in levels always have a cpuset */ 00321 if (hwloc_bitmap_isincluded(obj->cpuset, set)) { 00322 if (count == idx) 00323 return obj; 00324 count++; 00325 } 00326 obj = obj->next_cousin; 00327 } 00328 return NULL; 00329 } 00330 00337 static inline hwloc_obj_t 00338 hwloc_get_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00339 hwloc_obj_type_t type, unsigned idx) 00340 { 00341 int depth = hwloc_get_type_depth(topology, type); 00342 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00343 return NULL; 00344 return hwloc_get_obj_inside_cpuset_by_depth(topology, set, depth, idx); 00345 } 00346 00348 static inline unsigned 00349 hwloc_get_nbobjs_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00350 unsigned depth) 00351 { 00352 hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0); 00353 int count = 0; 00354 while (obj) { 00355 /* no need to check obj->cpuset because objects in levels always have a cpuset */ 00356 if (hwloc_bitmap_isincluded(obj->cpuset, set)) 00357 count++; 00358 obj = obj->next_cousin; 00359 } 00360 return count; 00361 } 00362 00369 static inline int 00370 hwloc_get_nbobjs_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00371 hwloc_obj_type_t type) 00372 { 00373 int depth = hwloc_get_type_depth(topology, type); 00374 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) 00375 return 0; 00376 if (depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00377 return -1; /* FIXME: agregate nbobjs from different levels? */ 00378 return hwloc_get_nbobjs_inside_cpuset_by_depth(topology, set, depth); 00379 } 00380 00393 static inline hwloc_obj_t 00394 hwloc_get_child_covering_cpuset (hwloc_topology_t topology , hwloc_const_cpuset_t set, 00395 hwloc_obj_t parent) 00396 { 00397 hwloc_obj_t child; 00398 00399 if (hwloc_bitmap_iszero(set)) 00400 return NULL; 00401 00402 child = parent->first_child; 00403 while (child) { 00404 if (child->cpuset && hwloc_bitmap_isincluded(set, child->cpuset)) 00405 return child; 00406 child = child->next_sibling; 00407 } 00408 return NULL; 00409 } 00410 00415 static inline hwloc_obj_t 00416 hwloc_get_obj_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set) 00417 { 00418 struct hwloc_obj *current = hwloc_get_root_obj(topology); 00419 00420 if (hwloc_bitmap_iszero(set)) 00421 return NULL; 00422 00423 /* FIXME: what if !root->cpuset? */ 00424 if (!hwloc_bitmap_isincluded(set, current->cpuset)) 00425 return NULL; 00426 00427 while (1) { 00428 hwloc_obj_t child = hwloc_get_child_covering_cpuset(topology, set, current); 00429 if (!child) 00430 return current; 00431 current = child; 00432 } 00433 } 00434 00435 00451 static inline hwloc_obj_t 00452 hwloc_get_next_obj_covering_cpuset_by_depth(hwloc_topology_t topology, hwloc_const_cpuset_t set, 00453 unsigned depth, hwloc_obj_t prev) 00454 { 00455 hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev); 00456 /* no need to check next->cpuset because objects in levels always have a cpuset */ 00457 while (next && !hwloc_bitmap_intersects(set, next->cpuset)) 00458 next = next->next_cousin; 00459 return next; 00460 } 00461 00474 static inline hwloc_obj_t 00475 hwloc_get_next_obj_covering_cpuset_by_type(hwloc_topology_t topology, hwloc_const_cpuset_t set, 00476 hwloc_obj_type_t type, hwloc_obj_t prev) 00477 { 00478 int depth = hwloc_get_type_depth(topology, type); 00479 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00480 return NULL; 00481 return hwloc_get_next_obj_covering_cpuset_by_depth(topology, set, depth, prev); 00482 } 00483 00496 static inline hwloc_obj_t 00497 hwloc_get_cache_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set) 00498 { 00499 hwloc_obj_t current = hwloc_get_obj_covering_cpuset(topology, set); 00500 while (current) { 00501 if (current->type == HWLOC_OBJ_CACHE) 00502 return current; 00503 current = current->parent; 00504 } 00505 return NULL; 00506 } 00507 00512 static inline hwloc_obj_t 00513 hwloc_get_shared_cache_covering_obj (hwloc_topology_t topology , hwloc_obj_t obj) 00514 { 00515 hwloc_obj_t current = obj->parent; 00516 if (!obj->cpuset) 00517 return NULL; 00518 while (current && current->cpuset) { 00519 if (!hwloc_bitmap_isequal(current->cpuset, obj->cpuset) 00520 && current->type == HWLOC_OBJ_CACHE) 00521 return current; 00522 current = current->parent; 00523 } 00524 return NULL; 00525 } 00526 00549 /* TODO: rather provide an iterator? Provide a way to know how much should be allocated? By returning the total number of objects instead? */ 00550 unsigned hwloc_get_closest_objs (hwloc_topology_t topology, hwloc_obj_t src, hwloc_obj_t * restrict objs, unsigned max); 00551 00562 static inline hwloc_obj_t 00563 hwloc_get_obj_below_by_type (hwloc_topology_t topology, 00564 hwloc_obj_type_t type1, unsigned idx1, 00565 hwloc_obj_type_t type2, unsigned idx2) 00566 { 00567 hwloc_obj_t obj; 00568 00569 obj = hwloc_get_obj_by_type (topology, type1, idx1); 00570 if (!obj) 00571 return NULL; 00572 00573 return hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, type2, idx2); 00574 } 00575 00591 static inline hwloc_obj_t 00592 hwloc_get_obj_below_array_by_type (hwloc_topology_t topology, int nr, hwloc_obj_type_t *typev, unsigned *idxv) 00593 { 00594 hwloc_obj_t obj = hwloc_get_root_obj(topology); 00595 int i; 00596 00597 /* FIXME: what if !root->cpuset? */ 00598 for(i=0; i<nr; i++) { 00599 obj = hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, typev[i], idxv[i]); 00600 if (!obj) 00601 return NULL; 00602 } 00603 00604 return obj; 00605 } 00606 00628 static inline void 00629 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *root, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until); 00630 static inline void 00631 hwloc_distribute(hwloc_topology_t topology, hwloc_obj_t root, hwloc_cpuset_t *cpuset, unsigned n, unsigned until) 00632 { 00633 unsigned i; 00634 00635 /* FIXME: what if !root->cpuset? */ 00636 if (!root->arity || n == 1 || root->depth >= until) { 00637 /* Got to the bottom, we can't split any more, put everything there. */ 00638 for (i=0; i<n; i++) 00639 cpuset[i] = hwloc_bitmap_dup(root->cpuset); 00640 return; 00641 } 00642 00643 hwloc_distributev(topology, root->children, root->arity, cpuset, n, until); 00644 } 00645 00651 static inline void 00652 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *roots, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until) 00653 { 00654 unsigned i; 00655 unsigned tot_weight; 00656 hwloc_cpuset_t *cpusetp = cpuset; 00657 00658 tot_weight = 0; 00659 for (i = 0; i < n_roots; i++) 00660 if (roots[i]->cpuset) 00661 tot_weight += hwloc_bitmap_weight(roots[i]->cpuset); 00662 00663 for (i = 0; i < n_roots && tot_weight; i++) { 00664 /* Give to roots[i] a portion proportional to its weight */ 00665 unsigned weight = roots[i]->cpuset ? hwloc_bitmap_weight(roots[i]->cpuset) : 0; 00666 unsigned chunk = (n * weight + tot_weight-1) / tot_weight; 00667 hwloc_distribute(topology, roots[i], cpusetp, chunk, until); 00668 cpusetp += chunk; 00669 tot_weight -= weight; 00670 n -= chunk; 00671 } 00672 } 00673 00680 static inline void * 00681 hwloc_alloc_membind_policy_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) 00682 { 00683 void *p = hwloc_alloc_membind_nodeset(topology, len, nodeset, policy, flags); 00684 if (p) 00685 return p; 00686 hwloc_set_membind_nodeset(topology, nodeset, policy, flags); 00687 p = hwloc_alloc(topology, len); 00688 if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH) 00689 /* Enforce the binding by touching the data */ 00690 memset(p, 0, len); 00691 return p; 00692 } 00693 00698 static inline void * 00699 hwloc_alloc_membind_policy(hwloc_topology_t topology, size_t len, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags) 00700 { 00701 void *p = hwloc_alloc_membind(topology, len, cpuset, policy, flags); 00702 if (p) 00703 return p; 00704 hwloc_set_membind(topology, cpuset, policy, flags); 00705 p = hwloc_alloc(topology, len); 00706 if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH) 00707 /* Enforce the binding by touching the data */ 00708 memset(p, 0, len); 00709 return p; 00710 } 00711 00728 static inline hwloc_const_cpuset_t 00729 hwloc_topology_get_complete_cpuset(hwloc_topology_t topology) 00730 { 00731 return hwloc_get_root_obj(topology)->complete_cpuset; 00732 } 00733 00744 static inline hwloc_const_cpuset_t 00745 hwloc_topology_get_topology_cpuset(hwloc_topology_t topology) 00746 { 00747 return hwloc_get_root_obj(topology)->cpuset; 00748 } 00749 00759 static inline hwloc_const_cpuset_t 00760 hwloc_topology_get_online_cpuset(hwloc_topology_t topology) 00761 { 00762 return hwloc_get_root_obj(topology)->online_cpuset; 00763 } 00764 00774 static inline hwloc_const_cpuset_t 00775 hwloc_topology_get_allowed_cpuset(hwloc_topology_t topology) 00776 { 00777 return hwloc_get_root_obj(topology)->allowed_cpuset; 00778 } 00779 00796 static inline hwloc_const_nodeset_t 00797 hwloc_topology_get_complete_nodeset(hwloc_topology_t topology) 00798 { 00799 return hwloc_get_root_obj(topology)->complete_nodeset; 00800 } 00801 00812 static inline hwloc_const_nodeset_t 00813 hwloc_topology_get_topology_nodeset(hwloc_topology_t topology) 00814 { 00815 return hwloc_get_root_obj(topology)->nodeset; 00816 } 00817 00827 static inline hwloc_const_nodeset_t 00828 hwloc_topology_get_allowed_nodeset(hwloc_topology_t topology) 00829 { 00830 return hwloc_get_root_obj(topology)->allowed_nodeset; 00831 } 00832 00863 static inline void 00864 hwloc_cpuset_to_nodeset(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset) 00865 { 00866 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 00867 hwloc_obj_t obj; 00868 00869 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) { 00870 if (hwloc_bitmap_iszero(cpuset)) 00871 hwloc_bitmap_zero(nodeset); 00872 else 00873 /* Assume the whole system */ 00874 hwloc_bitmap_fill(nodeset); 00875 return; 00876 } 00877 00878 hwloc_bitmap_zero(nodeset); 00879 obj = NULL; 00880 while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL) 00881 hwloc_bitmap_set(nodeset, obj->os_index); 00882 } 00883 00891 static inline void 00892 hwloc_cpuset_to_nodeset_strict(struct hwloc_topology *topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset) 00893 { 00894 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 00895 hwloc_obj_t obj; 00896 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) 00897 return; 00898 hwloc_bitmap_zero(nodeset); 00899 obj = NULL; 00900 while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL) 00901 hwloc_bitmap_set(nodeset, obj->os_index); 00902 } 00903 00912 static inline void 00913 hwloc_cpuset_from_nodeset(hwloc_topology_t topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset) 00914 { 00915 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 00916 hwloc_obj_t obj; 00917 00918 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) { 00919 if (hwloc_bitmap_iszero(nodeset)) 00920 hwloc_bitmap_zero(cpuset); 00921 else 00922 /* Assume the whole system */ 00923 hwloc_bitmap_fill(cpuset); 00924 return; 00925 } 00926 00927 hwloc_bitmap_zero(cpuset); 00928 obj = NULL; 00929 while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL) { 00930 if (hwloc_bitmap_isset(nodeset, obj->os_index)) 00931 /* no need to check obj->cpuset because objects in levels always have a cpuset */ 00932 hwloc_bitmap_or(cpuset, cpuset, obj->cpuset); 00933 } 00934 } 00935 00943 static inline void 00944 hwloc_cpuset_from_nodeset_strict(struct hwloc_topology *topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset) 00945 { 00946 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 00947 hwloc_obj_t obj; 00948 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) 00949 return; 00950 hwloc_bitmap_zero(cpuset); 00951 obj = NULL; 00952 while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL) 00953 if (hwloc_bitmap_isset(nodeset, obj->os_index)) 00954 /* no need to check obj->cpuset because objects in levels always have a cpuset */ 00955 hwloc_bitmap_or(cpuset, cpuset, obj->cpuset); 00956 } 00957 00985 static inline const struct hwloc_distances_s * 00986 hwloc_get_whole_distance_matrix_by_depth(hwloc_topology_t topology, unsigned depth) 00987 { 00988 hwloc_obj_t root = hwloc_get_root_obj(topology); 00989 unsigned i; 00990 for(i=0; i<root->distances_count; i++) 00991 if (root->distances[i]->relative_depth == depth) 00992 return root->distances[i]; 00993 return NULL; 00994 } 00995 01015 static inline const struct hwloc_distances_s * 01016 hwloc_get_whole_distance_matrix_by_type(hwloc_topology_t topology, hwloc_obj_type_t type) 01017 { 01018 int depth = hwloc_get_type_depth(topology, type); 01019 if (depth < 0) 01020 return NULL; 01021 return hwloc_get_whole_distance_matrix_by_depth(topology, depth); 01022 } 01023 01037 static inline const struct hwloc_distances_s * 01038 hwloc_get_distance_matrix_covering_obj_by_depth(hwloc_topology_t topology, 01039 hwloc_obj_t obj, unsigned depth, 01040 unsigned *firstp) 01041 { 01042 while (obj && obj->cpuset) { 01043 unsigned i; 01044 for(i=0; i<obj->distances_count; i++) 01045 if (obj->distances[i]->relative_depth == depth - obj->depth) { 01046 if (!obj->distances[i]->nbobjs) 01047 continue; 01048 *firstp = hwloc_get_next_obj_inside_cpuset_by_depth(topology, obj->cpuset, depth, NULL)->logical_index; 01049 return obj->distances[i]; 01050 } 01051 obj = obj->parent; 01052 } 01053 return NULL; 01054 } 01055 01067 static inline int 01068 hwloc_get_latency(hwloc_topology_t topology, 01069 hwloc_obj_t obj1, hwloc_obj_t obj2, 01070 float *latency, float *reverse_latency) 01071 { 01072 hwloc_obj_t ancestor; 01073 const struct hwloc_distances_s * distances; 01074 unsigned first_logical ; 01075 01076 if (obj1->depth != obj2->depth) { 01077 errno = EINVAL; 01078 return -1; 01079 } 01080 01081 ancestor = hwloc_get_common_ancestor_obj(topology, obj1, obj2); 01082 distances = hwloc_get_distance_matrix_covering_obj_by_depth(topology, ancestor, obj1->depth, &first_logical); 01083 if (distances && distances->latency) { 01084 const float * latency_matrix = distances->latency; 01085 unsigned nbobjs = distances->nbobjs; 01086 unsigned l1 = obj1->logical_index - first_logical; 01087 unsigned l2 = obj2->logical_index - first_logical; 01088 *latency = latency_matrix[l1*nbobjs+l2]; 01089 *reverse_latency = latency_matrix[l2*nbobjs+l1]; 01090 return 0; 01091 } 01092 01093 errno = ENOSYS; 01094 return -1; 01095 } 01096 01111 static inline hwloc_obj_t 01112 hwloc_get_non_io_ancestor_obj(hwloc_topology_t topology , 01113 hwloc_obj_t ioobj) 01114 { 01115 hwloc_obj_t obj = ioobj; 01116 while (obj && !obj->cpuset) { 01117 obj = obj->parent; 01118 } 01119 return obj; 01120 } 01121 01126 static inline hwloc_obj_t 01127 hwloc_get_next_pcidev(hwloc_topology_t topology, hwloc_obj_t prev) 01128 { 01129 return hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_PCI_DEVICE, prev); 01130 } 01131 01135 static inline hwloc_obj_t 01136 hwloc_get_pcidev_by_busid(hwloc_topology_t topology, 01137 unsigned domain, unsigned bus, unsigned dev, unsigned func) 01138 { 01139 hwloc_obj_t obj = NULL; 01140 while ((obj = hwloc_get_next_pcidev(topology, obj)) != NULL) { 01141 if (obj->attr->pcidev.domain == domain 01142 && obj->attr->pcidev.bus == bus 01143 && obj->attr->pcidev.dev == dev 01144 && obj->attr->pcidev.func == func) 01145 return obj; 01146 } 01147 return NULL; 01148 } 01149 01153 static inline hwloc_obj_t 01154 hwloc_get_pcidev_by_busidstring(hwloc_topology_t topology, const char *busid) 01155 { 01156 unsigned domain = 0; /* default */ 01157 unsigned bus, dev, func; 01158 01159 if (sscanf(busid, "%x:%x.%x", &bus, &dev, &func) != 3 01160 && sscanf(busid, "%x:%x:%x.%x", &domain, &bus, &dev, &func) != 4) { 01161 errno = EINVAL; 01162 return NULL; 01163 } 01164 01165 return hwloc_get_pcidev_by_busid(topology, domain, bus, dev, func); 01166 } 01167 01172 static inline hwloc_obj_t 01173 hwloc_get_next_osdev(hwloc_topology_t topology, hwloc_obj_t prev) 01174 { 01175 return hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_OS_DEVICE, prev); 01176 } 01177 01182 static inline hwloc_obj_t 01183 hwloc_get_next_bridge(hwloc_topology_t topology, hwloc_obj_t prev) 01184 { 01185 return hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_BRIDGE, prev); 01186 } 01187 01188 /* \brief Checks whether a given bridge covers a given PCI bus. 01189 */ 01190 static inline int 01191 hwloc_bridge_covers_pcibus(hwloc_obj_t bridge, 01192 unsigned domain, unsigned bus) 01193 { 01194 return bridge->type == HWLOC_OBJ_BRIDGE 01195 && bridge->attr->bridge.downstream_type == HWLOC_OBJ_BRIDGE_PCI 01196 && bridge->attr->bridge.downstream.pci.domain == domain 01197 && bridge->attr->bridge.downstream.pci.secondary_bus <= bus 01198 && bridge->attr->bridge.downstream.pci.subordinate_bus >= bus; 01199 } 01200 01206 static inline hwloc_obj_t 01207 hwloc_get_hostbridge_by_pcibus(hwloc_topology_t topology, 01208 unsigned domain, unsigned bus) 01209 { 01210 hwloc_obj_t obj = NULL; 01211 while ((obj = hwloc_get_next_bridge(topology, obj)) != NULL) { 01212 if (hwloc_bridge_covers_pcibus(obj, domain, bus)) { 01213 /* found bridge covering this pcibus, make sure it's a hostbridge */ 01214 assert(obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_HOST); 01215 assert(obj->parent->type != HWLOC_OBJ_BRIDGE); 01216 assert(obj->parent->cpuset); 01217 return obj; 01218 } 01219 } 01220 return NULL; 01221 } 01222 01227 #ifdef __cplusplus 01228 } /* extern "C" */ 01229 #endif 01230 01231 01232 #endif /* HWLOC_HELPER_H */