From 7a83fdb9bb3aa13aad10a0f5a5695942a37c8bb1 Mon Sep 17 00:00:00 2001 From: Ralph Castain Date: Wed, 21 Jun 2017 21:10:35 -0700 Subject: [PATCH 1/2] Update to hwloc 2.0.0a with shmem support. Update to support passing of HWLOC shmem topology to client procs Update use of distance API per @bgoglin Have the openib component lookup its object in the distance matrix Bring usnic up-to-date Restore binding for hwloc2 Signed-off-by: Ralph Castain --- .gitignore | 3 +- ompi/mca/osc/rdma/osc_rdma_active_target.c | 7 +- opal/mca/btl/openib/btl_openib_component.c | 152 +- opal/mca/btl/openib/btl_openib_proc.c | 4 +- opal/mca/btl/usnic/btl_usnic_hwloc.c | 57 +- opal/mca/hwloc/base/hwloc_base_util.c | 130 +- opal/mca/hwloc/hwloc1116/README-ompi.txt | 6 - opal/mca/hwloc/hwloc1116/hwloc/AUTHORS | 10 - opal/mca/hwloc/hwloc1116/hwloc/README | 75 - .../hwloc/include/hwloc/deprecated.h | 102 - .../hwloc/include/private/components.h | 40 - opal/mca/hwloc/hwloc1116/hwloc/src/base64.c | 306 -- opal/mca/hwloc/hwloc1116/hwloc/src/bitmap.c | 1514 ------- opal/mca/hwloc/hwloc1116/hwloc/src/diff.c | 408 -- .../mca/hwloc/hwloc1116/hwloc/src/distances.c | 1080 ----- .../hwloc/hwloc1116/hwloc/src/pci-common.c | 545 --- .../hwloc1116/hwloc/src/topology-custom.c | 100 - .../hwloc1116/hwloc/src/topology-hardwired.c | 197 - .../hwloc/hwloc1116/hwloc/src/topology-nvml.c | 239 - .../hwloc1116/hwloc/src/topology-opencl.c | 346 -- .../hwloc/hwloc1116/hwloc/src/topology-osf.c | 392 -- .../hwloc/hwloc1116/hwloc/src/topology-x86.c | 1233 ------ .../hwloc/hwloc1116/hwloc/src/topology-xml.c | 1827 -------- opal/mca/hwloc/hwloc1116/hwloc/src/topology.c | 3337 -------------- .../mca/hwloc/hwloc1116/hwloc/src/traversal.c | 715 --- .../hwloc/{hwloc1116 => hwloc2a}/Makefile.am | 28 +- opal/mca/hwloc/hwloc2a/README-ompi.txt | 1 + .../hwloc/{hwloc1116 => hwloc2a}/configure.m4 | 130 +- opal/mca/hwloc/hwloc2a/hwloc/AUTHORS | 29 + .../{hwloc1116 => hwloc2a}/hwloc/COPYING | 1 + .../{hwloc1116 => hwloc2a}/hwloc/Makefile.am | 62 +- .../hwloc/{hwloc1116 => hwloc2a}/hwloc/NEWS | 133 + opal/mca/hwloc/hwloc2a/hwloc/README | 65 + .../{hwloc1116 => hwloc2a}/hwloc/VERSION | 11 +- .../hwloc/config/distscript.sh | 1 + .../hwloc/config/hwloc.m4 | 135 +- .../hwloc/config/hwloc_check_attributes.m4 | 1 - .../hwloc/config/hwloc_check_vendor.m4 | 3 + .../hwloc/config/hwloc_check_visibility.m4 | 0 .../hwloc/config/hwloc_components.m4 | 0 .../hwloc/config/hwloc_get_version.sh | 45 +- .../hwloc/config/hwloc_internal.m4 | 116 +- .../hwloc/config/hwloc_pkg.m4 | 0 opal/mca/hwloc/hwloc2a/hwloc/config/netloc.m4 | 116 + .../hwloc/config/test-driver | 0 .../{hwloc1116 => hwloc2a}/hwloc/configure.ac | 122 +- .../hwloc/contrib/hwloc-valgrind.supp | 19 +- .../hwloc/contrib/misc}/README.txt | 0 .../hwloc/contrib/systemd}/README.txt | 0 .../hwloc/contrib/windows}/README.txt | 0 .../utils => hwloc2a/hwloc/doc}/README.txt | 0 .../{hwloc1116 => hwloc2a}/hwloc/hwloc.pc.in | 0 .../src => hwloc2a/hwloc/hwloc}/Makefile.am | 13 +- opal/mca/hwloc/hwloc2a/hwloc/hwloc/base64.c | 306 ++ .../hwloc/src => hwloc2a/hwloc/hwloc}/bind.c | 148 +- opal/mca/hwloc/hwloc2a/hwloc/hwloc/bitmap.c | 1527 +++++++ .../src => hwloc2a/hwloc/hwloc}/components.c | 276 +- opal/mca/hwloc/hwloc2a/hwloc/hwloc/diff.c | 468 ++ .../mca/hwloc/hwloc2a/hwloc/hwloc/distances.c | 931 ++++ .../hwloc/src => hwloc2a/hwloc/hwloc}/dolib.c | 0 .../src => hwloc2a/hwloc/hwloc}/hwloc.dtd | 42 +- .../hwloc/src => hwloc2a/hwloc/hwloc}/misc.c | 6 +- .../hwloc/hwloc2a/hwloc/hwloc/pci-common.c | 954 ++++ opal/mca/hwloc/hwloc2a/hwloc/hwloc/shmem.c | 275 ++ .../hwloc/hwloc}/topology-aix.c | 211 +- .../hwloc/hwloc}/topology-bgq.c | 117 +- .../hwloc/hwloc}/topology-cuda.c | 154 +- .../hwloc/hwloc}/topology-darwin.c | 64 +- .../hwloc/hwloc}/topology-fake.c | 6 +- .../hwloc/hwloc}/topology-freebsd.c | 17 +- .../src => hwloc2a/hwloc/hwloc}/topology-gl.c | 160 +- .../hwloc2a/hwloc/hwloc/topology-hardwired.c | 223 + .../hwloc/hwloc}/topology-hpux.c | 39 +- .../hwloc/hwloc}/topology-linux.c | 3936 +++++++++-------- .../hwloc/hwloc}/topology-netbsd.c | 13 +- .../hwloc/hwloc}/topology-noos.c | 15 +- .../hwloc/hwloc2a/hwloc/hwloc/topology-nvml.c | 146 + .../hwloc2a/hwloc/hwloc/topology-opencl.c | 203 + .../hwloc/hwloc}/topology-pci.c | 167 +- .../hwloc/hwloc}/topology-solaris-chiptype.c | 21 +- .../hwloc/hwloc}/topology-solaris.c | 421 +- .../hwloc/hwloc}/topology-synthetic.c | 673 +-- .../hwloc/hwloc}/topology-windows.c | 483 +- .../hwloc/hwloc2a/hwloc/hwloc/topology-x86.c | 1437 ++++++ .../hwloc/hwloc}/topology-xml-libxml.c | 106 +- .../hwloc/hwloc}/topology-xml-nolibxml.c | 80 +- .../hwloc/hwloc2a/hwloc/hwloc/topology-xml.c | 2398 ++++++++++ opal/mca/hwloc/hwloc2a/hwloc/hwloc/topology.c | 3808 ++++++++++++++++ .../mca/hwloc/hwloc2a/hwloc/hwloc/traversal.c | 553 +++ .../hwloc/include/Makefile.am | 17 +- .../hwloc/include/hwloc.h | 2061 ++++----- .../hwloc/include/hwloc/autogen/config.h.in | 10 +- .../hwloc/include/hwloc/bitmap.h | 2 +- .../hwloc/include/hwloc/cuda.h | 74 +- .../hwloc/include/hwloc/cudart.h | 37 +- .../hwloc2a/hwloc/include/hwloc/deprecated.h | 216 + .../hwloc/include/hwloc/diff.h | 25 +- .../hwloc2a/hwloc/include/hwloc/distances.h | 223 + .../hwloc2a/hwloc/include/hwloc/export.h | 236 + .../hwloc/include/hwloc/gl.h | 35 +- .../hwloc/include/hwloc/glibc-sched.h | 2 +- .../hwloc/include/hwloc/helper.h | 530 +-- .../hwloc/include/hwloc/inlines.h | 18 +- .../hwloc/include/hwloc/intel-mic.h | 77 +- .../hwloc/include/hwloc/linux-libnuma.h | 186 +- .../hwloc/include/hwloc/linux.h | 16 +- .../hwloc/include/hwloc/myriexpress.h | 8 +- .../hwloc/include/hwloc/nvml.h | 83 +- .../hwloc/include/hwloc/opencl.h | 137 +- .../hwloc/include/hwloc/openfabrics-verbs.h | 41 +- .../hwloc/include/hwloc/plugins.h | 231 +- .../hwloc/include/hwloc/rename.h | 248 +- .../hwloc/hwloc2a/hwloc/include/hwloc/shmem.h | 115 + opal/mca/hwloc/hwloc2a/hwloc/include/netloc.h | 57 + .../hwloc2a/hwloc/include/netloc/utarray.h | 237 + .../hwloc2a/hwloc/include/netloc/uthash.h | 966 ++++ .../hwloc2a/hwloc/include/netlocscotch.h | 123 + .../hwloc/include/private/autogen/config.h.in | 36 +- .../hwloc/include/private/components.h | 42 + .../hwloc/include/private/cpuid-x86.h | 2 +- .../hwloc/include/private/debug.h | 6 +- .../hwloc/include/private/misc.h | 256 +- .../hwloc2a/hwloc/include/private/netloc.h | 579 +++ .../hwloc/include/private/private.h | 210 +- .../hwloc/include/private/solaris-chiptype.h | 1 + .../hwloc/include/private/xml.h | 21 +- opal/mca/hwloc/hwloc2a/hwloc/netloc.pc | 11 + opal/mca/hwloc/hwloc2a/hwloc/netloc.pc.in | 11 + .../mca/hwloc/hwloc2a/hwloc/netloc/README.txt | 4 + .../hwloc/hwloc2a/hwloc/netlocscotch.pc.in | 11 + opal/mca/hwloc/hwloc2a/hwloc/tests/README.txt | 4 + opal/mca/hwloc/hwloc2a/hwloc/utils/README.txt | 4 + .../hwloc1116.h => hwloc2a/hwloc2a.h} | 9 +- .../hwloc2a_component.c} | 12 +- .../hwloc/{hwloc1116 => hwloc2a}/owner.txt | 0 .../pmix/pmix2x/pmix/include/pmix_common.h | 2 + opal/mca/pmix/pmix_types.h | 6 +- orte/mca/ess/base/ess_base_fns.c | 3 + orte/mca/ess/pmi/ess_pmi_module.c | 3 + orte/mca/odls/base/odls_base_default_fns.c | 4 + orte/mca/plm/base/plm_base_launch_support.c | 3 - orte/mca/rmaps/base/rmaps_base_binding.c | 3 + orte/mca/rtc/hwloc/Makefile.am | 4 +- orte/mca/rtc/hwloc/help-orte-rtc-hwloc.txt | 30 + orte/mca/rtc/hwloc/rtc_hwloc.c | 442 ++ orte/mca/rtc/hwloc/rtc_hwloc.h | 27 +- orte/mca/rtc/hwloc/rtc_hwloc_component.c | 56 +- orte/test/mpi/binding.c | 16 +- 148 files changed, 23244 insertions(+), 18825 deletions(-) delete mode 100644 opal/mca/hwloc/hwloc1116/README-ompi.txt delete mode 100644 opal/mca/hwloc/hwloc1116/hwloc/AUTHORS delete mode 100644 opal/mca/hwloc/hwloc1116/hwloc/README delete mode 100644 opal/mca/hwloc/hwloc1116/hwloc/include/hwloc/deprecated.h delete mode 100644 opal/mca/hwloc/hwloc1116/hwloc/include/private/components.h delete mode 100644 opal/mca/hwloc/hwloc1116/hwloc/src/base64.c delete mode 100644 opal/mca/hwloc/hwloc1116/hwloc/src/bitmap.c delete mode 100644 opal/mca/hwloc/hwloc1116/hwloc/src/diff.c delete mode 100644 opal/mca/hwloc/hwloc1116/hwloc/src/distances.c delete mode 100644 opal/mca/hwloc/hwloc1116/hwloc/src/pci-common.c delete mode 100644 opal/mca/hwloc/hwloc1116/hwloc/src/topology-custom.c delete mode 100644 opal/mca/hwloc/hwloc1116/hwloc/src/topology-hardwired.c delete mode 100644 opal/mca/hwloc/hwloc1116/hwloc/src/topology-nvml.c delete mode 100644 opal/mca/hwloc/hwloc1116/hwloc/src/topology-opencl.c delete mode 100644 opal/mca/hwloc/hwloc1116/hwloc/src/topology-osf.c delete mode 100644 opal/mca/hwloc/hwloc1116/hwloc/src/topology-x86.c delete mode 100644 opal/mca/hwloc/hwloc1116/hwloc/src/topology-xml.c delete mode 100644 opal/mca/hwloc/hwloc1116/hwloc/src/topology.c delete mode 100644 opal/mca/hwloc/hwloc1116/hwloc/src/traversal.c rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/Makefile.am (77%) create mode 100644 opal/mca/hwloc/hwloc2a/README-ompi.txt rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/configure.m4 (51%) create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/AUTHORS rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/COPYING (96%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/Makefile.am (82%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/NEWS (89%) create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/README rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/VERSION (94%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/config/distscript.sh (98%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/config/hwloc.m4 (92%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/config/hwloc_check_attributes.m4 (99%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/config/hwloc_check_vendor.m4 (98%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/config/hwloc_check_visibility.m4 (100%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/config/hwloc_components.m4 (100%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/config/hwloc_get_version.sh (74%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/config/hwloc_internal.m4 (76%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/config/hwloc_pkg.m4 (100%) create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/config/netloc.m4 rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/config/test-driver (100%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/configure.ac (74%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/contrib/hwloc-valgrind.supp (87%) rename opal/mca/hwloc/{hwloc1116/hwloc/contrib/systemd => hwloc2a/hwloc/contrib/misc}/README.txt (100%) rename opal/mca/hwloc/{hwloc1116/hwloc/doc => hwloc2a/hwloc/contrib/systemd}/README.txt (100%) rename opal/mca/hwloc/{hwloc1116/hwloc/tests => hwloc2a/hwloc/contrib/windows}/README.txt (100%) rename opal/mca/hwloc/{hwloc1116/hwloc/utils => hwloc2a/hwloc/doc}/README.txt (100%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/hwloc.pc.in (100%) rename opal/mca/hwloc/{hwloc1116/hwloc/src => hwloc2a/hwloc/hwloc}/Makefile.am (96%) create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/hwloc/base64.c rename opal/mca/hwloc/{hwloc1116/hwloc/src => hwloc2a/hwloc/hwloc}/bind.c (87%) create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/hwloc/bitmap.c rename opal/mca/hwloc/{hwloc1116/hwloc/src => hwloc2a/hwloc/hwloc}/components.c (75%) create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/hwloc/diff.c create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/hwloc/distances.c rename opal/mca/hwloc/{hwloc1116/hwloc/src => hwloc2a/hwloc/hwloc}/dolib.c (100%) rename opal/mca/hwloc/{hwloc1116/hwloc/src => hwloc2a/hwloc/hwloc}/hwloc.dtd (71%) rename opal/mca/hwloc/{hwloc1116/hwloc/src => hwloc2a/hwloc/hwloc}/misc.c (96%) create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/hwloc/pci-common.c create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/hwloc/shmem.c rename opal/mca/hwloc/{hwloc1116/hwloc/src => hwloc2a/hwloc/hwloc}/topology-aix.c (81%) rename opal/mca/hwloc/{hwloc1116/hwloc/src => hwloc2a/hwloc/hwloc}/topology-bgq.c (70%) rename opal/mca/hwloc/{hwloc1116/hwloc/src => hwloc2a/hwloc/hwloc}/topology-cuda.c (52%) rename opal/mca/hwloc/{hwloc1116/hwloc/src => hwloc2a/hwloc/hwloc}/topology-darwin.c (82%) rename opal/mca/hwloc/{hwloc1116/hwloc/src => hwloc2a/hwloc/hwloc}/topology-fake.c (86%) rename opal/mca/hwloc/{hwloc1116/hwloc/src => hwloc2a/hwloc/hwloc}/topology-freebsd.c (92%) rename opal/mca/hwloc/{hwloc1116/hwloc/src => hwloc2a/hwloc/hwloc}/topology-gl.c (51%) create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/hwloc/topology-hardwired.c rename opal/mca/hwloc/{hwloc1116/hwloc/src => hwloc2a/hwloc/hwloc}/topology-hpux.c (85%) rename opal/mca/hwloc/{hwloc1116/hwloc/src => hwloc2a/hwloc/hwloc}/topology-linux.c (63%) rename opal/mca/hwloc/{hwloc1116/hwloc/src => hwloc2a/hwloc/hwloc}/topology-netbsd.c (94%) rename opal/mca/hwloc/{hwloc1116/hwloc/src => hwloc2a/hwloc/hwloc}/topology-noos.c (78%) create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/hwloc/topology-nvml.c create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/hwloc/topology-opencl.c rename opal/mca/hwloc/{hwloc1116/hwloc/src => hwloc2a/hwloc/hwloc}/topology-pci.c (68%) rename opal/mca/hwloc/{hwloc1116/hwloc/src => hwloc2a/hwloc/hwloc}/topology-solaris-chiptype.c (95%) rename opal/mca/hwloc/{hwloc1116/hwloc/src => hwloc2a/hwloc/hwloc}/topology-solaris.c (69%) rename opal/mca/hwloc/{hwloc1116/hwloc/src => hwloc2a/hwloc/hwloc}/topology-synthetic.c (57%) rename opal/mca/hwloc/{hwloc1116/hwloc/src => hwloc2a/hwloc/hwloc}/topology-windows.c (68%) create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/hwloc/topology-x86.c rename opal/mca/hwloc/{hwloc1116/hwloc/src => hwloc2a/hwloc/hwloc}/topology-xml-libxml.c (85%) rename opal/mca/hwloc/{hwloc1116/hwloc/src => hwloc2a/hwloc/hwloc}/topology-xml-nolibxml.c (92%) create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/hwloc/topology-xml.c create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/hwloc/topology.c create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/hwloc/traversal.c rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/Makefile.am (79%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/hwloc.h (60%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/hwloc/autogen/config.h.in (97%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/hwloc/bitmap.h (99%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/hwloc/cuda.h (76%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/hwloc/cudart.h (85%) create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/include/hwloc/deprecated.h rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/hwloc/diff.h (89%) create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/include/hwloc/distances.h create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/include/hwloc/export.h rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/hwloc/gl.h (83%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/hwloc/glibc-sched.h (97%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/hwloc/helper.h (69%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/hwloc/inlines.h (86%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/hwloc/intel-mic.h (60%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/hwloc/linux-libnuma.h (60%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/hwloc/linux.h (89%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/hwloc/myriexpress.h (93%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/hwloc/nvml.h (69%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/hwloc/opencl.h (50%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/hwloc/openfabrics-verbs.h (83%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/hwloc/plugins.h (63%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/hwloc/rename.h (80%) create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/include/hwloc/shmem.h create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/include/netloc.h create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/include/netloc/utarray.h create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/include/netloc/uthash.h create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/include/netlocscotch.h rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/private/autogen/config.h.in (97%) create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/include/private/components.h rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/private/cpuid-x86.h (97%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/private/debug.h (89%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/private/misc.h (57%) create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/include/private/netloc.h rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/private/private.h (65%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/private/solaris-chiptype.h (96%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/hwloc/include/private/xml.h (87%) create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/netloc.pc create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/netloc.pc.in create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/netloc/README.txt create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/netlocscotch.pc.in create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/tests/README.txt create mode 100644 opal/mca/hwloc/hwloc2a/hwloc/utils/README.txt rename opal/mca/hwloc/{hwloc1116/hwloc1116.h => hwloc2a/hwloc2a.h} (89%) rename opal/mca/hwloc/{hwloc1116/hwloc1116_component.c => hwloc2a/hwloc2a_component.c} (83%) rename opal/mca/hwloc/{hwloc1116 => hwloc2a}/owner.txt (100%) create mode 100644 orte/mca/rtc/hwloc/help-orte-rtc-hwloc.txt diff --git a/.gitignore b/.gitignore index 9b462dbe3b..067c241372 100644 --- a/.gitignore +++ b/.gitignore @@ -302,9 +302,7 @@ opal/mca/event/libevent*/libevent/libevent_pthreads.pc opal/mca/event/libevent*/libevent/include/event2/event-config.h opal/mca/hwloc/hwloc*/hwloc/include/hwloc/autogen/config.h -opal/mca/hwloc/hwloc*/hwloc/include/hwloc/autogen/config.h.in opal/mca/hwloc/hwloc*/hwloc/include/private/autogen/config.h -opal/mca/hwloc/hwloc*/hwloc/include/private/autogen/config.h.in opal/mca/hwloc/base/static-components.h.new.extern opal/mca/hwloc/base/static-components.h.new.struct @@ -361,6 +359,7 @@ orte/test/mpi/accept orte/test/mpi/attach orte/test/mpi/bad_exit orte/test/mpi/bcast_loop +orte/test/mpi/binding orte/test/mpi/concurrent_spawn orte/test/mpi/connect orte/test/mpi/crisscross diff --git a/ompi/mca/osc/rdma/osc_rdma_active_target.c b/ompi/mca/osc/rdma/osc_rdma_active_target.c index 635cf838bb..30e160e93f 100644 --- a/ompi/mca/osc/rdma/osc_rdma_active_target.c +++ b/ompi/mca/osc/rdma/osc_rdma_active_target.c @@ -16,6 +16,7 @@ * Copyright (c) 2017 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. + * Copyright (c) 2017 Intel, Inc. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -242,10 +243,6 @@ int ompi_osc_rdma_post_atomic (ompi_group_t *group, int assert, ompi_win_t *win) return OMPI_SUCCESS; } - if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) { - return OMPI_ERR_OUT_OF_RESOURCE; - } - /* translate group ranks into the communicator */ peers = ompi_osc_rdma_get_peers (module, module->pw_group); if (OPAL_UNLIKELY(NULL == peers)) { @@ -281,7 +278,7 @@ int ompi_osc_rdma_post_atomic (ompi_group_t *group, int assert, ompi_win_t *win) do { ompi_osc_rdma_lock_t result; - OSC_RDMA_VERBOSE(MCA_BASE_VERBOSE_TRACE, "attempting to post to index %d @ rank %d", post_index, peer->rank); + OSC_RDMA_VERBOSE(MCA_BASE_VERBOSE_TRACE, "attempting to post to index %d @ rank %d", (int)post_index, peer->rank); /* try to post. if the value isn't 0 then another rank is occupying this index */ if (!ompi_osc_rdma_peer_local_state (peer)) { diff --git a/opal/mca/btl/openib/btl_openib_component.c b/opal/mca/btl/openib/btl_openib_component.c index 42e21e666f..5e99e1829e 100644 --- a/opal/mca/btl/openib/btl_openib_component.c +++ b/opal/mca/btl/openib/btl_openib_component.c @@ -18,7 +18,7 @@ * Copyright (c) 2009-2012 Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011-2015 NVIDIA Corporation. All rights reserved. * Copyright (c) 2012 Oak Ridge National Laboratory. All rights reserved - * Copyright (c) 2013-2016 Intel, Inc. All rights reserved. + * Copyright (c) 2013-2017 Intel, Inc. All rights reserved. * Copyright (c) 2014-2017 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2014 Bull SAS. All rights reserved. @@ -2330,32 +2330,41 @@ static float get_ib_dev_distance(struct ibv_device *dev) /* If we don't have hwloc, we'll default to a distance of 0, because we have no way of measuring. */ float distance = 0; + float a, b; + int i; + hwloc_cpuset_t my_cpuset = NULL, ibv_cpuset = NULL; + hwloc_obj_t my_obj, ibv_obj, node_obj; + struct hwloc_distances_s *hwloc_distances = NULL; -#if HWLOC_API_VERSION < 0x20000 /* Override any distance logic so all devices are used */ if (0 != mca_btl_openib_component.ignore_locality || OPAL_SUCCESS != opal_hwloc_base_get_topology()) { return distance; } - float a, b; - int i; - hwloc_cpuset_t my_cpuset = NULL, ibv_cpuset = NULL; - hwloc_obj_t my_obj, ibv_obj, node_obj; - - /* Note that this struct is owned by hwloc; there's no need to - free it at the end of time */ - static const struct hwloc_distances_s *hwloc_distances = NULL; +#if HWLOC_API_VERSION >= 0x20000 + unsigned int j, distances_nr = 1; + int ibvindex, myindex; +#endif if (NULL == hwloc_distances) { - hwloc_distances = - hwloc_get_whole_distance_matrix_by_type(opal_hwloc_topology, - HWLOC_OBJ_NODE); - } + #if HWLOC_API_VERSION < 0x20000 + hwloc_distances = + hwloc_get_whole_distance_matrix_by_type(opal_hwloc_topology, + HWLOC_OBJ_NODE); + /* If we got no info, just return 0 */ + if (NULL == hwloc_distances || NULL == hwloc_distances->latency) { + goto out; + } - /* If we got no info, just return 0 */ - if (NULL == hwloc_distances || NULL == hwloc_distances->latency) { - goto out; + #else + if (0 != hwloc_distances_get_by_type(opal_hwloc_topology, HWLOC_OBJ_NODE, + &distances_nr, &hwloc_distances, + HWLOC_DISTANCES_KIND_MEANS_LATENCY, 0) || 0 == distances_nr) { + hwloc_distances = NULL; + goto out; + } + #endif } /* Next, find the NUMA node where this IBV device is located */ @@ -2373,16 +2382,31 @@ static float get_ib_dev_distance(struct ibv_device *dev) opal_output_verbose(5, opal_btl_base_framework.framework_output, "hwloc_distances->nbobjs=%d", hwloc_distances->nbobjs); +#if HWLOC_API_VERSION < 0x20000 for (i = 0; i < (int)(2 * hwloc_distances->nbobjs); i++) { opal_output_verbose(5, opal_btl_base_framework.framework_output, "hwloc_distances->latency[%d]=%f", i, hwloc_distances->latency[i]); } +#else + for (i = 0; i < (int)hwloc_distances->nbobjs; i++) { + opal_output_verbose(5, opal_btl_base_framework.framework_output, + "hwloc_distances->values[%d]=%"PRIu64, i, hwloc_distances->values[i]); + } +#endif /* If ibv_obj is a NUMA node or below, we're good. */ switch (ibv_obj->type) { case HWLOC_OBJ_NODE: case HWLOC_OBJ_SOCKET: +#if HWLOC_API_VERSION < 0x20000 case HWLOC_OBJ_CACHE: +#else + case HWLOC_OBJ_L1CACHE: + case HWLOC_OBJ_L2CACHE: + case HWLOC_OBJ_L3CACHE: + case HWLOC_OBJ_L4CACHE: + case HWLOC_OBJ_L5CACHE: +#endif case HWLOC_OBJ_CORE: case HWLOC_OBJ_PU: while (NULL != ibv_obj && ibv_obj->type != HWLOC_OBJ_NODE) { @@ -2402,6 +2426,22 @@ static float get_ib_dev_distance(struct ibv_device *dev) if (NULL == ibv_obj) { goto out; } + #if HWLOC_API_VERSION >= 0x20000 + /* the new matrix format isn't quite as friendly, so we have to + * do an exhaustive search to find the index of this object + * in that array */ + ibvindex = -1; + for (j=0; j < distances_nr; j++) { + if (ibv_obj == hwloc_distances->objs[j]) { + ibvindex = j; + break; + } + } + if (-1 == ibvindex) { + OPAL_ERROR_LOG(OPAL_ERR_NOT_FOUND); + goto out; + } + #endif opal_output_verbose(5, opal_btl_base_framework.framework_output, "ibv_obj->logical_index=%d", ibv_obj->logical_index); @@ -2424,7 +2464,15 @@ static float get_ib_dev_distance(struct ibv_device *dev) switch (my_obj->type) { case HWLOC_OBJ_NODE: case HWLOC_OBJ_SOCKET: - case HWLOC_OBJ_CACHE: + #if HWLOC_API_VERSION < 0x20000 + case HWLOC_OBJ_CACHE: + #else + case HWLOC_OBJ_L1CACHE: + case HWLOC_OBJ_L2CACHE: + case HWLOC_OBJ_L3CACHE: + case HWLOC_OBJ_L4CACHE: + case HWLOC_OBJ_L5CACHE: + #endif case HWLOC_OBJ_CORE: case HWLOC_OBJ_PU: while (NULL != my_obj && my_obj->type != HWLOC_OBJ_NODE) { @@ -2435,12 +2483,31 @@ static float get_ib_dev_distance(struct ibv_device *dev) "my_obj->logical_index=%d", my_obj->logical_index); /* Distance may be asymetrical, so calculate both of them and take the max */ - a = hwloc_distances->latency[my_obj->logical_index + - (ibv_obj->logical_index * - hwloc_distances->nbobjs)]; - b = hwloc_distances->latency[ibv_obj->logical_index + - (my_obj->logical_index * - hwloc_distances->nbobjs)]; + #if HWLOC_API_VERSION < 0x20000 + a = hwloc_distances->latency[my_obj->logical_index + + (ibv_obj->logical_index * + hwloc_distances->nbobjs)]; + b = hwloc_distances->latency[ibv_obj->logical_index + + (my_obj->logical_index * + hwloc_distances->nbobjs)]; + #else + /* the new matrix format isn't quite as friendly, so we have to + * do an exhaustive search to find the index of this object + * in that array */ + myindex = -1; + for (j=0; j < distances_nr; j++) { + if (my_obj == hwloc_distances->objs[j]) { + myindex = j; + break; + } + } + if (-1 == myindex) { + OPAL_ERROR_LOG(OPAL_ERR_NOT_FOUND); + goto out; + } + a = (float)hwloc_distances->values[myindex + (ibvindex * hwloc_distances->nbobjs)]; + b = (float)hwloc_distances->values[ibvindex + (myindex * hwloc_distances->nbobjs)]; + #endif distance = (a > b) ? a : b; } break; @@ -2456,13 +2523,28 @@ static float get_ib_dev_distance(struct ibv_device *dev) node_obj = hwloc_get_obj_inside_cpuset_by_type(opal_hwloc_topology, ibv_obj->cpuset, HWLOC_OBJ_NODE, ++i)) { - - a = hwloc_distances->latency[node_obj->logical_index + - (ibv_obj->logical_index * - hwloc_distances->nbobjs)]; - b = hwloc_distances->latency[ibv_obj->logical_index + - (node_obj->logical_index * - hwloc_distances->nbobjs)]; + #if HWLOC_API_VERSION < 0x20000 + a = hwloc_distances->latency[node_obj->logical_index + + (ibv_obj->logical_index * + hwloc_distances->nbobjs)]; + b = hwloc_distances->latency[ibv_obj->logical_index + + (node_obj->logical_index * + hwloc_distances->nbobjs)]; + #else + unsigned int j; + j = node_obj->logical_index + (ibv_obj->logical_index * hwloc_distances->nbobjs); + if (j < distances_nr) { + a = (float)hwloc_distances->values[j]; + } else { + goto out; + } + j = ibv_obj->logical_index + (node_obj->logical_index * hwloc_distances->nbobjs); + if (j < distances_nr) { + b = (float)hwloc_distances->values[j]; + } else { + goto out; + } + #endif a = (a > b) ? a : b; distance = (a > distance) ? a : distance; } @@ -2476,10 +2558,12 @@ static float get_ib_dev_distance(struct ibv_device *dev) if (NULL != my_cpuset) { hwloc_bitmap_free(my_cpuset); } -#else -#warning FIXME get_ib_dev_distance is not implemented with hwloc v2 -#endif +#if HWLOC_API_VERSION < 0x20000 + if (NULL != hwloc_distances) { + hwloc_distances_release(opal_hwloc_topology, hwloc_distances); + } +#endif return distance; } diff --git a/opal/mca/btl/openib/btl_openib_proc.c b/opal/mca/btl/openib/btl_openib_proc.c index 8d751c86af..a4b77fa643 100644 --- a/opal/mca/btl/openib/btl_openib_proc.c +++ b/opal/mca/btl/openib/btl_openib_proc.c @@ -12,7 +12,7 @@ * All rights reserved. * Copyright (c) 2007-2015 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2006-2007 Voltaire All rights reserved. - * Copyright (c) 2014 Intel, Inc. All rights reserved. + * Copyright (c) 2014-2017 Intel, Inc. All rights reserved. * Copyright (c) 2015-2016 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2015 Mellanox Technologies. All rights reserved. @@ -77,8 +77,6 @@ void mca_btl_openib_proc_construct(mca_btl_openib_proc_t* ib_proc) void mca_btl_openib_proc_destruct(mca_btl_openib_proc_t* ib_proc) { - mca_btl_openib_proc_btlptr_t* elem; - /* release resources */ if(NULL != ib_proc->proc_endpoints) { free(ib_proc->proc_endpoints); diff --git a/opal/mca/btl/usnic/btl_usnic_hwloc.c b/opal/mca/btl/usnic/btl_usnic_hwloc.c index e0230f02c9..a435a8a404 100644 --- a/opal/mca/btl/usnic/btl_usnic_hwloc.c +++ b/opal/mca/btl/usnic/btl_usnic_hwloc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2013-2016 Cisco Systems, Inc. All rights reserved. - * Copyright (c) 2016 Intel, Inc. All rights reserved. + * Copyright (c) 2016-2017 Intel, Inc. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -26,22 +26,34 @@ */ static hwloc_obj_t my_numa_node = NULL; static int num_numa_nodes = 0; -static const struct hwloc_distances_s *matrix = NULL; +static struct hwloc_distances_s *matrix = NULL; +#if HWLOC_API_VERSION >= 0x20000 +static unsigned int matrix_nr = 1; +#endif /* * Get the hwloc distance matrix (if we don't already have it). - * - * Note that the matrix data structure belongs to hwloc; we are not - * responsibile for freeing it. */ static int get_distance_matrix(void) { +#if HWLOC_API_VERSION < 0x20000 + /* Note that the matrix data structure belongs to hwloc; we are not + * responsible for freeing it. */ + if (NULL == matrix) { matrix = hwloc_get_whole_distance_matrix_by_type(opal_hwloc_topology, HWLOC_OBJ_NODE); } return (NULL == matrix) ? OPAL_ERROR : OPAL_SUCCESS; +#else + if (0 != hwloc_distances_get_by_type(opal_hwloc_topology, HWLOC_OBJ_NODE, + &matrix_nr, &matrix, + HWLOC_DISTANCES_KIND_MEANS_LATENCY, 0) || 0 == matrix_nr) { + return OPAL_ERROR; + } + return OPAL_SUCCESS; +#endif } /* @@ -219,6 +231,7 @@ int opal_btl_usnic_hwloc_distance(opal_btl_usnic_module_t *module) /* Lookup the distance between my NUMA node and the NUMA node of the device */ +#if HWLOC_API_VERSION < 0x20000 if (NULL != dev_numa) { module->numa_distance = matrix->latency[dev_numa->logical_index * num_numa_nodes + @@ -229,6 +242,40 @@ int opal_btl_usnic_hwloc_distance(opal_btl_usnic_module_t *module) module->linux_device_name, module->numa_distance); } +#else + if (NULL != dev_numa) { + int myindex, devindex; + unsigned int j; + myindex = -1; + for (j=0; j < matrix_nr; j++) { + if (my_numa_node == matrix->objs[j]) { + myindex = j; + break; + } + } + if (-1 == myindex) { + return OPAL_SUCCESS; + } + devindex = -1; + for (j=0; j < matrix_nr; j++) { + if (dev_numa == matrix->objs[j]) { + devindex = j; + break; + } + } + if (-1 == devindex) { + return OPAL_SUCCESS; + } + + module->numa_distance = + matrix->values[(devindex * num_numa_nodes) + myindex]; + + opal_output_verbose(5, USNIC_OUT, + "btl:usnic:filter_numa: %s is distance %d from me", + module->linux_device_name, + module->numa_distance); + } +#endif return OPAL_SUCCESS; } diff --git a/opal/mca/hwloc/base/hwloc_base_util.c b/opal/mca/hwloc/base/hwloc_base_util.c index 2da9d22af2..1f9ee5a8d7 100644 --- a/opal/mca/hwloc/base/hwloc_base_util.c +++ b/opal/mca/hwloc/base/hwloc_base_util.c @@ -35,6 +35,12 @@ #ifdef HAVE_ENDIAN_H #include #endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#if HAVE_FCNTL_H +#include +#endif #include "opal/runtime/opal.h" #include "opal/constants.h" @@ -48,6 +54,8 @@ #include "opal/mca/hwloc/hwloc-internal.h" #include "opal/mca/hwloc/base/base.h" +static bool topo_in_shmem = false; + /* * Provide the hwloc object that corresponds to the given * processor id of the given type. Remember: "processor" here [usually] means "core" -- @@ -251,21 +259,58 @@ int opal_hwloc_base_get_topology(void) int rc; opal_process_name_t wildcard_rank; char *val = NULL; +#if HWLOC_API_VERSION >= 0x20000 + int rc2, rc3, fd; + uint64_t addr, *aptr, size, *sptr; + char *shmemfile; + hwloc_obj_t root; + opal_hwloc_topo_data_t *sum; +#endif OPAL_OUTPUT_VERBOSE((2, opal_hwloc_base_framework.framework_output, "hwloc:base:get_topology")); - /* see if we already got it */ + /* see if we already have it */ if (NULL != opal_hwloc_topology) { return OPAL_SUCCESS; } + wildcard_rank.jobid = OPAL_PROC_MY_NAME.jobid; + wildcard_rank.vpid = OPAL_VPID_WILDCARD; if (NULL != opal_pmix.get) { - /* try to retrieve it from the PMIx store */ +#if HWLOC_API_VERSION >= 0x20000 + OPAL_OUTPUT_VERBOSE((2, opal_hwloc_base_framework.framework_output, + "hwloc:base: looking for topology in shared memory")); + + /* first try to get the shmem link, if available */ + aptr = &addr; + sptr = &size; + OPAL_MODEX_RECV_VALUE_OPTIONAL(rc, OPAL_PMIX_HWLOC_SHMEM_FILE, + &wildcard_rank, (void**)&shmemfile, OPAL_STRING); + OPAL_MODEX_RECV_VALUE_OPTIONAL(rc2, OPAL_PMIX_HWLOC_SHMEM_ADDR, + &wildcard_rank, (void**)&aptr, OPAL_SIZE); + OPAL_MODEX_RECV_VALUE_OPTIONAL(rc3, OPAL_PMIX_HWLOC_SHMEM_SIZE, + &wildcard_rank, (void**)&sptr, OPAL_SIZE); + if (OPAL_SUCCESS == rc && OPAL_SUCCESS == rc2 && OPAL_SUCCESS == rc3) { + if (0 > (fd = open(shmemfile, O_RDONLY))) { + free(shmemfile); + return OPAL_ERROR; + } + free(shmemfile); + if (0 != hwloc_shmem_topology_adopt(&opal_hwloc_topology, fd, + 0, (void*)addr, size, 0)) { + return OPAL_ERROR; + } + OPAL_OUTPUT_VERBOSE((2, opal_hwloc_base_framework.framework_output, + "hwloc:base: topology in shared memory")); + topo_in_shmem = true; + return OPAL_SUCCESS; + } +#endif + /* if that isn't available, then try to retrieve + * the xml representation from the PMIx data store */ opal_output_verbose(1, opal_hwloc_base_framework.framework_output, "hwloc:base instantiating topology"); - wildcard_rank.jobid = OPAL_PROC_MY_NAME.jobid; - wildcard_rank.vpid = OPAL_VPID_WILDCARD; OPAL_MODEX_RECV_VALUE_OPTIONAL(rc, OPAL_PMIX_LOCAL_TOPO, &wildcard_rank, &val, OPAL_STRING); } else { @@ -306,6 +351,20 @@ int opal_hwloc_base_get_topology(void) hwloc_topology_destroy(opal_hwloc_topology); return rc; } +#else + /* setup the summary cpuset to make things consistent */ + root = hwloc_get_root_obj(opal_hwloc_topology); + + if (NULL == root->userdata) { + root->userdata = (void*)OBJ_NEW(opal_hwloc_topo_data_t); + } + sum = (opal_hwloc_topo_data_t*)root->userdata; + + /* should only ever enter here once, but check anyway */ + if (NULL == sum->available) { + sum->available = hwloc_bitmap_dup(root->allowed_cpuset); + return OPAL_SUCCESS; + } #endif } else if (NULL == opal_hwloc_base_topo_file) { if (0 != hwloc_topology_init(&opal_hwloc_topology) || @@ -319,6 +378,20 @@ int opal_hwloc_base_get_topology(void) hwloc_topology_destroy(opal_hwloc_topology); return rc; } +#else + /* setup the summary cpuset to make things consistent */ + root = hwloc_get_root_obj(opal_hwloc_topology); + + if (NULL == root->userdata) { + root->userdata = (void*)OBJ_NEW(opal_hwloc_topo_data_t); + } + sum = (opal_hwloc_topo_data_t*)root->userdata; + + /* should only ever enter here once, but check anyway */ + if (NULL == sum->available) { + sum->available = hwloc_bitmap_dup(root->allowed_cpuset); + return OPAL_SUCCESS; + } #endif } else { if (OPAL_SUCCESS != (rc = opal_hwloc_base_set_topology(opal_hwloc_base_topo_file))) { @@ -414,18 +487,20 @@ void opal_hwloc_base_free_topology(hwloc_topology_t topo) opal_hwloc_topo_data_t *rdata; unsigned k; - obj = hwloc_get_root_obj(topo); - /* release the root-level userdata */ - if (NULL != obj->userdata) { - rdata = (opal_hwloc_topo_data_t*)obj->userdata; - OBJ_RELEASE(rdata); - obj->userdata = NULL; - } - /* now recursively descend and release userdata - * in the rest of the objects - */ - for (k=0; k < obj->arity; k++) { - free_object(obj->children[k]); + if (!topo_in_shmem) { + obj = hwloc_get_root_obj(topo); + /* release the root-level userdata */ + if (NULL != obj->userdata) { + rdata = (opal_hwloc_topo_data_t*)obj->userdata; + OBJ_RELEASE(rdata); + obj->userdata = NULL; + } + /* now recursively descend and release userdata + * in the rest of the objects + */ + for (k=0; k < obj->arity; k++) { + free_object(obj->children[k]); + } } hwloc_topology_destroy(topo); } @@ -744,7 +819,9 @@ static hwloc_obj_t df_search(hwloc_topology_t topo, return NULL; } - notfound: +#if HWLOC_API_VERSION < 0x20000 + notfound: +#endif for (k=0; k < start->arity; k++) { obj = df_search(topo, start->children[k], target, cache_level, nobj, rtype, idx, num_objs); if (NULL != obj) { @@ -923,7 +1000,9 @@ hwloc_obj_t opal_hwloc_base_find_min_bound_target_under_obj(hwloc_topology_t top return obj; } - moveon: +#if HWLOC_API_VERSION < 0x20000 + moveon: +#endif /* the hwloc accessors all report at the topo level, * so we have to do some work */ @@ -1876,7 +1955,6 @@ int opal_hwloc_base_cset2mapstr(char *str, int len, /* if the cpuset includes all available cpus, then we are unbound */ root = hwloc_get_root_obj(topo); -#if HWLOC_API_VERSION < 0x20000 if (NULL != root->userdata) { sum = (opal_hwloc_topo_data_t*)root->userdata; if (NULL == sum->available) { @@ -1886,11 +1964,6 @@ int opal_hwloc_base_cset2mapstr(char *str, int len, return OPAL_ERR_NOT_BOUND; } } -#else - if (0 != hwloc_bitmap_isincluded(root->cpuset, cpuset)) { - return OPAL_ERR_NOT_BOUND; - } -#endif /* Iterate over all existing sockets */ for (socket = hwloc_get_obj_by_type(topo, HWLOC_OBJ_SOCKET, 0); @@ -1952,14 +2025,17 @@ static int dist_cmp_fn (opal_list_item_t **a, opal_list_item_t **b) static void sort_by_dist(hwloc_topology_t topo, char* device_name, opal_list_t *sorted_list) { hwloc_obj_t device_obj = NULL; - hwloc_obj_t obj = NULL, root = NULL; + hwloc_obj_t obj = NULL; struct hwloc_distances_s* distances; opal_rmaps_numa_node_t *numa_node; int close_node_index; float latency; unsigned int j; +#if HWLOC_API_VERSION < 0x20000 + hwloc_obj_t root = NULL; int depth; unsigned i; +#endif unsigned distances_nr = 0; 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)) { @@ -2019,7 +2095,9 @@ static void sort_by_dist(hwloc_topology_t topo, char* device_name, opal_list_t * opal_list_append(sorted_list, &numa_node->super); } #else - if (0 != hwloc_distances_get_by_type(topo, HWLOC_OBJ_NODE, &distances_nr, &distances, 0, 0) || 0 == distances_nr) { + distances_nr = 1; + if (0 != hwloc_distances_get_by_type(topo, HWLOC_OBJ_NODE, &distances_nr, &distances, + HWLOC_DISTANCES_KIND_MEANS_LATENCY, 0) || 0 == distances_nr) { opal_output_verbose(5, opal_hwloc_base_framework.framework_output, "hwloc:base:get_sorted_numa_list: There is no information about distances on the node."); return; diff --git a/opal/mca/hwloc/hwloc1116/README-ompi.txt b/opal/mca/hwloc/hwloc1116/README-ompi.txt deleted file mode 100644 index 1679af491e..0000000000 --- a/opal/mca/hwloc/hwloc1116/README-ompi.txt +++ /dev/null @@ -1,6 +0,0 @@ -Cherry-picked commits after 1.11.3: - -open-mpi/hwloc@9549fd59af04dca2e2340e17f0e685f8c552d818 -open-mpi/hwloc@0ab7af5e90fc2b58be30b2126cc2a73f9f7ecfe9 -open-mpi/hwloc@8b44fb1c812d01582887548c2fc28ee78255619 -open-mpi/hwloc@d4565c351e5f01e27d3e106e3a4c2f971a37c9dd diff --git a/opal/mca/hwloc/hwloc1116/hwloc/AUTHORS b/opal/mca/hwloc/hwloc1116/hwloc/AUTHORS deleted file mode 100644 index 0e52215789..0000000000 --- a/opal/mca/hwloc/hwloc1116/hwloc/AUTHORS +++ /dev/null @@ -1,10 +0,0 @@ -Cédric Augonnet -Guillaume Beauchamp -Jérôme Clet-Ortega -Ludovic Courtès -Nathalie Furmento -Brice Goglin -Alexey Kardashevskiy -Antoine Rougier (University of Bordeaux intern) -Jeff Squyres -Samuel Thibault diff --git a/opal/mca/hwloc/hwloc1116/hwloc/README b/opal/mca/hwloc/hwloc1116/hwloc/README deleted file mode 100644 index 6c43d4980a..0000000000 --- a/opal/mca/hwloc/hwloc1116/hwloc/README +++ /dev/null @@ -1,75 +0,0 @@ -Introduction - -hwloc provides command line tools and a C API to obtain the hierarchical map of -key computing elements, such as: NUMA memory nodes, shared caches, processor -packages, processor cores, processing units (logical processors or "threads") -and even I/O devices. hwloc also gathers various attributes such as cache and -memory information, and is portable across a variety of different operating -systems and platforms. Additionally it may assemble the topologies of multiple -machines into a single one so as to let applications consult the topology of an -entire fabric or cluster at once. - -hwloc primarily aims at helping high-performance computing (HPC) applications, -but is also applicable to any project seeking to exploit code and/or data -locality on modern computing platforms. - -hwloc supports the following operating systems: - - * Linux (including old kernels not having sysfs topology information, with - knowledge of cpusets, ScaleMP vSMP and Kerrighed support, etc.) on all - supported hardware, including Intel Xeon Phi (KNL and KNC, either - standalone or as a coprocessor) and NumaScale NumaConnect. - * Solaris - * AIX - * Darwin / OS X - * FreeBSD and its variants (such as kFreeBSD/GNU) - * NetBSD - * OSF/1 (a.k.a., Tru64) - * HP-UX - * Microsoft Windows - * IBM BlueGene/Q Compute Node Kernel (CNK) - -Since it uses standard Operating System information, hwloc's support is mostly -independant from the processor type (x86, powerpc, ...) and just relies on the -Operating System support. The only exception to this is kFreeBSD, which does -not support topology information, and hwloc thus uses an x86-only CPUID-based -backend (which can be used for other OSes too, see the Components and plugins -section). - -To check whether hwloc works on a particular machine, just try to build it and -run lstopo or lstopo-no-graphics. If some things do not look right (e.g. bogus -or missing cache information), see Questions and Bugs below. - -hwloc only reports the number of processors on unsupported operating systems; -no topology information is available. - -For development and debugging purposes, hwloc also offers the ability to work -on "fake" topologies: - - * Symmetrical tree of resources generated from a list of level arities, see - Synthetic topologies. - * Remote machine simulation through the gathering of topology as XML files, - see Importing and exporting topologies from/to XML files. - -hwloc can display the topology in a human-readable format, either in graphical -mode (X11), or by exporting in one of several different formats, including: -plain text, PDF, PNG, and FIG (see Command-line Examples below). Note that some -of the export formats require additional support libraries. - -hwloc offers a programming interface for manipulating topologies and objects. -It also brings a powerful CPU bitmap API that is used to describe topology -objects location on physical/logical processors. See the Programming Interface -below. It may also be used to binding applications onto certain cores or memory -nodes. Several utility programs are also provided to ease command-line -manipulation of topology objects, binding of processes, and so on. - -Perl bindings are available from Bernd Kallies on CPAN. - -Python bindings are available from Guy Streeter: - - * Fedora RPM and tarball. - * git tree (html). - - - -See https://www.open-mpi.org/projects/hwloc/doc/ for more hwloc documentation. diff --git a/opal/mca/hwloc/hwloc1116/hwloc/include/hwloc/deprecated.h b/opal/mca/hwloc/hwloc1116/hwloc/include/hwloc/deprecated.h deleted file mode 100644 index ac42c13de0..0000000000 --- a/opal/mca/hwloc/hwloc1116/hwloc/include/hwloc/deprecated.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright © 2009 CNRS - * Copyright © 2009-2014 Inria. All rights reserved. - * Copyright © 2009-2012 Université Bordeaux - * Copyright © 2009-2010 Cisco Systems, Inc. All rights reserved. - * See COPYING in top-level directory. - */ - -/** - * This file contains the inline code of functions declared in hwloc.h - */ - -#ifndef HWLOC_DEPRECATED_H -#define HWLOC_DEPRECATED_H - -#ifndef HWLOC_H -#error Please include the main hwloc.h instead -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* backward compat with v1.10 before Socket->Package renaming */ -#define HWLOC_OBJ_SOCKET HWLOC_OBJ_PACKAGE -/* backward compat with v1.10 before Node->NUMANode clarification */ -#define HWLOC_OBJ_NODE HWLOC_OBJ_NUMANODE - -/** \brief Return an object type from the string - * - * \return -1 if unrecognized. - */ -HWLOC_DECLSPEC hwloc_obj_type_t hwloc_obj_type_of_string (const char * string) __hwloc_attribute_pure __hwloc_attribute_deprecated; - -/** \brief Stringify a given topology object into a human-readable form. - * - * \note This function is deprecated in favor of hwloc_obj_type_snprintf() - * and hwloc_obj_attr_snprintf() since it is not very flexible and - * only prints physical/OS indexes. - * - * Fill string \p string up to \p size characters with the description - * of topology object \p obj in topology \p topology. - * - * If \p verbose is set, a longer description is used. Otherwise a - * short description is used. - * - * \p indexprefix is used to prefix the \p os_index attribute number of - * the object in the description. If \c NULL, the \c # character is used. - * - * If \p size is 0, \p string may safely be \c NULL. - * - * \return the number of character that were actually written if not truncating, - * or that would have been written (not including the ending \\0). - */ -HWLOC_DECLSPEC int hwloc_obj_snprintf(char * __hwloc_restrict string, size_t size, - hwloc_topology_t topology, hwloc_obj_t obj, - const char * __hwloc_restrict indexprefix, int verbose) __hwloc_attribute_deprecated; - -/** \brief Distribute \p n items over the topology under \p root - * - * Array \p cpuset will be filled with \p n cpusets recursively distributed - * linearly over the topology under \p root, down to depth \p until (which can - * be INT_MAX to distribute down to the finest level). - * - * This is typically useful when an application wants to distribute \p n - * threads over a machine, giving each of them as much private cache as - * possible and keeping them locally in number order. - * - * The caller may typically want to also call hwloc_bitmap_singlify() - * before binding a thread so that it does not move at all. - * - * \note This function requires the \p root object to have a CPU set. - */ -static __hwloc_inline void -hwloc_distribute(hwloc_topology_t topology, hwloc_obj_t root, hwloc_cpuset_t *set, unsigned n, unsigned until) __hwloc_attribute_deprecated; -static __hwloc_inline void -hwloc_distribute(hwloc_topology_t topology, hwloc_obj_t root, hwloc_cpuset_t *set, unsigned n, unsigned until) -{ - hwloc_distrib(topology, &root, 1, set, n, until, 0); -} - -/** \brief Distribute \p n items over the topology under \p roots - * - * This is the same as hwloc_distribute(), but takes an array of roots instead of - * just one root. - * - * \note This function requires the \p roots objects to have a CPU set. - */ -static __hwloc_inline void -hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *roots, unsigned n_roots, hwloc_cpuset_t *set, unsigned n, unsigned until) __hwloc_attribute_deprecated; -static __hwloc_inline void -hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *roots, unsigned n_roots, hwloc_cpuset_t *set, unsigned n, unsigned until) -{ - hwloc_distrib(topology, roots, n_roots, set, n, until, 0); -} - -#ifdef __cplusplus -} /* extern "C" */ -#endif - - -#endif /* HWLOC_DEPRECATED_H */ diff --git a/opal/mca/hwloc/hwloc1116/hwloc/include/private/components.h b/opal/mca/hwloc/hwloc1116/hwloc/include/private/components.h deleted file mode 100644 index b36634535f..0000000000 --- a/opal/mca/hwloc/hwloc1116/hwloc/include/private/components.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright © 2012 Inria. All rights reserved. - * See COPYING in top-level directory. - */ - - -#ifdef HWLOC_INSIDE_PLUGIN -/* - * these declarations are internal only, they are not available to plugins - * (many functions below are internal static symbols). - */ -#error This file should not be used in plugins -#endif - - -#ifndef PRIVATE_COMPONENTS_H -#define PRIVATE_COMPONENTS_H 1 - -#include - -struct hwloc_topology; - -extern int hwloc_disc_component_force_enable(struct hwloc_topology *topology, - int envvar_forced, /* 1 if forced through envvar, 0 if forced through API */ - int type, const char *name, - const void *data1, const void *data2, const void *data3); -extern void hwloc_disc_components_enable_others(struct hwloc_topology *topology); - -/* Compute the topology is_thissystem flag based on enabled backends */ -extern void hwloc_backends_is_thissystem(struct hwloc_topology *topology); - -/* Disable and destroy all backends used by a topology */ -extern void hwloc_backends_disable_all(struct hwloc_topology *topology); - -/* Used by the core to setup/destroy the list of components */ -extern void hwloc_components_init(struct hwloc_topology *topology); /* increases components refcount, should be called exactly once per topology (during init) */ -extern void hwloc_components_destroy_all(struct hwloc_topology *topology); /* decreases components refcount, should be called exactly once per topology (during destroy) */ - -#endif /* PRIVATE_COMPONENTS_H */ - diff --git a/opal/mca/hwloc/hwloc1116/hwloc/src/base64.c b/opal/mca/hwloc/hwloc1116/hwloc/src/base64.c deleted file mode 100644 index 4e1976fde4..0000000000 --- a/opal/mca/hwloc/hwloc1116/hwloc/src/base64.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright © 2012 Inria. All rights reserved. - * See COPYING in top-level directory. - * - * Modifications after import: - * - removed all #if - * - updated prototypes - * - updated #include - */ - -/* $OpenBSD: base64.c,v 1.5 2006/10/21 09:55:03 otto Exp $ */ - -/* - * Copyright (c) 1996 by Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -/* - * Portions Copyright (c) 1995 by International Business Machines, Inc. - * - * International Business Machines, Inc. (hereinafter called IBM) grants - * permission under its copyrights to use, copy, modify, and distribute this - * Software with or without fee, provided that the above copyright notice and - * all paragraphs of this notice appear in all copies, and that the name of IBM - * not be used in connection with the marketing of any product incorporating - * the Software or modifications thereof, without specific, written prior - * permission. - * - * To the extent it has a right to do so, IBM grants an immunity from suit - * under its patents, if any, for the use, sale or manufacture of products to - * the extent that such products are used for performing Domain Name System - * dynamic updates in TCP/IP networks by means of the Software. No immunity is - * granted for any product per se or for any other function of any product. - * - * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, - * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN - * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. - */ - -/* OPENBSD ORIGINAL: lib/libc/net/base64.c */ - -static const char Base64[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -static const char Pad64 = '='; - -/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) - The following encoding technique is taken from RFC 1521 by Borenstein - and Freed. It is reproduced here in a slightly edited form for - convenience. - - A 65-character subset of US-ASCII is used, enabling 6 bits to be - represented per printable character. (The extra 65th character, "=", - is used to signify a special processing function.) - - The encoding process represents 24-bit groups of input bits as output - strings of 4 encoded characters. Proceeding from left to right, a - 24-bit input group is formed by concatenating 3 8-bit input groups. - These 24 bits are then treated as 4 concatenated 6-bit groups, each - of which is translated into a single digit in the base64 alphabet. - - Each 6-bit group is used as an index into an array of 64 printable - characters. The character referenced by the index is placed in the - output string. - - Table 1: The Base64 Alphabet - - Value Encoding Value Encoding Value Encoding Value Encoding - 0 A 17 R 34 i 51 z - 1 B 18 S 35 j 52 0 - 2 C 19 T 36 k 53 1 - 3 D 20 U 37 l 54 2 - 4 E 21 V 38 m 55 3 - 5 F 22 W 39 n 56 4 - 6 G 23 X 40 o 57 5 - 7 H 24 Y 41 p 58 6 - 8 I 25 Z 42 q 59 7 - 9 J 26 a 43 r 60 8 - 10 K 27 b 44 s 61 9 - 11 L 28 c 45 t 62 + - 12 M 29 d 46 u 63 / - 13 N 30 e 47 v - 14 O 31 f 48 w (pad) = - 15 P 32 g 49 x - 16 Q 33 h 50 y - - Special processing is performed if fewer than 24 bits are available - at the end of the data being encoded. A full encoding quantum is - always completed at the end of a quantity. When fewer than 24 input - bits are available in an input group, zero bits are added (on the - right) to form an integral number of 6-bit groups. Padding at the - end of the data is performed using the '=' character. - - Since all base64 input is an integral number of octets, only the - ------------------------------------------------- - following cases can arise: - - (1) the final quantum of encoding input is an integral - multiple of 24 bits; here, the final unit of encoded - output will be an integral multiple of 4 characters - with no "=" padding, - (2) the final quantum of encoding input is exactly 8 bits; - here, the final unit of encoded output will be two - characters followed by two "=" padding characters, or - (3) the final quantum of encoding input is exactly 16 bits; - here, the final unit of encoded output will be three - characters followed by one "=" padding character. - */ - -#include -#include -#include - -#include - -int -hwloc_encode_to_base64(const char *src, size_t srclength, char *target, size_t targsize) -{ - size_t datalength = 0; - unsigned char input[3]; - unsigned char output[4]; - unsigned int i; - - while (2 < srclength) { - input[0] = *src++; - input[1] = *src++; - input[2] = *src++; - srclength -= 3; - - output[0] = input[0] >> 2; - output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); - output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); - output[3] = input[2] & 0x3f; - - if (datalength + 4 > targsize) - return (-1); - target[datalength++] = Base64[output[0]]; - target[datalength++] = Base64[output[1]]; - target[datalength++] = Base64[output[2]]; - target[datalength++] = Base64[output[3]]; - } - - /* Now we worry about padding. */ - if (0 != srclength) { - /* Get what's left. */ - input[0] = input[1] = input[2] = '\0'; - for (i = 0; i < srclength; i++) - input[i] = *src++; - - output[0] = input[0] >> 2; - output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); - output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); - - if (datalength + 4 > targsize) - return (-1); - target[datalength++] = Base64[output[0]]; - target[datalength++] = Base64[output[1]]; - if (srclength == 1) - target[datalength++] = Pad64; - else - target[datalength++] = Base64[output[2]]; - target[datalength++] = Pad64; - } - if (datalength >= targsize) - return (-1); - target[datalength] = '\0'; /* Returned value doesn't count \0. */ - return (int)(datalength); -} - -/* skips all whitespace anywhere. - converts characters, four at a time, starting at (or after) - src from base - 64 numbers into three 8 bit bytes in the target area. - it returns the number of data bytes stored at the target, or -1 on error. - */ - -int -hwloc_decode_from_base64(char const *src, char *target, size_t targsize) -{ - unsigned int tarindex, state; - int ch; - char *pos; - - state = 0; - tarindex = 0; - - while ((ch = *src++) != '\0') { - if (isspace(ch)) /* Skip whitespace anywhere. */ - continue; - - if (ch == Pad64) - break; - - pos = strchr(Base64, ch); - if (pos == 0) /* A non-base64 character. */ - return (-1); - - switch (state) { - case 0: - if (target) { - if (tarindex >= targsize) - return (-1); - target[tarindex] = (char)(pos - Base64) << 2; - } - state = 1; - break; - case 1: - if (target) { - if (tarindex + 1 >= targsize) - return (-1); - target[tarindex] |= (pos - Base64) >> 4; - target[tarindex+1] = ((pos - Base64) & 0x0f) - << 4 ; - } - tarindex++; - state = 2; - break; - case 2: - if (target) { - if (tarindex + 1 >= targsize) - return (-1); - target[tarindex] |= (pos - Base64) >> 2; - target[tarindex+1] = ((pos - Base64) & 0x03) - << 6; - } - tarindex++; - state = 3; - break; - case 3: - if (target) { - if (tarindex >= targsize) - return (-1); - target[tarindex] |= (pos - Base64); - } - tarindex++; - state = 0; - break; - } - } - - /* - * We are done decoding Base-64 chars. Let's see if we ended - * on a byte boundary, and/or with erroneous trailing characters. - */ - - if (ch == Pad64) { /* We got a pad char. */ - ch = *src++; /* Skip it, get next. */ - switch (state) { - case 0: /* Invalid = in first position */ - case 1: /* Invalid = in second position */ - return (-1); - - case 2: /* Valid, means one byte of info */ - /* Skip any number of spaces. */ - for (; ch != '\0'; ch = *src++) - if (!isspace(ch)) - break; - /* Make sure there is another trailing = sign. */ - if (ch != Pad64) - return (-1); - ch = *src++; /* Skip the = */ - /* Fall through to "single trailing =" case. */ - /* FALLTHROUGH */ - - case 3: /* Valid, means two bytes of info */ - /* - * We know this char is an =. Is there anything but - * whitespace after it? - */ - for (; ch != '\0'; ch = *src++) - if (!isspace(ch)) - return (-1); - - /* - * Now make sure for cases 2 and 3 that the "extra" - * bits that slopped past the last full byte were - * zeros. If we don't check them, they become a - * subliminal channel. - */ - if (target && target[tarindex] != 0) - return (-1); - } - } else { - /* - * We ended by seeing the end of the string. Make sure we - * have no partial bytes lying around. - */ - if (state != 0) - return (-1); - } - - return (tarindex); -} diff --git a/opal/mca/hwloc/hwloc1116/hwloc/src/bitmap.c b/opal/mca/hwloc/hwloc1116/hwloc/src/bitmap.c deleted file mode 100644 index 75c0c1ea35..0000000000 --- a/opal/mca/hwloc/hwloc1116/hwloc/src/bitmap.c +++ /dev/null @@ -1,1514 +0,0 @@ -/* - * Copyright © 2009 CNRS - * Copyright © 2009-2015 Inria. All rights reserved. - * Copyright © 2009-2011 Université Bordeaux - * Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved. - * See COPYING in top-level directory. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* TODO - * - have a way to change the initial allocation size - * - preallocate inside the bitmap structure (so that the whole structure is a cacheline for instance) - * and allocate a dedicated array only later when reallocating larger - */ - -/* magic number */ -#define HWLOC_BITMAP_MAGIC 0x20091007 - -/* actual opaque type internals */ -struct hwloc_bitmap_s { - unsigned ulongs_count; /* how many ulong bitmasks are valid, >= 1 */ - unsigned ulongs_allocated; /* how many ulong bitmasks are allocated, >= ulongs_count */ - unsigned long *ulongs; - int infinite; /* set to 1 if all bits beyond ulongs are set */ -#ifdef HWLOC_DEBUG - int magic; -#endif -}; - -/* overzealous check in debug-mode, not as powerful as valgrind but still useful */ -#ifdef HWLOC_DEBUG -#define HWLOC__BITMAP_CHECK(set) do { \ - assert((set)->magic == HWLOC_BITMAP_MAGIC); \ - assert((set)->ulongs_count >= 1); \ - assert((set)->ulongs_allocated >= (set)->ulongs_count); \ -} while (0) -#else -#define HWLOC__BITMAP_CHECK(set) -#endif - -/* extract a subset from a set using an index or a cpu */ -#define HWLOC_SUBBITMAP_INDEX(cpu) ((cpu)/(HWLOC_BITS_PER_LONG)) -#define HWLOC_SUBBITMAP_CPU_ULBIT(cpu) ((cpu)%(HWLOC_BITS_PER_LONG)) -/* Read from a bitmap ulong without knowing whether x is valid. - * Writers should make sure that x is valid and modify set->ulongs[x] directly. - */ -#define HWLOC_SUBBITMAP_READULONG(set,x) ((x) < (set)->ulongs_count ? (set)->ulongs[x] : (set)->infinite ? HWLOC_SUBBITMAP_FULL : HWLOC_SUBBITMAP_ZERO) - -/* predefined subset values */ -#define HWLOC_SUBBITMAP_ZERO 0UL -#define HWLOC_SUBBITMAP_FULL (~0UL) -#define HWLOC_SUBBITMAP_ULBIT(bit) (1UL<<(bit)) -#define HWLOC_SUBBITMAP_CPU(cpu) HWLOC_SUBBITMAP_ULBIT(HWLOC_SUBBITMAP_CPU_ULBIT(cpu)) -#define HWLOC_SUBBITMAP_ULBIT_TO(bit) (HWLOC_SUBBITMAP_FULL>>(HWLOC_BITS_PER_LONG-1-(bit))) -#define HWLOC_SUBBITMAP_ULBIT_FROM(bit) (HWLOC_SUBBITMAP_FULL<<(bit)) -#define HWLOC_SUBBITMAP_ULBIT_FROMTO(begin,end) (HWLOC_SUBBITMAP_ULBIT_TO(end) & HWLOC_SUBBITMAP_ULBIT_FROM(begin)) - -struct hwloc_bitmap_s * hwloc_bitmap_alloc(void) -{ - struct hwloc_bitmap_s * set; - - set = malloc(sizeof(struct hwloc_bitmap_s)); - if (!set) - return NULL; - - set->ulongs_count = 1; - set->ulongs_allocated = 64/sizeof(unsigned long); - set->ulongs = malloc(64); - if (!set->ulongs) { - free(set); - return NULL; - } - - set->ulongs[0] = HWLOC_SUBBITMAP_ZERO; - set->infinite = 0; -#ifdef HWLOC_DEBUG - set->magic = HWLOC_BITMAP_MAGIC; -#endif - return set; -} - -struct hwloc_bitmap_s * hwloc_bitmap_alloc_full(void) -{ - struct hwloc_bitmap_s * set = hwloc_bitmap_alloc(); - if (set) { - set->infinite = 1; - set->ulongs[0] = HWLOC_SUBBITMAP_FULL; - } - return set; -} - -void hwloc_bitmap_free(struct hwloc_bitmap_s * set) -{ - if (!set) - return; - - HWLOC__BITMAP_CHECK(set); -#ifdef HWLOC_DEBUG - set->magic = 0; -#endif - - free(set->ulongs); - free(set); -} - -/* enlarge until it contains at least needed_count ulongs. - */ -static void -hwloc_bitmap_enlarge_by_ulongs(struct hwloc_bitmap_s * set, unsigned needed_count) -{ - unsigned tmp = 1 << hwloc_flsl((unsigned long) needed_count - 1); - if (tmp > set->ulongs_allocated) { - set->ulongs = realloc(set->ulongs, tmp * sizeof(unsigned long)); - assert(set->ulongs); - set->ulongs_allocated = tmp; - } -} - -/* enlarge until it contains at least needed_count ulongs, - * and update new ulongs according to the infinite field. - */ -static void -hwloc_bitmap_realloc_by_ulongs(struct hwloc_bitmap_s * set, unsigned needed_count) -{ - unsigned i; - - HWLOC__BITMAP_CHECK(set); - - if (needed_count <= set->ulongs_count) - return; - - /* realloc larger if needed */ - hwloc_bitmap_enlarge_by_ulongs(set, needed_count); - - /* fill the newly allocated subset depending on the infinite flag */ - for(i=set->ulongs_count; iulongs[i] = set->infinite ? HWLOC_SUBBITMAP_FULL : HWLOC_SUBBITMAP_ZERO; - set->ulongs_count = needed_count; -} - -/* realloc until it contains at least cpu+1 bits */ -#define hwloc_bitmap_realloc_by_cpu_index(set, cpu) hwloc_bitmap_realloc_by_ulongs(set, ((cpu)/HWLOC_BITS_PER_LONG)+1) - -/* reset a bitmap to exactely the needed size. - * the caller must reinitialize all ulongs and the infinite flag later. - */ -static void -hwloc_bitmap_reset_by_ulongs(struct hwloc_bitmap_s * set, unsigned needed_count) -{ - hwloc_bitmap_enlarge_by_ulongs(set, needed_count); - set->ulongs_count = needed_count; -} - -/* reset until it contains exactly cpu+1 bits (roundup to a ulong). - * the caller must reinitialize all ulongs and the infinite flag later. - */ -#define hwloc_bitmap_reset_by_cpu_index(set, cpu) hwloc_bitmap_reset_by_ulongs(set, ((cpu)/HWLOC_BITS_PER_LONG)+1) - -struct hwloc_bitmap_s * hwloc_bitmap_dup(const struct hwloc_bitmap_s * old) -{ - struct hwloc_bitmap_s * new; - - if (!old) - return NULL; - - HWLOC__BITMAP_CHECK(old); - - new = malloc(sizeof(struct hwloc_bitmap_s)); - if (!new) - return NULL; - - new->ulongs = malloc(old->ulongs_allocated * sizeof(unsigned long)); - if (!new->ulongs) { - free(new); - return NULL; - } - new->ulongs_allocated = old->ulongs_allocated; - new->ulongs_count = old->ulongs_count; - memcpy(new->ulongs, old->ulongs, new->ulongs_count * sizeof(unsigned long)); - new->infinite = old->infinite; -#ifdef HWLOC_DEBUG - new->magic = HWLOC_BITMAP_MAGIC; -#endif - return new; -} - -void hwloc_bitmap_copy(struct hwloc_bitmap_s * dst, const struct hwloc_bitmap_s * src) -{ - HWLOC__BITMAP_CHECK(dst); - HWLOC__BITMAP_CHECK(src); - - hwloc_bitmap_reset_by_ulongs(dst, src->ulongs_count); - - memcpy(dst->ulongs, src->ulongs, src->ulongs_count * sizeof(unsigned long)); - dst->infinite = src->infinite; -} - -/* Strings always use 32bit groups */ -#define HWLOC_PRIxSUBBITMAP "%08lx" -#define HWLOC_BITMAP_SUBSTRING_SIZE 32 -#define HWLOC_BITMAP_SUBSTRING_LENGTH (HWLOC_BITMAP_SUBSTRING_SIZE/4) -#define HWLOC_BITMAP_STRING_PER_LONG (HWLOC_BITS_PER_LONG/HWLOC_BITMAP_SUBSTRING_SIZE) - -int hwloc_bitmap_snprintf(char * __hwloc_restrict buf, size_t buflen, const struct hwloc_bitmap_s * __hwloc_restrict set) -{ - ssize_t size = buflen; - char *tmp = buf; - int res, ret = 0; - int needcomma = 0; - int i; - unsigned long accum = 0; - int accumed = 0; -#if HWLOC_BITS_PER_LONG == HWLOC_BITMAP_SUBSTRING_SIZE - const unsigned long accum_mask = ~0UL; -#else /* HWLOC_BITS_PER_LONG != HWLOC_BITMAP_SUBSTRING_SIZE */ - const unsigned long accum_mask = ((1UL << HWLOC_BITMAP_SUBSTRING_SIZE) - 1) << (HWLOC_BITS_PER_LONG - HWLOC_BITMAP_SUBSTRING_SIZE); -#endif /* HWLOC_BITS_PER_LONG != HWLOC_BITMAP_SUBSTRING_SIZE */ - - HWLOC__BITMAP_CHECK(set); - - /* mark the end in case we do nothing later */ - if (buflen > 0) - tmp[0] = '\0'; - - if (set->infinite) { - res = hwloc_snprintf(tmp, size, "0xf...f"); - needcomma = 1; - if (res < 0) - return -1; - ret += res; - if (res >= size) - res = size>0 ? (int)size - 1 : 0; - tmp += res; - size -= res; - } - - i=set->ulongs_count-1; - - if (set->infinite) { - /* ignore starting FULL since we have 0xf...f already */ - while (i>=0 && set->ulongs[i] == HWLOC_SUBBITMAP_FULL) - i--; - } else { - /* ignore starting ZERO except the last one */ - while (i>=0 && set->ulongs[i] == HWLOC_SUBBITMAP_ZERO) - i--; - } - - while (i>=0 || accumed) { - /* Refill accumulator */ - if (!accumed) { - accum = set->ulongs[i--]; - accumed = HWLOC_BITS_PER_LONG; - } - - if (accum & accum_mask) { - /* print the whole subset if not empty */ - res = hwloc_snprintf(tmp, size, needcomma ? ",0x" HWLOC_PRIxSUBBITMAP : "0x" HWLOC_PRIxSUBBITMAP, - (accum & accum_mask) >> (HWLOC_BITS_PER_LONG - HWLOC_BITMAP_SUBSTRING_SIZE)); - needcomma = 1; - } else if (i == -1 && accumed == HWLOC_BITMAP_SUBSTRING_SIZE) { - /* print a single 0 to mark the last subset */ - res = hwloc_snprintf(tmp, size, needcomma ? ",0x0" : "0x0"); - } else if (needcomma) { - res = hwloc_snprintf(tmp, size, ","); - } else { - res = 0; - } - if (res < 0) - return -1; - ret += res; - -#if HWLOC_BITS_PER_LONG == HWLOC_BITMAP_SUBSTRING_SIZE - accum = 0; - accumed = 0; -#else - accum <<= HWLOC_BITMAP_SUBSTRING_SIZE; - accumed -= HWLOC_BITMAP_SUBSTRING_SIZE; -#endif - - if (res >= size) - res = size>0 ? (int)size - 1 : 0; - - tmp += res; - size -= res; - } - - /* if didn't display anything, display 0x0 */ - if (!ret) { - res = hwloc_snprintf(tmp, size, "0x0"); - if (res < 0) - return -1; - ret += res; - } - - return ret; -} - -int hwloc_bitmap_asprintf(char ** strp, const struct hwloc_bitmap_s * __hwloc_restrict set) -{ - int len; - char *buf; - - HWLOC__BITMAP_CHECK(set); - - len = hwloc_bitmap_snprintf(NULL, 0, set); - buf = malloc(len+1); - *strp = buf; - return hwloc_bitmap_snprintf(buf, len+1, set); -} - -int hwloc_bitmap_sscanf(struct hwloc_bitmap_s *set, const char * __hwloc_restrict string) -{ - const char * current = string; - unsigned long accum = 0; - int count=0; - int infinite = 0; - - /* count how many substrings there are */ - count++; - while ((current = strchr(current+1, ',')) != NULL) - count++; - - current = string; - if (!strncmp("0xf...f", current, 7)) { - current += 7; - if (*current != ',') { - /* special case for infinite/full bitmap */ - hwloc_bitmap_fill(set); - return 0; - } - current++; - infinite = 1; - count--; - } - - hwloc_bitmap_reset_by_ulongs(set, (count + HWLOC_BITMAP_STRING_PER_LONG - 1) / HWLOC_BITMAP_STRING_PER_LONG); - set->infinite = 0; - - while (*current != '\0') { - unsigned long val; - char *next; - val = strtoul(current, &next, 16); - - assert(count > 0); - count--; - - accum |= (val << ((count * HWLOC_BITMAP_SUBSTRING_SIZE) % HWLOC_BITS_PER_LONG)); - if (!(count % HWLOC_BITMAP_STRING_PER_LONG)) { - set->ulongs[count / HWLOC_BITMAP_STRING_PER_LONG] = accum; - accum = 0; - } - - if (*next != ',') { - if (*next || count > 0) - goto failed; - else - break; - } - current = (const char*) next+1; - } - - set->infinite = infinite; /* set at the end, to avoid spurious realloc with filled new ulongs */ - - return 0; - - failed: - /* failure to parse */ - hwloc_bitmap_zero(set); - return -1; -} - -int hwloc_bitmap_list_snprintf(char * __hwloc_restrict buf, size_t buflen, const struct hwloc_bitmap_s * __hwloc_restrict set) -{ - int prev = -1; - hwloc_bitmap_t reverse; - ssize_t size = buflen; - char *tmp = buf; - int res, ret = 0; - int needcomma = 0; - - HWLOC__BITMAP_CHECK(set); - - reverse = hwloc_bitmap_alloc(); /* FIXME: add hwloc_bitmap_alloc_size() + hwloc_bitmap_init_allocated() to avoid malloc? */ - hwloc_bitmap_not(reverse, set); - - /* mark the end in case we do nothing later */ - if (buflen > 0) - tmp[0] = '\0'; - - while (1) { - int begin, end; - - begin = hwloc_bitmap_next(set, prev); - if (begin == -1) - break; - end = hwloc_bitmap_next(reverse, begin); - - if (end == begin+1) { - res = hwloc_snprintf(tmp, size, needcomma ? ",%d" : "%d", begin); - } else if (end == -1) { - res = hwloc_snprintf(tmp, size, needcomma ? ",%d-" : "%d-", begin); - } else { - res = hwloc_snprintf(tmp, size, needcomma ? ",%d-%d" : "%d-%d", begin, end-1); - } - if (res < 0) { - hwloc_bitmap_free(reverse); - return -1; - } - ret += res; - - if (res >= size) - res = size>0 ? (int)size - 1 : 0; - - tmp += res; - size -= res; - needcomma = 1; - - if (end == -1) - break; - else - prev = end - 1; - } - - hwloc_bitmap_free(reverse); - - return ret; -} - -int hwloc_bitmap_list_asprintf(char ** strp, const struct hwloc_bitmap_s * __hwloc_restrict set) -{ - int len; - char *buf; - - HWLOC__BITMAP_CHECK(set); - - len = hwloc_bitmap_list_snprintf(NULL, 0, set); - buf = malloc(len+1); - *strp = buf; - return hwloc_bitmap_list_snprintf(buf, len+1, set); -} - -int hwloc_bitmap_list_sscanf(struct hwloc_bitmap_s *set, const char * __hwloc_restrict string) -{ - const char * current = string; - char *next; - long begin = -1, val; - - hwloc_bitmap_zero(set); - - while (*current != '\0') { - - /* ignore empty ranges */ - while (*current == ',') - current++; - - val = strtoul(current, &next, 0); - /* make sure we got at least one digit */ - if (next == current) - goto failed; - - if (begin != -1) { - /* finishing a range */ - hwloc_bitmap_set_range(set, begin, val); - begin = -1; - - } else if (*next == '-') { - /* starting a new range */ - if (*(next+1) == '\0') { - /* infinite range */ - hwloc_bitmap_set_range(set, val, -1); - break; - } else { - /* normal range */ - begin = val; - } - - } else if (*next == ',' || *next == '\0') { - /* single digit */ - hwloc_bitmap_set(set, val); - } - - if (*next == '\0') - break; - current = next+1; - } - - return 0; - - failed: - /* failure to parse */ - hwloc_bitmap_zero(set); - return -1; -} - -int hwloc_bitmap_taskset_snprintf(char * __hwloc_restrict buf, size_t buflen, const struct hwloc_bitmap_s * __hwloc_restrict set) -{ - ssize_t size = buflen; - char *tmp = buf; - int res, ret = 0; - int started = 0; - int i; - - HWLOC__BITMAP_CHECK(set); - - /* mark the end in case we do nothing later */ - if (buflen > 0) - tmp[0] = '\0'; - - if (set->infinite) { - res = hwloc_snprintf(tmp, size, "0xf...f"); - started = 1; - if (res < 0) - return -1; - ret += res; - if (res >= size) - res = size>0 ? (int)size - 1 : 0; - tmp += res; - size -= res; - } - - i=set->ulongs_count-1; - - if (set->infinite) { - /* ignore starting FULL since we have 0xf...f already */ - while (i>=0 && set->ulongs[i] == HWLOC_SUBBITMAP_FULL) - i--; - } else { - /* ignore starting ZERO except the last one */ - while (i>=1 && set->ulongs[i] == HWLOC_SUBBITMAP_ZERO) - i--; - } - - while (i>=0) { - unsigned long val = set->ulongs[i--]; - if (started) { - /* print the whole subset */ -#if HWLOC_BITS_PER_LONG == 64 - res = hwloc_snprintf(tmp, size, "%016lx", val); -#else - res = hwloc_snprintf(tmp, size, "%08lx", val); -#endif - } else if (val || i == -1) { - res = hwloc_snprintf(tmp, size, "0x%lx", val); - started = 1; - } else { - res = 0; - } - if (res < 0) - return -1; - ret += res; - if (res >= size) - res = size>0 ? (int)size - 1 : 0; - tmp += res; - size -= res; - } - - /* if didn't display anything, display 0x0 */ - if (!ret) { - res = hwloc_snprintf(tmp, size, "0x0"); - if (res < 0) - return -1; - ret += res; - } - - return ret; -} - -int hwloc_bitmap_taskset_asprintf(char ** strp, const struct hwloc_bitmap_s * __hwloc_restrict set) -{ - int len; - char *buf; - - HWLOC__BITMAP_CHECK(set); - - len = hwloc_bitmap_taskset_snprintf(NULL, 0, set); - buf = malloc(len+1); - *strp = buf; - return hwloc_bitmap_taskset_snprintf(buf, len+1, set); -} - -int hwloc_bitmap_taskset_sscanf(struct hwloc_bitmap_s *set, const char * __hwloc_restrict string) -{ - const char * current = string; - int chars; - int count; - int infinite = 0; - - current = string; - if (!strncmp("0xf...f", current, 7)) { - /* infinite bitmap */ - infinite = 1; - current += 7; - if (*current == '\0') { - /* special case for infinite/full bitmap */ - hwloc_bitmap_fill(set); - return 0; - } - } else { - /* finite bitmap */ - if (!strncmp("0x", current, 2)) - current += 2; - if (*current == '\0') { - /* special case for empty bitmap */ - hwloc_bitmap_zero(set); - return 0; - } - } - /* we know there are other characters now */ - - chars = (int)strlen(current); - count = (chars * 4 + HWLOC_BITS_PER_LONG - 1) / HWLOC_BITS_PER_LONG; - - hwloc_bitmap_reset_by_ulongs(set, count); - set->infinite = 0; - - while (*current != '\0') { - int tmpchars; - char ustr[17]; - unsigned long val; - char *next; - - tmpchars = chars % (HWLOC_BITS_PER_LONG/4); - if (!tmpchars) - tmpchars = (HWLOC_BITS_PER_LONG/4); - - memcpy(ustr, current, tmpchars); - ustr[tmpchars] = '\0'; - val = strtoul(ustr, &next, 16); - if (*next != '\0') - goto failed; - - set->ulongs[count-1] = val; - - current += tmpchars; - chars -= tmpchars; - count--; - } - - set->infinite = infinite; /* set at the end, to avoid spurious realloc with filled new ulongs */ - - return 0; - - failed: - /* failure to parse */ - hwloc_bitmap_zero(set); - return -1; -} - -static void hwloc_bitmap__zero(struct hwloc_bitmap_s *set) -{ - unsigned i; - for(i=0; iulongs_count; i++) - set->ulongs[i] = HWLOC_SUBBITMAP_ZERO; - set->infinite = 0; -} - -void hwloc_bitmap_zero(struct hwloc_bitmap_s * set) -{ - HWLOC__BITMAP_CHECK(set); - - hwloc_bitmap_reset_by_ulongs(set, 1); - hwloc_bitmap__zero(set); -} - -static void hwloc_bitmap__fill(struct hwloc_bitmap_s * set) -{ - unsigned i; - for(i=0; iulongs_count; i++) - set->ulongs[i] = HWLOC_SUBBITMAP_FULL; - set->infinite = 1; -} - -void hwloc_bitmap_fill(struct hwloc_bitmap_s * set) -{ - HWLOC__BITMAP_CHECK(set); - - hwloc_bitmap_reset_by_ulongs(set, 1); - hwloc_bitmap__fill(set); -} - -void hwloc_bitmap_from_ulong(struct hwloc_bitmap_s *set, unsigned long mask) -{ - HWLOC__BITMAP_CHECK(set); - - hwloc_bitmap_reset_by_ulongs(set, 1); - set->ulongs[0] = mask; /* there's always at least one ulong allocated */ - set->infinite = 0; -} - -void hwloc_bitmap_from_ith_ulong(struct hwloc_bitmap_s *set, unsigned i, unsigned long mask) -{ - unsigned j; - - HWLOC__BITMAP_CHECK(set); - - hwloc_bitmap_reset_by_ulongs(set, i+1); - set->ulongs[i] = mask; - for(j=0; julongs[j] = HWLOC_SUBBITMAP_ZERO; - set->infinite = 0; -} - -unsigned long hwloc_bitmap_to_ulong(const struct hwloc_bitmap_s *set) -{ - HWLOC__BITMAP_CHECK(set); - - return set->ulongs[0]; /* there's always at least one ulong allocated */ -} - -unsigned long hwloc_bitmap_to_ith_ulong(const struct hwloc_bitmap_s *set, unsigned i) -{ - HWLOC__BITMAP_CHECK(set); - - return HWLOC_SUBBITMAP_READULONG(set, i); -} - -void hwloc_bitmap_only(struct hwloc_bitmap_s * set, unsigned cpu) -{ - unsigned index_ = HWLOC_SUBBITMAP_INDEX(cpu); - - HWLOC__BITMAP_CHECK(set); - - hwloc_bitmap_reset_by_cpu_index(set, cpu); - hwloc_bitmap__zero(set); - set->ulongs[index_] |= HWLOC_SUBBITMAP_CPU(cpu); -} - -void hwloc_bitmap_allbut(struct hwloc_bitmap_s * set, unsigned cpu) -{ - unsigned index_ = HWLOC_SUBBITMAP_INDEX(cpu); - - HWLOC__BITMAP_CHECK(set); - - hwloc_bitmap_reset_by_cpu_index(set, cpu); - hwloc_bitmap__fill(set); - set->ulongs[index_] &= ~HWLOC_SUBBITMAP_CPU(cpu); -} - -void hwloc_bitmap_set(struct hwloc_bitmap_s * set, unsigned cpu) -{ - unsigned index_ = HWLOC_SUBBITMAP_INDEX(cpu); - - HWLOC__BITMAP_CHECK(set); - - /* nothing to do if setting inside the infinite part of the bitmap */ - if (set->infinite && cpu >= set->ulongs_count * HWLOC_BITS_PER_LONG) - return; - - hwloc_bitmap_realloc_by_cpu_index(set, cpu); - set->ulongs[index_] |= HWLOC_SUBBITMAP_CPU(cpu); -} - -void hwloc_bitmap_set_range(struct hwloc_bitmap_s * set, unsigned begincpu, int _endcpu) -{ - unsigned i; - unsigned beginset,endset; - unsigned endcpu = (unsigned) _endcpu; - - HWLOC__BITMAP_CHECK(set); - - if (endcpu < begincpu) - return; - if (set->infinite && begincpu >= set->ulongs_count * HWLOC_BITS_PER_LONG) - /* setting only in the already-set infinite part, nothing to do */ - return; - - if (_endcpu == -1) { - /* infinite range */ - - /* make sure we can play with the ulong that contains begincpu */ - hwloc_bitmap_realloc_by_cpu_index(set, begincpu); - /* update the ulong that contains begincpu */ - beginset = HWLOC_SUBBITMAP_INDEX(begincpu); - set->ulongs[beginset] |= HWLOC_SUBBITMAP_ULBIT_FROM(HWLOC_SUBBITMAP_CPU_ULBIT(begincpu)); - /* set ulongs after begincpu if any already allocated */ - for(i=beginset+1; iulongs_count; i++) - set->ulongs[i] = HWLOC_SUBBITMAP_FULL; - /* mark the infinity as set */ - set->infinite = 1; - } else { - /* finite range */ - - /* ignore the part of the range that overlaps with the already-set infinite part */ - if (set->infinite && endcpu >= set->ulongs_count * HWLOC_BITS_PER_LONG) - endcpu = set->ulongs_count * HWLOC_BITS_PER_LONG - 1; - /* make sure we can play with the ulongs that contain begincpu and endcpu */ - hwloc_bitmap_realloc_by_cpu_index(set, endcpu); - /* update first and last ulongs */ - beginset = HWLOC_SUBBITMAP_INDEX(begincpu); - endset = HWLOC_SUBBITMAP_INDEX(endcpu); - if (beginset == endset) { - set->ulongs[beginset] |= HWLOC_SUBBITMAP_ULBIT_FROMTO(HWLOC_SUBBITMAP_CPU_ULBIT(begincpu), HWLOC_SUBBITMAP_CPU_ULBIT(endcpu)); - } else { - set->ulongs[beginset] |= HWLOC_SUBBITMAP_ULBIT_FROM(HWLOC_SUBBITMAP_CPU_ULBIT(begincpu)); - set->ulongs[endset] |= HWLOC_SUBBITMAP_ULBIT_TO(HWLOC_SUBBITMAP_CPU_ULBIT(endcpu)); - } - /* set ulongs in the middle of the range */ - for(i=beginset+1; iulongs[i] = HWLOC_SUBBITMAP_FULL; - } -} - -void hwloc_bitmap_set_ith_ulong(struct hwloc_bitmap_s *set, unsigned i, unsigned long mask) -{ - HWLOC__BITMAP_CHECK(set); - - hwloc_bitmap_realloc_by_ulongs(set, i+1); - set->ulongs[i] = mask; -} - -void hwloc_bitmap_clr(struct hwloc_bitmap_s * set, unsigned cpu) -{ - unsigned index_ = HWLOC_SUBBITMAP_INDEX(cpu); - - HWLOC__BITMAP_CHECK(set); - - /* nothing to do if clearing inside the infinitely-unset part of the bitmap */ - if (!set->infinite && cpu >= set->ulongs_count * HWLOC_BITS_PER_LONG) - return; - - hwloc_bitmap_realloc_by_cpu_index(set, cpu); - set->ulongs[index_] &= ~HWLOC_SUBBITMAP_CPU(cpu); -} - -void hwloc_bitmap_clr_range(struct hwloc_bitmap_s * set, unsigned begincpu, int _endcpu) -{ - unsigned i; - unsigned beginset,endset; - unsigned endcpu = (unsigned) _endcpu; - - HWLOC__BITMAP_CHECK(set); - - if (endcpu < begincpu) - return; - - if (!set->infinite && begincpu >= set->ulongs_count * HWLOC_BITS_PER_LONG) - /* clearing only in the already-unset infinite part, nothing to do */ - return; - - if (_endcpu == -1) { - /* infinite range */ - - /* make sure we can play with the ulong that contains begincpu */ - hwloc_bitmap_realloc_by_cpu_index(set, begincpu); - /* update the ulong that contains begincpu */ - beginset = HWLOC_SUBBITMAP_INDEX(begincpu); - set->ulongs[beginset] &= ~HWLOC_SUBBITMAP_ULBIT_FROM(HWLOC_SUBBITMAP_CPU_ULBIT(begincpu)); - /* clear ulong after begincpu if any already allocated */ - for(i=beginset+1; iulongs_count; i++) - set->ulongs[i] = HWLOC_SUBBITMAP_ZERO; - /* mark the infinity as unset */ - set->infinite = 0; - } else { - /* finite range */ - - /* ignore the part of the range that overlaps with the already-unset infinite part */ - if (!set->infinite && endcpu >= set->ulongs_count * HWLOC_BITS_PER_LONG) - endcpu = set->ulongs_count * HWLOC_BITS_PER_LONG - 1; - /* make sure we can play with the ulongs that contain begincpu and endcpu */ - hwloc_bitmap_realloc_by_cpu_index(set, endcpu); - /* update first and last ulongs */ - beginset = HWLOC_SUBBITMAP_INDEX(begincpu); - endset = HWLOC_SUBBITMAP_INDEX(endcpu); - if (beginset == endset) { - set->ulongs[beginset] &= ~HWLOC_SUBBITMAP_ULBIT_FROMTO(HWLOC_SUBBITMAP_CPU_ULBIT(begincpu), HWLOC_SUBBITMAP_CPU_ULBIT(endcpu)); - } else { - set->ulongs[beginset] &= ~HWLOC_SUBBITMAP_ULBIT_FROM(HWLOC_SUBBITMAP_CPU_ULBIT(begincpu)); - set->ulongs[endset] &= ~HWLOC_SUBBITMAP_ULBIT_TO(HWLOC_SUBBITMAP_CPU_ULBIT(endcpu)); - } - /* clear ulongs in the middle of the range */ - for(i=beginset+1; iulongs[i] = HWLOC_SUBBITMAP_ZERO; - } -} - -int hwloc_bitmap_isset(const struct hwloc_bitmap_s * set, unsigned cpu) -{ - unsigned index_ = HWLOC_SUBBITMAP_INDEX(cpu); - - HWLOC__BITMAP_CHECK(set); - - return (HWLOC_SUBBITMAP_READULONG(set, index_) & HWLOC_SUBBITMAP_CPU(cpu)) != 0; -} - -int hwloc_bitmap_iszero(const struct hwloc_bitmap_s *set) -{ - unsigned i; - - HWLOC__BITMAP_CHECK(set); - - if (set->infinite) - return 0; - for(i=0; iulongs_count; i++) - if (set->ulongs[i] != HWLOC_SUBBITMAP_ZERO) - return 0; - return 1; -} - -int hwloc_bitmap_isfull(const struct hwloc_bitmap_s *set) -{ - unsigned i; - - HWLOC__BITMAP_CHECK(set); - - if (!set->infinite) - return 0; - for(i=0; iulongs_count; i++) - if (set->ulongs[i] != HWLOC_SUBBITMAP_FULL) - return 0; - return 1; -} - -int hwloc_bitmap_isequal (const struct hwloc_bitmap_s *set1, const struct hwloc_bitmap_s *set2) -{ - unsigned count1 = set1->ulongs_count; - unsigned count2 = set2->ulongs_count; - unsigned min_count = count1 < count2 ? count1 : count2; - unsigned i; - - HWLOC__BITMAP_CHECK(set1); - HWLOC__BITMAP_CHECK(set2); - - for(i=0; iulongs[i] != set2->ulongs[i]) - return 0; - - if (count1 != count2) { - unsigned long w1 = set1->infinite ? HWLOC_SUBBITMAP_FULL : HWLOC_SUBBITMAP_ZERO; - unsigned long w2 = set2->infinite ? HWLOC_SUBBITMAP_FULL : HWLOC_SUBBITMAP_ZERO; - for(i=min_count; iulongs[i] != w2) - return 0; - } - for(i=min_count; iulongs[i] != w1) - return 0; - } - } - - if (set1->infinite != set2->infinite) - return 0; - - return 1; -} - -int hwloc_bitmap_intersects (const struct hwloc_bitmap_s *set1, const struct hwloc_bitmap_s *set2) -{ - unsigned count1 = set1->ulongs_count; - unsigned count2 = set2->ulongs_count; - unsigned min_count = count1 < count2 ? count1 : count2; - unsigned i; - - HWLOC__BITMAP_CHECK(set1); - HWLOC__BITMAP_CHECK(set2); - - for(i=0; iulongs[i] & set2->ulongs[i]) - return 1; - - if (count1 != count2) { - if (set2->infinite) { - for(i=min_count; iulongs_count; i++) - if (set1->ulongs[i]) - return 1; - } - if (set1->infinite) { - for(i=min_count; iulongs_count; i++) - if (set2->ulongs[i]) - return 1; - } - } - - if (set1->infinite && set2->infinite) - return 1; - - return 0; -} - -int hwloc_bitmap_isincluded (const struct hwloc_bitmap_s *sub_set, const struct hwloc_bitmap_s *super_set) -{ - unsigned super_count = super_set->ulongs_count; - unsigned sub_count = sub_set->ulongs_count; - unsigned min_count = super_count < sub_count ? super_count : sub_count; - unsigned i; - - HWLOC__BITMAP_CHECK(sub_set); - HWLOC__BITMAP_CHECK(super_set); - - for(i=0; iulongs[i] != (super_set->ulongs[i] | sub_set->ulongs[i])) - return 0; - - if (super_count != sub_count) { - if (!super_set->infinite) - for(i=min_count; iulongs[i]) - return 0; - if (sub_set->infinite) - for(i=min_count; iulongs[i] != HWLOC_SUBBITMAP_FULL) - return 0; - } - - if (sub_set->infinite && !super_set->infinite) - return 0; - - return 1; -} - -void hwloc_bitmap_or (struct hwloc_bitmap_s *res, const struct hwloc_bitmap_s *set1, const struct hwloc_bitmap_s *set2) -{ - /* cache counts so that we can reset res even if it's also set1 or set2 */ - unsigned count1 = set1->ulongs_count; - unsigned count2 = set2->ulongs_count; - unsigned max_count = count1 > count2 ? count1 : count2; - unsigned min_count = count1 + count2 - max_count; - unsigned i; - - HWLOC__BITMAP_CHECK(res); - HWLOC__BITMAP_CHECK(set1); - HWLOC__BITMAP_CHECK(set2); - - hwloc_bitmap_reset_by_ulongs(res, max_count); - - for(i=0; iulongs[i] = set1->ulongs[i] | set2->ulongs[i]; - - if (count1 != count2) { - if (min_count < count1) { - if (set2->infinite) { - res->ulongs_count = min_count; - } else { - for(i=min_count; iulongs[i] = set1->ulongs[i]; - } - } else { - if (set1->infinite) { - res->ulongs_count = min_count; - } else { - for(i=min_count; iulongs[i] = set2->ulongs[i]; - } - } - } - - res->infinite = set1->infinite || set2->infinite; -} - -void hwloc_bitmap_and (struct hwloc_bitmap_s *res, const struct hwloc_bitmap_s *set1, const struct hwloc_bitmap_s *set2) -{ - /* cache counts so that we can reset res even if it's also set1 or set2 */ - unsigned count1 = set1->ulongs_count; - unsigned count2 = set2->ulongs_count; - unsigned max_count = count1 > count2 ? count1 : count2; - unsigned min_count = count1 + count2 - max_count; - unsigned i; - - HWLOC__BITMAP_CHECK(res); - HWLOC__BITMAP_CHECK(set1); - HWLOC__BITMAP_CHECK(set2); - - hwloc_bitmap_reset_by_ulongs(res, max_count); - - for(i=0; iulongs[i] = set1->ulongs[i] & set2->ulongs[i]; - - if (count1 != count2) { - if (min_count < count1) { - if (set2->infinite) { - for(i=min_count; iulongs[i] = set1->ulongs[i]; - } else { - res->ulongs_count = min_count; - } - } else { - if (set1->infinite) { - for(i=min_count; iulongs[i] = set2->ulongs[i]; - } else { - res->ulongs_count = min_count; - } - } - } - - res->infinite = set1->infinite && set2->infinite; -} - -void hwloc_bitmap_andnot (struct hwloc_bitmap_s *res, const struct hwloc_bitmap_s *set1, const struct hwloc_bitmap_s *set2) -{ - /* cache counts so that we can reset res even if it's also set1 or set2 */ - unsigned count1 = set1->ulongs_count; - unsigned count2 = set2->ulongs_count; - unsigned max_count = count1 > count2 ? count1 : count2; - unsigned min_count = count1 + count2 - max_count; - unsigned i; - - HWLOC__BITMAP_CHECK(res); - HWLOC__BITMAP_CHECK(set1); - HWLOC__BITMAP_CHECK(set2); - - hwloc_bitmap_reset_by_ulongs(res, max_count); - - for(i=0; iulongs[i] = set1->ulongs[i] & ~set2->ulongs[i]; - - if (count1 != count2) { - if (min_count < count1) { - if (!set2->infinite) { - for(i=min_count; iulongs[i] = set1->ulongs[i]; - } else { - res->ulongs_count = min_count; - } - } else { - if (set1->infinite) { - for(i=min_count; iulongs[i] = ~set2->ulongs[i]; - } else { - res->ulongs_count = min_count; - } - } - } - - res->infinite = set1->infinite && !set2->infinite; -} - -void hwloc_bitmap_xor (struct hwloc_bitmap_s *res, const struct hwloc_bitmap_s *set1, const struct hwloc_bitmap_s *set2) -{ - /* cache counts so that we can reset res even if it's also set1 or set2 */ - unsigned count1 = set1->ulongs_count; - unsigned count2 = set2->ulongs_count; - unsigned max_count = count1 > count2 ? count1 : count2; - unsigned min_count = count1 + count2 - max_count; - unsigned i; - - HWLOC__BITMAP_CHECK(res); - HWLOC__BITMAP_CHECK(set1); - HWLOC__BITMAP_CHECK(set2); - - hwloc_bitmap_reset_by_ulongs(res, max_count); - - for(i=0; iulongs[i] = set1->ulongs[i] ^ set2->ulongs[i]; - - if (count1 != count2) { - if (min_count < count1) { - unsigned long w2 = set2->infinite ? HWLOC_SUBBITMAP_FULL : HWLOC_SUBBITMAP_ZERO; - for(i=min_count; iulongs[i] = set1->ulongs[i] ^ w2; - } else { - unsigned long w1 = set1->infinite ? HWLOC_SUBBITMAP_FULL : HWLOC_SUBBITMAP_ZERO; - for(i=min_count; iulongs[i] = set2->ulongs[i] ^ w1; - } - } - - res->infinite = (!set1->infinite) != (!set2->infinite); -} - -void hwloc_bitmap_not (struct hwloc_bitmap_s *res, const struct hwloc_bitmap_s *set) -{ - unsigned count = set->ulongs_count; - unsigned i; - - HWLOC__BITMAP_CHECK(res); - HWLOC__BITMAP_CHECK(set); - - hwloc_bitmap_reset_by_ulongs(res, count); - - for(i=0; iulongs[i] = ~set->ulongs[i]; - - res->infinite = !set->infinite; -} - -int hwloc_bitmap_first(const struct hwloc_bitmap_s * set) -{ - unsigned i; - - HWLOC__BITMAP_CHECK(set); - - for(i=0; iulongs_count; i++) { - /* subsets are unsigned longs, use ffsl */ - unsigned long w = set->ulongs[i]; - if (w) - return hwloc_ffsl(w) - 1 + HWLOC_BITS_PER_LONG*i; - } - - if (set->infinite) - return set->ulongs_count * HWLOC_BITS_PER_LONG; - - return -1; -} - -int hwloc_bitmap_last(const struct hwloc_bitmap_s * set) -{ - int i; - - HWLOC__BITMAP_CHECK(set); - - if (set->infinite) - return -1; - - for(i=set->ulongs_count-1; i>=0; i--) { - /* subsets are unsigned longs, use flsl */ - unsigned long w = set->ulongs[i]; - if (w) - return hwloc_flsl(w) - 1 + HWLOC_BITS_PER_LONG*i; - } - - return -1; -} - -int hwloc_bitmap_next(const struct hwloc_bitmap_s * set, int prev_cpu) -{ - unsigned i = HWLOC_SUBBITMAP_INDEX(prev_cpu + 1); - - HWLOC__BITMAP_CHECK(set); - - if (i >= set->ulongs_count) { - if (set->infinite) - return prev_cpu + 1; - else - return -1; - } - - for(; iulongs_count; i++) { - /* subsets are unsigned longs, use ffsl */ - unsigned long w = set->ulongs[i]; - - /* if the prev cpu is in the same word as the possible next one, - we need to mask out previous cpus */ - if (prev_cpu >= 0 && HWLOC_SUBBITMAP_INDEX((unsigned) prev_cpu) == i) - w &= ~HWLOC_SUBBITMAP_ULBIT_TO(HWLOC_SUBBITMAP_CPU_ULBIT(prev_cpu)); - - if (w) - return hwloc_ffsl(w) - 1 + HWLOC_BITS_PER_LONG*i; - } - - if (set->infinite) - return set->ulongs_count * HWLOC_BITS_PER_LONG; - - return -1; -} - -void hwloc_bitmap_singlify(struct hwloc_bitmap_s * set) -{ - unsigned i; - int found = 0; - - HWLOC__BITMAP_CHECK(set); - - for(i=0; iulongs_count; i++) { - if (found) { - set->ulongs[i] = HWLOC_SUBBITMAP_ZERO; - continue; - } else { - /* subsets are unsigned longs, use ffsl */ - unsigned long w = set->ulongs[i]; - if (w) { - int _ffs = hwloc_ffsl(w); - set->ulongs[i] = HWLOC_SUBBITMAP_CPU(_ffs-1); - found = 1; - } - } - } - - if (set->infinite) { - if (found) { - set->infinite = 0; - } else { - /* set the first non allocated bit */ - unsigned first = set->ulongs_count * HWLOC_BITS_PER_LONG; - set->infinite = 0; /* do not let realloc fill the newly allocated sets */ - hwloc_bitmap_set(set, first); - } - } -} - -int hwloc_bitmap_compare_first(const struct hwloc_bitmap_s * set1, const struct hwloc_bitmap_s * set2) -{ - unsigned count1 = set1->ulongs_count; - unsigned count2 = set2->ulongs_count; - unsigned max_count = count1 > count2 ? count1 : count2; - unsigned min_count = count1 + count2 - max_count; - unsigned i; - - HWLOC__BITMAP_CHECK(set1); - HWLOC__BITMAP_CHECK(set2); - - for(i=0; iulongs[i]; - unsigned long w2 = set2->ulongs[i]; - if (w1 || w2) { - int _ffs1 = hwloc_ffsl(w1); - int _ffs2 = hwloc_ffsl(w2); - /* if both have a bit set, compare for real */ - if (_ffs1 && _ffs2) - return _ffs1-_ffs2; - /* one is empty, and it is considered higher, so reverse-compare them */ - return _ffs2-_ffs1; - } - } - - if (count1 != count2) { - if (min_count < count2) { - for(i=min_count; iulongs[i]; - if (set1->infinite) - return -!(w2 & 1); - else if (w2) - return 1; - } - } else { - for(i=min_count; iulongs[i]; - if (set2->infinite) - return !(w1 & 1); - else if (w1) - return -1; - } - } - } - - return !!set1->infinite - !!set2->infinite; -} - -int hwloc_bitmap_compare(const struct hwloc_bitmap_s * set1, const struct hwloc_bitmap_s * set2) -{ - unsigned count1 = set1->ulongs_count; - unsigned count2 = set2->ulongs_count; - unsigned max_count = count1 > count2 ? count1 : count2; - unsigned min_count = count1 + count2 - max_count; - int i; - - HWLOC__BITMAP_CHECK(set1); - HWLOC__BITMAP_CHECK(set2); - - if ((!set1->infinite) != (!set2->infinite)) - return !!set1->infinite - !!set2->infinite; - - if (count1 != count2) { - if (min_count < count2) { - unsigned long val1 = set1->infinite ? HWLOC_SUBBITMAP_FULL : HWLOC_SUBBITMAP_ZERO; - for(i=max_count-1; i>=(signed) min_count; i--) { - unsigned long val2 = set2->ulongs[i]; - if (val1 == val2) - continue; - return val1 < val2 ? -1 : 1; - } - } else { - unsigned long val2 = set2->infinite ? HWLOC_SUBBITMAP_FULL : HWLOC_SUBBITMAP_ZERO; - for(i=max_count-1; i>=(signed) min_count; i--) { - unsigned long val1 = set1->ulongs[i]; - if (val1 == val2) - continue; - return val1 < val2 ? -1 : 1; - } - } - } - - for(i=min_count-1; i>=0; i--) { - unsigned long val1 = set1->ulongs[i]; - unsigned long val2 = set2->ulongs[i]; - if (val1 == val2) - continue; - return val1 < val2 ? -1 : 1; - } - - return 0; -} - -int hwloc_bitmap_weight(const struct hwloc_bitmap_s * set) -{ - int weight = 0; - unsigned i; - - HWLOC__BITMAP_CHECK(set); - - if (set->infinite) - return -1; - - for(i=0; iulongs_count; i++) - weight += hwloc_weight_long(set->ulongs[i]); - return weight; -} - -int hwloc_bitmap_compare_inclusion(const struct hwloc_bitmap_s * set1, const struct hwloc_bitmap_s * set2) -{ - unsigned max_count = set1->ulongs_count > set2->ulongs_count ? set1->ulongs_count : set2->ulongs_count; - int result = HWLOC_BITMAP_EQUAL; /* means empty sets return equal */ - int empty1 = 1; - int empty2 = 1; - unsigned i; - - HWLOC__BITMAP_CHECK(set1); - HWLOC__BITMAP_CHECK(set2); - - for(i=0; iinfinite) { - if (set2->infinite) { - /* set2 infinite only */ - if (result == HWLOC_BITMAP_CONTAINS) { - if (!empty2) - return HWLOC_BITMAP_INTERSECTS; - result = HWLOC_BITMAP_DIFFERENT; - } else if (result == HWLOC_BITMAP_EQUAL) { - result = HWLOC_BITMAP_INCLUDED; - } - /* no change otherwise */ - } - } else if (!set2->infinite) { - /* set1 infinite only */ - if (result == HWLOC_BITMAP_INCLUDED) { - if (!empty1) - return HWLOC_BITMAP_INTERSECTS; - result = HWLOC_BITMAP_DIFFERENT; - } else if (result == HWLOC_BITMAP_EQUAL) { - result = HWLOC_BITMAP_CONTAINS; - } - /* no change otherwise */ - } else { - /* both infinite */ - if (result == HWLOC_BITMAP_DIFFERENT) - return HWLOC_BITMAP_INTERSECTS; - /* equal/contains/included unchanged */ - } - - return result; -} diff --git a/opal/mca/hwloc/hwloc1116/hwloc/src/diff.c b/opal/mca/hwloc/hwloc1116/hwloc/src/diff.c deleted file mode 100644 index 060aa93f55..0000000000 --- a/opal/mca/hwloc/hwloc1116/hwloc/src/diff.c +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Copyright © 2013-2014 Inria. All rights reserved. - * See COPYING in top-level directory. - */ - -#include -#include -#include - -int hwloc_topology_diff_destroy(hwloc_topology_t topology __hwloc_attribute_unused, - hwloc_topology_diff_t diff) -{ - hwloc_topology_diff_t next; - while (diff) { - next = diff->generic.next; - switch (diff->generic.type) { - default: - break; - case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR: - switch (diff->obj_attr.diff.generic.type) { - default: - break; - case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_NAME: - case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_INFO: - free(diff->obj_attr.diff.string.name); - free(diff->obj_attr.diff.string.oldvalue); - free(diff->obj_attr.diff.string.newvalue); - break; - } - break; - } - free(diff); - diff = next; - } - return 0; -} - -/************************ - * Computing diffs - */ - -static void hwloc_append_diff(hwloc_topology_diff_t newdiff, - hwloc_topology_diff_t *firstdiffp, - hwloc_topology_diff_t *lastdiffp) -{ - if (*firstdiffp) - (*lastdiffp)->generic.next = newdiff; - else - *firstdiffp = newdiff; - *lastdiffp = newdiff; - newdiff->generic.next = NULL; -} - -static int hwloc_append_diff_too_complex(hwloc_obj_t obj1, - hwloc_topology_diff_t *firstdiffp, - hwloc_topology_diff_t *lastdiffp) -{ - hwloc_topology_diff_t newdiff; - newdiff = malloc(sizeof(*newdiff)); - if (!newdiff) - return -1; - - newdiff->too_complex.type = HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX; - newdiff->too_complex.obj_depth = obj1->depth; - newdiff->too_complex.obj_index = obj1->logical_index; - hwloc_append_diff(newdiff, firstdiffp, lastdiffp); - return 0; -} - -static int hwloc_append_diff_obj_attr_string(hwloc_obj_t obj, - hwloc_topology_diff_obj_attr_type_t type, - const char *name, - const char *oldvalue, - const char *newvalue, - hwloc_topology_diff_t *firstdiffp, - hwloc_topology_diff_t *lastdiffp) -{ - hwloc_topology_diff_t newdiff; - - if (obj->type == HWLOC_OBJ_MISC) - /* TODO: add a custom level/depth for Misc */ - return hwloc_append_diff_too_complex(obj, firstdiffp, lastdiffp); - - newdiff = malloc(sizeof(*newdiff)); - if (!newdiff) - return -1; - - newdiff->obj_attr.type = HWLOC_TOPOLOGY_DIFF_OBJ_ATTR; - newdiff->obj_attr.obj_depth = obj->depth; - newdiff->obj_attr.obj_index = obj->logical_index; - newdiff->obj_attr.diff.string.type = type; - newdiff->obj_attr.diff.string.name = name ? strdup(name) : NULL; - newdiff->obj_attr.diff.string.oldvalue = oldvalue ? strdup(oldvalue) : NULL; - newdiff->obj_attr.diff.string.newvalue = newvalue ? strdup(newvalue) : NULL; - hwloc_append_diff(newdiff, firstdiffp, lastdiffp); - return 0; -} - -static int hwloc_append_diff_obj_attr_uint64(hwloc_obj_t obj, - hwloc_topology_diff_obj_attr_type_t type, - hwloc_uint64_t idx, - hwloc_uint64_t oldvalue, - hwloc_uint64_t newvalue, - hwloc_topology_diff_t *firstdiffp, - hwloc_topology_diff_t *lastdiffp) -{ - hwloc_topology_diff_t newdiff; - - if (obj->type == HWLOC_OBJ_MISC) - /* TODO: add a custom level/depth for Misc */ - return hwloc_append_diff_too_complex(obj, firstdiffp, lastdiffp); - - newdiff = malloc(sizeof(*newdiff)); - if (!newdiff) - return -1; - - newdiff->obj_attr.type = HWLOC_TOPOLOGY_DIFF_OBJ_ATTR; - newdiff->obj_attr.obj_depth = obj->depth; - newdiff->obj_attr.obj_index = obj->logical_index; - newdiff->obj_attr.diff.uint64.type = type; - newdiff->obj_attr.diff.uint64.index = idx; - newdiff->obj_attr.diff.uint64.oldvalue = oldvalue; - newdiff->obj_attr.diff.uint64.newvalue = newvalue; - hwloc_append_diff(newdiff, firstdiffp, lastdiffp); - return 0; -} - -static int -hwloc_diff_trees(hwloc_topology_t topo1, hwloc_obj_t obj1, - hwloc_topology_t topo2, hwloc_obj_t obj2, - unsigned flags, - hwloc_topology_diff_t *firstdiffp, hwloc_topology_diff_t *lastdiffp) -{ - unsigned i; - int err; - - if (obj1->depth != obj2->depth) - goto out_too_complex; - if (obj1->type != obj2->type) - goto out_too_complex; - - if (obj1->os_index != obj2->os_index) - /* we could allow different os_index for non-PU non-NUMAnode objects - * but it's likely useless anyway */ - goto out_too_complex; - -#define _SETS_DIFFERENT(_set1, _set2) \ - ( ( !(_set1) != !(_set2) ) \ - || ( (_set1) && !hwloc_bitmap_isequal(_set1, _set2) ) ) -#define SETS_DIFFERENT(_set, _obj1, _obj2) _SETS_DIFFERENT((_obj1)->_set, (_obj2)->_set) - if (SETS_DIFFERENT(cpuset, obj1, obj2) - || SETS_DIFFERENT(complete_cpuset, obj1, obj2) - || SETS_DIFFERENT(online_cpuset, obj1, obj2) - || SETS_DIFFERENT(allowed_cpuset, obj1, obj2) - || SETS_DIFFERENT(nodeset, obj1, obj2) - || SETS_DIFFERENT(complete_nodeset, obj1, obj2) - || SETS_DIFFERENT(allowed_nodeset, obj1, obj2)) - goto out_too_complex; - - /* no need to check logical_index, sibling_rank, symmetric_subtree, - * the parents did it */ - - if ((!obj1->name) != (!obj2->name) - || (obj1->name && strcmp(obj1->name, obj2->name))) { - err = hwloc_append_diff_obj_attr_string(obj1, - HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_NAME, - NULL, - obj1->name, - obj2->name, - firstdiffp, lastdiffp); - if (err < 0) - return err; - } - - /* memory */ - if (obj1->memory.local_memory != obj2->memory.local_memory) { - err = hwloc_append_diff_obj_attr_uint64(obj1, - HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_SIZE, - 0, - obj1->memory.local_memory, - obj2->memory.local_memory, - firstdiffp, lastdiffp); - if (err < 0) - return err; - } - /* ignore memory page_types */ - - /* ignore os_level */ - - /* type-specific attrs */ - switch (obj1->type) { - default: - break; - case HWLOC_OBJ_CACHE: - if (memcmp(obj1->attr, obj2->attr, sizeof(obj1->attr->cache))) - goto out_too_complex; - break; - case HWLOC_OBJ_GROUP: - if (memcmp(obj1->attr, obj2->attr, sizeof(obj1->attr->group))) - goto out_too_complex; - break; - case HWLOC_OBJ_PCI_DEVICE: - if (memcmp(obj1->attr, obj2->attr, sizeof(obj1->attr->pcidev))) - goto out_too_complex; - break; - case HWLOC_OBJ_BRIDGE: - if (memcmp(obj1->attr, obj2->attr, sizeof(obj1->attr->bridge))) - goto out_too_complex; - break; - case HWLOC_OBJ_OS_DEVICE: - if (memcmp(obj1->attr, obj2->attr, sizeof(obj1->attr->osdev))) - goto out_too_complex; - break; - } - - /* distances */ - if (obj1->distances_count != obj2->distances_count) - goto out_too_complex; - for(i=0; idistances_count; i++) { - struct hwloc_distances_s *d1 = obj1->distances[i], *d2 = obj2->distances[i]; - if (d1->relative_depth != d2->relative_depth - || d1->nbobjs != d2->nbobjs - || d1->latency_max != d2->latency_max - || d1->latency_base != d2->latency_base - || memcmp(d1->latency, d2->latency, d1->nbobjs * d1->nbobjs * sizeof(*d1->latency))) - goto out_too_complex; - } - - /* infos */ - if (obj1->infos_count != obj2->infos_count) - goto out_too_complex; - for(i=0; iinfos_count; i++) { - if (strcmp(obj1->infos[i].name, obj2->infos[i].name)) - goto out_too_complex; - if (strcmp(obj1->infos[i].value, obj2->infos[i].value)) { - err = hwloc_append_diff_obj_attr_string(obj1, - HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_INFO, - obj1->infos[i].name, - obj1->infos[i].value, - obj2->infos[i].value, - firstdiffp, lastdiffp); - if (err < 0) - return err; - } - } - - /* ignore userdata */ - - /* children */ - if (obj1->arity != obj2->arity) - goto out_too_complex; - for(i=0; iarity; i++) { - err = hwloc_diff_trees(topo1, obj1->children[i], - topo2, obj2->children[i], - flags, - firstdiffp, lastdiffp); - if (err < 0) - return err; - } - - return 0; - -out_too_complex: - hwloc_append_diff_too_complex(obj1, firstdiffp, lastdiffp); - return 0; -} - -int hwloc_topology_diff_build(hwloc_topology_t topo1, - hwloc_topology_t topo2, - unsigned long flags, - hwloc_topology_diff_t *diffp) -{ - hwloc_topology_diff_t lastdiff, tmpdiff; - int err; - - if (flags != 0) { - errno = EINVAL; - return -1; - } - - *diffp = NULL; - err = hwloc_diff_trees(topo1, hwloc_get_root_obj(topo1), - topo2, hwloc_get_root_obj(topo2), - flags, - diffp, &lastdiff); - - if (!err) { - tmpdiff = *diffp; - while (tmpdiff) { - if (tmpdiff->generic.type == HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX) { - err = 1; - break; - } - tmpdiff = tmpdiff->generic.next; - } - } - - return err; -} - -/******************** - * Applying diffs - */ - -static int -hwloc_apply_diff_one(hwloc_topology_t topology, - hwloc_topology_diff_t diff, - unsigned long flags) -{ - int reverse = !!(flags & HWLOC_TOPOLOGY_DIFF_APPLY_REVERSE); - - switch (diff->generic.type) { - case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR: { - struct hwloc_topology_diff_obj_attr_s *obj_attr = &diff->obj_attr; - hwloc_obj_t obj = hwloc_get_obj_by_depth(topology, obj_attr->obj_depth, obj_attr->obj_index); - if (!obj) - return -1; - - switch (obj_attr->diff.generic.type) { - case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_SIZE: { - hwloc_obj_t tmpobj; - hwloc_uint64_t oldvalue = reverse ? obj_attr->diff.uint64.newvalue : obj_attr->diff.uint64.oldvalue; - hwloc_uint64_t newvalue = reverse ? obj_attr->diff.uint64.oldvalue : obj_attr->diff.uint64.newvalue; - hwloc_uint64_t valuediff = newvalue - oldvalue; - if (obj->memory.local_memory != oldvalue) - return -1; - obj->memory.local_memory = newvalue; - tmpobj = obj; - while (tmpobj) { - tmpobj->memory.total_memory += valuediff; - tmpobj = tmpobj->parent; - } - break; - } - case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_NAME: { - const char *oldvalue = reverse ? obj_attr->diff.string.newvalue : obj_attr->diff.string.oldvalue; - const char *newvalue = reverse ? obj_attr->diff.string.oldvalue : obj_attr->diff.string.newvalue; - if (!obj->name || strcmp(obj->name, oldvalue)) - return -1; - free(obj->name); - obj->name = strdup(newvalue); - break; - } - case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_INFO: { - const char *name = obj_attr->diff.string.name; - const char *oldvalue = reverse ? obj_attr->diff.string.newvalue : obj_attr->diff.string.oldvalue; - const char *newvalue = reverse ? obj_attr->diff.string.oldvalue : obj_attr->diff.string.newvalue; - unsigned i; - int found = 0; - for(i=0; iinfos_count; i++) { - if (!strcmp(obj->infos[i].name, name) - && !strcmp(obj->infos[i].value, oldvalue)) { - free(obj->infos[i].value); - obj->infos[i].value = strdup(newvalue); - found = 1; - break; - } - } - if (!found) - return -1; - break; - } - default: - return -1; - } - - break; - } - default: - return -1; - } - - return 0; -} - -int hwloc_topology_diff_apply(hwloc_topology_t topology, - hwloc_topology_diff_t diff, - unsigned long flags) -{ - hwloc_topology_diff_t tmpdiff, tmpdiff2; - int err, nr; - - if (flags & ~HWLOC_TOPOLOGY_DIFF_APPLY_REVERSE) { - errno = EINVAL; - return -1; - } - - tmpdiff = diff; - nr = 0; - while (tmpdiff) { - nr++; - err = hwloc_apply_diff_one(topology, tmpdiff, flags); - if (err < 0) - goto cancel; - tmpdiff = tmpdiff->generic.next; - } - return 0; - -cancel: - tmpdiff2 = tmpdiff; - tmpdiff = diff; - while (tmpdiff != tmpdiff2) { - hwloc_apply_diff_one(topology, tmpdiff, flags ^ HWLOC_TOPOLOGY_DIFF_APPLY_REVERSE); - tmpdiff = tmpdiff->generic.next; - } - errno = EINVAL; - return -nr; /* return the index (starting at 1) of the first element that couldn't be applied */ -} diff --git a/opal/mca/hwloc/hwloc1116/hwloc/src/distances.c b/opal/mca/hwloc/hwloc1116/hwloc/src/distances.c deleted file mode 100644 index c725e3c976..0000000000 --- a/opal/mca/hwloc/hwloc1116/hwloc/src/distances.c +++ /dev/null @@ -1,1080 +0,0 @@ -/* - * Copyright © 2010-2016 Inria. All rights reserved. - * Copyright © 2011-2012 Université Bordeaux - * Copyright © 2011 Cisco Systems, Inc. All rights reserved. - * See COPYING in top-level directory. - */ - -#include -#include -#include -#include -#include - -#include -#include - -/************************** - * Main Init/Clear/Destroy - */ - -/* called during topology init */ -void hwloc_distances_init(struct hwloc_topology *topology) -{ - topology->first_osdist = topology->last_osdist = NULL; -} - -/* called during topology destroy */ -void hwloc_distances_destroy(struct hwloc_topology * topology) -{ - struct hwloc_os_distances_s *osdist, *next = topology->first_osdist; - while ((osdist = next) != NULL) { - next = osdist->next; - /* remove final distance matrics AND physically-ordered ones */ - free(osdist->indexes); - free(osdist->objs); - free(osdist->distances); - free(osdist); - } - topology->first_osdist = topology->last_osdist = NULL; -} - -/****************************************************** - * Inserting distances in the topology - * from a backend, from the environment or by the user - */ - -/* insert a distance matrix in the topology. - * the caller gives us those pointers, we take care of freeing them later and so on. - */ -void hwloc_distances_set(hwloc_topology_t __hwloc_restrict topology, hwloc_obj_type_t type, - unsigned nbobjs, unsigned *indexes, hwloc_obj_t *objs, float *distances, - int force) -{ - struct hwloc_os_distances_s *osdist, *next = topology->first_osdist; - /* look for existing distances for the same type */ - while ((osdist = next) != NULL) { - next = osdist->next; - if (osdist->type == type) { - if (osdist->forced && !force) { - /* there is a forced distance element, ignore the new non-forced one */ - free(indexes); - free(objs); - free(distances); - return; - } else if (force) { - /* we're forcing a new distance, remove the old ones */ - free(osdist->indexes); - free(osdist->objs); - free(osdist->distances); - /* remove current object */ - if (osdist->prev) - osdist->prev->next = next; - else - topology->first_osdist = next; - if (next) - next->prev = osdist->prev; - else - topology->last_osdist = osdist->prev; - /* free current object */ - free(osdist); - } - } - } - - if (!nbobjs) - /* we're just clearing, return now */ - return; - assert(nbobjs >= 2); - - /* create the new element */ - osdist = malloc(sizeof(struct hwloc_os_distances_s)); - osdist->nbobjs = nbobjs; - osdist->indexes = indexes; - osdist->objs = objs; - osdist->distances = distances; - osdist->forced = force; - osdist->type = type; - /* insert it */ - osdist->next = NULL; - osdist->prev = topology->last_osdist; - if (topology->last_osdist) - topology->last_osdist->next = osdist; - else - topology->first_osdist = osdist; - topology->last_osdist = osdist; -} - -/* make sure a user-given distance matrix is sane */ -static int hwloc_distances__check_matrix(hwloc_topology_t __hwloc_restrict topology __hwloc_attribute_unused, hwloc_obj_type_t type __hwloc_attribute_unused, - unsigned nbobjs, unsigned *indexes, hwloc_obj_t *objs __hwloc_attribute_unused, float *distances __hwloc_attribute_unused) -{ - unsigned i,j; - /* make sure we don't have the same index twice */ - for(i=0; i= 2) { - /* generate the matrix to create x groups of y elements */ - if (x*y*z != nbobjs) { - fprintf(stderr, "Ignoring %s distances from environment variable, invalid grouping (%u*%u*%u=%u instead of %u)\n", - hwloc_obj_type_string(type), x, y, z, x*y*z, nbobjs); - free(indexes); - free(distances); - return; - } - for(i=0; ifirst_osdist; osdist; osdist = osdist->next) { - /* remove the objs array, we'll rebuild it from the indexes - * depending on remaining objects */ - free(osdist->objs); - osdist->objs = NULL; - } -} - - -/* cleanup everything we created from distances so that we may rebuild them - * at the end of restrict() - */ -void hwloc_distances_restrict(struct hwloc_topology *topology, unsigned long flags) -{ - if (flags & HWLOC_RESTRICT_FLAG_ADAPT_DISTANCES) { - /* some objects may have been removed, clear objects arrays so that finalize_os rebuilds them properly */ - hwloc_distances_restrict_os(topology); - } else { - /* if not adapting distances, drop everything */ - hwloc_distances_destroy(topology); - } -} - -/************************************************************** - * Convert user/env given array of indexes into actual objects - */ - -static hwloc_obj_t hwloc_find_obj_by_type_and_os_index(hwloc_obj_t root, hwloc_obj_type_t type, unsigned os_index) -{ - hwloc_obj_t child; - if (root->type == type && root->os_index == os_index) - return root; - child = root->first_child; - while (child) { - hwloc_obj_t found = hwloc_find_obj_by_type_and_os_index(child, type, os_index); - if (found) - return found; - child = child->next_sibling; - } - return NULL; -} - -/* convert distance indexes that were previously stored in the topology - * into actual objects if not done already. - * it's already done when distances come from backends (this function should not be called then). - * it's not done when distances come from the user. - * - * returns -1 if the matrix was invalid - */ -static int -hwloc_distances__finalize_os(struct hwloc_topology *topology, struct hwloc_os_distances_s *osdist) -{ - unsigned nbobjs = osdist->nbobjs; - unsigned *indexes = osdist->indexes; - float *distances = osdist->distances; - unsigned i, j; - hwloc_obj_type_t type = osdist->type; - hwloc_obj_t *objs = calloc(nbobjs, sizeof(hwloc_obj_t)); - - assert(!osdist->objs); - - /* traverse the topology and look for the relevant objects */ - for(i=0; ilevels[0][0], type, indexes[i]); - if (!obj) { - - /* shift the matrix */ -#define OLDPOS(i,j) (distances+(i)*nbobjs+(j)) -#define NEWPOS(i,j) (distances+(i)*(nbobjs-1)+(j)) - if (i>0) { - /** no need to move beginning of 0th line */ - for(j=0; jnbobjs = nbobjs; - if (!nbobjs) { - /* the whole matrix was invalid, let the caller remove this distances */ - free(objs); - return -1; - } - - /* setup the objs array */ - osdist->objs = objs; - return 0; -} - - -void hwloc_distances_finalize_os(struct hwloc_topology *topology) -{ - int dropall = !topology->levels[0][0]->cpuset; /* we don't support distances on multinode systems */ - - struct hwloc_os_distances_s *osdist, *next = topology->first_osdist; - while ((osdist = next) != NULL) { - int err; - next = osdist->next; - - if (dropall) - goto drop; - - /* remove final distance matrics AND physically-ordered ones */ - - if (osdist->objs) - /* nothing to do, switch to the next element */ - continue; - - err = hwloc_distances__finalize_os(topology, osdist); - if (!err) - /* convert ok, switch to the next element */ - continue; - - drop: - /* remove this element */ - free(osdist->indexes); - free(osdist->distances); - /* remove current object */ - if (osdist->prev) - osdist->prev->next = next; - else - topology->first_osdist = next; - if (next) - next->prev = osdist->prev; - else - topology->last_osdist = osdist->prev; - /* free current object */ - free(osdist); - } -} - -/*********************************************************** - * Convert internal distances given by the backend/env/user - * into exported logical distances attached to objects - */ - -static void -hwloc_distances__finalize_logical(struct hwloc_topology *topology, - unsigned nbobjs, - hwloc_obj_t *objs, float *osmatrix) -{ - struct hwloc_distances_s ** tmpdistances; - unsigned i, j, li, lj, minl; - float min = FLT_MAX, max = FLT_MIN; - hwloc_obj_t root, obj; - float *matrix; - hwloc_cpuset_t cpuset, complete_cpuset; - hwloc_nodeset_t nodeset, complete_nodeset; - unsigned depth; - int idx; - - /* find the root */ - cpuset = hwloc_bitmap_alloc(); - complete_cpuset = hwloc_bitmap_alloc(); - nodeset = hwloc_bitmap_alloc(); - complete_nodeset = hwloc_bitmap_alloc(); - for(i=0; icpuset); - if (objs[i]->complete_cpuset) - hwloc_bitmap_or(complete_cpuset, complete_cpuset, objs[i]->complete_cpuset); - if (objs[i]->nodeset) - hwloc_bitmap_or(nodeset, nodeset, objs[i]->nodeset); - if (objs[i]->complete_nodeset) - hwloc_bitmap_or(complete_nodeset, complete_nodeset, objs[i]->complete_nodeset); - } - /* find the object covering cpuset, we'll take care of the nodeset later */ - root = hwloc_get_obj_covering_cpuset(topology, cpuset); - /* walk up to find a parent that also covers the nodeset */ - while (root && - (!hwloc_bitmap_isincluded(nodeset, root->nodeset) - || !hwloc_bitmap_isincluded(complete_nodeset, root->complete_nodeset) - || !hwloc_bitmap_isincluded(complete_cpuset, root->complete_cpuset))) - root = root->parent; - if (!root) { - /* should not happen, ignore the distance matrix and report an error. */ - if (!hwloc_hide_errors()) { - char *a, *b; - hwloc_bitmap_asprintf(&a, cpuset); - hwloc_bitmap_asprintf(&b, nodeset); - fprintf(stderr, "****************************************************************************\n"); - fprintf(stderr, "* hwloc %s has encountered an error when adding a distance matrix to the topology.\n", HWLOC_VERSION); - fprintf(stderr, "*\n"); - fprintf(stderr, "* hwloc_distances__finalize_logical() could not find any object covering\n"); - fprintf(stderr, "* cpuset %s and nodeset %s\n", a, b); - fprintf(stderr, "*\n"); - fprintf(stderr, "* Please report this error message to the hwloc user's mailing list,\n"); -#ifdef HWLOC_LINUX_SYS - fprintf(stderr, "* along with the output from the hwloc-gather-topology script.\n"); -#else - fprintf(stderr, "* along with any relevant topology information from your platform.\n"); -#endif - fprintf(stderr, "****************************************************************************\n"); - free(a); - free(b); - } - hwloc_bitmap_free(cpuset); - hwloc_bitmap_free(complete_cpuset); - hwloc_bitmap_free(nodeset); - hwloc_bitmap_free(complete_nodeset); - return; - } - /* don't attach to Misc objects */ - while (root->type == HWLOC_OBJ_MISC) - root = root->parent; - /* ideally, root has the exact cpuset and nodeset. - * but ignoring or other things that remove objects may cause the object array to reduce */ - assert(hwloc_bitmap_isincluded(cpuset, root->cpuset)); - assert(hwloc_bitmap_isincluded(complete_cpuset, root->complete_cpuset)); - assert(hwloc_bitmap_isincluded(nodeset, root->nodeset)); - assert(hwloc_bitmap_isincluded(complete_nodeset, root->complete_nodeset)); - hwloc_bitmap_free(cpuset); - hwloc_bitmap_free(complete_cpuset); - hwloc_bitmap_free(nodeset); - hwloc_bitmap_free(complete_nodeset); - depth = objs[0]->depth; /* this assume that we have distances between objects of the same level */ - if (root->depth >= depth) { - /* strange topology led us to find invalid relative depth, ignore */ - return; - } - - /* count objects at that depth that are below root. - * we can't use hwloc_get_nbobjs_inside_cpuset_by_depth() because it ignore CPU-less objects. - */ - i = 0; - obj = NULL; - while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL) { - hwloc_obj_t myparent = obj->parent; - while (myparent->depth > root->depth) - myparent = myparent->parent; - if (myparent == root) - i++; - } - if (i != nbobjs) - /* the root does not cover the right number of objects, maybe we failed to insert a root (bad intersect or so). */ - return; - - /* get the logical index offset, it's the min of all logical indexes */ - minl = UINT_MAX; - for(i=0; i objs[i]->logical_index) - minl = objs[i]->logical_index; - - /* compute/check min/max values */ - for(i=0; i max) - max = val; - } - if (!min) { - /* Linux up to 2.6.36 reports ACPI SLIT distances, which should be memory latencies. - * Except of SGI IP27 (SGI Origin 200/2000 with MIPS processors) where the distances - * are the number of hops between routers. - */ - hwloc_debug("%s", "minimal distance is 0, matrix does not seem to contain latencies, ignoring\n"); - return; - } - - /* store the normalized latency matrix in the root object */ - tmpdistances = realloc(root->distances, (root->distances_count+1) * sizeof(struct hwloc_distances_s *)); - if (!tmpdistances) - return; /* Failed to allocate, ignore this distance matrix */ - - root->distances = tmpdistances; - idx = root->distances_count++; - root->distances[idx] = malloc(sizeof(struct hwloc_distances_s)); - root->distances[idx]->relative_depth = depth - root->depth; - root->distances[idx]->nbobjs = nbobjs; - root->distances[idx]->latency = matrix = malloc(nbobjs*nbobjs*sizeof(float)); - root->distances[idx]->latency_base = (float) min; -#define NORMALIZE_LATENCY(d) ((d)/(min)) - root->distances[idx]->latency_max = NORMALIZE_LATENCY(max); - for(i=0; ilogical_index - minl; - matrix[li*nbobjs+li] = NORMALIZE_LATENCY(osmatrix[i*nbobjs+i]); - for(j=i+1; jlogical_index - minl; - matrix[li*nbobjs+lj] = NORMALIZE_LATENCY(osmatrix[i*nbobjs+j]); - matrix[lj*nbobjs+li] = NORMALIZE_LATENCY(osmatrix[j*nbobjs+i]); - } - } -} - -/* convert internal distances into logically-ordered distances - * that can be exposed in the API - */ -void -hwloc_distances_finalize_logical(struct hwloc_topology *topology) -{ - unsigned nbobjs; - int depth; - struct hwloc_os_distances_s * osdist; - for(osdist = topology->first_osdist; osdist; osdist = osdist->next) { - - nbobjs = osdist->nbobjs; - if (!nbobjs) - continue; - - depth = hwloc_get_type_depth(topology, osdist->type); - if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE) - continue; - - if (osdist->objs) { - assert(osdist->distances); - hwloc_distances__finalize_logical(topology, nbobjs, - osdist->objs, - osdist->distances); - } - } -} - -/*************************************************** - * Destroying logical distances attached to objects - */ - -/* destroy an object distances structure */ -void -hwloc_clear_object_distances_one(struct hwloc_distances_s * distances) -{ - free(distances->latency); - free(distances); - -} - -void -hwloc_clear_object_distances(hwloc_obj_t obj) -{ - unsigned i; - for (i=0; idistances_count; i++) - hwloc_clear_object_distances_one(obj->distances[i]); - free(obj->distances); - obj->distances = NULL; - obj->distances_count = 0; -} - -/****************************************** - * Grouping objects according to distances - */ - -static void hwloc_report_user_distance_error(const char *msg, int line) -{ - static int reported = 0; - - if (!reported && !hwloc_hide_errors()) { - fprintf(stderr, "****************************************************************************\n"); - fprintf(stderr, "* hwloc %s has encountered what looks like an error from user-given distances.\n", HWLOC_VERSION); - fprintf(stderr, "*\n"); - fprintf(stderr, "* %s\n", msg); - fprintf(stderr, "* Error occurred in topology.c line %d\n", line); - fprintf(stderr, "*\n"); - fprintf(stderr, "* Please make sure that distances given through the interface or environment\n"); - fprintf(stderr, "* variables do not contradict any other topology information.\n"); - fprintf(stderr, "****************************************************************************\n"); - reported = 1; - } -} - -static int hwloc_compare_distances(float a, float b, float accuracy) -{ - if (accuracy != 0.0 && fabsf(a-b) < a * accuracy) - return 0; - return a < b ? -1 : a == b ? 0 : 1; -} - -/* - * Place objects in groups if they are in a transitive graph of minimal distances. - * Return how many groups were created, or 0 if some incomplete distance graphs were found. - */ -static unsigned -hwloc__find_groups_by_min_distance(unsigned nbobjs, - float *_distances, - float accuracy, - unsigned *groupids, - int verbose) -{ - float min_distance = FLT_MAX; - unsigned groupid = 1; - unsigned i,j,k; - unsigned skipped = 0; - -#define DISTANCE(i, j) _distances[(i) * nbobjs + (j)] - - memset(groupids, 0, nbobjs*sizeof(*groupids)); - - /* find the minimal distance */ - for(i=0; itype), accuracies[i]); - if (needcheck && hwloc__check_grouping_matrix(nbobjs, _distances, accuracies[i], verbose) < 0) - continue; - nbgroups = hwloc__find_groups_by_min_distance(nbobjs, _distances, accuracies[i], groupids, verbose); - if (nbgroups) - break; - } - if (!nbgroups) - goto outter_free; - - /* For convenience, put these declarations inside a block. It's a - crying shame we can't use C99 syntax here, and have to do a bunch - of mallocs. :-( */ - { - hwloc_obj_t *groupobjs = NULL; - unsigned *groupsizes = NULL; - float *groupdistances = NULL; - unsigned failed = 0; - - groupobjs = malloc(sizeof(hwloc_obj_t) * nbgroups); - groupsizes = malloc(sizeof(unsigned) * nbgroups); - groupdistances = malloc(sizeof(float) * nbgroups * nbgroups); - if (NULL == groupobjs || NULL == groupsizes || NULL == groupdistances) { - goto inner_free; - } - /* create new Group objects and record their size */ - memset(&(groupsizes[0]), 0, sizeof(groupsizes[0]) * nbgroups); - for(i=0; icpuset = hwloc_bitmap_alloc(); - group_obj->attr->group.depth = topology->next_group_depth; - for (j=0; jcpuset, group_obj->cpuset, objs[j]->cpuset); - if (objs[i]->complete_cpuset) { - if (!group_obj->complete_cpuset) - group_obj->complete_cpuset = hwloc_bitmap_alloc(); - hwloc_bitmap_or(group_obj->complete_cpuset, group_obj->complete_cpuset, objs[j]->complete_cpuset); - } - /* if one obj has a nodeset, assemble a group nodeset */ - if (objs[j]->nodeset) { - if (!group_obj->nodeset) - group_obj->nodeset = hwloc_bitmap_alloc(); - hwloc_bitmap_or(group_obj->nodeset, group_obj->nodeset, objs[j]->nodeset); - } - if (objs[i]->complete_nodeset) { - if (!group_obj->complete_nodeset) - group_obj->complete_nodeset = hwloc_bitmap_alloc(); - hwloc_bitmap_or(group_obj->complete_nodeset, group_obj->complete_nodeset, objs[j]->complete_nodeset); - } - groupsizes[i]++; - } - hwloc_debug_1arg_bitmap("adding Group object with %u objects and cpuset %s\n", - groupsizes[i], group_obj->cpuset); - res_obj = hwloc__insert_object_by_cpuset(topology, group_obj, - fromuser ? hwloc_report_user_distance_error : hwloc_report_os_error); - /* res_obj may be NULL on failure to insert. */ - if (!res_obj) - failed++; - /* or it may be different from groupobjs if we got groups from XML import before grouping */ - groupobjs[i] = res_obj; - } - - if (failed) - /* don't try to group above if we got a NULL group here, just keep this incomplete level */ - goto inner_free; - - /* factorize distances */ - memset(&(groupdistances[0]), 0, sizeof(groupdistances[0]) * nbgroups * nbgroups); -#undef DISTANCE -#define DISTANCE(i, j) _distances[(i) * nbobjs + (j)] -#define GROUP_DISTANCE(i, j) groupdistances[(i) * nbgroups + (j)] - for(i=0; inext_group_depth++; - hwloc__groups_by_distances(topology, nbgroups, groupobjs, (float*) groupdistances, nbaccuracies, accuracies, fromuser, 0 /* no need to check generated matrix */, verbose); - - inner_free: - /* Safely free everything */ - if (NULL != groupobjs) { - free(groupobjs); - } - if (NULL != groupsizes) { - free(groupsizes); - } - if (NULL != groupdistances) { - free(groupdistances); - } - } - - outter_free: - if (NULL != groupids) { - free(groupids); - } -} - -void -hwloc_group_by_distances(struct hwloc_topology *topology) -{ - unsigned nbobjs; - struct hwloc_os_distances_s * osdist; - const char *env; - float accuracies[5] = { 0.0f, 0.01f, 0.02f, 0.05f, 0.1f }; - unsigned nbaccuracies = 5; - hwloc_obj_t group_obj; - int verbose = 0; - unsigned i; - hwloc_localeswitch_declare; -#ifdef HWLOC_DEBUG - unsigned j; -#endif - - env = getenv("HWLOC_GROUPING"); - if (env && !atoi(env)) - return; - /* backward compat with v1.2 */ - if (getenv("HWLOC_IGNORE_DISTANCES")) - return; - - hwloc_localeswitch_init(); - env = getenv("HWLOC_GROUPING_ACCURACY"); - if (!env) { - /* only use 0.0 */ - nbaccuracies = 1; - } else if (strcmp(env, "try")) { - /* use the given value */ - nbaccuracies = 1; - accuracies[0] = (float) atof(env); - } /* otherwise try all values */ - hwloc_localeswitch_fini(); - -#ifdef HWLOC_DEBUG - verbose = 1; -#else - env = getenv("HWLOC_GROUPING_VERBOSE"); - if (env) - verbose = atoi(env); -#endif - - for(osdist = topology->first_osdist; osdist; osdist = osdist->next) { - - nbobjs = osdist->nbobjs; - if (!nbobjs) - continue; - - if (osdist->objs) { - /* if we have objs, we must have distances as well, - * thanks to hwloc_convert_distances_indexes_into_objects() - */ - assert(osdist->distances); - -#ifdef HWLOC_DEBUG - hwloc_debug("%s", "trying to group objects using distance matrix:\n"); - hwloc_debug("%s", " index"); - for(j=0; jobjs[j]->os_index); - hwloc_debug("%s", "\n"); - for(i=0; iobjs[i]->os_index); - for(j=0; jdistances[i*nbobjs + j]); - hwloc_debug("%s", "\n"); - } -#endif - - hwloc__groups_by_distances(topology, nbobjs, - osdist->objs, - osdist->distances, - nbaccuracies, accuracies, - osdist->indexes != NULL, - 1 /* check the first matrice */, - verbose); - - /* add a final group object covering everybody so that the distance matrix can be stored somewhere. - * this group will be merged into a regular object if the matrix isn't strangely incomplete - */ - group_obj = hwloc_alloc_setup_object(HWLOC_OBJ_GROUP, -1); - group_obj->attr->group.depth = (unsigned) -1; - group_obj->cpuset = hwloc_bitmap_alloc(); - for(i=0; icpuset, group_obj->cpuset, osdist->objs[i]->cpuset); - if (osdist->objs[i]->complete_cpuset) { - if (!group_obj->complete_cpuset) - group_obj->complete_cpuset = hwloc_bitmap_alloc(); - hwloc_bitmap_or(group_obj->complete_cpuset, group_obj->complete_cpuset, osdist->objs[i]->complete_cpuset); - } - /* if one obj has a nodeset, assemble a group nodeset */ - if (osdist->objs[i]->nodeset) { - if (!group_obj->nodeset) - group_obj->nodeset = hwloc_bitmap_alloc(); - hwloc_bitmap_or(group_obj->nodeset, group_obj->nodeset, osdist->objs[i]->nodeset); - } - if (osdist->objs[i]->complete_nodeset) { - if (!group_obj->complete_nodeset) - group_obj->complete_nodeset = hwloc_bitmap_alloc(); - hwloc_bitmap_or(group_obj->complete_nodeset, group_obj->complete_nodeset, osdist->objs[i]->complete_nodeset); - } - } - hwloc_debug_1arg_bitmap("adding Group object (as root of distance matrix with %u objects) with cpuset %s\n", - nbobjs, group_obj->cpuset); - hwloc__insert_object_by_cpuset(topology, group_obj, - osdist->indexes != NULL ? hwloc_report_user_distance_error : hwloc_report_os_error); - } - } -} diff --git a/opal/mca/hwloc/hwloc1116/hwloc/src/pci-common.c b/opal/mca/hwloc/hwloc1116/hwloc/src/pci-common.c deleted file mode 100644 index c4212d21ac..0000000000 --- a/opal/mca/hwloc/hwloc1116/hwloc/src/pci-common.c +++ /dev/null @@ -1,545 +0,0 @@ -/* - * Copyright © 2009-2017 Inria. All rights reserved. - * See COPYING in top-level directory. - */ - -#include -#include -#include -#include -#include -#include - -#ifdef HWLOC_DEBUG -static void -hwloc_pci_traverse_print_cb(void * cbdata __hwloc_attribute_unused, - struct hwloc_obj *pcidev) -{ - char busid[14]; - hwloc_obj_t parent; - - /* indent */ - parent = pcidev->parent; - while (parent) { - hwloc_debug("%s", " "); - parent = parent->parent; - } - - snprintf(busid, sizeof(busid), "%04x:%02x:%02x.%01x", - pcidev->attr->pcidev.domain, pcidev->attr->pcidev.bus, pcidev->attr->pcidev.dev, pcidev->attr->pcidev.func); - - if (pcidev->type == HWLOC_OBJ_BRIDGE) { - if (pcidev->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_HOST) - hwloc_debug("HostBridge"); - else - hwloc_debug("Bridge [%04x:%04x]", busid, - pcidev->attr->pcidev.vendor_id, pcidev->attr->pcidev.device_id); - hwloc_debug(" to %04x:[%02x:%02x]\n", - pcidev->attr->bridge.downstream.pci.domain, pcidev->attr->bridge.downstream.pci.secondary_bus, pcidev->attr->bridge.downstream.pci.subordinate_bus); - } else - hwloc_debug("%s Device [%04x:%04x (%04x:%04x) rev=%02x class=%04x]\n", busid, - pcidev->attr->pcidev.vendor_id, pcidev->attr->pcidev.device_id, - pcidev->attr->pcidev.subvendor_id, pcidev->attr->pcidev.subdevice_id, - pcidev->attr->pcidev.revision, pcidev->attr->pcidev.class_id); -} -#endif /* HWLOC_DEBUG */ - -static void -hwloc_pci_traverse_lookuposdevices_cb(void * cbdata, - struct hwloc_obj *pcidev) -{ - struct hwloc_backend *backend = cbdata; - - if (pcidev->type == HWLOC_OBJ_BRIDGE) - return; - - hwloc_backends_notify_new_object(backend, pcidev); -} - -static void -hwloc_pci__traverse(void * cbdata, struct hwloc_obj *root, - void (*cb)(void * cbdata, struct hwloc_obj *)) -{ - struct hwloc_obj *child = root->first_child; - while (child) { - cb(cbdata, child); - if (child->type == HWLOC_OBJ_BRIDGE) - hwloc_pci__traverse(cbdata, child, cb); - child = child->next_sibling; - } -} - -static void -hwloc_pci_traverse(void * cbdata, struct hwloc_obj *root, - void (*cb)(void * cbdata, struct hwloc_obj *)) -{ - hwloc_pci__traverse(cbdata, root, cb); -} - -enum hwloc_pci_busid_comparison_e { - HWLOC_PCI_BUSID_LOWER, - HWLOC_PCI_BUSID_HIGHER, - HWLOC_PCI_BUSID_INCLUDED, - HWLOC_PCI_BUSID_SUPERSET -}; - -static enum hwloc_pci_busid_comparison_e -hwloc_pci_compare_busids(struct hwloc_obj *a, struct hwloc_obj *b) -{ - if (a->type == HWLOC_OBJ_BRIDGE) - assert(a->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI); - if (b->type == HWLOC_OBJ_BRIDGE) - assert(b->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI); - - if (a->attr->pcidev.domain < b->attr->pcidev.domain) - return HWLOC_PCI_BUSID_LOWER; - if (a->attr->pcidev.domain > b->attr->pcidev.domain) - return HWLOC_PCI_BUSID_HIGHER; - - if (a->type == HWLOC_OBJ_BRIDGE - && b->attr->pcidev.bus >= a->attr->bridge.downstream.pci.secondary_bus - && b->attr->pcidev.bus <= a->attr->bridge.downstream.pci.subordinate_bus) - return HWLOC_PCI_BUSID_SUPERSET; - if (b->type == HWLOC_OBJ_BRIDGE - && a->attr->pcidev.bus >= b->attr->bridge.downstream.pci.secondary_bus - && a->attr->pcidev.bus <= b->attr->bridge.downstream.pci.subordinate_bus) - return HWLOC_PCI_BUSID_INCLUDED; - - if (a->attr->pcidev.bus < b->attr->pcidev.bus) - return HWLOC_PCI_BUSID_LOWER; - if (a->attr->pcidev.bus > b->attr->pcidev.bus) - return HWLOC_PCI_BUSID_HIGHER; - - if (a->attr->pcidev.dev < b->attr->pcidev.dev) - return HWLOC_PCI_BUSID_LOWER; - if (a->attr->pcidev.dev > b->attr->pcidev.dev) - return HWLOC_PCI_BUSID_HIGHER; - - if (a->attr->pcidev.func < b->attr->pcidev.func) - return HWLOC_PCI_BUSID_LOWER; - if (a->attr->pcidev.func > b->attr->pcidev.func) - return HWLOC_PCI_BUSID_HIGHER; - - /* Should never reach here. Abort on both debug builds and - non-debug builds */ - assert(0); - fprintf(stderr, "Bad assertion in hwloc %s:%d (aborting)\n", __FILE__, __LINE__); - exit(1); -} - -static void -hwloc_pci_add_child_before(struct hwloc_obj *root, struct hwloc_obj *child, struct hwloc_obj *new) -{ - if (child) { - new->prev_sibling = child->prev_sibling; - child->prev_sibling = new; - } else { - new->prev_sibling = root->last_child; - root->last_child = new; - } - - if (new->prev_sibling) - new->prev_sibling->next_sibling = new; - else - root->first_child = new; - new->next_sibling = child; - - new->parent = root; /* so that hwloc_pci_traverse_print_cb() can indent by depth */ -} - -static void -hwloc_pci_remove_child(struct hwloc_obj *root, struct hwloc_obj *child) -{ - if (child->next_sibling) - child->next_sibling->prev_sibling = child->prev_sibling; - else - root->last_child = child->prev_sibling; - if (child->prev_sibling) - child->prev_sibling->next_sibling = child->next_sibling; - else - root->first_child = child->next_sibling; - child->prev_sibling = NULL; - child->next_sibling = NULL; -} - -static void hwloc_pci_add_object(struct hwloc_obj *root, struct hwloc_obj *new); - -static void -hwloc_pci_try_insert_siblings_below_new_bridge(struct hwloc_obj *root, struct hwloc_obj *new) -{ - enum hwloc_pci_busid_comparison_e comp; - struct hwloc_obj *current, *next; - - next = new->next_sibling; - while (next) { - current = next; - next = current->next_sibling; - - comp = hwloc_pci_compare_busids(current, new); - assert(comp != HWLOC_PCI_BUSID_SUPERSET); - if (comp == HWLOC_PCI_BUSID_HIGHER) - continue; - assert(comp == HWLOC_PCI_BUSID_INCLUDED); - - /* move this object below the new bridge */ - hwloc_pci_remove_child(root, current); - hwloc_pci_add_object(new, current); - } -} - -static void -hwloc_pci_add_object(struct hwloc_obj *root, struct hwloc_obj *new) -{ - struct hwloc_obj *current; - - current = root->first_child; - while (current) { - enum hwloc_pci_busid_comparison_e comp = hwloc_pci_compare_busids(new, current); - switch (comp) { - case HWLOC_PCI_BUSID_HIGHER: - /* go further */ - current = current->next_sibling; - continue; - case HWLOC_PCI_BUSID_INCLUDED: - /* insert below current bridge */ - hwloc_pci_add_object(current, new); - return; - case HWLOC_PCI_BUSID_LOWER: - case HWLOC_PCI_BUSID_SUPERSET: - /* insert before current object */ - hwloc_pci_add_child_before(root, current, new); - /* walk next siblings and move them below new bridge if needed */ - hwloc_pci_try_insert_siblings_below_new_bridge(root, new); - return; - } - } - /* add to the end of the list if higher than everybody */ - hwloc_pci_add_child_before(root, NULL, new); -} - -static struct hwloc_obj * -hwloc_pci_fixup_hostbridge_parent(struct hwloc_topology *topology __hwloc_attribute_unused, - struct hwloc_obj *hostbridge, - struct hwloc_obj *parent) -{ - /* Xeon E5v3 in cluster-on-die mode only have PCI on the first NUMA node of each package. - * but many dual-processor host report the second PCI hierarchy on 2nd NUMA of first package. - */ - if (parent->depth >= 2 - && parent->type == HWLOC_OBJ_NUMANODE - && parent->sibling_rank == 1 && parent->parent->arity == 2 - && parent->parent->type == HWLOC_OBJ_PACKAGE - && parent->parent->sibling_rank == 0 && parent->parent->parent->arity == 2) { - const char *cpumodel = hwloc_obj_get_info_by_name(parent->parent, "CPUModel"); - if (cpumodel && strstr(cpumodel, "Xeon")) { - if (!hwloc_hide_errors()) { - fprintf(stderr, "****************************************************************************\n"); - fprintf(stderr, "* hwloc %s has encountered an incorrect PCI locality information.\n", HWLOC_VERSION); - fprintf(stderr, "* PCI bus %04x:%02x is supposedly close to 2nd NUMA node of 1st package,\n", - hostbridge->first_child->attr->pcidev.domain, hostbridge->first_child->attr->pcidev.bus); - fprintf(stderr, "* however hwloc believes this is impossible on this architecture.\n"); - fprintf(stderr, "* Therefore the PCI bus will be moved to 1st NUMA node of 2nd package.\n"); - fprintf(stderr, "*\n"); - fprintf(stderr, "* If you feel this fixup is wrong, disable it by setting in your environment\n"); - fprintf(stderr, "* HWLOC_PCI_%04x_%02x_LOCALCPUS= (empty value), and report the problem\n", - hostbridge->first_child->attr->pcidev.domain, hostbridge->first_child->attr->pcidev.bus); - fprintf(stderr, "* to the hwloc's user mailing list together with the XML output of lstopo.\n"); - fprintf(stderr, "*\n"); - fprintf(stderr, "* You may silence this message by setting HWLOC_HIDE_ERRORS=1 in your environment.\n"); - fprintf(stderr, "****************************************************************************\n"); - } - return parent->parent->next_sibling->first_child; - } - } - - return parent; -} - -static struct hwloc_obj * -hwloc_pci_find_hostbridge_parent(struct hwloc_topology *topology, struct hwloc_backend *backend, - struct hwloc_obj *hostbridge) -{ - hwloc_bitmap_t cpuset = hwloc_bitmap_alloc(); - struct hwloc_obj *parent; - const char *env; - int err; - - /* override the cpuset with the environment if given */ - int forced = 0; - char envname[256]; - snprintf(envname, sizeof(envname), "HWLOC_PCI_%04x_%02x_LOCALCPUS", - hostbridge->first_child->attr->pcidev.domain, hostbridge->first_child->attr->pcidev.bus); - env = getenv(envname); - if (env) - /* if env exists but is empty, don't let quirks change what the OS reports */ - forced = 1; - if (env && *env) { - /* force the hostbridge cpuset */ - hwloc_debug("Overriding localcpus using %s in the environment\n", envname); - hwloc_bitmap_sscanf(cpuset, env); - } else { - /* get the hostbridge cpuset by acking the OS backend. - * it's not a PCI device, so we use its first child locality info. - */ - err = hwloc_backends_get_obj_cpuset(backend, hostbridge->first_child, cpuset); - if (err < 0) - /* if we got nothing, assume the hostbridge is attached to the top of hierarchy */ - hwloc_bitmap_copy(cpuset, hwloc_topology_get_topology_cpuset(topology)); - } - - hwloc_debug_bitmap("Attaching hostbridge to cpuset %s\n", cpuset); - - /* restrict to the existing topology cpuset to avoid errors later */ - hwloc_bitmap_and(cpuset, cpuset, hwloc_topology_get_topology_cpuset(topology)); - - /* if the remaining cpuset is empty, take the root */ - if (hwloc_bitmap_iszero(cpuset)) - hwloc_bitmap_copy(cpuset, hwloc_topology_get_topology_cpuset(topology)); - - /* attach the hostbridge now that it contains the right objects */ - parent = hwloc_get_obj_covering_cpuset(topology, cpuset); - /* in the worst case, we got the root object */ - - if (hwloc_bitmap_isequal(cpuset, parent->cpuset)) { - /* this object has the right cpuset, but it could be a cache or so, - * go up as long as the cpuset is the same - */ - while (parent->parent && hwloc_bitmap_isequal(parent->cpuset, parent->parent->cpuset)) - parent = parent->parent; - - if (!forced) - parent = hwloc_pci_fixup_hostbridge_parent(topology, hostbridge, parent); - - } else { - /* the object we found is too large, insert an intermediate group */ - hwloc_obj_t group_obj = hwloc_alloc_setup_object(HWLOC_OBJ_GROUP, -1); - if (group_obj) { - group_obj->cpuset = hwloc_bitmap_dup(cpuset); - group_obj->complete_cpuset = hwloc_bitmap_dup(cpuset); - group_obj->attr->group.depth = (unsigned) -1; - parent = hwloc__insert_object_by_cpuset(topology, group_obj, hwloc_report_os_error); - if (parent == group_obj) - /* if didn't get merged, setup its sets */ - hwloc_fill_object_sets(group_obj); - if (!parent) - /* Failed to insert the parent, maybe a conflicting cpuset, attach to the root object instead */ - parent = hwloc_get_root_obj(topology); - } - } - - hwloc_bitmap_free(cpuset); - - return parent; -} - -int -hwloc_insert_pci_device_list(struct hwloc_backend *backend, - struct hwloc_obj *first_obj) -{ - struct hwloc_topology *topology = backend->topology; - struct hwloc_obj fakeparent; - struct hwloc_obj *obj; - unsigned current_hostbridge; - - if (!first_obj) - /* found nothing, exit */ - return 0; - - /* first, organise object as tree under a fake parent object */ - fakeparent.parent = NULL; - fakeparent.first_child = NULL; - fakeparent.last_child = NULL; - while (first_obj) { - obj = first_obj; - first_obj = obj->next_sibling; - hwloc_pci_add_object(&fakeparent, obj); - } - -#ifdef HWLOC_DEBUG - hwloc_debug("%s", "\nPCI hierarchy under fake parent:\n"); - hwloc_pci_traverse(NULL, &fakeparent, hwloc_pci_traverse_print_cb); - hwloc_debug("%s", "\n"); -#endif - - /* walk the hierarchy, and lookup OS devices */ - hwloc_pci_traverse(backend, &fakeparent, hwloc_pci_traverse_lookuposdevices_cb); - - /* - * fakeparent lists all objects connected to any upstream bus in the machine. - * We now create one real hostbridge object per upstream bus. - * It's not actually a PCI device so we have to create it. - */ - current_hostbridge = 0; - while (fakeparent.first_child) { - /* start a new host bridge */ - struct hwloc_obj *hostbridge = hwloc_alloc_setup_object(HWLOC_OBJ_BRIDGE, current_hostbridge++); - struct hwloc_obj *child = fakeparent.first_child; - struct hwloc_obj *next_child; - struct hwloc_obj *parent; - unsigned short current_domain = child->attr->pcidev.domain; - unsigned char current_bus = child->attr->pcidev.bus; - unsigned char current_subordinate = current_bus; - - hwloc_debug("Starting new PCI hostbridge %04x:%02x\n", current_domain, current_bus); - - /* - * attach all objects from the same upstream domain/bus - */ - next_child: - next_child = child->next_sibling; - hwloc_pci_remove_child(&fakeparent, child); - hwloc_pci_add_child_before(hostbridge, NULL, child); - - /* compute hostbridge secondary/subordinate buses */ - if (child->type == HWLOC_OBJ_BRIDGE - && child->attr->bridge.downstream.pci.subordinate_bus > current_subordinate) - current_subordinate = child->attr->bridge.downstream.pci.subordinate_bus; - - /* use next child if it has the same domains/bus */ - child = next_child; - if (child - && child->attr->pcidev.domain == current_domain - && child->attr->pcidev.bus == current_bus) - goto next_child; - - /* finish setting up this hostbridge */ - hostbridge->attr->bridge.upstream_type = HWLOC_OBJ_BRIDGE_HOST; - hostbridge->attr->bridge.downstream_type = HWLOC_OBJ_BRIDGE_PCI; - hostbridge->attr->bridge.downstream.pci.domain = current_domain; - hostbridge->attr->bridge.downstream.pci.secondary_bus = current_bus; - hostbridge->attr->bridge.downstream.pci.subordinate_bus = current_subordinate; - hwloc_debug("New PCI hostbridge %04x:[%02x-%02x]\n", - current_domain, current_bus, current_subordinate); - - /* attach the hostbridge where it belongs */ - parent = hwloc_pci_find_hostbridge_parent(topology, backend, hostbridge); - hwloc_insert_object_by_parent(topology, parent, hostbridge); - } - - return 1; -} - -#define HWLOC_PCI_STATUS 0x06 -#define HWLOC_PCI_STATUS_CAP_LIST 0x10 -#define HWLOC_PCI_CAPABILITY_LIST 0x34 -#define HWLOC_PCI_CAP_LIST_ID 0 -#define HWLOC_PCI_CAP_LIST_NEXT 1 - -unsigned -hwloc_pci_find_cap(const unsigned char *config, unsigned cap) -{ - unsigned char seen[256] = { 0 }; - unsigned char ptr; /* unsigned char to make sure we stay within the 256-byte config space */ - - if (!(config[HWLOC_PCI_STATUS] & HWLOC_PCI_STATUS_CAP_LIST)) - return 0; - - for (ptr = config[HWLOC_PCI_CAPABILITY_LIST] & ~3; - ptr; /* exit if next is 0 */ - ptr = config[ptr + HWLOC_PCI_CAP_LIST_NEXT] & ~3) { - unsigned char id; - - /* Looped around! */ - if (seen[ptr]) - break; - seen[ptr] = 1; - - id = config[ptr + HWLOC_PCI_CAP_LIST_ID]; - if (id == cap) - return ptr; - if (id == 0xff) /* exit if id is 0 or 0xff */ - break; - } - return 0; -} - -#define HWLOC_PCI_EXP_LNKSTA 0x12 -#define HWLOC_PCI_EXP_LNKSTA_SPEED 0x000f -#define HWLOC_PCI_EXP_LNKSTA_WIDTH 0x03f0 - -int -hwloc_pci_find_linkspeed(const unsigned char *config, - unsigned offset, float *linkspeed) -{ - unsigned linksta, speed, width; - float lanespeed; - - memcpy(&linksta, &config[offset + HWLOC_PCI_EXP_LNKSTA], 4); - speed = linksta & HWLOC_PCI_EXP_LNKSTA_SPEED; /* PCIe generation */ - width = (linksta & HWLOC_PCI_EXP_LNKSTA_WIDTH) >> 4; /* how many lanes */ - /* PCIe Gen1 = 2.5GT/s signal-rate per lane with 8/10 encoding = 0.25GB/s data-rate per lane - * PCIe Gen2 = 5 GT/s signal-rate per lane with 8/10 encoding = 0.5 GB/s data-rate per lane - * PCIe Gen3 = 8 GT/s signal-rate per lane with 128/130 encoding = 1 GB/s data-rate per lane - * PCIe Gen4 = 16 GT/s signal-rate per lane with 128/130 encoding = 2 GB/s data-rate per lane - */ - - /* lanespeed in Gbit/s */ - if (speed <= 2) - lanespeed = 2.5f * speed * 0.8f; - else - lanespeed = 8.0f * (1<<(speed-3)) * 128/130; /* assume Gen5 will be 32 GT/s and so on */ - - /* linkspeed in GB/s */ - *linkspeed = lanespeed * width / 8; - return 0; -} - -#define HWLOC_PCI_HEADER_TYPE 0x0e -#define HWLOC_PCI_HEADER_TYPE_BRIDGE 1 -#define HWLOC_PCI_CLASS_BRIDGE_PCI 0x0604 -#define HWLOC_PCI_PRIMARY_BUS 0x18 -#define HWLOC_PCI_SECONDARY_BUS 0x19 -#define HWLOC_PCI_SUBORDINATE_BUS 0x1a - -int -hwloc_pci_prepare_bridge(hwloc_obj_t obj, - const unsigned char *config) -{ - unsigned char headertype; - unsigned isbridge; - struct hwloc_pcidev_attr_s *pattr = &obj->attr->pcidev; - struct hwloc_bridge_attr_s *battr; - - headertype = config[HWLOC_PCI_HEADER_TYPE] & 0x7f; - isbridge = (pattr->class_id == HWLOC_PCI_CLASS_BRIDGE_PCI - && headertype == HWLOC_PCI_HEADER_TYPE_BRIDGE); - - if (!isbridge) - return 0; - - battr = &obj->attr->bridge; - - if (config[HWLOC_PCI_PRIMARY_BUS] != pattr->bus) { - /* Sometimes the config space contains 00 instead of the actual primary bus number. - * Always trust the bus ID because it was built by the system which has more information - * to workaround such problems (e.g. ACPI information about PCI parent/children). - */ - hwloc_debug(" %04x:%02x:%02x.%01x bridge with (ignored) invalid PCI_PRIMARY_BUS %02x\n", - pattr->domain, pattr->bus, pattr->dev, pattr->func, config[HWLOC_PCI_PRIMARY_BUS]); - } - - obj->type = HWLOC_OBJ_BRIDGE; - battr->upstream_type = HWLOC_OBJ_BRIDGE_PCI; - battr->downstream_type = HWLOC_OBJ_BRIDGE_PCI; - battr->downstream.pci.domain = pattr->domain; - battr->downstream.pci.secondary_bus = config[HWLOC_PCI_SECONDARY_BUS]; - battr->downstream.pci.subordinate_bus = config[HWLOC_PCI_SUBORDINATE_BUS]; - - if (battr->downstream.pci.secondary_bus <= pattr->bus - || battr->downstream.pci.subordinate_bus <= pattr->bus - || battr->downstream.pci.secondary_bus > battr->downstream.pci.subordinate_bus) { - /* This should catch most cases of invalid bridge information - * (e.g. 00 for secondary and subordinate). - * Ideally we would also check that [secondary-subordinate] is included - * in the parent bridge [secondary+1:subordinate]. But that's hard to do - * because objects may be discovered out of order (especially in the fsroot case). - */ - hwloc_debug(" %04x:%02x:%02x.%01x bridge has invalid secondary-subordinate buses [%02x-%02x]\n", - pattr->domain, pattr->bus, pattr->dev, pattr->func, - battr->downstream.pci.secondary_bus, battr->downstream.pci.subordinate_bus); - hwloc_free_unlinked_object(obj); - return -1; - } - - return 0; -} diff --git a/opal/mca/hwloc/hwloc1116/hwloc/src/topology-custom.c b/opal/mca/hwloc/hwloc1116/hwloc/src/topology-custom.c deleted file mode 100644 index c3ccfaadc9..0000000000 --- a/opal/mca/hwloc/hwloc1116/hwloc/src/topology-custom.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright © 2011-2014 Inria. All rights reserved. - * See COPYING in top-level directory. - */ - -#include -#include -#include - -hwloc_obj_t -hwloc_custom_insert_group_object_by_parent(struct hwloc_topology *topology, hwloc_obj_t parent, int groupdepth) -{ - hwloc_obj_t obj; - - /* must be called between set_custom() and load(), so there's a single backend, the custom one */ - if (topology->is_loaded || !topology->backends || !topology->backends->is_custom) { - errno = EINVAL; - return NULL; - } - - obj = hwloc_alloc_setup_object(HWLOC_OBJ_GROUP, -1); - obj->attr->group.depth = groupdepth; - hwloc_obj_add_info(obj, "Backend", "Custom"); - hwloc_insert_object_by_parent(topology, parent, obj); - /* insert_object_by_parent() doesn't merge during insert, so obj is still valid */ - - return obj; -} - -int -hwloc_custom_insert_topology(struct hwloc_topology *newtopology, - struct hwloc_obj *newparent, - struct hwloc_topology *oldtopology, - struct hwloc_obj *oldroot) -{ - /* must be called between set_custom() and load(), so there's a single backend, the custom one */ - if (newtopology->is_loaded || !newtopology->backends || !newtopology->backends->is_custom) { - errno = EINVAL; - return -1; - } - - if (!oldtopology->is_loaded) { - errno = EINVAL; - return -1; - } - - hwloc__duplicate_objects(newtopology, newparent, oldroot ? oldroot : oldtopology->levels[0][0]); - return 0; -} - -static int -hwloc_look_custom(struct hwloc_backend *backend) -{ - struct hwloc_topology *topology = backend->topology; - hwloc_obj_t root = topology->levels[0][0]; - - assert(!root->cpuset); - - if (!root->first_child) { - errno = EINVAL; - return -1; - } - - root->type = HWLOC_OBJ_SYSTEM; - hwloc_obj_add_info(root, "Backend", "Custom"); - return 1; -} - -static struct hwloc_backend * -hwloc_custom_component_instantiate(struct hwloc_disc_component *component, - const void *_data1 __hwloc_attribute_unused, - const void *_data2 __hwloc_attribute_unused, - const void *_data3 __hwloc_attribute_unused) -{ - struct hwloc_backend *backend; - backend = hwloc_backend_alloc(component); - if (!backend) - return NULL; - backend->discover = hwloc_look_custom; - backend->is_custom = 1; - backend->is_thissystem = 0; - return backend; -} - -static struct hwloc_disc_component hwloc_custom_disc_component = { - HWLOC_DISC_COMPONENT_TYPE_GLOBAL, - "custom", - ~0, - hwloc_custom_component_instantiate, - 30, - NULL -}; - -const struct hwloc_component hwloc_custom_component = { - HWLOC_COMPONENT_ABI, - NULL, NULL, - HWLOC_COMPONENT_TYPE_DISC, - 0, - &hwloc_custom_disc_component -}; diff --git a/opal/mca/hwloc/hwloc1116/hwloc/src/topology-hardwired.c b/opal/mca/hwloc/hwloc1116/hwloc/src/topology-hardwired.c deleted file mode 100644 index d448f3d55b..0000000000 --- a/opal/mca/hwloc/hwloc1116/hwloc/src/topology-hardwired.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright © 2015-2016 Inria. All rights reserved. - * See COPYING in top-level directory. - */ - -#include - -#include -#include - -int hwloc_look_hardwired_fujitsu_k(struct hwloc_topology *topology) -{ - /* If a broken core gets disabled, its bit disappears and other core bits are NOT shifted towards 0. - * Node is not given to user job, not need to handle that case properly. - */ - unsigned i; - hwloc_obj_t obj; - hwloc_bitmap_t set; - - for(i=0; i<8; i++) { - set = hwloc_bitmap_alloc(); - hwloc_bitmap_set(set, i); - - obj = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -1); - obj->cpuset = hwloc_bitmap_dup(set); - obj->attr->cache.type = HWLOC_OBJ_CACHE_INSTRUCTION; - obj->attr->cache.depth = 1; - obj->attr->cache.size = 32*1024; - obj->attr->cache.linesize = 128; - obj->attr->cache.associativity = 2; - hwloc_insert_object_by_cpuset(topology, obj); - - obj = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -1); - obj->cpuset = hwloc_bitmap_dup(set); - obj->attr->cache.type = HWLOC_OBJ_CACHE_DATA; - obj->attr->cache.depth = 1; - obj->attr->cache.size = 32*1024; - obj->attr->cache.linesize = 128; - obj->attr->cache.associativity = 2; - hwloc_insert_object_by_cpuset(topology, obj); - - obj = hwloc_alloc_setup_object(HWLOC_OBJ_CORE, i); - obj->cpuset = set; - hwloc_insert_object_by_cpuset(topology, obj); - } - - set = hwloc_bitmap_alloc(); - hwloc_bitmap_set_range(set, 0, 7); - - obj = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -1); - obj->cpuset = hwloc_bitmap_dup(set); - obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED; - obj->attr->cache.depth = 2; - obj->attr->cache.size = 6*1024*1024; - obj->attr->cache.linesize = 128; - obj->attr->cache.associativity = 12; - hwloc_insert_object_by_cpuset(topology, obj); - - obj = hwloc_alloc_setup_object(HWLOC_OBJ_PACKAGE, 0); - obj->cpuset = set; - hwloc_obj_add_info(obj, "CPUVendor", "Fujitsu"); - hwloc_obj_add_info(obj, "CPUModel", "SPARC64 VIIIfx"); - hwloc_insert_object_by_cpuset(topology, obj); - - hwloc_setup_pu_level(topology, 8); - - return 0; -} - -int hwloc_look_hardwired_fujitsu_fx10(struct hwloc_topology *topology) -{ - /* If a broken core gets disabled, its bit disappears and other core bits are NOT shifted towards 0. - * Node is not given to user job, not need to handle that case properly. - */ - unsigned i; - hwloc_obj_t obj; - hwloc_bitmap_t set; - - for(i=0; i<16; i++) { - set = hwloc_bitmap_alloc(); - hwloc_bitmap_set(set, i); - - obj = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -1); - obj->cpuset = hwloc_bitmap_dup(set); - obj->attr->cache.type = HWLOC_OBJ_CACHE_INSTRUCTION; - obj->attr->cache.depth = 1; - obj->attr->cache.size = 32*1024; - obj->attr->cache.linesize = 128; - obj->attr->cache.associativity = 2; - hwloc_insert_object_by_cpuset(topology, obj); - - obj = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -1); - obj->cpuset = hwloc_bitmap_dup(set); - obj->attr->cache.type = HWLOC_OBJ_CACHE_DATA; - obj->attr->cache.depth = 1; - obj->attr->cache.size = 32*1024; - obj->attr->cache.linesize = 128; - obj->attr->cache.associativity = 2; - hwloc_insert_object_by_cpuset(topology, obj); - - obj = hwloc_alloc_setup_object(HWLOC_OBJ_CORE, i); - obj->cpuset = set; - hwloc_insert_object_by_cpuset(topology, obj); - } - - set = hwloc_bitmap_alloc(); - hwloc_bitmap_set_range(set, 0, 15); - - obj = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -1); - obj->cpuset = hwloc_bitmap_dup(set); - obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED; - obj->attr->cache.depth = 2; - obj->attr->cache.size = 12*1024*1024; - obj->attr->cache.linesize = 128; - obj->attr->cache.associativity = 24; - hwloc_insert_object_by_cpuset(topology, obj); - - obj = hwloc_alloc_setup_object(HWLOC_OBJ_PACKAGE, 0); - obj->cpuset = set; - hwloc_obj_add_info(obj, "CPUVendor", "Fujitsu"); - hwloc_obj_add_info(obj, "CPUModel", "SPARC64 IXfx"); - hwloc_insert_object_by_cpuset(topology, obj); - - hwloc_setup_pu_level(topology, 16); - - return 0; -} - -int hwloc_look_hardwired_fujitsu_fx100(struct hwloc_topology *topology) -{ - /* If a broken core gets disabled, its bit disappears and other core bits are NOT shifted towards 0. - * Node is not given to user job, not need to handle that case properly. - */ - unsigned i; - hwloc_obj_t obj; - hwloc_bitmap_t set; - - for(i=0; i<34; i++) { - set = hwloc_bitmap_alloc(); - hwloc_bitmap_set(set, i); - - obj = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -1); - obj->cpuset = hwloc_bitmap_dup(set); - obj->attr->cache.type = HWLOC_OBJ_CACHE_INSTRUCTION; - obj->attr->cache.depth = 1; - obj->attr->cache.size = 64*1024; - obj->attr->cache.linesize = 256; - obj->attr->cache.associativity = 4; - hwloc_insert_object_by_cpuset(topology, obj); - - obj = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -1); - obj->cpuset = hwloc_bitmap_dup(set); - obj->attr->cache.type = HWLOC_OBJ_CACHE_DATA; - obj->attr->cache.depth = 1; - obj->attr->cache.size = 64*1024; - obj->attr->cache.linesize = 256; - obj->attr->cache.associativity = 4; - hwloc_insert_object_by_cpuset(topology, obj); - - obj = hwloc_alloc_setup_object(HWLOC_OBJ_CORE, i); - obj->cpuset = set; - hwloc_insert_object_by_cpuset(topology, obj); - } - - obj = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -1); - obj->cpuset = hwloc_bitmap_alloc(); - hwloc_bitmap_set_range(obj->cpuset, 0, 15); - hwloc_bitmap_set(obj->cpuset, 32); - obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED; - obj->attr->cache.depth = 2; - obj->attr->cache.size = 12*1024*1024; - obj->attr->cache.linesize = 256; - obj->attr->cache.associativity = 24; - hwloc_insert_object_by_cpuset(topology, obj); - - obj = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -1); - obj->cpuset = hwloc_bitmap_alloc(); - hwloc_bitmap_set_range(obj->cpuset, 16, 31); - hwloc_bitmap_set(obj->cpuset, 33); - obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED; - obj->attr->cache.depth = 2; - obj->attr->cache.size = 12*1024*1024; - obj->attr->cache.linesize = 256; - obj->attr->cache.associativity = 24; - hwloc_insert_object_by_cpuset(topology, obj); - - obj = hwloc_alloc_setup_object(HWLOC_OBJ_PACKAGE, 0); - obj->cpuset = hwloc_bitmap_alloc(); - hwloc_bitmap_set_range(obj->cpuset, 0, 33); - hwloc_obj_add_info(obj, "CPUVendor", "Fujitsu"); - hwloc_obj_add_info(obj, "CPUModel", "SPARC64 XIfx"); - hwloc_insert_object_by_cpuset(topology, obj); - - hwloc_setup_pu_level(topology, 34); - - return 0; -} diff --git a/opal/mca/hwloc/hwloc1116/hwloc/src/topology-nvml.c b/opal/mca/hwloc/hwloc1116/hwloc/src/topology-nvml.c deleted file mode 100644 index 9c36d0a40b..0000000000 --- a/opal/mca/hwloc/hwloc1116/hwloc/src/topology-nvml.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright © 2012-2014 Inria. All rights reserved. - * See COPYING in top-level directory. - */ - -#include -#include -#include - -/* private headers allowed for convenience because this plugin is built within hwloc */ -#include -#include - -#include - -struct hwloc_nvml_backend_data_s { - unsigned nr_devices; /* -1 when unknown yet, first callback will setup */ - struct hwloc_nvml_device_info_s { - char name[64]; - char serial[64]; - char uuid[64]; - unsigned pcidomain, pcibus, pcidev, pcifunc; - float maxlinkspeed; - } * devices; -}; - -static void -hwloc_nvml_query_devices(struct hwloc_nvml_backend_data_s *data) -{ - nvmlReturn_t ret; - unsigned nb, i; - - /* mark the number of devices as 0 in case we fail below, - * so that we don't try again later. - */ - data->nr_devices = 0; - - ret = nvmlInit(); - if (NVML_SUCCESS != ret) - goto out; - ret = nvmlDeviceGetCount(&nb); - if (NVML_SUCCESS != ret) - goto out_with_init; - - /* allocate structs */ - data->devices = malloc(nb * sizeof(*data->devices)); - if (!data->devices) - goto out_with_init; - - for(i=0; idevices[data->nr_devices]; - nvmlPciInfo_t pci; - nvmlDevice_t device; - - ret = nvmlDeviceGetHandleByIndex(i, &device); - assert(ret == NVML_SUCCESS); - - ret = nvmlDeviceGetPciInfo(device, &pci); - if (NVML_SUCCESS != ret) - continue; - - info->pcidomain = pci.domain; - info->pcibus = pci.bus; - info->pcidev = pci.device; - info->pcifunc = 0; - - info->name[0] = '\0'; - ret = nvmlDeviceGetName(device, info->name, sizeof(info->name)); - /* these may fail with NVML_ERROR_NOT_SUPPORTED on old devices */ - info->serial[0] = '\0'; - ret = nvmlDeviceGetSerial(device, info->serial, sizeof(info->serial)); - info->uuid[0] = '\0'; - ret = nvmlDeviceGetUUID(device, info->uuid, sizeof(info->uuid)); - - info->maxlinkspeed = 0.0f; -#if HAVE_DECL_NVMLDEVICEGETMAXPCIELINKGENERATION - { - unsigned maxwidth = 0, maxgen = 0; - float lanespeed; - nvmlDeviceGetMaxPcieLinkWidth(device, &maxwidth); - nvmlDeviceGetMaxPcieLinkGeneration(device, &maxgen); - /* PCIe Gen1 = 2.5GT/s signal-rate per lane with 8/10 encoding = 0.25GB/s data-rate per lane - * PCIe Gen2 = 5 GT/s signal-rate per lane with 8/10 encoding = 0.5 GB/s data-rate per lane - * PCIe Gen3 = 8 GT/s signal-rate per lane with 128/130 encoding = 1 GB/s data-rate per lane - */ - lanespeed = maxgen <= 2 ? 2.5 * maxgen * 0.8 : 8.0 * 128/130; /* Gbit/s per lane */ - info->maxlinkspeed = lanespeed * maxwidth / 8; /* GB/s */ - } -#endif - - /* validate this device */ - data->nr_devices++; - } - -out_with_init: - nvmlShutdown(); -out: - return; -} - -static int -hwloc_nvml_backend_notify_new_object(struct hwloc_backend *backend, struct hwloc_backend *caller __hwloc_attribute_unused, - struct hwloc_obj *pcidev) -{ - struct hwloc_topology *topology = backend->topology; - struct hwloc_nvml_backend_data_s *data = backend->private_data; - unsigned i; - - if (!(hwloc_topology_get_flags(topology) & (HWLOC_TOPOLOGY_FLAG_IO_DEVICES|HWLOC_TOPOLOGY_FLAG_WHOLE_IO))) - return 0; - - if (!hwloc_topology_is_thissystem(topology)) { - hwloc_debug("%s", "\nno NVML detection (not thissystem)\n"); - return 0; - } - - if (HWLOC_OBJ_PCI_DEVICE != pcidev->type) - return 0; - - if (data->nr_devices == (unsigned) -1) { - /* first call, lookup all devices */ - hwloc_nvml_query_devices(data); - /* if it fails, data->nr_devices = 0 so we won't do anything below and in next callbacks */ - } - - if (!data->nr_devices) - /* found no devices */ - return 0; - - /* now the devices array is ready to use */ - for(i=0; inr_devices; i++) { - struct hwloc_nvml_device_info_s *info = &data->devices[i]; - hwloc_obj_t osdev; - char buffer[64]; - - if (info->pcidomain != pcidev->attr->pcidev.domain) - continue; - if (info->pcibus != pcidev->attr->pcidev.bus) - continue; - if (info->pcidev != pcidev->attr->pcidev.dev) - continue; - if (info->pcifunc != pcidev->attr->pcidev.func) - continue; - - osdev = hwloc_alloc_setup_object(HWLOC_OBJ_OS_DEVICE, -1); - snprintf(buffer, sizeof(buffer), "nvml%d", i); - osdev->name = strdup(buffer); - osdev->depth = (unsigned) HWLOC_TYPE_DEPTH_UNKNOWN; - osdev->attr->osdev.type = HWLOC_OBJ_OSDEV_GPU; - - hwloc_obj_add_info(osdev, "Backend", "NVML"); - hwloc_obj_add_info(osdev, "GPUVendor", "NVIDIA Corporation"); - hwloc_obj_add_info(osdev, "GPUModel", info->name); - if (info->serial[0] != '\0') - hwloc_obj_add_info(osdev, "NVIDIASerial", info->serial); - if (info->uuid[0] != '\0') - hwloc_obj_add_info(osdev, "NVIDIAUUID", info->uuid); - - hwloc_insert_object_by_parent(topology, pcidev, osdev); - - if (info->maxlinkspeed != 0.0f) - /* we found the max link speed, replace the current link speed found by pci (or none) */ - pcidev->attr->pcidev.linkspeed = info->maxlinkspeed; - - return 1; - } - - return 0; -} - -static void -hwloc_nvml_backend_disable(struct hwloc_backend *backend) -{ - struct hwloc_nvml_backend_data_s *data = backend->private_data; - free(data->devices); - free(data); -} - -static struct hwloc_backend * -hwloc_nvml_component_instantiate(struct hwloc_disc_component *component, - const void *_data1 __hwloc_attribute_unused, - const void *_data2 __hwloc_attribute_unused, - const void *_data3 __hwloc_attribute_unused) -{ - struct hwloc_backend *backend; - struct hwloc_nvml_backend_data_s *data; - - /* thissystem may not be fully initialized yet, we'll check flags in discover() */ - - backend = hwloc_backend_alloc(component); - if (!backend) - return NULL; - - data = malloc(sizeof(*data)); - if (!data) { - free(backend); - return NULL; - } - /* the first callback will initialize those */ - data->nr_devices = (unsigned) -1; /* unknown yet */ - data->devices = NULL; - - backend->private_data = data; - backend->disable = hwloc_nvml_backend_disable; - - backend->notify_new_object = hwloc_nvml_backend_notify_new_object; - return backend; -} - -static struct hwloc_disc_component hwloc_nvml_disc_component = { - HWLOC_DISC_COMPONENT_TYPE_MISC, - "nvml", - HWLOC_DISC_COMPONENT_TYPE_GLOBAL, - hwloc_nvml_component_instantiate, - 5, /* after pci, and after cuda since likely less useful */ - NULL -}; - -static int -hwloc_nvml_component_init(unsigned long flags) -{ - if (flags) - return -1; - if (hwloc_plugin_check_namespace("nvml", "hwloc_backend_alloc") < 0) - return -1; - return 0; -} - -#ifdef HWLOC_INSIDE_PLUGIN -HWLOC_DECLSPEC extern const struct hwloc_component hwloc_nvml_component; -#endif - -const struct hwloc_component hwloc_nvml_component = { - HWLOC_COMPONENT_ABI, - hwloc_nvml_component_init, NULL, - HWLOC_COMPONENT_TYPE_DISC, - 0, - &hwloc_nvml_disc_component -}; diff --git a/opal/mca/hwloc/hwloc1116/hwloc/src/topology-opencl.c b/opal/mca/hwloc/hwloc1116/hwloc/src/topology-opencl.c deleted file mode 100644 index 85057c7c15..0000000000 --- a/opal/mca/hwloc/hwloc1116/hwloc/src/topology-opencl.c +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Copyright © 2012-2014 Inria. All rights reserved. - * Copyright © 2013 Université Bordeaux. All right reserved. - * See COPYING in top-level directory. - */ - -#include -#include -#include - -/* private headers allowed for convenience because this plugin is built within hwloc */ -#include -#include - -#include - -typedef enum hwloc_opencl_device_type_e { - HWLOC_OPENCL_DEVICE_AMD -} hwloc_opencl_device_type_t; - -struct hwloc_opencl_backend_data_s { - unsigned nr_devices; /* -1 when unknown yet, first callback will setup */ - struct hwloc_opencl_device_info_s { - hwloc_opencl_device_type_t type; - - unsigned platformidx; - char platformname[64]; - unsigned platformdeviceidx; - char devicename[64]; - char devicevendor[64]; - char devicetype[64]; - - unsigned computeunits; - unsigned long long globalmemsize; - - union hwloc_opencl_device_info_u { - struct hwloc_opencl_device_info_amd_s { - unsigned pcidomain, pcibus, pcidev, pcifunc; - } amd; - } specific; - } * devices; -}; - -static void -hwloc_opencl_query_devices(struct hwloc_opencl_backend_data_s *data) -{ - cl_platform_id *platform_ids = NULL; - cl_uint nr_platforms; - cl_device_id *device_ids = NULL; - cl_uint nr_devices, nr_total_devices, tmp; - cl_int clret; - unsigned curpfidx, curpfdvidx, i; - - /* mark the number of devices as 0 in case we fail below, - * so that we don't try again later. - */ - data->nr_devices = 0; - - /* count platforms, allocate and get them */ - clret = clGetPlatformIDs(0, NULL, &nr_platforms); - if (CL_SUCCESS != clret || !nr_platforms) - goto out; - hwloc_debug("%u OpenCL platforms\n", nr_platforms); - platform_ids = malloc(nr_platforms * sizeof(*platform_ids)); - if (!platform_ids) - goto out; - clret = clGetPlatformIDs(nr_platforms, platform_ids, &nr_platforms); - if (CL_SUCCESS != clret || !nr_platforms) - goto out_with_platform_ids; - - /* how many devices, total? */ - tmp = 0; - for(i=0; idevices = malloc(nr_total_devices * sizeof(*data->devices)); - if (!data->devices || !device_ids) - goto out_with_device_ids; - /* actually query device ids */ - tmp = 0; - for(i=0; idevices[data->nr_devices]; - cl_platform_id platform_id = 0; - cl_device_type type; -#ifdef CL_DEVICE_TOPOLOGY_AMD - cl_device_topology_amd amdtopo; -#endif - cl_ulong globalmemsize; - cl_uint computeunits; - - hwloc_debug("Looking device %p\n", device_ids[i]); - - info->platformname[0] = '\0'; - clret = clGetDeviceInfo(device_ids[i], CL_DEVICE_PLATFORM, sizeof(platform_id), &platform_id, NULL); - if (CL_SUCCESS != clret) - continue; - clGetPlatformInfo(platform_id, CL_PLATFORM_NAME, sizeof(info->platformname), info->platformname, NULL); - - info->devicename[0] = '\0'; -#ifdef CL_DEVICE_BOARD_NAME_AMD - clGetDeviceInfo(device_ids[i], CL_DEVICE_BOARD_NAME_AMD, sizeof(info->devicename), info->devicename, NULL); -#else - clGetDeviceInfo(device_ids[i], CL_DEVICE_NAME, sizeof(info->devicename), info->devicename, NULL); -#endif - info->devicevendor[0] = '\0'; - clGetDeviceInfo(device_ids[i], CL_DEVICE_VENDOR, sizeof(info->devicevendor), info->devicevendor, NULL); - - clGetDeviceInfo(device_ids[i], CL_DEVICE_TYPE, sizeof(type), &type, NULL); - switch (type) { - case CL_DEVICE_TYPE_CPU: /* FIXME: cannot happen in PCI devices? */ - strcpy(info->devicetype, "CPU"); - break; - case CL_DEVICE_TYPE_GPU: - strcpy(info->devicetype, "GPU"); - break; - case CL_DEVICE_TYPE_ACCELERATOR: - strcpy(info->devicetype, "Accelerator"); - break; - default: - strcpy(info->devicetype, "Unknown"); - break; - } - - clGetDeviceInfo(device_ids[i], CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(globalmemsize), &globalmemsize, NULL); - info->globalmemsize = globalmemsize / 1024; - - clGetDeviceInfo(device_ids[i], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(computeunits), &computeunits, NULL); - info->computeunits = computeunits; - - hwloc_debug("platform %s device %s vendor %s type %s\n", info->platformname, info->devicename, info->devicevendor, info->devicetype); - - /* find our indexes */ - while (platform_id != platform_ids[curpfidx]) { - curpfidx++; - curpfdvidx = 0; - } - info->platformidx = curpfidx; - info->platformdeviceidx = curpfdvidx; - curpfdvidx++; - - hwloc_debug("This is opencl%dd%d\n", info->platformidx, info->platformdeviceidx); - -#ifdef CL_DEVICE_TOPOLOGY_AMD - clret = clGetDeviceInfo(device_ids[i], CL_DEVICE_TOPOLOGY_AMD, sizeof(amdtopo), &amdtopo, NULL); - if (CL_SUCCESS != clret) { - hwloc_debug("no AMD-specific device information: %d\n", clret); - continue; - } - if (CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD != amdtopo.raw.type) { - hwloc_debug("not a PCIe device: %u\n", amdtopo.raw.type); - continue; - } - - info->type = HWLOC_OPENCL_DEVICE_AMD; - info->specific.amd.pcidomain = 0; - info->specific.amd.pcibus = amdtopo.pcie.bus; - info->specific.amd.pcidev = amdtopo.pcie.device; - info->specific.amd.pcifunc = amdtopo.pcie.function; - - hwloc_debug("OpenCL device on PCI 0000:%02x:%02x.%u\n", amdtopo.pcie.bus, amdtopo.pcie.device, amdtopo.pcie.function); - - /* validate this device */ - data->nr_devices++; -#endif /* HAVE_DECL_CL_DEVICE_TOPOLOGY_AMD */ - } - free(device_ids); - free(platform_ids); - return; - -out_with_device_ids: - free(device_ids); - free(data->devices); - data->devices = NULL; -out_with_platform_ids: - free(platform_ids); -out: - return; -} - -static int -hwloc_opencl_backend_notify_new_object(struct hwloc_backend *backend, struct hwloc_backend *caller __hwloc_attribute_unused, - struct hwloc_obj *pcidev) -{ - struct hwloc_topology *topology = backend->topology; - struct hwloc_opencl_backend_data_s *data = backend->private_data; - unsigned i; - - if (!(hwloc_topology_get_flags(topology) & (HWLOC_TOPOLOGY_FLAG_IO_DEVICES|HWLOC_TOPOLOGY_FLAG_WHOLE_IO))) - return 0; - - if (!hwloc_topology_is_thissystem(topology)) { - hwloc_debug("%s", "\nno OpenCL detection (not thissystem)\n"); - return 0; - } - - if (HWLOC_OBJ_PCI_DEVICE != pcidev->type) - return 0; - - if (data->nr_devices == (unsigned) -1) { - /* first call, lookup all devices */ - hwloc_opencl_query_devices(data); - /* if it fails, data->nr_devices = 0 so we won't do anything below and in next callbacks */ - } - - if (!data->nr_devices) - /* found no devices */ - return 0; - - /* now the devices array is ready to use */ - for(i=0; inr_devices; i++) { - struct hwloc_opencl_device_info_s *info = &data->devices[i]; - hwloc_obj_t osdev; - char buffer[64]; - - assert(info->type == HWLOC_OPENCL_DEVICE_AMD); - if (info->specific.amd.pcidomain != pcidev->attr->pcidev.domain) - continue; - if (info->specific.amd.pcibus != pcidev->attr->pcidev.bus) - continue; - if (info->specific.amd.pcidev != pcidev->attr->pcidev.dev) - continue; - if (info->specific.amd.pcifunc != pcidev->attr->pcidev.func) - continue; - - osdev = hwloc_alloc_setup_object(HWLOC_OBJ_OS_DEVICE, -1); - snprintf(buffer, sizeof(buffer), "opencl%dd%d", info->platformidx, info->platformdeviceidx); - osdev->name = strdup(buffer); - osdev->depth = (unsigned) HWLOC_TYPE_DEPTH_UNKNOWN; - osdev->attr->osdev.type = HWLOC_OBJ_OSDEV_COPROC; - - hwloc_obj_add_info(osdev, "CoProcType", "OpenCL"); - hwloc_obj_add_info(osdev, "Backend", "OpenCL"); - hwloc_obj_add_info(osdev, "OpenCLDeviceType", info->devicetype); - - if (info->devicevendor[0] != '\0') - hwloc_obj_add_info(osdev, "GPUVendor", info->devicevendor); - if (info->devicename[0] != '\0') - hwloc_obj_add_info(osdev, "GPUModel", info->devicename); - - snprintf(buffer, sizeof(buffer), "%u", info->platformidx); - hwloc_obj_add_info(osdev, "OpenCLPlatformIndex", buffer); - if (info->platformname[0] != '\0') - hwloc_obj_add_info(osdev, "OpenCLPlatformName", info->platformname); - - snprintf(buffer, sizeof(buffer), "%u", info->platformdeviceidx); - hwloc_obj_add_info(osdev, "OpenCLPlatformDeviceIndex", buffer); - - snprintf(buffer, sizeof(buffer), "%u", info->computeunits); - hwloc_obj_add_info(osdev, "OpenCLComputeUnits", buffer); - - snprintf(buffer, sizeof(buffer), "%llu", info->globalmemsize); - hwloc_obj_add_info(osdev, "OpenCLGlobalMemorySize", buffer); - - hwloc_insert_object_by_parent(topology, pcidev, osdev); - return 1; - } - - return 0; -} - -static void -hwloc_opencl_backend_disable(struct hwloc_backend *backend) -{ - struct hwloc_opencl_backend_data_s *data = backend->private_data; - free(data->devices); - free(data); -} - -static struct hwloc_backend * -hwloc_opencl_component_instantiate(struct hwloc_disc_component *component, - const void *_data1 __hwloc_attribute_unused, - const void *_data2 __hwloc_attribute_unused, - const void *_data3 __hwloc_attribute_unused) -{ - struct hwloc_backend *backend; - struct hwloc_opencl_backend_data_s *data; - - /* thissystem may not be fully initialized yet, we'll check flags in discover() */ - - backend = hwloc_backend_alloc(component); - if (!backend) - return NULL; - - data = malloc(sizeof(*data)); - if (!data) { - free(backend); - return NULL; - } - /* the first callback will initialize those */ - data->nr_devices = (unsigned) -1; /* unknown yet */ - data->devices = NULL; - - backend->private_data = data; - backend->disable = hwloc_opencl_backend_disable; - - backend->notify_new_object = hwloc_opencl_backend_notify_new_object; - return backend; -} - -static struct hwloc_disc_component hwloc_opencl_disc_component = { - HWLOC_DISC_COMPONENT_TYPE_MISC, - "opencl", - HWLOC_DISC_COMPONENT_TYPE_GLOBAL, - hwloc_opencl_component_instantiate, - 10, /* after pci */ - NULL -}; - -static int -hwloc_opencl_component_init(unsigned long flags) -{ - if (flags) - return -1; - if (hwloc_plugin_check_namespace("opencl", "hwloc_backend_alloc") < 0) - return -1; - return 0; -} - -#ifdef HWLOC_INSIDE_PLUGIN -HWLOC_DECLSPEC extern const struct hwloc_component hwloc_opencl_component; -#endif - -const struct hwloc_component hwloc_opencl_component = { - HWLOC_COMPONENT_ABI, - hwloc_opencl_component_init, NULL, - HWLOC_COMPONENT_TYPE_DISC, - 0, - &hwloc_opencl_disc_component -}; diff --git a/opal/mca/hwloc/hwloc1116/hwloc/src/topology-osf.c b/opal/mca/hwloc/hwloc1116/hwloc/src/topology-osf.c deleted file mode 100644 index 01276e2b1f..0000000000 --- a/opal/mca/hwloc/hwloc1116/hwloc/src/topology-osf.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright © 2009 CNRS - * Copyright © 2009-2016 Inria. All rights reserved. - * Copyright © 2009-2011 Université Bordeaux - * Copyright © 2011 Cisco Systems, Inc. All rights reserved. - * See COPYING in top-level directory. - */ - -#include - -#include -#ifdef HAVE_DIRENT_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -/* - * TODO - * - * nsg_init(), nsg_attach_pid(), RAD_MIGRATE/RAD_WAIT - * assign_pid_to_pset() - * - * pthread_use_only_cpu too? - */ - -static int -prepare_radset(hwloc_topology_t topology __hwloc_attribute_unused, radset_t *radset, hwloc_const_bitmap_t hwloc_set) -{ - unsigned cpu; - cpuset_t target_cpuset; - cpuset_t cpuset, xor_cpuset; - radid_t radid; - int ret = 0; - int ret_errno = 0; - int nbnodes = rad_get_num(); - - cpusetcreate(&target_cpuset); - cpuemptyset(target_cpuset); - hwloc_bitmap_foreach_begin(cpu, hwloc_set) - cpuaddset(target_cpuset, cpu); - hwloc_bitmap_foreach_end(); - - cpusetcreate(&cpuset); - cpusetcreate(&xor_cpuset); - for (radid = 0; radid < nbnodes; radid++) { - cpuemptyset(cpuset); - if (rad_get_cpus(radid, cpuset)==-1) { - fprintf(stderr,"rad_get_cpus(%d) failed: %s\n",radid,strerror(errno)); - continue; - } - cpuxorset(target_cpuset, cpuset, xor_cpuset); - if (cpucountset(xor_cpuset) == 0) { - /* Found it */ - radsetcreate(radset); - rademptyset(*radset); - radaddset(*radset, radid); - ret = 1; - goto out; - } - } - /* radset containing exactly this set of CPUs not found */ - ret_errno = EXDEV; - -out: - cpusetdestroy(&target_cpuset); - cpusetdestroy(&cpuset); - cpusetdestroy(&xor_cpuset); - errno = ret_errno; - return ret; -} - -/* Note: get_cpubind not available on OSF */ - -static int -hwloc_osf_set_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t thread, hwloc_const_bitmap_t hwloc_set, int flags) -{ - radset_t radset; - - if (hwloc_bitmap_isequal(hwloc_set, hwloc_topology_get_complete_cpuset(topology))) { - if ((errno = pthread_rad_detach(thread))) - return -1; - return 0; - } - - /* Apparently OSF migrates pages */ - if (flags & HWLOC_CPUBIND_NOMEMBIND) { - errno = ENOSYS; - return -1; - } - - if (!prepare_radset(topology, &radset, hwloc_set)) - return -1; - - if (flags & HWLOC_CPUBIND_STRICT) { - if ((errno = pthread_rad_bind(thread, radset, RAD_INSIST | RAD_WAIT))) - return -1; - } else { - if ((errno = pthread_rad_attach(thread, radset, RAD_WAIT))) - return -1; - } - radsetdestroy(&radset); - - return 0; -} - -static int -hwloc_osf_set_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_bitmap_t hwloc_set, int flags) -{ - radset_t radset; - - if (hwloc_bitmap_isequal(hwloc_set, hwloc_topology_get_complete_cpuset(topology))) { - if (rad_detach_pid(pid)) - return -1; - return 0; - } - - /* Apparently OSF migrates pages */ - if (flags & HWLOC_CPUBIND_NOMEMBIND) { - errno = ENOSYS; - return -1; - } - - if (!prepare_radset(topology, &radset, hwloc_set)) - return -1; - - if (flags & HWLOC_CPUBIND_STRICT) { - if (rad_bind_pid(pid, radset, RAD_INSIST | RAD_WAIT)) - return -1; - } else { - if (rad_attach_pid(pid, radset, RAD_WAIT)) - return -1; - } - radsetdestroy(&radset); - - return 0; -} - -static int -hwloc_osf_set_thisthread_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags) -{ - return hwloc_osf_set_thread_cpubind(topology, pthread_self(), hwloc_set, flags); -} - -static int -hwloc_osf_set_thisproc_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags) -{ - return hwloc_osf_set_proc_cpubind(topology, getpid(), hwloc_set, flags); -} - -static int -hwloc_osf_prepare_mattr(hwloc_topology_t topology __hwloc_attribute_unused, memalloc_attr_t *mattr, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags __hwloc_attribute_unused) -{ - unsigned long osf_policy; - int node; - - switch (policy) { - case HWLOC_MEMBIND_FIRSTTOUCH: - osf_policy = MPOL_THREAD; - break; - case HWLOC_MEMBIND_DEFAULT: - case HWLOC_MEMBIND_BIND: - osf_policy = MPOL_DIRECTED; - break; - case HWLOC_MEMBIND_INTERLEAVE: - osf_policy = MPOL_STRIPPED; - break; - case HWLOC_MEMBIND_REPLICATE: - osf_policy = MPOL_REPLICATED; - break; - default: - errno = ENOSYS; - return -1; - } - - memset(mattr, 0, sizeof(*mattr)); - mattr->mattr_policy = osf_policy; - mattr->mattr_rad = RAD_NONE; - radsetcreate(&mattr->mattr_radset); - rademptyset(mattr->mattr_radset); - - hwloc_bitmap_foreach_begin(node, nodeset) - radaddset(mattr->mattr_radset, node); - hwloc_bitmap_foreach_end(); - return 0; -} - -static int -hwloc_osf_set_area_membind(hwloc_topology_t topology, const void *addr, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) -{ - memalloc_attr_t mattr; - int behavior = 0; - int ret; - - if (flags & HWLOC_MEMBIND_MIGRATE) - behavior |= MADV_CURRENT; - if (flags & HWLOC_MEMBIND_STRICT) - behavior |= MADV_INSIST; - - if (hwloc_osf_prepare_mattr(topology, &mattr, nodeset, policy, flags)) - return -1; - - ret = nmadvise(addr, len, MADV_CURRENT, &mattr); - radsetdestroy(&mattr.mattr_radset); - return ret; -} - -static void * -hwloc_osf_alloc_membind(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) -{ - memalloc_attr_t mattr; - void *ptr; - - if (hwloc_osf_prepare_mattr(topology, &mattr, nodeset, policy, flags)) - return hwloc_alloc_or_fail(topology, len, flags); - - /* TODO: rather use acreate/amalloc ? */ - ptr = nmmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, - 0, &mattr); - radsetdestroy(&mattr.mattr_radset); - return ptr == MAP_FAILED ? NULL : ptr; -} - -static int -hwloc_look_osf(struct hwloc_backend *backend) -{ - struct hwloc_topology *topology = backend->topology; - cpu_cursor_t cursor; - unsigned nbnodes; - radid_t radid, radid2; - radset_t radset, radset2; - cpuid_t cpuid; - cpuset_t cpuset; - struct hwloc_obj *obj; - unsigned distance; - - if (topology->levels[0][0]->cpuset) - /* somebody discovered things */ - return 0; - - hwloc_alloc_obj_cpusets(topology->levels[0][0]); - - nbnodes = rad_get_num(); - - cpusetcreate(&cpuset); - radsetcreate(&radset); - radsetcreate(&radset2); - { - hwloc_obj_t *nodes = calloc(nbnodes, sizeof(hwloc_obj_t)); - unsigned *indexes = calloc(nbnodes, sizeof(unsigned)); - float *distances = calloc(nbnodes*nbnodes, sizeof(float)); - unsigned nfound; - numa_attr_t attr; - - attr.nattr_type = R_RAD; - attr.nattr_descr.rd_radset = radset; - attr.nattr_flags = 0; - - for (radid = 0; radid < (radid_t) nbnodes; radid++) { - rademptyset(radset); - radaddset(radset, radid); - cpuemptyset(cpuset); - if (rad_get_cpus(radid, cpuset)==-1) { - fprintf(stderr,"rad_get_cpus(%d) failed: %s\n",radid,strerror(errno)); - continue; - } - - indexes[radid] = radid; - nodes[radid] = obj = hwloc_alloc_setup_object(HWLOC_OBJ_NUMANODE, radid); - obj->nodeset = hwloc_bitmap_alloc(); - hwloc_bitmap_set(obj->nodeset, radid); - obj->cpuset = hwloc_bitmap_alloc(); - obj->memory.local_memory = rad_get_physmem(radid) * hwloc_getpagesize(); - obj->memory.page_types_len = 2; - obj->memory.page_types = malloc(2*sizeof(*obj->memory.page_types)); - memset(obj->memory.page_types, 0, 2*sizeof(*obj->memory.page_types)); - obj->memory.page_types[0].size = hwloc_getpagesize(); -#if HAVE_DECL__SC_LARGE_PAGESIZE - obj->memory.page_types[1].size = sysconf(_SC_LARGE_PAGESIZE); -#endif - - cursor = SET_CURSOR_INIT; - while((cpuid = cpu_foreach(cpuset, 0, &cursor)) != CPU_NONE) - hwloc_bitmap_set(obj->cpuset, cpuid); - - hwloc_debug_1arg_bitmap("node %d has cpuset %s\n", - radid, obj->cpuset); - - hwloc_insert_object_by_cpuset(topology, obj); - - nfound = 0; - for (radid2 = 0; radid2 < (radid_t) nbnodes; radid2++) - distances[radid*nbnodes+radid2] = RAD_DIST_REMOTE; - for (distance = RAD_DIST_LOCAL; distance < RAD_DIST_REMOTE; distance++) { - attr.nattr_distance = distance; - /* get set of NUMA nodes at distance <= DISTANCE */ - if (nloc(&attr, radset2)) { - fprintf(stderr,"nloc failed: %s\n", strerror(errno)); - continue; - } - cursor = SET_CURSOR_INIT; - while ((radid2 = rad_foreach(radset2, 0, &cursor)) != RAD_NONE) { - if (distances[radid*nbnodes+radid2] == RAD_DIST_REMOTE) { - distances[radid*nbnodes+radid2] = (float) distance; - nfound++; - } - } - if (nfound == nbnodes) - /* Finished finding distances, no need to go up to RAD_DIST_REMOTE */ - break; - } - } - - hwloc_distances_set(topology, HWLOC_OBJ_NUMANODE, nbnodes, indexes, nodes, distances, 0 /* OS cannot force */); - } - radsetdestroy(&radset2); - radsetdestroy(&radset); - cpusetdestroy(&cpuset); - - /* add PU objects */ - hwloc_setup_pu_level(topology, hwloc_fallback_nbprocessors(topology)); - - hwloc_obj_add_info(topology->levels[0][0], "Backend", "OSF"); - if (topology->is_thissystem) - hwloc_add_uname_info(topology, NULL); - return 1; -} - -void -hwloc_set_osf_hooks(struct hwloc_binding_hooks *hooks, - struct hwloc_topology_support *support) -{ - hooks->set_thread_cpubind = hwloc_osf_set_thread_cpubind; - hooks->set_thisthread_cpubind = hwloc_osf_set_thisthread_cpubind; - hooks->set_proc_cpubind = hwloc_osf_set_proc_cpubind; - hooks->set_thisproc_cpubind = hwloc_osf_set_thisproc_cpubind; - hooks->set_area_membind = hwloc_osf_set_area_membind; - hooks->alloc_membind = hwloc_osf_alloc_membind; - hooks->alloc = hwloc_alloc_mmap; - hooks->free_membind = hwloc_free_mmap; - support->membind->firsttouch_membind = 1; - support->membind->bind_membind = 1; - support->membind->interleave_membind = 1; - support->membind->replicate_membind = 1; -} - -static struct hwloc_backend * -hwloc_osf_component_instantiate(struct hwloc_disc_component *component, - const void *_data1 __hwloc_attribute_unused, - const void *_data2 __hwloc_attribute_unused, - const void *_data3 __hwloc_attribute_unused) -{ - struct hwloc_backend *backend; - backend = hwloc_backend_alloc(component); - if (!backend) - return NULL; - backend->discover = hwloc_look_osf; - return backend; -} - -static struct hwloc_disc_component hwloc_osf_disc_component = { - HWLOC_DISC_COMPONENT_TYPE_CPU, - "osf", - HWLOC_DISC_COMPONENT_TYPE_GLOBAL, - hwloc_osf_component_instantiate, - 50, - NULL -}; - -const struct hwloc_component hwloc_osf_component = { - HWLOC_COMPONENT_ABI, - NULL, NULL, - HWLOC_COMPONENT_TYPE_DISC, - 0, - &hwloc_osf_disc_component -}; diff --git a/opal/mca/hwloc/hwloc1116/hwloc/src/topology-x86.c b/opal/mca/hwloc/hwloc1116/hwloc/src/topology-x86.c deleted file mode 100644 index 3ab4eaf0c9..0000000000 --- a/opal/mca/hwloc/hwloc1116/hwloc/src/topology-x86.c +++ /dev/null @@ -1,1233 +0,0 @@ -/* - * Copyright © 2010-2017 Inria. All rights reserved. - * Copyright © 2010-2013 Université Bordeaux - * Copyright © 2010-2011 Cisco Systems, Inc. All rights reserved. - * See COPYING in top-level directory. - * - * - * This backend is only used when the operating system does not export - * the necessary hardware topology information to user-space applications. - * Currently, only the FreeBSD backend relies on this x86 backend. - * - * Other backends such as Linux have their own way to retrieve various - * pieces of hardware topology information from the operating system - * on various architectures, without having to use this x86-specific code. - */ - -#include -#include -#include -#include -#include - -#include - -#ifdef HAVE_VALGRIND_VALGRIND_H -#include -#endif - -struct hwloc_x86_backend_data_s { - unsigned nbprocs; - hwloc_bitmap_t apicid_set; - int apicid_unique; - int is_knl; -}; - -#define has_topoext(features) ((features)[6] & (1 << 22)) -#define has_x2apic(features) ((features)[4] & (1 << 21)) - -struct cacheinfo { - unsigned type; - unsigned level; - unsigned nbthreads_sharing; - unsigned cacheid; - - unsigned linesize; - unsigned linepart; - int inclusive; - int ways; - unsigned sets; - unsigned long size; -}; - -struct procinfo { - unsigned present; - unsigned apicid; - unsigned max_log_proc; - unsigned max_nbcores; - unsigned max_nbthreads; - unsigned packageid; - unsigned nodeid; - unsigned unitid; - unsigned logprocid; - unsigned threadid; - unsigned coreid; - unsigned *otherids; - unsigned levels; - unsigned numcaches; - struct cacheinfo *cache; - char cpuvendor[13]; - char cpumodel[3*4*4+1]; - unsigned cpustepping; - unsigned cpumodelnumber; - unsigned cpufamilynumber; -}; - -enum cpuid_type { - intel, - amd, - unknown -}; - -static void fill_amd_cache(struct procinfo *infos, unsigned level, int type, unsigned cpuid) -{ - struct cacheinfo *cache, *tmpcaches; - unsigned cachenum; - unsigned long size = 0; - - if (level == 1) - size = ((cpuid >> 24)) << 10; - else if (level == 2) - size = ((cpuid >> 16)) << 10; - else if (level == 3) - size = ((cpuid >> 18)) << 19; - if (!size) - return; - - tmpcaches = realloc(infos->cache, (infos->numcaches+1)*sizeof(*infos->cache)); - if (!tmpcaches) - /* failed to allocated, ignore that cache */ - return; - infos->cache = tmpcaches; - cachenum = infos->numcaches++; - - cache = &infos->cache[cachenum]; - - cache->type = type; - cache->level = level; - if (level <= 2) - cache->nbthreads_sharing = 1; - else - cache->nbthreads_sharing = infos->max_log_proc; - cache->linesize = cpuid & 0xff; - cache->linepart = 0; - cache->inclusive = 0; /* old AMD (K8-K10) supposed to have exclusive caches */ - - if (level == 1) { - cache->ways = (cpuid >> 16) & 0xff; - if (cache->ways == 0xff) - /* Fully associative */ - cache->ways = -1; - } else { - static const unsigned ways_tab[] = { 0, 1, 2, 0, 4, 0, 8, 0, 16, 0, 32, 48, 64, 96, 128, -1 }; - unsigned ways = (cpuid >> 12) & 0xf; - cache->ways = ways_tab[ways]; - } - cache->size = size; - cache->sets = 0; - - hwloc_debug("cache L%u t%u linesize %u ways %u size %luKB\n", cache->level, cache->nbthreads_sharing, cache->linesize, cache->ways, cache->size >> 10); -} - -/* Fetch information from the processor itself thanks to cpuid and store it in - * infos for summarize to analyze them globally */ -static void look_proc(struct hwloc_backend *backend, struct procinfo *infos, unsigned highest_cpuid, unsigned highest_ext_cpuid, unsigned *features, enum cpuid_type cpuid_type) -{ - struct hwloc_x86_backend_data_s *data = backend->private_data; - unsigned eax, ebx, ecx = 0, edx; - unsigned cachenum; - struct cacheinfo *cache; - unsigned regs[4]; - unsigned _model, _extendedmodel, _family, _extendedfamily; - - infos->present = 1; - - /* on return from this function, the following fields must be set in infos: - * packageid, nodeid, unitid, coreid, threadid, or -1 - * apicid - * levels and levels slots in otherids[] - * numcaches and numcaches slots in caches[] - * - * max_log_proc, max_nbthreads, max_nbcores, logprocid - * are only used temporarily inside this function and its callees. - */ - - /* Get apicid, max_log_proc, packageid, logprocid from cpuid 0x01 */ - eax = 0x01; - hwloc_x86_cpuid(&eax, &ebx, &ecx, &edx); - infos->apicid = ebx >> 24; - if (edx & (1 << 28)) - infos->max_log_proc = 1 << hwloc_flsl(((ebx >> 16) & 0xff) - 1); - else - infos->max_log_proc = 1; - hwloc_debug("APIC ID 0x%02x max_log_proc %u\n", infos->apicid, infos->max_log_proc); - infos->packageid = infos->apicid / infos->max_log_proc; - infos->logprocid = infos->apicid % infos->max_log_proc; - hwloc_debug("phys %u thread %u\n", infos->packageid, infos->logprocid); - - /* Get cpu model/family/stepping numbers from same cpuid */ - _model = (eax>>4) & 0xf; - _extendedmodel = (eax>>16) & 0xf; - _family = (eax>>8) & 0xf; - _extendedfamily = (eax>>20) & 0xff; - if ((cpuid_type == intel || cpuid_type == amd) && _family == 0xf) { - infos->cpufamilynumber = _family + _extendedfamily; - } else { - infos->cpufamilynumber = _family; - } - if ((cpuid_type == intel && (_family == 0x6 || _family == 0xf)) - || (cpuid_type == amd && _family == 0xf)) { - infos->cpumodelnumber = _model + (_extendedmodel << 4); - } else { - infos->cpumodelnumber = _model; - } - infos->cpustepping = eax & 0xf; - - if (cpuid_type == intel && infos->cpufamilynumber == 0x6 && - (infos->cpumodelnumber == 0x57 || infos->cpumodelnumber == 0x85)) - data->is_knl = 1; /* KNM is the same as KNL */ - - /* Get cpu vendor string from cpuid 0x00 */ - memset(regs, 0, sizeof(regs)); - regs[0] = 0; - hwloc_x86_cpuid(®s[0], ®s[1], ®s[3], ®s[2]); - memcpy(infos->cpuvendor, regs+1, 4*3); - /* infos was calloc'ed, already ends with \0 */ - - /* Get cpu model string from cpuid 0x80000002-4 */ - if (highest_ext_cpuid >= 0x80000004) { - memset(regs, 0, sizeof(regs)); - regs[0] = 0x80000002; - hwloc_x86_cpuid(®s[0], ®s[1], ®s[2], ®s[3]); - memcpy(infos->cpumodel, regs, 4*4); - regs[0] = 0x80000003; - hwloc_x86_cpuid(®s[0], ®s[1], ®s[2], ®s[3]); - memcpy(infos->cpumodel + 4*4, regs, 4*4); - regs[0] = 0x80000004; - hwloc_x86_cpuid(®s[0], ®s[1], ®s[2], ®s[3]); - memcpy(infos->cpumodel + 4*4*2, regs, 4*4); - /* infos was calloc'ed, already ends with \0 */ - } - - /* Get core/thread information from cpuid 0x80000008 - * (not supported on Intel) - */ - if (cpuid_type != intel && highest_ext_cpuid >= 0x80000008) { - unsigned coreidsize; - eax = 0x80000008; - hwloc_x86_cpuid(&eax, &ebx, &ecx, &edx); - coreidsize = (ecx >> 12) & 0xf; - hwloc_debug("core ID size: %u\n", coreidsize); - if (!coreidsize) { - infos->max_nbcores = (ecx & 0xff) + 1; - } else - infos->max_nbcores = 1 << coreidsize; - hwloc_debug("Thus max # of cores: %u\n", infos->max_nbcores); - /* Still no multithreaded AMD */ - infos->max_nbthreads = 1 ; - hwloc_debug("and max # of threads: %u\n", infos->max_nbthreads); - /* The legacy max_log_proc is deprecated, it can be smaller than max_nbcores, - * which is the maximum number of cores that the processor could theoretically support - * (see "Multiple Core Calculation" in the AMD CPUID specification). - * Recompute packageid/logprocid/threadid/coreid accordingly. - */ - infos->packageid = infos->apicid / infos->max_nbcores; - infos->logprocid = infos->apicid % infos->max_nbcores; - infos->threadid = infos->logprocid % infos->max_nbthreads; - infos->coreid = infos->logprocid / infos->max_nbthreads; - hwloc_debug("this is thread %u of core %u\n", infos->threadid, infos->coreid); - } - - infos->numcaches = 0; - infos->cache = NULL; - - /* Get apicid, nodeid, unitid from cpuid 0x8000001e - * and cache information from cpuid 0x8000001d - * (AMD topology extension) - */ - if (cpuid_type != intel && has_topoext(features)) { - unsigned apic_id, node_id, nodes_per_proc; - - eax = 0x8000001e; - hwloc_x86_cpuid(&eax, &ebx, &ecx, &edx); - infos->apicid = apic_id = eax; - - if (infos->cpufamilynumber == 0x16) { - /* ecx is reserved */ - node_id = 0; - nodes_per_proc = 1; - } else { - node_id = ecx & 0xff; - nodes_per_proc = ((ecx >> 8) & 7) + 1; - } - infos->nodeid = node_id; - if ((infos->cpufamilynumber == 0x15 && nodes_per_proc > 2) - || (infos->cpufamilynumber == 0x17 && nodes_per_proc > 4)) { - hwloc_debug("warning: undefined nodes_per_proc value %d, assuming it means %d\n", nodes_per_proc, nodes_per_proc); - } - - if (infos->cpufamilynumber <= 0x16) { /* topoext appeared in 0x15 and compute-units were only used in 0x15 and 0x16 */ - unsigned unit_id, cores_per_unit; - infos->unitid = unit_id = ebx & 0xff; - cores_per_unit = ((ebx >> 8) & 0xff) + 1; - hwloc_debug("topoext %08x, %d nodes, node %d, %d cores in unit %d\n", apic_id, nodes_per_proc, node_id, cores_per_unit, unit_id); - } else { - unsigned core_id, threads_per_core; - infos->coreid = core_id = ebx & 0xff; - threads_per_core = ((ebx >> 8) & 0xff) + 1; - hwloc_debug("topoext %08x, %d nodes, node %d, %d threads in core %d\n", apic_id, nodes_per_proc, node_id, threads_per_core, core_id); - } - - for (cachenum = 0; ; cachenum++) { - unsigned type; - eax = 0x8000001d; - ecx = cachenum; - hwloc_x86_cpuid(&eax, &ebx, &ecx, &edx); - type = eax & 0x1f; - if (type == 0) - break; - infos->numcaches++; - } - - cache = infos->cache = malloc(infos->numcaches * sizeof(*infos->cache)); - - for (cachenum = 0; ; cachenum++) { - unsigned long linesize, linepart, ways, sets; - unsigned type; - eax = 0x8000001d; - ecx = cachenum; - hwloc_x86_cpuid(&eax, &ebx, &ecx, &edx); - - type = eax & 0x1f; - - if (type == 0) - break; - - cache->type = type; - cache->level = (eax >> 5) & 0x7; - /* Note: actually number of cores */ - cache->nbthreads_sharing = ((eax >> 14) & 0xfff) + 1; - - cache->linesize = linesize = (ebx & 0xfff) + 1; - cache->linepart = linepart = ((ebx >> 12) & 0x3ff) + 1; - ways = ((ebx >> 22) & 0x3ff) + 1; - - if (eax & (1 << 9)) - /* Fully associative */ - cache->ways = -1; - else - cache->ways = ways; - cache->sets = sets = ecx + 1; - cache->size = linesize * linepart * ways * sets; - cache->inclusive = edx & 0x2; - - hwloc_debug("cache %u type %u L%u t%u c%u linesize %lu linepart %lu ways %lu sets %lu, size %uKB\n", cachenum, cache->type, cache->level, cache->nbthreads_sharing, infos->max_nbcores, linesize, linepart, ways, sets, cache->size >> 10); - - cache++; - } - } else { - /* If there's no topoext, - * get cache information from cpuid 0x80000005 and 0x80000006 - * (not supported on Intel) - */ - if (cpuid_type != intel && highest_ext_cpuid >= 0x80000005) { - eax = 0x80000005; - hwloc_x86_cpuid(&eax, &ebx, &ecx, &edx); - fill_amd_cache(infos, 1, 1, ecx); /* L1d */ - fill_amd_cache(infos, 1, 2, edx); /* L1i */ - } - if (cpuid_type != intel && highest_ext_cpuid >= 0x80000006) { - eax = 0x80000006; - hwloc_x86_cpuid(&eax, &ebx, &ecx, &edx); - if (ecx & 0xf000) - /* This is actually supported on Intel but LinePerTag isn't returned in bits 8-11. - * Could be useful if some Intels (at least before Core micro-architecture) - * support this leaf without leaf 0x4. - */ - fill_amd_cache(infos, 2, 3, ecx); /* L2u */ - if (edx & 0xf000) - fill_amd_cache(infos, 3, 3, edx); /* L3u */ - } - } - - /* Get thread/core + cache information from cpuid 0x04 - * (not supported on AMD) - */ - if (cpuid_type != amd && highest_cpuid >= 0x04) { - unsigned level; - for (cachenum = 0; ; cachenum++) { - unsigned type; - eax = 0x04; - ecx = cachenum; - hwloc_x86_cpuid(&eax, &ebx, &ecx, &edx); - - type = eax & 0x1f; - - hwloc_debug("cache %u type %u\n", cachenum, type); - - if (type == 0) - break; - level = (eax >> 5) & 0x7; - if (data->is_knl && level == 3) - /* KNL reports wrong L3 information (size always 0, cpuset always the entire machine, ignore it */ - break; - infos->numcaches++; - - if (!cachenum) { - /* by the way, get thread/core information from the first cache */ - infos->max_nbcores = ((eax >> 26) & 0x3f) + 1; - infos->max_nbthreads = infos->max_log_proc / infos->max_nbcores; - hwloc_debug("thus %u threads\n", infos->max_nbthreads); - infos->threadid = infos->logprocid % infos->max_nbthreads; - infos->coreid = infos->logprocid / infos->max_nbthreads; - hwloc_debug("this is thread %u of core %u\n", infos->threadid, infos->coreid); - } - } - - cache = infos->cache = malloc(infos->numcaches * sizeof(*infos->cache)); - - for (cachenum = 0; ; cachenum++) { - unsigned long linesize, linepart, ways, sets; - unsigned type; - eax = 0x04; - ecx = cachenum; - hwloc_x86_cpuid(&eax, &ebx, &ecx, &edx); - - type = eax & 0x1f; - - if (type == 0) - break; - level = (eax >> 5) & 0x7; - if (data->is_knl && level == 3) - /* KNL reports wrong L3 information (size always 0, cpuset always the entire machine, ignore it */ - break; - - cache->type = type; - cache->level = level; - cache->nbthreads_sharing = ((eax >> 14) & 0xfff) + 1; - - cache->linesize = linesize = (ebx & 0xfff) + 1; - cache->linepart = linepart = ((ebx >> 12) & 0x3ff) + 1; - ways = ((ebx >> 22) & 0x3ff) + 1; - if (eax & (1 << 9)) - /* Fully associative */ - cache->ways = -1; - else - cache->ways = ways; - cache->sets = sets = ecx + 1; - cache->size = linesize * linepart * ways * sets; - cache->inclusive = edx & 0x2; - - hwloc_debug("cache %u type %u L%u t%u c%u linesize %lu linepart %lu ways %lu sets %lu, size %uKB\n", cachenum, cache->type, cache->level, cache->nbthreads_sharing, infos->max_nbcores, linesize, linepart, ways, sets, cache->size >> 10); - - cache++; - } - } - - /* Get package/core/thread information from cpuid 0x0b - * (Intel x2APIC) - */ - if (cpuid_type == intel && highest_cpuid >= 0x0b && has_x2apic(features)) { - unsigned level, apic_nextshift, apic_number, apic_type, apic_id = 0, apic_shift = 0, id; - for (level = 0; ; level++) { - ecx = level; - eax = 0x0b; - hwloc_x86_cpuid(&eax, &ebx, &ecx, &edx); - if (!eax && !ebx) - break; - } - if (level) { - infos->levels = level; - infos->otherids = malloc(level * sizeof(*infos->otherids)); - for (level = 0; ; level++) { - ecx = level; - eax = 0x0b; - hwloc_x86_cpuid(&eax, &ebx, &ecx, &edx); - if (!eax && !ebx) - break; - apic_nextshift = eax & 0x1f; - apic_number = ebx & 0xffff; - apic_type = (ecx & 0xff00) >> 8; - apic_id = edx; - id = (apic_id >> apic_shift) & ((1 << (apic_nextshift - apic_shift)) - 1); - hwloc_debug("x2APIC %08x %d: nextshift %d num %2d type %d id %2d\n", apic_id, level, apic_nextshift, apic_number, apic_type, id); - infos->apicid = apic_id; - infos->otherids[level] = UINT_MAX; - switch (apic_type) { - case 1: - infos->threadid = id; - break; - case 2: - infos->coreid = id; - break; - default: - hwloc_debug("x2APIC %d: unknown type %d\n", level, apic_type); - infos->otherids[level] = apic_id >> apic_shift; - break; - } - apic_shift = apic_nextshift; - } - infos->apicid = apic_id; - infos->packageid = apic_id >> apic_shift; - hwloc_debug("x2APIC remainder: %d\n", infos->packageid); - hwloc_debug("this is thread %u of core %u\n", infos->threadid, infos->coreid); - } - } - - /* Now that we have all info, compute cacheids and apply quirks */ - for (cachenum = 0; cachenum < infos->numcaches; cachenum++) { - struct cacheinfo *cache = &infos->cache[cachenum]; - - /* default cacheid value */ - cache->cacheid = infos->apicid / cache->nbthreads_sharing; - - /* AMD quirk */ - if (cpuid_type == amd - && infos->cpufamilynumber== 0x10 && infos->cpumodelnumber == 0x9 - && cache->level == 3 - && (cache->ways == -1 || (cache->ways % 2 == 0)) && cache->nbthreads_sharing >= 8) { - /* Fix AMD family 0x10 model 0x9 (Magny-Cours) with 8 or 12 cores. - * The L3 (and its associativity) is actually split into two halves). - */ - if (cache->nbthreads_sharing == 16) - cache->nbthreads_sharing = 12; /* nbthreads_sharing is a power of 2 but the processor actually has 8 or 12 cores */ - cache->nbthreads_sharing /= 2; - cache->size /= 2; - if (cache->ways != -1) - cache->ways /= 2; - /* AMD Magny-Cours 12-cores processor reserve APIC ids as AAAAAABBBBBB.... - * among first L3 (A), second L3 (B), and unexisting cores (.). - * On multi-socket servers, L3 in non-first sockets may have APIC id ranges - * such as [16-21] that are not aligned on multiple of nbthreads_sharing (6). - * That means, we can't just compare apicid/nbthreads_sharing to identify siblings. - */ - cache->cacheid = (infos->apicid % infos->max_log_proc) / cache->nbthreads_sharing /* cacheid within the package */ - + 2 * (infos->apicid / infos->max_log_proc); /* add 2 caches per previous package */ - - } else if (cpuid_type == amd - && infos->cpufamilynumber == 0x15 - && (infos->cpumodelnumber == 0x1 /* Bulldozer */ || infos->cpumodelnumber == 0x2 /* Piledriver */) - && cache->level == 3 && cache->nbthreads_sharing == 6) { - /* AMD Bulldozer and Piledriver 12-core processors have same APIC ids as Magny-Cours above, - * but we can't merge the checks because the original nbthreads_sharing must be exactly 6 here. - */ - cache->cacheid = (infos->apicid % infos->max_log_proc) / cache->nbthreads_sharing /* cacheid within the package */ - + 2 * (infos->apicid / infos->max_log_proc); /* add 2 cache per previous package */ - } - } - - if (hwloc_bitmap_isset(data->apicid_set, infos->apicid)) - data->apicid_unique = 0; - else - hwloc_bitmap_set(data->apicid_set, infos->apicid); -} - -static void -hwloc_x86_add_cpuinfos(hwloc_obj_t obj, struct procinfo *info, int nodup) -{ - char number[8]; - hwloc_obj_add_info_nodup(obj, "CPUVendor", info->cpuvendor, nodup); - snprintf(number, sizeof(number), "%u", info->cpufamilynumber); - hwloc_obj_add_info_nodup(obj, "CPUFamilyNumber", number, nodup); - snprintf(number, sizeof(number), "%u", info->cpumodelnumber); - hwloc_obj_add_info_nodup(obj, "CPUModelNumber", number, nodup); - if (info->cpumodel[0]) { - const char *c = info->cpumodel; - while (*c == ' ') - c++; - hwloc_obj_add_info_nodup(obj, "CPUModel", c, nodup); - } - snprintf(number, sizeof(number), "%u", info->cpustepping); - hwloc_obj_add_info_nodup(obj, "CPUStepping", number, nodup); -} - -/* Analyse information stored in infos, and build/annotate topology levels accordingly */ -static int summarize(struct hwloc_backend *backend, struct procinfo *infos, int fulldiscovery) -{ - struct hwloc_topology *topology = backend->topology; - struct hwloc_x86_backend_data_s *data = backend->private_data; - unsigned nbprocs = data->nbprocs; - hwloc_bitmap_t complete_cpuset = hwloc_bitmap_alloc(); - unsigned i, j, l, level, type; - unsigned nbpackages = 0; - int one = -1; - unsigned next_group_depth = topology->next_group_depth; - int caches_added = 0; - hwloc_bitmap_t remaining_cpuset; - - for (i = 0; i < nbprocs; i++) - if (infos[i].present) { - hwloc_bitmap_set(complete_cpuset, i); - one = i; - } - - if (one == -1) { - hwloc_bitmap_free(complete_cpuset); - return 0; - } - - remaining_cpuset = hwloc_bitmap_alloc(); - - /* Ideally, when fulldiscovery=0, we could add any object that doesn't exist yet. - * But what if the x86 and the native backends disagree because one is buggy? Which one to trust? - * Only annotate existing objects for now. - */ - - /* Look for packages */ - if (fulldiscovery) { - hwloc_bitmap_t package_cpuset; - hwloc_obj_t package; - - hwloc_bitmap_copy(remaining_cpuset, complete_cpuset); - while ((i = hwloc_bitmap_first(remaining_cpuset)) != (unsigned) -1) { - unsigned packageid = infos[i].packageid; - - package_cpuset = hwloc_bitmap_alloc(); - for (j = i; j < nbprocs; j++) { - if (infos[j].packageid == packageid) { - hwloc_bitmap_set(package_cpuset, j); - hwloc_bitmap_clr(remaining_cpuset, j); - } - } - package = hwloc_alloc_setup_object(HWLOC_OBJ_PACKAGE, packageid); - package->cpuset = package_cpuset; - - hwloc_x86_add_cpuinfos(package, &infos[i], 0); - - hwloc_debug_1arg_bitmap("os package %u has cpuset %s\n", - packageid, package_cpuset); - hwloc_insert_object_by_cpuset(topology, package); - nbpackages++; - } - - } else { - /* Annotate packages previously-existing packages */ - hwloc_obj_t package = NULL; - int same = 1; - nbpackages = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_PACKAGE); - /* check whether all packages have the same info */ - for(i=1; ios_index == (unsigned) -1) { - /* try to fix the package OS index if unknown. - * FIXME: ideally, we should check all bits in case x86 and the native backend disagree. - */ - for(i=0; icpuset, i)) { - package->os_index = infos[i].packageid; - break; - } - } - } - for(i=0; ios_index || (same && package->os_index == (unsigned) -1)) { - hwloc_x86_add_cpuinfos(package, &infos[i], 1); - break; - } - } - } - } - /* If there was no package, annotate the Machine instead */ - if ((!nbpackages) && infos[0].cpumodel[0]) { - hwloc_x86_add_cpuinfos(hwloc_get_root_obj(topology), &infos[0], 1); - } - - /* Look for Numa nodes inside packages */ - if (fulldiscovery) { - hwloc_bitmap_t node_cpuset; - hwloc_obj_t node; - - hwloc_bitmap_copy(remaining_cpuset, complete_cpuset); - while ((i = hwloc_bitmap_first(remaining_cpuset)) != (unsigned) -1) { - unsigned packageid = infos[i].packageid; - unsigned nodeid = infos[i].nodeid; - - if (nodeid == (unsigned)-1) { - hwloc_bitmap_clr(remaining_cpuset, i); - continue; - } - - node_cpuset = hwloc_bitmap_alloc(); - for (j = i; j < nbprocs; j++) { - if (infos[j].nodeid == (unsigned) -1) { - hwloc_bitmap_clr(remaining_cpuset, j); - continue; - } - - if (infos[j].packageid == packageid && infos[j].nodeid == nodeid) { - hwloc_bitmap_set(node_cpuset, j); - hwloc_bitmap_clr(remaining_cpuset, j); - } - } - node = hwloc_alloc_setup_object(HWLOC_OBJ_NUMANODE, nodeid); - node->cpuset = node_cpuset; - node->nodeset = hwloc_bitmap_alloc(); - hwloc_bitmap_set(node->nodeset, nodeid); - hwloc_debug_1arg_bitmap("os node %u has cpuset %s\n", - nodeid, node_cpuset); - hwloc_insert_object_by_cpuset(topology, node); - } - } - - /* Look for Compute units inside packages */ - if (fulldiscovery) { - hwloc_bitmap_t unit_cpuset; - hwloc_obj_t unit; - - hwloc_bitmap_copy(remaining_cpuset, complete_cpuset); - while ((i = hwloc_bitmap_first(remaining_cpuset)) != (unsigned) -1) { - unsigned packageid = infos[i].packageid; - unsigned unitid = infos[i].unitid; - - if (unitid == (unsigned)-1) { - hwloc_bitmap_clr(remaining_cpuset, i); - continue; - } - - unit_cpuset = hwloc_bitmap_alloc(); - for (j = i; j < nbprocs; j++) { - if (infos[j].unitid == (unsigned) -1) { - hwloc_bitmap_clr(remaining_cpuset, j); - continue; - } - - if (infos[j].packageid == packageid && infos[j].unitid == unitid) { - hwloc_bitmap_set(unit_cpuset, j); - hwloc_bitmap_clr(remaining_cpuset, j); - } - } - unit = hwloc_alloc_setup_object(HWLOC_OBJ_GROUP, unitid); - unit->cpuset = unit_cpuset; - hwloc_obj_add_info(unit, "Type", "ComputeUnit"); - hwloc_debug_1arg_bitmap("os unit %u has cpuset %s\n", - unitid, unit_cpuset); - hwloc_insert_object_by_cpuset(topology, unit); - } - } - - /* Look for unknown objects */ - if (infos[one].otherids) { - for (level = infos[one].levels-1; level <= infos[one].levels-1; level--) { - if (infos[one].otherids[level] != UINT_MAX) { - hwloc_bitmap_t unknown_cpuset; - hwloc_obj_t unknown_obj; - - hwloc_bitmap_copy(remaining_cpuset, complete_cpuset); - while ((i = hwloc_bitmap_first(remaining_cpuset)) != (unsigned) -1) { - unsigned unknownid = infos[i].otherids[level]; - - unknown_cpuset = hwloc_bitmap_alloc(); - for (j = i; j < nbprocs; j++) { - if (infos[j].otherids[level] == unknownid) { - hwloc_bitmap_set(unknown_cpuset, j); - hwloc_bitmap_clr(remaining_cpuset, j); - } - } - unknown_obj = hwloc_alloc_setup_object(HWLOC_OBJ_GROUP, unknownid); - unknown_obj->cpuset = unknown_cpuset; - unknown_obj->os_level = level; - unknown_obj->attr->group.depth = topology->next_group_depth + level; - if (next_group_depth <= topology->next_group_depth + level) - next_group_depth = topology->next_group_depth + level + 1; - hwloc_debug_2args_bitmap("os unknown%d %u has cpuset %s\n", - level, unknownid, unknown_cpuset); - hwloc_insert_object_by_cpuset(topology, unknown_obj); - } - } - } - } - - /* Look for cores */ - if (fulldiscovery) { - hwloc_bitmap_t core_cpuset; - hwloc_obj_t core; - - hwloc_bitmap_copy(remaining_cpuset, complete_cpuset); - while ((i = hwloc_bitmap_first(remaining_cpuset)) != (unsigned) -1) { - unsigned packageid = infos[i].packageid; - unsigned nodeid = infos[i].nodeid; - unsigned coreid = infos[i].coreid; - - if (coreid == (unsigned) -1) { - hwloc_bitmap_clr(remaining_cpuset, i); - continue; - } - - core_cpuset = hwloc_bitmap_alloc(); - for (j = i; j < nbprocs; j++) { - if (infos[j].coreid == (unsigned) -1) { - hwloc_bitmap_clr(remaining_cpuset, j); - continue; - } - - if (infos[j].packageid == packageid && infos[j].nodeid == nodeid && infos[j].coreid == coreid) { - hwloc_bitmap_set(core_cpuset, j); - hwloc_bitmap_clr(remaining_cpuset, j); - } - } - core = hwloc_alloc_setup_object(HWLOC_OBJ_CORE, coreid); - core->cpuset = core_cpuset; - hwloc_debug_1arg_bitmap("os core %u has cpuset %s\n", - coreid, core_cpuset); - hwloc_insert_object_by_cpuset(topology, core); - } - } - - /* Look for PUs */ - if (fulldiscovery) { - unsigned i; - hwloc_debug("%s", "\n\n * CPU cpusets *\n\n"); - for (i=0; icpuset = hwloc_bitmap_alloc(); - hwloc_bitmap_only(obj->cpuset, i); - hwloc_debug_1arg_bitmap("PU %u has cpuset %s\n", i, obj->cpuset); - hwloc_insert_object_by_cpuset(topology, obj); - } - } - - /* Look for caches */ - /* First find max level */ - level = 0; - for (i = 0; i < nbprocs; i++) - for (j = 0; j < infos[i].numcaches; j++) - if (infos[i].cache[j].level > level) - level = infos[i].cache[j].level; - while (level > 0) { - for (type = 1; type <= 3; type++) { - /* Look for caches of that type at level level */ - { - hwloc_obj_t cache; - - hwloc_bitmap_copy(remaining_cpuset, complete_cpuset); - while ((i = hwloc_bitmap_first(remaining_cpuset)) != (unsigned) -1) { - hwloc_bitmap_t puset; - int depth; - - for (l = 0; l < infos[i].numcaches; l++) { - if (infos[i].cache[l].level == level && infos[i].cache[l].type == type) - break; - } - if (l == infos[i].numcaches) { - /* no cache Llevel of that type in i */ - hwloc_bitmap_clr(remaining_cpuset, i); - continue; - } - - puset = hwloc_bitmap_alloc(); - hwloc_bitmap_set(puset, i); - depth = hwloc_get_cache_type_depth(topology, level, - type == 1 ? HWLOC_OBJ_CACHE_DATA : type == 2 ? HWLOC_OBJ_CACHE_INSTRUCTION : HWLOC_OBJ_CACHE_UNIFIED); - if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) - cache = hwloc_get_next_obj_covering_cpuset_by_depth(topology, puset, depth, NULL); - else - cache = NULL; - hwloc_bitmap_free(puset); - - if (cache) { - /* Found cache above that PU, annotate if no such attribute yet */ - if (!hwloc_obj_get_info_by_name(cache, "Inclusive")) - hwloc_obj_add_info(cache, "Inclusive", infos[i].cache[l].inclusive ? "1" : "0"); - hwloc_bitmap_andnot(remaining_cpuset, remaining_cpuset, cache->cpuset); - } else { - /* Add the missing cache */ - hwloc_bitmap_t cache_cpuset; - unsigned packageid = infos[i].packageid; - unsigned cacheid = infos[i].cache[l].cacheid; - /* Now look for others sharing it */ - cache_cpuset = hwloc_bitmap_alloc(); - for (j = i; j < nbprocs; j++) { - unsigned l2; - for (l2 = 0; l2 < infos[j].numcaches; l2++) { - if (infos[j].cache[l2].level == level && infos[j].cache[l2].type == type) - break; - } - if (l2 == infos[j].numcaches) { - /* no cache Llevel of that type in j */ - hwloc_bitmap_clr(remaining_cpuset, j); - continue; - } - if (infos[j].packageid == packageid && infos[j].cache[l2].cacheid == cacheid) { - hwloc_bitmap_set(cache_cpuset, j); - hwloc_bitmap_clr(remaining_cpuset, j); - } - } - cache = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, cacheid); - cache->attr->cache.depth = level; - cache->attr->cache.size = infos[i].cache[l].size; - cache->attr->cache.linesize = infos[i].cache[l].linesize; - cache->attr->cache.associativity = infos[i].cache[l].ways; - switch (infos[i].cache[l].type) { - case 1: - cache->attr->cache.type = HWLOC_OBJ_CACHE_DATA; - break; - case 2: - cache->attr->cache.type = HWLOC_OBJ_CACHE_INSTRUCTION; - break; - case 3: - cache->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED; - break; - } - cache->cpuset = cache_cpuset; - hwloc_obj_add_info(cache, "Inclusive", infos[i].cache[l].inclusive ? "1" : "0"); - hwloc_debug_2args_bitmap("os L%u cache %u has cpuset %s\n", - level, cacheid, cache_cpuset); - hwloc_insert_object_by_cpuset(topology, cache); - caches_added++; - } - } - } - } - level--; - } - - hwloc_bitmap_free(remaining_cpuset); - hwloc_bitmap_free(complete_cpuset); - topology->next_group_depth = next_group_depth; - - return fulldiscovery || caches_added; -} - -static int -look_procs(struct hwloc_backend *backend, struct procinfo *infos, int fulldiscovery, - unsigned highest_cpuid, unsigned highest_ext_cpuid, unsigned *features, enum cpuid_type cpuid_type, - int (*get_cpubind)(hwloc_topology_t topology, hwloc_cpuset_t set, int flags), - int (*set_cpubind)(hwloc_topology_t topology, hwloc_const_cpuset_t set, int flags)) -{ - struct hwloc_x86_backend_data_s *data = backend->private_data; - struct hwloc_topology *topology = backend->topology; - unsigned nbprocs = data->nbprocs; - hwloc_bitmap_t orig_cpuset = hwloc_bitmap_alloc(); - hwloc_bitmap_t set; - unsigned i; - int ret = 0; - - if (get_cpubind(topology, orig_cpuset, HWLOC_CPUBIND_STRICT)) { - hwloc_bitmap_free(orig_cpuset); - return -1; - } - - set = hwloc_bitmap_alloc(); - - for (i = 0; i < nbprocs; i++) { - hwloc_bitmap_only(set, i); - hwloc_debug("binding to CPU%d\n", i); - if (set_cpubind(topology, set, HWLOC_CPUBIND_STRICT)) { - hwloc_debug("could not bind to CPU%d: %s\n", i, strerror(errno)); - continue; - } - look_proc(backend, &infos[i], highest_cpuid, highest_ext_cpuid, features, cpuid_type); - } - - set_cpubind(topology, orig_cpuset, 0); - hwloc_bitmap_free(set); - hwloc_bitmap_free(orig_cpuset); - - if (!data->apicid_unique) - fulldiscovery = 0; - else - ret = summarize(backend, infos, fulldiscovery); - return ret; -} - -#if defined HWLOC_FREEBSD_SYS && defined HAVE_CPUSET_SETID -#include -#include -typedef cpusetid_t hwloc_x86_os_state_t; -static void hwloc_x86_os_state_save(hwloc_x86_os_state_t *state) -{ - /* temporary make all cpus available during discovery */ - cpuset_getid(CPU_LEVEL_CPUSET, CPU_WHICH_PID, -1, state); - cpuset_setid(CPU_WHICH_PID, -1, 0); -} -static void hwloc_x86_os_state_restore(hwloc_x86_os_state_t *state) -{ - /* restore initial cpuset */ - cpuset_setid(CPU_WHICH_PID, -1, *state); -} -#else /* !defined HWLOC_FREEBSD_SYS || !defined HAVE_CPUSET_SETID */ -typedef void * hwloc_x86_os_state_t; -static void hwloc_x86_os_state_save(hwloc_x86_os_state_t *state __hwloc_attribute_unused) { } -static void hwloc_x86_os_state_restore(hwloc_x86_os_state_t *state __hwloc_attribute_unused) { } -#endif /* !defined HWLOC_FREEBSD_SYS || !defined HAVE_CPUSET_SETID */ - - -#define INTEL_EBX ('G' | ('e'<<8) | ('n'<<16) | ('u'<<24)) -#define INTEL_EDX ('i' | ('n'<<8) | ('e'<<16) | ('I'<<24)) -#define INTEL_ECX ('n' | ('t'<<8) | ('e'<<16) | ('l'<<24)) - -#define AMD_EBX ('A' | ('u'<<8) | ('t'<<16) | ('h'<<24)) -#define AMD_EDX ('e' | ('n'<<8) | ('t'<<16) | ('i'<<24)) -#define AMD_ECX ('c' | ('A'<<8) | ('M'<<16) | ('D'<<24)) - -/* fake cpubind for when nbprocs=1 and no binding support */ -static int fake_get_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, - hwloc_cpuset_t set __hwloc_attribute_unused, - int flags __hwloc_attribute_unused) -{ - return 0; -} -static int fake_set_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, - hwloc_const_cpuset_t set __hwloc_attribute_unused, - int flags __hwloc_attribute_unused) -{ - return 0; -} - -static -int hwloc_look_x86(struct hwloc_backend *backend, int fulldiscovery) -{ - struct hwloc_x86_backend_data_s *data = backend->private_data; - unsigned nbprocs = data->nbprocs; - unsigned eax, ebx, ecx = 0, edx; - unsigned i; - unsigned highest_cpuid; - unsigned highest_ext_cpuid; - /* This stores cpuid features with the same indexing as Linux */ - unsigned features[10] = { 0 }; - struct procinfo *infos = NULL; - enum cpuid_type cpuid_type = unknown; - hwloc_x86_os_state_t os_state; - struct hwloc_binding_hooks hooks; - struct hwloc_topology_support support; - struct hwloc_topology_membind_support memsupport __hwloc_attribute_unused; - int (*get_cpubind)(hwloc_topology_t topology, hwloc_cpuset_t set, int flags); - int (*set_cpubind)(hwloc_topology_t topology, hwloc_const_cpuset_t set, int flags); - int ret = -1; - - /* check if binding works */ - memset(&hooks, 0, sizeof(hooks)); - support.membind = &memsupport; - hwloc_set_native_binding_hooks(&hooks, &support); - if (hooks.get_thisthread_cpubind && hooks.set_thisthread_cpubind) { - get_cpubind = hooks.get_thisthread_cpubind; - set_cpubind = hooks.set_thisthread_cpubind; - } else if (hooks.get_thisproc_cpubind && hooks.set_thisproc_cpubind) { - get_cpubind = hooks.get_thisproc_cpubind; - set_cpubind = hooks.set_thisproc_cpubind; - } else { - /* we need binding support if there are multiple PUs */ - if (nbprocs > 1) - goto out; - get_cpubind = fake_get_cpubind; - set_cpubind = fake_set_cpubind; - } - - if (!hwloc_have_x86_cpuid()) - goto out; - - infos = calloc(nbprocs, sizeof(struct procinfo)); - if (NULL == infos) - goto out; - for (i = 0; i < nbprocs; i++) { - infos[i].nodeid = (unsigned) -1; - infos[i].packageid = (unsigned) -1; - infos[i].unitid = (unsigned) -1; - infos[i].coreid = (unsigned) -1; - infos[i].threadid = (unsigned) -1; - } - - eax = 0x00; - hwloc_x86_cpuid(&eax, &ebx, &ecx, &edx); - highest_cpuid = eax; - if (ebx == INTEL_EBX && ecx == INTEL_ECX && edx == INTEL_EDX) - cpuid_type = intel; - if (ebx == AMD_EBX && ecx == AMD_ECX && edx == AMD_EDX) - cpuid_type = amd; - - hwloc_debug("highest cpuid %x, cpuid type %u\n", highest_cpuid, cpuid_type); - if (highest_cpuid < 0x01) { - goto out_with_infos; - } - - eax = 0x01; - hwloc_x86_cpuid(&eax, &ebx, &ecx, &edx); - features[0] = edx; - features[4] = ecx; - - eax = 0x80000000; - hwloc_x86_cpuid(&eax, &ebx, &ecx, &edx); - highest_ext_cpuid = eax; - - hwloc_debug("highest extended cpuid %x\n", highest_ext_cpuid); - - if (highest_cpuid >= 0x7) { - eax = 0x7; - ecx = 0; - hwloc_x86_cpuid(&eax, &ebx, &ecx, &edx); - features[9] = ebx; - } - - if (cpuid_type != intel && highest_ext_cpuid >= 0x80000001) { - eax = 0x80000001; - hwloc_x86_cpuid(&eax, &ebx, &ecx, &edx); - features[1] = edx; - features[6] = ecx; - } - - hwloc_x86_os_state_save(&os_state); - - ret = look_procs(backend, infos, fulldiscovery, - highest_cpuid, highest_ext_cpuid, features, cpuid_type, - get_cpubind, set_cpubind); - if (ret >= 0) - /* success, we're done */ - goto out_with_os_state; - - if (nbprocs == 1) { - /* only one processor, no need to bind */ - look_proc(backend, &infos[0], highest_cpuid, highest_ext_cpuid, features, cpuid_type); - ret = summarize(backend, infos, fulldiscovery); - } - -out_with_os_state: - hwloc_x86_os_state_restore(&os_state); - -out_with_infos: - if (NULL != infos) { - for (i = 0; i < nbprocs; i++) { - free(infos[i].cache); - if (infos[i].otherids) - free(infos[i].otherids); - } - free(infos); - } - -out: - return ret; -} - -static int -hwloc_x86_discover(struct hwloc_backend *backend) -{ - struct hwloc_x86_backend_data_s *data = backend->private_data; - struct hwloc_topology *topology = backend->topology; - int alreadypus = 0; - int ret; - -#if HAVE_DECL_RUNNING_ON_VALGRIND - if (RUNNING_ON_VALGRIND) { - fprintf(stderr, "hwloc x86 backend cannot work under Valgrind, disabling.\n"); - return 0; - } -#endif - - data->nbprocs = hwloc_fallback_nbprocessors(topology); - - if (!topology->is_thissystem) { - hwloc_debug("%s", "\nno x86 detection (not thissystem)\n"); - return 0; - } - - if (topology->levels[0][0]->cpuset) { - /* somebody else discovered things */ - if (topology->nb_levels == 2 && topology->level_nbobjects[1] == data->nbprocs) { - /* only PUs were discovered, as much as we would, complete the topology with everything else */ - alreadypus = 1; - goto fulldiscovery; - } - - /* several object types were added, we can't easily complete, just do partial discovery */ - ret = hwloc_look_x86(backend, 0); - if (ret) - hwloc_obj_add_info(topology->levels[0][0], "Backend", "x86"); - return ret; - } else { - /* topology is empty, initialize it */ - hwloc_alloc_obj_cpusets(topology->levels[0][0]); - } - -fulldiscovery: - if (hwloc_look_x86(backend, 1) < 0) { - /* if failed, create PUs */ - if (!alreadypus) - hwloc_setup_pu_level(topology, data->nbprocs); - } - - hwloc_obj_add_info(topology->levels[0][0], "Backend", "x86"); - -#ifdef HAVE_UNAME - hwloc_add_uname_info(topology, NULL); /* we already know is_thissystem() is true */ -#else - /* uname isn't available, manually setup the "Architecture" info */ -#ifdef HWLOC_X86_64_ARCH - hwloc_obj_add_info(topology->levels[0][0], "Architecture", "x86_64"); -#else - hwloc_obj_add_info(topology->levels[0][0], "Architecture", "x86"); -#endif -#endif - return 1; -} - -static void -hwloc_x86_backend_disable(struct hwloc_backend *backend) -{ - struct hwloc_x86_backend_data_s *data = backend->private_data; - hwloc_bitmap_free(data->apicid_set); - free(data); -} - -static struct hwloc_backend * -hwloc_x86_component_instantiate(struct hwloc_disc_component *component, - const void *_data1 __hwloc_attribute_unused, - const void *_data2 __hwloc_attribute_unused, - const void *_data3 __hwloc_attribute_unused) -{ - struct hwloc_backend *backend; - struct hwloc_x86_backend_data_s *data; - - backend = hwloc_backend_alloc(component); - if (!backend) - goto out; - - data = malloc(sizeof(*data)); - if (!data) { - errno = ENOMEM; - goto out_with_backend; - } - - backend->private_data = data; - backend->flags = HWLOC_BACKEND_FLAG_NEED_LEVELS; - backend->discover = hwloc_x86_discover; - backend->disable = hwloc_x86_backend_disable; - - /* default values */ - data->is_knl = 0; - data->apicid_set = hwloc_bitmap_alloc(); - data->apicid_unique = 1; - - return backend; - - out_with_backend: - free(backend); - out: - return NULL; -} - -static struct hwloc_disc_component hwloc_x86_disc_component = { - HWLOC_DISC_COMPONENT_TYPE_CPU, - "x86", - HWLOC_DISC_COMPONENT_TYPE_GLOBAL, - hwloc_x86_component_instantiate, - 45, /* between native and no_os */ - NULL -}; - -const struct hwloc_component hwloc_x86_component = { - HWLOC_COMPONENT_ABI, - NULL, NULL, - HWLOC_COMPONENT_TYPE_DISC, - 0, - &hwloc_x86_disc_component -}; diff --git a/opal/mca/hwloc/hwloc1116/hwloc/src/topology-xml.c b/opal/mca/hwloc/hwloc1116/hwloc/src/topology-xml.c deleted file mode 100644 index 1d60ee1da3..0000000000 --- a/opal/mca/hwloc/hwloc1116/hwloc/src/topology-xml.c +++ /dev/null @@ -1,1827 +0,0 @@ -/* - * Copyright © 2009 CNRS - * Copyright © 2009-2017 Inria. All rights reserved. - * Copyright © 2009-2011 Université Bordeaux - * Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved. - * See COPYING in top-level directory. - */ - -#include -#include -#include -#include -#include -#include - -int -hwloc__xml_verbose(void) -{ - static int first = 1; - static int verbose = 0; - if (first) { - const char *env = getenv("HWLOC_XML_VERBOSE"); - if (env) - verbose = atoi(env); - first = 0; - } - return verbose; -} - -static int -hwloc_nolibxml_import(void) -{ - static int first = 1; - static int nolibxml = 0; - if (first) { - const char *env = getenv("HWLOC_NO_LIBXML_IMPORT"); - if (env) - nolibxml = atoi(env); - first = 0; - } - return nolibxml; -} - -static int -hwloc_nolibxml_export(void) -{ - static int first = 1; - static int nolibxml = 0; - if (first) { - const char *env = getenv("HWLOC_NO_LIBXML_EXPORT"); - if (env) - nolibxml = atoi(env); - first = 0; - } - return nolibxml; -} - -#define BASE64_ENCODED_LENGTH(length) (4*(((length)+2)/3)) - -/********************************* - ********* XML callbacks ********* - *********************************/ - -/* set when registering nolibxml and libxml components. - * modifications protected by the components mutex. - * read by the common XML code in topology-xml.c to jump to the right XML backend. - */ -static struct hwloc_xml_callbacks *hwloc_nolibxml_callbacks = NULL, *hwloc_libxml_callbacks = NULL; - -void -hwloc_xml_callbacks_register(struct hwloc_xml_component *comp) -{ - if (!hwloc_nolibxml_callbacks) - hwloc_nolibxml_callbacks = comp->nolibxml_callbacks; - if (!hwloc_libxml_callbacks) - hwloc_libxml_callbacks = comp->libxml_callbacks; -} - -void -hwloc_xml_callbacks_reset(void) -{ - hwloc_nolibxml_callbacks = NULL; - hwloc_libxml_callbacks = NULL; -} - -/************************************************ - ********* XML import (common routines) ********* - ************************************************/ - -static void -hwloc__xml_import_object_attr(struct hwloc_topology *topology __hwloc_attribute_unused, struct hwloc_obj *obj, - const char *name, const char *value, - hwloc__xml_import_state_t state) -{ - if (!strcmp(name, "type")) { - /* already handled */ - return; - } - - else if (!strcmp(name, "os_level")) - obj->os_level = strtoul(value, NULL, 10); - else if (!strcmp(name, "os_index")) - obj->os_index = strtoul(value, NULL, 10); - else if (!strcmp(name, "cpuset")) { - obj->cpuset = hwloc_bitmap_alloc(); - hwloc_bitmap_sscanf(obj->cpuset, value); - } else if (!strcmp(name, "complete_cpuset")) { - obj->complete_cpuset = hwloc_bitmap_alloc(); - hwloc_bitmap_sscanf(obj->complete_cpuset,value); - } else if (!strcmp(name, "online_cpuset")) { - obj->online_cpuset = hwloc_bitmap_alloc(); - hwloc_bitmap_sscanf(obj->online_cpuset, value); - } else if (!strcmp(name, "allowed_cpuset")) { - obj->allowed_cpuset = hwloc_bitmap_alloc(); - hwloc_bitmap_sscanf(obj->allowed_cpuset, value); - } else if (!strcmp(name, "nodeset")) { - obj->nodeset = hwloc_bitmap_alloc(); - hwloc_bitmap_sscanf(obj->nodeset, value); - } else if (!strcmp(name, "complete_nodeset")) { - obj->complete_nodeset = hwloc_bitmap_alloc(); - hwloc_bitmap_sscanf(obj->complete_nodeset, value); - } else if (!strcmp(name, "allowed_nodeset")) { - obj->allowed_nodeset = hwloc_bitmap_alloc(); - hwloc_bitmap_sscanf(obj->allowed_nodeset, value); - } else if (!strcmp(name, "name")) - obj->name = strdup(value); - - else if (!strcmp(name, "cache_size")) { - unsigned long long lvalue = strtoull(value, NULL, 10); - if (obj->type == HWLOC_OBJ_CACHE) - obj->attr->cache.size = lvalue; - else if (hwloc__xml_verbose()) - fprintf(stderr, "%s: ignoring cache_size attribute for non-cache object type\n", - state->global->msgprefix); - } - - else if (!strcmp(name, "cache_linesize")) { - unsigned long lvalue = strtoul(value, NULL, 10); - if (obj->type == HWLOC_OBJ_CACHE) - obj->attr->cache.linesize = lvalue; - else if (hwloc__xml_verbose()) - fprintf(stderr, "%s: ignoring cache_linesize attribute for non-cache object type\n", - state->global->msgprefix); - } - - else if (!strcmp(name, "cache_associativity")) { - unsigned long lvalue = strtoul(value, NULL, 10); - if (obj->type == HWLOC_OBJ_CACHE) - obj->attr->cache.associativity = lvalue; - else if (hwloc__xml_verbose()) - fprintf(stderr, "%s: ignoring cache_associativity attribute for non-cache object type\n", - state->global->msgprefix); - } - - else if (!strcmp(name, "cache_type")) { - unsigned long lvalue = strtoul(value, NULL, 10); - if (obj->type == HWLOC_OBJ_CACHE) { - if (lvalue == HWLOC_OBJ_CACHE_UNIFIED - || lvalue == HWLOC_OBJ_CACHE_DATA - || lvalue == HWLOC_OBJ_CACHE_INSTRUCTION) - obj->attr->cache.type = (hwloc_obj_cache_type_t) lvalue; - else - fprintf(stderr, "%s: ignoring invalid cache_type attribute %ld\n", - state->global->msgprefix, lvalue); - } else if (hwloc__xml_verbose()) - fprintf(stderr, "%s: ignoring cache_type attribute for non-cache object type\n", - state->global->msgprefix); - } - - else if (!strcmp(name, "local_memory")) - obj->memory.local_memory = strtoull(value, NULL, 10); - - else if (!strcmp(name, "depth")) { - unsigned long lvalue = strtoul(value, NULL, 10); - switch (obj->type) { - case HWLOC_OBJ_CACHE: - obj->attr->cache.depth = lvalue; - break; - case HWLOC_OBJ_GROUP: - obj->attr->group.depth = lvalue; - break; - case HWLOC_OBJ_BRIDGE: - obj->attr->bridge.depth = lvalue; - break; - default: - if (hwloc__xml_verbose()) - fprintf(stderr, "%s: ignoring depth attribute for object type without depth\n", - state->global->msgprefix); - break; - } - } - - else if (!strcmp(name, "pci_busid")) { - switch (obj->type) { - case HWLOC_OBJ_PCI_DEVICE: - case HWLOC_OBJ_BRIDGE: { - unsigned domain, bus, dev, func; - if (sscanf(value, "%04x:%02x:%02x.%01x", - &domain, &bus, &dev, &func) != 4) { - if (hwloc__xml_verbose()) - fprintf(stderr, "%s: ignoring invalid pci_busid format string %s\n", - state->global->msgprefix, value); - } else { - obj->attr->pcidev.domain = domain; - obj->attr->pcidev.bus = bus; - obj->attr->pcidev.dev = dev; - obj->attr->pcidev.func = func; - } - break; - } - default: - if (hwloc__xml_verbose()) - fprintf(stderr, "%s: ignoring pci_busid attribute for non-PCI object\n", - state->global->msgprefix); - break; - } - } - - else if (!strcmp(name, "pci_type")) { - switch (obj->type) { - case HWLOC_OBJ_PCI_DEVICE: - case HWLOC_OBJ_BRIDGE: { - unsigned classid, vendor, device, subvendor, subdevice, revision; - if (sscanf(value, "%04x [%04x:%04x] [%04x:%04x] %02x", - &classid, &vendor, &device, &subvendor, &subdevice, &revision) != 6) { - if (hwloc__xml_verbose()) - fprintf(stderr, "%s: ignoring invalid pci_type format string %s\n", - state->global->msgprefix, value); - } else { - obj->attr->pcidev.class_id = classid; - obj->attr->pcidev.vendor_id = vendor; - obj->attr->pcidev.device_id = device; - obj->attr->pcidev.subvendor_id = subvendor; - obj->attr->pcidev.subdevice_id = subdevice; - obj->attr->pcidev.revision = revision; - } - break; - } - default: - if (hwloc__xml_verbose()) - fprintf(stderr, "%s: ignoring pci_type attribute for non-PCI object\n", - state->global->msgprefix); - break; - } - } - - else if (!strcmp(name, "pci_link_speed")) { - switch (obj->type) { - case HWLOC_OBJ_PCI_DEVICE: - case HWLOC_OBJ_BRIDGE: { - obj->attr->pcidev.linkspeed = (float) atof(value); - break; - } - default: - if (hwloc__xml_verbose()) - fprintf(stderr, "%s: ignoring pci_link_speed attribute for non-PCI object\n", - state->global->msgprefix); - break; - } - } - - else if (!strcmp(name, "bridge_type")) { - switch (obj->type) { - case HWLOC_OBJ_BRIDGE: { - unsigned upstream_type, downstream_type; - if (sscanf(value, "%u-%u", &upstream_type, &downstream_type) != 2) { - if (hwloc__xml_verbose()) - fprintf(stderr, "%s: ignoring invalid bridge_type format string %s\n", - state->global->msgprefix, value); - } else { - obj->attr->bridge.upstream_type = (hwloc_obj_bridge_type_t) upstream_type; - obj->attr->bridge.downstream_type = (hwloc_obj_bridge_type_t) downstream_type; - }; - break; - } - default: - if (hwloc__xml_verbose()) - fprintf(stderr, "%s: ignoring bridge_type attribute for non-bridge object\n", - state->global->msgprefix); - break; - } - } - - else if (!strcmp(name, "bridge_pci")) { - switch (obj->type) { - case HWLOC_OBJ_BRIDGE: { - unsigned domain, secbus, subbus; - if (sscanf(value, "%04x:[%02x-%02x]", - &domain, &secbus, &subbus) != 3) { - if (hwloc__xml_verbose()) - fprintf(stderr, "%s: ignoring invalid bridge_pci format string %s\n", - state->global->msgprefix, value); - } else { - obj->attr->bridge.downstream.pci.domain = domain; - obj->attr->bridge.downstream.pci.secondary_bus = secbus; - obj->attr->bridge.downstream.pci.subordinate_bus = subbus; - } - break; - } - default: - if (hwloc__xml_verbose()) - fprintf(stderr, "%s: ignoring bridge_pci attribute for non-bridge object\n", - state->global->msgprefix); - break; - } - } - - else if (!strcmp(name, "osdev_type")) { - switch (obj->type) { - case HWLOC_OBJ_OS_DEVICE: { - unsigned osdev_type; - if (sscanf(value, "%u", &osdev_type) != 1) { - if (hwloc__xml_verbose()) - fprintf(stderr, "%s: ignoring invalid osdev_type format string %s\n", - state->global->msgprefix, value); - } else - obj->attr->osdev.type = (hwloc_obj_osdev_type_t) osdev_type; - break; - } - default: - if (hwloc__xml_verbose()) - fprintf(stderr, "%s: ignoring osdev_type attribute for non-osdev object\n", - state->global->msgprefix); - break; - } - } - - /************************** - * forward compat with 2.0 - */ - else if (!strcmp(name, "kind") || !strcmp(name, "subkind")) { - if (obj->type == HWLOC_OBJ_GROUP) { - /* ignored, unused in <2.0 */ - } else { - if (hwloc__xml_verbose()) - fprintf(stderr, "%s: ignoring %s attribute for non-group object\n", - state->global->msgprefix, name); - } - } - else if (!strcmp(name, "subtype")) { - hwloc_obj_add_info(obj, "Type", value); - /* will be changed into CoProcType in the caller once we have osdev.type too */ - } - else if (!strcmp(name, "gp_index")) { - /* doesn't exist in v1.x */ - } - - - /************************* - * deprecated (from 1.0) - */ - else if (!strcmp(name, "dmi_board_vendor")) { - hwloc_obj_add_info(obj, "DMIBoardVendor", value); - } - else if (!strcmp(name, "dmi_board_name")) { - hwloc_obj_add_info(obj, "DMIBoardName", value); - } - - /************************* - * deprecated (from 0.9) - */ - else if (!strcmp(name, "memory_kB")) { - unsigned long long lvalue = strtoull(value, NULL, 10); - switch (obj->type) { - case HWLOC_OBJ_CACHE: - obj->attr->cache.size = lvalue << 10; - break; - case HWLOC_OBJ_NUMANODE: - case HWLOC_OBJ_MACHINE: - case HWLOC_OBJ_SYSTEM: - obj->memory.local_memory = lvalue << 10; - break; - default: - if (hwloc__xml_verbose()) - fprintf(stderr, "%s: ignoring memory_kB attribute for object type without memory\n", - state->global->msgprefix); - break; - } - } - else if (!strcmp(name, "huge_page_size_kB")) { - unsigned long lvalue = strtoul(value, NULL, 10); - switch (obj->type) { - case HWLOC_OBJ_NUMANODE: - case HWLOC_OBJ_MACHINE: - case HWLOC_OBJ_SYSTEM: - if (!obj->memory.page_types) { - obj->memory.page_types = malloc(sizeof(*obj->memory.page_types)); - obj->memory.page_types_len = 1; - } - obj->memory.page_types[0].size = lvalue << 10; - break; - default: - if (hwloc__xml_verbose()) - fprintf(stderr, "%s: ignoring huge_page_size_kB attribute for object type without huge pages\n", - state->global->msgprefix); - break; - } - } - else if (!strcmp(name, "huge_page_free")) { - unsigned long lvalue = strtoul(value, NULL, 10); - switch (obj->type) { - case HWLOC_OBJ_NUMANODE: - case HWLOC_OBJ_MACHINE: - case HWLOC_OBJ_SYSTEM: - if (!obj->memory.page_types) { - obj->memory.page_types = malloc(sizeof(*obj->memory.page_types)); - obj->memory.page_types_len = 1; - } - obj->memory.page_types[0].count = lvalue; - break; - default: - if (hwloc__xml_verbose()) - fprintf(stderr, "%s: ignoring huge_page_free attribute for object type without huge pages\n", - state->global->msgprefix); - break; - } - } - /* - * end of deprecated (from 0.9) - *******************************/ - - - - else if (hwloc__xml_verbose()) - fprintf(stderr, "%s: ignoring unknown object attribute %s\n", - state->global->msgprefix, name); -} - - -static int -hwloc__xml_import_info(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_obj_t obj, - hwloc__xml_import_state_t state) -{ - char *infoname = NULL; - char *infovalue = NULL; - - while (1) { - char *attrname, *attrvalue; - if (state->global->next_attr(state, &attrname, &attrvalue) < 0) - break; - if (!strcmp(attrname, "name")) - infoname = attrvalue; - else if (!strcmp(attrname, "value")) - infovalue = attrvalue; - else - return -1; - } - - if (infoname) - /* empty strings are ignored by libxml */ - hwloc_obj_add_info(obj, infoname, infovalue ? infovalue : ""); - - return state->global->close_tag(state); -} - -static int -hwloc__xml_import_pagetype(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_obj_t obj, - hwloc__xml_import_state_t state) -{ - uint64_t size = 0, count = 0; - - while (1) { - char *attrname, *attrvalue; - if (state->global->next_attr(state, &attrname, &attrvalue) < 0) - break; - if (!strcmp(attrname, "size")) - size = strtoull(attrvalue, NULL, 10); - else if (!strcmp(attrname, "count")) - count = strtoull(attrvalue, NULL, 10); - else - return -1; - } - - if (size) { - int idx = obj->memory.page_types_len; - struct hwloc_obj_memory_page_type_s *tmp; - tmp = realloc(obj->memory.page_types, (idx+1)*sizeof(*obj->memory.page_types)); - if (tmp) { /* if failed to allocate, ignore this page_type entry */ - obj->memory.page_types = tmp; - obj->memory.page_types_len = idx+1; - obj->memory.page_types[idx].size = size; - obj->memory.page_types[idx].count = count; - } - } - - return state->global->close_tag(state); -} - -static int -hwloc__xml_import_distances(struct hwloc_xml_backend_data_s *data, - hwloc_obj_t obj, - hwloc__xml_import_state_t state) -{ - unsigned long reldepth = 0, nbobjs = 0; - float latbase = 0; - char *tag; - int ret; - - while (1) { - char *attrname, *attrvalue; - if (state->global->next_attr(state, &attrname, &attrvalue) < 0) - break; - if (!strcmp(attrname, "nbobjs")) - nbobjs = strtoul(attrvalue, NULL, 10); - else if (!strcmp(attrname, "relative_depth")) - reldepth = strtoul(attrvalue, NULL, 10); - else if (!strcmp(attrname, "latency_base")) - latbase = (float) atof(attrvalue); - else - return -1; - } - - if (nbobjs && reldepth && latbase) { - unsigned i; - float *matrix, latmax = 0; - struct hwloc_xml_imported_distances_s *distances; - - matrix = malloc(nbobjs*nbobjs*sizeof(float)); - distances = malloc(sizeof(*distances)); - if (!matrix || !distances) { - if (hwloc__xml_verbose()) - fprintf(stderr, "%s: failed to allocate distance matrix for %lu objects\n", - state->global->msgprefix, nbobjs); - free(distances); - free(matrix); - return -1; - } - - distances->root = obj; - distances->distances.relative_depth = reldepth; - distances->distances.nbobjs = nbobjs; - distances->distances.latency = matrix; - distances->distances.latency_base = latbase; - - for(i=0; iglobal->find_child(state, &childstate, &tag); - if (ret <= 0 || strcmp(tag, "latency")) { - /* a latency child is needed */ - free(distances->distances.latency); - free(distances); - return -1; - } - - ret = state->global->next_attr(&childstate, &attrname, &attrvalue); - if (ret < 0 || strcmp(attrname, "value")) { - free(distances->distances.latency); - free(distances); - return -1; - } - - val = (float) atof((char *) attrvalue); - matrix[i] = val; - if (val > latmax) - latmax = val; - - ret = state->global->close_tag(&childstate); - if (ret < 0) - return -1; - - state->global->close_child(&childstate); - } - - distances->distances.latency_max = latmax; - - if (nbobjs < 2) { - /* distances with a single object are useless, even if the XML isn't invalid */ - assert(nbobjs == 1); - if (hwloc__xml_verbose()) - fprintf(stderr, "%s: ignoring invalid distance matrix with only 1 object\n", - state->global->msgprefix); - free(matrix); - free(distances); - } else { - /* queue the distance */ - distances->prev = data->last_distances; - distances->next = NULL; - if (data->last_distances) - data->last_distances->next = distances; - else - data->first_distances = distances; - data->last_distances = distances; - } - } - - return state->global->close_tag(state); -} - -static int -hwloc__xml_import_userdata(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_obj_t obj, - hwloc__xml_import_state_t state) -{ - size_t length = 0; - int encoded = 0; - char *name = NULL; /* optional */ - int ret; - - while (1) { - char *attrname, *attrvalue; - if (state->global->next_attr(state, &attrname, &attrvalue) < 0) - break; - if (!strcmp(attrname, "length")) - length = strtoul(attrvalue, NULL, 10); - else if (!strcmp(attrname, "encoding")) - encoded = !strcmp(attrvalue, "base64"); - else if (!strcmp(attrname, "name")) - name = attrvalue; - else - return -1; - } - - if (!topology->userdata_import_cb) { - char *buffer; - size_t reallength = encoded ? BASE64_ENCODED_LENGTH(length) : length; - ret = state->global->get_content(state, &buffer, reallength); - if (ret < 0) - return -1; - - } else if (topology->userdata_not_decoded) { - char *buffer, *fakename; - size_t reallength = encoded ? BASE64_ENCODED_LENGTH(length) : length; - ret = state->global->get_content(state, &buffer, reallength); - if (ret < 0) - return -1; - fakename = malloc(6 + 1 + (name ? strlen(name) : 4) + 1); - if (!fakename) - return -1; - sprintf(fakename, encoded ? "base64%c%s" : "normal%c%s", name ? ':' : '-', name ? name : "anon"); - topology->userdata_import_cb(topology, obj, fakename, buffer, length); - free(fakename); - - } else if (encoded && length) { - char *encoded_buffer; - size_t encoded_length = BASE64_ENCODED_LENGTH(length); - ret = state->global->get_content(state, &encoded_buffer, encoded_length); - if (ret < 0) - return -1; - if (ret) { - char *decoded_buffer = malloc(length+1); - if (!decoded_buffer) - return -1; - assert(encoded_buffer[encoded_length] == 0); - ret = hwloc_decode_from_base64(encoded_buffer, decoded_buffer, length+1); - if (ret != (int) length) { - free(decoded_buffer); - return -1; - } - topology->userdata_import_cb(topology, obj, name, decoded_buffer, length); - free(decoded_buffer); - } - - } else { /* always handle length==0 in the non-encoded case */ - char *buffer = ""; - if (length) { - ret = state->global->get_content(state, &buffer, length); - if (ret < 0) - return -1; - } - topology->userdata_import_cb(topology, obj, name, buffer, length); - } - - state->global->close_content(state); - return state->global->close_tag(state); -} - -static int -hwloc__xml_import_object(hwloc_topology_t topology, - struct hwloc_xml_backend_data_s *data, - hwloc_obj_t obj, - hwloc__xml_import_state_t state) -{ - hwloc_obj_t parent = obj->parent; - - /* process attributes */ - while (1) { - char *attrname, *attrvalue; - if (state->global->next_attr(state, &attrname, &attrvalue) < 0) - break; - if (!strcmp(attrname, "type")) { - if (hwloc_obj_type_sscanf(attrvalue, &obj->type, NULL, NULL, 0) < 0) - goto error_with_object; - } else { - /* type needed first */ - if (obj->type == (hwloc_obj_type_t)-1) - goto error_with_object; - hwloc__xml_import_object_attr(topology, obj, attrname, attrvalue, state); - } - } - - /* obj->subtype is imported as "CoProcType" instead of "Type" for osdev/coproc. - * Cannot properly import earlier because osdev.type is imported after subtype. - * Don't do it later so that the actual infos array isn't imported yet, - * there's likely only "Type" in obj->infos[]. - */ - if (obj->type == HWLOC_OBJ_OS_DEVICE && obj->attr->osdev.type == HWLOC_OBJ_OSDEV_COPROC) { - unsigned i; - for(i=0; iinfos_count; i++) - if (!strcmp(obj->infos[i].name, "Type")) { - /* HACK: we're not supposed to modify infos[].name from here */ - free(obj->infos[i].name); - obj->infos[i].name = strdup("CoProcType"); - } - } - - if (parent) { - /* root->parent is NULL, and root is already inserted */ - - /* warn if inserting out-of-order */ - if (parent->cpuset) { /* don't compare children if multinode parent */ - hwloc_obj_t *current; - for (current = &parent->first_child; *current; current = &(*current)->next_sibling) { - hwloc_bitmap_t curcpuset = (*current)->cpuset; - if (obj->cpuset && (!curcpuset || hwloc__object_cpusets_compare_first(obj, *current) < 0)) { - static int reported = 0; - if (!reported && !hwloc_hide_errors()) { - char *progname = hwloc_progname(topology); - const char *origversion = hwloc_obj_get_info_by_name(topology->levels[0][0], "hwlocVersion"); - const char *origprogname = hwloc_obj_get_info_by_name(topology->levels[0][0], "ProcessName"); - char *c1, *cc1, t1[64]; - char *c2 = NULL, *cc2 = NULL, t2[64]; - hwloc_bitmap_asprintf(&c1, obj->cpuset); - hwloc_bitmap_asprintf(&cc1, obj->complete_cpuset); - hwloc_obj_type_snprintf(t1, sizeof(t1), obj, 0); - if (curcpuset) - hwloc_bitmap_asprintf(&c2, curcpuset); - if ((*current)->complete_cpuset) - hwloc_bitmap_asprintf(&cc2, (*current)->complete_cpuset); - hwloc_obj_type_snprintf(t2, sizeof(t2), *current, 0); - fprintf(stderr, "****************************************************************************\n"); - fprintf(stderr, "* hwloc has encountered an out-of-order XML topology load.\n"); - fprintf(stderr, "* Object %s cpuset %s complete %s\n", - t1, c1, cc1); - fprintf(stderr, "* was inserted after object %s with %s and %s.\n", - t2, c2 ? c2 : "none", cc2 ? cc2 : "none"); - fprintf(stderr, "* The error occured in hwloc %s inside process `%s', while\n", - HWLOC_VERSION, - progname ? progname : ""); - if (origversion || origprogname) - fprintf(stderr, "* the input XML was generated by hwloc %s inside process `%s'.\n", - origversion ? origversion : "(unknown version)", - origprogname ? origprogname : ""); - else - fprintf(stderr, "* the input XML was generated by an unspecified ancient hwloc release.\n"); - fprintf(stderr, "* Please check that your input topology XML file is valid.\n"); - fprintf(stderr, "****************************************************************************\n"); - free(c1); - free(cc1); - if (c2) - free(c2); - if (cc2) - free(cc2); - free(progname); - reported = 1; - } - } - } - } - - hwloc_insert_object_by_parent(topology, obj->parent /* filled by the caller */, obj); - /* insert_object_by_parent() doesn't merge during insert, so obj is still valid */ - } - - /* process subnodes */ - while (1) { - struct hwloc__xml_import_state_s childstate; - char *tag; - int ret; - - ret = state->global->find_child(state, &childstate, &tag); - if (ret < 0) - goto error; - if (!ret) - break; - - if (!strcmp(tag, "object")) { - hwloc_obj_t childobj = hwloc_alloc_setup_object(HWLOC_OBJ_TYPE_MAX, -1); - childobj->parent = obj; /* store the parent pointer for use in insert() below */ - ret = hwloc__xml_import_object(topology, data, childobj, &childstate); - } else if (!strcmp(tag, "page_type")) { - ret = hwloc__xml_import_pagetype(topology, obj, &childstate); - } else if (!strcmp(tag, "info")) { - ret = hwloc__xml_import_info(topology, obj, &childstate); - } else if (!strcmp(tag, "distances")) { - ret = hwloc__xml_import_distances(data, obj, &childstate); - } else if (!strcmp(tag, "userdata")) { - ret = hwloc__xml_import_userdata(topology, obj, &childstate); - } else - ret = -1; - - if (ret < 0) - goto error; - - state->global->close_child(&childstate); - } - - return state->global->close_tag(state); - - error_with_object: - if (parent) - /* root->parent is NULL, and root is already inserted. the caller will cleanup that root. */ - hwloc_free_unlinked_object(obj); - error: - return -1; -} - -static int -hwloc__xml_import_diff_one(hwloc__xml_import_state_t state, - hwloc_topology_diff_t *firstdiffp, - hwloc_topology_diff_t *lastdiffp) -{ - char *type_s = NULL; - char *obj_depth_s = NULL; - char *obj_index_s = NULL; - char *obj_attr_type_s = NULL; -/* char *obj_attr_index_s = NULL; unused for now */ - char *obj_attr_name_s = NULL; - char *obj_attr_oldvalue_s = NULL; - char *obj_attr_newvalue_s = NULL; - - while (1) { - char *attrname, *attrvalue; - if (state->global->next_attr(state, &attrname, &attrvalue) < 0) - break; - if (!strcmp(attrname, "type")) - type_s = attrvalue; - else if (!strcmp(attrname, "obj_depth")) - obj_depth_s = attrvalue; - else if (!strcmp(attrname, "obj_index")) - obj_index_s = attrvalue; - else if (!strcmp(attrname, "obj_attr_type")) - obj_attr_type_s = attrvalue; - else if (!strcmp(attrname, "obj_attr_index")) - { /* obj_attr_index_s = attrvalue; unused for now */ } - else if (!strcmp(attrname, "obj_attr_name")) - obj_attr_name_s = attrvalue; - else if (!strcmp(attrname, "obj_attr_oldvalue")) - obj_attr_oldvalue_s = attrvalue; - else if (!strcmp(attrname, "obj_attr_newvalue")) - obj_attr_newvalue_s = attrvalue; - else { - if (hwloc__xml_verbose()) - fprintf(stderr, "%s: ignoring unknown diff attribute %s\n", - state->global->msgprefix, attrname); - return -1; - } - } - - if (type_s) { - switch (atoi(type_s)) { - default: - break; - case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR: { - /* object attribute diff */ - hwloc_topology_diff_obj_attr_type_t obj_attr_type; - hwloc_topology_diff_t diff; - - /* obj_attr mandatory generic attributes */ - if (!obj_depth_s || !obj_index_s || !obj_attr_type_s) { - if (hwloc__xml_verbose()) - fprintf(stderr, "%s: missing mandatory obj attr generic attributes\n", - state->global->msgprefix); - break; - } - - /* obj_attr mandatory attributes common to all subtypes */ - if (!obj_attr_oldvalue_s || !obj_attr_newvalue_s) { - if (hwloc__xml_verbose()) - fprintf(stderr, "%s: missing mandatory obj attr value attributes\n", - state->global->msgprefix); - break; - } - - /* mandatory attributes for obj_attr_info subtype */ - obj_attr_type = atoi(obj_attr_type_s); - if (obj_attr_type == HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_INFO && !obj_attr_name_s) { - if (hwloc__xml_verbose()) - fprintf(stderr, "%s: missing mandatory obj attr info name attribute\n", - state->global->msgprefix); - break; - } - - /* now we know we have everything we need */ - diff = malloc(sizeof(*diff)); - if (!diff) - return -1; - diff->obj_attr.type = HWLOC_TOPOLOGY_DIFF_OBJ_ATTR; - diff->obj_attr.obj_depth = atoi(obj_depth_s); - diff->obj_attr.obj_index = atoi(obj_index_s); - memset(&diff->obj_attr.diff, 0, sizeof(diff->obj_attr.diff)); - diff->obj_attr.diff.generic.type = obj_attr_type; - - switch (atoi(obj_attr_type_s)) { - case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_SIZE: - diff->obj_attr.diff.uint64.oldvalue = strtoull(obj_attr_oldvalue_s, NULL, 0); - diff->obj_attr.diff.uint64.newvalue = strtoull(obj_attr_newvalue_s, NULL, 0); - break; - case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_INFO: - diff->obj_attr.diff.string.name = strdup(obj_attr_name_s); - /* fallthrough */ - case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_NAME: - diff->obj_attr.diff.string.oldvalue = strdup(obj_attr_oldvalue_s); - diff->obj_attr.diff.string.newvalue = strdup(obj_attr_newvalue_s); - break; - } - - if (*firstdiffp) - (*lastdiffp)->generic.next = diff; - else - *firstdiffp = diff; - *lastdiffp = diff; - diff->generic.next = NULL; - } - } - } - - return state->global->close_tag(state); -} - -int -hwloc__xml_import_diff(hwloc__xml_import_state_t state, - hwloc_topology_diff_t *firstdiffp) -{ - hwloc_topology_diff_t firstdiff = NULL, lastdiff = NULL; - *firstdiffp = NULL; - - while (1) { - struct hwloc__xml_import_state_s childstate; - char *tag; - int ret; - - ret = state->global->find_child(state, &childstate, &tag); - if (ret < 0) - return -1; - if (!ret) - break; - - if (!strcmp(tag, "diff")) { - ret = hwloc__xml_import_diff_one(&childstate, &firstdiff, &lastdiff); - } else - ret = -1; - - if (ret < 0) - return ret; - - state->global->close_child(&childstate); - } - - *firstdiffp = firstdiff; - return 0; -} - -/*********************************** - ********* main XML import ********* - ***********************************/ - -static void -hwloc_xml__free_distances(struct hwloc_xml_backend_data_s *data) -{ - struct hwloc_xml_imported_distances_s *xmldist; - while ((xmldist = data->first_distances) != NULL) { - data->first_distances = xmldist->next; - free(xmldist->distances.latency); - free(xmldist); - } -} - -static int -hwloc_xml__handle_distances(struct hwloc_topology *topology, - struct hwloc_xml_backend_data_s *data, - const char *msgprefix) -{ - struct hwloc_xml_imported_distances_s *xmldist; - - /* connect things now because we need levels to check/build, they'll be reconnected properly later anyway */ - hwloc_connect_children(topology->levels[0][0]); - if (hwloc_connect_levels(topology) < 0) { - hwloc_xml__free_distances(data); - return -1; - } - - while ((xmldist = data->first_distances) != NULL) { - hwloc_obj_t root = xmldist->root; - unsigned depth = root->depth + xmldist->distances.relative_depth; - unsigned nbobjs = xmldist->distances.nbobjs, j; - unsigned *indexes = malloc(nbobjs * sizeof(unsigned)); - hwloc_obj_t child, *objs = malloc(nbobjs * sizeof(hwloc_obj_t)); - - data->first_distances = xmldist->next; - j = 0; - child = NULL; - /* we can't use hwloc_get_next_obj_inside_cpuset_by_depth() because it ignore CPU-less objects */ - while ((child = hwloc_get_next_obj_by_depth(topology, depth, child)) != NULL) { - hwloc_obj_t myparent = child->parent; - while (myparent->depth > root->depth) - myparent = myparent->parent; - if (myparent == root) { - if (j == nbobjs) - goto badnbobjs; - indexes[j] = child->os_index; - objs[j] = child; - j++; - } - } - - if (j < nbobjs) - goto badnbobjs; - - /* distances valid, add it to the internal OS distances list for grouping */ - for(j=0; jdistances.latency[j] *= xmldist->distances.latency_base; - hwloc_distances_set(topology, objs[0]->type, nbobjs, indexes, objs, xmldist->distances.latency, 0 /* XML cannot force */); - free(xmldist); - continue; - - badnbobjs: - printf("bad nbobjs\n"); - if (hwloc__xml_verbose()) - fprintf(stderr, "%s: ignoring invalid distance matrix, there aren't exactly %u objects below root\n", - msgprefix, nbobjs); - free(indexes); - free(objs); - free(xmldist->distances.latency); - free(xmldist); - } - - return 0; -} - -/* this canNOT be the first XML call */ -static int -hwloc_look_xml(struct hwloc_backend *backend) -{ - struct hwloc_topology *topology = backend->topology; - struct hwloc_xml_backend_data_s *data = backend->private_data; - struct hwloc__xml_import_state_s state, childstate; - char *tag; - hwloc_localeswitch_declare; - int ret; - - state.global = data; - - assert(!topology->levels[0][0]->cpuset); - - hwloc_localeswitch_init(); - - data->first_distances = data->last_distances = NULL; - - ret = data->look_init(data, &state); - if (ret < 0) - goto failed; - - /* find root object tag and import it */ - ret = state.global->find_child(&state, &childstate, &tag); - if (ret < 0 || !ret || strcmp(tag, "object")) - goto failed; - ret = hwloc__xml_import_object(topology, data, topology->levels[0][0], &childstate); - if (ret < 0) - goto failed; - state.global->close_child(&childstate); - - /* find end of topology tag */ - state.global->close_tag(&state); - - /* keep the "Backend" information intact */ - /* we could add "BackendSource=XML" to notify that XML was used between the actual backend and here */ - - /* if we added some distances, we must check them, and make them groupable */ - if (hwloc_xml__handle_distances(topology, data, data->msgprefix) < 0) - goto err; - data->first_distances = data->last_distances = NULL; - topology->support.discovery->pu = 1; - - hwloc_localeswitch_fini(); - return 1; - - failed: - if (data->look_failed) - data->look_failed(data); - if (hwloc__xml_verbose()) - fprintf(stderr, "%s: XML component discovery failed.\n", - data->msgprefix); - err: - hwloc_xml__free_distances(data); - hwloc_localeswitch_fini(); - return -1; -} - -/* this can be the first XML call */ -int -hwloc_topology_diff_load_xml(hwloc_topology_t topology __hwloc_attribute_unused, - const char *xmlpath, - hwloc_topology_diff_t *firstdiffp, char **refnamep) -{ - struct hwloc__xml_import_state_s state; - struct hwloc_xml_backend_data_s fakedata; /* only for storing global info during parsing */ - hwloc_localeswitch_declare; - const char *basename; - int force_nolibxml; - int ret; - - state.global = &fakedata; - - basename = strrchr(xmlpath, '/'); - if (basename) - basename++; - else - basename = xmlpath; - fakedata.msgprefix = strdup(basename); - - if (!hwloc_libxml_callbacks && !hwloc_nolibxml_callbacks) { - free(fakedata.msgprefix); - errno = ENOSYS; - return -1; - } - - hwloc_localeswitch_init(); - - *firstdiffp = NULL; - - force_nolibxml = hwloc_nolibxml_import(); -retry: - if (!hwloc_libxml_callbacks || (hwloc_nolibxml_callbacks && force_nolibxml)) - ret = hwloc_nolibxml_callbacks->import_diff(&state, xmlpath, NULL, 0, firstdiffp, refnamep); - else { - ret = hwloc_libxml_callbacks->import_diff(&state, xmlpath, NULL, 0, firstdiffp, refnamep); - if (ret < 0 && errno == ENOSYS) { - hwloc_libxml_callbacks = NULL; - goto retry; - } - } - - hwloc_localeswitch_fini(); - - free(fakedata.msgprefix); - return ret; -} - -/* this can be the first XML call */ -int -hwloc_topology_diff_load_xmlbuffer(hwloc_topology_t topology __hwloc_attribute_unused, - const char *xmlbuffer, int buflen, - hwloc_topology_diff_t *firstdiffp, char **refnamep) -{ - struct hwloc__xml_import_state_s state; - struct hwloc_xml_backend_data_s fakedata; /* only for storing global info during parsing */ - hwloc_localeswitch_declare; - int force_nolibxml; - int ret; - - state.global = &fakedata; - fakedata.msgprefix = strdup("xmldiffbuffer"); - - if (!hwloc_libxml_callbacks && !hwloc_nolibxml_callbacks) { - free(fakedata.msgprefix); - errno = ENOSYS; - return -1; - } - - hwloc_localeswitch_init(); - - *firstdiffp = NULL; - - force_nolibxml = hwloc_nolibxml_import(); - retry: - if (!hwloc_libxml_callbacks || (hwloc_nolibxml_callbacks && force_nolibxml)) - ret = hwloc_nolibxml_callbacks->import_diff(&state, NULL, xmlbuffer, buflen, firstdiffp, refnamep); - else { - ret = hwloc_libxml_callbacks->import_diff(&state, NULL, xmlbuffer, buflen, firstdiffp, refnamep); - if (ret < 0 && errno == ENOSYS) { - hwloc_libxml_callbacks = NULL; - goto retry; - } - } - - hwloc_localeswitch_fini(); - - free(fakedata.msgprefix); - return ret; -} - -/************************************************ - ********* XML export (common routines) ********* - ************************************************/ - -#define HWLOC_XML_CHAR_VALID(c) (((c) >= 32 && (c) <= 126) || (c) == '\t' || (c) == '\n' || (c) == '\r') - -static int -hwloc__xml_export_check_buffer(const char *buf, size_t length) -{ - unsigned i; - for(i=0; inew_child(parentstate, &state, "object"); - - state.new_prop(&state, "type", hwloc_obj_type_string(obj->type)); - if (obj->os_level != -1) { - sprintf(tmp, "%d", obj->os_level); - state.new_prop(&state, "os_level", tmp); - } - if (obj->os_index != (unsigned) -1) { - sprintf(tmp, "%u", obj->os_index); - state.new_prop(&state, "os_index", tmp); - } - if (obj->cpuset) { - hwloc_bitmap_asprintf(&cpuset, obj->cpuset); - state.new_prop(&state, "cpuset", cpuset); - free(cpuset); - } - if (obj->complete_cpuset) { - hwloc_bitmap_asprintf(&cpuset, obj->complete_cpuset); - state.new_prop(&state, "complete_cpuset", cpuset); - free(cpuset); - } - if (obj->online_cpuset) { - hwloc_bitmap_asprintf(&cpuset, obj->online_cpuset); - state.new_prop(&state, "online_cpuset", cpuset); - free(cpuset); - } - if (obj->allowed_cpuset) { - hwloc_bitmap_asprintf(&cpuset, obj->allowed_cpuset); - state.new_prop(&state, "allowed_cpuset", cpuset); - free(cpuset); - } - if (obj->nodeset && !hwloc_bitmap_isfull(obj->nodeset)) { - hwloc_bitmap_asprintf(&cpuset, obj->nodeset); - state.new_prop(&state, "nodeset", cpuset); - free(cpuset); - } - if (obj->complete_nodeset && !hwloc_bitmap_isfull(obj->complete_nodeset)) { - hwloc_bitmap_asprintf(&cpuset, obj->complete_nodeset); - state.new_prop(&state, "complete_nodeset", cpuset); - free(cpuset); - } - if (obj->allowed_nodeset && !hwloc_bitmap_isfull(obj->allowed_nodeset)) { - hwloc_bitmap_asprintf(&cpuset, obj->allowed_nodeset); - state.new_prop(&state, "allowed_nodeset", cpuset); - free(cpuset); - } - - if (obj->name) { - char *name = hwloc__xml_export_safestrdup(obj->name); - state.new_prop(&state, "name", name); - free(name); - } - - switch (obj->type) { - case HWLOC_OBJ_CACHE: - sprintf(tmp, "%llu", (unsigned long long) obj->attr->cache.size); - state.new_prop(&state, "cache_size", tmp); - sprintf(tmp, "%u", obj->attr->cache.depth); - state.new_prop(&state, "depth", tmp); - sprintf(tmp, "%u", (unsigned) obj->attr->cache.linesize); - state.new_prop(&state, "cache_linesize", tmp); - sprintf(tmp, "%d", (unsigned) obj->attr->cache.associativity); - state.new_prop(&state, "cache_associativity", tmp); - sprintf(tmp, "%d", (unsigned) obj->attr->cache.type); - state.new_prop(&state, "cache_type", tmp); - break; - case HWLOC_OBJ_GROUP: - sprintf(tmp, "%u", obj->attr->group.depth); - state.new_prop(&state, "depth", tmp); - break; - case HWLOC_OBJ_BRIDGE: - sprintf(tmp, "%u-%u", obj->attr->bridge.upstream_type, obj->attr->bridge.downstream_type); - state.new_prop(&state, "bridge_type", tmp); - sprintf(tmp, "%u", obj->attr->bridge.depth); - state.new_prop(&state, "depth", tmp); - if (obj->attr->bridge.downstream_type == HWLOC_OBJ_BRIDGE_PCI) { - sprintf(tmp, "%04x:[%02x-%02x]", - (unsigned) obj->attr->bridge.downstream.pci.domain, - (unsigned) obj->attr->bridge.downstream.pci.secondary_bus, - (unsigned) obj->attr->bridge.downstream.pci.subordinate_bus); - state.new_prop(&state, "bridge_pci", tmp); - } - if (obj->attr->bridge.upstream_type != HWLOC_OBJ_BRIDGE_PCI) - break; - /* fallthrough */ - case HWLOC_OBJ_PCI_DEVICE: - sprintf(tmp, "%04x:%02x:%02x.%01x", - (unsigned) obj->attr->pcidev.domain, - (unsigned) obj->attr->pcidev.bus, - (unsigned) obj->attr->pcidev.dev, - (unsigned) obj->attr->pcidev.func); - state.new_prop(&state, "pci_busid", tmp); - sprintf(tmp, "%04x [%04x:%04x] [%04x:%04x] %02x", - (unsigned) obj->attr->pcidev.class_id, - (unsigned) obj->attr->pcidev.vendor_id, (unsigned) obj->attr->pcidev.device_id, - (unsigned) obj->attr->pcidev.subvendor_id, (unsigned) obj->attr->pcidev.subdevice_id, - (unsigned) obj->attr->pcidev.revision); - state.new_prop(&state, "pci_type", tmp); - sprintf(tmp, "%f", obj->attr->pcidev.linkspeed); - state.new_prop(&state, "pci_link_speed", tmp); - break; - case HWLOC_OBJ_OS_DEVICE: - sprintf(tmp, "%u", obj->attr->osdev.type); - state.new_prop(&state, "osdev_type", tmp); - break; - default: - break; - } - - if (obj->memory.local_memory) { - sprintf(tmp, "%llu", (unsigned long long) obj->memory.local_memory); - state.new_prop(&state, "local_memory", tmp); - } - - for(i=0; imemory.page_types_len; i++) { - struct hwloc__xml_export_state_s childstate; - state.new_child(&state, &childstate, "page_type"); - sprintf(tmp, "%llu", (unsigned long long) obj->memory.page_types[i].size); - childstate.new_prop(&childstate, "size", tmp); - sprintf(tmp, "%llu", (unsigned long long) obj->memory.page_types[i].count); - childstate.new_prop(&childstate, "count", tmp); - childstate.end_object(&childstate, "page_type"); - } - - for(i=0; iinfos_count; i++) { - char *name = hwloc__xml_export_safestrdup(obj->infos[i].name); - char *value = hwloc__xml_export_safestrdup(obj->infos[i].value); - struct hwloc__xml_export_state_s childstate; - state.new_child(&state, &childstate, "info"); - childstate.new_prop(&childstate, "name", name); - childstate.new_prop(&childstate, "value", value); - childstate.end_object(&childstate, "info"); - free(name); - free(value); - } - - for(i=0; idistances_count; i++) { - unsigned nbobjs = obj->distances[i]->nbobjs; - unsigned j; - struct hwloc__xml_export_state_s childstate; - state.new_child(&state, &childstate, "distances"); - sprintf(tmp, "%u", nbobjs); - childstate.new_prop(&childstate, "nbobjs", tmp); - sprintf(tmp, "%u", obj->distances[i]->relative_depth); - childstate.new_prop(&childstate, "relative_depth", tmp); - sprintf(tmp, "%f", obj->distances[i]->latency_base); - childstate.new_prop(&childstate, "latency_base", tmp); - for(j=0; jdistances[i]->latency[j]); - greatchildstate.new_prop(&greatchildstate, "value", tmp); - greatchildstate.end_object(&greatchildstate, "latency"); - } - childstate.end_object(&childstate, "distances"); - } - - if (obj->userdata && topology->userdata_export_cb) - topology->userdata_export_cb((void*) &state, topology, obj); - - if (obj->arity) { - unsigned x; - for (x=0; xarity; x++) - hwloc__xml_export_object (&state, topology, obj->children[x]); - } - - state.end_object(&state, "object"); -} - -void -hwloc__xml_export_diff(hwloc__xml_export_state_t parentstate, hwloc_topology_diff_t diff) -{ - while (diff) { - struct hwloc__xml_export_state_s state; - char tmp[255]; - - parentstate->new_child(parentstate, &state, "diff"); - - sprintf(tmp, "%u", diff->generic.type); - state.new_prop(&state, "type", tmp); - - switch (diff->generic.type) { - case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR: - sprintf(tmp, "%d", diff->obj_attr.obj_depth); - state.new_prop(&state, "obj_depth", tmp); - sprintf(tmp, "%u", diff->obj_attr.obj_index); - state.new_prop(&state, "obj_index", tmp); - - sprintf(tmp, "%u", diff->obj_attr.diff.generic.type); - state.new_prop(&state, "obj_attr_type", tmp); - - switch (diff->obj_attr.diff.generic.type) { - case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_SIZE: - sprintf(tmp, "%llu", (unsigned long long) diff->obj_attr.diff.uint64.index); - state.new_prop(&state, "obj_attr_index", tmp); - sprintf(tmp, "%llu", (unsigned long long) diff->obj_attr.diff.uint64.oldvalue); - state.new_prop(&state, "obj_attr_oldvalue", tmp); - sprintf(tmp, "%llu", (unsigned long long) diff->obj_attr.diff.uint64.newvalue); - state.new_prop(&state, "obj_attr_newvalue", tmp); - break; - case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_NAME: - case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_INFO: - if (diff->obj_attr.diff.string.name) - state.new_prop(&state, "obj_attr_name", diff->obj_attr.diff.string.name); - state.new_prop(&state, "obj_attr_oldvalue", diff->obj_attr.diff.string.oldvalue); - state.new_prop(&state, "obj_attr_newvalue", diff->obj_attr.diff.string.newvalue); - break; - } - - break; - default: - assert(0); - } - state.end_object(&state, "diff"); - - diff = diff->generic.next; - } -} - -/********************************** - ********* main XML export ******** - **********************************/ - -/* this can be the first XML call */ -int hwloc_topology_export_xml(hwloc_topology_t topology, const char *filename) -{ - hwloc_localeswitch_declare; - int force_nolibxml; - int ret; - - if (!hwloc_libxml_callbacks && !hwloc_nolibxml_callbacks) { - errno = ENOSYS; - return -1; - } - - hwloc_localeswitch_init(); - - force_nolibxml = hwloc_nolibxml_export(); -retry: - if (!hwloc_libxml_callbacks || (hwloc_nolibxml_callbacks && force_nolibxml)) - ret = hwloc_nolibxml_callbacks->export_file(topology, filename); - else { - ret = hwloc_libxml_callbacks->export_file(topology, filename); - if (ret < 0 && errno == ENOSYS) { - hwloc_libxml_callbacks = NULL; - goto retry; - } - } - - hwloc_localeswitch_fini(); - return ret; -} - -/* this can be the first XML call */ -int hwloc_topology_export_xmlbuffer(hwloc_topology_t topology, char **xmlbuffer, int *buflen) -{ - hwloc_localeswitch_declare; - int force_nolibxml; - int ret; - - if (!hwloc_libxml_callbacks && !hwloc_nolibxml_callbacks) { - errno = ENOSYS; - return -1; - } - - hwloc_localeswitch_init(); - - force_nolibxml = hwloc_nolibxml_export(); -retry: - if (!hwloc_libxml_callbacks || (hwloc_nolibxml_callbacks && force_nolibxml)) - ret = hwloc_nolibxml_callbacks->export_buffer(topology, xmlbuffer, buflen); - else { - ret = hwloc_libxml_callbacks->export_buffer(topology, xmlbuffer, buflen); - if (ret < 0 && errno == ENOSYS) { - hwloc_libxml_callbacks = NULL; - goto retry; - } - } - - hwloc_localeswitch_fini(); - return ret; -} - -/* this can be the first XML call */ -int -hwloc_topology_diff_export_xml(hwloc_topology_t topology __hwloc_attribute_unused, - hwloc_topology_diff_t diff, const char *refname, - const char *filename) -{ - hwloc_localeswitch_declare; - hwloc_topology_diff_t tmpdiff; - int force_nolibxml; - int ret; - - if (!hwloc_libxml_callbacks && !hwloc_nolibxml_callbacks) { - errno = ENOSYS; - return -1; - } - - tmpdiff = diff; - while (tmpdiff) { - if (tmpdiff->generic.type == HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX) { - errno = EINVAL; - return -1; - } - tmpdiff = tmpdiff->generic.next; - } - - hwloc_localeswitch_init(); - - force_nolibxml = hwloc_nolibxml_export(); -retry: - if (!hwloc_libxml_callbacks || (hwloc_nolibxml_callbacks && force_nolibxml)) - ret = hwloc_nolibxml_callbacks->export_diff_file(diff, refname, filename); - else { - ret = hwloc_libxml_callbacks->export_diff_file(diff, refname, filename); - if (ret < 0 && errno == ENOSYS) { - hwloc_libxml_callbacks = NULL; - goto retry; - } - } - - hwloc_localeswitch_fini(); - return ret; -} - -/* this can be the first XML call */ -int -hwloc_topology_diff_export_xmlbuffer(hwloc_topology_t topology __hwloc_attribute_unused, - hwloc_topology_diff_t diff, const char *refname, - char **xmlbuffer, int *buflen) -{ - hwloc_localeswitch_declare; - hwloc_topology_diff_t tmpdiff; - int force_nolibxml; - int ret; - - if (!hwloc_libxml_callbacks && !hwloc_nolibxml_callbacks) { - errno = ENOSYS; - return -1; - } - - tmpdiff = diff; - while (tmpdiff) { - if (tmpdiff->generic.type == HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX) { - errno = EINVAL; - return -1; - } - tmpdiff = tmpdiff->generic.next; - } - - hwloc_localeswitch_init(); - - force_nolibxml = hwloc_nolibxml_export(); -retry: - if (!hwloc_libxml_callbacks || (hwloc_nolibxml_callbacks && force_nolibxml)) - ret = hwloc_nolibxml_callbacks->export_diff_buffer(diff, refname, xmlbuffer, buflen); - else { - ret = hwloc_libxml_callbacks->export_diff_buffer(diff, refname, xmlbuffer, buflen); - if (ret < 0 && errno == ENOSYS) { - hwloc_libxml_callbacks = NULL; - goto retry; - } - } - - hwloc_localeswitch_fini(); - return ret; -} - -void hwloc_free_xmlbuffer(hwloc_topology_t topology __hwloc_attribute_unused, char *xmlbuffer) -{ - int force_nolibxml; - - if (!hwloc_libxml_callbacks && !hwloc_nolibxml_callbacks) { - errno = ENOSYS; - return ; - } - - force_nolibxml = hwloc_nolibxml_export(); - if (!hwloc_libxml_callbacks || (hwloc_nolibxml_callbacks && force_nolibxml)) - hwloc_nolibxml_callbacks->free_buffer(xmlbuffer); - else - hwloc_libxml_callbacks->free_buffer(xmlbuffer); -} - -void -hwloc_topology_set_userdata_export_callback(hwloc_topology_t topology, - void (*export)(void *reserved, struct hwloc_topology *topology, struct hwloc_obj *obj)) -{ - topology->userdata_export_cb = export; -} - -static void -hwloc__export_obj_userdata(hwloc__xml_export_state_t parentstate, int encoded, - const char *name, size_t length, const void *buffer, size_t encoded_length) -{ - struct hwloc__xml_export_state_s state; - char tmp[255]; - parentstate->new_child(parentstate, &state, "userdata"); - if (name) - state.new_prop(&state, "name", name); - sprintf(tmp, "%lu", (unsigned long) length); - state.new_prop(&state, "length", tmp); - if (encoded) - state.new_prop(&state, "encoding", "base64"); - if (encoded_length) - state.add_content(&state, buffer, encoded ? encoded_length : length); - state.end_object(&state, "userdata"); -} - -int -hwloc_export_obj_userdata(void *reserved, - struct hwloc_topology *topology, struct hwloc_obj *obj __hwloc_attribute_unused, - const char *name, const void *buffer, size_t length) -{ - hwloc__xml_export_state_t state = reserved; - - if (!buffer) { - errno = EINVAL; - return -1; - } - - if ((name && hwloc__xml_export_check_buffer(name, strlen(name)) < 0) - || hwloc__xml_export_check_buffer(buffer, length) < 0) { - errno = EINVAL; - return -1; - } - - if (topology->userdata_not_decoded) { - int encoded; - size_t encoded_length; - const char *realname; - if (!strncmp(name, "normal", 6)) { - encoded = 0; - encoded_length = length; - } else if (!strncmp(name, "base64", 6)) { - encoded = 1; - encoded_length = BASE64_ENCODED_LENGTH(length); - } else - assert(0); - if (name[6] == ':') - realname = name+7; - else if (!strcmp(name+6, "-anon")) - realname = NULL; - else - assert(0); - hwloc__export_obj_userdata(state, encoded, realname, length, buffer, encoded_length); - - } else - hwloc__export_obj_userdata(state, 0, name, length, buffer, length); - - return 0; -} - -int -hwloc_export_obj_userdata_base64(void *reserved, - struct hwloc_topology *topology __hwloc_attribute_unused, struct hwloc_obj *obj __hwloc_attribute_unused, - const char *name, const void *buffer, size_t length) -{ - hwloc__xml_export_state_t state = reserved; - size_t encoded_length; - char *encoded_buffer; - int ret __hwloc_attribute_unused; - - if (!buffer) { - errno = EINVAL; - return -1; - } - - assert(!topology->userdata_not_decoded); - - if (name && hwloc__xml_export_check_buffer(name, strlen(name)) < 0) { - errno = EINVAL; - return -1; - } - - encoded_length = BASE64_ENCODED_LENGTH(length); - encoded_buffer = malloc(encoded_length+1); - if (!encoded_buffer) { - errno = ENOMEM; - return -1; - } - - ret = hwloc_encode_to_base64(buffer, length, encoded_buffer, encoded_length+1); - assert(ret == (int) encoded_length); - - hwloc__export_obj_userdata(state, 1, name, length, encoded_buffer, encoded_length); - - free(encoded_buffer); - return 0; -} - -void -hwloc_topology_set_userdata_import_callback(hwloc_topology_t topology, - void (*import)(struct hwloc_topology *topology, struct hwloc_obj *obj, const char *name, const void *buffer, size_t length)) -{ - topology->userdata_import_cb = import; -} - -/*************************************** - ************ XML component ************ - ***************************************/ - -static void -hwloc_xml_backend_disable(struct hwloc_backend *backend) -{ - struct hwloc_xml_backend_data_s *data = backend->private_data; - data->backend_exit(data); - free(data->msgprefix); - free(data); -} - -static struct hwloc_backend * -hwloc_xml_component_instantiate(struct hwloc_disc_component *component, - const void *_data1, - const void *_data2, - const void *_data3) -{ - struct hwloc_xml_backend_data_s *data; - struct hwloc_backend *backend; - int force_nolibxml; - const char * xmlpath = (const char *) _data1; - const char * xmlbuffer = (const char *) _data2; - int xmlbuflen = (int)(uintptr_t) _data3; - const char *basename; - int err; - - if (!hwloc_libxml_callbacks && !hwloc_nolibxml_callbacks) { - errno = ENOSYS; - goto out; - } - - if (!xmlpath && !xmlbuffer) { - errno = EINVAL; - goto out; - } - - backend = hwloc_backend_alloc(component); - if (!backend) - goto out; - - data = malloc(sizeof(*data)); - if (!data) { - errno = ENOMEM; - goto out_with_backend; - } - - backend->private_data = data; - backend->discover = hwloc_look_xml; - backend->disable = hwloc_xml_backend_disable; - backend->is_thissystem = 0; - - if (xmlpath) { - basename = strrchr(xmlpath, '/'); - if (basename) - basename++; - else - basename = xmlpath; - } else { - basename = "xmlbuffer"; - } - data->msgprefix = strdup(basename); - - force_nolibxml = hwloc_nolibxml_import(); -retry: - if (!hwloc_libxml_callbacks || (hwloc_nolibxml_callbacks && force_nolibxml)) - err = hwloc_nolibxml_callbacks->backend_init(data, xmlpath, xmlbuffer, xmlbuflen); - else { - err = hwloc_libxml_callbacks->backend_init(data, xmlpath, xmlbuffer, xmlbuflen); - if (err < 0 && errno == ENOSYS) { - hwloc_libxml_callbacks = NULL; - goto retry; - } - } - if (err < 0) - goto out_with_data; - - return backend; - - out_with_data: - free(data->msgprefix); - free(data); - out_with_backend: - free(backend); - out: - return NULL; -} - -static struct hwloc_disc_component hwloc_xml_disc_component = { - HWLOC_DISC_COMPONENT_TYPE_GLOBAL, - "xml", - ~0, - hwloc_xml_component_instantiate, - 30, - NULL -}; - -const struct hwloc_component hwloc_xml_component = { - HWLOC_COMPONENT_ABI, - NULL, NULL, - HWLOC_COMPONENT_TYPE_DISC, - 0, - &hwloc_xml_disc_component -}; diff --git a/opal/mca/hwloc/hwloc1116/hwloc/src/topology.c b/opal/mca/hwloc/hwloc1116/hwloc/src/topology.c deleted file mode 100644 index c7716cf5aa..0000000000 --- a/opal/mca/hwloc/hwloc1116/hwloc/src/topology.c +++ /dev/null @@ -1,3337 +0,0 @@ -/* - * Copyright © 2009 CNRS - * Copyright © 2009-2017 Inria. All rights reserved. - * Copyright © 2009-2012 Université Bordeaux - * Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved. - * See COPYING in top-level directory. - */ - -#include - -#define _ATFILE_SOURCE -#include -#include -#ifdef HAVE_DIRENT_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#ifdef HAVE_MACH_MACH_INIT_H -#include -#endif -#ifdef HAVE_MACH_MACH_HOST_H -#include -#endif - -#ifdef HAVE_SYS_PARAM_H -#include -#endif - -#ifdef HAVE_SYS_SYSCTL_H -#include -#endif - -#ifdef HWLOC_WIN_SYS -#include -#endif - -unsigned hwloc_get_api_version(void) -{ - return HWLOC_API_VERSION; -} - -int hwloc_hide_errors(void) -{ - static int hide = 0; - static int checked = 0; - if (!checked) { - const char *envvar = getenv("HWLOC_HIDE_ERRORS"); - if (envvar) - hide = atoi(envvar); - checked = 1; - } - return hide; -} - -void hwloc_report_os_error(const char *msg, int line) -{ - static int reported = 0; - - if (!reported && !hwloc_hide_errors()) { - fprintf(stderr, "****************************************************************************\n"); - fprintf(stderr, "* hwloc %s has encountered what looks like an error from the operating system.\n", HWLOC_VERSION); - fprintf(stderr, "*\n"); - fprintf(stderr, "* %s\n", msg); - fprintf(stderr, "* Error occurred in topology.c line %d\n", line); - fprintf(stderr, "*\n"); - fprintf(stderr, "* The following FAQ entry in the hwloc documentation may help:\n"); - fprintf(stderr, "* What should I do when hwloc reports \"operating system\" warnings?\n"); - fprintf(stderr, "* Otherwise please report this error message to the hwloc user's mailing list,\n"); -#ifdef HWLOC_LINUX_SYS - fprintf(stderr, "* along with the output+tarball generated by the hwloc-gather-topology script.\n"); -#else - fprintf(stderr, "* along with any relevant topology information from your platform.\n"); -#endif - fprintf(stderr, "****************************************************************************\n"); - reported = 1; - } -} - -#if defined(HAVE_SYSCTLBYNAME) -int hwloc_get_sysctlbyname(const char *name, int64_t *ret) -{ - union { - int32_t i32; - int64_t i64; - } n; - size_t size = sizeof(n); - if (sysctlbyname(name, &n, &size, NULL, 0)) - return -1; - switch (size) { - case sizeof(n.i32): - *ret = n.i32; - break; - case sizeof(n.i64): - *ret = n.i64; - break; - default: - return -1; - } - return 0; -} -#endif - -#if defined(HAVE_SYSCTL) -int hwloc_get_sysctl(int name[], unsigned namelen, int *ret) -{ - int n; - size_t size = sizeof(n); - if (sysctl(name, namelen, &n, &size, NULL, 0)) - return -1; - if (size != sizeof(n)) - return -1; - *ret = n; - return 0; -} -#endif - -/* Return the OS-provided number of processors. Unlike other methods such as - reading sysfs on Linux, this method is not virtualizable; thus it's only - used as a fall-back method, allowing `hwloc_set_fsroot ()' to - have the desired effect. */ -#ifndef HWLOC_WIN_SYS /* The windows implementation is in topology-windows.c */ -unsigned -hwloc_fallback_nbprocessors(struct hwloc_topology *topology) { - int n; -#if HAVE_DECL__SC_NPROCESSORS_ONLN - n = sysconf(_SC_NPROCESSORS_ONLN); -#elif HAVE_DECL__SC_NPROC_ONLN - n = sysconf(_SC_NPROC_ONLN); -#elif HAVE_DECL__SC_NPROCESSORS_CONF - n = sysconf(_SC_NPROCESSORS_CONF); -#elif HAVE_DECL__SC_NPROC_CONF - n = sysconf(_SC_NPROC_CONF); -#elif defined(HAVE_HOST_INFO) && HAVE_HOST_INFO - struct host_basic_info info; - mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT; - host_info(mach_host_self(), HOST_BASIC_INFO, (integer_t*) &info, &count); - n = info.avail_cpus; -#elif defined(HAVE_SYSCTLBYNAME) - int64_t nn; - if (hwloc_get_sysctlbyname("hw.ncpu", &nn)) - nn = -1; - n = nn; -#elif defined(HAVE_SYSCTL) && HAVE_DECL_CTL_HW && HAVE_DECL_HW_NCPU - static int name[2] = {CTL_HW, HW_NPCU}; - if (hwloc_get_sysctl(name, sizeof(name)/sizeof(*name)), &n) - n = -1; -#else -#ifdef __GNUC__ -#warning No known way to discover number of available processors on this system -#warning hwloc_fallback_nbprocessors will default to 1 -#endif - n = -1; -#endif - if (n >= 1) - topology->support.discovery->pu = 1; - else - n = 1; - return n; -} -#endif /* !HWLOC_WIN_SYS */ - -/* - * Use the given number of processors and the optional online cpuset if given - * to set a PU level. - */ -void -hwloc_setup_pu_level(struct hwloc_topology *topology, - unsigned nb_pus) -{ - struct hwloc_obj *obj; - unsigned oscpu,cpu; - - hwloc_debug("%s", "\n\n * CPU cpusets *\n\n"); - for (cpu=0,oscpu=0; cpucpuset = hwloc_bitmap_alloc(); - hwloc_bitmap_only(obj->cpuset, oscpu); - - hwloc_debug_2args_bitmap("cpu %u (os %u) has cpuset %s\n", - cpu, oscpu, obj->cpuset); - hwloc_insert_object_by_cpuset(topology, obj); - - cpu++; - } -} - -#ifdef HWLOC_DEBUG -/* Just for debugging. */ -static void -hwloc_debug_print_object(int indent __hwloc_attribute_unused, hwloc_obj_t obj) -{ - char type[64], idx[10], attr[1024], *cpuset = NULL; - hwloc_debug("%*s", 2*indent, ""); - hwloc_obj_type_snprintf(type, sizeof(type), obj, 1); - if (obj->os_index != (unsigned) -1) - snprintf(idx, sizeof(idx), "#%u", obj->os_index); - else - *idx = '\0'; - hwloc_obj_attr_snprintf(attr, sizeof(attr), obj, " ", 1); - hwloc_debug("%s%s%s%s%s", type, idx, *attr ? "(" : "", attr, *attr ? ")" : ""); - if (obj->name) - hwloc_debug(" name %s", obj->name); - if (obj->cpuset) { - hwloc_bitmap_asprintf(&cpuset, obj->cpuset); - hwloc_debug(" cpuset %s", cpuset); - free(cpuset); - } - if (obj->complete_cpuset) { - hwloc_bitmap_asprintf(&cpuset, obj->complete_cpuset); - hwloc_debug(" complete %s", cpuset); - free(cpuset); - } - if (obj->online_cpuset) { - hwloc_bitmap_asprintf(&cpuset, obj->online_cpuset); - hwloc_debug(" online %s", cpuset); - free(cpuset); - } - if (obj->allowed_cpuset) { - hwloc_bitmap_asprintf(&cpuset, obj->allowed_cpuset); - hwloc_debug(" allowed %s", cpuset); - free(cpuset); - } - if (obj->nodeset) { - hwloc_bitmap_asprintf(&cpuset, obj->nodeset); - hwloc_debug(" nodeset %s", cpuset); - free(cpuset); - } - if (obj->complete_nodeset) { - hwloc_bitmap_asprintf(&cpuset, obj->complete_nodeset); - hwloc_debug(" completeN %s", cpuset); - free(cpuset); - } - if (obj->allowed_nodeset) { - hwloc_bitmap_asprintf(&cpuset, obj->allowed_nodeset); - hwloc_debug(" allowedN %s", cpuset); - free(cpuset); - } - if (obj->arity) - hwloc_debug(" arity %u", obj->arity); - hwloc_debug("%s", "\n"); -} - -static void -hwloc_debug_print_objects(int indent __hwloc_attribute_unused, hwloc_obj_t obj) -{ - hwloc_debug_print_object(indent, obj); - for (obj = obj->first_child; obj; obj = obj->next_sibling) - hwloc_debug_print_objects(indent + 1, obj); -} -#else /* !HWLOC_DEBUG */ -#define hwloc_debug_print_object(indent, obj) do { /* nothing */ } while (0) -#define hwloc_debug_print_objects(indent, obj) do { /* nothing */ } while (0) -#endif /* !HWLOC_DEBUG */ - -void hwloc__free_infos(struct hwloc_obj_info_s *infos, unsigned count) -{ - unsigned i; - for(i=0; iinfos, &obj->infos_count, name, value); -} - -void hwloc_obj_add_info_nodup(hwloc_obj_t obj, const char *name, const char *value, int nodup) -{ - if (nodup && hwloc_obj_get_info_by_name(obj, name)) - return; - hwloc__add_info(&obj->infos, &obj->infos_count, name, value); -} - -/* Traverse children of a parent in a safe way: reread the next pointer as - * appropriate to prevent crash on child deletion: */ -#define for_each_child_safe(child, parent, pchild) \ - for (pchild = &(parent)->first_child, child = *pchild; \ - child; \ - /* Check whether the current child was not dropped. */ \ - (*pchild == child ? pchild = &(child->next_sibling) : NULL), \ - /* Get pointer to next childect. */ \ - child = *pchild) - -static void -hwloc__free_object_contents(hwloc_obj_t obj) -{ - switch (obj->type) { - default: - break; - } - hwloc__free_infos(obj->infos, obj->infos_count); - hwloc_clear_object_distances(obj); - free(obj->memory.page_types); - free(obj->attr); - free(obj->children); - free(obj->name); - hwloc_bitmap_free(obj->cpuset); - hwloc_bitmap_free(obj->complete_cpuset); - hwloc_bitmap_free(obj->online_cpuset); - hwloc_bitmap_free(obj->allowed_cpuset); - hwloc_bitmap_free(obj->nodeset); - hwloc_bitmap_free(obj->complete_nodeset); - hwloc_bitmap_free(obj->allowed_nodeset); -} - -/* Free an object and all its content. */ -void -hwloc_free_unlinked_object(hwloc_obj_t obj) -{ - hwloc__free_object_contents(obj); - free(obj); -} - -/* Replace old with contents of new object, and make new freeable by the caller. - * Only updates next_sibling/first_child pointers, - * so may only be used during early discovery. - */ -static void -hwloc_replace_linked_object(hwloc_obj_t old, hwloc_obj_t new) -{ - /* drop old fields */ - hwloc__free_object_contents(old); - /* copy old tree pointers to new */ - new->next_sibling = old->next_sibling; - new->first_child = old->first_child; - /* copy new contents to old now that tree pointers are OK */ - memcpy(old, new, sizeof(*old)); - /* clear new to that we may free it */ - memset(new, 0,sizeof(*new)); -} - -/* insert the (non-empty) list of sibling starting at firstnew as new children of newparent, - * and return the address of the pointer to the next one - */ -static hwloc_obj_t * -insert_siblings_list(hwloc_obj_t *firstp, hwloc_obj_t firstnew, hwloc_obj_t newparent) -{ - hwloc_obj_t tmp; - assert(firstnew); - *firstp = tmp = firstnew; - tmp->parent = newparent; - while (tmp->next_sibling) { - tmp = tmp->next_sibling; - } - return &tmp->next_sibling; -} - -/* Remove an object from its parent and free it. - * Only updates next_sibling/first_child pointers, - * so may only be used during early discovery. - * Children are inserted where the object was. - */ -static void -unlink_and_free_single_object(hwloc_obj_t *pparent) -{ - hwloc_obj_t old = *pparent; - hwloc_obj_t *lastp; - - if (old->first_child) - /* insert old object children as new siblings below parent instead of old */ - lastp = insert_siblings_list(pparent, old->first_child, old->parent); - else - lastp = pparent; - /* append old siblings back */ - *lastp = old->next_sibling; - - hwloc_free_unlinked_object(old); -} - -/* Remove an object and its children from its parent and free them. - * Only updates next_sibling/first_child pointers, - * so may only be used during early discovery. - */ -static void -unlink_and_free_object_and_children(hwloc_obj_t *pobj) -{ - hwloc_obj_t obj = *pobj, child, *pchild; - - for_each_child_safe(child, obj, pchild) - unlink_and_free_object_and_children(pchild); - - *pobj = obj->next_sibling; - hwloc_free_unlinked_object(obj); -} - -static void -hwloc__duplicate_object(struct hwloc_obj *newobj, - struct hwloc_obj *src) -{ - size_t len; - unsigned i; - - newobj->type = src->type; - newobj->os_index = src->os_index; - - if (src->name) - newobj->name = strdup(src->name); - newobj->userdata = src->userdata; - - memcpy(&newobj->memory, &src->memory, sizeof(struct hwloc_obj_memory_s)); - if (src->memory.page_types_len) { - len = src->memory.page_types_len * sizeof(struct hwloc_obj_memory_page_type_s); - newobj->memory.page_types = malloc(len); - memcpy(newobj->memory.page_types, src->memory.page_types, len); - } - - memcpy(newobj->attr, src->attr, sizeof(*newobj->attr)); - - newobj->cpuset = hwloc_bitmap_dup(src->cpuset); - newobj->complete_cpuset = hwloc_bitmap_dup(src->complete_cpuset); - newobj->allowed_cpuset = hwloc_bitmap_dup(src->allowed_cpuset); - newobj->online_cpuset = hwloc_bitmap_dup(src->online_cpuset); - newobj->nodeset = hwloc_bitmap_dup(src->nodeset); - newobj->complete_nodeset = hwloc_bitmap_dup(src->complete_nodeset); - newobj->allowed_nodeset = hwloc_bitmap_dup(src->allowed_nodeset); - - /* don't duplicate distances, they'll be recreated at the end of the topology build */ - - for(i=0; iinfos_count; i++) - hwloc__add_info(&newobj->infos, &newobj->infos_count, src->infos[i].name, src->infos[i].value); -} - -void -hwloc__duplicate_objects(struct hwloc_topology *newtopology, - struct hwloc_obj *newparent, - struct hwloc_obj *src) -{ - hwloc_obj_t newobj; - hwloc_obj_t child; - - newobj = hwloc_alloc_setup_object(src->type, src->os_index); - hwloc__duplicate_object(newobj, src); - - child = NULL; - while ((child = hwloc_get_next_child(newtopology, src, child)) != NULL) - hwloc__duplicate_objects(newtopology, newobj, child); - - /* no need to check the children order here, the source topology - * is supposed to be OK already, and we have debug asserts. - */ - hwloc_insert_object_by_parent(newtopology, newparent, newobj); -} - -int -hwloc_topology_dup(hwloc_topology_t *newp, - hwloc_topology_t old) -{ - hwloc_topology_t new; - hwloc_obj_t newroot; - hwloc_obj_t oldroot = hwloc_get_root_obj(old); - unsigned i; - - if (!old->is_loaded) { - errno = EINVAL; - return -1; - } - - hwloc_topology_init(&new); - - new->flags = old->flags; - memcpy(new->ignored_types, old->ignored_types, sizeof(old->ignored_types)); - new->is_thissystem = old->is_thissystem; - new->is_loaded = 1; - new->pid = old->pid; - - memcpy(&new->binding_hooks, &old->binding_hooks, sizeof(old->binding_hooks)); - - memcpy(new->support.discovery, old->support.discovery, sizeof(*old->support.discovery)); - memcpy(new->support.cpubind, old->support.cpubind, sizeof(*old->support.cpubind)); - memcpy(new->support.membind, old->support.membind, sizeof(*old->support.membind)); - - new->userdata_export_cb = old->userdata_export_cb; - new->userdata_import_cb = old->userdata_import_cb; - new->userdata_not_decoded = old->userdata_not_decoded; - - newroot = hwloc_get_root_obj(new); - hwloc__duplicate_object(newroot, oldroot); - for(i=0; iarity; i++) - hwloc__duplicate_objects(new, newroot, oldroot->children[i]); - - if (old->first_osdist) { - struct hwloc_os_distances_s *olddist = old->first_osdist; - while (olddist) { - struct hwloc_os_distances_s *newdist = malloc(sizeof(*newdist)); - newdist->type = olddist->type; - newdist->nbobjs = olddist->nbobjs; - newdist->indexes = malloc(newdist->nbobjs * sizeof(*newdist->indexes)); - memcpy(newdist->indexes, olddist->indexes, newdist->nbobjs * sizeof(*newdist->indexes)); - newdist->objs = NULL; /* will be recomputed when needed */ - newdist->distances = malloc(newdist->nbobjs * newdist->nbobjs * sizeof(*newdist->distances)); - memcpy(newdist->distances, olddist->distances, newdist->nbobjs * newdist->nbobjs * sizeof(*newdist->distances)); - - newdist->forced = olddist->forced; - if (new->first_osdist) { - new->last_osdist->next = newdist; - newdist->prev = new->last_osdist; - } else { - new->first_osdist = newdist; - newdist->prev = NULL; - } - new->last_osdist = newdist; - newdist->next = NULL; - - olddist = olddist->next; - } - } else - new->first_osdist = old->last_osdist = NULL; - - /* no need to duplicate backends, topology is already loaded */ - new->backends = NULL; - - hwloc_connect_children(new->levels[0][0]); - if (hwloc_connect_levels(new) < 0) - goto out; - - hwloc_distances_finalize_os(new); - hwloc_distances_finalize_logical(new); - -#ifndef HWLOC_DEBUG - if (getenv("HWLOC_DEBUG_CHECK")) -#endif - hwloc_topology_check(new); - - *newp = new; - return 0; - - out: - hwloc_topology_destroy(new); - return -1; -} - -/* WARNING: The indexes of this array MUST match the ordering that of - the obj_order_type[] array, below. Specifically, the values must - be laid out such that: - - obj_order_type[obj_type_order[N]] = N - - for all HWLOC_OBJ_* values of N. Put differently: - - obj_type_order[A] = B - - where the A values are in order of the hwloc_obj_type_t enum, and - the B values are the corresponding indexes of obj_order_type. - - We can't use C99 syntax to initialize this in a little safer manner - -- bummer. :-( - - ************************************************************* - *** DO NOT CHANGE THE ORDERING OF THIS ARRAY WITHOUT TRIPLE - *** CHECKING ITS CORRECTNESS! - ************************************************************* - */ -static const unsigned obj_type_order[] = { - /* first entry is HWLOC_OBJ_SYSTEM */ 0, - /* next entry is HWLOC_OBJ_MACHINE */ 1, - /* next entry is HWLOC_OBJ_NUMANODE */ 3, - /* next entry is HWLOC_OBJ_PACKAGE */ 4, - /* next entry is HWLOC_OBJ_CACHE */ 5, - /* next entry is HWLOC_OBJ_CORE */ 6, - /* next entry is HWLOC_OBJ_PU */ 10, - /* next entry is HWLOC_OBJ_GROUP */ 2, - /* next entry is HWLOC_OBJ_MISC */ 11, - /* next entry is HWLOC_OBJ_BRIDGE */ 7, - /* next entry is HWLOC_OBJ_PCI_DEVICE */ 8, - /* next entry is HWLOC_OBJ_OS_DEVICE */ 9 -}; - -static const hwloc_obj_type_t obj_order_type[] = { - HWLOC_OBJ_SYSTEM, - HWLOC_OBJ_MACHINE, - HWLOC_OBJ_GROUP, - HWLOC_OBJ_NUMANODE, - HWLOC_OBJ_PACKAGE, - HWLOC_OBJ_CACHE, - HWLOC_OBJ_CORE, - HWLOC_OBJ_BRIDGE, - HWLOC_OBJ_PCI_DEVICE, - HWLOC_OBJ_OS_DEVICE, - HWLOC_OBJ_PU, - HWLOC_OBJ_MISC, -}; - -/* priority to be used when merging identical parent/children object - * (in merge_useless_child), keep the highest priority one. - * - * Always keep Machine/PU/PCIDev/OSDev - * then System/Node - * then Core - * then Package - * then Cache - * then always drop Group/Misc/Bridge. - * - * Some type won't actually ever be involved in such merging. - */ -static const int obj_type_priority[] = { - /* first entry is HWLOC_OBJ_SYSTEM */ 80, - /* next entry is HWLOC_OBJ_MACHINE */ 100, - /* next entry is HWLOC_OBJ_NUMANODE */ 80, - /* next entry is HWLOC_OBJ_PACKAGE */ 40, - /* next entry is HWLOC_OBJ_CACHE */ 20, - /* next entry is HWLOC_OBJ_CORE */ 60, - /* next entry is HWLOC_OBJ_PU */ 100, - /* next entry is HWLOC_OBJ_GROUP */ 0, - /* next entry is HWLOC_OBJ_MISC */ 0, - /* next entry is HWLOC_OBJ_BRIDGE */ 0, - /* next entry is HWLOC_OBJ_PCI_DEVICE */ 100, - /* next entry is HWLOC_OBJ_OS_DEVICE */ 100 -}; - -static unsigned __hwloc_attribute_const -hwloc_get_type_order(hwloc_obj_type_t type) -{ - return obj_type_order[type]; -} - -#if !defined(NDEBUG) -static hwloc_obj_type_t hwloc_get_order_type(int order) -{ - return obj_order_type[order]; -} -#endif - -static int hwloc_obj_type_is_io (hwloc_obj_type_t type) -{ - return type == HWLOC_OBJ_BRIDGE || type == HWLOC_OBJ_PCI_DEVICE || type == HWLOC_OBJ_OS_DEVICE; -} - -int hwloc_compare_types (hwloc_obj_type_t type1, hwloc_obj_type_t type2) -{ - unsigned order1 = hwloc_get_type_order(type1); - unsigned order2 = hwloc_get_type_order(type2); - - /* bridge and devices are only comparable with each others and with machine and system */ - if (hwloc_obj_type_is_io(type1) - && !hwloc_obj_type_is_io(type2) && type2 != HWLOC_OBJ_SYSTEM && type2 != HWLOC_OBJ_MACHINE) - return HWLOC_TYPE_UNORDERED; - if (hwloc_obj_type_is_io(type2) - && !hwloc_obj_type_is_io(type1) && type1 != HWLOC_OBJ_SYSTEM && type1 != HWLOC_OBJ_MACHINE) - return HWLOC_TYPE_UNORDERED; - - return order1 - order2; -} - -enum hwloc_obj_cmp_e { - HWLOC_OBJ_EQUAL = HWLOC_BITMAP_EQUAL, /**< \brief Equal */ - HWLOC_OBJ_INCLUDED = HWLOC_BITMAP_INCLUDED, /**< \brief Strictly included into */ - HWLOC_OBJ_CONTAINS = HWLOC_BITMAP_CONTAINS, /**< \brief Strictly contains */ - HWLOC_OBJ_INTERSECTS = HWLOC_BITMAP_INTERSECTS, /**< \brief Intersects, but no inclusion! */ - HWLOC_OBJ_DIFFERENT = HWLOC_BITMAP_DIFFERENT /**< \brief No intersection */ -}; - -static enum hwloc_obj_cmp_e -hwloc_type_cmp(hwloc_obj_t obj1, hwloc_obj_t obj2) -{ - hwloc_obj_type_t type1 = obj1->type; - hwloc_obj_type_t type2 = obj2->type; - int compare; - - compare = hwloc_compare_types(type1, type2); - if (compare == HWLOC_TYPE_UNORDERED) - return HWLOC_OBJ_DIFFERENT; /* we cannot do better */ - if (compare > 0) - return HWLOC_OBJ_INCLUDED; - if (compare < 0) - return HWLOC_OBJ_CONTAINS; - - /* Caches have the same types but can have different depths. */ - if (type1 == HWLOC_OBJ_CACHE) { - if (obj1->attr->cache.depth < obj2->attr->cache.depth) - return HWLOC_OBJ_INCLUDED; - else if (obj1->attr->cache.depth > obj2->attr->cache.depth) - return HWLOC_OBJ_CONTAINS; - else if (obj1->attr->cache.type > obj2->attr->cache.type) - /* consider icache deeper than dcache and dcache deeper than unified */ - return HWLOC_OBJ_INCLUDED; - else if (obj1->attr->cache.type < obj2->attr->cache.type) - /* consider icache deeper than dcache and dcache deeper than unified */ - return HWLOC_OBJ_CONTAINS; - } - - /* Group objects have the same types but can have different depths. */ - if (type1 == HWLOC_OBJ_GROUP) { - if (obj1->attr->group.depth == (unsigned) -1 - || obj2->attr->group.depth == (unsigned) -1) - return HWLOC_OBJ_EQUAL; - if (obj1->attr->group.depth < obj2->attr->group.depth) - return HWLOC_OBJ_INCLUDED; - else if (obj1->attr->group.depth > obj2->attr->group.depth) - return HWLOC_OBJ_CONTAINS; - } - - /* Bridges objects have the same types but can have different depths. */ - if (type1 == HWLOC_OBJ_BRIDGE) { - if (obj1->attr->bridge.depth < obj2->attr->bridge.depth) - return HWLOC_OBJ_INCLUDED; - else if (obj1->attr->bridge.depth > obj2->attr->bridge.depth) - return HWLOC_OBJ_CONTAINS; - } - - return HWLOC_OBJ_EQUAL; -} - -/* - * How to compare objects based on cpusets. - */ - -static int -hwloc_obj_cmp_sets(hwloc_obj_t obj1, hwloc_obj_t obj2) -{ - hwloc_bitmap_t set1, set2; - int res = HWLOC_OBJ_DIFFERENT; - - /* compare cpusets first */ - if (obj1->complete_cpuset && obj2->complete_cpuset) { - set1 = obj1->complete_cpuset; - set2 = obj2->complete_cpuset; - } else { - set1 = obj1->cpuset; - set2 = obj2->cpuset; - } - if (set1 && set2 && !hwloc_bitmap_iszero(set1) && !hwloc_bitmap_iszero(set2)) { - res = hwloc_bitmap_compare_inclusion(set1, set2); - if (res == HWLOC_OBJ_INTERSECTS) - return HWLOC_OBJ_INTERSECTS; - } - - /* then compare nodesets, and combine the results */ - if (obj1->complete_nodeset && obj2->complete_nodeset) { - set1 = obj1->complete_nodeset; - set2 = obj2->complete_nodeset; - } else { - set1 = obj1->nodeset; - set2 = obj2->nodeset; - } - if (set1 && set2 && !hwloc_bitmap_iszero(set1) && !hwloc_bitmap_iszero(set2)) { - int noderes = hwloc_bitmap_compare_inclusion(set1, set2); - /* deal with conflicting cpusets/nodesets inclusions */ - if (noderes == HWLOC_OBJ_INCLUDED) { - if (res == HWLOC_OBJ_CONTAINS) - /* contradicting order for cpusets and nodesets */ - return HWLOC_OBJ_INTERSECTS; - res = HWLOC_OBJ_INCLUDED; - - } else if (noderes == HWLOC_OBJ_CONTAINS) { - if (res == HWLOC_OBJ_INCLUDED) - /* contradicting order for cpusets and nodesets */ - return HWLOC_OBJ_INTERSECTS; - res = HWLOC_OBJ_CONTAINS; - - } else if (noderes == HWLOC_OBJ_INTERSECTS) { - return HWLOC_OBJ_INTERSECTS; - - } else { - /* nodesets are different, keep the cpuset order */ - /* FIXME: with upcoming multiple levels of NUMA, we may have to report INCLUDED or CONTAINED here */ - - } - } - - return res; -} - -/* Compare object cpusets based on complete_cpuset if defined (always correctly ordered), - * or fallback to the main cpusets (only correctly ordered during early insert before disallowed/offline bits are cleared). - * - * This is the sane way to compare object among a horizontal level. - */ -int -hwloc__object_cpusets_compare_first(hwloc_obj_t obj1, hwloc_obj_t obj2) -{ - if (obj1->complete_cpuset && obj2->complete_cpuset) - return hwloc_bitmap_compare_first(obj1->complete_cpuset, obj2->complete_cpuset); - else - return hwloc_bitmap_compare_first(obj1->cpuset, obj2->cpuset); -} - -/* format the obj info to print in error messages */ -static void -hwloc__report_error_format_obj(char *buf, size_t buflen, hwloc_obj_t obj) -{ - char typestr[64]; - char *cpusetstr; - hwloc_obj_type_snprintf(typestr, sizeof(typestr), obj, 0); - hwloc_bitmap_asprintf(&cpusetstr, obj->cpuset); - if (obj->os_index != (unsigned) -1) - snprintf(buf, buflen, "%s (P#%u cpuset %s)", - typestr, obj->os_index, cpusetstr); - else - snprintf(buf, buflen, "%s (cpuset %s)", - typestr, cpusetstr); - free(cpusetstr); -} - -/* - * How to insert objects into the topology. - * - * Note: during detection, only the first_child and next_sibling pointers are - * kept up to date. Others are computed only once topology detection is - * complete. - */ - -#define merge_index(new, old, field, type) \ - if ((old)->field == (type) -1) \ - (old)->field = (new)->field; -#define merge_sizes(new, old, field) \ - if (!(old)->field) \ - (old)->field = (new)->field; -#ifdef HWLOC_DEBUG -#define check_sizes(new, old, field) \ - if ((new)->field) \ - assert((old)->field == (new)->field) -#else -#define check_sizes(new, old, field) -#endif - -static void -merge_insert_equal(hwloc_obj_t new, hwloc_obj_t old) -{ - merge_index(new, old, os_index, unsigned); - - if (new->distances_count) { - if (old->distances_count) { - struct hwloc_distances_s **tmpdists; - tmpdists = realloc(old->distances, (old->distances_count+new->distances_count) * sizeof(*old->distances)); - if (!tmpdists) { - /* failed to realloc, ignore new distances */ - hwloc_clear_object_distances(new); - } else { - old->distances = tmpdists; - old->distances_count += new->distances_count; - memcpy(old->distances + new->distances_count, new->distances, new->distances_count * sizeof(*old->distances)); - free(new->distances); - } - } else { - old->distances_count = new->distances_count; - old->distances = new->distances; - } - new->distances_count = 0; - new->distances = NULL; - } - - if (new->infos_count) { - hwloc__move_infos(&old->infos, &old->infos_count, - &new->infos, &new->infos_count); - } - - if (new->name && !old->name) { - old->name = new->name; - new->name = NULL; - } - - assert(!new->userdata); /* user could not set userdata here (we're before load() */ - - switch(new->type) { - case HWLOC_OBJ_NUMANODE: - if (new->memory.local_memory && !old->memory.local_memory) { - /* no memory in old, use new memory */ - old->memory.local_memory = new->memory.local_memory; - if (old->memory.page_types) - free(old->memory.page_types); - old->memory.page_types_len = new->memory.page_types_len; - old->memory.page_types = new->memory.page_types; - new->memory.page_types = NULL; - new->memory.page_types_len = 0; - } - /* old->memory.total_memory will be updated by propagate_total_memory() */ - break; - case HWLOC_OBJ_CACHE: - merge_sizes(new, old, attr->cache.size); - check_sizes(new, old, attr->cache.size); - merge_sizes(new, old, attr->cache.linesize); - check_sizes(new, old, attr->cache.linesize); - break; - default: - break; - } -} - -/* Try to insert OBJ in CUR, recurse if needed. - * Returns the object if it was inserted, - * the remaining object it was merged, - * NULL if failed to insert. - */ -static struct hwloc_obj * -hwloc___insert_object_by_cpuset(struct hwloc_topology *topology, hwloc_obj_t cur, hwloc_obj_t obj, - hwloc_report_error_t report_error) -{ - hwloc_obj_t child, next_child = NULL; - /* These will always point to the pointer to their next last child. */ - hwloc_obj_t *cur_children = &cur->first_child; - hwloc_obj_t *obj_children = &obj->first_child; - /* Pointer where OBJ should be put */ - hwloc_obj_t *putp = NULL; /* OBJ position isn't found yet */ - - /* Make sure we haven't gone too deep. */ - if (!hwloc_bitmap_isincluded(obj->cpuset, cur->cpuset)) { - fprintf(stderr,"recursion has gone too deep?!\n"); - return NULL; - } - - /* Iteration with prefetching to be completely safe against CHILD removal. - * The list is already sorted by cpuset, and there's no intersection between siblings. - */ - for (child = cur->first_child, child ? next_child = child->next_sibling : NULL; - child; - child = next_child, child ? next_child = child->next_sibling : NULL) { - - int res = hwloc_obj_cmp_sets(obj, child); - - if (res == HWLOC_OBJ_EQUAL) { - if (obj->type == HWLOC_OBJ_GROUP) { - /* Groups are ignored keep_structure or always. Non-ignored Groups isn't possible. */ - assert(topology->ignored_types[HWLOC_OBJ_GROUP] != HWLOC_IGNORE_TYPE_NEVER); - /* Remove the Group now. The normal ignore code path wouldn't tell us whether the Group was removed or not. - * - * The Group doesn't contain anything to keep, just let the caller free it. - */ - return child; - - } else if (child->type == HWLOC_OBJ_GROUP) { - - /* Replace the Group with the new object contents - * and let the caller free the new object - */ - hwloc_replace_linked_object(child, obj); - return child; - - } else { - /* otherwise compare actual types to decide of the inclusion */ - res = hwloc_type_cmp(obj, child); - if (res == HWLOC_OBJ_EQUAL && obj->type == HWLOC_OBJ_MISC) { - /* Misc objects may vary by name */ - int ret = strcmp(obj->name, child->name); - if (ret < 0) - res = HWLOC_OBJ_INCLUDED; - else if (ret > 0) - res = HWLOC_OBJ_CONTAINS; - } - } - } - - switch (res) { - case HWLOC_OBJ_EQUAL: - merge_index(obj, child, os_level, signed); - if (obj->os_level != child->os_level) { - static int reported = 0; - if (!reported && !hwloc_hide_errors()) { - fprintf(stderr, "Cannot merge similar %s objects with different OS levels %u and %u\n", - hwloc_obj_type_string(obj->type), child->os_level, obj->os_level); - reported = 1; - } - return NULL; - } - /* Two objects with same type. - * Groups are handled above. - */ - if (obj->type == child->type - && (obj->type == HWLOC_OBJ_PU || obj->type == HWLOC_OBJ_NUMANODE) - && obj->os_index != child->os_index) { - static int reported = 0; - if (!reported && !hwloc_hide_errors()) { - fprintf(stderr, "Cannot merge similar %s objects with different OS indexes %u and %u\n", - hwloc_obj_type_string(obj->type), child->os_index, obj->os_index); - reported = 1; - } - return NULL; - } - merge_insert_equal(obj, child); - /* Already present, no need to insert. */ - return child; - - case HWLOC_OBJ_INCLUDED: - /* OBJ is strictly contained is some child of CUR, go deeper. */ - return hwloc___insert_object_by_cpuset(topology, child, obj, report_error); - - case HWLOC_OBJ_INTERSECTS: - if (report_error) { - char childstr[512]; - char objstr[512]; - char msg[1024]; - hwloc__report_error_format_obj(objstr, sizeof(objstr), obj); - hwloc__report_error_format_obj(childstr, sizeof(childstr), child); - snprintf(msg, sizeof(msg), "%s intersects with %s without inclusion!", objstr, childstr); - report_error(msg, __LINE__); - } - goto putback; - - case HWLOC_OBJ_DIFFERENT: - /* OBJ should be a child of CUR before CHILD, mark its position if not found yet. */ - if (!putp && (!child->cpuset || hwloc__object_cpusets_compare_first(obj, child) < 0)) - /* Don't insert yet, there could be intersect errors later */ - putp = cur_children; - /* Advance cur_children. */ - cur_children = &child->next_sibling; - break; - - case HWLOC_OBJ_CONTAINS: - /* OBJ contains CHILD, remove CHILD from CUR */ - *cur_children = child->next_sibling; - child->next_sibling = NULL; - /* Put CHILD in OBJ */ - *obj_children = child; - obj_children = &child->next_sibling; - break; - } - } - /* cur/obj_children points to last CUR/OBJ child next_sibling pointer, which must be NULL. */ - assert(!*obj_children); - assert(!*cur_children); - - /* Put OBJ where it belongs, or in last in CUR's children. */ - if (!putp) - putp = cur_children; - obj->next_sibling = *putp; - *putp = obj; - - return obj; - - putback: - /* Put-back OBJ children in CUR and return an error. */ - if (putp) - cur_children = putp; /* No need to try to insert before where OBJ was supposed to go */ - else - cur_children = &cur->first_child; /* Start from the beginning */ - /* We can insert in order, but there can be holes in the middle. */ - while ((child = obj->first_child) != NULL) { - /* Remove from OBJ */ - obj->first_child = child->next_sibling; - /* Find child position in CUR, and insert. */ - while (*cur_children && (*cur_children)->cpuset && hwloc__object_cpusets_compare_first(*cur_children, child) < 0) - cur_children = &(*cur_children)->next_sibling; - child->next_sibling = *cur_children; - *cur_children = child; - } - return NULL; -} - -/* insertion routine that lets you change the error reporting callback */ -struct hwloc_obj * -hwloc__insert_object_by_cpuset(struct hwloc_topology *topology, hwloc_obj_t obj, - hwloc_report_error_t report_error) -{ - struct hwloc_obj *result; - /* Start at the top. */ - result = hwloc___insert_object_by_cpuset(topology, topology->levels[0][0], obj, report_error); - if (result != obj) { - /* either failed to insert, or got merged, free the original object */ - hwloc_free_unlinked_object(obj); - } else { - /* Add the cpuset to the top */ - hwloc_bitmap_or(topology->levels[0][0]->complete_cpuset, topology->levels[0][0]->complete_cpuset, obj->cpuset); - if (obj->nodeset) - hwloc_bitmap_or(topology->levels[0][0]->complete_nodeset, topology->levels[0][0]->complete_nodeset, obj->nodeset); - } - return result; -} - -/* the default insertion routine warns in case of error. - * it's used by most backends */ -struct hwloc_obj * -hwloc_insert_object_by_cpuset(struct hwloc_topology *topology, hwloc_obj_t obj) -{ - return hwloc__insert_object_by_cpuset(topology, obj, hwloc_report_os_error); -} - -void -hwloc_insert_object_by_parent(struct hwloc_topology *topology, hwloc_obj_t parent, hwloc_obj_t obj) -{ - hwloc_obj_t child, next_child = obj->first_child; - hwloc_obj_t *current; - - /* Append to the end of the list. - * The caller takes care of inserting children in the right cpuset order. - * XML checks the order. - * Duplicating doesn't need to check the order since the source topology is supposed to be OK already. - * Other callers just insert random objects such as I/O or Misc. - */ - for (current = &parent->first_child; *current; current = &(*current)->next_sibling); - *current = obj; - obj->next_sibling = NULL; - obj->first_child = NULL; - - /* Use the new object to insert children */ - parent = obj; - - /* Recursively insert children below */ - while (next_child) { - child = next_child; - next_child = child->next_sibling; - hwloc_insert_object_by_parent(topology, parent, child); - } - - if (obj->type == HWLOC_OBJ_MISC) { - /* misc objects go in no level (needed here because level building doesn't see Misc objects inside I/O trees) */ - obj->depth = (unsigned) HWLOC_TYPE_DEPTH_UNKNOWN; - } -} - -/* Adds a misc object _after_ detection, and thus has to reconnect all the pointers */ -hwloc_obj_t -hwloc_topology_insert_misc_object_by_cpuset(struct hwloc_topology *topology, hwloc_const_bitmap_t cpuset, const char *name) -{ - hwloc_obj_t obj, child; - - if (!topology->is_loaded) { - errno = EINVAL; - return NULL; - } - - if (hwloc_bitmap_iszero(cpuset)) - return NULL; - if (!hwloc_bitmap_isincluded(cpuset, hwloc_topology_get_topology_cpuset(topology))) - return NULL; - - obj = hwloc_alloc_setup_object(HWLOC_OBJ_MISC, -1); - if (name) - obj->name = strdup(name); - - /* misc objects go in no level */ - obj->depth = (unsigned) HWLOC_TYPE_DEPTH_UNKNOWN; - - obj->cpuset = hwloc_bitmap_dup(cpuset); - /* initialize default cpusets, we'll adjust them later */ - obj->complete_cpuset = hwloc_bitmap_dup(cpuset); - obj->allowed_cpuset = hwloc_bitmap_dup(cpuset); - obj->online_cpuset = hwloc_bitmap_dup(cpuset); - - obj = hwloc__insert_object_by_cpuset(topology, obj, NULL /* do not show errors on stdout */); - if (!obj) - return NULL; - - hwloc_connect_children(topology->levels[0][0]); - - if ((child = obj->first_child) != NULL && child->cpuset) { - /* keep the main cpuset untouched, but update other cpusets and nodesets from children */ - obj->nodeset = hwloc_bitmap_alloc(); - obj->complete_nodeset = hwloc_bitmap_alloc(); - obj->allowed_nodeset = hwloc_bitmap_alloc(); - while (child) { - if (child->complete_cpuset) - hwloc_bitmap_or(obj->complete_cpuset, obj->complete_cpuset, child->complete_cpuset); - if (child->allowed_cpuset) - hwloc_bitmap_or(obj->allowed_cpuset, obj->allowed_cpuset, child->allowed_cpuset); - if (child->online_cpuset) - hwloc_bitmap_or(obj->online_cpuset, obj->online_cpuset, child->online_cpuset); - if (child->nodeset) - hwloc_bitmap_or(obj->nodeset, obj->nodeset, child->nodeset); - if (child->complete_nodeset) - hwloc_bitmap_or(obj->complete_nodeset, obj->complete_nodeset, child->complete_nodeset); - if (child->allowed_nodeset) - hwloc_bitmap_or(obj->allowed_nodeset, obj->allowed_nodeset, child->allowed_nodeset); - child = child->next_sibling; - } - } else { - /* copy the parent nodesets */ - obj->nodeset = hwloc_bitmap_dup(obj->parent->nodeset); - obj->complete_nodeset = hwloc_bitmap_dup(obj->parent->complete_nodeset); - obj->allowed_nodeset = hwloc_bitmap_dup(obj->parent->allowed_nodeset); - } - - return obj; -} - -hwloc_obj_t -hwloc_topology_insert_misc_object_by_parent(struct hwloc_topology *topology, hwloc_obj_t parent, const char *name) -{ - hwloc_obj_t obj = hwloc_alloc_setup_object(HWLOC_OBJ_MISC, -1); - if (name) - obj->name = strdup(name); - - if (!topology->is_loaded) { - hwloc_free_unlinked_object(obj); - errno = EINVAL; - return NULL; - } - - hwloc_insert_object_by_parent(topology, parent, obj); - - hwloc_connect_children(topology->levels[0][0]); - /* no need to hwloc_connect_levels() since misc object are not in levels */ - - return obj; -} - -/* Append I/O devices below this object to their list */ -static void -append_iodevs(hwloc_topology_t topology, hwloc_obj_t obj) -{ - hwloc_obj_t child, *temp; - - /* make sure we don't have remaining stale pointers from a previous load */ - obj->next_cousin = NULL; - obj->prev_cousin = NULL; - - if (obj->type == HWLOC_OBJ_BRIDGE) { - obj->depth = HWLOC_TYPE_DEPTH_BRIDGE; - /* Insert in the main bridge list */ - if (topology->first_bridge) { - obj->prev_cousin = topology->last_bridge; - obj->prev_cousin->next_cousin = obj; - topology->last_bridge = obj; - } else { - topology->first_bridge = topology->last_bridge = obj; - } - } else if (obj->type == HWLOC_OBJ_PCI_DEVICE) { - obj->depth = HWLOC_TYPE_DEPTH_PCI_DEVICE; - /* Insert in the main pcidev list */ - if (topology->first_pcidev) { - obj->prev_cousin = topology->last_pcidev; - obj->prev_cousin->next_cousin = obj; - topology->last_pcidev = obj; - } else { - topology->first_pcidev = topology->last_pcidev = obj; - } - } else if (obj->type == HWLOC_OBJ_OS_DEVICE) { - obj->depth = HWLOC_TYPE_DEPTH_OS_DEVICE; - /* Insert in the main osdev list */ - if (topology->first_osdev) { - obj->prev_cousin = topology->last_osdev; - obj->prev_cousin->next_cousin = obj; - topology->last_osdev = obj; - } else { - topology->first_osdev = topology->last_osdev = obj; - } - } - - for_each_child_safe(child, obj, temp) - append_iodevs(topology, child); -} - -static int hwloc_memory_page_type_compare(const void *_a, const void *_b) -{ - const struct hwloc_obj_memory_page_type_s *a = _a; - const struct hwloc_obj_memory_page_type_s *b = _b; - /* consider 0 as larger so that 0-size page_type go to the end */ - if (!b->size) - return -1; - /* don't cast a-b in int since those are ullongs */ - if (b->size == a->size) - return 0; - return a->size < b->size ? -1 : 1; -} - -/* Propagate memory counts */ -static void -propagate_total_memory(hwloc_obj_t obj) -{ - hwloc_obj_t *temp, child; - unsigned i; - - /* reset total before counting local and children memory */ - obj->memory.total_memory = 0; - - /* Propagate memory up */ - for_each_child_safe(child, obj, temp) { - propagate_total_memory(child); - obj->memory.total_memory += child->memory.total_memory; - } - obj->memory.total_memory += obj->memory.local_memory; - - /* By the way, sort the page_type array. - * Cannot do it on insert since some backends (e.g. XML) add page_types after inserting the object. - */ - qsort(obj->memory.page_types, obj->memory.page_types_len, sizeof(*obj->memory.page_types), hwloc_memory_page_type_compare); - /* Ignore 0-size page_types, they are at the end */ - for(i=obj->memory.page_types_len; i>=1; i--) - if (obj->memory.page_types[i-1].size) - break; - obj->memory.page_types_len = i; -} - -/* Collect the cpuset of all the PU objects. */ -static void -collect_proc_cpuset(hwloc_obj_t obj, hwloc_obj_t sys) -{ - hwloc_obj_t child, *temp; - - if (sys) { - /* We are already given a pointer to a system object */ - if (obj->type == HWLOC_OBJ_PU) - hwloc_bitmap_or(sys->cpuset, sys->cpuset, obj->cpuset); - } else { - if (obj->cpuset) { - /* This object is the root of a machine */ - sys = obj; - /* Assume no PU for now */ - hwloc_bitmap_zero(obj->cpuset); - } - } - - for_each_child_safe(child, obj, temp) - collect_proc_cpuset(child, sys); -} - -/* While traversing down and up, propagate the offline/disallowed cpus by - * and'ing them to and from the first object that has a cpuset */ -static void -propagate_unused_cpuset(hwloc_obj_t obj, hwloc_obj_t sys) -{ - hwloc_obj_t child, *temp; - - if (obj->cpuset) { - if (sys) { - /* We are already given a pointer to an system object, update it and update ourselves */ - hwloc_bitmap_t mask = hwloc_bitmap_alloc(); - - /* Apply the topology cpuset */ - hwloc_bitmap_and(obj->cpuset, obj->cpuset, sys->cpuset); - - /* Update complete cpuset down */ - if (obj->complete_cpuset) { - hwloc_bitmap_and(obj->complete_cpuset, obj->complete_cpuset, sys->complete_cpuset); - } else { - obj->complete_cpuset = hwloc_bitmap_dup(sys->complete_cpuset); - hwloc_bitmap_and(obj->complete_cpuset, obj->complete_cpuset, obj->cpuset); - } - - /* Update online cpusets */ - if (obj->online_cpuset) { - /* Update ours */ - hwloc_bitmap_and(obj->online_cpuset, obj->online_cpuset, sys->online_cpuset); - - /* Update the given cpuset, but only what we know */ - hwloc_bitmap_copy(mask, obj->cpuset); - hwloc_bitmap_not(mask, mask); - hwloc_bitmap_or(mask, mask, obj->online_cpuset); - hwloc_bitmap_and(sys->online_cpuset, sys->online_cpuset, mask); - } else { - /* Just take it as such */ - obj->online_cpuset = hwloc_bitmap_dup(sys->online_cpuset); - hwloc_bitmap_and(obj->online_cpuset, obj->online_cpuset, obj->cpuset); - } - - /* Update allowed cpusets */ - if (obj->allowed_cpuset) { - /* Update ours */ - hwloc_bitmap_and(obj->allowed_cpuset, obj->allowed_cpuset, sys->allowed_cpuset); - - /* Update the given cpuset, but only what we know */ - hwloc_bitmap_copy(mask, obj->cpuset); - hwloc_bitmap_not(mask, mask); - hwloc_bitmap_or(mask, mask, obj->allowed_cpuset); - hwloc_bitmap_and(sys->allowed_cpuset, sys->allowed_cpuset, mask); - } else { - /* Just take it as such */ - obj->allowed_cpuset = hwloc_bitmap_dup(sys->allowed_cpuset); - hwloc_bitmap_and(obj->allowed_cpuset, obj->allowed_cpuset, obj->cpuset); - } - - hwloc_bitmap_free(mask); - } else { - /* This object is the root of a machine */ - sys = obj; - /* Apply complete cpuset to cpuset, online_cpuset and allowed_cpuset, it - * will automatically be applied below */ - if (obj->complete_cpuset) - hwloc_bitmap_and(obj->cpuset, obj->cpuset, obj->complete_cpuset); - else - obj->complete_cpuset = hwloc_bitmap_dup(obj->cpuset); - if (obj->online_cpuset) - hwloc_bitmap_and(obj->online_cpuset, obj->online_cpuset, obj->complete_cpuset); - else - obj->online_cpuset = hwloc_bitmap_dup(obj->complete_cpuset); - if (obj->allowed_cpuset) - hwloc_bitmap_and(obj->allowed_cpuset, obj->allowed_cpuset, obj->complete_cpuset); - else - obj->allowed_cpuset = hwloc_bitmap_dup(obj->complete_cpuset); - } - } - - for_each_child_safe(child, obj, temp) - propagate_unused_cpuset(child, sys); -} - -/* Force full nodeset for non-NUMA machines */ -static void -add_default_object_sets(hwloc_obj_t obj, int parent_has_sets) -{ - hwloc_obj_t child, *temp; - - /* I/O devices (and their children) have no sets */ - if (hwloc_obj_type_is_io(obj->type)) - return; - - if (parent_has_sets && obj->type != HWLOC_OBJ_MISC) { - /* non-MISC object must have cpuset if parent has one. */ - assert(obj->cpuset); - } - - /* other sets must be consistent with main cpuset: - * check cpusets and add nodesets if needed. - * - * MISC may have no sets at all (if added by parent), or usual ones (if added by cpuset), - * but that's not easy to detect, so just make sure sets are consistent as usual. - */ - if (obj->cpuset) { - assert(obj->online_cpuset); - assert(obj->complete_cpuset); - assert(obj->allowed_cpuset); - if (!obj->nodeset) - obj->nodeset = hwloc_bitmap_alloc_full(); - if (!obj->complete_nodeset) - obj->complete_nodeset = hwloc_bitmap_alloc_full(); - if (!obj->allowed_nodeset) - obj->allowed_nodeset = hwloc_bitmap_alloc_full(); - } else { - assert(!obj->online_cpuset); - assert(!obj->complete_cpuset); - assert(!obj->allowed_cpuset); - assert(!obj->nodeset); - assert(!obj->complete_nodeset); - assert(!obj->allowed_nodeset); - } - - for_each_child_safe(child, obj, temp) - add_default_object_sets(child, obj->cpuset != NULL); -} - -/* Setup object cpusets/nodesets by OR'ing its children. */ -int -hwloc_fill_object_sets(hwloc_obj_t obj) -{ - hwloc_obj_t child; - assert(obj->cpuset != NULL); - child = obj->first_child; - while (child) { - assert(child->cpuset != NULL); - if (child->complete_cpuset) { - if (!obj->complete_cpuset) - obj->complete_cpuset = hwloc_bitmap_alloc(); - hwloc_bitmap_or(obj->complete_cpuset, obj->complete_cpuset, child->complete_cpuset); - } - if (child->online_cpuset) { - if (!obj->online_cpuset) - obj->online_cpuset = hwloc_bitmap_alloc(); - hwloc_bitmap_or(obj->online_cpuset, obj->online_cpuset, child->online_cpuset); - } - if (child->allowed_cpuset) { - if (!obj->allowed_cpuset) - obj->allowed_cpuset = hwloc_bitmap_alloc(); - hwloc_bitmap_or(obj->allowed_cpuset, obj->allowed_cpuset, child->allowed_cpuset); - } - if (child->nodeset) { - if (!obj->nodeset) - obj->nodeset = hwloc_bitmap_alloc(); - hwloc_bitmap_or(obj->nodeset, obj->nodeset, child->nodeset); - } - if (child->complete_nodeset) { - if (!obj->complete_nodeset) - obj->complete_nodeset = hwloc_bitmap_alloc(); - hwloc_bitmap_or(obj->complete_nodeset, obj->complete_nodeset, child->complete_nodeset); - } - if (child->allowed_nodeset) { - if (!obj->allowed_nodeset) - obj->allowed_nodeset = hwloc_bitmap_alloc(); - hwloc_bitmap_or(obj->allowed_nodeset, obj->allowed_nodeset, child->allowed_nodeset); - } - child = child->next_sibling; - } - return 0; -} - -/* Propagate nodesets up and down */ -static void -propagate_nodeset(hwloc_obj_t obj, hwloc_obj_t sys) -{ - hwloc_obj_t child, *temp; - hwloc_bitmap_t parent_nodeset = NULL; - int parent_weight = 0; - - if (!sys && obj->nodeset) { - sys = obj; - if (!obj->complete_nodeset) - obj->complete_nodeset = hwloc_bitmap_dup(obj->nodeset); - if (!obj->allowed_nodeset) - obj->allowed_nodeset = hwloc_bitmap_dup(obj->complete_nodeset); - } - - if (sys) { - if (obj->nodeset) { - /* Some existing nodeset coming from above, to possibly propagate down */ - parent_nodeset = obj->nodeset; - parent_weight = hwloc_bitmap_weight(parent_nodeset); - } else - obj->nodeset = hwloc_bitmap_alloc(); - } - - for_each_child_safe(child, obj, temp) { - /* don't propagate nodesets in I/O objects, keep them NULL */ - if (hwloc_obj_type_is_io(child->type)) - return; - /* don't propagate nodesets in Misc inserted by parent (no nodeset if no cpuset) */ - if (child->type == HWLOC_OBJ_MISC && !child->cpuset) - return; - - /* Propagate singleton nodesets down */ - if (parent_weight == 1) { - if (!child->nodeset) - child->nodeset = hwloc_bitmap_dup(obj->nodeset); - else if (!hwloc_bitmap_isequal(child->nodeset, parent_nodeset)) { - hwloc_debug_bitmap("Oops, parent nodeset %s", parent_nodeset); - hwloc_debug_bitmap(" is different from child nodeset %s, ignoring the child one\n", child->nodeset); - hwloc_bitmap_copy(child->nodeset, parent_nodeset); - } - } - - /* Recurse */ - propagate_nodeset(child, sys); - - /* Propagate children nodesets up */ - if (sys && child->nodeset) - hwloc_bitmap_or(obj->nodeset, obj->nodeset, child->nodeset); - } -} - -/* Propagate allowed and complete nodesets */ -static void -propagate_nodesets(hwloc_obj_t obj) -{ - hwloc_bitmap_t mask = hwloc_bitmap_alloc(); - hwloc_obj_t child, *temp; - - for_each_child_safe(child, obj, temp) { - /* don't propagate nodesets in I/O objects, keep them NULL */ - if (hwloc_obj_type_is_io(child->type)) - continue; - - if (obj->nodeset) { - /* Update complete nodesets down */ - if (child->complete_nodeset) { - hwloc_bitmap_and(child->complete_nodeset, child->complete_nodeset, obj->complete_nodeset); - } else if (child->nodeset) { - child->complete_nodeset = hwloc_bitmap_dup(obj->complete_nodeset); - hwloc_bitmap_and(child->complete_nodeset, child->complete_nodeset, child->nodeset); - } /* else the child doesn't have nodeset information, we can not provide a complete nodeset */ - - /* Update allowed nodesets down */ - if (child->allowed_nodeset) { - hwloc_bitmap_and(child->allowed_nodeset, child->allowed_nodeset, obj->allowed_nodeset); - } else if (child->nodeset) { - child->allowed_nodeset = hwloc_bitmap_dup(obj->allowed_nodeset); - hwloc_bitmap_and(child->allowed_nodeset, child->allowed_nodeset, child->nodeset); - } - } - - propagate_nodesets(child); - - if (obj->nodeset) { - /* Update allowed nodesets up */ - if (child->nodeset && child->allowed_nodeset) { - hwloc_bitmap_copy(mask, child->nodeset); - hwloc_bitmap_andnot(mask, mask, child->allowed_nodeset); - hwloc_bitmap_andnot(obj->allowed_nodeset, obj->allowed_nodeset, mask); - } - } - } - hwloc_bitmap_free(mask); - - if (obj->nodeset) { - /* Apply complete nodeset to nodeset and allowed_nodeset */ - if (obj->complete_nodeset) - hwloc_bitmap_and(obj->nodeset, obj->nodeset, obj->complete_nodeset); - else - obj->complete_nodeset = hwloc_bitmap_dup(obj->nodeset); - if (obj->allowed_nodeset) - hwloc_bitmap_and(obj->allowed_nodeset, obj->allowed_nodeset, obj->complete_nodeset); - else - obj->allowed_nodeset = hwloc_bitmap_dup(obj->complete_nodeset); - } -} - -static void -remove_unused_sets(hwloc_obj_t obj) -{ - hwloc_obj_t child, *temp; - - if (obj->cpuset) { - hwloc_bitmap_and(obj->cpuset, obj->cpuset, obj->online_cpuset); - hwloc_bitmap_and(obj->cpuset, obj->cpuset, obj->allowed_cpuset); - } - if (obj->nodeset) { - hwloc_bitmap_and(obj->nodeset, obj->nodeset, obj->allowed_nodeset); - } - if (obj->type == HWLOC_OBJ_NUMANODE && obj->os_index != (unsigned) -1 && - !hwloc_bitmap_isset(obj->allowed_nodeset, obj->os_index)) { - unsigned i; - hwloc_debug("Dropping memory from disallowed node %u\n", obj->os_index); - obj->memory.local_memory = 0; - obj->memory.total_memory = 0; - for(i=0; imemory.page_types_len; i++) - obj->memory.page_types[i].count = 0; - } - - for_each_child_safe(child, obj, temp) - remove_unused_sets(child); -} - -static void -reorder_children(hwloc_obj_t parent) -{ - /* move the children list on the side */ - hwloc_obj_t *prev, child, children = parent->first_child; - parent->first_child = NULL; - while (children) { - /* dequeue child */ - child = children; - children = child->next_sibling; - /* find where to enqueue it */ - prev = &parent->first_child; - while (*prev - && (!child->cpuset || !(*prev)->cpuset - || hwloc__object_cpusets_compare_first(child, *prev) > 0)) - prev = &((*prev)->next_sibling); - /* enqueue */ - child->next_sibling = *prev; - *prev = child; - } -} - -/* Remove all ignored objects. */ -static int -remove_ignored(hwloc_topology_t topology, hwloc_obj_t *pparent) -{ - hwloc_obj_t parent = *pparent, child, *pchild; - int dropped_children = 0; - int dropped = 0; - - for_each_child_safe(child, parent, pchild) - dropped_children += remove_ignored(topology, pchild); - - if ((parent != topology->levels[0][0] && - topology->ignored_types[parent->type] == HWLOC_IGNORE_TYPE_ALWAYS) - || (parent->type == HWLOC_OBJ_CACHE && parent->attr->cache.type == HWLOC_OBJ_CACHE_INSTRUCTION - && !(topology->flags & HWLOC_TOPOLOGY_FLAG_ICACHES))) { - hwloc_debug("%s", "\nDropping ignored object "); - hwloc_debug_print_object(0, parent); - unlink_and_free_single_object(pparent); - dropped = 1; - - } else if (dropped_children) { - /* we keep this object but its children changed, reorder them by complete_cpuset */ - reorder_children(parent); - } - - return dropped; -} - -/* Remove all children whose cpuset is empty, except NUMA nodes - * since we want to keep memory information, and except PCI bridges and devices. - */ -static void -remove_empty(hwloc_topology_t topology, hwloc_obj_t *pobj) -{ - hwloc_obj_t obj = *pobj, child, *pchild; - - for_each_child_safe(child, obj, pchild) - remove_empty(topology, pchild); - - if (obj->type != HWLOC_OBJ_NUMANODE - && !obj->first_child /* only remove if all children were removed above, so that we don't remove parents of NUMAnode */ - && !hwloc_obj_type_is_io(obj->type) && obj->type != HWLOC_OBJ_MISC - && obj->cpuset /* don't remove if no cpuset at all, there's likely a good reason why it's different from having an empty cpuset */ - && hwloc_bitmap_iszero(obj->cpuset)) { - /* Remove empty children */ - hwloc_debug("%s", "\nRemoving empty object "); - hwloc_debug_print_object(0, obj); - unlink_and_free_single_object(pobj); - } -} - -/* adjust object cpusets according the given droppedcpuset, - * drop object whose cpuset becomes empty, - * and mark dropped nodes in droppednodeset - */ -static void -restrict_object(hwloc_topology_t topology, unsigned long flags, hwloc_obj_t *pobj, hwloc_const_cpuset_t droppedcpuset, hwloc_nodeset_t droppednodeset, int droppingparent) -{ - hwloc_obj_t obj = *pobj, child, *pchild; - int dropping; - int modified = obj->complete_cpuset && hwloc_bitmap_intersects(obj->complete_cpuset, droppedcpuset); - - hwloc_clear_object_distances(obj); - - if (obj->cpuset) - hwloc_bitmap_andnot(obj->cpuset, obj->cpuset, droppedcpuset); - if (obj->complete_cpuset) - hwloc_bitmap_andnot(obj->complete_cpuset, obj->complete_cpuset, droppedcpuset); - if (obj->online_cpuset) - hwloc_bitmap_andnot(obj->online_cpuset, obj->online_cpuset, droppedcpuset); - if (obj->allowed_cpuset) - hwloc_bitmap_andnot(obj->allowed_cpuset, obj->allowed_cpuset, droppedcpuset); - - if (obj->type == HWLOC_OBJ_MISC) { - dropping = droppingparent && !(flags & HWLOC_RESTRICT_FLAG_ADAPT_MISC); - } else if (hwloc_obj_type_is_io(obj->type)) { - dropping = droppingparent && !(flags & HWLOC_RESTRICT_FLAG_ADAPT_IO); - } else { - dropping = droppingparent || (obj->cpuset && hwloc_bitmap_iszero(obj->cpuset)); - } - - if (modified) - for_each_child_safe(child, obj, pchild) - restrict_object(topology, flags, pchild, droppedcpuset, droppednodeset, dropping); - - if (dropping) { - hwloc_debug("%s", "\nRemoving object during restrict"); - hwloc_debug_print_objects(0, obj); - if (obj->type == HWLOC_OBJ_NUMANODE) - hwloc_bitmap_set(droppednodeset, obj->os_index); - /* remove the object from the tree (no need to remove from levels, they will be entirely rebuilt by the caller) */ - unlink_and_free_single_object(pobj); - /* do not remove children. if they were to be removed, they would have been already */ - } -} - -/* adjust object nodesets accordingly the given droppednodeset - */ -static void -restrict_object_nodeset(hwloc_topology_t topology, hwloc_obj_t *pobj, hwloc_nodeset_t droppednodeset) -{ - hwloc_obj_t obj = *pobj, child, *pchild; - - /* if this object isn't modified, don't bother looking at children */ - if (obj->complete_nodeset && !hwloc_bitmap_intersects(obj->complete_nodeset, droppednodeset)) - return; - - if (obj->nodeset) - hwloc_bitmap_andnot(obj->nodeset, obj->nodeset, droppednodeset); - if (obj->complete_nodeset) - hwloc_bitmap_andnot(obj->complete_nodeset, obj->complete_nodeset, droppednodeset); - if (obj->allowed_nodeset) - hwloc_bitmap_andnot(obj->allowed_nodeset, obj->allowed_nodeset, droppednodeset); - - for_each_child_safe(child, obj, pchild) - restrict_object_nodeset(topology, pchild, droppednodeset); -} - -/* we don't want to merge groups that were inserted explicitly with the custom interface */ -static int -can_merge_group(hwloc_topology_t topology, hwloc_obj_t obj) -{ - const char *value; - /* custom-inserted groups are in custom topologies and have no cpusets, - * don't bother calling hwloc_obj_get_info_by_name() and strcmp() uselessly. - */ - if (!topology->backends->is_custom || obj->cpuset) - return 1; - value = hwloc_obj_get_info_by_name(obj, "Backend"); - return (!value) || strcmp(value, "Custom"); -} - -/* - * Merge with the only child if either the parent or the child has a type to be - * ignored while keeping structure - */ -static int -merge_useless_child(hwloc_topology_t topology, hwloc_obj_t *pparent) -{ - hwloc_obj_t parent = *pparent, child, *pchild, ios; - int replacechild = 0, replaceparent = 0, droppedchildren = 0; - - if (!parent->first_child) - /* There are no child, nothing to merge. */ - return 0; - - for_each_child_safe(child, parent, pchild) - droppedchildren += merge_useless_child(topology, pchild); - - if (droppedchildren) - reorder_children(parent); - - child = parent->first_child; - /* we don't merge if there are multiple "important" children. - * non-important ones are at the end of the list. - * look at the second child to find out. - */ - if (child->next_sibling - /* I/O objects may be ignored when trying to merge */ - && !hwloc_obj_type_is_io(child->next_sibling->type) - /* Misc objects without cpuset may be ignored as well */ - && !(child->next_sibling->type == HWLOC_OBJ_MISC && !child->next_sibling->cpuset)) - /* There are several children that prevent from merging */ - return 0; - - /* There is one important child, and some children that may be ignored - * during merging because they can be attached to anything with the same locality. - * Move them to the side during merging, and append them back later. - * This is easy because children with no cpuset are always last in the list. - */ - ios = child->next_sibling; - child->next_sibling = NULL; - - /* Check whether parent and/or child can be replaced */ - if (topology->ignored_types[parent->type] == HWLOC_IGNORE_TYPE_KEEP_STRUCTURE) { - if (parent->type != HWLOC_OBJ_GROUP || can_merge_group(topology, parent)) - /* Parent can be ignored in favor of the child. */ - replaceparent = 1; - } - if (topology->ignored_types[child->type] == HWLOC_IGNORE_TYPE_KEEP_STRUCTURE) { - if (child->type != HWLOC_OBJ_GROUP || can_merge_group(topology, child)) - /* Child can be ignored in favor of the parent. */ - replacechild = 1; - } - - /* Decide which one to actually replace */ - if (replaceparent && replacechild) { - /* If both may be replaced, look at obj_type_priority */ - if (obj_type_priority[parent->type] > obj_type_priority[child->type]) - replaceparent = 0; - else - replacechild = 0; - } - - if (replaceparent) { - /* Replace parent with child */ - hwloc_debug("%s", "\nIgnoring parent "); - hwloc_debug_print_object(0, parent); - if (parent == topology->levels[0][0]) { - child->parent = NULL; - child->depth = 0; - } - unlink_and_free_single_object(pparent); - - } else if (replacechild) { - /* Replace child with parent */ - hwloc_debug("%s", "\nIgnoring child "); - hwloc_debug_print_object(0, child); - unlink_and_free_single_object(&parent->first_child); - } - - if (ios) { - /* append the remaining list of children to the remaining object */ - pchild = &((*pparent)->first_child); - while (*pchild) - pchild = &((*pchild)->next_sibling); - *pchild = ios; - } - - return replaceparent ? 1 : 0; -} - -static void -hwloc_drop_all_io(hwloc_topology_t topology, hwloc_obj_t root) -{ - hwloc_obj_t child, *pchild; - for_each_child_safe(child, root, pchild) { - if (hwloc_obj_type_is_io(child->type)) - unlink_and_free_object_and_children(pchild); - else - hwloc_drop_all_io(topology, child); - } -} - -/* - * If IO_DEVICES and WHOLE_IO are not set, we drop everything. - * If WHOLE_IO is not set, we drop non-interesting devices, - * and bridges that have no children. - * If IO_BRIDGES is also not set, we also drop all bridges - * except the hostbridges. - */ -static void -hwloc_drop_useless_io(hwloc_topology_t topology, hwloc_obj_t root) -{ - hwloc_obj_t child, *pchild; - - if (!(topology->flags & (HWLOC_TOPOLOGY_FLAG_IO_DEVICES|HWLOC_TOPOLOGY_FLAG_WHOLE_IO))) { - /* drop all I/O children */ - hwloc_drop_all_io(topology, root); - return; - } - - if (!(topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_IO)) { - /* drop non-interesting devices */ - for_each_child_safe(child, root, pchild) { - if (child->type == HWLOC_OBJ_PCI_DEVICE) { - unsigned classid = child->attr->pcidev.class_id; - unsigned baseclass = classid >> 8; - if (baseclass != 0x03 /* PCI_BASE_CLASS_DISPLAY */ - && baseclass != 0x02 /* PCI_BASE_CLASS_NETWORK */ - && baseclass != 0x01 /* PCI_BASE_CLASS_STORAGE */ - && baseclass != 0x0b /* PCI_BASE_CLASS_PROCESSOR */ - && classid != 0x0c04 /* PCI_CLASS_SERIAL_FIBER */ - && classid != 0x0c06 /* PCI_CLASS_SERIAL_INFINIBAND */ - && baseclass != 0x12 /* Processing Accelerators */) - unlink_and_free_object_and_children(pchild); - } - } - } - - /* look at remaining children, process recursively, and remove useless bridges */ - for_each_child_safe(child, root, pchild) { - hwloc_drop_useless_io(topology, child); - - if (child->type == HWLOC_OBJ_BRIDGE) { - if (!child->first_child) { - /* bridges with no children are removed if WHOLE_IO isn't given */ - if (!(topology->flags & (HWLOC_TOPOLOGY_FLAG_WHOLE_IO))) { - unlink_and_free_single_object(pchild); - } - - } else if (child->attr->bridge.upstream_type != HWLOC_OBJ_BRIDGE_HOST) { - /* only hostbridges are kept if WHOLE_IO or IO_BRIDGE are not given */ - if (!(topology->flags & (HWLOC_TOPOLOGY_FLAG_IO_BRIDGES|HWLOC_TOPOLOGY_FLAG_WHOLE_IO))) { - unlink_and_free_single_object(pchild); - } - } - } - } -} - -static void -hwloc_propagate_bridge_depth(hwloc_topology_t topology, hwloc_obj_t root, unsigned depth) -{ - hwloc_obj_t child = root->first_child; - while (child) { - if (child->type == HWLOC_OBJ_BRIDGE) { - child->attr->bridge.depth = depth; - hwloc_propagate_bridge_depth(topology, child, depth+1); - } else if (!hwloc_obj_type_is_io(child->type)) { - hwloc_propagate_bridge_depth(topology, child, 0); - } - child = child->next_sibling; - } -} - -static void -hwloc_propagate_symmetric_subtree(hwloc_topology_t topology, hwloc_obj_t root) -{ - hwloc_obj_t child, *array; - - /* assume we're not symmetric by default */ - root->symmetric_subtree = 0; - - /* if no child, we are symmetric */ - if (!root->arity) { - root->symmetric_subtree = 1; - return; - } - - /* look at children, and return if they are not symmetric */ - child = NULL; - while ((child = hwloc_get_next_child(topology, root, child)) != NULL) - hwloc_propagate_symmetric_subtree(topology, child); - while ((child = hwloc_get_next_child(topology, root, child)) != NULL) - if (!child->symmetric_subtree) - return; - - /* now check that children subtrees are identical. - * just walk down the first child in each tree and compare their depth and arities - */ - array = malloc(root->arity * sizeof(*array)); - memcpy(array, root->children, root->arity * sizeof(*array)); - while (1) { - unsigned i; - /* check current level arities and depth */ - for(i=1; iarity; i++) - if (array[i]->depth != array[0]->depth - || array[i]->arity != array[0]->arity) { - free(array); - return; - } - if (!array[0]->arity) - /* no more children level, we're ok */ - break; - /* look at first child of each element now */ - for(i=0; iarity; i++) - array[i] = array[i]->first_child; - } - free(array); - - /* everything went fine, we're symmetric */ - root->symmetric_subtree = 1; -} - -/* - * Initialize handy pointers in the whole topology. - * The topology only had first_child and next_sibling pointers. - * When this funtions return, all parent/children pointers are initialized. - * The remaining fields (levels, cousins, logical_index, depth, ...) will - * be setup later in hwloc_connect_levels(). - * - * Can be called several times, so may have to update the array. - */ -void -hwloc_connect_children(hwloc_obj_t parent) -{ - unsigned n, oldn = parent->arity; - hwloc_obj_t child, prev_child = NULL; - int ok = 1; - - for (n = 0, child = parent->first_child; - child; - n++, prev_child = child, child = child->next_sibling) { - child->parent = parent; - child->sibling_rank = n; - child->prev_sibling = prev_child; - /* already OK in the array? */ - if (n >= oldn || parent->children[n] != child) - ok = 0; - /* recurse */ - hwloc_connect_children(child); - } - parent->last_child = prev_child; - parent->arity = n; - if (!n) { - /* no need for an array anymore */ - free(parent->children); - parent->children = NULL; - return; - } - if (ok) - /* array is already OK (even if too large) */ - return; - - /* alloc a larger array if needed */ - if (oldn < n) { - free(parent->children); - parent->children = malloc(n * sizeof(*parent->children)); - } - /* refill */ - for (n = 0, child = parent->first_child; - child; - n++, child = child->next_sibling) { - parent->children[n] = child; - } -} - -/* - * Check whether there is an object below ROOT that has the same type as OBJ. - * Only used for building levels. - * Stop at I/O or Misc since these don't go into levels, and we never have - * normal objects under them. - */ -static int -find_same_type(hwloc_obj_t root, hwloc_obj_t obj) -{ - hwloc_obj_t child; - - if (hwloc_type_cmp(root, obj) == HWLOC_OBJ_EQUAL) - return 1; - - for (child = root->first_child; child; child = child->next_sibling) - if (!hwloc_obj_type_is_io(child->type) - && child->type != HWLOC_OBJ_MISC - && find_same_type(child, obj)) - return 1; - - return 0; -} - -/* traverse the array of current object and compare them with top_obj. - * if equal, take the object and put its children into the remaining objs. - * if not equal, put the object into the remaining objs. - */ -static int -hwloc_level_take_objects(hwloc_obj_t top_obj, - hwloc_obj_t *current_objs, unsigned n_current_objs, - hwloc_obj_t *taken_objs, unsigned n_taken_objs __hwloc_attribute_unused, - hwloc_obj_t *remaining_objs, unsigned n_remaining_objs __hwloc_attribute_unused) -{ - unsigned taken_i = 0; - unsigned new_i = 0; - unsigned i, j; - - for (i = 0; i < n_current_objs; i++) - if (hwloc_type_cmp(top_obj, current_objs[i]) == HWLOC_OBJ_EQUAL) { - /* Take it, add children. */ - taken_objs[taken_i++] = current_objs[i]; - for (j = 0; j < current_objs[i]->arity; j++) - remaining_objs[new_i++] = current_objs[i]->children[j]; - } else { - /* Leave it. */ - remaining_objs[new_i++] = current_objs[i]; - } - -#ifdef HWLOC_DEBUG - /* Make sure we didn't mess up. */ - assert(taken_i == n_taken_objs); - assert(new_i == n_current_objs - n_taken_objs + n_remaining_objs); -#endif - - return new_i; -} - -/* Given an input object, copy it or its interesting children into the output array. - * If new_obj is NULL, we're just counting interesting ohjects. - */ -static unsigned -hwloc_level_filter_object(hwloc_topology_t topology, - hwloc_obj_t *new_obj, hwloc_obj_t old) -{ - unsigned i, total; - if (hwloc_obj_type_is_io(old->type)) { - if (new_obj) - append_iodevs(topology, old); - return 0; - } - if (old->type != HWLOC_OBJ_MISC) { - if (new_obj) - *new_obj = old; - return 1; - } - for(i=0, total=0; iarity; i++) { - int nb = hwloc_level_filter_object(topology, new_obj, old->children[i]); - if (new_obj) { - new_obj += nb; - } - total += nb; - } - return total; -} - -/* Replace an input array of objects with an input array containing - * only interesting objects for levels. - * Misc objects are removed, their interesting children are added. - * I/O devices are removed and queue to their own lists. - */ -static int -hwloc_level_filter_objects(hwloc_topology_t topology, - hwloc_obj_t **objs, unsigned *n_objs) -{ - hwloc_obj_t *old = *objs, *new; - unsigned nold = *n_objs, nnew, i; - - /* anything to filter? */ - for(i=0; itype) - || old[i]->type == HWLOC_OBJ_MISC) - break; - if (i==nold) - return 0; - - /* count interesting objects and allocate the new array */ - for(i=0, nnew=0; inext_cousin; - } - nb = i; - - if (nb) { - /* allocate and fill level */ - *levelp = malloc(nb * sizeof(struct hwloc_obj *)); - obj = first; - i = 0; - while (obj) { - obj->logical_index = i; - (*levelp)[i] = obj; - i++; - obj = obj->next_cousin; - } - } - - return nb; -} - -/* - * Do the remaining work that hwloc_connect_children() did not do earlier. - */ -int -hwloc_connect_levels(hwloc_topology_t topology) -{ - unsigned l, i=0; - hwloc_obj_t *objs, *taken_objs, *new_objs, top_obj; - unsigned n_objs, n_taken_objs, n_new_objs; - int err; - - /* reset non-root levels (root was initialized during init and will not change here) */ - for(l=1; llevels[l]); - memset(topology->levels+1, 0, (HWLOC_DEPTH_MAX-1)*sizeof(*topology->levels)); - memset(topology->level_nbobjects+1, 0, (HWLOC_DEPTH_MAX-1)*sizeof(*topology->level_nbobjects)); - topology->nb_levels = 1; - /* don't touch next_group_depth, the Group objects are still here */ - - /* initialize all depth to unknown */ - for (l = HWLOC_OBJ_SYSTEM; l < HWLOC_OBJ_MISC; l++) - topology->type_depth[l] = HWLOC_TYPE_DEPTH_UNKNOWN; - /* initialize root type depth */ - topology->type_depth[topology->levels[0][0]->type] = 0; - - /* initialize I/O special levels */ - free(topology->bridge_level); - topology->bridge_level = NULL; - topology->bridge_nbobjects = 0; - topology->first_bridge = topology->last_bridge = NULL; - free(topology->pcidev_level); - topology->pcidev_level = NULL; - topology->pcidev_nbobjects = 0; - topology->first_pcidev = topology->last_pcidev = NULL; - free(topology->osdev_level); - topology->osdev_level = NULL; - topology->osdev_nbobjects = 0; - topology->first_osdev = topology->last_osdev = NULL; - - /* Start with children of the whole system. */ - n_objs = topology->levels[0][0]->arity; - objs = malloc(n_objs * sizeof(objs[0])); - if (!objs) { - errno = ENOMEM; - return -1; - } - memcpy(objs, topology->levels[0][0]->children, n_objs*sizeof(objs[0])); - - /* Filter-out interesting objects */ - err = hwloc_level_filter_objects(topology, &objs, &n_objs); - if (err < 0) - return -1; - - /* Keep building levels while there are objects left in OBJS. */ - while (n_objs) { - /* At this point, the objs array contains only objects that may go into levels */ - - /* First find which type of object is the topmost. - * Don't use PU if there are other types since we want to keep PU at the bottom. - */ - - /* Look for the first non-PU object, and use the first PU if we really find nothing else */ - for (i = 0; i < n_objs; i++) - if (objs[i]->type != HWLOC_OBJ_PU) - break; - top_obj = i == n_objs ? objs[0] : objs[i]; - - /* See if this is actually the topmost object */ - for (i = 0; i < n_objs; i++) { - if (hwloc_type_cmp(top_obj, objs[i]) != HWLOC_OBJ_EQUAL) { - if (find_same_type(objs[i], top_obj)) { - /* OBJS[i] is strictly above an object of the same type as TOP_OBJ, so it - * is above TOP_OBJ. */ - top_obj = objs[i]; - } - } - } - - /* Now peek all objects of the same type, build a level with that and - * replace them with their children. */ - - /* First count them. */ - n_taken_objs = 0; - n_new_objs = 0; - for (i = 0; i < n_objs; i++) - if (hwloc_type_cmp(top_obj, objs[i]) == HWLOC_OBJ_EQUAL) { - n_taken_objs++; - n_new_objs += objs[i]->arity; - } - - /* New level. */ - taken_objs = malloc((n_taken_objs + 1) * sizeof(taken_objs[0])); - /* New list of pending objects. */ - if (n_objs - n_taken_objs + n_new_objs) { - new_objs = malloc((n_objs - n_taken_objs + n_new_objs) * sizeof(new_objs[0])); - } else { -#ifdef HWLOC_DEBUG - assert(!n_new_objs); - assert(n_objs == n_taken_objs); -#endif - new_objs = NULL; - } - - n_new_objs = hwloc_level_take_objects(top_obj, - objs, n_objs, - taken_objs, n_taken_objs, - new_objs, n_new_objs); - - /* Ok, put numbers in the level and link cousins. */ - for (i = 0; i < n_taken_objs; i++) { - taken_objs[i]->depth = topology->nb_levels; - taken_objs[i]->logical_index = i; - if (i) { - taken_objs[i]->prev_cousin = taken_objs[i-1]; - taken_objs[i-1]->next_cousin = taken_objs[i]; - } - } - taken_objs[0]->prev_cousin = NULL; - taken_objs[n_taken_objs-1]->next_cousin = NULL; - - /* One more level! */ - if (top_obj->type == HWLOC_OBJ_CACHE) - hwloc_debug("--- Cache level depth %u", top_obj->attr->cache.depth); - else - hwloc_debug("--- %s level", hwloc_obj_type_string(top_obj->type)); - hwloc_debug(" has number %u\n\n", topology->nb_levels); - - if (topology->type_depth[top_obj->type] == HWLOC_TYPE_DEPTH_UNKNOWN) - topology->type_depth[top_obj->type] = topology->nb_levels; - else - topology->type_depth[top_obj->type] = HWLOC_TYPE_DEPTH_MULTIPLE; /* mark as unknown */ - - taken_objs[n_taken_objs] = NULL; - - topology->level_nbobjects[topology->nb_levels] = n_taken_objs; - topology->levels[topology->nb_levels] = taken_objs; - - topology->nb_levels++; - - free(objs); - - /* Switch to new_objs, after filtering-out interesting objects */ - err = hwloc_level_filter_objects(topology, &new_objs, &n_new_objs); - if (err < 0) - return -1; - - objs = new_objs; - n_objs = n_new_objs; - } - - /* It's empty now. */ - if (objs) - free(objs); - - topology->bridge_nbobjects = hwloc_build_level_from_list(topology->first_bridge, &topology->bridge_level); - topology->pcidev_nbobjects = hwloc_build_level_from_list(topology->first_pcidev, &topology->pcidev_level); - topology->osdev_nbobjects = hwloc_build_level_from_list(topology->first_osdev, &topology->osdev_level); - - hwloc_propagate_symmetric_subtree(topology, topology->levels[0][0]); - - return 0; -} - -void hwloc_alloc_obj_cpusets(hwloc_obj_t obj) -{ - if (!obj->cpuset) - obj->cpuset = hwloc_bitmap_alloc_full(); - if (!obj->complete_cpuset) - obj->complete_cpuset = hwloc_bitmap_alloc(); - if (!obj->online_cpuset) - obj->online_cpuset = hwloc_bitmap_alloc_full(); - if (!obj->allowed_cpuset) - obj->allowed_cpuset = hwloc_bitmap_alloc_full(); - if (!obj->nodeset) - obj->nodeset = hwloc_bitmap_alloc(); - if (!obj->complete_nodeset) - obj->complete_nodeset = hwloc_bitmap_alloc(); - if (!obj->allowed_nodeset) - obj->allowed_nodeset = hwloc_bitmap_alloc_full(); -} - -/* Main discovery loop */ -static int -hwloc_discover(struct hwloc_topology *topology) -{ - struct hwloc_backend *backend; - int gotsomeio = 0; - unsigned discoveries = 0; - unsigned need_reconnect = 0; - - /* discover() callbacks should use hwloc_insert to add objects initialized - * through hwloc_alloc_setup_object. - * For node levels, nodeset and memory must be initialized. - * For cache levels, memory and type/depth must be initialized. - * For group levels, depth must be initialized. - */ - - /* There must be at least a PU object for each logical processor, at worse - * produced by hwloc_setup_pu_level() - */ - - /* To be able to just use hwloc_insert_object_by_cpuset to insert the object - * in the topology according to the cpuset, the cpuset field must be - * initialized. - */ - - /* A priori, All processors are visible in the topology, online, and allowed - * for the application. - * - * - If some processors exist but topology information is unknown for them - * (and thus the backend couldn't create objects for them), they should be - * added to the complete_cpuset field of the lowest object where the object - * could reside. - * - * - If some processors are not online, they should be dropped from the - * online_cpuset field. - * - * - If some processors are not allowed for the application (e.g. for - * administration reasons), they should be dropped from the allowed_cpuset - * field. - * - * The same applies to the node sets complete_nodeset and allowed_cpuset. - * - * If such field doesn't exist yet, it can be allocated, and initialized to - * zero (for complete), or to full (for online and allowed). The values are - * automatically propagated to the whole tree after detection. - */ - - /* - * Discover CPUs first - */ - backend = topology->backends; - while (NULL != backend) { - int err; - if (backend->component->type != HWLOC_DISC_COMPONENT_TYPE_CPU - && backend->component->type != HWLOC_DISC_COMPONENT_TYPE_GLOBAL) - /* not yet */ - goto next_cpubackend; - if (!backend->discover) - goto next_cpubackend; - - if (need_reconnect && (backend->flags & HWLOC_BACKEND_FLAG_NEED_LEVELS)) { - hwloc_debug("Backend %s forcing a reconnect of levels\n", backend->component->name); - hwloc_connect_children(topology->levels[0][0]); - if (hwloc_connect_levels(topology) < 0) - return -1; - need_reconnect = 0; - } - - err = backend->discover(backend); - if (err >= 0) { - if (backend->component->type == HWLOC_DISC_COMPONENT_TYPE_GLOBAL) - gotsomeio += err; - discoveries++; - if (err > 0) - need_reconnect++; - } - hwloc_debug_print_objects(0, topology->levels[0][0]); - -next_cpubackend: - backend = backend->next; - } - - if (!discoveries) { - hwloc_debug("%s", "No CPU backend enabled or no discovery succeeded\n"); - errno = EINVAL; - return -1; - } - - /* - * Group levels by distances - */ - hwloc_distances_finalize_os(topology); - hwloc_group_by_distances(topology); - - /* Update objects cpusets and nodesets now that the CPU/GLOBAL backend populated PUs and nodes */ - - hwloc_debug("%s", "\nRestrict topology cpusets to existing PU and NODE objects\n"); - collect_proc_cpuset(topology->levels[0][0], NULL); - - if (topology->binding_hooks.get_allowed_resources && topology->is_thissystem) { - const char *env = getenv("HWLOC_THISSYSTEM_ALLOWED_RESOURCES"); - if ((env && atoi(env)) - || (topology->flags & HWLOC_TOPOLOGY_FLAG_THISSYSTEM_ALLOWED_RESOURCES)) - topology->binding_hooks.get_allowed_resources(topology); - } - - hwloc_debug("%s", "\nPropagate offline and disallowed cpus down and up\n"); - propagate_unused_cpuset(topology->levels[0][0], NULL); - - if (topology->levels[0][0]->complete_nodeset && hwloc_bitmap_iszero(topology->levels[0][0]->complete_nodeset)) { - /* No nodeset, drop all of them */ - hwloc_bitmap_free(topology->levels[0][0]->nodeset); - topology->levels[0][0]->nodeset = NULL; - hwloc_bitmap_free(topology->levels[0][0]->complete_nodeset); - topology->levels[0][0]->complete_nodeset = NULL; - hwloc_bitmap_free(topology->levels[0][0]->allowed_nodeset); - topology->levels[0][0]->allowed_nodeset = NULL; - } - hwloc_debug("%s", "\nPropagate nodesets\n"); - propagate_nodeset(topology->levels[0][0], NULL); - propagate_nodesets(topology->levels[0][0]); - - hwloc_debug_print_objects(0, topology->levels[0][0]); - - if (!(topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM)) { - hwloc_debug("%s", "\nRemoving unauthorized and offline sets from all sets\n"); - remove_unused_sets(topology->levels[0][0]); - hwloc_debug_print_objects(0, topology->levels[0][0]); - } - - hwloc_debug("%s", "\nAdd default object sets\n"); - add_default_object_sets(topology->levels[0][0], 0); - - /* Now connect handy pointers to make remaining discovery easier. */ - hwloc_debug("%s", "\nOk, finished tweaking, now connect\n"); - hwloc_connect_children(topology->levels[0][0]); - if (hwloc_connect_levels(topology) < 0) - return -1; - hwloc_debug_print_objects(0, topology->levels[0][0]); - - /* - * Additional discovery with other backends - */ - - backend = topology->backends; - need_reconnect = 0; - while (NULL != backend) { - int err; - if (backend->component->type == HWLOC_DISC_COMPONENT_TYPE_CPU - || backend->component->type == HWLOC_DISC_COMPONENT_TYPE_GLOBAL) - /* already done above */ - goto next_noncpubackend; - if (!backend->discover) - goto next_noncpubackend; - - if (need_reconnect && (backend->flags & HWLOC_BACKEND_FLAG_NEED_LEVELS)) { - hwloc_debug("Backend %s forcing a reconnect of levels\n", backend->component->name); - hwloc_connect_children(topology->levels[0][0]); - if (hwloc_connect_levels(topology) < 0) - return -1; - need_reconnect = 0; - } - - err = backend->discover(backend); - if (err >= 0) { - gotsomeio += err; - if (err > 0) - need_reconnect++; - } - hwloc_debug_print_objects(0, topology->levels[0][0]); - -next_noncpubackend: - backend = backend->next; - } - - /* if we got anything, filter interesting objects and update the tree */ - if (gotsomeio) { - hwloc_drop_useless_io(topology, topology->levels[0][0]); - hwloc_debug("%s", "\nNow reconnecting\n"); - hwloc_debug_print_objects(0, topology->levels[0][0]); - hwloc_propagate_bridge_depth(topology, topology->levels[0][0], 0); - } - - /* Removed some stuff */ - - hwloc_debug("%s", "\nRemoving ignored objects\n"); - remove_ignored(topology, &topology->levels[0][0]); - hwloc_debug_print_objects(0, topology->levels[0][0]); - - hwloc_debug("%s", "\nRemoving empty objects except numa nodes and PCI devices\n"); - remove_empty(topology, &topology->levels[0][0]); - if (!topology->levels[0][0]) { - fprintf(stderr, "Topology became empty, aborting!\n"); - abort(); - } - hwloc_debug_print_objects(0, topology->levels[0][0]); - - hwloc_debug("%s", "\nRemoving objects whose type has HWLOC_IGNORE_TYPE_KEEP_STRUCTURE and have only one child or are the only child\n"); - merge_useless_child(topology, &topology->levels[0][0]); - hwloc_debug_print_objects(0, topology->levels[0][0]); - - /* Reconnect things after all these changes */ - hwloc_connect_children(topology->levels[0][0]); - if (hwloc_connect_levels(topology) < 0) - return -1; - - /* accumulate children memory in total_memory fields (only once parent is set) */ - hwloc_debug("%s", "\nPropagate total memory up\n"); - propagate_total_memory(topology->levels[0][0]); - - /* - * Now that objects are numbered, take distance matrices from backends and put them in the main topology. - * - * Some objects may have disappeared (in removed_empty or removed_ignored) since we setup os distances - * (hwloc_distances_finalize_os()) above. Reset them so as to not point to disappeared objects anymore. - */ - hwloc_distances_restrict_os(topology); - hwloc_distances_finalize_os(topology); - hwloc_distances_finalize_logical(topology); - - /* add some identification attributes if not loading from XML */ - if (topology->backends - && strcmp(topology->backends->component->name, "xml")) { - char *value; - /* add a hwlocVersion */ - hwloc_obj_add_info(topology->levels[0][0], "hwlocVersion", HWLOC_VERSION); - /* add a ProcessName */ - value = hwloc_progname(topology); - if (value) { - hwloc_obj_add_info(topology->levels[0][0], "ProcessName", value); - free(value); - } - } - - return 0; -} - -/* To be before discovery is actually launched, - * Resets everything in case a previous load initialized some stuff. - */ -void -hwloc_topology_setup_defaults(struct hwloc_topology *topology) -{ - struct hwloc_obj *root_obj; - unsigned l; - - /* reset support */ - memset(&topology->binding_hooks, 0, sizeof(topology->binding_hooks)); - memset(topology->support.discovery, 0, sizeof(*topology->support.discovery)); - memset(topology->support.cpubind, 0, sizeof(*topology->support.cpubind)); - memset(topology->support.membind, 0, sizeof(*topology->support.membind)); - - /* Only the System object on top by default */ - topology->nb_levels = 1; /* there's at least SYSTEM */ - topology->next_group_depth = 0; - topology->levels[0] = malloc (sizeof (hwloc_obj_t)); - topology->level_nbobjects[0] = 1; - /* NULLify other levels so that we can detect and free old ones in hwloc_connect_levels() if needed */ - memset(topology->levels+1, 0, (HWLOC_DEPTH_MAX-1)*sizeof(*topology->levels)); - topology->bridge_level = NULL; - topology->pcidev_level = NULL; - topology->osdev_level = NULL; - topology->first_bridge = topology->last_bridge = NULL; - topology->first_pcidev = topology->last_pcidev = NULL; - topology->first_osdev = topology->last_osdev = NULL; - /* sane values to type_depth */ - for (l = HWLOC_OBJ_SYSTEM; l <= HWLOC_OBJ_MISC; l++) - topology->type_depth[l] = HWLOC_TYPE_DEPTH_UNKNOWN; - topology->type_depth[HWLOC_OBJ_BRIDGE] = HWLOC_TYPE_DEPTH_BRIDGE; - topology->type_depth[HWLOC_OBJ_PCI_DEVICE] = HWLOC_TYPE_DEPTH_PCI_DEVICE; - topology->type_depth[HWLOC_OBJ_OS_DEVICE] = HWLOC_TYPE_DEPTH_OS_DEVICE; - - /* Create the actual machine object, but don't touch its attributes yet - * since the OS backend may still change the object into something else - * (for instance System) - */ - root_obj = hwloc_alloc_setup_object(HWLOC_OBJ_MACHINE, 0); - root_obj->depth = 0; - root_obj->logical_index = 0; - root_obj->sibling_rank = 0; - topology->levels[0][0] = root_obj; -} - -int -hwloc_topology_init (struct hwloc_topology **topologyp) -{ - struct hwloc_topology *topology; - int i; - - topology = malloc (sizeof (struct hwloc_topology)); - if(!topology) - return -1; - - hwloc_components_init(topology); - - /* Setup topology context */ - topology->is_loaded = 0; - topology->flags = 0; - topology->is_thissystem = 1; - topology->pid = 0; - topology->userdata = NULL; - - topology->support.discovery = malloc(sizeof(*topology->support.discovery)); - topology->support.cpubind = malloc(sizeof(*topology->support.cpubind)); - topology->support.membind = malloc(sizeof(*topology->support.membind)); - - /* Only ignore useless cruft by default */ - for(i = HWLOC_OBJ_SYSTEM; i < HWLOC_OBJ_TYPE_MAX; i++) - topology->ignored_types[i] = HWLOC_IGNORE_TYPE_NEVER; - topology->ignored_types[HWLOC_OBJ_GROUP] = HWLOC_IGNORE_TYPE_KEEP_STRUCTURE; - - hwloc_distances_init(topology); - - topology->userdata_export_cb = NULL; - topology->userdata_import_cb = NULL; - topology->userdata_not_decoded = 0; - - /* Make the topology look like something coherent but empty */ - hwloc_topology_setup_defaults(topology); - - *topologyp = topology; - return 0; -} - -int -hwloc_topology_set_pid(struct hwloc_topology *topology __hwloc_attribute_unused, - hwloc_pid_t pid __hwloc_attribute_unused) -{ - /* this does *not* change the backend */ -#ifdef HWLOC_LINUX_SYS - topology->pid = pid; - return 0; -#else /* HWLOC_LINUX_SYS */ - errno = ENOSYS; - return -1; -#endif /* HWLOC_LINUX_SYS */ -} - -int -hwloc_topology_set_fsroot(struct hwloc_topology *topology, const char *fsroot_path) -{ - return hwloc_disc_component_force_enable(topology, - 0 /* api */, - HWLOC_DISC_COMPONENT_TYPE_CPU, "linux", - fsroot_path, NULL, NULL); -} - -int -hwloc_topology_set_synthetic(struct hwloc_topology *topology, const char *description) -{ - return hwloc_disc_component_force_enable(topology, - 0 /* api */, - -1, "synthetic", - description, NULL, NULL); -} - -int -hwloc_topology_set_xml(struct hwloc_topology *topology, - const char *xmlpath) -{ - return hwloc_disc_component_force_enable(topology, - 0 /* api */, - -1, "xml", - xmlpath, NULL, NULL); -} - -int -hwloc_topology_set_xmlbuffer(struct hwloc_topology *topology, - const char *xmlbuffer, - int size) -{ - return hwloc_disc_component_force_enable(topology, - 0 /* api */, - -1, "xml", NULL, - xmlbuffer, (void*) (uintptr_t) size); -} - -int -hwloc_topology_set_custom(struct hwloc_topology *topology) -{ - return hwloc_disc_component_force_enable(topology, - 0 /* api */, - -1, "custom", - NULL, NULL, NULL); -} - -int -hwloc_topology_set_flags (struct hwloc_topology *topology, unsigned long flags) -{ - if (topology->is_loaded) { - /* actually harmless */ - errno = EBUSY; - return -1; - } - topology->flags = flags; - return 0; -} - -unsigned long -hwloc_topology_get_flags (struct hwloc_topology *topology) -{ - return topology->flags; -} - -int -hwloc_topology_ignore_type(struct hwloc_topology *topology, hwloc_obj_type_t type) -{ - if (type >= HWLOC_OBJ_TYPE_MAX) { - errno = EINVAL; - return -1; - } - - if (type == HWLOC_OBJ_PU) { - /* we need the PU level */ - errno = EINVAL; - return -1; - } else if (hwloc_obj_type_is_io(type)) { - /* I/O devices aren't in any level, use topology flags to ignore them */ - errno = EINVAL; - return -1; - } - - topology->ignored_types[type] = HWLOC_IGNORE_TYPE_ALWAYS; - return 0; -} - -int -hwloc_topology_ignore_type_keep_structure(struct hwloc_topology *topology, hwloc_obj_type_t type) -{ - if (type >= HWLOC_OBJ_TYPE_MAX) { - errno = EINVAL; - return -1; - } - - if (type == HWLOC_OBJ_PU) { - /* we need the PU level */ - errno = EINVAL; - return -1; - } else if (hwloc_obj_type_is_io(type)) { - /* I/O devices aren't in any level, use topology flags to ignore them */ - errno = EINVAL; - return -1; - } - - topology->ignored_types[type] = HWLOC_IGNORE_TYPE_KEEP_STRUCTURE; - return 0; -} - -int -hwloc_topology_ignore_all_keep_structure(struct hwloc_topology *topology) -{ - unsigned type; - for(type = HWLOC_OBJ_SYSTEM; type < HWLOC_OBJ_TYPE_MAX; type++) - if (type != HWLOC_OBJ_PU - && !hwloc_obj_type_is_io((hwloc_obj_type_t) type)) - topology->ignored_types[type] = HWLOC_IGNORE_TYPE_KEEP_STRUCTURE; - return 0; -} - -/* traverse the tree and free everything. - * only use first_child/next_sibling so that it works before load() - * and may be used when switching between backend. - */ -static void -hwloc_topology_clear_tree (struct hwloc_topology *topology, struct hwloc_obj *root) -{ - hwloc_obj_t child = root->first_child; - while (child) { - hwloc_obj_t nextchild = child->next_sibling; - hwloc_topology_clear_tree (topology, child); - child = nextchild; - } - hwloc_free_unlinked_object (root); -} - -void -hwloc_topology_clear (struct hwloc_topology *topology) -{ - unsigned l; - hwloc_topology_clear_tree (topology, topology->levels[0][0]); - for (l=0; lnb_levels; l++) { - free(topology->levels[l]); - topology->levels[l] = NULL; - } - free(topology->bridge_level); - free(topology->pcidev_level); - free(topology->osdev_level); -} - -void -hwloc_topology_destroy (struct hwloc_topology *topology) -{ - hwloc_backends_disable_all(topology); - hwloc_components_destroy_all(topology); - - hwloc_topology_clear(topology); - hwloc_distances_destroy(topology); - - free(topology->support.discovery); - free(topology->support.cpubind); - free(topology->support.membind); - free(topology); -} - -int -hwloc_topology_load (struct hwloc_topology *topology) -{ - int err; - - if (topology->is_loaded) { - errno = EBUSY; - return -1; - } - - if (getenv("HWLOC_XML_USERDATA_NOT_DECODED")) - topology->userdata_not_decoded = 1; - - /* enforce backend anyway if a FORCE variable was given */ - { - const char *fsroot_path_env = getenv("HWLOC_FORCE_FSROOT"); - if (fsroot_path_env) - hwloc_disc_component_force_enable(topology, - 1 /* env force */, - HWLOC_DISC_COMPONENT_TYPE_CPU, "linux", - fsroot_path_env, NULL, NULL); - } - { - const char *xmlpath_env = getenv("HWLOC_FORCE_XMLFILE"); - if (xmlpath_env) - hwloc_disc_component_force_enable(topology, - 1 /* env force */, - -1, "xml", - xmlpath_env, NULL, NULL); - } - - /* only apply non-FORCE variables if we have not changed the backend yet */ - if (!topology->backends) { - const char *fsroot_path_env = getenv("HWLOC_FSROOT"); - if (fsroot_path_env) - hwloc_disc_component_force_enable(topology, - 1 /* env force */, - HWLOC_DISC_COMPONENT_TYPE_CPU, "linux", - fsroot_path_env, NULL, NULL); - } - if (!topology->backends) { - const char *xmlpath_env = getenv("HWLOC_XMLFILE"); - if (xmlpath_env) - hwloc_disc_component_force_enable(topology, - 1 /* env force */, - -1, "xml", - xmlpath_env, NULL, NULL); - } - - /* instantiate all possible other backends now */ - hwloc_disc_components_enable_others(topology); - /* now that backends are enabled, update the thissystem flag */ - hwloc_backends_is_thissystem(topology); - /* - * Now set binding hooks according to topology->is_thissystem - * and what the native OS backend offers. - */ - hwloc_set_binding_hooks(topology); - - /* get distance matrix from the environment are store them (as indexes) in the topology. - * indexes will be converted into objects later once the tree will be filled - */ - hwloc_distances_set_from_env(topology); - - /* actual topology discovery */ - err = hwloc_discover(topology); - if (err < 0) - goto out; - -#ifndef HWLOC_DEBUG - if (getenv("HWLOC_DEBUG_CHECK")) -#endif - hwloc_topology_check(topology); - - topology->is_loaded = 1; - return 0; - - out: - hwloc_topology_clear(topology); - hwloc_distances_destroy(topology); - hwloc_topology_setup_defaults(topology); - hwloc_backends_disable_all(topology); - return -1; -} - -int -hwloc_topology_restrict(struct hwloc_topology *topology, hwloc_const_cpuset_t cpuset, unsigned long flags) -{ - hwloc_bitmap_t droppedcpuset, droppednodeset; - - if (!topology->is_loaded) { - errno = EINVAL; - return -1; - } - - /* make sure we'll keep something in the topology */ - if (!hwloc_bitmap_intersects(cpuset, topology->levels[0][0]->cpuset)) { - errno = EINVAL; /* easy failure, just don't touch the topology */ - return -1; - } - - droppedcpuset = hwloc_bitmap_alloc(); - droppednodeset = hwloc_bitmap_alloc(); - - /* drop object based on the reverse of cpuset, and fill the 'dropped' nodeset */ - hwloc_bitmap_not(droppedcpuset, cpuset); - restrict_object(topology, flags, &topology->levels[0][0], droppedcpuset, droppednodeset, 0 /* root cannot be removed */); - /* update nodesets according to dropped nodeset */ - restrict_object_nodeset(topology, &topology->levels[0][0], droppednodeset); - - hwloc_bitmap_free(droppedcpuset); - hwloc_bitmap_free(droppednodeset); - - hwloc_connect_children(topology->levels[0][0]); - if (hwloc_connect_levels(topology) < 0) - goto out; - - propagate_total_memory(topology->levels[0][0]); - hwloc_distances_restrict(topology, flags); - hwloc_distances_finalize_os(topology); - hwloc_distances_finalize_logical(topology); - return 0; - - out: - /* unrecoverable failure, re-init the topology */ - hwloc_topology_clear(topology); - hwloc_distances_destroy(topology); - hwloc_topology_setup_defaults(topology); - return -1; -} - -int -hwloc_topology_is_thissystem(struct hwloc_topology *topology) -{ - return topology->is_thissystem; -} - -unsigned -hwloc_topology_get_depth(struct hwloc_topology *topology) -{ - return topology->nb_levels; -} - -/* check children between a parent object */ -static void -hwloc__check_children(struct hwloc_obj *parent) -{ - unsigned j; - - if (!parent->arity) { - /* check whether that parent has no children for real */ - assert(!parent->children); - assert(!parent->first_child); - assert(!parent->last_child); - return; - } - /* check whether that parent has children for real */ - assert(parent->children); - assert(parent->first_child); - assert(parent->last_child); - - /* first child specific checks */ - assert(parent->first_child->sibling_rank == 0); - assert(parent->first_child == parent->children[0]); - assert(parent->first_child->prev_sibling == NULL); - - /* last child specific checks */ - assert(parent->last_child->sibling_rank == parent->arity-1); - assert(parent->last_child == parent->children[parent->arity-1]); - assert(parent->last_child->next_sibling == NULL); - - /* check that parent->cpuset == exclusive OR of children - * (can be wrong for complete_cpuset since disallowed/offline/unknown PUs can be removed) - */ - if (parent->cpuset) { - hwloc_bitmap_t remaining_parent_set = hwloc_bitmap_dup(parent->cpuset); - for(j=0; jarity; j++) { - if (!parent->children[j]->cpuset) - continue; - /* check that child cpuset is included in the reminder of the parent */ - assert(hwloc_bitmap_isincluded(parent->children[j]->cpuset, remaining_parent_set)); - hwloc_bitmap_andnot(remaining_parent_set, remaining_parent_set, parent->children[j]->cpuset); - } - if (parent->type == HWLOC_OBJ_PU) { - /* if parent is a PU, its os_index bit may remain. - * it may be in a Misc child inserted by cpuset, or could be in no child */ - if (hwloc_bitmap_weight(remaining_parent_set) == 1) - assert((unsigned) hwloc_bitmap_first(remaining_parent_set) == parent->os_index); - else - assert(hwloc_bitmap_iszero(remaining_parent_set)); - } else { - /* nothing remains */ - assert(hwloc_bitmap_iszero(remaining_parent_set)); - } - hwloc_bitmap_free(remaining_parent_set); - } - - /* check that children complete_cpuset are properly ordered, empty ones may be anywhere - * (can be wrong for main cpuset since removed PUs can break the ordering). - */ - if (parent->complete_cpuset) { - int firstchild; - int prev_firstchild = -1; /* -1 works fine with first comparisons below */ - for(j=0; jarity; j++) { - if (!parent->children[j]->complete_cpuset - || hwloc_bitmap_iszero(parent->children[j]->complete_cpuset)) - continue; - - firstchild = hwloc_bitmap_first(parent->children[j]->complete_cpuset); - assert(prev_firstchild < firstchild); - prev_firstchild = firstchild; - } - } - - /* checks for all children */ - for(j=1; jarity; j++) { - assert(parent->children[j]->parent == parent); - assert(parent->children[j]->sibling_rank == j); - assert(parent->children[j-1]->next_sibling == parent->children[j]); - assert(parent->children[j]->prev_sibling == parent->children[j-1]); - } -} - -static void -hwloc__check_children_depth(struct hwloc_topology *topology, struct hwloc_obj *parent) -{ - hwloc_obj_t child = NULL; - while ((child = hwloc_get_next_child(topology, parent, child)) != NULL) { - if (child->type == HWLOC_OBJ_BRIDGE) - assert(child->depth == (unsigned) HWLOC_TYPE_DEPTH_BRIDGE); - else if (child->type == HWLOC_OBJ_PCI_DEVICE) - assert(child->depth == (unsigned) HWLOC_TYPE_DEPTH_PCI_DEVICE); - else if (child->type == HWLOC_OBJ_OS_DEVICE) - assert(child->depth == (unsigned) HWLOC_TYPE_DEPTH_OS_DEVICE); - else if (child->type == HWLOC_OBJ_MISC) - assert(child->depth == (unsigned) -1); - else if (parent->depth != (unsigned) -1) - assert(child->depth > parent->depth); - hwloc__check_children_depth(topology, child); - } -} - -/* check a whole topology structure */ -void -hwloc_topology_check(struct hwloc_topology *topology) -{ - struct hwloc_obj *obj; - hwloc_obj_type_t type; - unsigned i, j, depth; - - /* check type orders */ - for (type = HWLOC_OBJ_SYSTEM; type < HWLOC_OBJ_TYPE_MAX; type++) { - assert(hwloc_get_order_type(hwloc_get_type_order(type)) == type); - } - for (i = hwloc_get_type_order(HWLOC_OBJ_SYSTEM); - i <= hwloc_get_type_order(HWLOC_OBJ_CORE); i++) { - assert(i == hwloc_get_type_order(hwloc_get_order_type(i))); - } - - /* check that last level is PU */ - assert(hwloc_get_depth_type(topology, hwloc_topology_get_depth(topology)-1) == HWLOC_OBJ_PU); - /* check that other levels are not PU */ - for(i=1; iparent); - - depth = hwloc_topology_get_depth(topology); - - /* check each level */ - for(i=0; idepth == i); - assert(obj->logical_index == j); - /* check that all objects in the level have the same type */ - if (prev) { - assert(hwloc_type_cmp(obj, prev) == HWLOC_OBJ_EQUAL); - assert(prev->next_cousin == obj); - assert(obj->prev_cousin == prev); - } - if (obj->complete_cpuset) { - if (obj->cpuset) - assert(hwloc_bitmap_isincluded(obj->cpuset, obj->complete_cpuset)); - if (obj->online_cpuset) - assert(hwloc_bitmap_isincluded(obj->online_cpuset, obj->complete_cpuset)); - if (obj->allowed_cpuset) - assert(hwloc_bitmap_isincluded(obj->allowed_cpuset, obj->complete_cpuset)); - } - if (obj->complete_nodeset) { - if (obj->nodeset) - assert(hwloc_bitmap_isincluded(obj->nodeset, obj->complete_nodeset)); - if (obj->allowed_nodeset) - assert(hwloc_bitmap_isincluded(obj->allowed_nodeset, obj->complete_nodeset)); - } - /* check that PUs and NUMA nodes have cpuset/nodeset */ - if (obj->type == HWLOC_OBJ_PU) { - assert(obj->cpuset); - assert(obj->complete_cpuset); - assert(hwloc_bitmap_weight(obj->complete_cpuset) == 1); - assert(hwloc_bitmap_first(obj->complete_cpuset) == (int) obj->os_index); - } - if (obj->type == HWLOC_OBJ_NUMANODE) { - assert(obj->nodeset); - assert(obj->complete_nodeset); - assert(hwloc_bitmap_weight(obj->complete_nodeset) == 1); - assert(hwloc_bitmap_first(obj->complete_nodeset) == (int) obj->os_index); - } - /* check children */ - hwloc__check_children(obj); - prev = obj; - } - - /* check first object of the level */ - obj = hwloc_get_obj_by_depth(topology, i, 0); - assert(obj); - assert(!obj->prev_cousin); - - /* check type */ - assert(hwloc_get_depth_type(topology, i) == obj->type); - assert(i == (unsigned) hwloc_get_type_depth(topology, obj->type) || - HWLOC_TYPE_DEPTH_MULTIPLE == hwloc_get_type_depth(topology, obj->type)); - - /* check last object of the level */ - obj = hwloc_get_obj_by_depth(topology, i, width-1); - assert(obj); - assert(!obj->next_cousin); - - /* check last+1 object of the level */ - obj = hwloc_get_obj_by_depth(topology, i, width); - assert(!obj); - } - - /* check bottom objects */ - assert(hwloc_get_nbobjs_by_depth(topology, depth-1) > 0); - for(j=0; jtype == HWLOC_OBJ_PU); - } - - /* check relative depths */ - obj = hwloc_get_root_obj(topology); - assert(obj->depth == 0); - hwloc__check_children_depth(topology, obj); -} - -const struct hwloc_topology_support * -hwloc_topology_get_support(struct hwloc_topology * topology) -{ - return &topology->support; -} - -void hwloc_topology_set_userdata(struct hwloc_topology * topology, const void *userdata) -{ - topology->userdata = (void *) userdata; -} - -void * hwloc_topology_get_userdata(struct hwloc_topology * topology) -{ - return topology->userdata; -} diff --git a/opal/mca/hwloc/hwloc1116/hwloc/src/traversal.c b/opal/mca/hwloc/hwloc1116/hwloc/src/traversal.c deleted file mode 100644 index 15ea4baba3..0000000000 --- a/opal/mca/hwloc/hwloc1116/hwloc/src/traversal.c +++ /dev/null @@ -1,715 +0,0 @@ -/* - * Copyright © 2009 CNRS - * Copyright © 2009-2016 Inria. All rights reserved. - * Copyright © 2009-2010 Université Bordeaux - * Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved. - * See COPYING in top-level directory. - */ - -#include -#include -#include -#include -#include -#ifdef HAVE_STRINGS_H -#include -#endif /* HAVE_STRINGS_H */ - -int -hwloc_get_type_depth (struct hwloc_topology *topology, hwloc_obj_type_t type) -{ - return topology->type_depth[type]; -} - -hwloc_obj_type_t -hwloc_get_depth_type (hwloc_topology_t topology, unsigned depth) -{ - if (depth >= topology->nb_levels) - switch (depth) { - case HWLOC_TYPE_DEPTH_BRIDGE: - return HWLOC_OBJ_BRIDGE; - case HWLOC_TYPE_DEPTH_PCI_DEVICE: - return HWLOC_OBJ_PCI_DEVICE; - case HWLOC_TYPE_DEPTH_OS_DEVICE: - return HWLOC_OBJ_OS_DEVICE; - default: - return (hwloc_obj_type_t) -1; - } - return topology->levels[depth][0]->type; -} - -unsigned -hwloc_get_nbobjs_by_depth (struct hwloc_topology *topology, unsigned depth) -{ - if (depth >= topology->nb_levels) - switch (depth) { - case HWLOC_TYPE_DEPTH_BRIDGE: - return topology->bridge_nbobjects; - case HWLOC_TYPE_DEPTH_PCI_DEVICE: - return topology->pcidev_nbobjects; - case HWLOC_TYPE_DEPTH_OS_DEVICE: - return topology->osdev_nbobjects; - default: - return 0; - } - return topology->level_nbobjects[depth]; -} - -struct hwloc_obj * -hwloc_get_obj_by_depth (struct hwloc_topology *topology, unsigned depth, unsigned idx) -{ - if (depth >= topology->nb_levels) - switch (depth) { - case HWLOC_TYPE_DEPTH_BRIDGE: - return idx < topology->bridge_nbobjects ? topology->bridge_level[idx] : NULL; - case HWLOC_TYPE_DEPTH_PCI_DEVICE: - return idx < topology->pcidev_nbobjects ? topology->pcidev_level[idx] : NULL; - case HWLOC_TYPE_DEPTH_OS_DEVICE: - return idx < topology->osdev_nbobjects ? topology->osdev_level[idx] : NULL; - default: - return NULL; - } - if (idx >= topology->level_nbobjects[depth]) - return NULL; - return topology->levels[depth][idx]; -} - -unsigned hwloc_get_closest_objs (struct hwloc_topology *topology, struct hwloc_obj *src, struct hwloc_obj **objs, unsigned max) -{ - struct hwloc_obj *parent, *nextparent, **src_objs; - int i,src_nbobjects; - unsigned stored = 0; - - if (!src->cpuset) - return 0; - - src_nbobjects = topology->level_nbobjects[src->depth]; - src_objs = topology->levels[src->depth]; - - parent = src; - while (stored < max) { - while (1) { - nextparent = parent->parent; - if (!nextparent) - goto out; - if (!nextparent->cpuset || !hwloc_bitmap_isequal(parent->cpuset, nextparent->cpuset)) - break; - parent = nextparent; - } - - if (!nextparent->cpuset) - break; - - /* traverse src's objects and find those that are in nextparent and were not in parent */ - for(i=0; icpuset, nextparent->cpuset) - && !hwloc_bitmap_isincluded(src_objs[i]->cpuset, parent->cpuset)) { - objs[stored++] = src_objs[i]; - if (stored == max) - goto out; - } - } - parent = nextparent; - } - - out: - return stored; -} - -static int -hwloc__get_largest_objs_inside_cpuset (struct hwloc_obj *current, hwloc_const_bitmap_t set, - struct hwloc_obj ***res, int *max) -{ - int gotten = 0; - unsigned i; - - /* the caller must ensure this */ - if (*max <= 0) - return 0; - - if (hwloc_bitmap_isequal(current->cpuset, set)) { - **res = current; - (*res)++; - (*max)--; - return 1; - } - - for (i=0; iarity; i++) { - hwloc_bitmap_t subset = hwloc_bitmap_dup(set); - int ret; - - /* split out the cpuset part corresponding to this child and see if there's anything to do */ - if (current->children[i]->cpuset) { - hwloc_bitmap_and(subset, subset, current->children[i]->cpuset); - if (hwloc_bitmap_iszero(subset)) { - hwloc_bitmap_free(subset); - continue; - } - } - - ret = hwloc__get_largest_objs_inside_cpuset (current->children[i], subset, res, max); - gotten += ret; - hwloc_bitmap_free(subset); - - /* if no more room to store remaining objects, return what we got so far */ - if (!*max) - break; - } - - return gotten; -} - -int -hwloc_get_largest_objs_inside_cpuset (struct hwloc_topology *topology, hwloc_const_bitmap_t set, - struct hwloc_obj **objs, int max) -{ - struct hwloc_obj *current = topology->levels[0][0]; - - if (!current->cpuset || !hwloc_bitmap_isincluded(set, current->cpuset)) - return -1; - - if (max <= 0) - return 0; - - return hwloc__get_largest_objs_inside_cpuset (current, set, &objs, &max); -} - -const char * -hwloc_obj_type_string (hwloc_obj_type_t obj) -{ - switch (obj) - { - case HWLOC_OBJ_SYSTEM: return "System"; - case HWLOC_OBJ_MACHINE: return "Machine"; - case HWLOC_OBJ_MISC: return "Misc"; - case HWLOC_OBJ_GROUP: return "Group"; - case HWLOC_OBJ_NUMANODE: return "NUMANode"; - case HWLOC_OBJ_PACKAGE: return "Package"; - case HWLOC_OBJ_CACHE: return "Cache"; - case HWLOC_OBJ_CORE: return "Core"; - case HWLOC_OBJ_BRIDGE: return "Bridge"; - case HWLOC_OBJ_PCI_DEVICE: return "PCIDev"; - case HWLOC_OBJ_OS_DEVICE: return "OSDev"; - case HWLOC_OBJ_PU: return "PU"; - default: return "Unknown"; - } -} - -hwloc_obj_type_t -hwloc_obj_type_of_string (const char * string) -{ - if (!strcasecmp(string, "System")) return HWLOC_OBJ_SYSTEM; - if (!strcasecmp(string, "Machine")) return HWLOC_OBJ_MACHINE; - if (!strcasecmp(string, "Misc")) return HWLOC_OBJ_MISC; - if (!strcasecmp(string, "Group")) return HWLOC_OBJ_GROUP; - if (!strcasecmp(string, "NUMANode") || !strcasecmp(string, "Node")) return HWLOC_OBJ_NUMANODE; - if (!strcasecmp(string, "Package") || !strcasecmp(string, "Socket") /* backward compat with v1.10 */) return HWLOC_OBJ_PACKAGE; - if (!strcasecmp(string, "Cache")) return HWLOC_OBJ_CACHE; - if (!strcasecmp(string, "Core")) return HWLOC_OBJ_CORE; - if (!strcasecmp(string, "PU")) return HWLOC_OBJ_PU; - if (!strcasecmp(string, "Bridge") || !strcasecmp(string, "HostBridge") || !strcasecmp(string, "PCIBridge")) return HWLOC_OBJ_BRIDGE; - if (!strcasecmp(string, "PCIDev")) return HWLOC_OBJ_PCI_DEVICE; - if (!strcasecmp(string, "OSDev")) return HWLOC_OBJ_OS_DEVICE; - return (hwloc_obj_type_t) -1; -} - -int -hwloc_obj_type_sscanf(const char *string, hwloc_obj_type_t *typep, int *depthattrp, void *typeattrp, size_t typeattrsize) -{ - hwloc_obj_type_t type = (hwloc_obj_type_t) -1; - int depthattr = -1; - hwloc_obj_cache_type_t cachetypeattr = (hwloc_obj_cache_type_t) -1; /* unspecified */ - char *end; - - /* never match the ending \0 since we want to match things like core:2 too. - * just use hwloc_strncasecmp() everywhere. - */ - - /* types without depthattr */ - if (!hwloc_strncasecmp(string, "system", 2)) { - type = HWLOC_OBJ_SYSTEM; - } else if (!hwloc_strncasecmp(string, "machine", 2)) { - type = HWLOC_OBJ_MACHINE; - } else if (!hwloc_strncasecmp(string, "node", 2) - || !hwloc_strncasecmp(string, "numa", 2)) { /* matches node and numanode */ - type = HWLOC_OBJ_NUMANODE; - } else if (!hwloc_strncasecmp(string, "package", 2) - || !hwloc_strncasecmp(string, "socket", 2)) { /* backward compat with v1.10 */ - type = HWLOC_OBJ_PACKAGE; - } else if (!hwloc_strncasecmp(string, "core", 2)) { - type = HWLOC_OBJ_CORE; - } else if (!hwloc_strncasecmp(string, "pu", 2)) { - type = HWLOC_OBJ_PU; - } else if (!hwloc_strncasecmp(string, "misc", 4)) { - type = HWLOC_OBJ_MISC; - } else if (!hwloc_strncasecmp(string, "bridge", 4) - || !hwloc_strncasecmp(string, "hostbridge", 6) - || !hwloc_strncasecmp(string, "pcibridge", 5)) { - type = HWLOC_OBJ_BRIDGE; - } else if (!hwloc_strncasecmp(string, "pci", 3)) { - type = HWLOC_OBJ_PCI_DEVICE; - } else if (!hwloc_strncasecmp(string, "os", 2) - || !hwloc_strncasecmp(string, "bloc", 4) - || !hwloc_strncasecmp(string, "net", 3) - || !hwloc_strncasecmp(string, "openfab", 7) - || !hwloc_strncasecmp(string, "dma", 3) - || !hwloc_strncasecmp(string, "gpu", 3) - || !hwloc_strncasecmp(string, "copro", 5) - || !hwloc_strncasecmp(string, "co-pro", 6)) { - type = HWLOC_OBJ_OS_DEVICE; - - /* types with depthattr */ - } else if (!hwloc_strncasecmp(string, "cache", 2)) { - type = HWLOC_OBJ_CACHE; - - } else if ((string[0] == 'l' || string[0] == 'L') && string[1] >= '0' && string[1] <= '9') { - type = HWLOC_OBJ_CACHE; - depthattr = strtol(string+1, &end, 10); - if (*end == 'd') { - cachetypeattr = HWLOC_OBJ_CACHE_DATA; - } else if (*end == 'i') { - cachetypeattr = HWLOC_OBJ_CACHE_INSTRUCTION; - } else if (*end == 'u') { - cachetypeattr = HWLOC_OBJ_CACHE_UNIFIED; - } - - } else if (!hwloc_strncasecmp(string, "group", 2)) { - size_t length; - type = HWLOC_OBJ_GROUP; - length = strcspn(string, "0123456789"); - if (length <= 5 && !hwloc_strncasecmp(string, "group", length) - && string[length] >= '0' && string[length] <= '9') { - depthattr = strtol(string+length, &end, 10); - } - } else - return -1; - - *typep = type; - if (depthattrp) - *depthattrp = depthattr; - if (typeattrp) { - if (type == HWLOC_OBJ_CACHE && sizeof(hwloc_obj_cache_type_t) <= typeattrsize) - memcpy(typeattrp, &cachetypeattr, sizeof(hwloc_obj_cache_type_t)); - } - - return 0; -} - -static const char * -hwloc_pci_class_string(unsigned short class_id) -{ - switch ((class_id & 0xff00) >> 8) { - case 0x00: - switch (class_id) { - case 0x0001: return "VGA"; - } - return "PCI"; - case 0x01: - switch (class_id) { - case 0x0100: return "SCSI"; - case 0x0101: return "IDE"; - case 0x0102: return "Flop"; - case 0x0103: return "IPI"; - case 0x0104: return "RAID"; - case 0x0105: return "ATA"; - case 0x0106: return "SATA"; - case 0x0107: return "SAS"; - case 0x0108: return "NVMExp"; - } - return "Stor"; - case 0x02: - switch (class_id) { - case 0x0200: return "Ether"; - case 0x0201: return "TokRn"; - case 0x0202: return "FDDI"; - case 0x0203: return "ATM"; - case 0x0204: return "ISDN"; - case 0x0205: return "WrdFip"; - case 0x0206: return "PICMG"; - case 0x0207: return "IB"; - case 0x0208: return "FI"; - } - return "Net"; - case 0x03: - switch (class_id) { - case 0x0300: return "VGA"; - case 0x0301: return "XGA"; - case 0x0302: return "3D"; - } - return "Disp"; - case 0x04: - switch (class_id) { - case 0x0400: return "Video"; - case 0x0401: return "Audio"; - case 0x0402: return "Phone"; - case 0x0403: return "Auddv"; - } - return "MM"; - case 0x05: - switch (class_id) { - case 0x0500: return "RAM"; - case 0x0501: return "Flash"; - } - return "Mem"; - case 0x06: - switch (class_id) { - case 0x0600: return "Host"; - case 0x0601: return "ISA"; - case 0x0602: return "EISA"; - case 0x0603: return "MC"; - case 0x0604: return "PCI_B"; - case 0x0605: return "PCMCIA"; - case 0x0606: return "Nubus"; - case 0x0607: return "CardBus"; - case 0x0608: return "RACEway"; - case 0x0609: return "PCI_SB"; - case 0x060a: return "IB_B"; - } - return "Bridg"; - case 0x07: - switch (class_id) { - case 0x0700: return "Ser"; - case 0x0701: return "Para"; - case 0x0702: return "MSer"; - case 0x0703: return "Modm"; - case 0x0704: return "GPIB"; - case 0x0705: return "SmrtCrd"; - } - return "Comm"; - case 0x08: - switch (class_id) { - case 0x0800: return "PIC"; - case 0x0801: return "DMA"; - case 0x0802: return "Time"; - case 0x0803: return "RTC"; - case 0x0804: return "HtPl"; - case 0x0805: return "SD-HtPl"; - case 0x0806: return "IOMMU"; - } - return "Syst"; - case 0x09: - switch (class_id) { - case 0x0900: return "Kbd"; - case 0x0901: return "Pen"; - case 0x0902: return "Mouse"; - case 0x0903: return "Scan"; - case 0x0904: return "Game"; - } - return "In"; - case 0x0a: - return "Dock"; - case 0x0b: - switch (class_id) { - case 0x0b00: return "386"; - case 0x0b01: return "486"; - case 0x0b02: return "Pent"; - case 0x0b10: return "Alpha"; - case 0x0b20: return "PPC"; - case 0x0b30: return "MIPS"; - case 0x0b40: return "CoProc"; - } - return "Proc"; - case 0x0c: - switch (class_id) { - case 0x0c00: return "Firw"; - case 0x0c01: return "ACCES"; - case 0x0c02: return "SSA"; - case 0x0c03: return "USB"; - case 0x0c04: return "Fibre"; - case 0x0c05: return "SMBus"; - case 0x0c06: return "IB"; - case 0x0c07: return "IPMI"; - case 0x0c08: return "SERCOS"; - case 0x0c09: return "CANBUS"; - } - return "Ser"; - case 0x0d: - switch (class_id) { - case 0x0d00: return "IRDA"; - case 0x0d01: return "IR"; - case 0x0d10: return "RF"; - case 0x0d11: return "Blueth"; - case 0x0d12: return "BroadB"; - case 0x0d20: return "802.1a"; - case 0x0d21: return "802.1b"; - } - return "Wifi"; - case 0x0e: - switch (class_id) { - case 0x0e00: return "I2O"; - } - return "Intll"; - case 0x0f: - switch (class_id) { - case 0x0f00: return "S-TV"; - case 0x0f01: return "S-Aud"; - case 0x0f02: return "S-Voice"; - case 0x0f03: return "S-Data"; - } - return "Satel"; - case 0x10: - return "Crypt"; - case 0x11: - return "Signl"; - case 0x12: - return "Accel"; - case 0x13: - return "Instr"; - case 0xff: - return "Oth"; - } - return "PCI"; -} - -static const char* hwloc_obj_cache_type_letter(hwloc_obj_cache_type_t type) -{ - switch (type) { - case HWLOC_OBJ_CACHE_UNIFIED: return ""; - case HWLOC_OBJ_CACHE_DATA: return "d"; - case HWLOC_OBJ_CACHE_INSTRUCTION: return "i"; - default: return "unknown"; - } -} - -int -hwloc_obj_type_snprintf(char * __hwloc_restrict string, size_t size, hwloc_obj_t obj, int verbose) -{ - hwloc_obj_type_t type = obj->type; - switch (type) { - case HWLOC_OBJ_MISC: - case HWLOC_OBJ_SYSTEM: - case HWLOC_OBJ_MACHINE: - case HWLOC_OBJ_NUMANODE: - case HWLOC_OBJ_PACKAGE: - case HWLOC_OBJ_CORE: - case HWLOC_OBJ_PU: - return hwloc_snprintf(string, size, "%s", hwloc_obj_type_string(type)); - case HWLOC_OBJ_CACHE: - return hwloc_snprintf(string, size, "L%u%s%s", obj->attr->cache.depth, - hwloc_obj_cache_type_letter(obj->attr->cache.type), - verbose ? hwloc_obj_type_string(type): ""); - case HWLOC_OBJ_GROUP: - /* TODO: more pretty presentation? */ - if (obj->attr->group.depth != (unsigned) -1) - return hwloc_snprintf(string, size, "%s%u", hwloc_obj_type_string(type), obj->attr->group.depth); - else - return hwloc_snprintf(string, size, "%s", hwloc_obj_type_string(type)); - case HWLOC_OBJ_BRIDGE: - if (verbose) - return snprintf(string, size, "Bridge %s->%s", - obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI ? "PCI" : "Host", - "PCI"); - else - return snprintf(string, size, obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI ? "PCIBridge" : "HostBridge"); - case HWLOC_OBJ_PCI_DEVICE: - return snprintf(string, size, "PCI %04x:%04x", - obj->attr->pcidev.vendor_id, obj->attr->pcidev.device_id); - case HWLOC_OBJ_OS_DEVICE: - switch (obj->attr->osdev.type) { - case HWLOC_OBJ_OSDEV_BLOCK: return hwloc_snprintf(string, size, "Block"); - case HWLOC_OBJ_OSDEV_NETWORK: return hwloc_snprintf(string, size, verbose ? "Network" : "Net"); - case HWLOC_OBJ_OSDEV_OPENFABRICS: return hwloc_snprintf(string, size, "OpenFabrics"); - case HWLOC_OBJ_OSDEV_DMA: return hwloc_snprintf(string, size, "DMA"); - case HWLOC_OBJ_OSDEV_GPU: return hwloc_snprintf(string, size, "GPU"); - case HWLOC_OBJ_OSDEV_COPROC: return hwloc_snprintf(string, size, verbose ? "Co-Processor" : "CoProc"); - default: - if (size > 0) - *string = '\0'; - return 0; - } - break; - default: - if (size > 0) - *string = '\0'; - return 0; - } -} - -int -hwloc_obj_attr_snprintf(char * __hwloc_restrict string, size_t size, hwloc_obj_t obj, const char * separator, int verbose) -{ - const char *prefix = ""; - char *tmp = string; - ssize_t tmplen = size; - int ret = 0; - int res; - - /* make sure we output at least an empty string */ - if (size) - *string = '\0'; - - /* print memory attributes */ - res = 0; - if (verbose) { - if (obj->memory.local_memory) - res = hwloc_snprintf(tmp, tmplen, "%slocal=%lu%s%stotal=%lu%s", - prefix, - (unsigned long) hwloc_memory_size_printf_value(obj->memory.local_memory, verbose), - hwloc_memory_size_printf_unit(obj->memory.total_memory, verbose), - separator, - (unsigned long) hwloc_memory_size_printf_value(obj->memory.total_memory, verbose), - hwloc_memory_size_printf_unit(obj->memory.local_memory, verbose)); - else if (obj->memory.total_memory) - res = hwloc_snprintf(tmp, tmplen, "%stotal=%lu%s", - prefix, - (unsigned long) hwloc_memory_size_printf_value(obj->memory.total_memory, verbose), - hwloc_memory_size_printf_unit(obj->memory.total_memory, verbose)); - } else { - if (obj->memory.local_memory) - res = hwloc_snprintf(tmp, tmplen, "%s%lu%s", - prefix, - (unsigned long) hwloc_memory_size_printf_value(obj->memory.local_memory, verbose), - hwloc_memory_size_printf_unit(obj->memory.local_memory, verbose)); - } - if (res < 0) - return -1; - ret += res; - if (ret > 0) - prefix = separator; - if (res >= tmplen) - res = tmplen>0 ? (int)tmplen - 1 : 0; - tmp += res; - tmplen -= res; - - /* printf type-specific attributes */ - res = 0; - switch (obj->type) { - case HWLOC_OBJ_CACHE: - if (verbose) { - char assoc[32]; - if (obj->attr->cache.associativity == -1) - snprintf(assoc, sizeof(assoc), "%sfully-associative", separator); - else if (obj->attr->cache.associativity == 0) - *assoc = '\0'; - else - snprintf(assoc, sizeof(assoc), "%sways=%d", separator, obj->attr->cache.associativity); - res = hwloc_snprintf(tmp, tmplen, "%ssize=%lu%s%slinesize=%u%s", - prefix, - (unsigned long) hwloc_memory_size_printf_value(obj->attr->cache.size, verbose), - hwloc_memory_size_printf_unit(obj->attr->cache.size, verbose), - separator, obj->attr->cache.linesize, - assoc); - } else - res = hwloc_snprintf(tmp, tmplen, "%s%lu%s", - prefix, - (unsigned long) hwloc_memory_size_printf_value(obj->attr->cache.size, verbose), - hwloc_memory_size_printf_unit(obj->attr->cache.size, verbose)); - break; - case HWLOC_OBJ_BRIDGE: - if (verbose) { - char up[128], down[64]; - /* upstream is PCI or HOST */ - if (obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI) { - char linkspeed[64]= ""; - if (obj->attr->pcidev.linkspeed) - snprintf(linkspeed, sizeof(linkspeed), "%slink=%.2fGB/s", separator, obj->attr->pcidev.linkspeed); - snprintf(up, sizeof(up), "busid=%04x:%02x:%02x.%01x%sid=%04x:%04x%sclass=%04x(%s)%s", - obj->attr->pcidev.domain, obj->attr->pcidev.bus, obj->attr->pcidev.dev, obj->attr->pcidev.func, separator, - obj->attr->pcidev.vendor_id, obj->attr->pcidev.device_id, separator, - obj->attr->pcidev.class_id, hwloc_pci_class_string(obj->attr->pcidev.class_id), linkspeed); - } else - *up = '\0'; - /* downstream is_PCI */ - snprintf(down, sizeof(down), "buses=%04x:[%02x-%02x]", - obj->attr->bridge.downstream.pci.domain, obj->attr->bridge.downstream.pci.secondary_bus, obj->attr->bridge.downstream.pci.subordinate_bus); - if (*up) - res = snprintf(string, size, "%s%s%s", up, separator, down); - else - res = snprintf(string, size, "%s", down); - } - break; - case HWLOC_OBJ_PCI_DEVICE: - if (verbose) { - char linkspeed[64]= ""; - char busid[16] = "[collapsed]"; - if (obj->attr->pcidev.linkspeed) - snprintf(linkspeed, sizeof(linkspeed), "%slink=%.2fGB/s", separator, obj->attr->pcidev.linkspeed); - if (!hwloc_obj_get_info_by_name(obj, "lstopoCollapse")) - snprintf(busid, sizeof(busid), "%04x:%02x:%02x.%01x", - obj->attr->pcidev.domain, obj->attr->pcidev.bus, obj->attr->pcidev.dev, obj->attr->pcidev.func); - res = snprintf(string, size, "busid=%s%sclass=%04x(%s)%s", - busid, separator, - obj->attr->pcidev.class_id, hwloc_pci_class_string(obj->attr->pcidev.class_id), linkspeed); - } - break; - default: - break; - } - if (res < 0) - return -1; - ret += res; - if (ret > 0) - prefix = separator; - if (res >= tmplen) - res = tmplen>0 ? (int)tmplen - 1 : 0; - tmp += res; - tmplen -= res; - - /* printf infos */ - if (verbose) { - unsigned i; - for(i=0; iinfos_count; i++) { - if (!strcmp(obj->infos[i].name, "lstopoCollapse")) - continue; - if (strchr(obj->infos[i].value, ' ')) - res = hwloc_snprintf(tmp, tmplen, "%s%s=\"%s\"", - prefix, - obj->infos[i].name, obj->infos[i].value); - else - res = hwloc_snprintf(tmp, tmplen, "%s%s=%s", - prefix, - obj->infos[i].name, obj->infos[i].value); - if (res < 0) - return -1; - ret += res; - if (res >= tmplen) - res = tmplen>0 ? (int)tmplen - 1 : 0; - tmp += res; - tmplen -= res; - if (ret > 0) - prefix = separator; - } - } - - return ret; -} - - -int -hwloc_obj_snprintf(char *string, size_t size, - struct hwloc_topology *topology __hwloc_attribute_unused, struct hwloc_obj *l, const char *_indexprefix, int verbose) -{ - const char *indexprefix = _indexprefix ? _indexprefix : "#"; - char os_index[12] = ""; - char type[64]; - char attr[128]; - int attrlen; - - if (l->os_index != (unsigned) -1) { - hwloc_snprintf(os_index, 12, "%s%u", indexprefix, l->os_index); - } - - hwloc_obj_type_snprintf(type, sizeof(type), l, verbose); - attrlen = hwloc_obj_attr_snprintf(attr, sizeof(attr), l, " ", verbose); - - if (attrlen > 0) - return hwloc_snprintf(string, size, "%s%s(%s)", type, os_index, attr); - else - return hwloc_snprintf(string, size, "%s%s", type, os_index); -} - -int hwloc_obj_cpuset_snprintf(char *str, size_t size, size_t nobj, struct hwloc_obj * const *objs) -{ - hwloc_bitmap_t set = hwloc_bitmap_alloc(); - int res; - unsigned i; - - hwloc_bitmap_zero(set); - for(i=0; icpuset) - hwloc_bitmap_or(set, set, objs[i]->cpuset); - - res = hwloc_bitmap_snprintf(str, size, set); - hwloc_bitmap_free(set); - return res; -} diff --git a/opal/mca/hwloc/hwloc1116/Makefile.am b/opal/mca/hwloc/hwloc2a/Makefile.am similarity index 77% rename from opal/mca/hwloc/hwloc1116/Makefile.am rename to opal/mca/hwloc/hwloc2a/Makefile.am index 74a1254f4f..49cc5325da 100644 --- a/opal/mca/hwloc/hwloc1116/Makefile.am +++ b/opal/mca/hwloc/hwloc2a/Makefile.am @@ -1,6 +1,6 @@ # # Copyright (c) 2011-2016 Cisco Systems, Inc. All rights reserved. -# Copyright (c) 2014-2015 Intel, Inc. All right reserved. +# Copyright (c) 2014-2017 Intel, Inc. All rights reserved. # Copyright (c) 2016 Los Alamos National Security, LLC. All rights # reserved. # Copyright (c) 2017 Research Organization for Information Science @@ -30,17 +30,17 @@ EXTRA_DIST = \ SUBDIRS = hwloc # Headers and sources -headers = hwloc1116.h -sources = hwloc1116_component.c +headers = hwloc2a.h +sources = hwloc2a_component.c # We only ever build this component statically -noinst_LTLIBRARIES = libmca_hwloc_hwloc1116.la -libmca_hwloc_hwloc1116_la_SOURCES = $(headers) $(sources) -nodist_libmca_hwloc_hwloc1116_la_SOURCES = $(nodist_headers) -libmca_hwloc_hwloc1116_la_LDFLAGS = -module -avoid-version $(opal_hwloc_hwloc1116_LDFLAGS) -libmca_hwloc_hwloc1116_la_LIBADD = $(opal_hwloc_hwloc1116_LIBS) -libmca_hwloc_hwloc1116_la_DEPENDENCIES = \ - $(HWLOC_top_builddir)/src/libhwloc_embedded.la +noinst_LTLIBRARIES = libmca_hwloc_hwloc2a.la +libmca_hwloc_hwloc2a_la_SOURCES = $(headers) $(sources) +nodist_libmca_hwloc_hwloc2a_la_SOURCES = $(nodist_headers) +libmca_hwloc_hwloc2a_la_LDFLAGS = -module -avoid-version $(opal_hwloc_hwloc2a_LDFLAGS) +libmca_hwloc_hwloc2a_la_LIBADD = $(opal_hwloc_hwloc2a_LIBS) +libmca_hwloc_hwloc2a_la_DEPENDENCIES = \ + $(HWLOC_top_builddir)/hwloc/libhwloc_embedded.la # Since the rest of the code base includes the underlying hwloc.h, we # also have to install the underlying header files when @@ -54,6 +54,8 @@ headers += \ hwloc/include/hwloc/cudart.h \ hwloc/include/hwloc/deprecated.h \ hwloc/include/hwloc/diff.h \ + hwloc/include/hwloc/distances.h \ + hwloc/include/hwloc/export.h \ hwloc/include/hwloc/gl.h \ hwloc/include/hwloc/helper.h \ hwloc/include/hwloc/inlines.h \ @@ -64,6 +66,7 @@ headers += \ hwloc/include/hwloc/openfabrics-verbs.h \ hwloc/include/hwloc/plugins.h \ hwloc/include/hwloc/rename.h \ + hwloc/include/hwloc/shmem.h \ hwloc/include/private/private.h \ hwloc/include/private/debug.h \ hwloc/include/private/misc.h \ @@ -76,6 +79,11 @@ headers += \ hwloc/include/hwloc/linux-libnuma.h endif HWLOC_HAVE_LINUX +if HWLOC_HAVE_SOLARIS +headers += \ + hwloc/include/private/solaris-chiptype.h +endif HWLOC_HAVE_SOLARIS + if HWLOC_HAVE_SCHED_SETAFFINITY headers += hwloc/include/hwloc/glibc-sched.h endif HWLOC_HAVE_SCHED_SETAFFINITY diff --git a/opal/mca/hwloc/hwloc2a/README-ompi.txt b/opal/mca/hwloc/hwloc2a/README-ompi.txt new file mode 100644 index 0000000000..a6acc981c7 --- /dev/null +++ b/opal/mca/hwloc/hwloc2a/README-ompi.txt @@ -0,0 +1 @@ +Cherry-picked commits after 2.0.0: diff --git a/opal/mca/hwloc/hwloc1116/configure.m4 b/opal/mca/hwloc/hwloc2a/configure.m4 similarity index 51% rename from opal/mca/hwloc/hwloc1116/configure.m4 rename to opal/mca/hwloc/hwloc2a/configure.m4 index fbb8bd24b1..d53fb10dc6 100644 --- a/opal/mca/hwloc/hwloc1116/configure.m4 +++ b/opal/mca/hwloc/hwloc2a/configure.m4 @@ -1,7 +1,7 @@ # -*- shell-script -*- # # Copyright (c) 2009-2017 Cisco Systems, Inc. All rights reserved -# Copyright (c) 2014-2015 Intel, Inc. All rights reserved. +# Copyright (c) 2014-2017 Intel, Inc. All rights reserved. # Copyright (c) 2015-2017 Research Organization for Information Science # and Technology (RIST). All rights reserved. # Copyright (c) 2016 Los Alamos National Security, LLC. All rights @@ -17,41 +17,43 @@ # # Priority # -AC_DEFUN([MCA_opal_hwloc_hwloc1116_PRIORITY], [90]) +AC_DEFUN([MCA_opal_hwloc_hwloc2a_PRIORITY], [90]) # # Force this component to compile in static-only mode # -AC_DEFUN([MCA_opal_hwloc_hwloc1116_COMPILE_MODE], [ +AC_DEFUN([MCA_opal_hwloc_hwloc2a_COMPILE_MODE], [ AC_MSG_CHECKING([for MCA component $2:$3 compile mode]) $4="static" AC_MSG_RESULT([$$4]) ]) # Include hwloc m4 files -m4_include(opal/mca/hwloc/hwloc1116/hwloc/config/hwloc.m4) -m4_include(opal/mca/hwloc/hwloc1116/hwloc/config/hwloc_pkg.m4) -m4_include(opal/mca/hwloc/hwloc1116/hwloc/config/hwloc_check_attributes.m4) -m4_include(opal/mca/hwloc/hwloc1116/hwloc/config/hwloc_check_visibility.m4) -m4_include(opal/mca/hwloc/hwloc1116/hwloc/config/hwloc_check_vendor.m4) -m4_include(opal/mca/hwloc/hwloc1116/hwloc/config/hwloc_components.m4) +m4_include(opal/mca/hwloc/hwloc2a/hwloc/config/hwloc.m4) +m4_include(opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_pkg.m4) +m4_include(opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_check_attributes.m4) +m4_include(opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_check_visibility.m4) +m4_include(opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_check_vendor.m4) +m4_include(opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_components.m4) +m4_include(opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_internal.m4) +m4_include(opal/mca/hwloc/hwloc2a/hwloc/config/netloc.m4) -# MCA_hwloc_hwloc1116_POST_CONFIG() +# MCA_hwloc_hwloc2a_POST_CONFIG() # --------------------------------- -AC_DEFUN([MCA_opal_hwloc_hwloc1116_POST_CONFIG],[ - OPAL_VAR_SCOPE_PUSH([opal_hwloc_hwloc1116_basedir]) +AC_DEFUN([MCA_opal_hwloc_hwloc2a_POST_CONFIG],[ + OPAL_VAR_SCOPE_PUSH([opal_hwloc_hwloc2a_basedir]) # If we won, then do all the rest of the setup - AS_IF([test "$1" = "1" && test "$opal_hwloc_hwloc1116_support" = "yes"], + AS_IF([test "$1" = "1" && test "$opal_hwloc_hwloc2a_support" = "yes"], [ # Set this variable so that the framework m4 knows what # file to include in opal/mca/hwloc/hwloc-internal.h - opal_hwloc_hwloc1116_basedir=opal/mca/hwloc/hwloc1116 - opal_hwloc_base_include="$opal_hwloc_hwloc1116_basedir/hwloc1116.h" + opal_hwloc_hwloc2a_basedir=opal/mca/hwloc/hwloc2a + opal_hwloc_base_include="$opal_hwloc_hwloc2a_basedir/hwloc2a.h" # Add some stuff to CPPFLAGS so that the rest of the source # tree can be built - file=$opal_hwloc_hwloc1116_basedir/hwloc + file=$opal_hwloc_hwloc2a_basedir/hwloc CPPFLAGS="-I$OPAL_TOP_SRCDIR/$file/include $CPPFLAGS" AS_IF([test "$OPAL_TOP_BUILDDIR" != "$OPAL_TOP_SRCDIR"], [CPPFLAGS="-I$OPAL_TOP_BUILDDIR/$file/include $CPPFLAGS"]) @@ -64,40 +66,41 @@ AC_DEFUN([MCA_opal_hwloc_hwloc1116_POST_CONFIG],[ ])dnl -# MCA_hwloc_hwloc1116_CONFIG([action-if-found], [action-if-not-found]) +# MCA_hwloc_hwloc2a_CONFIG([action-if-found], [action-if-not-found]) # -------------------------------------------------------------------- -AC_DEFUN([MCA_opal_hwloc_hwloc1116_CONFIG],[ +AC_DEFUN([MCA_opal_hwloc_hwloc2a_CONFIG],[ # Hwloc needs to know if we have Verbs support AC_REQUIRE([OPAL_CHECK_VERBS_DIR]) - AC_CONFIG_FILES([opal/mca/hwloc/hwloc1116/Makefile]) + AC_CONFIG_FILES([opal/mca/hwloc/hwloc2a/Makefile]) - OPAL_VAR_SCOPE_PUSH([HWLOC_VERSION opal_hwloc_hwloc1116_save_CPPFLAGS opal_hwloc_hwloc1116_save_LDFLAGS opal_hwloc_hwloc1116_save_LIBS opal_hwloc_hwloc1116_save_cairo opal_hwloc_hwloc1116_save_xml opal_hwloc_hwloc1116_basedir opal_hwloc_hwloc1116_file opal_hwloc_hwloc1116_save_cflags CPPFLAGS_save LIBS_save opal_hwloc_external]) + OPAL_VAR_SCOPE_PUSH([HWLOC_VERSION opal_hwloc_hwloc2a_save_CPPFLAGS opal_hwloc_hwloc2a_save_LDFLAGS opal_hwloc_hwloc2a_save_LIBS opal_hwloc_hwloc2a_save_cairo opal_hwloc_hwloc2a_save_xml opal_hwloc_hwloc2a_save_mode opal_hwloc_hwloc2a_basedir opal_hwloc_hwloc2a_file opal_hwloc_hwloc2a_save_cflags CPPFLAGS_save LIBS_save opal_hwloc_external]) # default to this component not providing support - opal_hwloc_hwloc1116_basedir=opal/mca/hwloc/hwloc1116 - opal_hwloc_hwloc1116_support=no + opal_hwloc_hwloc2a_basedir=opal/mca/hwloc/hwloc2a + opal_hwloc_hwloc2a_support=no AS_IF([test "$with_hwloc" = "internal" || test -z "$with_hwloc" || test "$with_hwloc" = "yes"], [opal_hwloc_external="no"], [opal_hwloc_external="yes"]) - opal_hwloc_hwloc1116_save_CPPFLAGS=$CPPFLAGS - opal_hwloc_hwloc1116_save_LDFLAGS=$LDFLAGS - opal_hwloc_hwloc1116_save_LIBS=$LIBS + opal_hwloc_hwloc2a_save_CPPFLAGS=$CPPFLAGS + opal_hwloc_hwloc2a_save_LDFLAGS=$LDFLAGS + opal_hwloc_hwloc2a_save_LIBS=$LIBS # Run the hwloc configuration - if no external hwloc, then set the prefixi # to minimize the chance that someone will use the internal symbols AS_IF([test "$opal_hwloc_external" = "no" && test "$with_hwloc" != "future"], - [HWLOC_SET_SYMBOL_PREFIX([opal_hwloc1116_])]) + [HWLOC_SET_SYMBOL_PREFIX([opal_hwloc2a_])]) # save XML or graphical options - opal_hwloc_hwloc1116_save_cairo=$enable_cairo - opal_hwloc_hwloc1116_save_xml=$enable_xml - opal_hwloc_hwloc1116_save_static=$enable_static - opal_hwloc_hwloc1116_save_shared=$enable_shared - opal_hwloc_hwloc1116_save_plugins=$enable_plugins + opal_hwloc_hwloc2a_save_cairo=$enable_cairo + opal_hwloc_hwloc2a_save_xml=$enable_xml + opal_hwloc_hwloc2a_save_static=$enable_static + opal_hwloc_hwloc2a_save_shared=$enable_shared + opal_hwloc_hwloc2a_save_plugins=$enable_plugins + opal_hwloc_hwloc2a_save_mode=$hwloc_mode # never enable hwloc's graphical option enable_cairo=no @@ -112,28 +115,31 @@ AC_DEFUN([MCA_opal_hwloc_hwloc1116_CONFIG],[ enable_libxml2=no enable_xml=yes + # ensure we are in "embedded" mode + hwloc_mode=embedded + # Disable NVML support if CUDA support is not built AS_IF([test "$opal_check_cuda_happy" != "yes"], [enable_nvml=no]) # hwloc checks for compiler visibility, and its needs to do # this without "picky" flags. - opal_hwloc_hwloc1116_save_cflags=$CFLAGS + opal_hwloc_hwloc2a_save_cflags=$CFLAGS CFLAGS=$OPAL_CFLAGS_BEFORE_PICKY AS_IF([test -n "$opal_datatype_cuda_CPPFLAGS"], [CPPFLAGS="$CPPFLAGS $opal_datatype_cuda_CPPFLAGS"]) - HWLOC_SETUP_CORE([opal/mca/hwloc/hwloc1116/hwloc], + HWLOC_SETUP_CORE([opal/mca/hwloc/hwloc2a/hwloc], [AC_MSG_CHECKING([whether hwloc configure succeeded]) AC_MSG_RESULT([yes]) - HWLOC_VERSION="internal v`$srcdir/$opal_hwloc_hwloc1116_basedir/hwloc/config/hwloc_get_version.sh $srcdir/$opal_hwloc_hwloc1116_basedir/hwloc/VERSION`" + HWLOC_VERSION="internal v`$srcdir/$opal_hwloc_hwloc2a_basedir/hwloc/config/hwloc_get_version.sh $srcdir/$opal_hwloc_hwloc2a_basedir/hwloc/VERSION`" # Build flags for our Makefile.am - opal_hwloc_hwloc1116_LDFLAGS='$(HWLOC_EMBEDDED_LDFLAGS)' - opal_hwloc_hwloc1116_LIBS='$(OPAL_TOP_BUILDDIR)/'"$opal_hwloc_hwloc1116_basedir"'/hwloc/src/libhwloc_embedded.la $(HWLOC_EMBEDDED_LIBS)' - opal_hwloc_hwloc1116_support=yes + opal_hwloc_hwloc2a_LDFLAGS='$(HWLOC_EMBEDDED_LDFLAGS)' + opal_hwloc_hwloc2a_LIBS='$(OPAL_TOP_BUILDDIR)/'"$opal_hwloc_hwloc2a_basedir"'/hwloc/hwloc/libhwloc_embedded.la $(HWLOC_EMBEDDED_LIBS)' + opal_hwloc_hwloc2a_support=yes - AC_DEFINE_UNQUOTED([HWLOC_HWLOC1116_HWLOC_VERSION], + AC_DEFINE_UNQUOTED([HWLOC_HWLOC2a_HWLOC_VERSION], ["$HWLOC_VERSION"], [Version of hwloc]) @@ -146,35 +152,35 @@ AC_DEFUN([MCA_opal_hwloc_hwloc1116_CONFIG],[ ], [AC_MSG_CHECKING([whether hwloc configure succeeded]) AC_MSG_RESULT([no]) - opal_hwloc_hwloc1116_support=no]) - CFLAGS=$opal_hwloc_hwloc1116_save_cflags + opal_hwloc_hwloc2a_support=no]) + CFLAGS=$opal_hwloc_hwloc2a_save_cflags # Restore some env variables, if necessary - AS_IF([test -n "$opal_hwloc_hwloc1116_save_cairo"], - [enable_cairo=$opal_hwloc_hwloc1116_save_cairo]) - AS_IF([test -n "$opal_hwloc_hwloc1116_save_xml"], - [enable_xml=$opal_hwloc_hwloc1116_save_xml]) - AS_IF([test -n "$opal_hwloc_hwloc1116_save_static"], - [enable_static=$opal_hwloc_hwloc1116_save_static]) - AS_IF([test -n "$opal_hwloc_hwloc1116_save_shared"], - [enable_shared=$opal_hwloc_hwloc1116_save_shared]) - AS_IF([test -n "$opal_hwloc_hwloc1116_save_plugins"], - [enable_plugins=$opal_hwloc_hwloc1116_save_shared]) + AS_IF([test -n "$opal_hwloc_hwloc2a_save_cairo"], + [enable_cairo=$opal_hwloc_hwloc2a_save_cairo]) + AS_IF([test -n "$opal_hwloc_hwloc2a_save_xml"], + [enable_xml=$opal_hwloc_hwloc2a_save_xml]) + AS_IF([test -n "$opal_hwloc_hwloc2a_save_static"], + [enable_static=$opal_hwloc_hwloc2a_save_static]) + AS_IF([test -n "$opal_hwloc_hwloc2a_save_shared"], + [enable_shared=$opal_hwloc_hwloc2a_save_shared]) + AS_IF([test -n "$opal_hwloc_hwloc2a_save_plugins"], + [enable_plugins=$opal_hwloc_hwloc2a_save_shared]) - CPPFLAGS=$opal_hwloc_hwloc1116_save_CPPFLAGS - LDFLAGS=$opal_hwloc_hwloc1116_save_LDFLAGS - LIBS=$opal_hwloc_hwloc1116_save_LIBS + CPPFLAGS=$opal_hwloc_hwloc2a_save_CPPFLAGS + LDFLAGS=$opal_hwloc_hwloc2a_save_LDFLAGS + LIBS=$opal_hwloc_hwloc2a_save_LIBS - AC_SUBST([opal_hwloc_hwloc1116_CFLAGS]) - AC_SUBST([opal_hwloc_hwloc1116_CPPFLAGS]) - AC_SUBST([opal_hwloc_hwloc1116_LDFLAGS]) - AC_SUBST([opal_hwloc_hwloc1116_LIBS]) + AC_SUBST([opal_hwloc_hwloc2a_CFLAGS]) + AC_SUBST([opal_hwloc_hwloc2a_CPPFLAGS]) + AC_SUBST([opal_hwloc_hwloc2a_LDFLAGS]) + AC_SUBST([opal_hwloc_hwloc2a_LIBS]) # Finally, add some flags to the wrapper compiler so that our # headers can be found. - hwloc_hwloc1116_WRAPPER_EXTRA_LDFLAGS="$HWLOC_EMBEDDED_LDFLAGS" - hwloc_hwloc1116_WRAPPER_EXTRA_LIBS="$HWLOC_EMBEDDED_LIBS" - hwloc_hwloc1116_WRAPPER_EXTRA_CPPFLAGS='-I${pkgincludedir}/'"$opal_hwloc_hwloc1116_basedir/hwloc/include" + hwloc_hwloc2a_WRAPPER_EXTRA_LDFLAGS="$HWLOC_EMBEDDED_LDFLAGS" + hwloc_hwloc2a_WRAPPER_EXTRA_LIBS="$HWLOC_EMBEDDED_LIBS" + hwloc_hwloc2a_WRAPPER_EXTRA_CPPFLAGS='-I${pkgincludedir}/'"$opal_hwloc_hwloc2a_basedir/hwloc/include" # If we are not building the internal hwloc, then indicate that # this component should not be built. NOTE: we still did all the @@ -184,12 +190,12 @@ AC_DEFUN([MCA_opal_hwloc_hwloc1116_CONFIG],[ # distclean" infrastructure to work properly). AS_IF([test "$opal_hwloc_external" = "yes"], [AC_MSG_WARN([using an external hwloc; disqualifying this component]) - opal_hwloc_hwloc1116_support=no], + opal_hwloc_hwloc2a_support=no], [AC_DEFINE([HAVE_DECL_HWLOC_OBJ_OSDEV_COPROC], [1]) AC_DEFINE([HAVE_HWLOC_TOPOLOGY_DUP], [1])]) # Done! - AS_IF([test "$opal_hwloc_hwloc1116_support" = "yes"], + AS_IF([test "$opal_hwloc_hwloc2a_support" = "yes"], [$1], [$2]) diff --git a/opal/mca/hwloc/hwloc2a/hwloc/AUTHORS b/opal/mca/hwloc/hwloc2a/hwloc/AUTHORS new file mode 100644 index 0000000000..740de337b2 --- /dev/null +++ b/opal/mca/hwloc/hwloc2a/hwloc/AUTHORS @@ -0,0 +1,29 @@ +netloc Authors +============== + +The following cumulative list contains the names of most individuals who +have committed code to the hwloc repository. + +Name Affiliation(s) +--------------------------- -------------------- +Cédric Augonnet University of Bordeaux +Guillaume Beauchamp Inria +Ahmad Boissetri Binzagr Inria +Cyril Bordage Inria +Nicholas Buroker UWL +Jérôme Clet-Ortega University of Bordeaux +Ludovic Courtès Inria +Nathalie Furmento CNRS +Brice Goglin Inria +Joshua Hursey UWL +Alexey Kardashevskiy IBM +Douglas MacFarland UWL +Antoine Rougier intern from University of Bordeaux +Jeff Squyres Cisco +Samuel Thibault University of Bordeaux + +Affiliaion abbreviations: +------------------------- +Cisco = Cisco Systems, Inc. +CNRS = Centre national de la recherche scientifique (France) +UWL = University of Wisconsin-La Crosse diff --git a/opal/mca/hwloc/hwloc1116/hwloc/COPYING b/opal/mca/hwloc/hwloc2a/hwloc/COPYING similarity index 96% rename from opal/mca/hwloc/hwloc1116/hwloc/COPYING rename to opal/mca/hwloc/hwloc2a/hwloc/COPYING index 485798f705..e77516e180 100644 --- a/opal/mca/hwloc/hwloc1116/hwloc/COPYING +++ b/opal/mca/hwloc/hwloc2a/hwloc/COPYING @@ -11,6 +11,7 @@ Copyright © 2010 IBM Copyright © 2010 Jirka Hladky Copyright © 2012 Aleksej Saushev, The NetBSD Foundation Copyright © 2012 Blue Brain Project, EPFL. All rights reserved. +Copyright © 2013-2014 University of Wisconsin-La Crosse. All rights reserved. Copyright © 2015 Research Organization for Information Science and Technology (RIST). All rights reserved. Copyright © 2015-2016 Intel, Inc. All rights reserved. See COPYING in top-level directory. diff --git a/opal/mca/hwloc/hwloc1116/hwloc/Makefile.am b/opal/mca/hwloc/hwloc2a/hwloc/Makefile.am similarity index 82% rename from opal/mca/hwloc/hwloc1116/hwloc/Makefile.am rename to opal/mca/hwloc/hwloc2a/hwloc/Makefile.am index b92ff287de..3aa78ab251 100644 --- a/opal/mca/hwloc/hwloc1116/hwloc/Makefile.am +++ b/opal/mca/hwloc/hwloc2a/hwloc/Makefile.am @@ -7,9 +7,23 @@ # via AC_CONFIG_MACRO_DIR in configure.ac. ACLOCAL_AMFLAGS = -I ./config -SUBDIRS = src include +# +# "make distcheck" requires that tarballs are able to be able to "make +# dist", so we have to include config/distscript.sh. +# +EXTRA_DIST = \ + README VERSION COPYING AUTHORS \ + config/hwloc_get_version.sh \ + config/distscript.sh + +SUBDIRS = include hwloc + +if BUILD_NETLOC +SUBDIRS += netloc +endif + if HWLOC_BUILD_STANDALONE -SUBDIRS += utils tests contrib/systemd +SUBDIRS += utils tests contrib/systemd contrib/misc # We need doc/ if HWLOC_BUILD_DOXYGEN, or during make install if HWLOC_INSTALL_DOXYGEN. # There's no INSTALL_SUBDIRS, so always enter doc/ and check HWLOC_BUILD/INSTALL_DOXYGEN there SUBDIRS += doc @@ -23,23 +37,25 @@ DIST_SUBDIRS = $(SUBDIRS) if HWLOC_BUILD_STANDALONE pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = hwloc.pc -endif +if BUILD_NETLOC +# JMS Need to compare hwloc.pc and netloc.pc -- I think netloc.pc is +# missing some things. +# pkgconfig_DATA += netloc.pc Disabled until the netloc API is public +EXTRA_DIST += netloc.pc +if BUILD_NETLOCSCOTCH +pkgconfig_DATA += netlocscotch.pc +endif BUILD_NETLOCSCOTCH +endif BUILD_NETLOC +endif HWLOC_BUILD_STANDALONE -# Only install the valgrind suppressions file if we're building in standalone mode +# Only install the valgrind suppressions file if we're building in +# standalone mode if HWLOC_BUILD_STANDALONE dist_pkgdata_DATA = contrib/hwloc-valgrind.supp endif -# -# "make distcheck" requires that tarballs are able to be able to "make -# dist", so we have to include config/distscript.sh. -# -EXTRA_DIST = \ - README VERSION COPYING AUTHORS \ - config/hwloc_get_version.sh \ - config/distscript.sh - -# Only install entire visual studio subdirectory if we're building in standalone mode +# Only install entire visual studio subdirectory if we're building in +# standalone mode if HWLOC_BUILD_STANDALONE EXTRA_DIST += contrib/windows endif @@ -49,15 +65,6 @@ dist-hook: sh "$(top_srcdir)/config/distscript.sh" "$(top_srcdir)" "$(distdir)" "$(HWLOC_VERSION)" endif HWLOC_BUILD_STANDALONE -# -# Build the documenation and top-level README file -# -if HWLOC_BUILD_STANDALONE -.PHONY: doc readme -doc readme: - $(MAKE) -C doc -endif HWLOC_BUILD_STANDALONE - if HWLOC_BUILD_STANDALONE if HWLOC_HAVE_WINDOWS # @@ -71,3 +78,12 @@ uninstall-local: rm -f $(DESTDIR)$(prefix)/README.txt $(DESTDIR)$(prefix)/NEWS.txt $(DESTDIR)$(prefix)/COPYING.txt endif HWLOC_HAVE_WINDOWS endif HWLOC_BUILD_STANDALONE + +# +# Build the documenation and top-level README file +# +if HWLOC_BUILD_STANDALONE +.PHONY: doc readme +doc readme: + $(MAKE) -C doc +endif HWLOC_BUILD_STANDALONE diff --git a/opal/mca/hwloc/hwloc1116/hwloc/NEWS b/opal/mca/hwloc/hwloc2a/hwloc/NEWS similarity index 89% rename from opal/mca/hwloc/hwloc1116/hwloc/NEWS rename to opal/mca/hwloc/hwloc2a/hwloc/NEWS index 97f53fb705..e64c22cb8e 100644 --- a/opal/mca/hwloc/hwloc1116/hwloc/NEWS +++ b/opal/mca/hwloc/hwloc2a/hwloc/NEWS @@ -3,6 +3,7 @@ Copyright © 2009-2017 Inria. All rights reserved. Copyright © 2009-2013 Université Bordeaux Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved. +Copyright (c) 2017 Intel, Inc. All rights reserved. $COPYRIGHT$ Additional copyrights may follow @@ -17,6 +18,138 @@ bug fixes (and other actions) for each version of hwloc since version in v0.9.1). +Version 2.0.0 +------------- +* The ABI of the library has changed. For instance some hwloc_obj fields + were reordered. + - HWLOC_API_VERSION and hwloc_get_api_version() now give 0x00020000. + - See "How do I handle ABI breaks and API upgrades ?" in the FAQ + and https://github.com/open-mpi/hwloc/wiki/Upgrading-to-v2.0-API +* Major changes + + Topologies always have at least one NUMA object. On non-NUMA machines, + a single NUMA object is added to describe the entire machine memory. + The NUMA level cannot be ignored anymore. + + The HWLOC_OBJ_CACHE type is replaced with 8 types HWLOC_OBJ_L[1-5]CACHE + and HWLOC_OBJ_L[1-3]ICACHE that remove the need to disambiguate levels + when looking for caches with _by_type() functions. + - New hwloc_obj_type_is_{,d,i}cache() functions may be used to check whether + a given type is a cache. + + Replace hwloc_topology_ignore*() functions with hwloc_topology_set_type_filter() + and hwloc_topology_set_all_types_filter(). + - Contrary to hwloc_topology_ignore_{type,all}_keep_structure() which + removed individual objects, HWLOC_TYPE_FILTER_KEEP_STRUCTURE only removes + entire levels (so that topology do not become too asymmetric). + + Remove HWLOC_TOPOLOGY_FLAG_ICACHES in favor of hwloc_topology_set_icache_types_filter() + with HWLOC_TYPE_FILTER_KEEP_ALL. + + Remove HWLOC_TOPOLOGY_FLAG_IO_DEVICES, _IO_BRIDGES and _WHOLE_IO in favor of + hwloc_topology_set_io_types_filter() with HWLOC_TYPE_FILTER_KEEP_ALL or + HWLOC_TYPE_FILTER_KEEP_IMPORTANT. + + hwloc_topology_restrict() doesn't remove objects that contain memory + by default anymore. + - The list of existing restrict flags was modified. + + XML export functions take an additional flags argument, + for instance for exporting XMLs that are compatible with hwloc 1.x. + + The distance API has been completely reworked. It is now described + in hwloc/distances.h. + + Add the experimental netloc subproject. It is enabled by default when + supported and can be disabled with --disable-netloc. + It currently brings command-line tools to gather and visualize the + topology of InfiniBand fabrics, and an API to convert such topologies + into Scotch architectures for process mapping. + See the documentation for details. + + Remove the online_cpuset from struct hwloc_obj. Offline PUs get unknown + topologies on Linux nowadays, and wrong topology on Solaris. Other OS + do not support them. And one cannot do much about them anyway. Just keep + them in complete_cpuset. + + Remove the custom interface for assembling the topologies of different + nodes as well as the hwloc-assembler tools. + + Remove Kerrighed support from the Linux backend. + + Remove Tru64 (OSF/1) support. + - Remove HWLOC_MEMBIND_REPLICATE which wasn't available anywhere else. +* API + + Objects now have a "subtype" field that supersedes former "Type" and + "CoProcType" info attributes. + + The almost-unused "os_level" attribute has been removed from the + hwloc_obj structure. + + I/O and Misc objects are now stored in a dedicated children list, only + normal children with non-NULL cpusets and nodesets are in the main + children list. + - hwloc_get_next_child() may still be used to iterate over these 3 lists + of children at once. + + Replace hwloc_topology_insert_misc_object_by_cpuset() with + hwloc_topology_insert_group_object() to precisely specify the location + of an additional hierarchy level in the topology. + + Misc objects have their own level and depth to iterate over all of them. + + Misc objects may now only be inserted as a leaf object with + hwloc_topology_insert_misc_object() which deprecates + hwloc_topology_insert_misc_object_by_parent(). + + hwloc_topology_set_fsroot() is removed, the environment variable + HWLOC_FSROOT may be used for the same remote testing/debugging purpose. + + hwloc_type_sscanf() deprecates the old hwloc_obj_type_sscanf(). + + hwloc_type_sscanf_as_depth() is added to convert a type name into + a level depth. + + hwloc_type_name() deprecates the old hwloc_obj_type_string(). + + Remove the deprecated hwloc_obj_snprintf(), hwloc_obj_type_of_string(), + hwloc_distribute[v](). + + hwloc_obj_cpuset_snprintf() is deprecated in favor of hwloc_bitmap_snprintf(). + + Functions diff_load_xml*(), diff_export_xml*() and diff_destroy() in + hwloc/diff.h do not need a topology as first parameter anymore. + + hwloc_parse_cpumap_file () superseded by hwloc_linux_read_path_as_cpumask() + in hwloc/linux.h. +* Tools + - lstopo and hwloc-info have a new --filter option matching the new filtering API. + - hwloc-distances was removed and replaced with lstopo --distances. +* Plugin API + + hwloc_fill_object_sets() is renamed into hwloc_obj_add_children_sets(). +* Misc + + Linux OS devices do not have to be attached through PCI anymore, + for instance enabling the discovery of NVDIMM block devices. + + Add a SectorSize attribute to block OS devices on Linux. + + Misc MemoryModule objects are only added when full I/O discovery is enabled + (WHOLE_IO topology flag). + + Do not set PCI devices and bridges name automatically. Vendor and device + names are already in info attributes. + + Exporting to synthetic now ignores I/O and Misc objects. + + XML and Synthetic export functions have moved to hwloc/export.h, + automatically included from hwloc.h. + + Separate OS device discovery from PCI discovery. Only the latter is disabled + with --disable-pci at configure time. Both may be disabled with --disable-io. + + The old `libpci' component name from hwloc 1.6 is not supported anymore, + only the `pci' name from hwloc 1.7 is now recognized. + + The `linuxpci' component is now renamed into `linuxio'. + + The HWLOC_PCI___LOCALCPUS environment variables are superseded + with a single HWLOC_PCI_LOCALITY where bus ranges may be specified. + + Add HWLOC_SYNTHETIC environment variable to enforce a synthetic topology + as if hwloc_topology_set_synthetic() had been called. + + HWLOC_COMPONENTS doesn't support xml or synthetic component attributes + anymore, they should be passed in HWLOC_XMLFILE or HWLOC_SYNTHETIC instead. + + HWLOC_COMPONENTS takes precedence over other environment variables + for selecting components. + + Remove the dependency on libnuma on Linux. + + +Version 1.11.7 +-------------- +* Fix hwloc-bind --membind for CPU-less NUMA nodes (again). + Thanks to Gilles Gouaillardet for reporting the issue. +* Fix a memory leak on IBM S/390 platforms running Linux. +* Fix a memory leak when forcing the x86 backend first on amd64/topoext + platforms running Linux. +* Command-line tools now support "hbm" instead "numanode" for filtering + only high-bandwidth memory nodes when selecting locations. + + hwloc-bind also support --hbm and --no-hbm for filtering only or + no HBM nodes. + Thanks to Nicolas Denoyelle for the suggestion. +* Add --children and --descendants to hwloc-info for listing object + children or object descendants of a specific type. +* Add --no-index, --index, --no-attrs, --attrs to disable/enable display + of index numbers or attributes in the graphical lstopo output. +* Try to gather hwloc-dump-hwdata output from all possible locations + in hwloc-gather-topology. +* Updates to the documentation of locations in hwloc(7) and + command-line tools manpages. + + Version 1.11.6 -------------- * Make the Linux discovery about twice faster, especially on the CPU side, diff --git a/opal/mca/hwloc/hwloc2a/hwloc/README b/opal/mca/hwloc/hwloc2a/hwloc/README new file mode 100644 index 0000000000..eadf3bc6a0 --- /dev/null +++ b/opal/mca/hwloc/hwloc2a/hwloc/README @@ -0,0 +1,65 @@ +Introduction + +The Hardware Locality (hwloc) software project aims at easing the process of +discovering hardware resources in parallel architectures. It offers +command-line tools and a C API for consulting these resources, their locality, +attributes, and interconnection. hwloc primarily aims at helping +high-performance computing (HPC) applications, but is also applicable to any +project seeking to exploit code and/or data locality on modern computing +platforms. + +hwloc is actually made of two subprojects distributed together: + + * The original hwloc project for describing the internals of computing nodes. + It is described in details between sections Hardware Locality (hwloc) + Introduction and Network Locality (netloc). + * The network-oriented companion called netloc (Network Locality), described + in details starting at section Network Locality (netloc). Netloc may be + disabled, but the original hwloc cannot. Both hwloc and netloc APIs are + documented after these sections. + +Installation + +hwloc (http://www.open-mpi.org/projects/hwloc/) is available under the BSD +license. It is hosted as a sub-project of the overall Open MPI project (http:// +www.open-mpi.org/). Note that hwloc does not require any functionality from +Open MPI -- it is a wholly separate (and much smaller!) project and code base. +It just happens to be hosted as part of the overall Open MPI project. + +Nightly development snapshots are available on the web site. Additionally, the +code can be directly cloned from Git: + +shell$ git clone https://github.com/open-mpi/hwloc.git +shell$ cd hwloc +shell$ ./autogen.sh + +Note that GNU Autoconf >=2.63, Automake >=1.11 and Libtool >=2.2.6 are required +when building from a Git clone. + +Installation by itself is the fairly common GNU-based process: + +shell$ ./configure --prefix=... +shell$ make +shell$ make install + +hwloc- and netloc-specific configure options and requirements are documented in +sections hwloc Installation and Netloc Installation respectively. + +Also note that if you install supplemental libraries in non-standard locations, +hwloc's configure script may not be able to find them without some help. You +may need to specify additional CPPFLAGS, LDFLAGS, or PKG_CONFIG_PATH values on +the configure command line. + +For example, if libpciaccess was installed into /opt/pciaccess, hwloc's +configure script may not find it be default. Try adding PKG_CONFIG_PATH to the +./configure command line, like this: + +./configure PKG_CONFIG_PATH=/opt/pciaccess/lib/pkgconfig ... + +Running the "lstopo" tool is a good way to check as a graphical output whether +hwloc properly detected the architecture of your node. Netloc command-line +tools can be used to display the network topology interconnecting your nodes. + + + +See https://www.open-mpi.org/projects/hwloc/doc/ for more hwloc documentation. diff --git a/opal/mca/hwloc/hwloc1116/hwloc/VERSION b/opal/mca/hwloc/hwloc2a/hwloc/VERSION similarity index 94% rename from opal/mca/hwloc/hwloc1116/hwloc/VERSION rename to opal/mca/hwloc/hwloc2a/hwloc/VERSION index 5146cf2179..3c78a59a0b 100644 --- a/opal/mca/hwloc/hwloc1116/hwloc/VERSION +++ b/opal/mca/hwloc/hwloc2a/hwloc/VERSION @@ -7,9 +7,9 @@ # Please update HWLOC_VERSION in contrib/windows/private_config.h too. -major=1 -minor=11 -release=6 +major=2 +minor=0 +release=0 # greek is used for alpha or beta release tags. If it is non-empty, # it will be appended to the version number. It does not have to be @@ -22,7 +22,7 @@ greek= # The date when this release was created -date="Feb 23, 2017" +date="Jul 21, 2017" # If snapshot=1, then use the value from snapshot_version as the # entire hwloc version (i.e., ignore major, minor, release, and @@ -41,6 +41,7 @@ snapshot_version=${major}.${minor}.${release}${greek}-git # 2. Version numbers are described in the Libtool current:revision:age # format. -libhwloc_so_version=12:3:7 +libhwloc_so_version=0:0:0 +libnetloc_so_version=0:0:0 # Please also update the lines in contrib/windows/libhwloc.vcxproj diff --git a/opal/mca/hwloc/hwloc1116/hwloc/config/distscript.sh b/opal/mca/hwloc/hwloc2a/hwloc/config/distscript.sh similarity index 98% rename from opal/mca/hwloc/hwloc1116/hwloc/config/distscript.sh rename to opal/mca/hwloc/hwloc2a/hwloc/config/distscript.sh index d72a3fd305..07571a00e0 100755 --- a/opal/mca/hwloc/hwloc1116/hwloc/config/distscript.sh +++ b/opal/mca/hwloc/hwloc2a/hwloc/config/distscript.sh @@ -12,6 +12,7 @@ # All rights reserved. # Copyright © 2010-2014 Inria. All rights reserved. # Copyright © 2009-2014 Cisco Systems, Inc. All rights reserved. +# Copyright (c) 2017 Intel, Inc. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow diff --git a/opal/mca/hwloc/hwloc1116/hwloc/config/hwloc.m4 b/opal/mca/hwloc/hwloc2a/hwloc/config/hwloc.m4 similarity index 92% rename from opal/mca/hwloc/hwloc1116/hwloc/config/hwloc.m4 rename to opal/mca/hwloc/hwloc2a/hwloc/config/hwloc.m4 index 5c0e4df7c0..b086e7c79b 100644 --- a/opal/mca/hwloc/hwloc1116/hwloc/config/hwloc.m4 +++ b/opal/mca/hwloc/hwloc2a/hwloc/config/hwloc.m4 @@ -179,7 +179,7 @@ EOF]) # List of components to be built, either statically or dynamically. # To be enlarged below. # - hwloc_components="noos xml synthetic custom xml_nolibxml" + hwloc_components="noos xml synthetic xml_nolibxml" # # Check OS support @@ -197,10 +197,14 @@ EOF]) hwloc_linux=yes AC_MSG_RESULT([Linux]) hwloc_components="$hwloc_components linux" - if test x$enable_pci != xno; then - hwloc_components="$hwloc_components linuxpci" - AC_DEFINE(HWLOC_HAVE_LINUXPCI, 1, [Define to 1 if building the Linux PCI component]) - hwloc_linuxpci_happy=yes + if test "x$enable_io" != xno; then + hwloc_components="$hwloc_components linuxio" + AC_DEFINE(HWLOC_HAVE_LINUXIO, 1, [Define to 1 if building the Linux I/O component]) + hwloc_linuxio_happy=yes + if test x$enable_pci != xno; then + AC_DEFINE(HWLOC_HAVE_LINUXPCI, 1, [Define to 1 if enabling Linux-specific PCI discovery in the Linux I/O component]) + hwloc_linuxpci_happy=yes + fi fi ;; *-*-irix*) @@ -227,12 +231,6 @@ EOF]) AC_MSG_RESULT([AIX]) hwloc_components="$hwloc_components aix" ;; - *-*-osf*) - AC_DEFINE(HWLOC_OSF_SYS, 1, [Define to 1 on OSF]) - hwloc_osf=yes - AC_MSG_RESULT([OSF]) - hwloc_components="$hwloc_components osf" - ;; *-*-hpux*) AC_DEFINE(HWLOC_HPUX_SYS, 1, [Define to 1 on HP-UX]) hwloc_hpux=yes @@ -264,7 +262,7 @@ EOF]) AC_MSG_WARN([*** hwloc does not support this system.]) AC_MSG_WARN([*** hwloc will *attempt* to build (but it may not work).]) AC_MSG_WARN([*** hwloc run-time results may be reduced to showing just one processor,]) - AC_MSG_WARN([*** and binding will likely not be supported.]) + AC_MSG_WARN([*** and binding will not be supported.]) AC_MSG_WARN([*** You have been warned.]) AC_MSG_WARN([*** Pausing to give you time to read this message...]) AC_MSG_WARN([***********************************************************]) @@ -435,12 +433,12 @@ EOF]) [HWLOC_LIBS="-lpicl $HWLOC_LIBS"])]) AC_CHECK_DECLS([_SC_NPROCESSORS_ONLN, - _SC_NPROCESSORS_CONF, - _SC_NPROC_ONLN, - _SC_NPROC_CONF, - _SC_PAGESIZE, - _SC_PAGE_SIZE, - _SC_LARGE_PAGESIZE],,[:],[[#include ]]) + _SC_NPROCESSORS_CONF, + _SC_NPROC_ONLN, + _SC_NPROC_CONF, + _SC_PAGESIZE, + _SC_PAGE_SIZE, + _SC_LARGE_PAGESIZE],,[:],[[#include ]]) AC_HAVE_HEADERS([mach/mach_host.h]) AC_HAVE_HEADERS([mach/mach_init.h], [ @@ -593,22 +591,16 @@ EOF]) AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])]) - AC_MSG_CHECKING([for working syscall]) + AC_MSG_CHECKING([for working syscall with 6 parameters]) AC_LINK_IFELSE([ AC_LANG_PROGRAM([[ #include #include - ]], [[syscall(1, 2, 3);]])], - [AC_DEFINE([HWLOC_HAVE_SYSCALL], [1], [Define to 1 if function `syscall' is available]) + ]], [[syscall(0, 1, 2, 3, 4, 5, 6);]])], + [AC_DEFINE([HWLOC_HAVE_SYSCALL], [1], [Define to 1 if function `syscall' is available with 6 parameters]) AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])]) - # Check for kerrighed, but don't abort if not found. It's illegal - # to pass in an empty 3rd argument, but we trust the output of - # pkg-config, so just give it a value that will always work: - # printf. - HWLOC_PKG_CHECK_MODULES([KERRIGHED], [kerrighed >= 2.0], [printf], [stdio.h], [], [:]) - AC_PATH_PROGS([HWLOC_MS_LIB], [lib]) AC_ARG_VAR([HWLOC_MS_LIB], [Path to Microsoft's Visual Studio `lib' tool]) @@ -710,44 +702,6 @@ EOF]) ) AC_CHECK_FUNCS([cpuset_setid]) - # Linux libnuma support - hwloc_linux_libnuma_happy=no - if test "x$enable_libnuma" != "xno"; then - hwloc_linux_libnuma_happy=yes - AC_CHECK_HEADERS([numaif.h], [ - AC_CHECK_LIB([numa], [numa_available], [HWLOC_LINUX_LIBNUMA_LIBS="-lnuma"], [hwloc_linux_libnuma_happy=no]) - ], [hwloc_linux_libnuma_happy=no]) - fi - AC_SUBST(HWLOC_LINUX_LIBNUMA_LIBS) - # If we asked for Linux libnuma support but couldn't deliver, fail - HWLOC_LIBS="$HWLOC_LIBS $HWLOC_LINUX_LIBNUMA_LIBS" - AS_IF([test "$enable_libnuma" = "yes" -a "$hwloc_linux_libnuma_happy" = "no"], - [AC_MSG_WARN([Specified --enable-libnuma switch, but could not]) - AC_MSG_WARN([find appropriate support]) - AC_MSG_ERROR([Cannot continue])]) - if test "x$hwloc_linux_libnuma_happy" = "xyes"; then - tmp_save_LIBS="$LIBS" - LIBS="$LIBS $HWLOC_LINUX_LIBNUMA_LIBS" - - AC_CHECK_LIB([numa], [set_mempolicy], [ - enable_set_mempolicy=yes - AC_DEFINE([HWLOC_HAVE_SET_MEMPOLICY], [1], [Define to 1 if set_mempolicy is available.]) - ]) - AC_CHECK_LIB([numa], [mbind], [ - enable_mbind=yes - AC_DEFINE([HWLOC_HAVE_MBIND], [1], [Define to 1 if mbind is available.]) - ]) - AC_CHECK_LIB([numa], [migrate_pages], [ - enable_migrate_pages=yes - AC_DEFINE([HWLOC_HAVE_MIGRATE_PAGES], [1], [Define to 1 if migrate_pages is available.]) - ]) - AC_CHECK_LIB([numa], [move_pages], [ - AC_DEFINE([HWLOC_HAVE_MOVE_PAGES], [1], [Define to 1 if move_pages is available.]) - ]) - - LIBS="$tmp_save_LIBS" - fi - # Linux libudev support if test "x$enable_libudev" != xno; then AC_CHECK_HEADERS([libudev.h], [ @@ -761,32 +715,31 @@ EOF]) # PCI support via libpciaccess. NOTE: we do not support # libpci/pciutils because that library is GPL and is incompatible # with our BSD license. - hwloc_pci_happy=no - if test "x$enable_pci" != xno; then - hwloc_pci_happy=yes - HWLOC_PKG_CHECK_MODULES([PCIACCESS], [pciaccess], [pci_slot_match_iterator_create], [pciaccess.h], [:], [hwloc_pci_happy=no]) + hwloc_pciaccess_happy=no + if test "x$enable_io" != xno && test "x$enable_pci" != xno; then + hwloc_pciaccess_happy=yes + HWLOC_PKG_CHECK_MODULES([PCIACCESS], [pciaccess], [pci_slot_match_iterator_create], [pciaccess.h], [:], [hwloc_pciaccess_happy=no]) # Only add the REQUIRES if we got pciaccess through pkg-config. # Otherwise we don't know if pciaccess.pc is installed - AS_IF([test "$hwloc_pci_happy" = "yes"], [HWLOC_PCIACCESS_REQUIRES=pciaccess]) + AS_IF([test "$hwloc_pciaccess_happy" = "yes"], [HWLOC_PCIACCESS_REQUIRES=pciaccess]) # Just for giggles, if we didn't find a pciaccess pkg-config, # just try looking for its header file and library. - AS_IF([test "$hwloc_pci_happy" != "yes"], + AS_IF([test "$hwloc_pciaccess_happy" != "yes"], [AC_CHECK_HEADER([pciaccess.h], [AC_CHECK_LIB([pciaccess], [pci_slot_match_iterator_create], - [hwloc_pci_happy=yes + [hwloc_pciaccess_happy=yes HWLOC_PCIACCESS_LIBS="-lpciaccess"]) ]) ]) - AS_IF([test "$hwloc_pci_happy" = "yes"], - [hwloc_pci_lib=pciaccess - hwloc_components="$hwloc_components pci" + AS_IF([test "$hwloc_pciaccess_happy" = "yes"], + [hwloc_components="$hwloc_components pci" hwloc_pci_component_maybeplugin=1]) fi # If we asked for pci support but couldn't deliver, fail - AS_IF([test "$enable_pci" = "yes" -a "$hwloc_pci_happy" = "no"], + AS_IF([test "$enable_pci" = "yes" -a "$hwloc_pciaccess_happy" = "no"], [AC_MSG_WARN([Specified --enable-pci switch, but could not]) AC_MSG_WARN([find appropriate support]) AC_MSG_ERROR([Cannot continue])]) @@ -794,7 +747,7 @@ EOF]) # OpenCL support hwloc_opencl_happy=no - if test "x$enable_opencl" != "xno"; then + if test "x$enable_io" != xno && test "x$enable_opencl" != "xno"; then hwloc_opencl_happy=yes AC_CHECK_HEADERS([CL/cl_ext.h], [ AC_CHECK_LIB([OpenCL], [clGetDeviceIDs], [HWLOC_OPENCL_LIBS="-lOpenCL"], [hwloc_opencl_happy=no]) @@ -831,7 +784,7 @@ EOF]) # CUDA support hwloc_have_cuda=no hwloc_have_cudart=no - if test "x$enable_cuda" != "xno"; then + if test "x$enable_io" != xno && test "x$enable_cuda" != "xno"; then AC_CHECK_HEADERS([cuda.h], [ AC_MSG_CHECKING(if CUDA_VERSION >= 3020) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ @@ -880,7 +833,7 @@ EOF]) # NVML support hwloc_nvml_happy=no - if test "x$enable_nvml" != "xno"; then + if test "x$enable_io" != xno && test "x$enable_nvml" != "xno"; then hwloc_nvml_happy=yes AC_CHECK_HEADERS([nvml.h], [ AC_CHECK_LIB([nvidia-ml], [nvmlInit], [HWLOC_NVML_LIBS="-lnvidia-ml"], [hwloc_nvml_happy=no]) @@ -940,7 +893,7 @@ EOF]) # GL Support hwloc_gl_happy=no - if test "x$enable_gl" != "xno"; then + if test "x$enable_io" != xno && test "x$enable_gl" != "xno"; then hwloc_gl_happy=yes AS_IF([test "$hwloc_enable_X11" != "yes"], @@ -998,7 +951,7 @@ EOF]) AC_MSG_CHECKING([for x86 cpuid]) old_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS -I$HWLOC_top_srcdir/include" - # We need hwloc_uint64_t but we can't use hwloc/autogen/config.h before configure ends. + # We need hwloc_uint64_t but we can't use autogen/config.h before configure ends. # So pass #include/#define manually here for now. CPUID_CHECK_HEADERS= CPUID_CHECK_DEFINE= @@ -1107,7 +1060,7 @@ EOF]) AC_SUBST(HWLOC_PLUGINS_DIR) # Static components output file - hwloc_static_components_dir=${HWLOC_top_builddir}/src + hwloc_static_components_dir=${HWLOC_top_builddir}/hwloc mkdir -p ${hwloc_static_components_dir} hwloc_static_components_file=${hwloc_static_components_dir}/static-components.h rm -f ${hwloc_static_components_file} @@ -1173,7 +1126,7 @@ EOF]) AS_IF([test "$hwloc_mode" = "embedded"], [HWLOC_EMBEDDED_CFLAGS=$HWLOC_CFLAGS HWLOC_EMBEDDED_CPPFLAGS=$HWLOC_CPPFLAGS - HWLOC_EMBEDDED_LDADD='$(HWLOC_top_builddir)/src/libhwloc_embedded.la' + HWLOC_EMBEDDED_LDADD='$(HWLOC_top_builddir)/hwloc/libhwloc_embedded.la' HWLOC_EMBEDDED_LIBS=$HWLOC_LIBS HWLOC_LIBS=]) AC_SUBST(HWLOC_EMBEDDED_CFLAGS) @@ -1185,7 +1138,7 @@ EOF]) AC_CONFIG_FILES( hwloc_config_prefix[Makefile] hwloc_config_prefix[include/Makefile] - hwloc_config_prefix[src/Makefile ] + hwloc_config_prefix[hwloc/Makefile ] ) # Cleanup @@ -1213,12 +1166,12 @@ AC_DEFUN([HWLOC_DO_AM_CONDITIONALS],[ AM_CONDITIONAL([HWLOC_HAVE_GCC], [test "x$GCC" = "xyes"]) AM_CONDITIONAL([HWLOC_HAVE_MS_LIB], [test "x$HWLOC_MS_LIB" != "x"]) AM_CONDITIONAL([HWLOC_HAVE_OPENAT], [test "x$hwloc_have_openat" = "xyes"]) - AM_CONDITIONAL([HWLOC_HAVE_LINUX_LIBNUMA], - [test "x$hwloc_have_linux_libnuma" = "xyes"]) AM_CONDITIONAL([HWLOC_HAVE_SCHED_SETAFFINITY], [test "x$hwloc_have_sched_setaffinity" = "xyes"]) AM_CONDITIONAL([HWLOC_HAVE_PTHREAD], [test "x$hwloc_have_pthread" = "xyes"]) + AM_CONDITIONAL([HWLOC_HAVE_LINUX_LIBNUMA], + [test "x$hwloc_have_linux_libnuma" = "xyes"]) AM_CONDITIONAL([HWLOC_HAVE_LIBIBVERBS], [test "x$hwloc_have_libibverbs" = "xyes"]) AM_CONDITIONAL([HWLOC_HAVE_CUDA], @@ -1231,11 +1184,9 @@ AC_DEFUN([HWLOC_DO_AM_CONDITIONALS],[ [test "x$hwloc_have_cudart" = "xyes"]) AM_CONDITIONAL([HWLOC_HAVE_LIBXML2], [test "$hwloc_libxml2_happy" = "yes"]) AM_CONDITIONAL([HWLOC_HAVE_CAIRO], [test "$hwloc_cairo_happy" = "yes"]) - AM_CONDITIONAL([HWLOC_HAVE_PCI], [test "$hwloc_pci_happy" = "yes"]) + AM_CONDITIONAL([HWLOC_HAVE_PCIACCESS], [test "$hwloc_pciaccess_happy" = "yes"]) AM_CONDITIONAL([HWLOC_HAVE_OPENCL], [test "$hwloc_opencl_happy" = "yes"]) AM_CONDITIONAL([HWLOC_HAVE_NVML], [test "$hwloc_nvml_happy" = "yes"]) - AM_CONDITIONAL([HWLOC_HAVE_SET_MEMPOLICY], [test "x$enable_set_mempolicy" != "xno"]) - AM_CONDITIONAL([HWLOC_HAVE_MBIND], [test "x$enable_mbind" != "xno"]) AM_CONDITIONAL([HWLOC_HAVE_BUNZIPP], [test "x$BUNZIPP" != "xfalse"]) AM_CONDITIONAL([HWLOC_HAVE_USER32], [test "x$hwloc_have_user32" = "xyes"]) @@ -1254,7 +1205,6 @@ AC_DEFUN([HWLOC_DO_AM_CONDITIONALS],[ AM_CONDITIONAL([HWLOC_HAVE_NETBSD], [test "x$hwloc_netbsd" = "xyes"]) AM_CONDITIONAL([HWLOC_HAVE_SOLARIS], [test "x$hwloc_solaris" = "xyes"]) AM_CONDITIONAL([HWLOC_HAVE_AIX], [test "x$hwloc_aix" = "xyes"]) - AM_CONDITIONAL([HWLOC_HAVE_OSF], [test "x$hwloc_osf" = "xyes"]) AM_CONDITIONAL([HWLOC_HAVE_HPUX], [test "x$hwloc_hpux" = "xyes"]) AM_CONDITIONAL([HWLOC_HAVE_WINDOWS], [test "x$hwloc_windows" = "xyes"]) AM_CONDITIONAL([HWLOC_HAVE_MINGW32], [test "x$target_os" = "xmingw32"]) @@ -1275,6 +1225,11 @@ AC_DEFUN([HWLOC_DO_AM_CONDITIONALS],[ AM_CONDITIONAL([HWLOC_HAVE_CXX], [test "x$hwloc_have_cxx" = "xyes"]) ]) hwloc_did_am_conditionals=yes + + # For backwards compatibility (i.e., packages that only call + # HWLOC_DO_AM_CONDITIONS, not NETLOC DO_AM_CONDITIONALS), we also have to + # do the netloc AM conditionals here + NETLOC_DO_AM_CONDITIONALS ])dnl #----------------------------------------------------------------------- diff --git a/opal/mca/hwloc/hwloc1116/hwloc/config/hwloc_check_attributes.m4 b/opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_check_attributes.m4 similarity index 99% rename from opal/mca/hwloc/hwloc1116/hwloc/config/hwloc_check_attributes.m4 rename to opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_check_attributes.m4 index 96348e819e..86444a950c 100644 --- a/opal/mca/hwloc/hwloc1116/hwloc/config/hwloc_check_attributes.m4 +++ b/opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_check_attributes.m4 @@ -531,4 +531,3 @@ AC_DEFUN([_HWLOC_CHECK_ATTRIBUTES], [ AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_WEAK_ALIAS, [$hwloc_cv___attribute__weak_alias], [Whether your compiler has __attribute__ weak alias or not]) ]) - diff --git a/opal/mca/hwloc/hwloc1116/hwloc/config/hwloc_check_vendor.m4 b/opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_check_vendor.m4 similarity index 98% rename from opal/mca/hwloc/hwloc1116/hwloc/config/hwloc_check_vendor.m4 rename to opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_check_vendor.m4 index 0340f4ca35..60ab56af79 100644 --- a/opal/mca/hwloc/hwloc1116/hwloc/config/hwloc_check_vendor.m4 +++ b/opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_check_vendor.m4 @@ -11,6 +11,8 @@ dnl University of Stuttgart. All rights reserved. dnl Copyright © 2004-2005 The Regents of the University of California. dnl All rights reserved. dnl Copyright © 2011 Cisco Systems, Inc. All rights reserved. +dnl Copyright © 2015 Inria. All rights reserved. +dnl Copyright (c) 2017 Intel, Inc. All rights reserved. dnl $COPYRIGHT$ dnl dnl Additional copyrights may follow @@ -120,6 +122,7 @@ AC_DEFUN([_HWLOC_CHECK_COMPILER_VENDOR], [ [hwloc_check_compiler_vendor_result="comeau"])]) # Compaq C/C++ + # OSF part actually not needed anymore but doesn't hurt AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], [HWLOC_IF_IFELSE([defined(__DECC) || defined(VAXC) || defined(__VAXC)], [hwloc_check_compiler_vendor_result="compaq"], diff --git a/opal/mca/hwloc/hwloc1116/hwloc/config/hwloc_check_visibility.m4 b/opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_check_visibility.m4 similarity index 100% rename from opal/mca/hwloc/hwloc1116/hwloc/config/hwloc_check_visibility.m4 rename to opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_check_visibility.m4 diff --git a/opal/mca/hwloc/hwloc1116/hwloc/config/hwloc_components.m4 b/opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_components.m4 similarity index 100% rename from opal/mca/hwloc/hwloc1116/hwloc/config/hwloc_components.m4 rename to opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_components.m4 diff --git a/opal/mca/hwloc/hwloc1116/hwloc/config/hwloc_get_version.sh b/opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_get_version.sh similarity index 74% rename from opal/mca/hwloc/hwloc1116/hwloc/config/hwloc_get_version.sh rename to opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_get_version.sh index 74bca537ce..63c357c92b 100755 --- a/opal/mca/hwloc/hwloc1116/hwloc/config/hwloc_get_version.sh +++ b/opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_get_version.sh @@ -12,6 +12,7 @@ # All rights reserved. # Copyright © 2008-2014 Cisco Systems, Inc. All rights reserved. # Copyright © 2014 Inria. All rights reserved. +# Copyright (c) 2017 Intel, Inc. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -29,24 +30,24 @@ else if test -f "$srcfile"; then ompi_vers=`sed -n " - t clear - : clear - s/^major/HWLOC_MAJOR_VERSION/ - s/^minor/HWLOC_MINOR_VERSION/ - s/^release/HWLOC_RELEASE_VERSION/ - s/^greek/HWLOC_GREEK_VERSION/ - s/\\\${major}/\\\${HWLOC_MAJOR_VERSION}/ - s/\\\${minor}/\\\${HWLOC_MINOR_VERSION}/ - s/\\\${release}/\\\${HWLOC_RELEASE_VERSION}/ - s/\\\${greek}/\\\${HWLOC_GREEK_VERSION}/ - s/^date/HWLOC_RELEASE_DATE/ - s/^snapshot_version/HWLOC_SNAPSHOT_VERSION/ - s/^snapshot/HWLOC_SNAPSHOT/ - t print - b - : print - p" < "$srcfile"` - eval "$ompi_vers" + t clear + : clear + s/^major/HWLOC_MAJOR_VERSION/ + s/^minor/HWLOC_MINOR_VERSION/ + s/^release/HWLOC_RELEASE_VERSION/ + s/^greek/HWLOC_GREEK_VERSION/ + s/\\\${major}/\\\${HWLOC_MAJOR_VERSION}/ + s/\\\${minor}/\\\${HWLOC_MINOR_VERSION}/ + s/\\\${release}/\\\${HWLOC_RELEASE_VERSION}/ + s/\\\${greek}/\\\${HWLOC_GREEK_VERSION}/ + s/^date/HWLOC_RELEASE_DATE/ + s/^snapshot_version/HWLOC_SNAPSHOT_VERSION/ + s/^snapshot/HWLOC_SNAPSHOT/ + t print + b + : print + p" < "$srcfile"` + eval "$ompi_vers" HWLOC_VERSION="$HWLOC_MAJOR_VERSION.$HWLOC_MINOR_VERSION.$HWLOC_RELEASE_VERSION${HWLOC_GREEK_VERSION}" @@ -62,14 +63,14 @@ else fi if test "$option" = ""; then - option="--version" + option="--version" fi fi case "$option" in --version) - echo $HWLOC_VERSION - ;; + echo $HWLOC_VERSION + ;; --release-date) echo $HWLOC_RELEASE_DATE ;; @@ -77,7 +78,7 @@ case "$option" in echo $HWLOC_SNAPSHOT ;; -h|--help) - cat <