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

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

DEFINITIONS

This source file includes following definitions.
  1. hwloc_get_type_depth
  2. hwloc_get_depth_type
  3. hwloc_get_memory_parents_depth
  4. hwloc_get_nbobjs_by_depth
  5. hwloc_get_obj_by_depth
  6. hwloc_obj_type_is_normal
  7. hwloc_obj_type_is_memory
  8. hwloc_obj_type_is_io
  9. hwloc_obj_type_is_cache
  10. hwloc_obj_type_is_dcache
  11. hwloc_obj_type_is_icache
  12. hwloc_get_closest_objs
  13. hwloc__get_largest_objs_inside_cpuset
  14. hwloc_get_largest_objs_inside_cpuset
  15. hwloc_obj_type_string
  16. hwloc_type_sscanf
  17. hwloc_type_sscanf_as_depth
  18. hwloc_obj_cache_type_letter
  19. hwloc_obj_type_snprintf
  20. hwloc_obj_attr_snprintf

   1 /*
   2  * Copyright © 2009 CNRS
   3  * Copyright © 2009-2018 Inria.  All rights reserved.
   4  * Copyright © 2009-2010 Université Bordeaux
   5  * Copyright © 2009-2011 Cisco Systems, Inc.  All rights reserved.
   6  * See COPYING in top-level directory.
   7  */
   8 
   9 #include <private/autogen/config.h>
  10 #include <hwloc.h>
  11 #include <private/private.h>
  12 #include <private/misc.h>
  13 #include <private/debug.h>
  14 #ifdef HAVE_STRINGS_H
  15 #include <strings.h>
  16 #endif /* HAVE_STRINGS_H */
  17 
  18 int
  19 hwloc_get_type_depth (struct hwloc_topology *topology, hwloc_obj_type_t type)
  20 {
  21   HWLOC_BUILD_ASSERT(HWLOC_OBJ_TYPE_MIN == 0);
  22   if ((unsigned) type >= HWLOC_OBJ_TYPE_MAX)
  23     return HWLOC_TYPE_DEPTH_UNKNOWN;
  24   else
  25     return topology->type_depth[type];
  26 }
  27 
  28 hwloc_obj_type_t
  29 hwloc_get_depth_type (hwloc_topology_t topology, int depth)
  30 {
  31   if ((unsigned)depth >= topology->nb_levels)
  32     switch (depth) {
  33     case HWLOC_TYPE_DEPTH_NUMANODE:
  34       return HWLOC_OBJ_NUMANODE;
  35     case HWLOC_TYPE_DEPTH_BRIDGE:
  36       return HWLOC_OBJ_BRIDGE;
  37     case HWLOC_TYPE_DEPTH_PCI_DEVICE:
  38       return HWLOC_OBJ_PCI_DEVICE;
  39     case HWLOC_TYPE_DEPTH_OS_DEVICE:
  40       return HWLOC_OBJ_OS_DEVICE;
  41     case HWLOC_TYPE_DEPTH_MISC:
  42       return HWLOC_OBJ_MISC;
  43     default:
  44       return HWLOC_OBJ_TYPE_NONE;
  45     }
  46   return topology->levels[depth][0]->type;
  47 }
  48 
  49 int
  50 hwloc_get_memory_parents_depth (hwloc_topology_t topology)
  51 {
  52   int depth = HWLOC_TYPE_DEPTH_UNKNOWN;
  53   /* memory leaves are always NUMA nodes for now, no need to check parents of other memory types */
  54   hwloc_obj_t numa = hwloc_get_obj_by_depth(topology, HWLOC_TYPE_DEPTH_NUMANODE, 0);
  55   assert(numa);
  56   while (numa) {
  57     hwloc_obj_t parent = numa->parent;
  58     /* walk-up the memory hierarchy */
  59     while (hwloc__obj_type_is_memory(parent->type))
  60       parent = parent->parent;
  61 
  62     if (depth == HWLOC_TYPE_DEPTH_UNKNOWN)
  63       depth = parent->depth;
  64     else if (depth != parent->depth)
  65       return HWLOC_TYPE_DEPTH_MULTIPLE;
  66 
  67     numa = numa->next_cousin;
  68   }
  69 
  70   assert(depth >= 0);
  71   return depth;
  72 }
  73 
  74 unsigned
  75 hwloc_get_nbobjs_by_depth (struct hwloc_topology *topology, int depth)
  76 {
  77   if ((unsigned)depth >= topology->nb_levels) {
  78     unsigned l = HWLOC_SLEVEL_FROM_DEPTH(depth);
  79     if (l < HWLOC_NR_SLEVELS)
  80       return topology->slevels[l].nbobjs;
  81     else
  82       return 0;
  83   }
  84   return topology->level_nbobjects[depth];
  85 }
  86 
  87 struct hwloc_obj *
  88 hwloc_get_obj_by_depth (struct hwloc_topology *topology, int depth, unsigned idx)
  89 {
  90   if ((unsigned)depth >= topology->nb_levels) {
  91     unsigned l = HWLOC_SLEVEL_FROM_DEPTH(depth);
  92     if (l < HWLOC_NR_SLEVELS)
  93       return idx < topology->slevels[l].nbobjs ? topology->slevels[l].objs[idx] : NULL;
  94     else
  95       return NULL;
  96   }
  97   if (idx >= topology->level_nbobjects[depth])
  98     return NULL;
  99   return topology->levels[depth][idx];
 100 }
 101 
 102 int
 103 hwloc_obj_type_is_normal(hwloc_obj_type_t type)
 104 {
 105   return hwloc__obj_type_is_normal(type);
 106 }
 107 
 108 int
 109 hwloc_obj_type_is_memory(hwloc_obj_type_t type)
 110 {
 111   return hwloc__obj_type_is_memory(type);
 112 }
 113 
 114 int
 115 hwloc_obj_type_is_io(hwloc_obj_type_t type)
 116 {
 117   return hwloc__obj_type_is_io(type);
 118 }
 119 
 120 int
 121 hwloc_obj_type_is_cache(hwloc_obj_type_t type)
 122 {
 123   return hwloc__obj_type_is_cache(type);
 124 }
 125 
 126 int
 127 hwloc_obj_type_is_dcache(hwloc_obj_type_t type)
 128 {
 129   return hwloc__obj_type_is_dcache(type);
 130 }
 131 
 132 int
 133 hwloc_obj_type_is_icache(hwloc_obj_type_t type)
 134 {
 135   return hwloc__obj_type_is_icache(type);
 136 }
 137 
 138 unsigned hwloc_get_closest_objs (struct hwloc_topology *topology, struct hwloc_obj *src, struct hwloc_obj **objs, unsigned max)
 139 {
 140   struct hwloc_obj *parent, *nextparent, **src_objs;
 141   unsigned i,src_nbobjects;
 142   unsigned stored = 0;
 143 
 144   if (!src->cpuset)
 145     return 0;
 146 
 147   src_nbobjects = topology->level_nbobjects[src->depth];
 148   src_objs = topology->levels[src->depth];
 149 
 150   parent = src;
 151   while (stored < max) {
 152     while (1) {
 153       nextparent = parent->parent;
 154       if (!nextparent)
 155         goto out;
 156       if (!hwloc_bitmap_isequal(parent->cpuset, nextparent->cpuset))
 157         break;
 158       parent = nextparent;
 159     }
 160 
 161     /* traverse src's objects and find those that are in nextparent and were not in parent */
 162     for(i=0; i<src_nbobjects; i++) {
 163       if (hwloc_bitmap_isincluded(src_objs[i]->cpuset, nextparent->cpuset)
 164           && !hwloc_bitmap_isincluded(src_objs[i]->cpuset, parent->cpuset)) {
 165         objs[stored++] = src_objs[i];
 166         if (stored == max)
 167           goto out;
 168       }
 169     }
 170     parent = nextparent;
 171   }
 172 
 173  out:
 174   return stored;
 175 }
 176 
 177 static int
 178 hwloc__get_largest_objs_inside_cpuset (struct hwloc_obj *current, hwloc_const_bitmap_t set,
 179                                        struct hwloc_obj ***res, int *max)
 180 {
 181   int gotten = 0;
 182   unsigned i;
 183 
 184   /* the caller must ensure this */
 185   if (*max <= 0)
 186     return 0;
 187 
 188   if (hwloc_bitmap_isequal(current->cpuset, set)) {
 189     **res = current;
 190     (*res)++;
 191     (*max)--;
 192     return 1;
 193   }
 194 
 195   for (i=0; i<current->arity; i++) {
 196     hwloc_bitmap_t subset;
 197     int ret;
 198 
 199     /* split out the cpuset part corresponding to this child and see if there's anything to do */
 200     if (!hwloc_bitmap_intersects(set,current->children[i]->cpuset))
 201       continue;
 202 
 203     subset = hwloc_bitmap_dup(set);
 204     hwloc_bitmap_and(subset, subset, current->children[i]->cpuset);
 205     ret = hwloc__get_largest_objs_inside_cpuset (current->children[i], subset, res, max);
 206     gotten += ret;
 207     hwloc_bitmap_free(subset);
 208 
 209     /* if no more room to store remaining objects, return what we got so far */
 210     if (!*max)
 211       break;
 212   }
 213 
 214   return gotten;
 215 }
 216 
 217 int
 218 hwloc_get_largest_objs_inside_cpuset (struct hwloc_topology *topology, hwloc_const_bitmap_t set,
 219                                       struct hwloc_obj **objs, int max)
 220 {
 221   struct hwloc_obj *current = topology->levels[0][0];
 222 
 223   if (!hwloc_bitmap_isincluded(set, current->cpuset))
 224     return -1;
 225 
 226   if (max <= 0)
 227     return 0;
 228 
 229   return hwloc__get_largest_objs_inside_cpuset (current, set, &objs, &max);
 230 }
 231 
 232 const char *
 233 hwloc_obj_type_string (hwloc_obj_type_t obj)
 234 {
 235   switch (obj)
 236     {
 237     case HWLOC_OBJ_MACHINE: return "Machine";
 238     case HWLOC_OBJ_MISC: return "Misc";
 239     case HWLOC_OBJ_GROUP: return "Group";
 240     case HWLOC_OBJ_NUMANODE: return "NUMANode";
 241     case HWLOC_OBJ_PACKAGE: return "Package";
 242     case HWLOC_OBJ_L1CACHE: return "L1Cache";
 243     case HWLOC_OBJ_L2CACHE: return "L2Cache";
 244     case HWLOC_OBJ_L3CACHE: return "L3Cache";
 245     case HWLOC_OBJ_L4CACHE: return "L4Cache";
 246     case HWLOC_OBJ_L5CACHE: return "L5Cache";
 247     case HWLOC_OBJ_L1ICACHE: return "L1iCache";
 248     case HWLOC_OBJ_L2ICACHE: return "L2iCache";
 249     case HWLOC_OBJ_L3ICACHE: return "L3iCache";
 250     case HWLOC_OBJ_CORE: return "Core";
 251     case HWLOC_OBJ_BRIDGE: return "Bridge";
 252     case HWLOC_OBJ_PCI_DEVICE: return "PCIDev";
 253     case HWLOC_OBJ_OS_DEVICE: return "OSDev";
 254     case HWLOC_OBJ_PU: return "PU";
 255     default: return "Unknown";
 256     }
 257 }
 258 
 259 int
 260 hwloc_type_sscanf(const char *string, hwloc_obj_type_t *typep,
 261                   union hwloc_obj_attr_u *attrp, size_t attrsize)
 262 {
 263   hwloc_obj_type_t type = (hwloc_obj_type_t) -1;
 264   unsigned depthattr = (unsigned) -1;
 265   hwloc_obj_cache_type_t cachetypeattr = (hwloc_obj_cache_type_t) -1; /* unspecified */
 266   hwloc_obj_bridge_type_t ubtype = (hwloc_obj_bridge_type_t) -1;
 267   hwloc_obj_osdev_type_t ostype = (hwloc_obj_osdev_type_t) -1;
 268   char *end;
 269 
 270   /* never match the ending \0 since we want to match things like core:2 too.
 271    * just use hwloc_strncasecmp() everywhere.
 272    */
 273 
 274   /* types without a custom depth */
 275 
 276   /* osdev subtype first to avoid conflicts coproc/core etc */
 277   if (!hwloc_strncasecmp(string, "os", 2)) {
 278     type = HWLOC_OBJ_OS_DEVICE;
 279   } else if (!hwloc_strncasecmp(string, "bloc", 4)) {
 280     type = HWLOC_OBJ_OS_DEVICE;
 281     ostype = HWLOC_OBJ_OSDEV_BLOCK;
 282   } else if (!hwloc_strncasecmp(string, "net", 3)) {
 283     type = HWLOC_OBJ_OS_DEVICE;
 284     ostype = HWLOC_OBJ_OSDEV_NETWORK;
 285   } else if (!hwloc_strncasecmp(string, "openfab", 7)) {
 286     type = HWLOC_OBJ_OS_DEVICE;
 287     ostype = HWLOC_OBJ_OSDEV_OPENFABRICS;
 288   } else if (!hwloc_strncasecmp(string, "dma", 3)) {
 289     type = HWLOC_OBJ_OS_DEVICE;
 290     ostype = HWLOC_OBJ_OSDEV_DMA;
 291   } else if (!hwloc_strncasecmp(string, "gpu", 3)) {
 292     type = HWLOC_OBJ_OS_DEVICE;
 293     ostype = HWLOC_OBJ_OSDEV_GPU;
 294   } else if (!hwloc_strncasecmp(string, "copro", 5)
 295              || !hwloc_strncasecmp(string, "co-pro", 6)) {
 296     type = HWLOC_OBJ_OS_DEVICE;
 297     ostype = HWLOC_OBJ_OSDEV_COPROC;
 298 
 299   } else if (!hwloc_strncasecmp(string, "machine", 2)) {
 300     type = HWLOC_OBJ_MACHINE;
 301   } else if (!hwloc_strncasecmp(string, "node", 2)
 302              || !hwloc_strncasecmp(string, "numa", 2)) { /* matches node and numanode */
 303     type = HWLOC_OBJ_NUMANODE;
 304   } else if (!hwloc_strncasecmp(string, "package", 2)
 305              || !hwloc_strncasecmp(string, "socket", 2)) { /* backward compat with v1.10 */
 306     type = HWLOC_OBJ_PACKAGE;
 307   } else if (!hwloc_strncasecmp(string, "core", 2)) {
 308     type = HWLOC_OBJ_CORE;
 309   } else if (!hwloc_strncasecmp(string, "pu", 2)) {
 310     type = HWLOC_OBJ_PU;
 311   } else if (!hwloc_strncasecmp(string, "misc", 4)) {
 312     type = HWLOC_OBJ_MISC;
 313 
 314   } else if (!hwloc_strncasecmp(string, "bridge", 4)) {
 315     type = HWLOC_OBJ_BRIDGE;
 316   } else if (!hwloc_strncasecmp(string, "hostbridge", 6)) {
 317     type = HWLOC_OBJ_BRIDGE;
 318     ubtype = HWLOC_OBJ_BRIDGE_HOST;
 319   } else if (!hwloc_strncasecmp(string, "pcibridge", 5)) {
 320     type = HWLOC_OBJ_BRIDGE;
 321     ubtype = HWLOC_OBJ_BRIDGE_PCI;
 322 
 323   } else if (!hwloc_strncasecmp(string, "pci", 3)) {
 324     type = HWLOC_OBJ_PCI_DEVICE;
 325 
 326   /* types with depthattr */
 327   } else if ((string[0] == 'l' || string[0] == 'L') && string[1] >= '0' && string[1] <= '9') {
 328     depthattr = strtol(string+1, &end, 10);
 329     if (*end == 'i') {
 330       if (depthattr >= 1 && depthattr <= 3) {
 331         type = HWLOC_OBJ_L1ICACHE + depthattr-1;
 332         cachetypeattr = HWLOC_OBJ_CACHE_INSTRUCTION;
 333       } else
 334         return -1;
 335     } else {
 336       if (depthattr >= 1 && depthattr <= 5) {
 337         type = HWLOC_OBJ_L1CACHE + depthattr-1;
 338         cachetypeattr = *end == 'd' ? HWLOC_OBJ_CACHE_DATA : HWLOC_OBJ_CACHE_UNIFIED;
 339       } else
 340         return -1;
 341     }
 342 
 343   } else if (!hwloc_strncasecmp(string, "group", 2)) {
 344     size_t length;
 345     type = HWLOC_OBJ_GROUP;
 346     length = strcspn(string, "0123456789");
 347     if (length <= 5 && !hwloc_strncasecmp(string, "group", length)
 348         && string[length] >= '0' && string[length] <= '9') {
 349       depthattr = strtol(string+length, &end, 10);
 350     }
 351 
 352   } else
 353     return -1;
 354 
 355   *typep = type;
 356   if (attrp) {
 357     if (hwloc__obj_type_is_cache(type) && attrsize >= sizeof(attrp->cache)) {
 358       attrp->cache.depth = depthattr;
 359       attrp->cache.type = cachetypeattr;
 360     } else if (type == HWLOC_OBJ_GROUP && attrsize >= sizeof(attrp->group)) {
 361       attrp->group.depth = depthattr;
 362     } else if (type == HWLOC_OBJ_BRIDGE && attrsize >= sizeof(attrp->bridge)) {
 363       attrp->bridge.upstream_type = ubtype;
 364       attrp->bridge.downstream_type = HWLOC_OBJ_BRIDGE_PCI; /* nothing else so far */
 365     } else if (type == HWLOC_OBJ_OS_DEVICE && attrsize >= sizeof(attrp->osdev)) {
 366       attrp->osdev.type = ostype;
 367     }
 368   }
 369   return 0;
 370 }
 371 
 372 int
 373 hwloc_type_sscanf_as_depth(const char *string, hwloc_obj_type_t *typep,
 374                            hwloc_topology_t topology, int *depthp)
 375 {
 376   union hwloc_obj_attr_u attr;
 377   hwloc_obj_type_t type;
 378   int depth;
 379   int err;
 380 
 381   err = hwloc_type_sscanf(string, &type, &attr, sizeof(attr));
 382   if (err < 0)
 383     return err;
 384 
 385   depth = hwloc_get_type_depth(topology, type);
 386   if (type == HWLOC_OBJ_GROUP
 387       && depth == HWLOC_TYPE_DEPTH_MULTIPLE
 388       && attr.group.depth != (unsigned)-1) {
 389     unsigned l;
 390     depth = HWLOC_TYPE_DEPTH_UNKNOWN;
 391     for(l=0; l<topology->nb_levels; l++) {
 392       if (topology->levels[l][0]->type == HWLOC_OBJ_GROUP
 393           && topology->levels[l][0]->attr->group.depth == attr.group.depth) {
 394         depth = (int)l;
 395         break;
 396       }
 397     }
 398   }
 399 
 400   if (typep)
 401     *typep = type;
 402   *depthp = depth;
 403   return 0;
 404 }
 405 
 406 static const char* hwloc_obj_cache_type_letter(hwloc_obj_cache_type_t type)
 407 {
 408   switch (type) {
 409   case HWLOC_OBJ_CACHE_UNIFIED: return "";
 410   case HWLOC_OBJ_CACHE_DATA: return "d";
 411   case HWLOC_OBJ_CACHE_INSTRUCTION: return "i";
 412   default: return "unknown";
 413   }
 414 }
 415 
 416 int
 417 hwloc_obj_type_snprintf(char * __hwloc_restrict string, size_t size, hwloc_obj_t obj, int verbose)
 418 {
 419   hwloc_obj_type_t type = obj->type;
 420   switch (type) {
 421   case HWLOC_OBJ_MISC:
 422   case HWLOC_OBJ_MACHINE:
 423   case HWLOC_OBJ_NUMANODE:
 424   case HWLOC_OBJ_PACKAGE:
 425   case HWLOC_OBJ_CORE:
 426   case HWLOC_OBJ_PU:
 427     return hwloc_snprintf(string, size, "%s", hwloc_obj_type_string(type));
 428   case HWLOC_OBJ_L1CACHE:
 429   case HWLOC_OBJ_L2CACHE:
 430   case HWLOC_OBJ_L3CACHE:
 431   case HWLOC_OBJ_L4CACHE:
 432   case HWLOC_OBJ_L5CACHE:
 433   case HWLOC_OBJ_L1ICACHE:
 434   case HWLOC_OBJ_L2ICACHE:
 435   case HWLOC_OBJ_L3ICACHE:
 436     return hwloc_snprintf(string, size, "L%u%s%s", obj->attr->cache.depth,
 437                           hwloc_obj_cache_type_letter(obj->attr->cache.type),
 438                           verbose ? "Cache" : "");
 439   case HWLOC_OBJ_GROUP:
 440     if (obj->attr->group.depth != (unsigned) -1)
 441       return hwloc_snprintf(string, size, "%s%u", hwloc_obj_type_string(type), obj->attr->group.depth);
 442     else
 443       return hwloc_snprintf(string, size, "%s", hwloc_obj_type_string(type));
 444   case HWLOC_OBJ_BRIDGE:
 445     return snprintf(string, size, obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI ? "PCIBridge" : "HostBridge");
 446   case HWLOC_OBJ_PCI_DEVICE:
 447     return hwloc_snprintf(string, size, "PCI");
 448   case HWLOC_OBJ_OS_DEVICE:
 449     switch (obj->attr->osdev.type) {
 450     case HWLOC_OBJ_OSDEV_BLOCK: return hwloc_snprintf(string, size, "Block");
 451     case HWLOC_OBJ_OSDEV_NETWORK: return hwloc_snprintf(string, size, verbose ? "Network" : "Net");
 452     case HWLOC_OBJ_OSDEV_OPENFABRICS: return hwloc_snprintf(string, size, "OpenFabrics");
 453     case HWLOC_OBJ_OSDEV_DMA: return hwloc_snprintf(string, size, "DMA");
 454     case HWLOC_OBJ_OSDEV_GPU: return hwloc_snprintf(string, size, "GPU");
 455     case HWLOC_OBJ_OSDEV_COPROC: return hwloc_snprintf(string, size, verbose ? "Co-Processor" : "CoProc");
 456     default:
 457       if (size > 0)
 458         *string = '\0';
 459       return 0;
 460     }
 461     break;
 462   default:
 463     if (size > 0)
 464       *string = '\0';
 465     return 0;
 466   }
 467 }
 468 
 469 int
 470 hwloc_obj_attr_snprintf(char * __hwloc_restrict string, size_t size, hwloc_obj_t obj, const char * separator, int verbose)
 471 {
 472   const char *prefix = "";
 473   char *tmp = string;
 474   ssize_t tmplen = size;
 475   int ret = 0;
 476   int res;
 477 
 478   /* make sure we output at least an empty string */
 479   if (size)
 480     *string = '\0';
 481 
 482   /* print memory attributes */
 483   res = 0;
 484   if (verbose) {
 485     if (obj->type == HWLOC_OBJ_NUMANODE && obj->attr->numanode.local_memory)
 486       res = hwloc_snprintf(tmp, tmplen, "%slocal=%lu%s%stotal=%lu%s",
 487                            prefix,
 488                            (unsigned long) hwloc_memory_size_printf_value(obj->attr->numanode.local_memory, verbose),
 489                            hwloc_memory_size_printf_unit(obj->attr->numanode.local_memory, verbose),
 490                            separator,
 491                            (unsigned long) hwloc_memory_size_printf_value(obj->total_memory, verbose),
 492                            hwloc_memory_size_printf_unit(obj->total_memory, verbose));
 493     else if (obj->total_memory)
 494       res = hwloc_snprintf(tmp, tmplen, "%stotal=%lu%s",
 495                            prefix,
 496                            (unsigned long) hwloc_memory_size_printf_value(obj->total_memory, verbose),
 497                            hwloc_memory_size_printf_unit(obj->total_memory, verbose));
 498   } else {
 499     if (obj->type == HWLOC_OBJ_NUMANODE && obj->attr->numanode.local_memory)
 500       res = hwloc_snprintf(tmp, tmplen, "%s%lu%s",
 501                            prefix,
 502                            (unsigned long) hwloc_memory_size_printf_value(obj->attr->numanode.local_memory, verbose),
 503                            hwloc_memory_size_printf_unit(obj->attr->numanode.local_memory, verbose));
 504   }
 505   if (res < 0)
 506     return -1;
 507   ret += res;
 508   if (ret > 0)
 509     prefix = separator;
 510   if (res >= tmplen)
 511     res = tmplen>0 ? (int)tmplen - 1 : 0;
 512   tmp += res;
 513   tmplen -= res;
 514 
 515   /* printf type-specific attributes */
 516   res = 0;
 517   switch (obj->type) {
 518   case HWLOC_OBJ_L1CACHE:
 519   case HWLOC_OBJ_L2CACHE:
 520   case HWLOC_OBJ_L3CACHE:
 521   case HWLOC_OBJ_L4CACHE:
 522   case HWLOC_OBJ_L5CACHE:
 523   case HWLOC_OBJ_L1ICACHE:
 524   case HWLOC_OBJ_L2ICACHE:
 525   case HWLOC_OBJ_L3ICACHE:
 526     if (verbose) {
 527       char assoc[32];
 528       if (obj->attr->cache.associativity == -1)
 529         snprintf(assoc, sizeof(assoc), "%sfully-associative", separator);
 530       else if (obj->attr->cache.associativity == 0)
 531         *assoc = '\0';
 532       else
 533         snprintf(assoc, sizeof(assoc), "%sways=%d", separator, obj->attr->cache.associativity);
 534       res = hwloc_snprintf(tmp, tmplen, "%ssize=%lu%s%slinesize=%u%s",
 535                            prefix,
 536                            (unsigned long) hwloc_memory_size_printf_value(obj->attr->cache.size, verbose),
 537                            hwloc_memory_size_printf_unit(obj->attr->cache.size, verbose),
 538                            separator, obj->attr->cache.linesize,
 539                            assoc);
 540     } else
 541       res = hwloc_snprintf(tmp, tmplen, "%s%lu%s",
 542                            prefix,
 543                            (unsigned long) hwloc_memory_size_printf_value(obj->attr->cache.size, verbose),
 544                            hwloc_memory_size_printf_unit(obj->attr->cache.size, verbose));
 545     break;
 546   case HWLOC_OBJ_BRIDGE:
 547     if (verbose) {
 548       char up[128], down[64];
 549       /* upstream is PCI or HOST */
 550       if (obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI) {
 551         char linkspeed[64]= "";
 552         if (obj->attr->pcidev.linkspeed)
 553           snprintf(linkspeed, sizeof(linkspeed), "%slink=%.2fGB/s", separator, obj->attr->pcidev.linkspeed);
 554         snprintf(up, sizeof(up), "busid=%04x:%02x:%02x.%01x%sid=%04x:%04x%sclass=%04x(%s)%s",
 555                  obj->attr->pcidev.domain, obj->attr->pcidev.bus, obj->attr->pcidev.dev, obj->attr->pcidev.func, separator,
 556                  obj->attr->pcidev.vendor_id, obj->attr->pcidev.device_id, separator,
 557                  obj->attr->pcidev.class_id, hwloc_pci_class_string(obj->attr->pcidev.class_id), linkspeed);
 558       } else
 559         *up = '\0';
 560       /* downstream is_PCI */
 561       snprintf(down, sizeof(down), "buses=%04x:[%02x-%02x]",
 562                obj->attr->bridge.downstream.pci.domain, obj->attr->bridge.downstream.pci.secondary_bus, obj->attr->bridge.downstream.pci.subordinate_bus);
 563       if (*up)
 564         res = snprintf(string, size, "%s%s%s", up, separator, down);
 565       else
 566         res = snprintf(string, size, "%s", down);
 567     }
 568     break;
 569   case HWLOC_OBJ_PCI_DEVICE:
 570     if (verbose) {
 571       char linkspeed[64]= "";
 572       if (obj->attr->pcidev.linkspeed)
 573         snprintf(linkspeed, sizeof(linkspeed), "%slink=%.2fGB/s", separator, obj->attr->pcidev.linkspeed);
 574       res = snprintf(string, size, "busid=%04x:%02x:%02x.%01x%sid=%04x:%04x%sclass=%04x(%s)%s",
 575                      obj->attr->pcidev.domain, obj->attr->pcidev.bus, obj->attr->pcidev.dev, obj->attr->pcidev.func, separator,
 576                      obj->attr->pcidev.vendor_id, obj->attr->pcidev.device_id, separator,
 577                      obj->attr->pcidev.class_id, hwloc_pci_class_string(obj->attr->pcidev.class_id), linkspeed);
 578     }
 579     break;
 580   default:
 581     break;
 582   }
 583   if (res < 0)
 584     return -1;
 585   ret += res;
 586   if (ret > 0)
 587     prefix = separator;
 588   if (res >= tmplen)
 589     res = tmplen>0 ? (int)tmplen - 1 : 0;
 590   tmp += res;
 591   tmplen -= res;
 592 
 593   /* printf infos */
 594   if (verbose) {
 595     unsigned i;
 596     for(i=0; i<obj->infos_count; i++) {
 597       struct hwloc_info_s *info = &obj->infos[i];
 598       const char *quote = strchr(info->value, ' ') ? "\"" : "";
 599       res = hwloc_snprintf(tmp, tmplen, "%s%s=%s%s%s",
 600                              prefix,
 601                              info->name,
 602                              quote, info->value, quote);
 603       if (res < 0)
 604         return -1;
 605       ret += res;
 606       if (res >= tmplen)
 607         res = tmplen>0 ? (int)tmplen - 1 : 0;
 608       tmp += res;
 609       tmplen -= res;
 610       if (ret > 0)
 611         prefix = separator;
 612     }
 613   }
 614 
 615   return ret;
 616 }

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