root/opal/mca/hwloc/hwloc201/hwloc/hwloc/diff.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hwloc_topology_diff_destroy
  2. hwloc_append_diff
  3. hwloc_append_diff_too_complex
  4. hwloc_append_diff_obj_attr_string
  5. hwloc_append_diff_obj_attr_uint64
  6. hwloc_diff_trees
  7. hwloc_topology_diff_build
  8. hwloc_apply_diff_one
  9. hwloc_topology_diff_apply

   1 /*
   2  * Copyright © 2013-2018 Inria.  All rights reserved.
   3  * See COPYING in top-level directory.
   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  * Computing diffs
  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                 /* we could allow different os_index for non-PU non-NUMAnode objects
 138                  * but it's likely useless anyway */
 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         /* no need to check logical_index, sibling_rank, symmetric_subtree,
 152          * the parents did it */
 153 
 154         /* gp_index don't have to be strictly identical */
 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         /* type-specific attrs */
 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                 /* ignore memory page_types */
 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         /* infos */
 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         /* ignore userdata */
 234 
 235         /* children */
 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         /* memory children */
 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         /* I/O children */
 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         /* misc children */
 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                 /* distances */
 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                                 /* gp_index isn't enforced above. so compare logical_index instead, which is enforced. requires distances refresh() above */
 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  * Applying diffs
 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; /* return the index (starting at 1) of the first element that couldn't be applied */
 492 }

/* [<][>][^][v][top][bottom][index][help] */