This source file includes following definitions.
- hwloc_topology_diff_destroy
- hwloc_append_diff
- hwloc_append_diff_too_complex
- hwloc_append_diff_obj_attr_string
- hwloc_append_diff_obj_attr_uint64
- hwloc_diff_trees
- hwloc_topology_diff_build
- hwloc_apply_diff_one
- hwloc_topology_diff_apply
1
2
3
4
5
6 #include <private/autogen/config.h>
7 #include <private/private.h>
8 #include <private/misc.h>
9
10 int hwloc_topology_diff_destroy(hwloc_topology_diff_t diff)
11 {
12 hwloc_topology_diff_t next;
13 while (diff) {
14 next = diff->generic.next;
15 switch (diff->generic.type) {
16 default:
17 break;
18 case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR:
19 switch (diff->obj_attr.diff.generic.type) {
20 default:
21 break;
22 case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_NAME:
23 case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_INFO:
24 free(diff->obj_attr.diff.string.name);
25 free(diff->obj_attr.diff.string.oldvalue);
26 free(diff->obj_attr.diff.string.newvalue);
27 break;
28 }
29 break;
30 }
31 free(diff);
32 diff = next;
33 }
34 return 0;
35 }
36
37
38
39
40
41 static void hwloc_append_diff(hwloc_topology_diff_t newdiff,
42 hwloc_topology_diff_t *firstdiffp,
43 hwloc_topology_diff_t *lastdiffp)
44 {
45 if (*firstdiffp)
46 (*lastdiffp)->generic.next = newdiff;
47 else
48 *firstdiffp = newdiff;
49 *lastdiffp = newdiff;
50 newdiff->generic.next = NULL;
51 }
52
53 static int hwloc_append_diff_too_complex(hwloc_obj_t obj1,
54 hwloc_topology_diff_t *firstdiffp,
55 hwloc_topology_diff_t *lastdiffp)
56 {
57 hwloc_topology_diff_t newdiff;
58 newdiff = malloc(sizeof(*newdiff));
59 if (!newdiff)
60 return -1;
61
62 newdiff->too_complex.type = HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX;
63 newdiff->too_complex.obj_depth = obj1->depth;
64 newdiff->too_complex.obj_index = obj1->logical_index;
65 hwloc_append_diff(newdiff, firstdiffp, lastdiffp);
66 return 0;
67 }
68
69 static int hwloc_append_diff_obj_attr_string(hwloc_obj_t obj,
70 hwloc_topology_diff_obj_attr_type_t type,
71 const char *name,
72 const char *oldvalue,
73 const char *newvalue,
74 hwloc_topology_diff_t *firstdiffp,
75 hwloc_topology_diff_t *lastdiffp)
76 {
77 hwloc_topology_diff_t newdiff;
78 newdiff = malloc(sizeof(*newdiff));
79 if (!newdiff)
80 return -1;
81
82 newdiff->obj_attr.type = HWLOC_TOPOLOGY_DIFF_OBJ_ATTR;
83 newdiff->obj_attr.obj_depth = obj->depth;
84 newdiff->obj_attr.obj_index = obj->logical_index;
85 newdiff->obj_attr.diff.string.type = type;
86 newdiff->obj_attr.diff.string.name = name ? strdup(name) : NULL;
87 newdiff->obj_attr.diff.string.oldvalue = oldvalue ? strdup(oldvalue) : NULL;
88 newdiff->obj_attr.diff.string.newvalue = newvalue ? strdup(newvalue) : NULL;
89 hwloc_append_diff(newdiff, firstdiffp, lastdiffp);
90 return 0;
91 }
92
93 static int hwloc_append_diff_obj_attr_uint64(hwloc_obj_t obj,
94 hwloc_topology_diff_obj_attr_type_t type,
95 hwloc_uint64_t idx,
96 hwloc_uint64_t oldvalue,
97 hwloc_uint64_t newvalue,
98 hwloc_topology_diff_t *firstdiffp,
99 hwloc_topology_diff_t *lastdiffp)
100 {
101 hwloc_topology_diff_t newdiff;
102 newdiff = malloc(sizeof(*newdiff));
103 if (!newdiff)
104 return -1;
105
106 newdiff->obj_attr.type = HWLOC_TOPOLOGY_DIFF_OBJ_ATTR;
107 newdiff->obj_attr.obj_depth = obj->depth;
108 newdiff->obj_attr.obj_index = obj->logical_index;
109 newdiff->obj_attr.diff.uint64.type = type;
110 newdiff->obj_attr.diff.uint64.index = idx;
111 newdiff->obj_attr.diff.uint64.oldvalue = oldvalue;
112 newdiff->obj_attr.diff.uint64.newvalue = newvalue;
113 hwloc_append_diff(newdiff, firstdiffp, lastdiffp);
114 return 0;
115 }
116
117 static int
118 hwloc_diff_trees(hwloc_topology_t topo1, hwloc_obj_t obj1,
119 hwloc_topology_t topo2, hwloc_obj_t obj2,
120 unsigned flags,
121 hwloc_topology_diff_t *firstdiffp, hwloc_topology_diff_t *lastdiffp)
122 {
123 unsigned i;
124 int err;
125 hwloc_obj_t child1, child2;
126
127 if (obj1->depth != obj2->depth)
128 goto out_too_complex;
129
130 if (obj1->type != obj2->type)
131 goto out_too_complex;
132 if ((!obj1->subtype) != (!obj2->subtype)
133 || (obj1->subtype && strcmp(obj1->subtype, obj2->subtype)))
134 goto out_too_complex;
135
136 if (obj1->os_index != obj2->os_index)
137
138
139 goto out_too_complex;
140
141 #define _SETS_DIFFERENT(_set1, _set2) \
142 ( ( !(_set1) != !(_set2) ) \
143 || ( (_set1) && !hwloc_bitmap_isequal(_set1, _set2) ) )
144 #define SETS_DIFFERENT(_set, _obj1, _obj2) _SETS_DIFFERENT((_obj1)->_set, (_obj2)->_set)
145 if (SETS_DIFFERENT(cpuset, obj1, obj2)
146 || SETS_DIFFERENT(complete_cpuset, obj1, obj2)
147 || SETS_DIFFERENT(nodeset, obj1, obj2)
148 || SETS_DIFFERENT(complete_nodeset, obj1, obj2))
149 goto out_too_complex;
150
151
152
153
154
155
156 if ((!obj1->name) != (!obj2->name)
157 || (obj1->name && strcmp(obj1->name, obj2->name))) {
158 err = hwloc_append_diff_obj_attr_string(obj1,
159 HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_NAME,
160 NULL,
161 obj1->name,
162 obj2->name,
163 firstdiffp, lastdiffp);
164 if (err < 0)
165 return err;
166 }
167
168
169 switch (obj1->type) {
170 default:
171 break;
172 case HWLOC_OBJ_NUMANODE:
173 if (obj1->attr->numanode.local_memory != obj2->attr->numanode.local_memory) {
174 err = hwloc_append_diff_obj_attr_uint64(obj1,
175 HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_SIZE,
176 0,
177 obj1->attr->numanode.local_memory,
178 obj2->attr->numanode.local_memory,
179 firstdiffp, lastdiffp);
180 if (err < 0)
181 return err;
182 }
183
184 break;
185 case HWLOC_OBJ_L1CACHE:
186 case HWLOC_OBJ_L2CACHE:
187 case HWLOC_OBJ_L3CACHE:
188 case HWLOC_OBJ_L4CACHE:
189 case HWLOC_OBJ_L5CACHE:
190 case HWLOC_OBJ_L1ICACHE:
191 case HWLOC_OBJ_L2ICACHE:
192 case HWLOC_OBJ_L3ICACHE:
193 if (memcmp(obj1->attr, obj2->attr, sizeof(obj1->attr->cache)))
194 goto out_too_complex;
195 break;
196 case HWLOC_OBJ_GROUP:
197 if (memcmp(obj1->attr, obj2->attr, sizeof(obj1->attr->group)))
198 goto out_too_complex;
199 break;
200 case HWLOC_OBJ_PCI_DEVICE:
201 if (memcmp(obj1->attr, obj2->attr, sizeof(obj1->attr->pcidev)))
202 goto out_too_complex;
203 break;
204 case HWLOC_OBJ_BRIDGE:
205 if (memcmp(obj1->attr, obj2->attr, sizeof(obj1->attr->bridge)))
206 goto out_too_complex;
207 break;
208 case HWLOC_OBJ_OS_DEVICE:
209 if (memcmp(obj1->attr, obj2->attr, sizeof(obj1->attr->osdev)))
210 goto out_too_complex;
211 break;
212 }
213
214
215 if (obj1->infos_count != obj2->infos_count)
216 goto out_too_complex;
217 for(i=0; i<obj1->infos_count; i++) {
218 struct hwloc_info_s *info1 = &obj1->infos[i], *info2 = &obj2->infos[i];
219 if (strcmp(info1->name, info2->name))
220 goto out_too_complex;
221 if (strcmp(obj1->infos[i].value, obj2->infos[i].value)) {
222 err = hwloc_append_diff_obj_attr_string(obj1,
223 HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_INFO,
224 info1->name,
225 info1->value,
226 info2->value,
227 firstdiffp, lastdiffp);
228 if (err < 0)
229 return err;
230 }
231 }
232
233
234
235
236 for(child1 = obj1->first_child, child2 = obj2->first_child;
237 child1 != NULL && child2 != NULL;
238 child1 = child1->next_sibling, child2 = child2->next_sibling) {
239 err = hwloc_diff_trees(topo1, child1,
240 topo2, child2,
241 flags,
242 firstdiffp, lastdiffp);
243 if (err < 0)
244 return err;
245 }
246 if (child1 || child2)
247 goto out_too_complex;
248
249
250 for(child1 = obj1->memory_first_child, child2 = obj2->memory_first_child;
251 child1 != NULL && child2 != NULL;
252 child1 = child1->next_sibling, child2 = child2->next_sibling) {
253 err = hwloc_diff_trees(topo1, child1,
254 topo2, child2,
255 flags,
256 firstdiffp, lastdiffp);
257 if (err < 0)
258 return err;
259 }
260 if (child1 || child2)
261 goto out_too_complex;
262
263
264 for(child1 = obj1->io_first_child, child2 = obj2->io_first_child;
265 child1 != NULL && child2 != NULL;
266 child1 = child1->next_sibling, child2 = child2->next_sibling) {
267 err = hwloc_diff_trees(topo1, child1,
268 topo2, child2,
269 flags,
270 firstdiffp, lastdiffp);
271 if (err < 0)
272 return err;
273 }
274 if (child1 || child2)
275 goto out_too_complex;
276
277
278 for(child1 = obj1->misc_first_child, child2 = obj2->misc_first_child;
279 child1 != NULL && child2 != NULL;
280 child1 = child1->next_sibling, child2 = child2->next_sibling) {
281 err = hwloc_diff_trees(topo1, child1,
282 topo2, child2,
283 flags,
284 firstdiffp, lastdiffp);
285 if (err < 0)
286 return err;
287 }
288 if (child1 || child2)
289 goto out_too_complex;
290
291 return 0;
292
293 out_too_complex:
294 hwloc_append_diff_too_complex(obj1, firstdiffp, lastdiffp);
295 return 0;
296 }
297
298 int hwloc_topology_diff_build(hwloc_topology_t topo1,
299 hwloc_topology_t topo2,
300 unsigned long flags,
301 hwloc_topology_diff_t *diffp)
302 {
303 hwloc_topology_diff_t lastdiff, tmpdiff;
304 struct hwloc_internal_distances_s *dist1, *dist2;
305 unsigned i;
306 int err;
307
308 if (!topo1->is_loaded || !topo2->is_loaded) {
309 errno = EINVAL;
310 return -1;
311 }
312
313 if (flags != 0) {
314 errno = EINVAL;
315 return -1;
316 }
317
318 *diffp = NULL;
319 err = hwloc_diff_trees(topo1, hwloc_get_root_obj(topo1),
320 topo2, hwloc_get_root_obj(topo2),
321 flags,
322 diffp, &lastdiff);
323 if (!err) {
324 tmpdiff = *diffp;
325 while (tmpdiff) {
326 if (tmpdiff->generic.type == HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX) {
327 err = 1;
328 break;
329 }
330 tmpdiff = tmpdiff->generic.next;
331 }
332 }
333
334 if (!err) {
335 if (SETS_DIFFERENT(allowed_cpuset, topo1, topo2)
336 || SETS_DIFFERENT(allowed_nodeset, topo1, topo2)) {
337 hwloc_append_diff_too_complex(hwloc_get_root_obj(topo1), diffp, &lastdiff);
338 err = 1;
339 }
340 }
341
342 if (!err) {
343
344 hwloc_internal_distances_refresh(topo1);
345 hwloc_internal_distances_refresh(topo2);
346 dist1 = topo1->first_dist;
347 dist2 = topo2->first_dist;
348 while (dist1 || dist2) {
349 if (!!dist1 != !!dist2) {
350 hwloc_append_diff_too_complex(hwloc_get_root_obj(topo1), diffp, &lastdiff);
351 err = 1;
352 break;
353 }
354 if (dist1->type != dist2->type
355 || dist1->nbobjs != dist2->nbobjs
356 || dist1->kind != dist2->kind
357 || memcmp(dist1->values, dist2->values, dist1->nbobjs * dist1->nbobjs * sizeof(*dist1->values))) {
358 hwloc_append_diff_too_complex(hwloc_get_root_obj(topo1), diffp, &lastdiff);
359 err = 1;
360 break;
361 }
362 for(i=0; i<dist1->nbobjs; i++)
363
364 if (dist1->objs[i]->logical_index != dist2->objs[i]->logical_index) {
365 hwloc_append_diff_too_complex(hwloc_get_root_obj(topo1), diffp, &lastdiff);
366 err = 1;
367 break;
368 }
369 dist1 = dist1->next;
370 dist2 = dist2->next;
371 }
372 }
373
374 return err;
375 }
376
377
378
379
380
381 static int
382 hwloc_apply_diff_one(hwloc_topology_t topology,
383 hwloc_topology_diff_t diff,
384 unsigned long flags)
385 {
386 int reverse = !!(flags & HWLOC_TOPOLOGY_DIFF_APPLY_REVERSE);
387
388 switch (diff->generic.type) {
389 case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR: {
390 struct hwloc_topology_diff_obj_attr_s *obj_attr = &diff->obj_attr;
391 hwloc_obj_t obj = hwloc_get_obj_by_depth(topology, obj_attr->obj_depth, obj_attr->obj_index);
392 if (!obj)
393 return -1;
394
395 switch (obj_attr->diff.generic.type) {
396 case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_SIZE: {
397 hwloc_obj_t tmpobj;
398 hwloc_uint64_t oldvalue = reverse ? obj_attr->diff.uint64.newvalue : obj_attr->diff.uint64.oldvalue;
399 hwloc_uint64_t newvalue = reverse ? obj_attr->diff.uint64.oldvalue : obj_attr->diff.uint64.newvalue;
400 hwloc_uint64_t valuediff = newvalue - oldvalue;
401 if (obj->type != HWLOC_OBJ_NUMANODE)
402 return -1;
403 if (obj->attr->numanode.local_memory != oldvalue)
404 return -1;
405 obj->attr->numanode.local_memory = newvalue;
406 tmpobj = obj;
407 while (tmpobj) {
408 tmpobj->total_memory += valuediff;
409 tmpobj = tmpobj->parent;
410 }
411 break;
412 }
413 case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_NAME: {
414 const char *oldvalue = reverse ? obj_attr->diff.string.newvalue : obj_attr->diff.string.oldvalue;
415 const char *newvalue = reverse ? obj_attr->diff.string.oldvalue : obj_attr->diff.string.newvalue;
416 if (!obj->name || strcmp(obj->name, oldvalue))
417 return -1;
418 free(obj->name);
419 obj->name = strdup(newvalue);
420 break;
421 }
422 case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_INFO: {
423 const char *name = obj_attr->diff.string.name;
424 const char *oldvalue = reverse ? obj_attr->diff.string.newvalue : obj_attr->diff.string.oldvalue;
425 const char *newvalue = reverse ? obj_attr->diff.string.oldvalue : obj_attr->diff.string.newvalue;
426 unsigned i;
427 int found = 0;
428 for(i=0; i<obj->infos_count; i++) {
429 struct hwloc_info_s *info = &obj->infos[i];
430 if (!strcmp(info->name, name)
431 && !strcmp(info->value, oldvalue)) {
432 free(info->value);
433 info->value = strdup(newvalue);
434 found = 1;
435 break;
436 }
437 }
438 if (!found)
439 return -1;
440 break;
441 }
442 default:
443 return -1;
444 }
445
446 break;
447 }
448 default:
449 return -1;
450 }
451
452 return 0;
453 }
454
455 int hwloc_topology_diff_apply(hwloc_topology_t topology,
456 hwloc_topology_diff_t diff,
457 unsigned long flags)
458 {
459 hwloc_topology_diff_t tmpdiff, tmpdiff2;
460 int err, nr;
461
462 if (!topology->is_loaded) {
463 errno = EINVAL;
464 return -1;
465 }
466
467 if (flags & ~HWLOC_TOPOLOGY_DIFF_APPLY_REVERSE) {
468 errno = EINVAL;
469 return -1;
470 }
471
472 tmpdiff = diff;
473 nr = 0;
474 while (tmpdiff) {
475 nr++;
476 err = hwloc_apply_diff_one(topology, tmpdiff, flags);
477 if (err < 0)
478 goto cancel;
479 tmpdiff = tmpdiff->generic.next;
480 }
481 return 0;
482
483 cancel:
484 tmpdiff2 = tmpdiff;
485 tmpdiff = diff;
486 while (tmpdiff != tmpdiff2) {
487 hwloc_apply_diff_one(topology, tmpdiff, flags ^ HWLOC_TOPOLOGY_DIFF_APPLY_REVERSE);
488 tmpdiff = tmpdiff->generic.next;
489 }
490 errno = EINVAL;
491 return -nr;
492 }