/* * Copyright © 2020 Inria. All rights reserved. * See COPYING in top-level directory. */ #include #include #include #include "hwloc.h" static void check_memattr(hwloc_topology_t topology, const char *name, hwloc_memattr_id_t id, unsigned long flags) { hwloc_memattr_id_t gotid; const char *gotname; unsigned long gotflags; int err; err = hwloc_memattr_get_by_name(topology, name, &gotid); assert(!err); assert(id == gotid); err = hwloc_memattr_get_name(topology, id, &gotname); assert(!err); assert(!strcmp(gotname, name)); err = hwloc_memattr_get_flags(topology, id, &gotflags); assert(!err); assert(gotflags == flags); } int main(void) { hwloc_topology_t topology; const char *gotname; hwloc_memattr_id_t id, id2, gotid; struct hwloc_location loc, locs[2]; unsigned nrlocs, nrtgs, i; hwloc_uint64_t gotvalue; hwloc_obj_t node, targets[4]; int err; hwloc_bitmap_t bitmap; err = hwloc_topology_init(&topology); assert(!err); err = hwloc_topology_set_synthetic(topology, "node:4 pu:2"); assert(!err); err = hwloc_topology_load(topology); assert(!err); /* check get local nodes */ err = hwloc_get_local_numanode_objs(topology, NULL, NULL, NULL, 0); assert(err < 0); /* get all nodes */ loc.type = HWLOC_LOCATION_TYPE_OBJECT; loc.location.object = hwloc_get_root_obj(topology); nrtgs = 4; err = hwloc_get_local_numanode_objs(topology, &loc, &nrtgs, targets, HWLOC_LOCAL_NUMANODE_FLAG_ALL); assert(!err); assert(nrtgs == 4); assert(targets[0] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)); assert(targets[1] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 1)); assert(targets[2] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2)); assert(targets[3] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 3)); /* get root local nodes (none) */ loc.type = HWLOC_LOCATION_TYPE_OBJECT; loc.location.object = hwloc_get_root_obj(topology); nrtgs = 4; err = hwloc_get_local_numanode_objs(topology, &loc, &nrtgs, targets, 0); assert(!err); assert(nrtgs == 0); /* get root-or-smaller local nodes (all) */ loc.type = HWLOC_LOCATION_TYPE_OBJECT; loc.location.object = hwloc_get_root_obj(topology); nrtgs = 4; err = hwloc_get_local_numanode_objs(topology, &loc, &nrtgs, targets, HWLOC_LOCAL_NUMANODE_FLAG_SMALLER_LOCALITY); assert(!err); assert(nrtgs == 4); assert(targets[0] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)); assert(targets[1] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 1)); assert(targets[2] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2)); assert(targets[3] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 3)); /* get PU local nodes (none) */ loc.type = HWLOC_LOCATION_TYPE_OBJECT; loc.location.object = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PU, 1); nrtgs = 4; err = hwloc_get_local_numanode_objs(topology, &loc, &nrtgs, targets, 0); assert(!err); assert(nrtgs == 0); /* get PU-or-larger local nodes (1) */ loc.type = HWLOC_LOCATION_TYPE_OBJECT; loc.location.object = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PU, 7); nrtgs = 4; err = hwloc_get_local_numanode_objs(topology, &loc, &nrtgs, targets, HWLOC_LOCAL_NUMANODE_FLAG_LARGER_LOCALITY); assert(!err); assert(nrtgs == 1); assert(targets[0] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 3)); /* get node local nodes (1) */ loc.type = HWLOC_LOCATION_TYPE_OBJECT; loc.location.object = hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2); nrtgs = 4; err = hwloc_get_local_numanode_objs(topology, &loc, &nrtgs, targets, 0); assert(!err); assert(nrtgs == 1); assert(targets[0] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2)); /* get 2-node local nodes (0) */ loc.type = HWLOC_LOCATION_TYPE_CPUSET; loc.location.cpuset = hwloc_bitmap_alloc(); hwloc_bitmap_set_range(loc.location.cpuset, 2, 5); nrtgs = 4; err = hwloc_get_local_numanode_objs(topology, &loc, &nrtgs, targets, 0); assert(!err); assert(nrtgs == 0); /* get 2-node-or-larger local nodes (0) */ nrtgs = 4; err = hwloc_get_local_numanode_objs(topology, &loc, &nrtgs, targets, HWLOC_LOCAL_NUMANODE_FLAG_LARGER_LOCALITY); assert(!err); assert(nrtgs == 0); /* get 2-node-or-smaller local nodes (2) */ nrtgs = 4; err = hwloc_get_local_numanode_objs(topology, &loc, &nrtgs, targets, HWLOC_LOCAL_NUMANODE_FLAG_SMALLER_LOCALITY); assert(!err); assert(nrtgs == 2); assert(targets[0] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 1)); assert(targets[1] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2)); hwloc_bitmap_free(loc.location.cpuset); /* check default memattrs */ check_memattr(topology, "Capacity", HWLOC_MEMATTR_ID_CAPACITY, HWLOC_MEMATTR_FLAG_HIGHER_FIRST); check_memattr(topology, "Locality", HWLOC_MEMATTR_ID_LOCALITY, HWLOC_MEMATTR_FLAG_LOWER_FIRST); check_memattr(topology, "Bandwidth", HWLOC_MEMATTR_ID_BANDWIDTH, HWLOC_MEMATTR_FLAG_HIGHER_FIRST|HWLOC_MEMATTR_FLAG_NEED_INITIATOR); check_memattr(topology, "Latency", HWLOC_MEMATTR_ID_LATENCY, HWLOC_MEMATTR_FLAG_LOWER_FIRST|HWLOC_MEMATTR_FLAG_NEED_INITIATOR); /* check convenience memattr values */ err = hwloc_memattr_get_value(topology, HWLOC_MEMATTR_ID_CAPACITY, hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 1), NULL, 0, &gotvalue); assert(!err); assert(gotvalue == 1024*1024*1024); err = hwloc_memattr_get_value(topology, HWLOC_MEMATTR_ID_LOCALITY, hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2), NULL, 0, &gotvalue); assert(!err); assert(gotvalue == 2); nrtgs = 0; err = hwloc_memattr_get_targets(topology, HWLOC_MEMATTR_ID_LOCALITY, NULL, 0, &nrtgs, targets, NULL); assert(!err); assert(nrtgs == 4); nrtgs = 4; err = hwloc_memattr_get_targets(topology, HWLOC_MEMATTR_ID_LOCALITY, NULL, 0, &nrtgs, targets, NULL); assert(!err); assert(nrtgs == 4); assert(targets[0] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)); assert(targets[1] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 1)); assert(targets[2] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2)); assert(targets[3] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 3)); /* look for unexisting memattr */ err = hwloc_memattr_get_by_name(topology, "foobarrrrr", &gotid); assert(err < 0); err = hwloc_memattr_get_name(topology, HWLOC_MEMATTR_ID_LATENCY+1, &gotname); assert(err < 0); /* (fail to) register with invalid flags */ err = hwloc_memattr_register(topology, "foobar", 0, &id); assert(err < 0); assert(errno == EINVAL); /* (fail to) register with existing name */ err = hwloc_memattr_register(topology, "Capacity", HWLOC_MEMATTR_FLAG_HIGHER_FIRST, &id); assert(err < 0); assert(errno == EBUSY); /******************************** * new attribute with initiators */ /* register with initiator */ err = hwloc_memattr_register(topology, "foobar", HWLOC_MEMATTR_FLAG_LOWER_FIRST|HWLOC_MEMATTR_FLAG_NEED_INITIATOR, &id); assert(!err); /* check it */ check_memattr(topology, "foobar", id, HWLOC_MEMATTR_FLAG_LOWER_FIRST|HWLOC_MEMATTR_FLAG_NEED_INITIATOR); /* check 0 target */ nrtgs = 0; err = hwloc_memattr_get_targets(topology, id, NULL, 0, &nrtgs, NULL, NULL); assert(!err); assert(!nrtgs); /* add a new value for the first NUMA node */ node = hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0); loc.type = HWLOC_LOCATION_TYPE_OBJECT; loc.location.object = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PU, hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_PU)-1); err = hwloc_memattr_set_value(topology, id, node, &loc, 0, 2345); assert(!err); /* check 1 target */ nrtgs = 4; err = hwloc_memattr_get_targets(topology, id, NULL, 0, &nrtgs, targets, NULL); assert(!err); assert(nrtgs == 1); assert(targets[0] == node); /* check that value */ err = hwloc_memattr_get_value(topology, id, node, &loc, 0, &gotvalue); assert(!err); assert(gotvalue == 2345); /* try with NULL or unknown initiators */ loc.type = HWLOC_LOCATION_TYPE_OBJECT; loc.location.object = NULL; err = hwloc_memattr_get_value(topology, id, node, &loc, 0, &gotvalue); assert(err < 0); loc.type = HWLOC_LOCATION_TYPE_OBJECT; loc.location.object = hwloc_get_root_obj(topology); err = hwloc_memattr_get_value(topology, id, node, &loc, 0, &gotvalue); assert(err < 0); loc.type = HWLOC_LOCATION_TYPE_CPUSET; loc.location.cpuset = NULL; err = hwloc_memattr_get_value(topology, id, node, &loc, 0, &gotvalue); assert(err < 0); loc.type = HWLOC_LOCATION_TYPE_CPUSET; loc.location.cpuset = hwloc_get_root_obj(topology)->cpuset; err = hwloc_memattr_get_value(topology, id, node, &loc, 0, &gotvalue); assert(err < 0); /* check initiators */ nrlocs = 0; err = hwloc_memattr_get_initiators(topology, id, node, 0, &nrlocs, NULL, NULL); assert(!err); assert(nrlocs == 1); /* try first without values */ err = hwloc_memattr_get_initiators(topology, id, node, 0, &nrlocs, &loc, NULL); assert(!err); assert(nrlocs == 1); assert(loc.type == HWLOC_LOCATION_TYPE_OBJECT); assert(loc.location.object != NULL); assert(loc.location.object->type == HWLOC_OBJ_PU); assert(loc.location.object->logical_index == (unsigned) (hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_PU) - 1)); /* try again with values */ err = hwloc_memattr_get_initiators(topology, id, node, 0, &nrlocs, &loc, &gotvalue); assert(!err); assert(nrlocs == 1); assert(loc.type == HWLOC_LOCATION_TYPE_OBJECT); assert(loc.location.object != NULL); assert(loc.location.object->type == HWLOC_OBJ_PU); assert(loc.location.object->logical_index == (unsigned) (hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_PU) - 1)); assert(gotvalue == 2345); /*********************************** * new attribute without initiators */ /* register without initiator */ err = hwloc_memattr_register(topology, "barnoinit", HWLOC_MEMATTR_FLAG_HIGHER_FIRST, &id2); assert(!err); /* check it */ check_memattr(topology, "barnoinit", id2, HWLOC_MEMATTR_FLAG_HIGHER_FIRST); /* check 0 target */ nrtgs = 0; err = hwloc_memattr_get_targets(topology, id2, NULL, 0, &nrtgs, NULL, NULL); assert(!err); assert(!nrtgs); /* add a new value for the last NUMA node */ node = hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_NUMANODE)-1); err = hwloc_memattr_set_value(topology, id2, node, NULL, 0, 3456); assert(!err); /* force refresh */ err = hwloc_topology_refresh(topology); assert(!err); /* check 1 target */ nrtgs = 4; err = hwloc_memattr_get_targets(topology, id2, NULL, 0, &nrtgs, targets, NULL); assert(!err); assert(nrtgs == 1); assert(targets[0] == node); /* check that value */ err = hwloc_memattr_get_value(topology, id2, node, NULL, 0, &gotvalue); assert(!err); assert(gotvalue == 3456); /* check that initiator is ignored when getting values */ loc.type = HWLOC_LOCATION_TYPE_OBJECT; loc.location.object = hwloc_get_root_obj(topology); gotvalue = 0; err = hwloc_memattr_get_value(topology, id2, node, &loc, 0, &gotvalue); assert(!err); assert(gotvalue == 3456); loc.type = HWLOC_LOCATION_TYPE_CPUSET; loc.location.cpuset = hwloc_get_root_obj(topology)->cpuset; gotvalue = 0; err = hwloc_memattr_get_value(topology, id2, node, &loc, 0, &gotvalue); assert(!err); assert(gotvalue == 3456); /* check no initiators are returned */ nrlocs = 0; err = hwloc_memattr_get_initiators(topology, id2, node, 0, &nrlocs, NULL, NULL); assert(!err); assert(nrlocs == 0); /********************************************** * add value for both attributes for all nodes */ /* use first node as initiator for first attribute */ loc.type = HWLOC_LOCATION_TYPE_CPUSET; loc.location.cpuset = hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)->cpuset; for(i=0; i<(unsigned)hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_NUMANODE); i++) { node = hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, i); /* increasing value for first attribute, best target will be first node */ err = hwloc_memattr_set_value(topology, id, node, &loc, 0, (i+1)*10); assert(!err); /* increasing value for second attribute without initiator, best target will be last node */ err = hwloc_memattr_set_value(topology, id2, node, NULL, 0, (i+1)*10); assert(!err); } /* check 4 targets for id */ nrtgs = 4; err = hwloc_memattr_get_targets(topology, id, NULL, 0, &nrtgs, targets, NULL); assert(!err); assert(nrtgs == 4); /* first target */ assert(targets[0] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)); nrlocs = 2; err = hwloc_memattr_get_initiators(topology, id, targets[0], 0, &nrlocs, locs, NULL); assert(!err); assert(nrlocs == 2); assert(locs[0].type == HWLOC_LOCATION_TYPE_OBJECT); assert(locs[0].location.object->type == HWLOC_OBJ_PU); assert(locs[0].location.object->os_index == 7); assert(locs[1].type == HWLOC_LOCATION_TYPE_CPUSET); assert(hwloc_bitmap_isequal(locs[1].location.cpuset, hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)->cpuset)); /* second target */ assert(targets[1] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 1)); nrlocs = 2; err = hwloc_memattr_get_initiators(topology, id, targets[1], 0, &nrlocs, locs, NULL); assert(!err); assert(nrlocs == 1); assert(locs[0].type == HWLOC_LOCATION_TYPE_CPUSET); assert(hwloc_bitmap_isequal(locs[0].location.cpuset, hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)->cpuset)); /* third target */ assert(targets[2] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2)); nrlocs = 2; err = hwloc_memattr_get_initiators(topology, id, targets[2], 0, &nrlocs, locs, NULL); assert(!err); assert(nrlocs == 1); assert(locs[0].type == HWLOC_LOCATION_TYPE_CPUSET); assert(hwloc_bitmap_isequal(locs[0].location.cpuset, hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)->cpuset)); /* fourth target */ assert(targets[3] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 3)); nrlocs = 2; err = hwloc_memattr_get_initiators(topology, id, targets[3], 0, &nrlocs, locs, NULL); assert(!err); assert(nrlocs == 1); assert(locs[0].type == HWLOC_LOCATION_TYPE_CPUSET); assert(hwloc_bitmap_isequal(locs[0].location.cpuset, hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)->cpuset)); /* check 4 targets for id with entire topology cpuset */ nrtgs = 4; err = hwloc_memattr_get_targets(topology, id, &loc, 0, &nrtgs, targets, NULL); assert(!err); assert(nrtgs == 4); /* check 0 targets for id with entire topology cpuset */ nrtgs = 4; loc.type = HWLOC_LOCATION_TYPE_CPUSET; loc.location.cpuset = (hwloc_bitmap_t) hwloc_topology_get_topology_cpuset(topology); err = hwloc_memattr_get_targets(topology, id, &loc, 0, &nrtgs, targets, NULL); assert(!err); assert(nrtgs == 0); /* check 4 targets for id2, no initiators to check */ nrtgs = 4; err = hwloc_memattr_get_targets(topology, id2, NULL, 0, &nrtgs, targets, NULL); assert(!err); assert(nrtgs == 4); assert(targets[0] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 3)); /* node 3 was added first */ assert(targets[1] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)); assert(targets[2] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 1)); assert(targets[3] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2)); /* now check best targets from first PU (included in first node used as initiator above) */ loc.type = HWLOC_LOCATION_TYPE_CPUSET; loc.location.cpuset = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PU, 0)->cpuset; /* check best is the first node for first attribute (lower first) */ err = hwloc_memattr_get_best_target(topology, id, &loc, 0, &node, NULL); assert(!err); assert(node); assert(node->type == HWLOC_OBJ_NUMANODE); assert(node == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)); /* check best is the last node for last attribute (lower first) */ err = hwloc_memattr_get_best_target(topology, id2, &loc, 0, &node, NULL); assert(!err); assert(node); assert(node->type == HWLOC_OBJ_NUMANODE); assert(node == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_NUMANODE)-1)); /* check best initiator for first NUMA is its own cpuset */ err = hwloc_memattr_get_best_initiator(topology, id, node, 0, &loc, NULL); assert(!err); assert(locs[0].type == HWLOC_LOCATION_TYPE_CPUSET); /* check best initiator is invalid for no-initiator memattr */ assert(hwloc_bitmap_isequal(locs[0].location.cpuset, hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)->cpuset)); err = hwloc_memattr_get_best_initiator(topology, id2, node, 0, &loc, NULL); assert(err == -1); assert(errno == EINVAL); /*************************** * restrict to only 3 nodes */ bitmap = hwloc_bitmap_alloc(); hwloc_bitmap_set_range(bitmap, 0, 2); err = hwloc_topology_restrict(topology, bitmap, HWLOC_RESTRICT_FLAG_BYNODESET); assert(!err); hwloc_bitmap_free(bitmap); /* now only 3 targets for id, last target was removed */ nrtgs = 4; err = hwloc_memattr_get_targets(topology, id, NULL, 0, &nrtgs, targets, NULL); assert(!err); assert(nrtgs == 3); /* first target unchanged */ assert(targets[0] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)); nrlocs = 2; err = hwloc_memattr_get_initiators(topology, id, targets[0], 0, &nrlocs, locs, NULL); assert(!err); assert(nrlocs == 2); assert(locs[0].type == HWLOC_LOCATION_TYPE_OBJECT); assert(locs[0].location.object->type == HWLOC_OBJ_PU); assert(locs[0].location.object->os_index == 7); assert(locs[1].type == HWLOC_LOCATION_TYPE_CPUSET); assert(hwloc_bitmap_isequal(locs[1].location.cpuset, hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)->cpuset)); /* second target unchanged */ assert(targets[1] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 1)); nrlocs = 2; err = hwloc_memattr_get_initiators(topology, id, targets[1], 0, &nrlocs, locs, NULL); assert(!err); assert(nrlocs == 1); assert(locs[0].type == HWLOC_LOCATION_TYPE_CPUSET); assert(hwloc_bitmap_isequal(locs[0].location.cpuset, hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)->cpuset)); /* third target unchanged */ assert(targets[2] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2)); nrlocs = 2; err = hwloc_memattr_get_initiators(topology, id, targets[2], 0, &nrlocs, locs, NULL); assert(!err); assert(nrlocs == 1); assert(locs[0].type == HWLOC_LOCATION_TYPE_CPUSET); assert(hwloc_bitmap_isequal(locs[0].location.cpuset, hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)->cpuset)); /* fourth target removed */ /* now only 3 targets for id2, last target was removed */ nrtgs = 4; err = hwloc_memattr_get_targets(topology, id2, NULL, 0, &nrtgs, targets, NULL); assert(!err); assert(nrtgs == 3); assert(targets[0] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)); assert(targets[1] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 1)); assert(targets[2] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2)); /******************************************** * restrict to only the second half of cores */ bitmap = hwloc_bitmap_alloc(); hwloc_bitmap_set_range(bitmap, 4, 7); err = hwloc_topology_restrict(topology, bitmap, 0); assert(!err); hwloc_bitmap_free(bitmap); /* now only 1 target for id, all cpuset initiators removed */ nrtgs = 4; err = hwloc_memattr_get_targets(topology, id, NULL, 0, &nrtgs, targets, NULL); assert(!err); assert(nrtgs == 1); /* first target only has one initiator */ assert(targets[0] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2)); /* CPUless node:0 became node:2 */ nrlocs = 2; err = hwloc_memattr_get_initiators(topology, id, targets[0], 0, &nrlocs, locs, NULL); assert(!err); assert(nrlocs == 1); assert(locs[0].type == HWLOC_LOCATION_TYPE_OBJECT); assert(locs[0].location.object->type == HWLOC_OBJ_PU); assert(locs[0].location.object->os_index == 7); /* second, third and fourth targets removed */ /* still only 3 targets for id2 */ nrtgs = 4; err = hwloc_memattr_get_targets(topology, id2, NULL, 0, &nrtgs, targets, NULL); assert(!err); assert(nrtgs == 3); assert(targets[0] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2)); /* CPUless node:0 became node:2 */ assert(targets[1] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 1)); /* 0 and 1 should be reversed, but the core doesn't current reordered those, see FIXME in restrict_object_by_nodeset() */ assert(targets[2] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)); hwloc_topology_destroy(topology); return 0; }