This source file includes following definitions.
- opal_hwloc_base_get_pu
- opal_hwloc_base_filter_cpus
- fill_cache_line_size
- opal_hwloc_base_get_topology
- opal_hwloc_base_set_topology
- free_object
- opal_hwloc_base_free_topology
- opal_hwloc_base_get_local_cpuset
- opal_hwloc_base_report_bind_failure
- opal_hwloc_base_single_cpu
- opal_hwloc_base_get_npus
- opal_hwloc_base_get_obj_idx
- df_search
- opal_hwloc_base_get_nbobjs_by_type
- opal_hwloc_base_get_obj_by_type
- df_clear
- opal_hwloc_base_clear_usage
- socket_to_cpu_set
- socket_core_to_cpu_set
- opal_hwloc_base_cpu_list_parse
- opal_hwloc_base_get_relative_locality
- opal_hwloc_base_find_coprocessors
- hwloc_getline
- opal_hwloc_base_check_on_coprocessor
- opal_hwloc_base_print_binding
- bitmap2rangestr
- build_map
- opal_hwloc_base_cset2str
- opal_hwloc_base_cset2mapstr
- dist_cmp_fn
- sort_by_dist
- find_devices
- opal_hwloc_get_sorted_numa_list
- opal_hwloc_base_get_topo_signature
- opal_hwloc_base_get_locality_string
- opal_hwloc_base_get_location
- opal_hwloc_compute_relative_locality
- opal_hwloc_base_topology_export_xmlbuffer
- opal_hwloc_base_topology_set_flags
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 #define OPAL_HWLOC_WANT_SHMEM 1
31
32 #include "opal_config.h"
33
34 #ifdef HAVE_SYS_TYPES_H
35 #include <sys/types.h>
36 #endif
37 #ifdef HAVE_UNISTD_H
38 #include <unistd.h>
39 #endif
40 #ifdef HAVE_ENDIAN_H
41 #include <endian.h>
42 #endif
43 #ifdef HAVE_SYS_STAT_H
44 #include <sys/stat.h>
45 #endif
46 #if HAVE_FCNTL_H
47 #include <fcntl.h>
48 #endif
49
50 #include "opal/runtime/opal.h"
51 #include "opal/constants.h"
52 #include "opal/util/argv.h"
53 #include "opal/util/output.h"
54 #include "opal/util/os_dirpath.h"
55 #include "opal/util/show_help.h"
56 #include "opal/util/printf.h"
57 #include "opal/threads/tsd.h"
58 #include "opal/mca/pmix/pmix.h"
59
60 #include "opal/mca/hwloc/hwloc-internal.h"
61 #include "opal/mca/hwloc/base/base.h"
62
63 static bool topo_in_shmem = false;
64
65
66
67
68
69
70
71
72 hwloc_obj_t opal_hwloc_base_get_pu(hwloc_topology_t topo,
73 int lid,
74 opal_hwloc_resource_type_t rtype)
75 {
76 hwloc_obj_type_t obj_type = HWLOC_OBJ_CORE;
77 hwloc_obj_t obj;
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92 if (opal_hwloc_use_hwthreads_as_cpus || (NULL == hwloc_get_obj_by_type(topo, HWLOC_OBJ_CORE, 0))) {
93 obj_type = HWLOC_OBJ_PU;
94 }
95
96 if (OPAL_HWLOC_PHYSICAL == rtype) {
97
98
99
100
101 obj = hwloc_get_pu_obj_by_os_index(topo, lid);
102 OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
103 "physical cpu %d %s found in cpuset %s",
104 lid, (NULL == obj) ? "not" : "is",
105 (NULL == opal_hwloc_base_cpu_list) ? "None" : opal_hwloc_base_cpu_list));
106
107 if (NULL != obj && HWLOC_OBJ_CORE == obj_type) {
108 obj = obj->parent;
109 }
110 return obj;
111 }
112
113 opal_output_verbose(5, opal_hwloc_base_framework.framework_output,
114 "Searching for %d LOGICAL PU", lid);
115
116
117 obj = hwloc_get_obj_by_type(topo, obj_type, lid);
118 OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
119 "logical cpu %d %s found in cpuset %s",
120 lid, (NULL == obj) ? "not" : "is",
121 (NULL == opal_hwloc_base_cpu_list) ? "None" : opal_hwloc_base_cpu_list));
122
123
124 return obj;
125 }
126
127
128
129
130 int opal_hwloc_base_filter_cpus(hwloc_topology_t topo)
131 {
132 hwloc_obj_t root, pu;
133 hwloc_cpuset_t avail = NULL, pucpus, res;
134 opal_hwloc_topo_data_t *sum;
135 opal_hwloc_obj_data_t *data;
136 char **ranges=NULL, **range=NULL;
137 int idx, cpu, start, end;
138
139 root = hwloc_get_root_obj(topo);
140
141 if (NULL == root->userdata) {
142 root->userdata = (void*)OBJ_NEW(opal_hwloc_topo_data_t);
143 }
144 sum = (opal_hwloc_topo_data_t*)root->userdata;
145
146
147 if (NULL != sum->available) {
148 return OPAL_SUCCESS;
149 }
150
151
152 if (NULL == opal_hwloc_base_cpu_list) {
153
154 #if HWLOC_API_VERSION < 0x20000
155 avail = hwloc_bitmap_alloc();
156 hwloc_bitmap_and(avail, root->online_cpuset, root->allowed_cpuset);
157 #else
158 avail = hwloc_bitmap_dup(root->cpuset);
159 #endif
160 OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
161 "hwloc:base: no cpus specified - using root available cpuset"));
162 } else {
163 OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
164 "hwloc:base: filtering cpuset"));
165
166 ranges = opal_argv_split(opal_hwloc_base_cpu_list, ',');
167 avail = hwloc_bitmap_alloc();
168 hwloc_bitmap_zero(avail);
169 res = hwloc_bitmap_alloc();
170 pucpus = hwloc_bitmap_alloc();
171 for (idx=0; idx < opal_argv_count(ranges); idx++) {
172 range = opal_argv_split(ranges[idx], '-');
173 switch (opal_argv_count(range)) {
174 case 1:
175
176 cpu = strtoul(range[0], NULL, 10);
177 if (NULL != (pu = opal_hwloc_base_get_pu(topo, cpu, OPAL_HWLOC_LOGICAL))) {
178 #if HWLOC_API_VERSION < 0x20000
179 hwloc_bitmap_and(pucpus, pu->online_cpuset, pu->allowed_cpuset);
180 #else
181 hwloc_bitmap_free(pucpus);
182 pucpus = hwloc_bitmap_dup(pu->cpuset);
183 #endif
184 hwloc_bitmap_or(res, avail, pucpus);
185 hwloc_bitmap_copy(avail, res);
186 data = (opal_hwloc_obj_data_t*)pu->userdata;
187 if (NULL == data) {
188 pu->userdata = (void*)OBJ_NEW(opal_hwloc_obj_data_t);
189 data = (opal_hwloc_obj_data_t*)pu->userdata;
190 }
191 data->npus++;
192 }
193 break;
194 case 2:
195
196 start = strtoul(range[0], NULL, 10);
197 end = strtoul(range[1], NULL, 10);
198 for (cpu=start; cpu <= end; cpu++) {
199 if (NULL != (pu = opal_hwloc_base_get_pu(topo, cpu, OPAL_HWLOC_LOGICAL))) {
200 #if HWLOC_API_VERSION < 0x20000
201 hwloc_bitmap_and(pucpus, pu->online_cpuset, pu->allowed_cpuset);
202 #else
203 hwloc_bitmap_free(pucpus);
204 pucpus = hwloc_bitmap_dup(pu->cpuset);
205 #endif
206 hwloc_bitmap_or(res, avail, pucpus);
207 hwloc_bitmap_copy(avail, res);
208 data = (opal_hwloc_obj_data_t*)pu->userdata;
209 if (NULL == data) {
210 pu->userdata = (void*)OBJ_NEW(opal_hwloc_obj_data_t);
211 data = (opal_hwloc_obj_data_t*)pu->userdata;
212 }
213 data->npus++;
214 }
215 }
216 break;
217 default:
218 break;
219 }
220 opal_argv_free(range);
221 }
222 if (NULL != ranges) {
223 opal_argv_free(ranges);
224 }
225 hwloc_bitmap_free(res);
226 hwloc_bitmap_free(pucpus);
227 }
228
229
230 sum->available = avail;
231
232 return OPAL_SUCCESS;
233 }
234
235 static void fill_cache_line_size(void)
236 {
237 int i = 0, cache_level = 2;
238 unsigned size;
239 unsigned int cache_object = HWLOC_OBJ_L2CACHE;
240 hwloc_obj_t obj;
241 bool found = false;
242
243
244 size = 4096;
245 while (cache_level > 0 && !found) {
246 i=0;
247 while (1) {
248 obj = opal_hwloc_base_get_obj_by_type(opal_hwloc_topology,
249 cache_object, cache_level,
250 i, OPAL_HWLOC_LOGICAL);
251 if (NULL == obj) {
252 --cache_level;
253 cache_object = HWLOC_OBJ_L1CACHE;
254 break;
255 } else {
256 if (NULL != obj->attr &&
257 obj->attr->cache.linesize > 0 &&
258 size > obj->attr->cache.linesize) {
259 size = obj->attr->cache.linesize;
260 found = true;
261 }
262 }
263 ++i;
264 }
265 }
266
267
268
269
270 if (found) {
271 opal_cache_line_size = (int) size;
272 }
273 }
274
275 int opal_hwloc_base_get_topology(void)
276 {
277 int rc;
278 opal_process_name_t wildcard_rank;
279 char *val = NULL;
280 #if HWLOC_API_VERSION >= 0x20000
281 int rc2, rc3, fd;
282 uint64_t addr, *aptr, size, *sptr;
283 char *shmemfile;
284 #endif
285
286 opal_output_verbose(2, opal_hwloc_base_framework.framework_output,
287 "hwloc:base:get_topology");
288
289
290 if (NULL != opal_hwloc_topology) {
291 return OPAL_SUCCESS;
292 }
293 wildcard_rank.jobid = OPAL_PROC_MY_NAME.jobid;
294 wildcard_rank.vpid = OPAL_VPID_WILDCARD;
295
296 if (NULL != opal_pmix.get) {
297 #if HWLOC_API_VERSION >= 0x20000
298 opal_output_verbose(2, opal_hwloc_base_framework.framework_output,
299 "hwloc:base: looking for topology in shared memory");
300
301
302 aptr = &addr;
303 sptr = &size;
304 OPAL_MODEX_RECV_VALUE_OPTIONAL(rc, OPAL_PMIX_HWLOC_SHMEM_FILE,
305 &wildcard_rank, (void**)&shmemfile, OPAL_STRING);
306 OPAL_MODEX_RECV_VALUE_OPTIONAL(rc2, OPAL_PMIX_HWLOC_SHMEM_ADDR,
307 &wildcard_rank, (void**)&aptr, OPAL_SIZE);
308 OPAL_MODEX_RECV_VALUE_OPTIONAL(rc3, OPAL_PMIX_HWLOC_SHMEM_SIZE,
309 &wildcard_rank, (void**)&sptr, OPAL_SIZE);
310 if (OPAL_SUCCESS == rc && OPAL_SUCCESS == rc2 && OPAL_SUCCESS == rc3) {
311 if (0 > (fd = open(shmemfile, O_RDONLY))) {
312 free(shmemfile);
313 OPAL_ERROR_LOG(OPAL_ERR_FILE_OPEN_FAILURE)
314 return OPAL_ERR_FILE_OPEN_FAILURE;
315 }
316 free(shmemfile);
317 if (0 != hwloc_shmem_topology_adopt(&opal_hwloc_topology, fd,
318 0, (void*)addr, size, 0)) {
319 if (4 < opal_output_get_verbosity(opal_hwloc_base_framework.framework_output)) {
320 FILE *file = fopen("/proc/self/maps", "r");
321 if (file) {
322 char line[256];
323 opal_output(0, "Dumping /proc/self/maps");
324
325 while (fgets(line, sizeof(line), file) != NULL) {
326 char *end = strchr(line, '\n');
327 if (end) {
328 *end = '\0';
329 }
330 opal_output(0, "%s", line);
331 }
332 fclose(file);
333 }
334 }
335
336 } else {
337 opal_output_verbose(2, opal_hwloc_base_framework.framework_output,
338 "hwloc:base: topology in shared memory");
339 topo_in_shmem = true;
340 return OPAL_SUCCESS;
341 }
342 }
343 #endif
344
345
346 opal_output_verbose(1, opal_hwloc_base_framework.framework_output,
347 "hwloc:base[%s:%d] getting topology XML string",
348 __FILE__, __LINE__);
349 #if HWLOC_API_VERSION >= 0x20000
350 OPAL_MODEX_RECV_VALUE_IMMEDIATE(rc, OPAL_PMIX_HWLOC_XML_V2,
351 &wildcard_rank, &val, OPAL_STRING);
352 #else
353 OPAL_MODEX_RECV_VALUE_IMMEDIATE(rc, OPAL_PMIX_HWLOC_XML_V1,
354 &wildcard_rank, &val, OPAL_STRING);
355 #endif
356 if (rc != OPAL_SUCCESS) {
357
358 OPAL_MODEX_RECV_VALUE_OPTIONAL(rc, OPAL_PMIX_LOCAL_TOPO,
359 &wildcard_rank, &val, OPAL_STRING);
360 }
361 } else {
362 opal_output_verbose(1, opal_hwloc_base_framework.framework_output,
363 "hwloc:base PMIx not available");
364 rc = OPAL_ERR_NOT_SUPPORTED;
365 }
366
367 if (OPAL_SUCCESS == rc && NULL != val) {
368 opal_output_verbose(1, opal_hwloc_base_framework.framework_output,
369 "hwloc:base loading topology from XML");
370
371 if (0 != hwloc_topology_init(&opal_hwloc_topology)) {
372 free(val);
373 return OPAL_ERROR;
374 }
375 if (0 != hwloc_topology_set_xmlbuffer(opal_hwloc_topology, val, strlen(val)+1)) {
376 free(val);
377 hwloc_topology_destroy(opal_hwloc_topology);
378 return OPAL_ERROR;
379 }
380
381
382
383 if (0 != opal_hwloc_base_topology_set_flags(opal_hwloc_topology,
384 HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM,
385 true)) {
386 hwloc_topology_destroy(opal_hwloc_topology);
387 free(val);
388 return OPAL_ERROR;
389 }
390
391 if (0 != hwloc_topology_load(opal_hwloc_topology)) {
392 hwloc_topology_destroy(opal_hwloc_topology);
393 free(val);
394 return OPAL_ERROR;
395 }
396 free(val);
397
398 if (OPAL_SUCCESS != (rc = opal_hwloc_base_filter_cpus(opal_hwloc_topology))) {
399 hwloc_topology_destroy(opal_hwloc_topology);
400 return rc;
401 }
402 } else if (NULL == opal_hwloc_base_topo_file) {
403 opal_output_verbose(1, opal_hwloc_base_framework.framework_output,
404 "hwloc:base discovering topology");
405 if (0 != hwloc_topology_init(&opal_hwloc_topology) ||
406 0 != opal_hwloc_base_topology_set_flags(opal_hwloc_topology, 0, true) ||
407 0 != hwloc_topology_load(opal_hwloc_topology)) {
408 OPAL_ERROR_LOG(OPAL_ERR_NOT_SUPPORTED);
409 return OPAL_ERR_NOT_SUPPORTED;
410 }
411
412 if (OPAL_SUCCESS != (rc = opal_hwloc_base_filter_cpus(opal_hwloc_topology))) {
413 hwloc_topology_destroy(opal_hwloc_topology);
414 return rc;
415 }
416 } else {
417 opal_output_verbose(1, opal_hwloc_base_framework.framework_output,
418 "hwloc:base loading topology from file %s",
419 opal_hwloc_base_topo_file);
420 if (OPAL_SUCCESS != (rc = opal_hwloc_base_set_topology(opal_hwloc_base_topo_file))) {
421 return rc;
422 }
423 }
424
425
426
427 fill_cache_line_size();
428
429
430
431
432 opal_hwloc_base_get_local_cpuset();
433
434 return OPAL_SUCCESS;
435 }
436
437 int opal_hwloc_base_set_topology(char *topofile)
438 {
439 struct hwloc_topology_support *support;
440
441 OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
442 "hwloc:base:set_topology %s", topofile));
443
444 if (NULL != opal_hwloc_topology) {
445 hwloc_topology_destroy(opal_hwloc_topology);
446 }
447 if (0 != hwloc_topology_init(&opal_hwloc_topology)) {
448 return OPAL_ERR_NOT_SUPPORTED;
449 }
450 if (0 != hwloc_topology_set_xml(opal_hwloc_topology, topofile)) {
451 hwloc_topology_destroy(opal_hwloc_topology);
452 OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
453 "hwloc:base:set_topology bad topo file"));
454 return OPAL_ERR_NOT_SUPPORTED;
455 }
456
457
458
459 if (0 != opal_hwloc_base_topology_set_flags(opal_hwloc_topology,
460 HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM,
461 true)) {
462 hwloc_topology_destroy(opal_hwloc_topology);
463 return OPAL_ERR_NOT_SUPPORTED;
464 }
465 if (0 != hwloc_topology_load(opal_hwloc_topology)) {
466 hwloc_topology_destroy(opal_hwloc_topology);
467 OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
468 "hwloc:base:set_topology failed to load"));
469 return OPAL_ERR_NOT_SUPPORTED;
470 }
471
472
473
474
475
476
477 support = (struct hwloc_topology_support*)hwloc_topology_get_support(opal_hwloc_topology);
478 support->cpubind->set_thisproc_cpubind = true;
479 support->membind->set_thisproc_membind = true;
480
481
482
483 fill_cache_line_size();
484
485
486 return OPAL_SUCCESS;
487 }
488
489 static void free_object(hwloc_obj_t obj)
490 {
491 opal_hwloc_obj_data_t *data;
492 unsigned k;
493
494
495 if (NULL != obj->userdata) {
496 data = (opal_hwloc_obj_data_t*)obj->userdata;
497 OBJ_RELEASE(data);
498 obj->userdata = NULL;
499 }
500
501
502 for (k=0; k < obj->arity; k++) {
503 free_object(obj->children[k]);
504 }
505 }
506
507 void opal_hwloc_base_free_topology(hwloc_topology_t topo)
508 {
509 hwloc_obj_t obj;
510 opal_hwloc_topo_data_t *rdata;
511 unsigned k;
512
513 if (!topo_in_shmem) {
514 obj = hwloc_get_root_obj(topo);
515
516 if (NULL != obj->userdata) {
517 rdata = (opal_hwloc_topo_data_t*)obj->userdata;
518 OBJ_RELEASE(rdata);
519 obj->userdata = NULL;
520 }
521
522
523
524 for (k=0; k < obj->arity; k++) {
525 free_object(obj->children[k]);
526 }
527 }
528 hwloc_topology_destroy(topo);
529 }
530
531 void opal_hwloc_base_get_local_cpuset(void)
532 {
533 hwloc_obj_t root;
534
535 if (NULL != opal_hwloc_topology) {
536 if (NULL == opal_hwloc_my_cpuset) {
537 opal_hwloc_my_cpuset = hwloc_bitmap_alloc();
538 }
539
540
541 if (hwloc_get_cpubind(opal_hwloc_topology,
542 opal_hwloc_my_cpuset,
543 HWLOC_CPUBIND_PROCESS) < 0) {
544
545 root = hwloc_get_root_obj(opal_hwloc_topology);
546 hwloc_bitmap_copy(opal_hwloc_my_cpuset, root->cpuset);
547 }
548 }
549 }
550
551 int opal_hwloc_base_report_bind_failure(const char *file,
552 int line,
553 const char *msg, int rc)
554 {
555 static int already_reported = 0;
556
557 if (!already_reported &&
558 OPAL_HWLOC_BASE_MBFA_SILENT != opal_hwloc_base_mbfa) {
559 char hostname[OPAL_MAXHOSTNAMELEN];
560 gethostname(hostname, sizeof(hostname));
561
562 opal_show_help("help-opal-hwloc-base.txt", "mbind failure", true,
563 hostname, getpid(), file, line, msg,
564 (OPAL_HWLOC_BASE_MBFA_WARN == opal_hwloc_base_mbfa) ?
565 "Warning -- your job will continue, but possibly with degraded performance" :
566 "ERROR -- your job may abort or behave erraticly");
567 already_reported = 1;
568 return rc;
569 }
570
571 return OPAL_SUCCESS;
572 }
573
574
575 bool opal_hwloc_base_single_cpu(hwloc_cpuset_t cpuset)
576 {
577 int i;
578 bool one=false;
579
580
581
582
583
584
585
586
587
588 for (i=hwloc_bitmap_first(cpuset);
589 i <= hwloc_bitmap_last(cpuset);
590 i++) {
591 if (hwloc_bitmap_isset(cpuset, i)) {
592 if (one) {
593 return false;
594 }
595 one = true;
596 }
597 }
598
599 return one;
600 }
601
602
603 unsigned int opal_hwloc_base_get_npus(hwloc_topology_t topo,
604 hwloc_obj_t obj)
605 {
606 opal_hwloc_obj_data_t *data;
607 unsigned int cnt = 0;
608
609 data = (opal_hwloc_obj_data_t*)obj->userdata;
610 if (NULL == data || !data->npus_calculated) {
611 if (!opal_hwloc_use_hwthreads_as_cpus) {
612
613
614
615
616
617
618
619 cnt = hwloc_get_nbobjs_inside_cpuset_by_type(topo, obj->cpuset, HWLOC_OBJ_CORE);
620 } else {
621 hwloc_cpuset_t cpuset;
622
623
624
625
626
627 if (NULL == (cpuset = obj->cpuset)) {
628 return 0;
629 }
630
631
632
633
634
635
636
637 cnt = hwloc_bitmap_weight(cpuset);
638 }
639
640 data = (opal_hwloc_obj_data_t*)obj->userdata;
641 if (NULL == data) {
642 data = OBJ_NEW(opal_hwloc_obj_data_t);
643 obj->userdata = (void*)data;
644 }
645 data->npus = cnt;
646 data->npus_calculated = true;
647 }
648
649 return data->npus;
650 }
651
652 unsigned int opal_hwloc_base_get_obj_idx(hwloc_topology_t topo,
653 hwloc_obj_t obj,
654 opal_hwloc_resource_type_t rtype)
655 {
656 unsigned cache_level=0;
657 opal_hwloc_obj_data_t *data;
658 hwloc_obj_t ptr;
659 unsigned int nobjs, i;
660
661 OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
662 "hwloc:base:get_idx"));
663
664
665 data = (opal_hwloc_obj_data_t*)obj->userdata;
666
667 if (NULL == data) {
668 data = OBJ_NEW(opal_hwloc_obj_data_t);
669 obj->userdata = (void*)data;
670 }
671
672 if (data->idx < UINT_MAX) {
673 OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
674 "hwloc:base:get_idx already have data: %u",
675 data->idx));
676 return data->idx;
677 }
678
679 #if HWLOC_API_VERSION < 0x20000
680
681 if (HWLOC_OBJ_CACHE == obj->type) {
682 cache_level = obj->attr->cache.depth;
683 }
684 #endif
685
686 nobjs = opal_hwloc_base_get_nbobjs_by_type(topo, obj->type, cache_level, rtype);
687
688 OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
689 "hwloc:base:get_idx found %u objects of type %s:%u",
690 nobjs, hwloc_obj_type_string(obj->type), cache_level));
691
692
693 for (i=0; i < nobjs; i++) {
694 ptr = opal_hwloc_base_get_obj_by_type(topo, obj->type, cache_level, i, rtype);
695 if (ptr == obj) {
696 data->idx = i;
697 return i;
698 }
699 }
700
701 opal_show_help("help-opal-hwloc-base.txt",
702 "obj-idx-failed", true,
703 hwloc_obj_type_string(obj->type), cache_level);
704 return UINT_MAX;
705 }
706
707
708
709
710
711
712
713 static hwloc_obj_t df_search(hwloc_topology_t topo,
714 hwloc_obj_t start,
715 hwloc_obj_type_t target,
716 unsigned cache_level,
717 unsigned int nobj,
718 opal_hwloc_resource_type_t rtype,
719 unsigned int *num_objs)
720 {
721 hwloc_obj_t obj;
722 int search_depth;
723
724 search_depth = hwloc_get_type_depth(topo, target);
725 if (HWLOC_TYPE_DEPTH_MULTIPLE == search_depth) {
726
727 #if HWLOC_API_VERSION >= 0x20000
728 return NULL;
729 #else
730 if (cache_level != HWLOC_OBJ_CACHE)
731 return NULL;
732 search_depth = hwloc_get_cache_type_depth(topo, cache_level, (hwloc_obj_cache_type_t) -1);
733 #endif
734 }
735 if (HWLOC_TYPE_DEPTH_UNKNOWN == search_depth)
736 return NULL;
737
738 if (OPAL_HWLOC_LOGICAL == rtype) {
739 if (num_objs)
740 *num_objs = hwloc_get_nbobjs_by_depth(topo, search_depth);
741 return hwloc_get_obj_by_depth(topo, search_depth, nobj);
742 }
743 if (OPAL_HWLOC_PHYSICAL == rtype) {
744
745
746
747
748
749
750
751
752
753
754
755 hwloc_obj_t found = NULL;
756 obj = NULL;
757 if (num_objs)
758 *num_objs = 0;
759 while ((obj = hwloc_get_next_obj_by_depth(topo, search_depth, obj)) != NULL) {
760 if (num_objs && obj->os_index > *num_objs)
761 *num_objs = obj->os_index;
762 if (obj->os_index == nobj)
763 found = obj;
764 }
765 return found;
766 }
767 if (OPAL_HWLOC_AVAILABLE == rtype) {
768
769
770
771 hwloc_obj_t root;
772 opal_hwloc_topo_data_t *rdata;
773 root = hwloc_get_root_obj(topo);
774 rdata = (opal_hwloc_topo_data_t*)root->userdata;
775 hwloc_cpuset_t constrained_cpuset;
776
777 constrained_cpuset = hwloc_bitmap_alloc();
778 if (rdata && rdata->available) {
779 hwloc_bitmap_and(constrained_cpuset, start->cpuset, rdata->available);
780 } else {
781 hwloc_bitmap_copy(constrained_cpuset, start->cpuset);
782 }
783
784 unsigned idx = 0;
785 if (num_objs)
786 *num_objs = hwloc_get_nbobjs_inside_cpuset_by_depth(topo, constrained_cpuset, search_depth);
787 obj = NULL;
788 while ((obj = hwloc_get_next_obj_inside_cpuset_by_depth(topo, constrained_cpuset, search_depth, obj)) != NULL) {
789 if (idx == nobj) {
790 hwloc_bitmap_free(constrained_cpuset);
791 return obj;
792 }
793 idx++;
794 }
795 hwloc_bitmap_free(constrained_cpuset);
796 return NULL;
797 }
798 return NULL;
799 }
800
801 unsigned int opal_hwloc_base_get_nbobjs_by_type(hwloc_topology_t topo,
802 hwloc_obj_type_t target,
803 unsigned cache_level,
804 opal_hwloc_resource_type_t rtype)
805 {
806 unsigned int num_objs;
807 hwloc_obj_t obj;
808 opal_hwloc_summary_t *sum;
809 opal_hwloc_topo_data_t *data;
810 int rc;
811
812
813 if (NULL == topo) {
814 OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
815 "hwloc:base:get_nbobjs NULL topology"));
816 return 0;
817 }
818
819
820
821
822
823 if (OPAL_HWLOC_LOGICAL == rtype
824 #if HWLOC_API_VERSION < 0x20000
825 && HWLOC_OBJ_CACHE != target
826 #endif
827 ) {
828
829 if (0 > (rc = hwloc_get_nbobjs_by_type(topo, target))) {
830 opal_output(0, "UNKNOWN HWLOC ERROR");
831 return 0;
832 }
833 return rc;
834 }
835
836
837 num_objs = 0;
838 obj = hwloc_get_root_obj(topo);
839
840
841 data = (opal_hwloc_topo_data_t*)obj->userdata;
842 if (NULL == data) {
843 data = OBJ_NEW(opal_hwloc_topo_data_t);
844 obj->userdata = (void*)data;
845 } else {
846 OPAL_LIST_FOREACH(sum, &data->summaries, opal_hwloc_summary_t) {
847 if (target == sum->type &&
848 cache_level == sum->cache_level &&
849 rtype == sum->rtype) {
850
851 OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
852 "hwloc:base:get_nbojbs pre-existing data %u of %s:%u",
853 sum->num_objs, hwloc_obj_type_string(target), cache_level));
854 return sum->num_objs;
855 }
856 }
857 }
858
859
860 df_search(topo, obj, target, cache_level, 0, rtype, &num_objs);
861
862
863 sum = OBJ_NEW(opal_hwloc_summary_t);
864 sum->type = target;
865 sum->cache_level = cache_level;
866 sum->num_objs = num_objs;
867 sum->rtype = rtype;
868 opal_list_append(&data->summaries, &sum->super);
869
870 OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
871 "hwloc:base:get_nbojbs computed data %u of %s:%u",
872 num_objs, hwloc_obj_type_string(target), cache_level));
873
874 return num_objs;
875 }
876
877
878
879
880 hwloc_obj_t opal_hwloc_base_get_obj_by_type(hwloc_topology_t topo,
881 hwloc_obj_type_t target,
882 unsigned cache_level,
883 unsigned int instance,
884 opal_hwloc_resource_type_t rtype)
885 {
886 hwloc_obj_t obj;
887
888
889 if (NULL == topo) {
890 return NULL;
891 }
892
893
894
895
896
897 if (OPAL_HWLOC_LOGICAL == rtype
898 #if HWLOC_API_VERSION < 0x20000
899 && HWLOC_OBJ_CACHE != target
900 #endif
901 ) {
902 return hwloc_get_obj_by_type(topo, target, instance);
903 }
904
905
906 obj = hwloc_get_root_obj(topo);
907 return df_search(topo, obj, target, cache_level, instance, rtype, NULL);
908 }
909
910 static void df_clear(hwloc_topology_t topo,
911 hwloc_obj_t start)
912 {
913 unsigned k;
914 opal_hwloc_obj_data_t *data;
915
916
917 data = (opal_hwloc_obj_data_t*)start->userdata;
918 if (NULL != data) {
919 data->num_bound = 0;
920 }
921
922 for (k=0; k < start->arity; k++) {
923 df_clear(topo, start->children[k]);
924 }
925 }
926
927 void opal_hwloc_base_clear_usage(hwloc_topology_t topo)
928 {
929 hwloc_obj_t root;
930 unsigned k;
931
932
933 if (NULL == topo) {
934 OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
935 "hwloc:base:clear_usage: NULL topology"));
936 return;
937 }
938
939 root = hwloc_get_root_obj(topo);
940
941
942
943 for (k=0; k < root->arity; k++) {
944 df_clear(topo, root->children[k]);
945 }
946 }
947
948
949
950
951
952
953 static int socket_to_cpu_set(char *cpus,
954 hwloc_topology_t topo,
955 opal_hwloc_resource_type_t rtype,
956 hwloc_bitmap_t cpumask)
957 {
958 char **range;
959 int range_cnt;
960 int lower_range, upper_range;
961 int socket_id;
962 hwloc_obj_t obj;
963
964 if ('*' == cpus[0]) {
965
966 obj = hwloc_get_root_obj(topo);
967
968
969
970 hwloc_bitmap_or(cpumask, cpumask, obj->cpuset);
971 return OPAL_SUCCESS;
972 }
973
974 range = opal_argv_split(cpus,'-');
975 range_cnt = opal_argv_count(range);
976 switch (range_cnt) {
977 case 1:
978 socket_id = atoi(range[0]);
979 obj = opal_hwloc_base_get_obj_by_type(topo, HWLOC_OBJ_SOCKET, 0, socket_id, rtype);
980
981 hwloc_bitmap_or(cpumask, cpumask, obj->cpuset);
982 break;
983
984 case 2:
985 lower_range = atoi(range[0]);
986 upper_range = atoi(range[1]);
987
988 for (socket_id=lower_range; socket_id<=upper_range; socket_id++) {
989 obj = opal_hwloc_base_get_obj_by_type(topo, HWLOC_OBJ_SOCKET, 0, socket_id, rtype);
990
991 hwloc_bitmap_or(cpumask, cpumask, obj->cpuset);
992 }
993 break;
994 default:
995 opal_argv_free(range);
996 return OPAL_ERROR;
997 }
998 opal_argv_free(range);
999
1000 return OPAL_SUCCESS;
1001 }
1002
1003 static int socket_core_to_cpu_set(char *socket_core_list,
1004 hwloc_topology_t topo,
1005 opal_hwloc_resource_type_t rtype,
1006 hwloc_bitmap_t cpumask)
1007 {
1008 int rc=OPAL_SUCCESS, i, j;
1009 char **socket_core, *corestr;
1010 char **range, **list;
1011 int range_cnt;
1012 int lower_range, upper_range;
1013 int socket_id, core_id;
1014 hwloc_obj_t socket, core;
1015 hwloc_obj_type_t obj_type = HWLOC_OBJ_CORE;
1016
1017 socket_core = opal_argv_split(socket_core_list, ':');
1018 socket_id = atoi(socket_core[0]);
1019
1020
1021 if (NULL == (socket = opal_hwloc_base_get_obj_by_type(topo, HWLOC_OBJ_SOCKET, 0,
1022 socket_id, rtype))) {
1023 opal_argv_free(socket_core);
1024 return OPAL_ERR_NOT_FOUND;
1025 }
1026
1027
1028
1029
1030
1031 if (NULL == hwloc_get_obj_by_type(topo, HWLOC_OBJ_CORE, 0)) {
1032 obj_type = HWLOC_OBJ_PU;
1033 }
1034
1035 for (i=1; NULL != socket_core[i]; i++) {
1036 if ('C' == socket_core[i][0] ||
1037 'c' == socket_core[i][0]) {
1038 corestr = &socket_core[i][1];
1039 } else {
1040 corestr = socket_core[i];
1041 }
1042 if ('*' == corestr[0]) {
1043
1044 hwloc_bitmap_or(cpumask, cpumask, socket->cpuset);
1045
1046 rc = OPAL_SUCCESS;
1047 break;
1048 } else {
1049 range = opal_argv_split(corestr, '-');
1050 range_cnt = opal_argv_count(range);
1051
1052 switch (range_cnt) {
1053 case 1:
1054 list = opal_argv_split(range[0], ',');
1055 for (j=0; NULL != list[j]; j++) {
1056 core_id = atoi(list[j]);
1057
1058 if (NULL == (core = df_search(topo, socket, obj_type, 0,
1059 core_id, OPAL_HWLOC_AVAILABLE,
1060 NULL))) {
1061 opal_argv_free(list);
1062 opal_argv_free(range);
1063 opal_argv_free(socket_core);
1064 return OPAL_ERR_NOT_FOUND;
1065 }
1066
1067 hwloc_bitmap_or(cpumask, cpumask, core->cpuset);
1068 }
1069 opal_argv_free(list);
1070 break;
1071
1072 case 2:
1073 opal_output_verbose(5, opal_hwloc_base_framework.framework_output,
1074 "range of cores given: start %s stop %s",
1075 range[0], range[1]);
1076 lower_range = atoi(range[0]);
1077 upper_range = atoi(range[1]);
1078 for (core_id=lower_range; core_id <= upper_range; core_id++) {
1079
1080 if (NULL == (core = df_search(topo, socket, obj_type, 0,
1081 core_id, OPAL_HWLOC_AVAILABLE,
1082 NULL))) {
1083 opal_argv_free(range);
1084 opal_argv_free(socket_core);
1085 return OPAL_ERR_NOT_FOUND;
1086 }
1087
1088 hwloc_bitmap_or(cpumask, cpumask, core->cpuset);
1089 }
1090 break;
1091
1092 default:
1093 opal_argv_free(range);
1094 opal_argv_free(socket_core);
1095 return OPAL_ERROR;
1096 }
1097 opal_argv_free(range);
1098 }
1099 }
1100 opal_argv_free(socket_core);
1101
1102 return rc;
1103 }
1104
1105 int opal_hwloc_base_cpu_list_parse(const char *slot_str,
1106 hwloc_topology_t topo,
1107 opal_hwloc_resource_type_t rtype,
1108 hwloc_cpuset_t cpumask)
1109 {
1110 char **item, **rngs;
1111 int rc, i, j, k;
1112 hwloc_obj_t pu;
1113 char **range, **list;
1114 size_t range_cnt;
1115 int core_id, lower_range, upper_range;
1116
1117
1118 if (NULL == opal_hwloc_topology) {
1119 return OPAL_ERR_NOT_SUPPORTED;
1120 }
1121 if (NULL == slot_str || 0 == strlen(slot_str)) {
1122 return OPAL_ERR_BAD_PARAM;
1123 }
1124
1125 opal_output_verbose(5, opal_hwloc_base_framework.framework_output,
1126 "slot assignment: slot_list == %s",
1127 slot_str);
1128
1129
1130 item = opal_argv_split(slot_str, ';');
1131
1132
1133 hwloc_bitmap_zero(cpumask);
1134
1135 for (i=0; NULL != item[i]; i++) {
1136 opal_output_verbose(5, opal_hwloc_base_framework.framework_output,
1137 "working assignment %s",
1138 item[i]);
1139
1140
1141
1142
1143 if ('S' == item[i][0] ||
1144 's' == item[i][0] ||
1145 NULL != strchr(item[i], ':')) {
1146
1147 if (NULL == strchr(item[i], ':')) {
1148
1149
1150
1151
1152 rngs = opal_argv_split(&item[i][1], ',');
1153 for (j=0; NULL != rngs[j]; j++) {
1154 if (OPAL_SUCCESS != (rc = socket_to_cpu_set(rngs[j], topo, rtype, cpumask))) {
1155 opal_argv_free(rngs);
1156 opal_argv_free(item);
1157 return rc;
1158 }
1159 }
1160 opal_argv_free(rngs);
1161 } else {
1162
1163 if ('S' == item[i][0] ||
1164 's' == item[i][0]) {
1165 rngs = opal_argv_split(&item[i][1], ',');
1166 for (j=0; NULL != rngs[j]; j++) {
1167 if (OPAL_SUCCESS != (rc = socket_core_to_cpu_set(rngs[j], topo, rtype, cpumask))) {
1168 opal_argv_free(rngs);
1169 opal_argv_free(item);
1170 return rc;
1171 }
1172 }
1173 opal_argv_free(rngs);
1174 } else {
1175 rngs = opal_argv_split(item[i], ',');
1176 for (j=0; NULL != rngs[j]; j++) {
1177 if (OPAL_SUCCESS != (rc = socket_core_to_cpu_set(rngs[j], topo, rtype, cpumask))) {
1178 opal_argv_free(rngs);
1179 opal_argv_free(item);
1180 return rc;
1181 }
1182 }
1183 opal_argv_free(rngs);
1184 }
1185 }
1186 } else {
1187 rngs = opal_argv_split(item[i], ',');
1188 for (k=0; NULL != rngs[k]; k++) {
1189
1190 range = opal_argv_split(rngs[k], '-');
1191 range_cnt = opal_argv_count(range);
1192
1193 switch (range_cnt) {
1194 case 1:
1195 list = opal_argv_split(range[0], ',');
1196 for (j=0; NULL != list[j]; j++) {
1197 core_id = atoi(list[j]);
1198
1199 if (NULL == (pu = opal_hwloc_base_get_pu(topo, core_id, rtype))) {
1200 opal_argv_free(range);
1201 opal_argv_free(item);
1202 opal_argv_free(rngs);
1203 opal_argv_free(list);
1204 return OPAL_ERR_SILENT;
1205 }
1206
1207 hwloc_bitmap_or(cpumask, cpumask, pu->cpuset);
1208 }
1209 opal_argv_free(list);
1210 break;
1211
1212 case 2:
1213 lower_range = atoi(range[0]);
1214 upper_range = atoi(range[1]);
1215 for (core_id=lower_range; core_id <= upper_range; core_id++) {
1216
1217 if (NULL == (pu = opal_hwloc_base_get_pu(topo, core_id, rtype))) {
1218 opal_argv_free(range);
1219 opal_argv_free(item);
1220 opal_argv_free(rngs);
1221 return OPAL_ERR_SILENT;
1222 }
1223
1224 hwloc_bitmap_or(cpumask, cpumask, pu->cpuset);
1225 }
1226 break;
1227
1228 default:
1229 opal_argv_free(range);
1230 opal_argv_free(item);
1231 opal_argv_free(rngs);
1232 return OPAL_ERROR;
1233 }
1234 opal_argv_free(range);
1235 }
1236 opal_argv_free(rngs);
1237 }
1238 }
1239 opal_argv_free(item);
1240 return OPAL_SUCCESS;
1241 }
1242
1243 opal_hwloc_locality_t opal_hwloc_base_get_relative_locality(hwloc_topology_t topo,
1244 char *cpuset1, char *cpuset2)
1245 {
1246 opal_hwloc_locality_t locality;
1247 hwloc_obj_t obj;
1248 unsigned depth, d, width, w;
1249 bool shared;
1250 hwloc_obj_type_t type;
1251 int sect1, sect2;
1252 hwloc_cpuset_t loc1, loc2;
1253
1254
1255
1256
1257
1258 locality = OPAL_PROC_ON_NODE | OPAL_PROC_ON_HOST | OPAL_PROC_ON_CU | OPAL_PROC_ON_CLUSTER;
1259
1260
1261 if (NULL == cpuset1 || NULL == cpuset2) {
1262 return locality;
1263 }
1264
1265
1266 depth = hwloc_topology_get_depth(topo);
1267
1268
1269 loc1 = hwloc_bitmap_alloc();
1270 hwloc_bitmap_list_sscanf(loc1, cpuset1);
1271 loc2 = hwloc_bitmap_alloc();
1272 hwloc_bitmap_list_sscanf(loc2, cpuset2);
1273
1274
1275 for (d=1; d < depth; d++) {
1276 shared = false;
1277
1278 type = hwloc_get_depth_type(topo, d);
1279
1280 if (HWLOC_OBJ_NODE != type &&
1281 HWLOC_OBJ_SOCKET != type &&
1282 #if HWLOC_API_VERSION < 0x20000
1283 HWLOC_OBJ_CACHE != type &&
1284 #else
1285 HWLOC_OBJ_L3CACHE != type &&
1286 HWLOC_OBJ_L2CACHE != type &&
1287 HWLOC_OBJ_L1CACHE != type &&
1288 #endif
1289 HWLOC_OBJ_CORE != type &&
1290 HWLOC_OBJ_PU != type) {
1291 continue;
1292 }
1293
1294 width = hwloc_get_nbobjs_by_depth(topo, d);
1295
1296
1297
1298
1299 for (w=0; w < width; w++) {
1300
1301 obj = hwloc_get_obj_by_depth(topo, d, w);
1302
1303 sect1 = hwloc_bitmap_intersects(obj->cpuset, loc1);
1304 sect2 = hwloc_bitmap_intersects(obj->cpuset, loc2);
1305
1306 if (sect1 && sect2) {
1307 shared = true;
1308 switch(obj->type) {
1309 case HWLOC_OBJ_NODE:
1310 locality |= OPAL_PROC_ON_NUMA;
1311 break;
1312 case HWLOC_OBJ_SOCKET:
1313 locality |= OPAL_PROC_ON_SOCKET;
1314 break;
1315 #if HWLOC_API_VERSION < 0x20000
1316 case HWLOC_OBJ_CACHE:
1317 if (3 == obj->attr->cache.depth) {
1318 locality |= OPAL_PROC_ON_L3CACHE;
1319 } else if (2 == obj->attr->cache.depth) {
1320 locality |= OPAL_PROC_ON_L2CACHE;
1321 } else {
1322 locality |= OPAL_PROC_ON_L1CACHE;
1323 }
1324 break;
1325 #else
1326 case HWLOC_OBJ_L3CACHE:
1327 locality |= OPAL_PROC_ON_L3CACHE;
1328 break;
1329 case HWLOC_OBJ_L2CACHE:
1330 locality |= OPAL_PROC_ON_L2CACHE;
1331 break;
1332 case HWLOC_OBJ_L1CACHE:
1333 locality |= OPAL_PROC_ON_L1CACHE;
1334 break;
1335 #endif
1336 case HWLOC_OBJ_CORE:
1337 locality |= OPAL_PROC_ON_CORE;
1338 break;
1339 case HWLOC_OBJ_PU:
1340 locality |= OPAL_PROC_ON_HWTHREAD;
1341 break;
1342 default:
1343
1344 break;
1345 }
1346 break;
1347 }
1348
1349
1350
1351
1352 }
1353
1354
1355
1356
1357 if (!shared) {
1358 break;
1359 }
1360 }
1361
1362 opal_output_verbose(5, opal_hwloc_base_framework.framework_output,
1363 "locality: %s",
1364 opal_hwloc_base_print_locality(locality));
1365 hwloc_bitmap_free(loc1);
1366 hwloc_bitmap_free(loc2);
1367
1368 return locality;
1369 }
1370
1371
1372
1373
1374
1375 char* opal_hwloc_base_find_coprocessors(hwloc_topology_t topo)
1376 {
1377 hwloc_obj_t osdev;
1378 unsigned i;
1379 char **cps = NULL;
1380 char *cpstring = NULL;
1381 int depth;
1382
1383
1384
1385
1386 if (HWLOC_TYPE_DEPTH_UNKNOWN == (depth = hwloc_get_type_depth(topo, HWLOC_OBJ_OS_DEVICE))) {
1387 OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
1388 "hwloc:base:find_coprocessors: NONE FOUND IN TOPO"));
1389 return NULL;
1390 }
1391 #if HAVE_DECL_HWLOC_OBJ_OSDEV_COPROC
1392
1393 osdev = hwloc_get_obj_by_depth(topo, depth, 0);
1394 while (NULL != osdev) {
1395 if (HWLOC_OBJ_OSDEV_COPROC == osdev->attr->osdev.type) {
1396
1397 for (i=0; i < osdev->infos_count; i++) {
1398 if (0 == strncmp(osdev->infos[i].name, "MICSerialNumber", strlen("MICSerialNumber"))) {
1399 OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
1400 "hwloc:base:find_coprocessors: coprocessor %s found",
1401 osdev->infos[i].value));
1402 opal_argv_append_nosize(&cps, osdev->infos[i].value);
1403 }
1404 }
1405 }
1406 osdev = osdev->next_cousin;
1407 }
1408 if (NULL != cps) {
1409 cpstring = opal_argv_join(cps, ',');
1410 opal_argv_free(cps);
1411 }
1412 OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
1413 "hwloc:base:find_coprocessors: hosting coprocessors %s",
1414 (NULL == cpstring) ? "NONE" : cpstring));
1415 #else
1416 OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
1417 "hwloc:base:find_coprocessors: the version of hwloc that Open MPI was built against (v%d.%d.%d) does not support detecting coprocessors",
1418 (HWLOC_API_VERSION>>16)&&0xFF, (HWLOC_API_VERSION>>8)&0xFF, HWLOC_API_VERSION&&0xFF));
1419 #endif
1420 return cpstring;
1421 }
1422
1423 #define OPAL_HWLOC_MAX_ELOG_LINE 1024
1424
1425 static char *hwloc_getline(FILE *fp)
1426 {
1427 char *ret, *buff;
1428 char input[OPAL_HWLOC_MAX_ELOG_LINE];
1429
1430 ret = fgets(input, OPAL_HWLOC_MAX_ELOG_LINE, fp);
1431 if (NULL != ret) {
1432 input[strlen(input)-1] = '\0';
1433 buff = strdup(input);
1434 return buff;
1435 }
1436
1437 return NULL;
1438 }
1439
1440
1441
1442
1443
1444 char* opal_hwloc_base_check_on_coprocessor(void)
1445 {
1446
1447
1448
1449
1450 FILE *fp;
1451 char *t, *cptr, *e, *cp=NULL;
1452
1453 if (OPAL_SUCCESS != opal_os_dirpath_access("/proc/elog", S_IRUSR)) {
1454
1455
1456
1457
1458 return NULL;
1459 }
1460 if (NULL == (fp = fopen("/proc/elog", "r"))) {
1461
1462 return NULL;
1463 }
1464
1465
1466
1467 while (NULL != (cptr = hwloc_getline(fp))) {
1468 if (NULL != (t = strstr(cptr, "Card"))) {
1469
1470
1471
1472 t += 5;
1473 if (NULL == (e = strchr(t, ':'))) {
1474
1475 free(cptr);
1476 continue;
1477 }
1478 *e = '\0';
1479 cp = strdup(t);
1480 free(cptr);
1481 break;
1482 }
1483 free(cptr);
1484 }
1485 fclose(fp);
1486 OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
1487 "hwloc:base:check_coprocessor: on coprocessor %s",
1488 (NULL == cp) ? "NONE" : cp));
1489 return cp;
1490 }
1491
1492 char* opal_hwloc_base_print_binding(opal_binding_policy_t binding)
1493 {
1494 char *ret, *bind;
1495 opal_hwloc_print_buffers_t *ptr;
1496
1497 switch(OPAL_GET_BINDING_POLICY(binding)) {
1498 case OPAL_BIND_TO_NONE:
1499 bind = "NONE";
1500 break;
1501 case OPAL_BIND_TO_BOARD:
1502 bind = "BOARD";
1503 break;
1504 case OPAL_BIND_TO_NUMA:
1505 bind = "NUMA";
1506 break;
1507 case OPAL_BIND_TO_SOCKET:
1508 bind = "SOCKET";
1509 break;
1510 case OPAL_BIND_TO_L3CACHE:
1511 bind = "L3CACHE";
1512 break;
1513 case OPAL_BIND_TO_L2CACHE:
1514 bind = "L2CACHE";
1515 break;
1516 case OPAL_BIND_TO_L1CACHE:
1517 bind = "L1CACHE";
1518 break;
1519 case OPAL_BIND_TO_CORE:
1520 bind = "CORE";
1521 break;
1522 case OPAL_BIND_TO_HWTHREAD:
1523 bind = "HWTHREAD";
1524 break;
1525 case OPAL_BIND_TO_CPUSET:
1526 bind = "CPUSET";
1527 break;
1528 default:
1529 bind = "UNKNOWN";
1530 }
1531 ptr = opal_hwloc_get_print_buffer();
1532 if (NULL == ptr) {
1533 return opal_hwloc_print_null;
1534 }
1535
1536 if (OPAL_HWLOC_PRINT_NUM_BUFS == ptr->cntr) {
1537 ptr->cntr = 0;
1538 }
1539 if (!OPAL_BINDING_REQUIRED(binding) &&
1540 OPAL_BIND_OVERLOAD_ALLOWED(binding)) {
1541 snprintf(ptr->buffers[ptr->cntr], OPAL_HWLOC_PRINT_MAX_SIZE,
1542 "%s:IF-SUPPORTED:OVERLOAD-ALLOWED", bind);
1543 } else if (OPAL_BIND_OVERLOAD_ALLOWED(binding)) {
1544 snprintf(ptr->buffers[ptr->cntr], OPAL_HWLOC_PRINT_MAX_SIZE,
1545 "%s:OVERLOAD-ALLOWED", bind);
1546 } else if (!OPAL_BINDING_REQUIRED(binding)) {
1547 snprintf(ptr->buffers[ptr->cntr], OPAL_HWLOC_PRINT_MAX_SIZE,
1548 "%s:IF-SUPPORTED", bind);
1549 } else {
1550 snprintf(ptr->buffers[ptr->cntr], OPAL_HWLOC_PRINT_MAX_SIZE, "%s", bind);
1551 }
1552 ret = ptr->buffers[ptr->cntr];
1553 ptr->cntr++;
1554
1555 return ret;
1556 }
1557
1558
1559
1560
1561 static char *bitmap2rangestr(int bitmap)
1562 {
1563 size_t i;
1564 int range_start, range_end;
1565 bool first, isset;
1566 char tmp[BUFSIZ];
1567 const int stmp = sizeof(tmp) - 1;
1568 static char ret[BUFSIZ];
1569
1570 memset(ret, 0, sizeof(ret));
1571
1572 first = true;
1573 range_start = -999;
1574 for (i = 0; i < sizeof(int) * 8; ++i) {
1575 isset = (bitmap & (1 << i));
1576
1577
1578 if (range_start >= 0) {
1579 if (isset) {
1580 continue;
1581 } else {
1582
1583 if (!first) {
1584 strncat(ret, ",", sizeof(ret) - strlen(ret) - 1);
1585 } else {
1586 first = false;
1587 }
1588
1589 range_end = i - 1;
1590 if (range_start == range_end) {
1591 snprintf(tmp, stmp, "%d", range_start);
1592 } else {
1593 snprintf(tmp, stmp, "%d-%d", range_start, range_end);
1594 }
1595 strncat(ret, tmp, sizeof(ret) - strlen(ret) - 1);
1596
1597 range_start = -999;
1598 }
1599 }
1600
1601
1602 else {
1603 if (isset) {
1604 range_start = i;
1605 }
1606 }
1607 }
1608
1609
1610 if (range_start >= 0) {
1611 if (!first) {
1612 strncat(ret, ",", sizeof(ret) - strlen(ret) - 1);
1613 first = false;
1614 }
1615
1616 range_end = i - 1;
1617 if (range_start == range_end) {
1618 snprintf(tmp, stmp, "%d", range_start);
1619 } else {
1620 snprintf(tmp, stmp, "%d-%d", range_start, range_end);
1621 }
1622 strncat(ret, tmp, sizeof(ret) - strlen(ret) - 1);
1623 }
1624
1625 return ret;
1626 }
1627
1628
1629
1630
1631 static int build_map(int *num_sockets_arg, int *num_cores_arg,
1632 hwloc_cpuset_t cpuset, int ***map, hwloc_topology_t topo)
1633 {
1634 int num_sockets, num_cores;
1635 int socket_index, core_index, pu_index;
1636 hwloc_obj_t socket, core, pu;
1637 int **data;
1638
1639
1640 num_sockets = hwloc_get_nbobjs_by_type(topo, HWLOC_OBJ_SOCKET);
1641
1642
1643
1644 if (0 == num_sockets) {
1645 num_sockets = 1;
1646 }
1647
1648
1649
1650 num_cores = hwloc_get_nbobjs_by_type(topo, HWLOC_OBJ_CORE);
1651 *num_sockets_arg = num_sockets;
1652 *num_cores_arg = num_cores;
1653
1654
1655 data = malloc(num_sockets * sizeof(int *));
1656 if (NULL == data) {
1657 return OPAL_ERR_OUT_OF_RESOURCE;
1658 }
1659 data[0] = calloc(num_sockets * num_cores, sizeof(int));
1660 if (NULL == data[0]) {
1661 free(data);
1662 return OPAL_ERR_OUT_OF_RESOURCE;
1663 }
1664 for (socket_index = 1; socket_index < num_sockets; ++socket_index) {
1665 data[socket_index] = data[socket_index - 1] + num_cores;
1666 }
1667
1668
1669
1670 for (pu_index = 0,
1671 pu = hwloc_get_obj_inside_cpuset_by_type(topo,
1672 cpuset, HWLOC_OBJ_PU,
1673 pu_index);
1674 NULL != pu;
1675 pu = hwloc_get_obj_inside_cpuset_by_type(topo,
1676 cpuset, HWLOC_OBJ_PU,
1677 ++pu_index)) {
1678
1679 core = pu;
1680 while (NULL != core && core->type != HWLOC_OBJ_CORE) {
1681 core = core->parent;
1682 }
1683 core_index = 0;
1684 if (NULL != core) {
1685 core_index = core->logical_index;
1686 }
1687
1688
1689 socket = pu;
1690 while (NULL != socket && socket->type != HWLOC_OBJ_SOCKET) {
1691 socket = socket->parent;
1692 }
1693 socket_index = 0;
1694 if (NULL != socket) {
1695 socket_index = socket->logical_index;
1696 }
1697
1698
1699
1700 data[socket_index][core_index] |= (1 << pu->sibling_rank);
1701 }
1702
1703 *map = data;
1704 return OPAL_SUCCESS;
1705 }
1706
1707
1708
1709
1710 int opal_hwloc_base_cset2str(char *str, int len,
1711 hwloc_topology_t topo,
1712 hwloc_cpuset_t cpuset)
1713 {
1714 bool first;
1715 int num_sockets, num_cores;
1716 int ret, socket_index, core_index;
1717 char tmp[BUFSIZ];
1718 const int stmp = sizeof(tmp) - 1;
1719 int **map=NULL;
1720 hwloc_obj_t root;
1721 opal_hwloc_topo_data_t *sum;
1722
1723 str[0] = tmp[stmp] = '\0';
1724
1725
1726 if (hwloc_bitmap_iszero(cpuset)) {
1727 return OPAL_ERR_NOT_BOUND;
1728 }
1729
1730
1731 root = hwloc_get_root_obj(topo);
1732 if (NULL != root->userdata) {
1733 sum = (opal_hwloc_topo_data_t*)root->userdata;
1734 if (NULL == sum->available) {
1735 return OPAL_ERROR;
1736 }
1737 if (0 != hwloc_bitmap_isincluded(sum->available, cpuset)) {
1738 return OPAL_ERR_NOT_BOUND;
1739 }
1740 }
1741
1742 if (OPAL_SUCCESS != (ret = build_map(&num_sockets, &num_cores, cpuset, &map, topo))) {
1743 return ret;
1744 }
1745
1746 first = true;
1747 for (socket_index = 0; socket_index < num_sockets; ++socket_index) {
1748 for (core_index = 0; core_index < num_cores; ++core_index) {
1749 if (map[socket_index][core_index] > 0) {
1750 if (!first) {
1751 strncat(str, ", ", len - strlen(str) - 1);
1752 }
1753 first = false;
1754
1755 snprintf(tmp, stmp, "socket %d[core %d[hwt %s]]",
1756 socket_index, core_index,
1757 bitmap2rangestr(map[socket_index][core_index]));
1758 strncat(str, tmp, len - strlen(str) - 1);
1759 }
1760 }
1761 }
1762 if (NULL != map) {
1763 if (NULL != map[0]) {
1764 free(map[0]);
1765 }
1766 free(map);
1767 }
1768
1769 return OPAL_SUCCESS;
1770 }
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780 int opal_hwloc_base_cset2mapstr(char *str, int len,
1781 hwloc_topology_t topo,
1782 hwloc_cpuset_t cpuset)
1783 {
1784 char tmp[BUFSIZ];
1785 int core_index, pu_index;
1786 const int stmp = sizeof(tmp) - 1;
1787 hwloc_obj_t socket, core, pu;
1788 hwloc_obj_t root;
1789 opal_hwloc_topo_data_t *sum;
1790
1791 str[0] = tmp[stmp] = '\0';
1792
1793
1794 if (hwloc_bitmap_iszero(cpuset)) {
1795 return OPAL_ERR_NOT_BOUND;
1796 }
1797
1798
1799 root = hwloc_get_root_obj(topo);
1800 if (NULL != root->userdata) {
1801 sum = (opal_hwloc_topo_data_t*)root->userdata;
1802 if (NULL == sum->available) {
1803 return OPAL_ERROR;
1804 }
1805 if (0 != hwloc_bitmap_isincluded(sum->available, cpuset)) {
1806 return OPAL_ERR_NOT_BOUND;
1807 }
1808 }
1809
1810
1811 for (socket = hwloc_get_obj_by_type(topo, HWLOC_OBJ_SOCKET, 0);
1812 NULL != socket;
1813 socket = socket->next_cousin) {
1814 strncat(str, "[", len - strlen(str) - 1);
1815
1816
1817 core_index = 0;
1818 for (core = hwloc_get_obj_inside_cpuset_by_type(topo,
1819 socket->cpuset,
1820 HWLOC_OBJ_CORE, core_index);
1821 NULL != core;
1822 core = hwloc_get_obj_inside_cpuset_by_type(topo,
1823 socket->cpuset,
1824 HWLOC_OBJ_CORE, ++core_index)) {
1825 if (core_index > 0) {
1826 strncat(str, "/", len - strlen(str) - 1);
1827 }
1828
1829
1830 pu_index = 0;
1831 for (pu = hwloc_get_obj_inside_cpuset_by_type(topo,
1832 core->cpuset,
1833 HWLOC_OBJ_PU, pu_index);
1834 NULL != pu;
1835 pu = hwloc_get_obj_inside_cpuset_by_type(topo,
1836 core->cpuset,
1837 HWLOC_OBJ_PU, ++pu_index)) {
1838
1839
1840 if (hwloc_bitmap_isset(cpuset, pu->os_index)) {
1841 strncat(str, "B", len - strlen(str) - 1);
1842 } else {
1843 strncat(str, ".", len - strlen(str) - 1);
1844 }
1845 }
1846 }
1847 strncat(str, "]", len - strlen(str) - 1);
1848 }
1849
1850 return OPAL_SUCCESS;
1851 }
1852
1853 static int dist_cmp_fn (opal_list_item_t **a, opal_list_item_t **b)
1854 {
1855 opal_rmaps_numa_node_t *aitem = *((opal_rmaps_numa_node_t **) a);
1856 opal_rmaps_numa_node_t *bitem = *((opal_rmaps_numa_node_t **) b);
1857
1858 if (aitem->dist_from_closed > bitem->dist_from_closed) {
1859 return 1;
1860 } else if( aitem->dist_from_closed == bitem->dist_from_closed ) {
1861 return 0;
1862 } else {
1863 return -1;
1864 }
1865 }
1866
1867 static void sort_by_dist(hwloc_topology_t topo, char* device_name, opal_list_t *sorted_list)
1868 {
1869 hwloc_obj_t device_obj = NULL;
1870 hwloc_obj_t obj = NULL;
1871 struct hwloc_distances_s* distances;
1872 opal_rmaps_numa_node_t *numa_node;
1873 int close_node_index;
1874 float latency;
1875 unsigned int j;
1876 #if HWLOC_API_VERSION < 0x20000
1877 hwloc_obj_t root = NULL;
1878 int depth;
1879 unsigned i;
1880 #else
1881 unsigned distances_nr = 0;
1882 #endif
1883
1884 for (device_obj = hwloc_get_obj_by_type(topo, HWLOC_OBJ_OS_DEVICE, 0); device_obj; device_obj = hwloc_get_next_osdev(topo, device_obj)) {
1885 if (device_obj->attr->osdev.type == HWLOC_OBJ_OSDEV_OPENFABRICS
1886 || device_obj->attr->osdev.type == HWLOC_OBJ_OSDEV_NETWORK) {
1887 if (!strcmp(device_obj->name, device_name)) {
1888
1889 obj = device_obj->parent;
1890 #if HWLOC_API_VERSION < 0x20000
1891 while ((obj != NULL) && (obj->type != HWLOC_OBJ_NODE)) {
1892 obj = obj->parent;
1893 }
1894 #else
1895 while (obj && !obj->memory_arity) {
1896 obj = obj->parent;
1897 }
1898 if (obj != NULL) {
1899 obj = obj->memory_first_child;
1900 }
1901 #endif
1902 if (obj == NULL) {
1903 opal_output_verbose(5, opal_hwloc_base_framework.framework_output,
1904 "hwloc:base:get_sorted_numa_list: NUMA node closest to %s wasn't found.",
1905 device_name);
1906 return;
1907 } else {
1908 close_node_index = obj->logical_index;
1909 }
1910
1911
1912 #if HWLOC_API_VERSION < 0x20000
1913 distances = (struct hwloc_distances_s*)hwloc_get_whole_distance_matrix_by_type(topo, HWLOC_OBJ_NODE);
1914 if (NULL == distances) {
1915
1916 depth = hwloc_get_type_depth(topo, HWLOC_OBJ_NODE);
1917 if (HWLOC_TYPE_DEPTH_UNKNOWN == depth) {
1918 opal_output_verbose(5, opal_hwloc_base_framework.framework_output,
1919 "hwloc:base:get_sorted_numa_list: There is no information about distances on the node.");
1920 return;
1921 }
1922 root = hwloc_get_root_obj(topo);
1923 for (i = 0; i < root->arity; i++) {
1924 obj = root->children[i];
1925 if (obj->distances_count > 0) {
1926 for(j = 0; j < obj->distances_count; j++) {
1927 if (obj->distances[j]->relative_depth + 1 == (unsigned) depth) {
1928 distances = obj->distances[j];
1929 break;
1930 }
1931 }
1932 }
1933 }
1934 }
1935
1936 if ((NULL == distances) || (0 == distances->nbobjs)) {
1937 opal_output_verbose(5, opal_hwloc_base_framework.framework_output,
1938 "hwloc:base:get_sorted_numa_list: There is no information about distances on the node.");
1939 return;
1940 }
1941
1942 for (j = 0; j < distances->nbobjs; j++) {
1943 latency = distances->latency[close_node_index + distances->nbobjs * j];
1944 numa_node = OBJ_NEW(opal_rmaps_numa_node_t);
1945 numa_node->index = j;
1946 numa_node->dist_from_closed = latency;
1947 opal_list_append(sorted_list, &numa_node->super);
1948 }
1949 #else
1950 distances_nr = 1;
1951 if (0 != hwloc_distances_get_by_type(topo, HWLOC_OBJ_NODE, &distances_nr, &distances,
1952 HWLOC_DISTANCES_KIND_MEANS_LATENCY, 0) || 0 == distances_nr) {
1953 opal_output_verbose(5, opal_hwloc_base_framework.framework_output,
1954 "hwloc:base:get_sorted_numa_list: There is no information about distances on the node.");
1955 return;
1956 }
1957
1958 for (j = 0; j < distances->nbobjs; j++) {
1959 latency = distances->values[close_node_index + distances->nbobjs * j];
1960 numa_node = OBJ_NEW(opal_rmaps_numa_node_t);
1961 numa_node->index = j;
1962 numa_node->dist_from_closed = latency;
1963 opal_list_append(sorted_list, &numa_node->super);
1964 }
1965 hwloc_distances_release(topo, distances);
1966 #endif
1967
1968 opal_list_sort(sorted_list, dist_cmp_fn);
1969 return;
1970 }
1971 }
1972 }
1973 }
1974
1975 static int find_devices(hwloc_topology_t topo, char** device_name)
1976 {
1977 hwloc_obj_t device_obj = NULL;
1978 int count = 0;
1979 for (device_obj = hwloc_get_obj_by_type(topo, HWLOC_OBJ_OS_DEVICE, 0); device_obj; device_obj = hwloc_get_next_osdev(topo, device_obj)) {
1980 if (device_obj->attr->osdev.type == HWLOC_OBJ_OSDEV_OPENFABRICS) {
1981 count++;
1982 free(*device_name);
1983 *device_name = strdup(device_obj->name);
1984 }
1985 }
1986 return count;
1987 }
1988
1989 int opal_hwloc_get_sorted_numa_list(hwloc_topology_t topo, char* device_name, opal_list_t *sorted_list)
1990 {
1991 hwloc_obj_t obj;
1992 opal_hwloc_summary_t *sum;
1993 opal_hwloc_topo_data_t *data;
1994 opal_rmaps_numa_node_t *numa, *copy_numa;
1995 int count;
1996
1997 obj = hwloc_get_root_obj(topo);
1998
1999
2000
2001 data = (opal_hwloc_topo_data_t*)obj->userdata;
2002 if (NULL != data) {
2003 OPAL_LIST_FOREACH(sum, &data->summaries, opal_hwloc_summary_t) {
2004 if (HWLOC_OBJ_NODE == sum->type) {
2005 if (opal_list_get_size(&sum->sorted_by_dist_list) > 0) {
2006 OPAL_LIST_FOREACH(numa, &(sum->sorted_by_dist_list), opal_rmaps_numa_node_t) {
2007 copy_numa = OBJ_NEW(opal_rmaps_numa_node_t);
2008 copy_numa->index = numa->index;
2009 copy_numa->dist_from_closed = numa->dist_from_closed;
2010 opal_list_append(sorted_list, ©_numa->super);
2011 }
2012 return OPAL_SUCCESS;
2013 }else {
2014
2015
2016 bool free_device_name = false;
2017 if (!strcmp(device_name, "auto")) {
2018 count = find_devices(topo, &device_name);
2019 if (count > 1) {
2020 free(device_name);
2021 return count;
2022 }
2023 free_device_name = true;
2024 }
2025 if (!device_name) {
2026 return OPAL_ERR_NOT_FOUND;
2027 } else if (free_device_name && (0 == strlen(device_name))) {
2028 free(device_name);
2029 return OPAL_ERR_NOT_FOUND;
2030 }
2031 sort_by_dist(topo, device_name, sorted_list);
2032 if (free_device_name) {
2033 free(device_name);
2034 }
2035
2036 OPAL_LIST_FOREACH(numa, sorted_list, opal_rmaps_numa_node_t) {
2037 copy_numa = OBJ_NEW(opal_rmaps_numa_node_t);
2038 copy_numa->index = numa->index;
2039 copy_numa->dist_from_closed = numa->dist_from_closed;
2040 opal_list_append(&(sum->sorted_by_dist_list), ©_numa->super);
2041 }
2042 return OPAL_SUCCESS;
2043 }
2044 }
2045 }
2046 }
2047 return OPAL_ERR_NOT_FOUND;
2048 }
2049
2050 char* opal_hwloc_base_get_topo_signature(hwloc_topology_t topo)
2051 {
2052 int nnuma, nsocket, nl3, nl2, nl1, ncore, nhwt;
2053 char *sig=NULL, *arch = NULL, *endian;
2054 hwloc_obj_t obj;
2055 unsigned i;
2056
2057 nnuma = opal_hwloc_base_get_nbobjs_by_type(topo, HWLOC_OBJ_NODE, 0, OPAL_HWLOC_AVAILABLE);
2058 nsocket = opal_hwloc_base_get_nbobjs_by_type(topo, HWLOC_OBJ_SOCKET, 0, OPAL_HWLOC_AVAILABLE);
2059 nl3 = opal_hwloc_base_get_nbobjs_by_type(topo, HWLOC_OBJ_L3CACHE, 3, OPAL_HWLOC_AVAILABLE);
2060 nl2 = opal_hwloc_base_get_nbobjs_by_type(topo, HWLOC_OBJ_L2CACHE, 2, OPAL_HWLOC_AVAILABLE);
2061 nl1 = opal_hwloc_base_get_nbobjs_by_type(topo, HWLOC_OBJ_L1CACHE, 1, OPAL_HWLOC_AVAILABLE);
2062 ncore = opal_hwloc_base_get_nbobjs_by_type(topo, HWLOC_OBJ_CORE, 0, OPAL_HWLOC_AVAILABLE);
2063 nhwt = opal_hwloc_base_get_nbobjs_by_type(topo, HWLOC_OBJ_PU, 0, OPAL_HWLOC_AVAILABLE);
2064
2065
2066 obj = hwloc_get_root_obj(topo);
2067 for (i=0; i < obj->infos_count; i++) {
2068 if (0 == strcmp(obj->infos[i].name, "Architecture")) {
2069 arch = obj->infos[i].value;
2070 break;
2071 }
2072 }
2073 if (NULL == arch) {
2074 arch = "unknown";
2075 }
2076
2077 #ifdef __BYTE_ORDER
2078 #if __BYTE_ORDER == __LITTLE_ENDIAN
2079 endian = "le";
2080 #else
2081 endian = "be";
2082 #endif
2083 #else
2084 endian = "unknown";
2085 #endif
2086
2087 opal_asprintf(&sig, "%dN:%dS:%dL3:%dL2:%dL1:%dC:%dH:%s:%s",
2088 nnuma, nsocket, nl3, nl2, nl1, ncore, nhwt, arch, endian);
2089 return sig;
2090 }
2091
2092 char* opal_hwloc_base_get_locality_string(hwloc_topology_t topo,
2093 char *bitmap)
2094 {
2095 hwloc_obj_t obj;
2096 char *locality=NULL, *tmp, *t2;
2097 unsigned depth, d, width, w;
2098 hwloc_cpuset_t cpuset, result;
2099 hwloc_obj_type_t type;
2100
2101
2102
2103
2104 if (NULL == bitmap) {
2105 return NULL;
2106 }
2107 cpuset = hwloc_bitmap_alloc();
2108 hwloc_bitmap_list_sscanf(cpuset, bitmap);
2109 if (hwloc_bitmap_isfull(cpuset)) {
2110 hwloc_bitmap_free(cpuset);
2111 return NULL;
2112 }
2113
2114
2115
2116 result = hwloc_bitmap_alloc();
2117
2118
2119 depth = hwloc_topology_get_depth(topo);
2120
2121
2122 for (d=1; d < depth; d++) {
2123
2124 type = hwloc_get_depth_type(topo, d);
2125
2126 if (HWLOC_OBJ_NODE != type &&
2127 HWLOC_OBJ_SOCKET != type &&
2128 #if HWLOC_API_VERSION < 0x20000
2129 HWLOC_OBJ_CACHE != type &&
2130 #else
2131 HWLOC_OBJ_L1CACHE != type &&
2132 HWLOC_OBJ_L2CACHE != type &&
2133 HWLOC_OBJ_L3CACHE != type &&
2134 #endif
2135 HWLOC_OBJ_CORE != type &&
2136 HWLOC_OBJ_PU != type) {
2137 continue;
2138 }
2139
2140
2141 width = hwloc_get_nbobjs_by_depth(topo, d);
2142 if (0 == width) {
2143 continue;
2144 }
2145
2146
2147
2148
2149 for (w=0; w < width; w++) {
2150
2151 obj = hwloc_get_obj_by_depth(topo, d, w);
2152
2153 if (hwloc_bitmap_intersects(obj->cpuset, cpuset)) {
2154 hwloc_bitmap_set(result, w);
2155 }
2156 }
2157
2158
2159 if (!hwloc_bitmap_iszero(result)) {
2160 hwloc_bitmap_list_asprintf(&tmp, result);
2161 switch(obj->type) {
2162 case HWLOC_OBJ_NODE:
2163 opal_asprintf(&t2, "%sNM%s:", (NULL == locality) ? "" : locality, tmp);
2164 if (NULL != locality) {
2165 free(locality);
2166 }
2167 locality = t2;
2168 break;
2169 case HWLOC_OBJ_SOCKET:
2170 opal_asprintf(&t2, "%sSK%s:", (NULL == locality) ? "" : locality, tmp);
2171 if (NULL != locality) {
2172 free(locality);
2173 }
2174 locality = t2;
2175 break;
2176 #if HWLOC_API_VERSION < 0x20000
2177 case HWLOC_OBJ_CACHE:
2178 if (3 == obj->attr->cache.depth) {
2179 opal_asprintf(&t2, "%sL3%s:", (NULL == locality) ? "" : locality, tmp);
2180 if (NULL != locality) {
2181 free(locality);
2182 }
2183 locality = t2;
2184 break;
2185 } else if (2 == obj->attr->cache.depth) {
2186 opal_asprintf(&t2, "%sL2%s:", (NULL == locality) ? "" : locality, tmp);
2187 if (NULL != locality) {
2188 free(locality);
2189 }
2190 locality = t2;
2191 break;
2192 } else {
2193 opal_asprintf(&t2, "%sL1%s:", (NULL == locality) ? "" : locality, tmp);
2194 if (NULL != locality) {
2195 free(locality);
2196 }
2197 locality = t2;
2198 break;
2199 }
2200 break;
2201 #else
2202 case HWLOC_OBJ_L3CACHE:
2203 opal_asprintf(&t2, "%sL3%s:", (NULL == locality) ? "" : locality, tmp);
2204 if (NULL != locality) {
2205 free(locality);
2206 }
2207 locality = t2;
2208 break;
2209 case HWLOC_OBJ_L2CACHE:
2210 opal_asprintf(&t2, "%sL2%s:", (NULL == locality) ? "" : locality, tmp);
2211 if (NULL != locality) {
2212 free(locality);
2213 }
2214 locality = t2;
2215 break;
2216 case HWLOC_OBJ_L1CACHE:
2217 opal_asprintf(&t2, "%sL1%s:", (NULL == locality) ? "" : locality, tmp);
2218 if (NULL != locality) {
2219 free(locality);
2220 }
2221 locality = t2;
2222 break;
2223 #endif
2224 case HWLOC_OBJ_CORE:
2225 opal_asprintf(&t2, "%sCR%s:", (NULL == locality) ? "" : locality, tmp);
2226 if (NULL != locality) {
2227 free(locality);
2228 }
2229 locality = t2;
2230 break;
2231 case HWLOC_OBJ_PU:
2232 opal_asprintf(&t2, "%sHT%s:", (NULL == locality) ? "" : locality, tmp);
2233 if (NULL != locality) {
2234 free(locality);
2235 }
2236 locality = t2;
2237 break;
2238 default:
2239
2240 break;
2241 }
2242 free(tmp);
2243 }
2244 hwloc_bitmap_zero(result);
2245 }
2246 hwloc_bitmap_free(result);
2247 hwloc_bitmap_free(cpuset);
2248
2249
2250 if (NULL != locality) {
2251 locality[strlen(locality)-1] = '\0';
2252 }
2253 return locality;
2254 }
2255
2256 char* opal_hwloc_base_get_location(char *locality,
2257 hwloc_obj_type_t type,
2258 unsigned index)
2259 {
2260 char **loc;
2261 char *srch, *ans = NULL;
2262 size_t n;
2263
2264 if (NULL == locality) {
2265 return NULL;
2266 }
2267 switch(type) {
2268 case HWLOC_OBJ_NODE:
2269 srch = "NM";
2270 break;
2271 case HWLOC_OBJ_SOCKET:
2272 srch = "SK";
2273 break;
2274 #if HWLOC_API_VERSION < 0x20000
2275 case HWLOC_OBJ_CACHE:
2276 if (3 == index) {
2277 srch = "L3";
2278 } else if (2 == index) {
2279 srch = "L2";
2280 } else {
2281 srch = "L0";
2282 }
2283 break;
2284 #else
2285 case HWLOC_OBJ_L3CACHE:
2286 srch = "L3";
2287 break;
2288 case HWLOC_OBJ_L2CACHE:
2289 srch = "L2";
2290 break;
2291 case HWLOC_OBJ_L1CACHE:
2292 srch = "L0";
2293 break;
2294 #endif
2295 case HWLOC_OBJ_CORE:
2296 srch = "CR";
2297 break;
2298 case HWLOC_OBJ_PU:
2299 srch = "HT";
2300 break;
2301 default:
2302 return NULL;
2303 }
2304 loc = opal_argv_split(locality, ':');
2305 for (n=0; NULL != loc[n]; n++) {
2306 if (0 == strncmp(loc[n], srch, 2)) {
2307 ans = strdup(&loc[n][2]);
2308 break;
2309 }
2310 }
2311 opal_argv_free(loc);
2312
2313 return ans;
2314 }
2315
2316 opal_hwloc_locality_t opal_hwloc_compute_relative_locality(char *loc1, char *loc2)
2317 {
2318 opal_hwloc_locality_t locality;
2319 char **set1, **set2;
2320 hwloc_bitmap_t bit1, bit2;
2321 size_t n1, n2;
2322
2323
2324
2325
2326
2327 locality = OPAL_PROC_ON_NODE | OPAL_PROC_ON_HOST | OPAL_PROC_ON_CU | OPAL_PROC_ON_CLUSTER;
2328
2329
2330 if (NULL == loc1 || NULL == loc2) {
2331 return locality;
2332 }
2333
2334 set1 = opal_argv_split(loc1, ':');
2335 set2 = opal_argv_split(loc2, ':');
2336 bit1 = hwloc_bitmap_alloc();
2337 bit2 = hwloc_bitmap_alloc();
2338
2339
2340 for (n1=0; NULL != set1[n1]; n1++) {
2341
2342 hwloc_bitmap_list_sscanf(bit1, &set1[n1][2]);
2343
2344 for (n2=0; NULL != set2[n2]; n2++) {
2345 if (0 == strncmp(set1[n1], set2[n2], 2)) {
2346
2347 hwloc_bitmap_list_sscanf(bit2, &set2[n2][2]);
2348
2349 if (hwloc_bitmap_intersects(bit1, bit2)) {
2350
2351 if (0 == strncmp(set1[n1], "NM", 2)) {
2352 locality |= OPAL_PROC_ON_NUMA;
2353 } else if (0 == strncmp(set1[n1], "SK", 2)) {
2354 locality |= OPAL_PROC_ON_SOCKET;
2355 } else if (0 == strncmp(set1[n1], "L3", 2)) {
2356 locality |= OPAL_PROC_ON_L3CACHE;
2357 } else if (0 == strncmp(set1[n1], "L2", 2)) {
2358 locality |= OPAL_PROC_ON_L2CACHE;
2359 } else if (0 == strncmp(set1[n1], "L1", 2)) {
2360 locality |= OPAL_PROC_ON_L1CACHE;
2361 } else if (0 == strncmp(set1[n1], "CR", 2)) {
2362 locality |= OPAL_PROC_ON_CORE;
2363 } else if (0 == strncmp(set1[n1], "HT", 2)) {
2364 locality |= OPAL_PROC_ON_HWTHREAD;
2365 } else {
2366
2367 opal_output(0, "UNRECOGNIZED LOCALITY %s", set1[n1]);
2368 }
2369 }
2370 break;
2371 }
2372 }
2373 }
2374 opal_argv_free(set1);
2375 opal_argv_free(set2);
2376 hwloc_bitmap_free(bit1);
2377 hwloc_bitmap_free(bit2);
2378 return locality;
2379 }
2380
2381 int opal_hwloc_base_topology_export_xmlbuffer(hwloc_topology_t topology, char **xmlpath, int *buflen) {
2382 #if HWLOC_API_VERSION < 0x20000
2383 return hwloc_topology_export_xmlbuffer(topology, xmlpath, buflen);
2384 #else
2385 return hwloc_topology_export_xmlbuffer(topology, xmlpath, buflen, 0);
2386 #endif
2387 }
2388
2389 int opal_hwloc_base_topology_set_flags (hwloc_topology_t topology, unsigned long flags, bool io) {
2390 if (io) {
2391 #if HWLOC_API_VERSION < 0x20000
2392 flags |= HWLOC_TOPOLOGY_FLAG_IO_DEVICES;
2393 #else
2394 int ret = hwloc_topology_set_io_types_filter(topology, HWLOC_TYPE_FILTER_KEEP_IMPORTANT);
2395 if (0 != ret) return ret;
2396 #endif
2397 }
2398 return hwloc_topology_set_flags(topology, flags);
2399 }