Hardware Locality (hwloc) 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 /* FIXME: what if !root->cpuset? */ 00236 if (!hwloc_bitmap_intersects(obj->cpuset, set)) 00237 return NULL; 00238 while (!hwloc_bitmap_isincluded(obj->cpuset, set)) { 00239 /* while the object intersects without being included, look at its children */ 00240 hwloc_obj_t child = NULL; 00241 while ((child = hwloc_get_next_child(topology, obj, child)) != NULL) { 00242 if (child->cpuset && hwloc_bitmap_intersects(child->cpuset, set)) 00243 break; 00244 } 00245 if (!child) 00246 /* no child intersects, return their father */ 00247 return obj; 00248 /* found one intersecting child, look at its children */ 00249 obj = child; 00250 } 00251 /* obj is included, return it */ 00252 return obj; 00253 } 00254 00259 int hwloc_get_largest_objs_inside_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00260 hwloc_obj_t * restrict objs, int max); 00261 00268 static inline hwloc_obj_t 00269 hwloc_get_next_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00270 unsigned depth, hwloc_obj_t prev) 00271 { 00272 hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev); 00273 /* no need to check next->cpuset because objects in levels always have a cpuset */ 00274 while (next && !hwloc_bitmap_isincluded(next->cpuset, set)) 00275 next = next->next_cousin; 00276 return next; 00277 } 00278 00285 static inline hwloc_obj_t 00286 hwloc_get_next_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00287 hwloc_obj_type_t type, hwloc_obj_t prev) 00288 { 00289 int depth = hwloc_get_type_depth(topology, type); 00290 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00291 return NULL; 00292 return hwloc_get_next_obj_inside_cpuset_by_depth(topology, set, depth, prev); 00293 } 00294 00297 static inline hwloc_obj_t 00298 hwloc_get_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00299 unsigned depth, unsigned idx) 00300 { 00301 unsigned count = 0; 00302 hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0); 00303 while (obj) { 00304 /* no need to check obj->cpuset because objects in levels always have a cpuset */ 00305 if (hwloc_bitmap_isincluded(obj->cpuset, set)) { 00306 if (count == idx) 00307 return obj; 00308 count++; 00309 } 00310 obj = obj->next_cousin; 00311 } 00312 return NULL; 00313 } 00314 00321 static inline hwloc_obj_t 00322 hwloc_get_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00323 hwloc_obj_type_t type, unsigned idx) 00324 { 00325 int depth = hwloc_get_type_depth(topology, type); 00326 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00327 return NULL; 00328 return hwloc_get_obj_inside_cpuset_by_depth(topology, set, depth, idx); 00329 } 00330 00332 static inline unsigned 00333 hwloc_get_nbobjs_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00334 unsigned depth) 00335 { 00336 hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0); 00337 int count = 0; 00338 while (obj) { 00339 /* no need to check obj->cpuset because objects in levels always have a cpuset */ 00340 if (hwloc_bitmap_isincluded(obj->cpuset, set)) 00341 count++; 00342 obj = obj->next_cousin; 00343 } 00344 return count; 00345 } 00346 00353 static inline int 00354 hwloc_get_nbobjs_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00355 hwloc_obj_type_t type) 00356 { 00357 int depth = hwloc_get_type_depth(topology, type); 00358 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) 00359 return 0; 00360 if (depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00361 return -1; /* FIXME: agregate nbobjs from different levels? */ 00362 return hwloc_get_nbobjs_inside_cpuset_by_depth(topology, set, depth); 00363 } 00364 00377 static inline hwloc_obj_t 00378 hwloc_get_child_covering_cpuset (hwloc_topology_t topology , hwloc_const_cpuset_t set, 00379 hwloc_obj_t parent) 00380 { 00381 hwloc_obj_t child; 00382 00383 if (hwloc_bitmap_iszero(set)) 00384 return NULL; 00385 00386 child = parent->first_child; 00387 while (child) { 00388 if (child->cpuset && hwloc_bitmap_isincluded(set, child->cpuset)) 00389 return child; 00390 child = child->next_sibling; 00391 } 00392 return NULL; 00393 } 00394 00399 static inline hwloc_obj_t 00400 hwloc_get_obj_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set) 00401 { 00402 struct hwloc_obj *current = hwloc_get_root_obj(topology); 00403 00404 if (hwloc_bitmap_iszero(set)) 00405 return NULL; 00406 00407 /* FIXME: what if !root->cpuset? */ 00408 if (!hwloc_bitmap_isincluded(set, current->cpuset)) 00409 return NULL; 00410 00411 while (1) { 00412 hwloc_obj_t child = hwloc_get_child_covering_cpuset(topology, set, current); 00413 if (!child) 00414 return current; 00415 current = child; 00416 } 00417 } 00418 00419 00435 static inline hwloc_obj_t 00436 hwloc_get_next_obj_covering_cpuset_by_depth(hwloc_topology_t topology, hwloc_const_cpuset_t set, 00437 unsigned depth, hwloc_obj_t prev) 00438 { 00439 hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev); 00440 /* no need to check next->cpuset because objects in levels always have a cpuset */ 00441 while (next && !hwloc_bitmap_intersects(set, next->cpuset)) 00442 next = next->next_cousin; 00443 return next; 00444 } 00445 00458 static inline hwloc_obj_t 00459 hwloc_get_next_obj_covering_cpuset_by_type(hwloc_topology_t topology, hwloc_const_cpuset_t set, 00460 hwloc_obj_type_t type, hwloc_obj_t prev) 00461 { 00462 int depth = hwloc_get_type_depth(topology, type); 00463 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00464 return NULL; 00465 return hwloc_get_next_obj_covering_cpuset_by_depth(topology, set, depth, prev); 00466 } 00467 00480 static inline hwloc_obj_t 00481 hwloc_get_cache_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set) 00482 { 00483 hwloc_obj_t current = hwloc_get_obj_covering_cpuset(topology, set); 00484 while (current) { 00485 if (current->type == HWLOC_OBJ_CACHE) 00486 return current; 00487 current = current->parent; 00488 } 00489 return NULL; 00490 } 00491 00496 static inline hwloc_obj_t 00497 hwloc_get_shared_cache_covering_obj (hwloc_topology_t topology , hwloc_obj_t obj) 00498 { 00499 hwloc_obj_t current = obj->parent; 00500 if (!obj->cpuset) 00501 return NULL; 00502 while (current && current->cpuset) { 00503 if (!hwloc_bitmap_isequal(current->cpuset, obj->cpuset) 00504 && current->type == HWLOC_OBJ_CACHE) 00505 return current; 00506 current = current->parent; 00507 } 00508 return NULL; 00509 } 00510 00526 /* TODO: rather provide an iterator? Provide a way to know how much should be allocated? By returning the total number of objects instead? */ 00527 unsigned hwloc_get_closest_objs (hwloc_topology_t topology, hwloc_obj_t src, hwloc_obj_t * restrict objs, unsigned max); 00528 00539 static inline hwloc_obj_t 00540 hwloc_get_obj_below_by_type (hwloc_topology_t topology, 00541 hwloc_obj_type_t type1, unsigned idx1, 00542 hwloc_obj_type_t type2, unsigned idx2) 00543 { 00544 hwloc_obj_t obj; 00545 00546 obj = hwloc_get_obj_by_type (topology, type1, idx1); 00547 if (!obj) 00548 return NULL; 00549 00550 return hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, type2, idx2); 00551 } 00552 00568 static inline hwloc_obj_t 00569 hwloc_get_obj_below_array_by_type (hwloc_topology_t topology, int nr, hwloc_obj_type_t *typev, unsigned *idxv) 00570 { 00571 hwloc_obj_t obj = hwloc_get_root_obj(topology); 00572 int i; 00573 00574 /* FIXME: what if !root->cpuset? */ 00575 for(i=0; i<nr; i++) { 00576 obj = hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, typev[i], idxv[i]); 00577 if (!obj) 00578 return NULL; 00579 } 00580 00581 return obj; 00582 } 00583 00605 static inline void 00606 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *root, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until); 00607 static inline void 00608 hwloc_distribute(hwloc_topology_t topology, hwloc_obj_t root, hwloc_cpuset_t *cpuset, unsigned n, unsigned until) 00609 { 00610 unsigned i; 00611 00612 /* FIXME: what if !root->cpuset? */ 00613 if (!root->arity || n == 1 || root->depth >= until) { 00614 /* Got to the bottom, we can't split any more, put everything there. */ 00615 for (i=0; i<n; i++) 00616 cpuset[i] = hwloc_bitmap_dup(root->cpuset); 00617 return; 00618 } 00619 00620 hwloc_distributev(topology, root->children, root->arity, cpuset, n, until); 00621 } 00622 00628 static inline void 00629 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *roots, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until) 00630 { 00631 unsigned i; 00632 unsigned tot_weight; 00633 hwloc_cpuset_t *cpusetp = cpuset; 00634 00635 tot_weight = 0; 00636 for (i = 0; i < n_roots; i++) 00637 if (roots[i]->cpuset) 00638 tot_weight += hwloc_bitmap_weight(roots[i]->cpuset); 00639 00640 for (i = 0; i < n_roots && tot_weight; i++) { 00641 /* Give to roots[i] a portion proportional to its weight */ 00642 unsigned weight = roots[i]->cpuset ? hwloc_bitmap_weight(roots[i]->cpuset) : 0; 00643 unsigned chunk = (n * weight + tot_weight-1) / tot_weight; 00644 hwloc_distribute(topology, roots[i], cpusetp, chunk, until); 00645 cpusetp += chunk; 00646 tot_weight -= weight; 00647 n -= chunk; 00648 } 00649 } 00650 00657 static inline void * 00658 hwloc_alloc_membind_policy_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) 00659 { 00660 void *p = hwloc_alloc_membind_nodeset(topology, len, nodeset, policy, flags); 00661 if (p) 00662 return p; 00663 hwloc_set_membind_nodeset(topology, nodeset, policy, flags); 00664 p = hwloc_alloc(topology, len); 00665 if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH) 00666 /* Enforce the binding by touching the data */ 00667 memset(p, 0, len); 00668 return p; 00669 } 00670 00675 static inline void * 00676 hwloc_alloc_membind_policy(hwloc_topology_t topology, size_t len, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags) 00677 { 00678 void *p = hwloc_alloc_membind(topology, len, cpuset, policy, flags); 00679 if (p) 00680 return p; 00681 hwloc_set_membind(topology, cpuset, policy, flags); 00682 p = hwloc_alloc(topology, len); 00683 if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH) 00684 /* Enforce the binding by touching the data */ 00685 memset(p, 0, len); 00686 return p; 00687 } 00688 00705 static inline hwloc_const_cpuset_t 00706 hwloc_topology_get_complete_cpuset(hwloc_topology_t topology) 00707 { 00708 return hwloc_get_root_obj(topology)->complete_cpuset; 00709 } 00710 00721 static inline hwloc_const_cpuset_t 00722 hwloc_topology_get_topology_cpuset(hwloc_topology_t topology) 00723 { 00724 return hwloc_get_root_obj(topology)->cpuset; 00725 } 00726 00736 static inline hwloc_const_cpuset_t 00737 hwloc_topology_get_online_cpuset(hwloc_topology_t topology) 00738 { 00739 return hwloc_get_root_obj(topology)->online_cpuset; 00740 } 00741 00751 static inline hwloc_const_cpuset_t 00752 hwloc_topology_get_allowed_cpuset(hwloc_topology_t topology) 00753 { 00754 return hwloc_get_root_obj(topology)->allowed_cpuset; 00755 } 00756 00773 static inline hwloc_const_nodeset_t 00774 hwloc_topology_get_complete_nodeset(hwloc_topology_t topology) 00775 { 00776 return hwloc_get_root_obj(topology)->complete_nodeset; 00777 } 00778 00789 static inline hwloc_const_nodeset_t 00790 hwloc_topology_get_topology_nodeset(hwloc_topology_t topology) 00791 { 00792 return hwloc_get_root_obj(topology)->nodeset; 00793 } 00794 00804 static inline hwloc_const_nodeset_t 00805 hwloc_topology_get_allowed_nodeset(hwloc_topology_t topology) 00806 { 00807 return hwloc_get_root_obj(topology)->allowed_nodeset; 00808 } 00809 00840 static inline void 00841 hwloc_cpuset_to_nodeset(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset) 00842 { 00843 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 00844 hwloc_obj_t obj; 00845 00846 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) { 00847 if (hwloc_bitmap_iszero(cpuset)) 00848 hwloc_bitmap_zero(nodeset); 00849 else 00850 /* Assume the whole system */ 00851 hwloc_bitmap_fill(nodeset); 00852 return; 00853 } 00854 00855 hwloc_bitmap_zero(nodeset); 00856 obj = NULL; 00857 while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL) 00858 hwloc_bitmap_set(nodeset, obj->os_index); 00859 } 00860 00868 static inline void 00869 hwloc_cpuset_to_nodeset_strict(struct hwloc_topology *topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset) 00870 { 00871 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 00872 hwloc_obj_t obj; 00873 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) 00874 return; 00875 hwloc_bitmap_zero(nodeset); 00876 obj = NULL; 00877 while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL) 00878 hwloc_bitmap_set(nodeset, obj->os_index); 00879 } 00880 00889 static inline void 00890 hwloc_cpuset_from_nodeset(hwloc_topology_t topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset) 00891 { 00892 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 00893 hwloc_obj_t obj; 00894 00895 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) { 00896 if (hwloc_bitmap_iszero(nodeset)) 00897 hwloc_bitmap_zero(cpuset); 00898 else 00899 /* Assume the whole system */ 00900 hwloc_bitmap_fill(cpuset); 00901 return; 00902 } 00903 00904 hwloc_bitmap_zero(cpuset); 00905 obj = NULL; 00906 while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL) { 00907 if (hwloc_bitmap_isset(nodeset, obj->os_index)) 00908 /* no need to check obj->cpuset because objects in levels always have a cpuset */ 00909 hwloc_bitmap_or(cpuset, cpuset, obj->cpuset); 00910 } 00911 } 00912 00920 static inline void 00921 hwloc_cpuset_from_nodeset_strict(struct hwloc_topology *topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset) 00922 { 00923 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 00924 hwloc_obj_t obj; 00925 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) 00926 return; 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 00962 static inline const struct hwloc_distances_s * 00963 hwloc_get_whole_distance_matrix_by_depth(hwloc_topology_t topology, unsigned depth) 00964 { 00965 hwloc_obj_t root = hwloc_get_root_obj(topology); 00966 unsigned i; 00967 for(i=0; i<root->distances_count; i++) 00968 if (root->distances[i]->relative_depth == depth) 00969 return root->distances[i]; 00970 return NULL; 00971 } 00972 00992 static inline const struct hwloc_distances_s * 00993 hwloc_get_whole_distance_matrix_by_type(hwloc_topology_t topology, hwloc_obj_type_t type) 00994 { 00995 int depth = hwloc_get_type_depth(topology, type); 00996 if (depth < 0) 00997 return NULL; 00998 return hwloc_get_whole_distance_matrix_by_depth(topology, depth); 00999 } 01000 01014 static inline const struct hwloc_distances_s * 01015 hwloc_get_distance_matrix_covering_obj_by_depth(hwloc_topology_t topology, 01016 hwloc_obj_t obj, unsigned depth, 01017 unsigned *firstp) 01018 { 01019 while (obj && obj->cpuset) { 01020 unsigned i; 01021 for(i=0; i<obj->distances_count; i++) 01022 if (obj->distances[i]->relative_depth == depth - obj->depth) { 01023 if (!obj->distances[i]->nbobjs) 01024 continue; 01025 *firstp = hwloc_get_next_obj_inside_cpuset_by_depth(topology, obj->cpuset, depth, NULL)->logical_index; 01026 return obj->distances[i]; 01027 } 01028 obj = obj->parent; 01029 } 01030 return NULL; 01031 } 01032 01044 static inline int 01045 hwloc_get_latency(hwloc_topology_t topology, 01046 hwloc_obj_t obj1, hwloc_obj_t obj2, 01047 float *latency, float *reverse_latency) 01048 { 01049 hwloc_obj_t ancestor; 01050 const struct hwloc_distances_s * distances; 01051 unsigned first_logical ; 01052 01053 if (obj1->depth != obj2->depth) { 01054 errno = EINVAL; 01055 return -1; 01056 } 01057 01058 ancestor = hwloc_get_common_ancestor_obj(topology, obj1, obj2); 01059 distances = hwloc_get_distance_matrix_covering_obj_by_depth(topology, ancestor, obj1->depth, &first_logical); 01060 if (distances && distances->latency) { 01061 const float * latency_matrix = distances->latency; 01062 unsigned nbobjs = distances->nbobjs; 01063 unsigned l1 = obj1->logical_index - first_logical; 01064 unsigned l2 = obj2->logical_index - first_logical; 01065 *latency = latency_matrix[l1*nbobjs+l2]; 01066 *reverse_latency = latency_matrix[l2*nbobjs+l1]; 01067 return 0; 01068 } 01069 01070 errno = ENOSYS; 01071 return -1; 01072 } 01073 01078 #ifdef __cplusplus 01079 } /* extern "C" */ 01080 #endif 01081 01082 01083 #endif /* HWLOC_HELPER_H */