Hardware Locality (hwloc) 1.3
|
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 00543 /* TODO: rather provide an iterator? Provide a way to know how much should be allocated? By returning the total number of objects instead? */ 00544 unsigned hwloc_get_closest_objs (hwloc_topology_t topology, hwloc_obj_t src, hwloc_obj_t * restrict objs, unsigned max); 00545 00556 static inline hwloc_obj_t 00557 hwloc_get_obj_below_by_type (hwloc_topology_t topology, 00558 hwloc_obj_type_t type1, unsigned idx1, 00559 hwloc_obj_type_t type2, unsigned idx2) 00560 { 00561 hwloc_obj_t obj; 00562 00563 obj = hwloc_get_obj_by_type (topology, type1, idx1); 00564 if (!obj) 00565 return NULL; 00566 00567 return hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, type2, idx2); 00568 } 00569 00585 static inline hwloc_obj_t 00586 hwloc_get_obj_below_array_by_type (hwloc_topology_t topology, int nr, hwloc_obj_type_t *typev, unsigned *idxv) 00587 { 00588 hwloc_obj_t obj = hwloc_get_root_obj(topology); 00589 int i; 00590 00591 /* FIXME: what if !root->cpuset? */ 00592 for(i=0; i<nr; i++) { 00593 obj = hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, typev[i], idxv[i]); 00594 if (!obj) 00595 return NULL; 00596 } 00597 00598 return obj; 00599 } 00600 00622 static inline void 00623 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *root, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until); 00624 static inline void 00625 hwloc_distribute(hwloc_topology_t topology, hwloc_obj_t root, hwloc_cpuset_t *cpuset, unsigned n, unsigned until) 00626 { 00627 unsigned i; 00628 00629 /* FIXME: what if !root->cpuset? */ 00630 if (!root->arity || n == 1 || root->depth >= until) { 00631 /* Got to the bottom, we can't split any more, put everything there. */ 00632 for (i=0; i<n; i++) 00633 cpuset[i] = hwloc_bitmap_dup(root->cpuset); 00634 return; 00635 } 00636 00637 hwloc_distributev(topology, root->children, root->arity, cpuset, n, until); 00638 } 00639 00645 static inline void 00646 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *roots, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until) 00647 { 00648 unsigned i; 00649 unsigned tot_weight; 00650 hwloc_cpuset_t *cpusetp = cpuset; 00651 00652 tot_weight = 0; 00653 for (i = 0; i < n_roots; i++) 00654 if (roots[i]->cpuset) 00655 tot_weight += hwloc_bitmap_weight(roots[i]->cpuset); 00656 00657 for (i = 0; i < n_roots && tot_weight; i++) { 00658 /* Give to roots[i] a portion proportional to its weight */ 00659 unsigned weight = roots[i]->cpuset ? hwloc_bitmap_weight(roots[i]->cpuset) : 0; 00660 unsigned chunk = (n * weight + tot_weight-1) / tot_weight; 00661 hwloc_distribute(topology, roots[i], cpusetp, chunk, until); 00662 cpusetp += chunk; 00663 tot_weight -= weight; 00664 n -= chunk; 00665 } 00666 } 00667 00674 static inline void * 00675 hwloc_alloc_membind_policy_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) 00676 { 00677 void *p = hwloc_alloc_membind_nodeset(topology, len, nodeset, policy, flags); 00678 if (p) 00679 return p; 00680 hwloc_set_membind_nodeset(topology, nodeset, policy, flags); 00681 p = hwloc_alloc(topology, len); 00682 if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH) 00683 /* Enforce the binding by touching the data */ 00684 memset(p, 0, len); 00685 return p; 00686 } 00687 00692 static inline void * 00693 hwloc_alloc_membind_policy(hwloc_topology_t topology, size_t len, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags) 00694 { 00695 void *p = hwloc_alloc_membind(topology, len, cpuset, policy, flags); 00696 if (p) 00697 return p; 00698 hwloc_set_membind(topology, cpuset, policy, flags); 00699 p = hwloc_alloc(topology, len); 00700 if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH) 00701 /* Enforce the binding by touching the data */ 00702 memset(p, 0, len); 00703 return p; 00704 } 00705 00722 static inline hwloc_const_cpuset_t 00723 hwloc_topology_get_complete_cpuset(hwloc_topology_t topology) 00724 { 00725 return hwloc_get_root_obj(topology)->complete_cpuset; 00726 } 00727 00738 static inline hwloc_const_cpuset_t 00739 hwloc_topology_get_topology_cpuset(hwloc_topology_t topology) 00740 { 00741 return hwloc_get_root_obj(topology)->cpuset; 00742 } 00743 00753 static inline hwloc_const_cpuset_t 00754 hwloc_topology_get_online_cpuset(hwloc_topology_t topology) 00755 { 00756 return hwloc_get_root_obj(topology)->online_cpuset; 00757 } 00758 00768 static inline hwloc_const_cpuset_t 00769 hwloc_topology_get_allowed_cpuset(hwloc_topology_t topology) 00770 { 00771 return hwloc_get_root_obj(topology)->allowed_cpuset; 00772 } 00773 00790 static inline hwloc_const_nodeset_t 00791 hwloc_topology_get_complete_nodeset(hwloc_topology_t topology) 00792 { 00793 return hwloc_get_root_obj(topology)->complete_nodeset; 00794 } 00795 00806 static inline hwloc_const_nodeset_t 00807 hwloc_topology_get_topology_nodeset(hwloc_topology_t topology) 00808 { 00809 return hwloc_get_root_obj(topology)->nodeset; 00810 } 00811 00821 static inline hwloc_const_nodeset_t 00822 hwloc_topology_get_allowed_nodeset(hwloc_topology_t topology) 00823 { 00824 return hwloc_get_root_obj(topology)->allowed_nodeset; 00825 } 00826 00857 static inline void 00858 hwloc_cpuset_to_nodeset(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset) 00859 { 00860 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 00861 hwloc_obj_t obj; 00862 00863 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) { 00864 if (hwloc_bitmap_iszero(cpuset)) 00865 hwloc_bitmap_zero(nodeset); 00866 else 00867 /* Assume the whole system */ 00868 hwloc_bitmap_fill(nodeset); 00869 return; 00870 } 00871 00872 hwloc_bitmap_zero(nodeset); 00873 obj = NULL; 00874 while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL) 00875 hwloc_bitmap_set(nodeset, obj->os_index); 00876 } 00877 00885 static inline void 00886 hwloc_cpuset_to_nodeset_strict(struct hwloc_topology *topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset) 00887 { 00888 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 00889 hwloc_obj_t obj; 00890 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) 00891 return; 00892 hwloc_bitmap_zero(nodeset); 00893 obj = NULL; 00894 while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL) 00895 hwloc_bitmap_set(nodeset, obj->os_index); 00896 } 00897 00906 static inline void 00907 hwloc_cpuset_from_nodeset(hwloc_topology_t topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset) 00908 { 00909 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 00910 hwloc_obj_t obj; 00911 00912 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) { 00913 if (hwloc_bitmap_iszero(nodeset)) 00914 hwloc_bitmap_zero(cpuset); 00915 else 00916 /* Assume the whole system */ 00917 hwloc_bitmap_fill(cpuset); 00918 return; 00919 } 00920 00921 hwloc_bitmap_zero(cpuset); 00922 obj = NULL; 00923 while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL) { 00924 if (hwloc_bitmap_isset(nodeset, obj->os_index)) 00925 /* no need to check obj->cpuset because objects in levels always have a cpuset */ 00926 hwloc_bitmap_or(cpuset, cpuset, obj->cpuset); 00927 } 00928 } 00929 00937 static inline void 00938 hwloc_cpuset_from_nodeset_strict(struct hwloc_topology *topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset) 00939 { 00940 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 00941 hwloc_obj_t obj; 00942 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) 00943 return; 00944 hwloc_bitmap_zero(cpuset); 00945 obj = NULL; 00946 while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL) 00947 if (hwloc_bitmap_isset(nodeset, obj->os_index)) 00948 /* no need to check obj->cpuset because objects in levels always have a cpuset */ 00949 hwloc_bitmap_or(cpuset, cpuset, obj->cpuset); 00950 } 00951 00979 static inline const struct hwloc_distances_s * 00980 hwloc_get_whole_distance_matrix_by_depth(hwloc_topology_t topology, unsigned depth) 00981 { 00982 hwloc_obj_t root = hwloc_get_root_obj(topology); 00983 unsigned i; 00984 for(i=0; i<root->distances_count; i++) 00985 if (root->distances[i]->relative_depth == depth) 00986 return root->distances[i]; 00987 return NULL; 00988 } 00989 01009 static inline const struct hwloc_distances_s * 01010 hwloc_get_whole_distance_matrix_by_type(hwloc_topology_t topology, hwloc_obj_type_t type) 01011 { 01012 int depth = hwloc_get_type_depth(topology, type); 01013 if (depth < 0) 01014 return NULL; 01015 return hwloc_get_whole_distance_matrix_by_depth(topology, depth); 01016 } 01017 01031 static inline const struct hwloc_distances_s * 01032 hwloc_get_distance_matrix_covering_obj_by_depth(hwloc_topology_t topology, 01033 hwloc_obj_t obj, unsigned depth, 01034 unsigned *firstp) 01035 { 01036 while (obj && obj->cpuset) { 01037 unsigned i; 01038 for(i=0; i<obj->distances_count; i++) 01039 if (obj->distances[i]->relative_depth == depth - obj->depth) { 01040 if (!obj->distances[i]->nbobjs) 01041 continue; 01042 *firstp = hwloc_get_next_obj_inside_cpuset_by_depth(topology, obj->cpuset, depth, NULL)->logical_index; 01043 return obj->distances[i]; 01044 } 01045 obj = obj->parent; 01046 } 01047 return NULL; 01048 } 01049 01061 static inline int 01062 hwloc_get_latency(hwloc_topology_t topology, 01063 hwloc_obj_t obj1, hwloc_obj_t obj2, 01064 float *latency, float *reverse_latency) 01065 { 01066 hwloc_obj_t ancestor; 01067 const struct hwloc_distances_s * distances; 01068 unsigned first_logical ; 01069 01070 if (obj1->depth != obj2->depth) { 01071 errno = EINVAL; 01072 return -1; 01073 } 01074 01075 ancestor = hwloc_get_common_ancestor_obj(topology, obj1, obj2); 01076 distances = hwloc_get_distance_matrix_covering_obj_by_depth(topology, ancestor, obj1->depth, &first_logical); 01077 if (distances && distances->latency) { 01078 const float * latency_matrix = distances->latency; 01079 unsigned nbobjs = distances->nbobjs; 01080 unsigned l1 = obj1->logical_index - first_logical; 01081 unsigned l2 = obj2->logical_index - first_logical; 01082 *latency = latency_matrix[l1*nbobjs+l2]; 01083 *reverse_latency = latency_matrix[l2*nbobjs+l1]; 01084 return 0; 01085 } 01086 01087 errno = ENOSYS; 01088 return -1; 01089 } 01090 01105 static __inline hwloc_obj_t 01106 hwloc_get_non_io_ancestor_obj(hwloc_topology_t topology , 01107 hwloc_obj_t ioobj) 01108 { 01109 hwloc_obj_t obj = ioobj; 01110 while (obj && !obj->cpuset) { 01111 obj = obj->parent; 01112 } 01113 return obj; 01114 } 01115 01120 static __inline hwloc_obj_t 01121 hwloc_get_next_pcidev(hwloc_topology_t topology, hwloc_obj_t prev) 01122 { 01123 return hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_PCI_DEVICE, prev); 01124 } 01125 01129 static __inline hwloc_obj_t 01130 hwloc_get_pcidev_by_busid(hwloc_topology_t topology, 01131 unsigned domain, unsigned bus, unsigned dev, unsigned func) 01132 { 01133 hwloc_obj_t obj = NULL; 01134 while ((obj = hwloc_get_next_pcidev(topology, obj)) != NULL) { 01135 if (obj->attr->pcidev.domain == domain 01136 && obj->attr->pcidev.bus == bus 01137 && obj->attr->pcidev.dev == dev 01138 && obj->attr->pcidev.func == func) 01139 return obj; 01140 } 01141 return NULL; 01142 } 01143 01147 static __inline hwloc_obj_t 01148 hwloc_get_pcidev_by_busidstring(hwloc_topology_t topology, const char *busid) 01149 { 01150 unsigned domain = 0; /* default */ 01151 unsigned bus, dev, func; 01152 01153 if (sscanf(busid, "%x:%x.%x", &bus, &dev, &func) != 3 01154 && sscanf(busid, "%x:%x:%x.%x", &domain, &bus, &dev, &func) != 4) { 01155 errno = EINVAL; 01156 return NULL; 01157 } 01158 01159 return hwloc_get_pcidev_by_busid(topology, domain, bus, dev, func); 01160 } 01161 01166 static __inline hwloc_obj_t 01167 hwloc_get_next_osdev(hwloc_topology_t topology, hwloc_obj_t prev) 01168 { 01169 return hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_OS_DEVICE, prev); 01170 } 01171 01176 static __inline hwloc_obj_t 01177 hwloc_get_next_bridge(hwloc_topology_t topology, hwloc_obj_t prev) 01178 { 01179 return hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_BRIDGE, prev); 01180 } 01181 01182 /* \brief Checks whether a given bridge covers a given PCI bus. 01183 */ 01184 static __inline int 01185 hwloc_bridge_covers_pcibus(hwloc_obj_t bridge, 01186 unsigned domain, unsigned bus) 01187 { 01188 return bridge->type == HWLOC_OBJ_BRIDGE 01189 && bridge->attr->bridge.downstream_type == HWLOC_OBJ_BRIDGE_PCI 01190 && bridge->attr->bridge.downstream.pci.domain == domain 01191 && bridge->attr->bridge.downstream.pci.secondary_bus <= bus 01192 && bridge->attr->bridge.downstream.pci.subordinate_bus >= bus; 01193 } 01194 01200 static __inline hwloc_obj_t 01201 hwloc_get_hostbridge_by_pcibus(hwloc_topology_t topology, 01202 unsigned domain, unsigned bus) 01203 { 01204 hwloc_obj_t obj = NULL; 01205 while ((obj = hwloc_get_next_bridge(topology, obj)) != NULL) { 01206 if (hwloc_bridge_covers_pcibus(obj, domain, bus)) { 01207 /* found bridge covering this pcibus, make sure it's a hostbridge */ 01208 assert(obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_HOST); 01209 assert(obj->parent->type != HWLOC_OBJ_BRIDGE); 01210 assert(obj->parent->cpuset); 01211 return obj; 01212 } 01213 } 01214 return NULL; 01215 } 01216 01221 #ifdef __cplusplus 01222 } /* extern "C" */ 01223 #endif 01224 01225 01226 #endif /* HWLOC_HELPER_H */