Hardware Locality (hwloc)
1.4
|
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 00250 static inline hwloc_obj_t 00251 hwloc_get_first_largest_obj_inside_cpuset(hwloc_topology_t topology, hwloc_const_cpuset_t set) 00252 { 00253 hwloc_obj_t obj = hwloc_get_root_obj(topology); 00254 if (!obj->cpuset || !hwloc_bitmap_intersects(obj->cpuset, set)) 00255 return NULL; 00256 while (!hwloc_bitmap_isincluded(obj->cpuset, set)) { 00257 /* while the object intersects without being included, look at its children */ 00258 hwloc_obj_t child = NULL; 00259 while ((child = hwloc_get_next_child(topology, obj, child)) != NULL) { 00260 if (child->cpuset && hwloc_bitmap_intersects(child->cpuset, set)) 00261 break; 00262 } 00263 if (!child) 00264 /* no child intersects, return their father */ 00265 return obj; 00266 /* found one intersecting child, look at its children */ 00267 obj = child; 00268 } 00269 /* obj is included, return it */ 00270 return obj; 00271 } 00272 00280 int hwloc_get_largest_objs_inside_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00281 hwloc_obj_t * restrict objs, int max); 00282 00292 static inline hwloc_obj_t 00293 hwloc_get_next_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00294 unsigned depth, hwloc_obj_t prev) 00295 { 00296 hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev); 00297 if (!next || !next->cpuset) 00298 return NULL; 00299 while (next && !hwloc_bitmap_isincluded(next->cpuset, set)) 00300 next = next->next_cousin; 00301 return next; 00302 } 00303 00313 static inline hwloc_obj_t 00314 hwloc_get_next_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00315 hwloc_obj_type_t type, hwloc_obj_t prev) 00316 { 00317 int depth = hwloc_get_type_depth(topology, type); 00318 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00319 return NULL; 00320 return hwloc_get_next_obj_inside_cpuset_by_depth(topology, set, depth, prev); 00321 } 00322 00328 static inline hwloc_obj_t 00329 hwloc_get_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00330 unsigned depth, unsigned idx) 00331 { 00332 hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0); 00333 unsigned count = 0; 00334 if (!obj || !obj->cpuset) 00335 return NULL; 00336 while (obj) { 00337 if (hwloc_bitmap_isincluded(obj->cpuset, set)) { 00338 if (count == idx) 00339 return obj; 00340 count++; 00341 } 00342 obj = obj->next_cousin; 00343 } 00344 return NULL; 00345 } 00346 00356 static inline hwloc_obj_t 00357 hwloc_get_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00358 hwloc_obj_type_t type, unsigned idx) 00359 { 00360 int depth = hwloc_get_type_depth(topology, type); 00361 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00362 return NULL; 00363 return hwloc_get_obj_inside_cpuset_by_depth(topology, set, depth, idx); 00364 } 00365 00371 static inline unsigned 00372 hwloc_get_nbobjs_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00373 unsigned depth) 00374 { 00375 hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0); 00376 unsigned count = 0; 00377 if (!obj || !obj->cpuset) 00378 return 0; 00379 while (obj) { 00380 if (hwloc_bitmap_isincluded(obj->cpuset, set)) 00381 count++; 00382 obj = obj->next_cousin; 00383 } 00384 return count; 00385 } 00386 00396 static inline int 00397 hwloc_get_nbobjs_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set, 00398 hwloc_obj_type_t type) 00399 { 00400 int depth = hwloc_get_type_depth(topology, type); 00401 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) 00402 return 0; 00403 if (depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00404 return -1; /* FIXME: agregate nbobjs from different levels? */ 00405 return hwloc_get_nbobjs_inside_cpuset_by_depth(topology, set, depth); 00406 } 00407 00416 static inline int 00417 hwloc_get_obj_index_inside_cpuset (hwloc_topology_t topology , hwloc_const_cpuset_t set, 00418 hwloc_obj_t obj) 00419 { 00420 int index = 0; 00421 if (!hwloc_bitmap_isincluded(obj->cpuset, set)) 00422 return -1; 00423 /* count how many objects are inside the cpuset on the way from us to the beginning of the level */ 00424 while ((obj = obj->prev_cousin) != NULL) 00425 if (hwloc_bitmap_isincluded(obj->cpuset, set)) 00426 index++; 00427 return index; 00428 } 00429 00444 static inline hwloc_obj_t 00445 hwloc_get_child_covering_cpuset (hwloc_topology_t topology , hwloc_const_cpuset_t set, 00446 hwloc_obj_t parent) 00447 { 00448 hwloc_obj_t child; 00449 if (!parent->cpuset || hwloc_bitmap_iszero(set)) 00450 return NULL; 00451 child = parent->first_child; 00452 while (child) { 00453 if (child->cpuset && hwloc_bitmap_isincluded(set, child->cpuset)) 00454 return child; 00455 child = child->next_sibling; 00456 } 00457 return NULL; 00458 } 00459 00467 static inline hwloc_obj_t 00468 hwloc_get_obj_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set) 00469 { 00470 struct hwloc_obj *current = hwloc_get_root_obj(topology); 00471 if (hwloc_bitmap_iszero(set) || !current->cpuset || !hwloc_bitmap_isincluded(set, current->cpuset)) 00472 return NULL; 00473 while (1) { 00474 hwloc_obj_t child = hwloc_get_child_covering_cpuset(topology, set, current); 00475 if (!child) 00476 return current; 00477 current = child; 00478 } 00479 } 00480 00481 00500 static inline hwloc_obj_t 00501 hwloc_get_next_obj_covering_cpuset_by_depth(hwloc_topology_t topology, hwloc_const_cpuset_t set, 00502 unsigned depth, hwloc_obj_t prev) 00503 { 00504 hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev); 00505 if (!next || !next->cpuset) 00506 return NULL; 00507 while (next && !hwloc_bitmap_intersects(set, next->cpuset)) 00508 next = next->next_cousin; 00509 return next; 00510 } 00511 00527 static inline hwloc_obj_t 00528 hwloc_get_next_obj_covering_cpuset_by_type(hwloc_topology_t topology, hwloc_const_cpuset_t set, 00529 hwloc_obj_type_t type, hwloc_obj_t prev) 00530 { 00531 int depth = hwloc_get_type_depth(topology, type); 00532 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE) 00533 return NULL; 00534 return hwloc_get_next_obj_covering_cpuset_by_depth(topology, set, depth, prev); 00535 } 00536 00552 static inline hwloc_obj_t 00553 hwloc_get_cache_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set) 00554 { 00555 hwloc_obj_t current = hwloc_get_obj_covering_cpuset(topology, set); 00556 while (current) { 00557 if (current->type == HWLOC_OBJ_CACHE) 00558 return current; 00559 current = current->parent; 00560 } 00561 return NULL; 00562 } 00563 00568 static inline hwloc_obj_t 00569 hwloc_get_shared_cache_covering_obj (hwloc_topology_t topology , hwloc_obj_t obj) 00570 { 00571 hwloc_obj_t current = obj->parent; 00572 if (!obj->cpuset) 00573 return NULL; 00574 while (current && current->cpuset) { 00575 if (!hwloc_bitmap_isequal(current->cpuset, obj->cpuset) 00576 && current->type == HWLOC_OBJ_CACHE) 00577 return current; 00578 current = current->parent; 00579 } 00580 return NULL; 00581 } 00582 00607 /* TODO: rather provide an iterator? Provide a way to know how much should be allocated? By returning the total number of objects instead? */ 00608 unsigned hwloc_get_closest_objs (hwloc_topology_t topology, hwloc_obj_t src, hwloc_obj_t * restrict objs, unsigned max); 00609 00622 static inline hwloc_obj_t 00623 hwloc_get_obj_below_by_type (hwloc_topology_t topology, 00624 hwloc_obj_type_t type1, unsigned idx1, 00625 hwloc_obj_type_t type2, unsigned idx2) 00626 { 00627 hwloc_obj_t obj; 00628 obj = hwloc_get_obj_by_type (topology, type1, idx1); 00629 if (!obj || !obj->cpuset) 00630 return NULL; 00631 return hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, type2, idx2); 00632 } 00633 00652 static inline hwloc_obj_t 00653 hwloc_get_obj_below_array_by_type (hwloc_topology_t topology, int nr, hwloc_obj_type_t *typev, unsigned *idxv) 00654 { 00655 hwloc_obj_t obj = hwloc_get_root_obj(topology); 00656 int i; 00657 for(i=0; i<nr; i++) { 00658 if (!obj || !obj->cpuset) 00659 return NULL; 00660 obj = hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, typev[i], idxv[i]); 00661 } 00662 return obj; 00663 } 00664 00688 static inline void 00689 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *root, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until); 00690 static inline void 00691 hwloc_distribute(hwloc_topology_t topology, hwloc_obj_t root, hwloc_cpuset_t *cpuset, unsigned n, unsigned until) 00692 { 00693 unsigned i; 00694 if (!root->arity || n == 1 || root->depth >= until) { 00695 /* Got to the bottom, we can't split any more, put everything there. */ 00696 for (i=0; i<n; i++) 00697 cpuset[i] = hwloc_bitmap_dup(root->cpuset); 00698 return; 00699 } 00700 hwloc_distributev(topology, root->children, root->arity, cpuset, n, until); 00701 } 00702 00710 static inline void 00711 hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *roots, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until) 00712 { 00713 unsigned i; 00714 unsigned tot_weight; 00715 hwloc_cpuset_t *cpusetp = cpuset; 00716 00717 tot_weight = 0; 00718 for (i = 0; i < n_roots; i++) 00719 if (roots[i]->cpuset) 00720 tot_weight += hwloc_bitmap_weight(roots[i]->cpuset); 00721 00722 for (i = 0; i < n_roots && tot_weight; i++) { 00723 /* Give to roots[i] a portion proportional to its weight */ 00724 unsigned weight = roots[i]->cpuset ? hwloc_bitmap_weight(roots[i]->cpuset) : 0; 00725 unsigned chunk = (n * weight + tot_weight-1) / tot_weight; 00726 hwloc_distribute(topology, roots[i], cpusetp, chunk, until); 00727 cpusetp += chunk; 00728 tot_weight -= weight; 00729 n -= chunk; 00730 } 00731 } 00732 00739 static inline void * 00740 hwloc_alloc_membind_policy_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) 00741 { 00742 void *p = hwloc_alloc_membind_nodeset(topology, len, nodeset, policy, flags); 00743 if (p) 00744 return p; 00745 hwloc_set_membind_nodeset(topology, nodeset, policy, flags); 00746 p = hwloc_alloc(topology, len); 00747 if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH) 00748 /* Enforce the binding by touching the data */ 00749 memset(p, 0, len); 00750 return p; 00751 } 00752 00757 static inline void * 00758 hwloc_alloc_membind_policy(hwloc_topology_t topology, size_t len, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags) 00759 { 00760 void *p = hwloc_alloc_membind(topology, len, cpuset, policy, flags); 00761 if (p) 00762 return p; 00763 hwloc_set_membind(topology, cpuset, policy, flags); 00764 p = hwloc_alloc(topology, len); 00765 if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH) 00766 /* Enforce the binding by touching the data */ 00767 memset(p, 0, len); 00768 return p; 00769 } 00770 00787 static inline hwloc_const_cpuset_t 00788 hwloc_topology_get_complete_cpuset(hwloc_topology_t topology) 00789 { 00790 return hwloc_get_root_obj(topology)->complete_cpuset; 00791 } 00792 00803 static inline hwloc_const_cpuset_t 00804 hwloc_topology_get_topology_cpuset(hwloc_topology_t topology) 00805 { 00806 return hwloc_get_root_obj(topology)->cpuset; 00807 } 00808 00818 static inline hwloc_const_cpuset_t 00819 hwloc_topology_get_online_cpuset(hwloc_topology_t topology) 00820 { 00821 return hwloc_get_root_obj(topology)->online_cpuset; 00822 } 00823 00833 static inline hwloc_const_cpuset_t 00834 hwloc_topology_get_allowed_cpuset(hwloc_topology_t topology) 00835 { 00836 return hwloc_get_root_obj(topology)->allowed_cpuset; 00837 } 00838 00855 static inline hwloc_const_nodeset_t 00856 hwloc_topology_get_complete_nodeset(hwloc_topology_t topology) 00857 { 00858 return hwloc_get_root_obj(topology)->complete_nodeset; 00859 } 00860 00871 static inline hwloc_const_nodeset_t 00872 hwloc_topology_get_topology_nodeset(hwloc_topology_t topology) 00873 { 00874 return hwloc_get_root_obj(topology)->nodeset; 00875 } 00876 00886 static inline hwloc_const_nodeset_t 00887 hwloc_topology_get_allowed_nodeset(hwloc_topology_t topology) 00888 { 00889 return hwloc_get_root_obj(topology)->allowed_nodeset; 00890 } 00891 00922 static inline void 00923 hwloc_cpuset_to_nodeset(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset) 00924 { 00925 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 00926 hwloc_obj_t obj; 00927 00928 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) { 00929 if (hwloc_bitmap_iszero(cpuset)) 00930 hwloc_bitmap_zero(nodeset); 00931 else 00932 /* Assume the whole system */ 00933 hwloc_bitmap_fill(nodeset); 00934 return; 00935 } 00936 00937 hwloc_bitmap_zero(nodeset); 00938 obj = NULL; 00939 while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL) 00940 hwloc_bitmap_set(nodeset, obj->os_index); 00941 } 00942 00950 static inline void 00951 hwloc_cpuset_to_nodeset_strict(struct hwloc_topology *topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset) 00952 { 00953 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 00954 hwloc_obj_t obj; 00955 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) 00956 return; 00957 hwloc_bitmap_zero(nodeset); 00958 obj = NULL; 00959 while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL) 00960 hwloc_bitmap_set(nodeset, obj->os_index); 00961 } 00962 00971 static inline void 00972 hwloc_cpuset_from_nodeset(hwloc_topology_t topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset) 00973 { 00974 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 00975 hwloc_obj_t obj; 00976 00977 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) { 00978 if (hwloc_bitmap_iszero(nodeset)) 00979 hwloc_bitmap_zero(cpuset); 00980 else 00981 /* Assume the whole system */ 00982 hwloc_bitmap_fill(cpuset); 00983 return; 00984 } 00985 00986 hwloc_bitmap_zero(cpuset); 00987 obj = NULL; 00988 while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL) { 00989 if (hwloc_bitmap_isset(nodeset, obj->os_index)) 00990 /* no need to check obj->cpuset because objects in levels always have a cpuset */ 00991 hwloc_bitmap_or(cpuset, cpuset, obj->cpuset); 00992 } 00993 } 00994 01002 static inline void 01003 hwloc_cpuset_from_nodeset_strict(struct hwloc_topology *topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset) 01004 { 01005 int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); 01006 hwloc_obj_t obj; 01007 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) 01008 return; 01009 hwloc_bitmap_zero(cpuset); 01010 obj = NULL; 01011 while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL) 01012 if (hwloc_bitmap_isset(nodeset, obj->os_index)) 01013 /* no need to check obj->cpuset because objects in levels always have a cpuset */ 01014 hwloc_bitmap_or(cpuset, cpuset, obj->cpuset); 01015 } 01016 01044 static inline const struct hwloc_distances_s * 01045 hwloc_get_whole_distance_matrix_by_depth(hwloc_topology_t topology, unsigned depth) 01046 { 01047 hwloc_obj_t root = hwloc_get_root_obj(topology); 01048 unsigned i; 01049 for(i=0; i<root->distances_count; i++) 01050 if (root->distances[i]->relative_depth == depth) 01051 return root->distances[i]; 01052 return NULL; 01053 } 01054 01074 static inline const struct hwloc_distances_s * 01075 hwloc_get_whole_distance_matrix_by_type(hwloc_topology_t topology, hwloc_obj_type_t type) 01076 { 01077 int depth = hwloc_get_type_depth(topology, type); 01078 if (depth < 0) 01079 return NULL; 01080 return hwloc_get_whole_distance_matrix_by_depth(topology, depth); 01081 } 01082 01096 static inline const struct hwloc_distances_s * 01097 hwloc_get_distance_matrix_covering_obj_by_depth(hwloc_topology_t topology, 01098 hwloc_obj_t obj, unsigned depth, 01099 unsigned *firstp) 01100 { 01101 while (obj && obj->cpuset) { 01102 unsigned i; 01103 for(i=0; i<obj->distances_count; i++) 01104 if (obj->distances[i]->relative_depth == depth - obj->depth) { 01105 if (!obj->distances[i]->nbobjs) 01106 continue; 01107 *firstp = hwloc_get_next_obj_inside_cpuset_by_depth(topology, obj->cpuset, depth, NULL)->logical_index; 01108 return obj->distances[i]; 01109 } 01110 obj = obj->parent; 01111 } 01112 return NULL; 01113 } 01114 01126 static inline int 01127 hwloc_get_latency(hwloc_topology_t topology, 01128 hwloc_obj_t obj1, hwloc_obj_t obj2, 01129 float *latency, float *reverse_latency) 01130 { 01131 hwloc_obj_t ancestor; 01132 const struct hwloc_distances_s * distances; 01133 unsigned first_logical ; 01134 01135 if (obj1->depth != obj2->depth) { 01136 errno = EINVAL; 01137 return -1; 01138 } 01139 01140 ancestor = hwloc_get_common_ancestor_obj(topology, obj1, obj2); 01141 distances = hwloc_get_distance_matrix_covering_obj_by_depth(topology, ancestor, obj1->depth, &first_logical); 01142 if (distances && distances->latency) { 01143 const float * latency_matrix = distances->latency; 01144 unsigned nbobjs = distances->nbobjs; 01145 unsigned l1 = obj1->logical_index - first_logical; 01146 unsigned l2 = obj2->logical_index - first_logical; 01147 *latency = latency_matrix[l1*nbobjs+l2]; 01148 *reverse_latency = latency_matrix[l2*nbobjs+l1]; 01149 return 0; 01150 } 01151 01152 errno = ENOSYS; 01153 return -1; 01154 } 01155 01170 static inline hwloc_obj_t 01171 hwloc_get_non_io_ancestor_obj(hwloc_topology_t topology , 01172 hwloc_obj_t ioobj) 01173 { 01174 hwloc_obj_t obj = ioobj; 01175 while (obj && !obj->cpuset) { 01176 obj = obj->parent; 01177 } 01178 return obj; 01179 } 01180 01185 static inline hwloc_obj_t 01186 hwloc_get_next_pcidev(hwloc_topology_t topology, hwloc_obj_t prev) 01187 { 01188 return hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_PCI_DEVICE, prev); 01189 } 01190 01194 static inline hwloc_obj_t 01195 hwloc_get_pcidev_by_busid(hwloc_topology_t topology, 01196 unsigned domain, unsigned bus, unsigned dev, unsigned func) 01197 { 01198 hwloc_obj_t obj = NULL; 01199 while ((obj = hwloc_get_next_pcidev(topology, obj)) != NULL) { 01200 if (obj->attr->pcidev.domain == domain 01201 && obj->attr->pcidev.bus == bus 01202 && obj->attr->pcidev.dev == dev 01203 && obj->attr->pcidev.func == func) 01204 return obj; 01205 } 01206 return NULL; 01207 } 01208 01212 static inline hwloc_obj_t 01213 hwloc_get_pcidev_by_busidstring(hwloc_topology_t topology, const char *busid) 01214 { 01215 unsigned domain = 0; /* default */ 01216 unsigned bus, dev, func; 01217 01218 if (sscanf(busid, "%x:%x.%x", &bus, &dev, &func) != 3 01219 && sscanf(busid, "%x:%x:%x.%x", &domain, &bus, &dev, &func) != 4) { 01220 errno = EINVAL; 01221 return NULL; 01222 } 01223 01224 return hwloc_get_pcidev_by_busid(topology, domain, bus, dev, func); 01225 } 01226 01231 static inline hwloc_obj_t 01232 hwloc_get_next_osdev(hwloc_topology_t topology, hwloc_obj_t prev) 01233 { 01234 return hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_OS_DEVICE, prev); 01235 } 01236 01241 static inline hwloc_obj_t 01242 hwloc_get_next_bridge(hwloc_topology_t topology, hwloc_obj_t prev) 01243 { 01244 return hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_BRIDGE, prev); 01245 } 01246 01247 /* \brief Checks whether a given bridge covers a given PCI bus. 01248 */ 01249 static inline int 01250 hwloc_bridge_covers_pcibus(hwloc_obj_t bridge, 01251 unsigned domain, unsigned bus) 01252 { 01253 return bridge->type == HWLOC_OBJ_BRIDGE 01254 && bridge->attr->bridge.downstream_type == HWLOC_OBJ_BRIDGE_PCI 01255 && bridge->attr->bridge.downstream.pci.domain == domain 01256 && bridge->attr->bridge.downstream.pci.secondary_bus <= bus 01257 && bridge->attr->bridge.downstream.pci.subordinate_bus >= bus; 01258 } 01259 01265 static inline hwloc_obj_t 01266 hwloc_get_hostbridge_by_pcibus(hwloc_topology_t topology, 01267 unsigned domain, unsigned bus) 01268 { 01269 hwloc_obj_t obj = NULL; 01270 while ((obj = hwloc_get_next_bridge(topology, obj)) != NULL) { 01271 if (hwloc_bridge_covers_pcibus(obj, domain, bus)) { 01272 /* found bridge covering this pcibus, make sure it's a hostbridge */ 01273 assert(obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_HOST); 01274 assert(obj->parent->type != HWLOC_OBJ_BRIDGE); 01275 assert(obj->parent->cpuset); 01276 return obj; 01277 } 01278 } 01279 return NULL; 01280 } 01281 01286 #ifdef __cplusplus 01287 } /* extern "C" */ 01288 #endif 01289 01290 01291 #endif /* HWLOC_HELPER_H */