1 /*
2  * Copyright © 2020 Inria.  All rights reserved.
3  * See COPYING in top-level directory.
4  */
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <assert.h>
9 
10 #include "hwloc.h"
11 
12 static void
check_memattr(hwloc_topology_t topology,const char * name,hwloc_memattr_id_t id,unsigned long flags)13 check_memattr(hwloc_topology_t topology, const char *name, hwloc_memattr_id_t id, unsigned long flags)
14 {
15   hwloc_memattr_id_t gotid;
16   const char *gotname;
17   unsigned long gotflags;
18   int err;
19 
20   err = hwloc_memattr_get_by_name(topology, name, &gotid);
21   assert(!err);
22   assert(id == gotid);
23 
24   err = hwloc_memattr_get_name(topology, id, &gotname);
25   assert(!err);
26   assert(!strcmp(gotname, name));
27 
28   err = hwloc_memattr_get_flags(topology, id, &gotflags);
29   assert(!err);
30   assert(gotflags == flags);
31 }
32 
33 int
main(void)34 main(void)
35 {
36   hwloc_topology_t topology;
37   const char *gotname;
38   hwloc_memattr_id_t id, id2, gotid;
39   struct hwloc_location loc, locs[2];
40   unsigned nrlocs, nrtgs, i;
41   hwloc_uint64_t gotvalue;
42   hwloc_obj_t node, targets[4];
43   int err;
44   hwloc_bitmap_t bitmap;
45 
46   err = hwloc_topology_init(&topology);
47   assert(!err);
48   err = hwloc_topology_set_synthetic(topology, "node:4 pu:2");
49   assert(!err);
50   err = hwloc_topology_load(topology);
51   assert(!err);
52 
53   /* check get local nodes */
54   err = hwloc_get_local_numanode_objs(topology, NULL, NULL, NULL, 0);
55   assert(err < 0);
56   /* get all nodes */
57   loc.type = HWLOC_LOCATION_TYPE_OBJECT;
58   loc.location.object = hwloc_get_root_obj(topology);
59   nrtgs = 4;
60   err = hwloc_get_local_numanode_objs(topology, &loc, &nrtgs, targets, HWLOC_LOCAL_NUMANODE_FLAG_ALL);
61   assert(!err);
62   assert(nrtgs == 4);
63   assert(targets[0] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0));
64   assert(targets[1] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 1));
65   assert(targets[2] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2));
66   assert(targets[3] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 3));
67   /* get root local nodes (none) */
68   loc.type = HWLOC_LOCATION_TYPE_OBJECT;
69   loc.location.object = hwloc_get_root_obj(topology);
70   nrtgs = 4;
71   err = hwloc_get_local_numanode_objs(topology, &loc, &nrtgs, targets, 0);
72   assert(!err);
73   assert(nrtgs == 0);
74   /* get root-or-smaller local nodes (all) */
75   loc.type = HWLOC_LOCATION_TYPE_OBJECT;
76   loc.location.object = hwloc_get_root_obj(topology);
77   nrtgs = 4;
78   err = hwloc_get_local_numanode_objs(topology, &loc, &nrtgs, targets, HWLOC_LOCAL_NUMANODE_FLAG_SMALLER_LOCALITY);
79   assert(!err);
80   assert(nrtgs == 4);
81   assert(targets[0] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0));
82   assert(targets[1] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 1));
83   assert(targets[2] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2));
84   assert(targets[3] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 3));
85   /* get PU local nodes (none) */
86   loc.type = HWLOC_LOCATION_TYPE_OBJECT;
87   loc.location.object = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PU, 1);
88   nrtgs = 4;
89   err = hwloc_get_local_numanode_objs(topology, &loc, &nrtgs, targets, 0);
90   assert(!err);
91   assert(nrtgs == 0);
92   /* get PU-or-larger local nodes (1) */
93   loc.type = HWLOC_LOCATION_TYPE_OBJECT;
94   loc.location.object = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PU, 7);
95   nrtgs = 4;
96   err = hwloc_get_local_numanode_objs(topology, &loc, &nrtgs, targets, HWLOC_LOCAL_NUMANODE_FLAG_LARGER_LOCALITY);
97   assert(!err);
98   assert(nrtgs == 1);
99   assert(targets[0] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 3));
100   /* get node local nodes (1) */
101   loc.type = HWLOC_LOCATION_TYPE_OBJECT;
102   loc.location.object = hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2);
103   nrtgs = 4;
104   err = hwloc_get_local_numanode_objs(topology, &loc, &nrtgs, targets, 0);
105   assert(!err);
106   assert(nrtgs == 1);
107   assert(targets[0] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2));
108   /* get 2-node local nodes (0) */
109   loc.type = HWLOC_LOCATION_TYPE_CPUSET;
110   loc.location.cpuset = hwloc_bitmap_alloc();
111   hwloc_bitmap_set_range(loc.location.cpuset, 2, 5);
112   nrtgs = 4;
113   err = hwloc_get_local_numanode_objs(topology, &loc, &nrtgs, targets, 0);
114   assert(!err);
115   assert(nrtgs == 0);
116   /* get 2-node-or-larger local nodes (0) */
117   nrtgs = 4;
118   err = hwloc_get_local_numanode_objs(topology, &loc, &nrtgs, targets, HWLOC_LOCAL_NUMANODE_FLAG_LARGER_LOCALITY);
119   assert(!err);
120   assert(nrtgs == 0);
121   /* get 2-node-or-smaller local nodes (2) */
122   nrtgs = 4;
123   err = hwloc_get_local_numanode_objs(topology, &loc, &nrtgs, targets, HWLOC_LOCAL_NUMANODE_FLAG_SMALLER_LOCALITY);
124   assert(!err);
125   assert(nrtgs == 2);
126   assert(targets[0] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 1));
127   assert(targets[1] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2));
128   hwloc_bitmap_free(loc.location.cpuset);
129 
130   /* check default memattrs */
131   check_memattr(topology, "Capacity", HWLOC_MEMATTR_ID_CAPACITY, HWLOC_MEMATTR_FLAG_HIGHER_FIRST);
132   check_memattr(topology, "Locality", HWLOC_MEMATTR_ID_LOCALITY, HWLOC_MEMATTR_FLAG_LOWER_FIRST);
133   check_memattr(topology, "Bandwidth", HWLOC_MEMATTR_ID_BANDWIDTH, HWLOC_MEMATTR_FLAG_HIGHER_FIRST|HWLOC_MEMATTR_FLAG_NEED_INITIATOR);
134   check_memattr(topology, "Latency", HWLOC_MEMATTR_ID_LATENCY, HWLOC_MEMATTR_FLAG_LOWER_FIRST|HWLOC_MEMATTR_FLAG_NEED_INITIATOR);
135 
136   /* check convenience memattr values */
137   err = hwloc_memattr_get_value(topology, HWLOC_MEMATTR_ID_CAPACITY,
138                                 hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 1), NULL, 0,
139                                 &gotvalue);
140   assert(!err);
141   assert(gotvalue == 1024*1024*1024);
142   err = hwloc_memattr_get_value(topology, HWLOC_MEMATTR_ID_LOCALITY,
143                                 hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2), NULL, 0,
144                                 &gotvalue);
145   assert(!err);
146   assert(gotvalue == 2);
147   nrtgs = 0;
148   err = hwloc_memattr_get_targets(topology, HWLOC_MEMATTR_ID_LOCALITY, NULL, 0, &nrtgs, targets, NULL);
149   assert(!err);
150   assert(nrtgs == 4);
151   nrtgs = 4;
152   err = hwloc_memattr_get_targets(topology, HWLOC_MEMATTR_ID_LOCALITY, NULL, 0, &nrtgs, targets, NULL);
153   assert(!err);
154   assert(nrtgs == 4);
155   assert(targets[0] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0));
156   assert(targets[1] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 1));
157   assert(targets[2] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2));
158   assert(targets[3] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 3));
159 
160   /* look for unexisting memattr */
161   err = hwloc_memattr_get_by_name(topology, "foobarrrrr", &gotid);
162   assert(err < 0);
163   err = hwloc_memattr_get_name(topology, HWLOC_MEMATTR_ID_LATENCY+1, &gotname);
164   assert(err < 0);
165 
166   /* (fail to) register with invalid flags */
167   err = hwloc_memattr_register(topology, "foobar", 0, &id);
168   assert(err < 0);
169   assert(errno == EINVAL);
170 
171   /* (fail to) register with existing name */
172   err = hwloc_memattr_register(topology, "Capacity", HWLOC_MEMATTR_FLAG_HIGHER_FIRST, &id);
173   assert(err < 0);
174   assert(errno == EBUSY);
175 
176   /********************************
177    * new attribute with initiators
178    */
179 
180   /* register with initiator */
181   err = hwloc_memattr_register(topology, "foobar", HWLOC_MEMATTR_FLAG_LOWER_FIRST|HWLOC_MEMATTR_FLAG_NEED_INITIATOR, &id);
182   assert(!err);
183   /* check it */
184   check_memattr(topology, "foobar", id, HWLOC_MEMATTR_FLAG_LOWER_FIRST|HWLOC_MEMATTR_FLAG_NEED_INITIATOR);
185 
186   /* check 0 target */
187   nrtgs = 0;
188   err = hwloc_memattr_get_targets(topology, id, NULL, 0, &nrtgs, NULL, NULL);
189   assert(!err);
190   assert(!nrtgs);
191 
192   /* add a new value for the first NUMA node */
193   node = hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0);
194   loc.type = HWLOC_LOCATION_TYPE_OBJECT;
195   loc.location.object = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PU, hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_PU)-1);
196   err = hwloc_memattr_set_value(topology, id, node,
197                                 &loc, 0, 2345);
198   assert(!err);
199 
200   /* check 1 target */
201   nrtgs = 4;
202   err = hwloc_memattr_get_targets(topology, id, NULL, 0, &nrtgs, targets, NULL);
203   assert(!err);
204   assert(nrtgs == 1);
205   assert(targets[0] == node);
206 
207   /* check that value */
208   err = hwloc_memattr_get_value(topology, id, node, &loc, 0, &gotvalue);
209   assert(!err);
210   assert(gotvalue == 2345);
211 
212   /* try with NULL or unknown initiators */
213   loc.type = HWLOC_LOCATION_TYPE_OBJECT;
214   loc.location.object = NULL;
215   err = hwloc_memattr_get_value(topology, id, node, &loc, 0, &gotvalue);
216   assert(err < 0);
217 
218   loc.type = HWLOC_LOCATION_TYPE_OBJECT;
219   loc.location.object = hwloc_get_root_obj(topology);
220   err = hwloc_memattr_get_value(topology, id, node, &loc, 0, &gotvalue);
221   assert(err < 0);
222 
223   loc.type = HWLOC_LOCATION_TYPE_CPUSET;
224   loc.location.cpuset = NULL;
225   err = hwloc_memattr_get_value(topology, id, node, &loc, 0, &gotvalue);
226   assert(err < 0);
227 
228   loc.type = HWLOC_LOCATION_TYPE_CPUSET;
229   loc.location.cpuset = hwloc_get_root_obj(topology)->cpuset;
230   err = hwloc_memattr_get_value(topology, id, node, &loc, 0, &gotvalue);
231   assert(err < 0);
232 
233   /* check initiators */
234   nrlocs = 0;
235   err = hwloc_memattr_get_initiators(topology, id, node, 0, &nrlocs, NULL, NULL);
236   assert(!err);
237   assert(nrlocs == 1);
238   /* try first without values */
239   err = hwloc_memattr_get_initiators(topology, id, node, 0, &nrlocs, &loc, NULL);
240   assert(!err);
241   assert(nrlocs == 1);
242   assert(loc.type == HWLOC_LOCATION_TYPE_OBJECT);
243   assert(loc.location.object != NULL);
244   assert(loc.location.object->type == HWLOC_OBJ_PU);
245   assert(loc.location.object->logical_index == (unsigned) (hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_PU) - 1));
246   /* try again with values */
247   err = hwloc_memattr_get_initiators(topology, id, node, 0, &nrlocs, &loc, &gotvalue);
248   assert(!err);
249   assert(nrlocs == 1);
250   assert(loc.type == HWLOC_LOCATION_TYPE_OBJECT);
251   assert(loc.location.object != NULL);
252   assert(loc.location.object->type == HWLOC_OBJ_PU);
253   assert(loc.location.object->logical_index == (unsigned) (hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_PU) - 1));
254   assert(gotvalue == 2345);
255 
256   /***********************************
257    * new attribute without initiators
258    */
259 
260   /* register without initiator */
261   err = hwloc_memattr_register(topology, "barnoinit", HWLOC_MEMATTR_FLAG_HIGHER_FIRST, &id2);
262   assert(!err);
263   /* check it */
264   check_memattr(topology, "barnoinit", id2, HWLOC_MEMATTR_FLAG_HIGHER_FIRST);
265 
266   /* check 0 target */
267   nrtgs = 0;
268   err = hwloc_memattr_get_targets(topology, id2, NULL, 0, &nrtgs, NULL, NULL);
269   assert(!err);
270   assert(!nrtgs);
271 
272   /* add a new value for the last NUMA node */
273   node = hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_NUMANODE)-1);
274   err = hwloc_memattr_set_value(topology, id2, node,
275                                 NULL, 0, 3456);
276   assert(!err);
277 
278   /* force refresh */
279   err = hwloc_topology_refresh(topology);
280   assert(!err);
281 
282   /* check 1 target */
283   nrtgs = 4;
284   err = hwloc_memattr_get_targets(topology, id2, NULL, 0, &nrtgs, targets, NULL);
285   assert(!err);
286   assert(nrtgs == 1);
287   assert(targets[0] == node);
288 
289   /* check that value */
290   err = hwloc_memattr_get_value(topology, id2, node, NULL, 0, &gotvalue);
291   assert(!err);
292   assert(gotvalue == 3456);
293 
294   /* check that initiator is ignored when getting values */
295   loc.type = HWLOC_LOCATION_TYPE_OBJECT;
296   loc.location.object = hwloc_get_root_obj(topology);
297   gotvalue = 0;
298   err = hwloc_memattr_get_value(topology, id2, node, &loc, 0, &gotvalue);
299   assert(!err);
300   assert(gotvalue == 3456);
301 
302   loc.type = HWLOC_LOCATION_TYPE_CPUSET;
303   loc.location.cpuset = hwloc_get_root_obj(topology)->cpuset;
304   gotvalue = 0;
305   err = hwloc_memattr_get_value(topology, id2, node, &loc, 0, &gotvalue);
306   assert(!err);
307   assert(gotvalue == 3456);
308 
309   /* check no initiators are returned */
310   nrlocs = 0;
311   err = hwloc_memattr_get_initiators(topology, id2, node, 0, &nrlocs, NULL, NULL);
312   assert(!err);
313   assert(nrlocs == 0);
314 
315   /**********************************************
316    * add value for both attributes for all nodes
317    */
318   /* use first node as initiator for first attribute */
319   loc.type = HWLOC_LOCATION_TYPE_CPUSET;
320   loc.location.cpuset = hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)->cpuset;
321   for(i=0; i<(unsigned)hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_NUMANODE); i++) {
322     node = hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, i);
323     /* increasing value for first attribute, best target will be first node */
324     err = hwloc_memattr_set_value(topology, id, node,
325                                   &loc, 0, (i+1)*10);
326     assert(!err);
327 
328     /* increasing value for second attribute without initiator, best target will be last node */
329     err = hwloc_memattr_set_value(topology, id2, node,
330                                   NULL, 0, (i+1)*10);
331     assert(!err);
332   }
333 
334   /* check 4 targets for id */
335   nrtgs = 4;
336   err = hwloc_memattr_get_targets(topology, id, NULL, 0, &nrtgs, targets, NULL);
337   assert(!err);
338   assert(nrtgs == 4);
339   /* first target */
340   assert(targets[0] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0));
341   nrlocs = 2;
342   err = hwloc_memattr_get_initiators(topology, id, targets[0], 0, &nrlocs, locs, NULL);
343   assert(!err);
344   assert(nrlocs == 2);
345   assert(locs[0].type == HWLOC_LOCATION_TYPE_OBJECT);
346   assert(locs[0].location.object->type == HWLOC_OBJ_PU);
347   assert(locs[0].location.object->os_index == 7);
348   assert(locs[1].type == HWLOC_LOCATION_TYPE_CPUSET);
349   assert(hwloc_bitmap_isequal(locs[1].location.cpuset, hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)->cpuset));
350   /* second target */
351   assert(targets[1] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 1));
352   nrlocs = 2;
353   err = hwloc_memattr_get_initiators(topology, id, targets[1], 0, &nrlocs, locs, NULL);
354   assert(!err);
355   assert(nrlocs == 1);
356   assert(locs[0].type == HWLOC_LOCATION_TYPE_CPUSET);
357   assert(hwloc_bitmap_isequal(locs[0].location.cpuset, hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)->cpuset));
358   /* third target */
359   assert(targets[2] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2));
360   nrlocs = 2;
361   err = hwloc_memattr_get_initiators(topology, id, targets[2], 0, &nrlocs, locs, NULL);
362   assert(!err);
363   assert(nrlocs == 1);
364   assert(locs[0].type == HWLOC_LOCATION_TYPE_CPUSET);
365   assert(hwloc_bitmap_isequal(locs[0].location.cpuset, hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)->cpuset));
366   /* fourth target */
367   assert(targets[3] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 3));
368   nrlocs = 2;
369   err = hwloc_memattr_get_initiators(topology, id, targets[3], 0, &nrlocs, locs, NULL);
370   assert(!err);
371   assert(nrlocs == 1);
372   assert(locs[0].type == HWLOC_LOCATION_TYPE_CPUSET);
373   assert(hwloc_bitmap_isequal(locs[0].location.cpuset, hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)->cpuset));
374 
375   /* check 4 targets for id with entire topology cpuset */
376   nrtgs = 4;
377   err = hwloc_memattr_get_targets(topology, id, &loc, 0, &nrtgs, targets, NULL);
378   assert(!err);
379   assert(nrtgs == 4);
380   /* check 0 targets for id with entire topology cpuset */
381   nrtgs = 4;
382   loc.type = HWLOC_LOCATION_TYPE_CPUSET;
383   loc.location.cpuset = (hwloc_bitmap_t) hwloc_topology_get_topology_cpuset(topology);
384   err = hwloc_memattr_get_targets(topology, id, &loc, 0, &nrtgs, targets, NULL);
385   assert(!err);
386   assert(nrtgs == 0);
387 
388   /* check 4 targets for id2, no initiators to check */
389   nrtgs = 4;
390   err = hwloc_memattr_get_targets(topology, id2, NULL, 0, &nrtgs, targets, NULL);
391   assert(!err);
392   assert(nrtgs == 4);
393   assert(targets[0] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 3)); /* node 3 was added first */
394   assert(targets[1] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0));
395   assert(targets[2] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 1));
396   assert(targets[3] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2));
397 
398   /* now check best targets from first PU (included in first node used as initiator above) */
399   loc.type = HWLOC_LOCATION_TYPE_CPUSET;
400   loc.location.cpuset = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PU, 0)->cpuset;
401   /* check best is the first node for first attribute (lower first) */
402   err = hwloc_memattr_get_best_target(topology, id, &loc, 0, &node, NULL);
403   assert(!err);
404   assert(node);
405   assert(node->type == HWLOC_OBJ_NUMANODE);
406   assert(node == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0));
407   /* check best is the last node for last attribute (lower first) */
408   err = hwloc_memattr_get_best_target(topology, id2, &loc, 0, &node, NULL);
409   assert(!err);
410   assert(node);
411   assert(node->type == HWLOC_OBJ_NUMANODE);
412   assert(node == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_NUMANODE)-1));
413 
414   /* check best initiator for first NUMA is its own cpuset */
415   err = hwloc_memattr_get_best_initiator(topology, id, node, 0, &loc, NULL);
416   assert(!err);
417   assert(locs[0].type == HWLOC_LOCATION_TYPE_CPUSET);
418   /* check best initiator is invalid for no-initiator memattr */
419   assert(hwloc_bitmap_isequal(locs[0].location.cpuset, hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)->cpuset));
420   err = hwloc_memattr_get_best_initiator(topology, id2, node, 0, &loc, NULL);
421   assert(err == -1);
422   assert(errno == EINVAL);
423 
424   /***************************
425    * restrict to only 3 nodes
426    */
427   bitmap = hwloc_bitmap_alloc();
428   hwloc_bitmap_set_range(bitmap, 0, 2);
429   err = hwloc_topology_restrict(topology, bitmap, HWLOC_RESTRICT_FLAG_BYNODESET);
430   assert(!err);
431   hwloc_bitmap_free(bitmap);
432 
433   /* now only 3 targets for id, last target was removed */
434   nrtgs = 4;
435   err = hwloc_memattr_get_targets(topology, id, NULL, 0, &nrtgs, targets, NULL);
436   assert(!err);
437   assert(nrtgs == 3);
438   /* first target unchanged */
439   assert(targets[0] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0));
440   nrlocs = 2;
441   err = hwloc_memattr_get_initiators(topology, id, targets[0], 0, &nrlocs, locs, NULL);
442   assert(!err);
443   assert(nrlocs == 2);
444   assert(locs[0].type == HWLOC_LOCATION_TYPE_OBJECT);
445   assert(locs[0].location.object->type == HWLOC_OBJ_PU);
446   assert(locs[0].location.object->os_index == 7);
447   assert(locs[1].type == HWLOC_LOCATION_TYPE_CPUSET);
448   assert(hwloc_bitmap_isequal(locs[1].location.cpuset, hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)->cpuset));
449   /* second target unchanged */
450   assert(targets[1] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 1));
451   nrlocs = 2;
452   err = hwloc_memattr_get_initiators(topology, id, targets[1], 0, &nrlocs, locs, NULL);
453   assert(!err);
454   assert(nrlocs == 1);
455   assert(locs[0].type == HWLOC_LOCATION_TYPE_CPUSET);
456   assert(hwloc_bitmap_isequal(locs[0].location.cpuset, hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)->cpuset));
457   /* third target unchanged */
458   assert(targets[2] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2));
459   nrlocs = 2;
460   err = hwloc_memattr_get_initiators(topology, id, targets[2], 0, &nrlocs, locs, NULL);
461   assert(!err);
462   assert(nrlocs == 1);
463   assert(locs[0].type == HWLOC_LOCATION_TYPE_CPUSET);
464   assert(hwloc_bitmap_isequal(locs[0].location.cpuset, hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0)->cpuset));
465   /* fourth target removed */
466 
467   /* now only 3 targets for id2, last target was removed */
468   nrtgs = 4;
469   err = hwloc_memattr_get_targets(topology, id2, NULL, 0, &nrtgs, targets, NULL);
470   assert(!err);
471   assert(nrtgs == 3);
472   assert(targets[0] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0));
473   assert(targets[1] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 1));
474   assert(targets[2] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2));
475 
476   /********************************************
477    * restrict to only the second half of cores
478    */
479   bitmap = hwloc_bitmap_alloc();
480   hwloc_bitmap_set_range(bitmap, 4, 7);
481   err = hwloc_topology_restrict(topology, bitmap, 0);
482   assert(!err);
483   hwloc_bitmap_free(bitmap);
484 
485   /* now only 1 target for id, all cpuset initiators removed */
486   nrtgs = 4;
487   err = hwloc_memattr_get_targets(topology, id, NULL, 0, &nrtgs, targets, NULL);
488   assert(!err);
489   assert(nrtgs == 1);
490   /* first target only has one initiator */
491   assert(targets[0] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2)); /* CPUless node:0 became node:2 */
492   nrlocs = 2;
493   err = hwloc_memattr_get_initiators(topology, id, targets[0], 0, &nrlocs, locs, NULL);
494   assert(!err);
495   assert(nrlocs == 1);
496   assert(locs[0].type == HWLOC_LOCATION_TYPE_OBJECT);
497   assert(locs[0].location.object->type == HWLOC_OBJ_PU);
498   assert(locs[0].location.object->os_index == 7);
499   /* second, third and fourth targets removed */
500 
501   /* still only 3 targets for id2 */
502   nrtgs = 4;
503   err = hwloc_memattr_get_targets(topology, id2, NULL, 0, &nrtgs, targets, NULL);
504   assert(!err);
505   assert(nrtgs == 3);
506   assert(targets[0] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2)); /* CPUless node:0 became node:2 */
507   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() */
508   assert(targets[2] == hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0));
509 
510   hwloc_topology_destroy(topology);
511   return 0;
512 }
513 
514