This source file includes following definitions.
- hwloc_get_type_depth
- hwloc_get_depth_type
- hwloc_get_memory_parents_depth
- hwloc_get_nbobjs_by_depth
- hwloc_get_obj_by_depth
- hwloc_obj_type_is_normal
- hwloc_obj_type_is_memory
- hwloc_obj_type_is_io
- hwloc_obj_type_is_cache
- hwloc_obj_type_is_dcache
- hwloc_obj_type_is_icache
- hwloc_get_closest_objs
- hwloc__get_largest_objs_inside_cpuset
- hwloc_get_largest_objs_inside_cpuset
- hwloc_obj_type_string
- hwloc_type_sscanf
- hwloc_type_sscanf_as_depth
- hwloc_obj_cache_type_letter
- hwloc_obj_type_snprintf
- hwloc_obj_attr_snprintf
1
2
3
4
5
6
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
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
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
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
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
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
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
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;
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
271
272
273
274
275
276
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)) {
303 type = HWLOC_OBJ_NUMANODE;
304 } else if (!hwloc_strncasecmp(string, "package", 2)
305 || !hwloc_strncasecmp(string, "socket", 2)) {
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
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;
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
479 if (size)
480 *string = '\0';
481
482
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
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
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
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
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 }