00001
00002
00003
00004
00005
00006
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
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
00053
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
00071 for(depth = 0; ; depth++)
00072 if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) > 0)
00073 return depth-1;
00074
00075
00076
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
00188
00189
00190
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
00236 if (!hwloc_bitmap_intersects(obj->cpuset, set))
00237 return NULL;
00238 while (!hwloc_bitmap_isincluded(obj->cpuset, set)) {
00239
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
00247 return obj;
00248
00249 obj = child;
00250 }
00251
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
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
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
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;
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
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
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
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
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
00613 if (!root->arity || n == 1 || root->depth >= until) {
00614
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
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
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
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
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
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
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
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 }
01080 #endif
01081
01082
01083 #endif