Hardware Locality (hwloc) 1.2.2
|
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 00044 static inline int 00045 hwloc_get_type_or_below_depth (hwloc_topology_t topology, hwloc_obj_type_t type) 00046 { 00047 int depth = hwloc_get_type_depth(topology, type); 00048 00049 if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) 00050 return depth; 00051 00052 /* find the highest existing level with type order >= */ 00053 for(depth = hwloc_get_type_depth(topology, HWLOC_OBJ_PU); ; depth--) 00054 if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) < 0) 00055 return depth+1; 00056 00057 /* Shouldn't ever happen, as there is always a SYSTEM level with lower order and known depth. */ 00058 /* abort(); */ 00059 } 00060 00067 static inline int 00068 hwloc_get_type_or_above_depth (hwloc_topology_t topology, hwloc_obj_type_t type) 00069 { 00070 int depth = hwloc_get_type_depth(topology, type); 00071 00072 if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) 00073 return depth; 00074 00075 /* find the lowest existing level with type order <= */ 00076 for(depth = 0; ; depth++) 00077 if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) > 0) 00078 return depth-1; 00079 00080 /* Shouldn't ever happen, as there is always a PU level with higher order and known depth. */ 00081 /* abort(); */ 00082 } 00083 00103 static inline hwloc_obj_t 00104 hwloc_get_root_obj (hwloc_topology_t topology) 00105 { 00106 return hwloc_get_obj_by_depth (topology, 0, 0); 00107 } 00108 00110 static inline hwloc_obj_t 00111 hwloc_get_ancestor_obj_by_depth (hwloc_topology_t topology , unsigned depth, hwloc_obj_t obj) 00112 { 00113 hwloc_obj_t ancestor = obj; 00114 if (obj->depth < depth) 00115 return NULL; 00116 while (ancestor && ancestor->depth > depth) 00117 ancestor = ancestor->parent; 00118 return ancestor; 00119 } 00120 00122 static inline hwloc_obj_t 00123 hwloc_get_ancestor_obj_by_type (hwloc_topology_t topology , hwloc_obj_type_t type, hwloc_obj_t obj) 00124 { 00125 hwloc_obj_t ancestor = obj->parent; 00126 while (ancestor && ancestor->type != type) 00127 ancestor = ancestor->parent; 00128 return ancestor; 00129 } 00130 00135 static inline hwloc_obj_t 00136 hwloc_get_next_obj_by_depth (hwloc_topology_t topology, unsigned depth, hwloc_obj_t prev) 00137 { 00138 if (!prev) 00139 return hwloc_get_obj_by_depth (topology, depth, 0); 00140 if (prev->depth != depth) 00141 return NULL; 00142 return prev->next_cousin; 00143 } 00144 00151 static inline hwloc_obj_t 00152 hwloc_get_next_obj_by_type (hwloc_topology_t topology, hwloc_obj_type_t type, 00153 hwloc_obj_t prev) 00154 { 00155 int depth = hwloc_get_type_depth(topology, type); 00156 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00157 return NULL; 00158 return hwloc_get_next_obj_by_depth (topology, depth, prev); 00159 } 00160 00169 static inline hwloc_obj_t 00170 hwloc_get_pu_obj_by_os_index(hwloc_topology_t topology, unsigned os_index) 00171 { 00172 hwloc_obj_t obj = NULL; 00173 while ((obj = hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_PU, obj)) != NULL) 00174 if (obj->os_index == os_index) 00175 return obj; 00176 return NULL; 00177 } 00178 00183 static inline hwloc_obj_t 00184 hwloc_get_next_child (hwloc_topology_t topology , hwloc_obj_t parent, hwloc_obj_t prev) 00185 { 00186 if (!prev) 00187 return parent->first_child; 00188 if (prev->parent != parent) 00189 return NULL; 00190 return prev->next_sibling; 00191 } 00192 00194 static inline hwloc_obj_t 00195 hwloc_get_common_ancestor_obj (hwloc_topology_t topology , hwloc_obj_t obj1, hwloc_obj_t obj2) 00196 { 00197 /* the loop isn't so easy since intermediate ancestors may have 00198 * different depth, causing us to alternate between using obj1->parent 00199 * and obj2->parent. Also, even if at some point we find ancestors of 00200 * of the same depth, their ancestors may have different depth again. 00201 */ 00202 while (obj1 != obj2) { 00203 while (obj1->depth > obj2->depth) 00204 obj1 = obj1->parent; 00205 while (obj2->depth > obj1->depth) 00206 obj2 = obj2->parent; 00207 if (obj1 != obj2 && obj1->depth == obj2->depth) { 00208 obj1 = obj1->parent; 00209 obj2 = obj2->parent; 00210 } 00211 } 00212 return obj1; 00213 } 00214 00219 static inline int 00220 hwloc_obj_is_in_subtree (hwloc_topology_t topology , hwloc_obj_t obj, hwloc_obj_t subtree_root) 00221 { 00222 return hwloc_bitmap_isincluded(obj->cpuset, subtree_root->cpuset); 00223 } 00224 00241 static inline hwloc_obj_t 00242 hwloc_get_first_largest_obj_inside_cpuset(hwloc_topology_t topology, hwloc_const_cpuset_t set) 00243 { 00244 hwloc_obj_t obj = hwloc_get_root_obj(topology); 00245 /* FIXME: what if !root->cpuset? */ 00246 if (!hwloc_bitmap_intersects(obj->cpuset, set)) 00247 return NULL; 00248 while (!hwloc_bitmap_isincluded(obj->cpuset, set)) { 00249 /* while the object intersects without being included, look at its children */ 00250 hwloc_obj_t child = NULL; 00251 while ((child = hwloc_get_next_child(topology, obj, child)) != NULL) { 00252 if (child->cpuset && hwloc_bitmap_intersects(child->cpuset, set)) 00253 break; 00254 } 00255 if (!child) 00256 /* no child intersects, return their father */ 00257 return obj; 00258 /* found one intersecting child, look at its children */ 00259 obj = child; 00260 } 00261 /* obj is included, return it */ 00262 return obj; 00263 } 00264 00269 int hwloc_get_largest_objs_inside_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00270 hwloc_obj_t * restrict objs, int max); 00271 00278 static inline hwloc_obj_t 00279 hwloc_get_next_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00280 unsigned depth, hwloc_obj_t prev) 00281 { 00282 hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev); 00283 /* no need to check next->cpuset because objects in levels always have a cpuset */ 00284 while (next && !hwloc_bitmap_isincluded(next->cpuset, set)) 00285 next = next->next_cousin; 00286 return next; 00287 } 00288 00295 static inline hwloc_obj_t 00296 hwloc_get_next_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00297 hwloc_obj_type_t type, hwloc_obj_t prev) 00298 { 00299 int depth = hwloc_get_type_depth(topology, type); 00300 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00301 return NULL; 00302 return hwloc_get_next_obj_inside_cpuset_by_depth(topology, set, depth, prev); 00303 } 00304 00307 static inline hwloc_obj_t 00308 hwloc_get_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00309 unsigned depth, unsigned idx) 00310 { 00311 unsigned count = 0; 00312 hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0); 00313 while (obj) { 00314 /* no need to check obj->cpuset because objects in levels always have a cpuset */ 00315 if (hwloc_bitmap_isincluded(obj->cpuset, set)) { 00316 if (count == idx) 00317 return obj; 00318 count++; 00319 } 00320 obj = obj->next_cousin; 00321 } 00322 return NULL; 00323 } 00324 00331 static inline hwloc_obj_t 00332 hwloc_get_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00333 hwloc_obj_type_t type, unsigned idx) 00334 { 00335 int depth = hwloc_get_type_depth(topology, type); 00336 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00337 return NULL; 00338 return hwloc_get_obj_inside_cpuset_by_depth(topology, set, depth, idx); 00339 } 00340 00342 static inline unsigned 00343 hwloc_get_nbobjs_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00344 unsigned depth) 00345 { 00346 hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0); 00347 int count = 0; 00348 while (obj) { 00349 /* no need to check obj->cpuset because objects in levels always have a cpuset */ 00350 if (hwloc_bitmap_isincluded(obj->cpuset, set)) 00351 count++; 00352 obj = obj->next_cousin; 00353 } 00354 return count; 00355 } 00356 00363 static inline int 00364 hwloc_get_nbobjs_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00365 hwloc_obj_type_t type) 00366 { 00367 int depth = hwloc_get_type_depth(topology, type); 00368 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) 00369 return 0; 00370 if (depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00371 return -1; /* FIXME: agregate nbobjs from different levels? */ 00372 return hwloc_get_nbobjs_inside_cpuset_by_depth(topology, set, depth); 00373 } 00374 00387 static inline hwloc_obj_t 00388 hwloc_get_child_covering_cpuset (hwloc_topology_t topology , hwloc_const_cpuset_t set, 00389 hwloc_obj_t parent) 00390 { 00391 hwloc_obj_t child; 00392 00393 if (hwloc_bitmap_iszero(set)) 00394 return NULL; 00395 00396 child = parent->first_child; 00397 while (child) { 00398 if (child->cpuset && hwloc_bitmap_isincluded(set, child->cpuset)) 00399 return child; 00400 child = child->next_sibling; 00401 } 00402 return NULL; 00403 } 00404 00409 static inline hwloc_obj_t 00410 hwloc_get_obj_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set) 00411 { 00412 struct hwloc_obj *current = hwloc_get_root_obj(topology); 00413 00414 if (hwloc_bitmap_iszero(set)) 00415 return NULL; 00416 00417 /* FIXME: what if !root->cpuset? */ 00418 if (!hwloc_bitmap_isincluded(set, current->cpuset)) 00419 return NULL; 00420 00421 while (1) { 00422 hwloc_obj_t child = hwloc_get_child_covering_cpuset(topology, set, current); 00423 if (!child) 00424 return current; 00425 current = child; 00426 } 00427 } 00428 00429 00445 static inline hwloc_obj_t 00446 hwloc_get_next_obj_covering_cpuset_by_depth(hwloc_topology_t topology, hwloc_const_cpuset_t set, 00447 unsigned depth, hwloc_obj_t prev) 00448 { 00449 hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev); 00450 /* no need to check next->cpuset because objects in levels always have a cpuset */ 00451 while (next && !hwloc_bitmap_intersects(set, next->cpuset)) 00452 next = next->next_cousin; 00453 return next; 00454 } 00455 00468 static inline hwloc_obj_t 00469 hwloc_get_next_obj_covering_cpuset_by_type(hwloc_topology_t topology, hwloc_const_cpuset_t set, 00470 hwloc_obj_type_t type, hwloc_obj_t prev) 00471 { 00472 int depth = hwloc_get_type_depth(topology, type); 00473 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00474 return NULL; 00475 return hwloc_get_next_obj_covering_cpuset_by_depth(topology, set, depth, prev); 00476 } 00477 00490 static inline hwloc_obj_t 00491 hwloc_get_cache_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set) 00492 { 00493 hwloc_obj_t current = hwloc_get_obj_covering_cpuset(topology, set); 00494 while (current) { 00495 if (current->type == HWLOC_OBJ_CACHE) 00496 return current; 00497 current = current->parent; 00498 } 00499 return NULL; 00500 } 00501 00506 static inline hwloc_obj_t 00507 hwloc_get_shared_cache_covering_obj (hwloc_topology_t topology , hwloc_obj_t obj) 00508 { 00509 hwloc_obj_t current = obj->parent; 00510 if (!obj->cpuset) 00511 return NULL; 00512 while (current && current->cpuset) { 00513 if (!hwloc_bitmap_isequal(current->cpuset, obj->cpuset) 00514 && current->type == HWLOC_OBJ_CACHE) 00515 return current; 00516 current = current->parent; 00517 } 00518 return NULL; 00519 } 00520 00541 /* TODO: rather provide an iterator? Provide a way to know how much should be allocated? By returning the total number of objects instead? */ 00542 unsigned hwloc_get_closest_objs (hwloc_topology_t topology, hwloc_obj_t src, hwloc_obj_t * restrict objs, unsigned max); 00543 00554 static inline hwloc_obj_t 00555 hwloc_get_obj_below_by_type (hwloc_topology_t topology, 00556 hwloc_obj_type_t type1, unsigned idx1, 00557 hwloc_obj_type_t type2, unsigned idx2) 00558 { 00559 hwloc_obj_t obj; 00560 00561 obj = hwloc_get_obj_by_type (topology, type1, idx1); 00562 if (!obj) 00563 return NULL; 00564 00565 return hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, type2, idx2); 00566 } 00567 00583 static inline hwloc_obj_t 00584 hwloc_get_obj_below_array_by_type (hwloc_topology_t topology, int nr, hwloc_obj_type_t *typev, unsigned *idxv) 00585 { 00586 hwloc_obj_t obj = hwloc_get_root_obj(topology); 00587 int i; 00588 00589 /* FIXME: what if !root->cpuset? */ 00590 for(i=0; i<nr; i++) { 00591 obj = hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, typev[i], idxv[i]); 00592 if (!obj) 00593 return NULL; 00594 } 00595 00596 return obj; 00597 } 00598 00620 static inline void 00621 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *root, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until); 00622 static inline void 00623 hwloc_distribute(hwloc_topology_t topology, hwloc_obj_t root, hwloc_cpuset_t *cpuset, unsigned n, unsigned until) 00624 { 00625 unsigned i; 00626 00627 /* FIXME: what if !root->cpuset? */ 00628 if (!root->arity || n == 1 || root->depth >= until) { 00629 /* Got to the bottom, we can't split any more, put everything there. */ 00630 for (i=0; i<n; i++) 00631 cpuset[i] = hwloc_bitmap_dup(root->cpuset); 00632 return; 00633 } 00634 00635 hwloc_distributev(topology, root->children, root->arity, cpuset, n, until); 00636 } 00637 00643 static inline void 00644 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *roots, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until) 00645 { 00646 unsigned i; 00647 unsigned tot_weight; 00648 hwloc_cpuset_t *cpusetp = cpuset; 00649 00650 tot_weight = 0; 00651 for (i = 0; i < n_roots; i++) 00652 if (roots[i]->cpuset) 00653 tot_weight += hwloc_bitmap_weight(roots[i]->cpuset); 00654 00655 for (i = 0; i < n_roots && tot_weight; i++) { 00656 /* Give to roots[i] a portion proportional to its weight */ 00657 unsigned weight = roots[i]->cpuset ? hwloc_bitmap_weight(roots[i]->cpuset) : 0; 00658 unsigned chunk = (n * weight + tot_weight-1) / tot_weight; 00659 hwloc_distribute(topology, roots[i], cpusetp, chunk, until); 00660 cpusetp += chunk; 00661 tot_weight -= weight; 00662 n -= chunk; 00663 } 00664 } 00665 00672 static inline void * 00673 hwloc_alloc_membind_policy_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) 00674 { 00675 void *p = hwloc_alloc_membind_nodeset(topology, len, nodeset, policy, flags); 00676 if (p) 00677 return p; 00678 hwloc_set_membind_nodeset(topology, nodeset, policy, flags); 00679 p = hwloc_alloc(topology, len); 00680 if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH) 00681 /* Enforce the binding by touching the data */ 00682 memset(p, 0, len); 00683 return p; 00684 } 00685 00690 static inline void * 00691 hwloc_alloc_membind_policy(hwloc_topology_t topology, size_t len, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags) 00692 { 00693 void *p = hwloc_alloc_membind(topology, len, cpuset, policy, flags); 00694 if (p) 00695 return p; 00696 hwloc_set_membind(topology, cpuset, policy, flags); 00697 p = hwloc_alloc(topology, len); 00698 if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH) 00699 /* Enforce the binding by touching the data */ 00700 memset(p, 0, len); 00701 return p; 00702 } 00703 00720 static inline hwloc_const_cpuset_t 00721 hwloc_topology_get_complete_cpuset(hwloc_topology_t topology) 00722 { 00723 return hwloc_get_root_obj(topology)->complete_cpuset; 00724 } 00725 00736 static inline hwloc_const_cpuset_t 00737 hwloc_topology_get_topology_cpuset(hwloc_topology_t topology) 00738 { 00739 return hwloc_get_root_obj(topology)->cpuset; 00740 } 00741 00751 static inline hwloc_const_cpuset_t 00752 hwloc_topology_get_online_cpuset(hwloc_topology_t topology) 00753 { 00754 return hwloc_get_root_obj(topology)->online_cpuset; 00755 } 00756 00766 static inline hwloc_const_cpuset_t 00767 hwloc_topology_get_allowed_cpuset(hwloc_topology_t topology) 00768 { 00769 return hwloc_get_root_obj(topology)->allowed_cpuset; 00770 } 00771 00788 static inline hwloc_const_nodeset_t 00789 hwloc_topology_get_complete_nodeset(hwloc_topology_t topology) 00790 { 00791 return hwloc_get_root_obj(topology)->complete_nodeset; 00792 } 00793 00804 static inline hwloc_const_nodeset_t 00805 hwloc_topology_get_topology_nodeset(hwloc_topology_t topology) 00806 { 00807 return hwloc_get_root_obj(topology)->nodeset; 00808 } 00809 00819 static inline hwloc_const_nodeset_t 00820 hwloc_topology_get_allowed_nodeset(hwloc_topology_t topology) 00821 { 00822 return hwloc_get_root_obj(topology)->allowed_nodeset; 00823 } 00824 00855 static inline void 00856 hwloc_cpuset_to_nodeset(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset) 00857 { 00858 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 00859 hwloc_obj_t obj; 00860 00861 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) { 00862 if (hwloc_bitmap_iszero(cpuset)) 00863 hwloc_bitmap_zero(nodeset); 00864 else 00865 /* Assume the whole system */ 00866 hwloc_bitmap_fill(nodeset); 00867 return; 00868 } 00869 00870 hwloc_bitmap_zero(nodeset); 00871 obj = NULL; 00872 while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL) 00873 hwloc_bitmap_set(nodeset, obj->os_index); 00874 } 00875 00883 static inline void 00884 hwloc_cpuset_to_nodeset_strict(struct hwloc_topology *topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset) 00885 { 00886 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 00887 hwloc_obj_t obj; 00888 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) 00889 return; 00890 hwloc_bitmap_zero(nodeset); 00891 obj = NULL; 00892 while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL) 00893 hwloc_bitmap_set(nodeset, obj->os_index); 00894 } 00895 00904 static inline void 00905 hwloc_cpuset_from_nodeset(hwloc_topology_t topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset) 00906 { 00907 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 00908 hwloc_obj_t obj; 00909 00910 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) { 00911 if (hwloc_bitmap_iszero(nodeset)) 00912 hwloc_bitmap_zero(cpuset); 00913 else 00914 /* Assume the whole system */ 00915 hwloc_bitmap_fill(cpuset); 00916 return; 00917 } 00918 00919 hwloc_bitmap_zero(cpuset); 00920 obj = NULL; 00921 while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL) { 00922 if (hwloc_bitmap_isset(nodeset, obj->os_index)) 00923 /* no need to check obj->cpuset because objects in levels always have a cpuset */ 00924 hwloc_bitmap_or(cpuset, cpuset, obj->cpuset); 00925 } 00926 } 00927 00935 static inline void 00936 hwloc_cpuset_from_nodeset_strict(struct hwloc_topology *topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset) 00937 { 00938 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 00939 hwloc_obj_t obj; 00940 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) 00941 return; 00942 hwloc_bitmap_zero(cpuset); 00943 obj = NULL; 00944 while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL) 00945 if (hwloc_bitmap_isset(nodeset, obj->os_index)) 00946 /* no need to check obj->cpuset because objects in levels always have a cpuset */ 00947 hwloc_bitmap_or(cpuset, cpuset, obj->cpuset); 00948 } 00949 00977 static inline const struct hwloc_distances_s * 00978 hwloc_get_whole_distance_matrix_by_depth(hwloc_topology_t topology, unsigned depth) 00979 { 00980 hwloc_obj_t root = hwloc_get_root_obj(topology); 00981 unsigned i; 00982 for(i=0; i<root->distances_count; i++) 00983 if (root->distances[i]->relative_depth == depth) 00984 return root->distances[i]; 00985 return NULL; 00986 } 00987 01007 static inline const struct hwloc_distances_s * 01008 hwloc_get_whole_distance_matrix_by_type(hwloc_topology_t topology, hwloc_obj_type_t type) 01009 { 01010 int depth = hwloc_get_type_depth(topology, type); 01011 if (depth < 0) 01012 return NULL; 01013 return hwloc_get_whole_distance_matrix_by_depth(topology, depth); 01014 } 01015 01029 static inline const struct hwloc_distances_s * 01030 hwloc_get_distance_matrix_covering_obj_by_depth(hwloc_topology_t topology, 01031 hwloc_obj_t obj, unsigned depth, 01032 unsigned *firstp) 01033 { 01034 while (obj && obj->cpuset) { 01035 unsigned i; 01036 for(i=0; i<obj->distances_count; i++) 01037 if (obj->distances[i]->relative_depth == depth - obj->depth) { 01038 if (!obj->distances[i]->nbobjs) 01039 continue; 01040 *firstp = hwloc_get_next_obj_inside_cpuset_by_depth(topology, obj->cpuset, depth, NULL)->logical_index; 01041 return obj->distances[i]; 01042 } 01043 obj = obj->parent; 01044 } 01045 return NULL; 01046 } 01047 01059 static inline int 01060 hwloc_get_latency(hwloc_topology_t topology, 01061 hwloc_obj_t obj1, hwloc_obj_t obj2, 01062 float *latency, float *reverse_latency) 01063 { 01064 hwloc_obj_t ancestor; 01065 const struct hwloc_distances_s * distances; 01066 unsigned first_logical ; 01067 01068 if (obj1->depth != obj2->depth) { 01069 errno = EINVAL; 01070 return -1; 01071 } 01072 01073 ancestor = hwloc_get_common_ancestor_obj(topology, obj1, obj2); 01074 distances = hwloc_get_distance_matrix_covering_obj_by_depth(topology, ancestor, obj1->depth, &first_logical); 01075 if (distances && distances->latency) { 01076 const float * latency_matrix = distances->latency; 01077 unsigned nbobjs = distances->nbobjs; 01078 unsigned l1 = obj1->logical_index - first_logical; 01079 unsigned l2 = obj2->logical_index - first_logical; 01080 *latency = latency_matrix[l1*nbobjs+l2]; 01081 *reverse_latency = latency_matrix[l2*nbobjs+l1]; 01082 return 0; 01083 } 01084 01085 errno = ENOSYS; 01086 return -1; 01087 } 01088 01093 #ifdef __cplusplus 01094 } /* extern "C" */ 01095 #endif 01096 01097 01098 #endif /* HWLOC_HELPER_H */