From d9f23627fd8bc5f574879eecaad61a2473ce4bde Mon Sep 17 00:00:00 2001 From: Ralph Castain Date: Thu, 4 Jun 2015 15:35:56 -0700 Subject: [PATCH 1/2] Add in hwloc 1.11.0rc1 - will overwrite with final version --- opal/mca/hwloc/hwloc1110/Makefile.am | 83 + opal/mca/hwloc/hwloc1110/README-ompi.txt | 35 + opal/mca/hwloc/hwloc1110/configure.m4 | 170 + opal/mca/hwloc/hwloc1110/hwloc/AUTHORS | 8 + opal/mca/hwloc/hwloc1110/hwloc/COPYING | 28 + opal/mca/hwloc/hwloc1110/hwloc/Makefile.am | 75 + opal/mca/hwloc/hwloc1110/hwloc/NEWS | 1156 ++++ opal/mca/hwloc/hwloc1110/hwloc/README | 612 ++ opal/mca/hwloc/hwloc1110/hwloc/VERSION | 42 + .../hwloc1110/hwloc/config/distscript.sh | 130 + .../mca/hwloc/hwloc1110/hwloc/config/hwloc.m4 | 1357 +++++ .../hwloc/config/hwloc_check_attributes.m4 | 533 ++ .../hwloc/config/hwloc_check_vendor.m4 | 239 + .../hwloc/config/hwloc_check_visibility.m4 | 131 + .../hwloc/config/hwloc_components.m4 | 66 + .../hwloc/config/hwloc_get_version.sh | 98 + .../hwloc1110/hwloc/config/hwloc_internal.m4 | 423 ++ .../hwloc/hwloc1110/hwloc/config/hwloc_pkg.m4 | 207 + .../hwloc/hwloc1110/hwloc/config/test-driver | 148 + opal/mca/hwloc/hwloc1110/hwloc/configure.ac | 242 + .../hwloc/contrib/hwloc-valgrind.supp | 145 + opal/mca/hwloc/hwloc1110/hwloc/doc/README.txt | 4 + opal/mca/hwloc/hwloc1110/hwloc/hwloc.pc.in | 12 + .../hwloc/hwloc1110/hwloc/include/Makefile.am | 55 + .../mca/hwloc/hwloc1110/hwloc/include/hwloc.h | 2413 ++++++++ .../hwloc/include/hwloc/autogen/config.h.in | 201 + .../hwloc1110/hwloc/include/hwloc/bitmap.h | 359 ++ .../hwloc1110/hwloc/include/hwloc/cuda.h | 224 + .../hwloc1110/hwloc/include/hwloc/cudart.h | 183 + .../hwloc/include/hwloc/deprecated.h | 102 + .../hwloc1110/hwloc/include/hwloc/diff.h | 299 + .../hwloc/hwloc1110/hwloc/include/hwloc/gl.h | 135 + .../hwloc/include/hwloc/glibc-sched.h | 125 + .../hwloc1110/hwloc/include/hwloc/helper.h | 1290 ++++ .../hwloc1110/hwloc/include/hwloc/inlines.h | 154 + .../hwloc1110/hwloc/include/hwloc/intel-mic.h | 143 + .../hwloc/include/hwloc/linux-libnuma.h | 355 ++ .../hwloc1110/hwloc/include/hwloc/linux.h | 77 + .../hwloc/include/hwloc/myriexpress.h | 127 + .../hwloc1110/hwloc/include/hwloc/nvml.h | 176 + .../hwloc1110/hwloc/include/hwloc/opencl.h | 199 + .../hwloc/include/hwloc/openfabrics-verbs.h | 155 + .../hwloc1110/hwloc/include/hwloc/plugins.h | 437 ++ .../hwloc1110/hwloc/include/hwloc/rename.h | 651 ++ .../hwloc/include/private/autogen/config.h.in | 685 +++ .../hwloc/include/private/components.h | 40 + .../hwloc/include/private/cpuid-x86.h | 89 + .../hwloc1110/hwloc/include/private/debug.h | 57 + .../hwloc1110/hwloc/include/private/misc.h | 382 ++ .../hwloc1110/hwloc/include/private/private.h | 330 ++ .../hwloc/include/private/solaris-chiptype.h | 59 + .../hwloc1110/hwloc/include/private/xml.h | 97 + .../mca/hwloc/hwloc1110/hwloc/src/Makefile.am | 235 + opal/mca/hwloc/hwloc1110/hwloc/src/base64.c | 306 + opal/mca/hwloc/hwloc1110/hwloc/src/bind.c | 781 +++ opal/mca/hwloc/hwloc1110/hwloc/src/bitmap.c | 1485 +++++ .../hwloc/hwloc1110/hwloc/src/components.c | 811 +++ opal/mca/hwloc/hwloc1110/hwloc/src/diff.c | 408 ++ .../mca/hwloc/hwloc1110/hwloc/src/distances.c | 1040 ++++ opal/mca/hwloc/hwloc1110/hwloc/src/dolib.c | 47 + opal/mca/hwloc/hwloc1110/hwloc/src/hwloc.dtd | 71 + opal/mca/hwloc/hwloc1110/hwloc/src/misc.c | 166 + .../hwloc/hwloc1110/hwloc/src/pci-common.c | 514 ++ .../hwloc/hwloc1110/hwloc/src/topology-aix.c | 872 +++ .../hwloc/hwloc1110/hwloc/src/topology-bgq.c | 241 + .../hwloc/hwloc1110/hwloc/src/topology-cuda.c | 248 + .../hwloc1110/hwloc/src/topology-custom.c | 100 + .../hwloc1110/hwloc/src/topology-darwin.c | 307 + .../hwloc/hwloc1110/hwloc/src/topology-fake.c | 61 + .../hwloc1110/hwloc/src/topology-freebsd.c | 253 + .../hwloc/hwloc1110/hwloc/src/topology-gl.c | 271 + .../hwloc/hwloc1110/hwloc/src/topology-hpux.c | 311 + .../hwloc1110/hwloc/src/topology-linux.c | 5229 +++++++++++++++++ .../hwloc1110/hwloc/src/topology-netbsd.c | 214 + .../hwloc/hwloc1110/hwloc/src/topology-noos.c | 58 + .../hwloc/hwloc1110/hwloc/src/topology-nvml.c | 239 + .../hwloc1110/hwloc/src/topology-opencl.c | 346 ++ .../hwloc/hwloc1110/hwloc/src/topology-osf.c | 392 ++ .../hwloc/hwloc1110/hwloc/src/topology-pci.c | 341 ++ .../hwloc/src/topology-solaris-chiptype.c | 339 ++ .../hwloc1110/hwloc/src/topology-solaris.c | 804 +++ .../hwloc1110/hwloc/src/topology-synthetic.c | 1098 ++++ .../hwloc1110/hwloc/src/topology-windows.c | 812 +++ .../hwloc/hwloc1110/hwloc/src/topology-x86.c | 1104 ++++ .../hwloc1110/hwloc/src/topology-xml-libxml.c | 543 ++ .../hwloc/src/topology-xml-nolibxml.c | 850 +++ .../hwloc/hwloc1110/hwloc/src/topology-xml.c | 1675 ++++++ opal/mca/hwloc/hwloc1110/hwloc/src/topology.c | 3236 ++++++++++ .../mca/hwloc/hwloc1110/hwloc/src/traversal.c | 700 +++ .../hwloc/hwloc1110/hwloc/tests/README.txt | 4 + .../hwloc/hwloc1110/hwloc/utils/README.txt | 4 + opal/mca/hwloc/hwloc1110/hwloc1110.h | 45 + .../mca/hwloc/hwloc1110/hwloc1110_component.c | 55 + opal/mca/hwloc/hwloc1110/owner.txt | 7 + opal/mca/hwloc/hwloc191/configure.m4 | 2 +- 95 files changed, 42167 insertions(+), 1 deletion(-) create mode 100644 opal/mca/hwloc/hwloc1110/Makefile.am create mode 100644 opal/mca/hwloc/hwloc1110/README-ompi.txt create mode 100644 opal/mca/hwloc/hwloc1110/configure.m4 create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/AUTHORS create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/COPYING create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/Makefile.am create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/NEWS create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/README create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/VERSION create mode 100755 opal/mca/hwloc/hwloc1110/hwloc/config/distscript.sh create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/config/hwloc.m4 create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_check_attributes.m4 create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_check_vendor.m4 create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_check_visibility.m4 create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_components.m4 create mode 100755 opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_get_version.sh create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_internal.m4 create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_pkg.m4 create mode 100755 opal/mca/hwloc/hwloc1110/hwloc/config/test-driver create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/configure.ac create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/contrib/hwloc-valgrind.supp create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/doc/README.txt create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/hwloc.pc.in create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/Makefile.am create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/hwloc.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/autogen/config.h.in create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/bitmap.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/cuda.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/cudart.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/deprecated.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/diff.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/gl.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/glibc-sched.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/helper.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/inlines.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/intel-mic.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/linux-libnuma.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/linux.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/myriexpress.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/nvml.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/opencl.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/openfabrics-verbs.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/plugins.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/rename.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/private/autogen/config.h.in create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/private/components.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/private/cpuid-x86.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/private/debug.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/private/misc.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/private/private.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/private/solaris-chiptype.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/include/private/xml.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/Makefile.am create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/base64.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/bind.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/bitmap.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/components.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/diff.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/distances.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/dolib.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/hwloc.dtd create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/misc.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/pci-common.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology-aix.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology-bgq.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology-cuda.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology-custom.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology-darwin.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology-fake.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology-freebsd.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology-gl.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology-hpux.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology-linux.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology-netbsd.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology-noos.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology-nvml.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology-opencl.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology-osf.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology-pci.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology-solaris-chiptype.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology-solaris.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology-synthetic.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology-windows.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology-x86.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology-xml-libxml.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology-xml-nolibxml.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology-xml.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/topology.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/src/traversal.c create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/tests/README.txt create mode 100644 opal/mca/hwloc/hwloc1110/hwloc/utils/README.txt create mode 100644 opal/mca/hwloc/hwloc1110/hwloc1110.h create mode 100644 opal/mca/hwloc/hwloc1110/hwloc1110_component.c create mode 100644 opal/mca/hwloc/hwloc1110/owner.txt diff --git a/opal/mca/hwloc/hwloc1110/Makefile.am b/opal/mca/hwloc/hwloc1110/Makefile.am new file mode 100644 index 0000000000..4fb47162ac --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/Makefile.am @@ -0,0 +1,83 @@ +# +# Copyright (c) 2011-2014 Cisco Systems, Inc. All rights reserved. +# Copyright (c) 2014-2015 Intel, Inc. All right reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# + +# Due to what might be a bug in Automake, we need to remove stamp-h? +# files manually. See +# http://debbugs.gnu.org/cgi/bugreport.cgi?bug=19418. +DISTCLEANFILES = \ + hwloc/include/hwloc/autogen/stamp-h? \ + hwloc/include/private/autogen/stamp-h? + +# Need to include these files so that these directories are carried in +# the tarball (in case someone invokes autogen.sh on a dist tarball). +EXTRA_DIST = \ + hwloc/doc/README.txt \ + hwloc/tests/README.txt \ + hwloc/utils/README.txt + +SUBDIRS = hwloc + +# Headers and sources +headers = hwloc1110.h +sources = hwloc1110_component.c + +# We only ever build this component statically +noinst_LTLIBRARIES = libmca_hwloc_hwloc1110.la +libmca_hwloc_hwloc1110_la_SOURCES = $(headers) $(sources) +nodist_libmca_hwloc_hwloc1110_la_SOURCES = $(nodist_headers) +libmca_hwloc_hwloc1110_la_LDFLAGS = -module -avoid-version $(opal_hwloc_hwloc1110_LDFLAGS) +libmca_hwloc_hwloc1110_la_LIBADD = $(opal_hwloc_hwloc1110_LIBS) +libmca_hwloc_hwloc1110_la_DEPENDENCIES = \ + $(HWLOC_top_builddir)/src/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 +# --with-devel-headers is specified. hwloc doesn't support this; the +# least gross way to make this happen is just to list all of hwloc's +# header files here. :-( +headers += \ + hwloc/include/hwloc.h \ + hwloc/include/hwloc/bitmap.h \ + hwloc/include/hwloc/cuda.h \ + hwloc/include/hwloc/cudart.h \ + hwloc/include/hwloc/deprecated.h \ + hwloc/include/hwloc/diff.h \ + hwloc/include/hwloc/gl.h \ + hwloc/include/hwloc/helper.h \ + hwloc/include/hwloc/inlines.h \ + hwloc/include/hwloc/intel-mic.h \ + hwloc/include/hwloc/myriexpress.h \ + hwloc/include/hwloc/nvml.h \ + hwloc/include/hwloc/opencl.h \ + hwloc/include/hwloc/openfabrics-verbs.h \ + hwloc/include/hwloc/plugins.h \ + hwloc/include/hwloc/rename.h \ + hwloc/include/private/private.h \ + hwloc/include/private/debug.h \ + hwloc/include/private/misc.h \ + hwloc/include/private/cpuid-x86.h +nodist_headers = hwloc/include/hwloc/autogen/config.h + +if HWLOC_HAVE_LINUX +headers += \ + hwloc/include/hwloc/linux.h \ + hwloc/include/hwloc/linux-libnuma.h +endif HWLOC_HAVE_LINUX + +if HWLOC_HAVE_SCHED_SETAFFINITY +headers += hwloc/include/hwloc/glibc-sched.h +endif HWLOC_HAVE_SCHED_SETAFFINITY + +# Conditionally install the header files +if WANT_INSTALL_HEADERS +opaldir = $(opalincludedir)/$(subdir) +nobase_opal_HEADERS = $(headers) +nobase_nodist_opal_HEADERS = $(nodist_headers) +endif diff --git a/opal/mca/hwloc/hwloc1110/README-ompi.txt b/opal/mca/hwloc/hwloc1110/README-ompi.txt new file mode 100644 index 0000000000..948285aaff --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/README-ompi.txt @@ -0,0 +1,35 @@ +Applied the following patches from the upstream hwloc 1.9 branch after +the v1.9.1 release: + +All relevant commits up to open-mpi/hwloc@4e23b12 (i.e., the HEAD as +of 27 March 2015). "Relevant" commits are defined as those that +included files that are embedded in the Open MPI tree (e.g., updates +to files in docs/, utils/, etc. aren't relevant because they are not +embedded in the Open MPI tree). To be specific, the following commits +have been cherry-picked over to Open MPI: + +* open-mpi/hwloc@7c03216 v1.9.1 released, doing 1.9.2rc1 now +* open-mpi/hwloc@b35ced8 misc.h: Fix hwloc_strncasecmp() build under strict flags on BSD +* open-mpi/hwloc@d8c3f3d misc.h: Fix hwloc_strncasecmp() with some icc +* open-mpi/hwloc@f705a23 Use gcc's __asm__ version of the asm extension, which can be used in all standards +* open-mpi/hwloc@307726a configure: fix the check for X11/Xutil.h +* open-mpi/hwloc@ec58c05 errors: improve the advice to send hwloc-gather-topology files in the OS error message +* open-mpi/hwloc@35c743d NEWS update +* open-mpi/hwloc@868170e API: clearly state that os_index isn't unique while logical_index is +* open-mpi/hwloc@851532d x86 and OSF: Don't forget to set NUMA node nodeset +* open-mpi/hwloc@790aa2e cpuid-x86: Fix duplicate asm labels in case of heavy inlining on x86-32 +* open-mpi/hwloc@dd09aa5 debug: fix an overzealous assertion about the parent cpuset vs its children +* open-mpi/hwloc@769b9b5 core: fix the merging of identical objects in presence of Misc objects +* open-mpi/hwloc@71da0f1 core: reorder children in merge_useless_child() as well +* open-mpi/hwloc@c9cef07 hpux: improve hwloc_hpux_find_ldom() looking for NUMA node +* open-mpi/hwloc@cdffea6 x86: use ulong for cache sizes, uint won't be enough in the near future +* open-mpi/hwloc@55b0676 x86: use Group instead of Misc for unknown x2apic levels +* open-mpi/hwloc@7764ce5 synthetic: Misc levels are not allowed in the synthetic description +* open-mpi/hwloc@5b2dce1 error: point to the FAQ when displaying the big OS error message +* open-mpi/hwloc@c7bd9e6 pci: fix SR-IOV VF vendor/device names +* open-mpi/hwloc@a0f72ef distances: when we fail to insert an intermediate group, don't try to group further above +* open-mpi/hwloc@e419811 AIX: Fix PU os_index +* open-mpi/hwloc@08ab793 groups: add complete sets when inserting distance/pci groups +* open-mpi/hwloc@c66e714 core: only update root->complete sets if insert succeeds +* open-mpi/hwloc@01da9b9 bitmap: fix a corner case in hwloc_bitmap_isincluded() with infinite sets +* open-mpi/hwloc@e7b192b pci: fix bridge depth diff --git a/opal/mca/hwloc/hwloc1110/configure.m4 b/opal/mca/hwloc/hwloc1110/configure.m4 new file mode 100644 index 0000000000..72a249f8f9 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/configure.m4 @@ -0,0 +1,170 @@ +# -*- shell-script -*- +# +# Copyright (c) 2009-2014 Cisco Systems, Inc. All rights reserved. +# Copyright (c) 2014-2015 Intel, Inc. All rights reserved. +# +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# + +# +# Priority +# +AC_DEFUN([MCA_opal_hwloc_hwloc1110_PRIORITY], [90]) + +# +# Force this component to compile in static-only mode +# +AC_DEFUN([MCA_opal_hwloc_hwloc1110_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/hwloc1110/hwloc/config/hwloc.m4) +m4_include(opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_pkg.m4) +m4_include(opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_check_attributes.m4) +m4_include(opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_check_visibility.m4) +m4_include(opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_check_vendor.m4) +m4_include(opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_components.m4) + +# MCA_hwloc_hwloc1110_POST_CONFIG() +# --------------------------------- +AC_DEFUN([MCA_opal_hwloc_hwloc1110_POST_CONFIG],[ + OPAL_VAR_SCOPE_PUSH([opal_hwloc_hwloc1110_basedir]) + + # If we won, then do all the rest of the setup + AS_IF([test "$1" = "1" && test "$opal_hwloc_hwloc1110_support" = "yes"], + [ + # Set this variable so that the framework m4 knows what + # file to include in opal/mca/hwloc/hwloc.h + opal_hwloc_hwloc1110_basedir=opal/mca/hwloc/hwloc1110 + opal_hwloc_base_include="$opal_hwloc_hwloc1110_basedir/hwloc1110.h" + + # Add some stuff to CPPFLAGS so that the rest of the source + # tree can be built + file=$opal_hwloc_hwloc1110_basedir/hwloc + CPPFLAGS="$CPPFLAGS -I$OPAL_TOP_SRCDIR/$file/include" + AS_IF([test "$OPAL_TOP_BUILDDIR" != "$OPAL_TOP_SRCDIR"], + [CPPFLAGS="$CPPFLAGS -I$OPAL_TOP_BUILDDIR/$file/include"]) + unset file + ]) + OPAL_VAR_SCOPE_POP + + # This must be run unconditionally + HWLOC_DO_AM_CONDITIONALS +])dnl + + +# MCA_hwloc_hwloc1110_CONFIG([action-if-found], [action-if-not-found]) +# -------------------------------------------------------------------- +AC_DEFUN([MCA_opal_hwloc_hwloc1110_CONFIG],[ + # Hwloc needs to know if we have Verbs support + AC_REQUIRE([OPAL_CHECK_VERBS_DIR]) + + AC_CONFIG_FILES([opal/mca/hwloc/hwloc1110/Makefile]) + + OPAL_VAR_SCOPE_PUSH([HWLOC_VERSION opal_hwloc_hwloc1110_save_CPPFLAGS opal_hwloc_hwloc1110_save_LDFLAGS opal_hwloc_hwloc1110_save_LIBS opal_hwloc_hwloc1110_save_cairo opal_hwloc_hwloc1110_save_xml opal_hwloc_hwloc1110_basedir opal_hwloc_hwloc1110_file opal_hwloc_hwloc1110_save_cflags CPPFLAGS_save LIBS_save]) + + # default to this component not providing support + opal_hwloc_hwloc1110_basedir=opal/mca/hwloc/hwloc1110 + opal_hwloc_hwloc1110_support=no + + if test "$with_hwloc" = "internal" -o "$with_hwloc" = "" -o "$with_hwloc" = "yes"; then + opal_hwloc_hwloc1110_save_CPPFLAGS=$CPPFLAGS + opal_hwloc_hwloc1110_save_LDFLAGS=$LDFLAGS + opal_hwloc_hwloc1110_save_LIBS=$LIBS + + # Run the hwloc configuration - set the prefix to minimize + # the chance that someone will use the internal symbols + HWLOC_SET_SYMBOL_PREFIX([opal_hwloc1110_]) + + # save XML or graphical options + opal_hwloc_hwloc1110_save_cairo=$enable_cairo + opal_hwloc_hwloc1110_save_xml=$enable_xml + opal_hwloc_hwloc1110_save_static=$enable_static + opal_hwloc_hwloc1110_save_shared=$enable_shared + opal_hwloc_hwloc1110_save_plugins=$enable_plugins + + # never enable hwloc's graphical option + enable_cairo=no + + # never enable hwloc's plugin system + enable_plugins=no + enable_static=yes + enable_shared=no + + # Override -- disable hwloc's libxml2 support, but enable the + # native hwloc XML support + enable_libxml2=no + enable_xml=yes + + # hwloc checks for compiler visibility, and its needs to do + # this without "picky" flags. + opal_hwloc_hwloc1110_save_cflags=$CFLAGS + CFLAGS=$OPAL_CFLAGS_BEFORE_PICKY + HWLOC_SETUP_CORE([opal/mca/hwloc/hwloc1110/hwloc], + [AC_MSG_CHECKING([whether hwloc configure succeeded]) + AC_MSG_RESULT([yes]) + HWLOC_VERSION="internal v`$srcdir/$opal_hwloc_hwloc1110_basedir/hwloc/config/hwloc_get_version.sh $srcdir/$opal_hwloc_hwloc1110_basedir/hwloc/VERSION`" + + # Build flags for our Makefile.am + opal_hwloc_hwloc1110_LDFLAGS='$(HWLOC_EMBEDDED_LDFLAGS)' + opal_hwloc_hwloc1110_LIBS='$(OPAL_TOP_BUILDDIR)/'"$opal_hwloc_hwloc1110_basedir"'/hwloc/src/libhwloc_embedded.la $(HWLOC_EMBEDDED_LIBS)' + opal_hwloc_hwloc1110_support=yes + + AC_DEFINE_UNQUOTED([HWLOC_HWLOC1110_HWLOC_VERSION], + ["$HWLOC_VERSION"], + [Version of hwloc]) + + # Do we have verbs support? + CPPFLAGS_save=$CPPFLAGS + AS_IF([test "$opal_want_verbs" = "yes"], + [CPPFLAGS="-I$opal_verbs_dir/include $CPPFLAGS"]) + AC_CHECK_HEADERS([infiniband/verbs.h]) + CPPFLAGS=$CPPFLAGS_save + ], + [AC_MSG_CHECKING([whether hwloc configure succeeded]) + AC_MSG_RESULT([no]) + opal_hwloc_hwloc1110_support=no]) + CFLAGS=$opal_hwloc_hwloc1110_save_cflags + + # Restore some env variables, if necessary + AS_IF([test -n "$opal_hwloc_hwloc1110_save_cairo"], + [enable_cairo=$opal_hwloc_hwloc1110_save_cairo]) + AS_IF([test -n "$opal_hwloc_hwloc1110_save_xml"], + [enable_xml=$opal_hwloc_hwloc1110_save_xml]) + AS_IF([test -n "$opal_hwloc_hwloc1110_save_static"], + [enable_static=$opal_hwloc_hwloc1110_save_static]) + AS_IF([test -n "$opal_hwloc_hwloc1110_save_shared"], + [enable_shared=$opal_hwloc_hwloc1110_save_shared]) + AS_IF([test -n "$opal_hwloc_hwloc1110_save_plugins"], + [enable_plugins=$opal_hwloc_hwloc1110_save_shared]) + + CPPFLAGS=$opal_hwloc_hwloc1110_save_CPPFLAGS + LDFLAGS=$opal_hwloc_hwloc1110_save_LDFLAGS + LIBS=$opal_hwloc_hwloc1110_save_LIBS + + AC_SUBST([opal_hwloc_hwloc1110_CFLAGS]) + AC_SUBST([opal_hwloc_hwloc1110_CPPFLAGS]) + AC_SUBST([opal_hwloc_hwloc1110_LDFLAGS]) + AC_SUBST([opal_hwloc_hwloc1110_LIBS]) + + # Finally, add some flags to the wrapper compiler so that our + # headers can be found. + hwloc_hwloc1110_WRAPPER_EXTRA_LDFLAGS="$HWLOC_EMBEDDED_LDFLAGS" + hwloc_hwloc1110_WRAPPER_EXTRA_LIBS="$HWLOC_EMBEDDED_LIBS" + hwloc_hwloc1110_WRAPPER_EXTRA_CPPFLAGS='-I${includedir}/openmpi/'"$opal_hwloc_hwloc1110_basedir/hwloc/include" + fi + + # Done! + AS_IF([test "$opal_hwloc_hwloc1110_support" = "yes"], + [$1], + [$2]) + + OPAL_VAR_SCOPE_POP +])dnl diff --git a/opal/mca/hwloc/hwloc1110/hwloc/AUTHORS b/opal/mca/hwloc/hwloc1110/hwloc/AUTHORS new file mode 100644 index 0000000000..837b27f2ca --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/AUTHORS @@ -0,0 +1,8 @@ +Cédric Augonnet +Jérôme Clet-Ortega +Ludovic Courtès +Brice Goglin +Nathalie Furmento +Samuel Thibault +Jeff Squyres +Alexey Kardashevskiy diff --git a/opal/mca/hwloc/hwloc1110/hwloc/COPYING b/opal/mca/hwloc/hwloc1110/hwloc/COPYING new file mode 100644 index 0000000000..694a7bd774 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/COPYING @@ -0,0 +1,28 @@ +Copyright © 2009 CNRS +Copyright © 2009 inria. All rights reserved. +Copyright © 2009 Université Bordeaux +Copyright © 2009 Cisco Systems, Inc. All rights reserved. +Copyright © 2012 Blue Brain Project, EPFL. All rights reserved. +See COPYING in top-level directory. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/opal/mca/hwloc/hwloc1110/hwloc/Makefile.am b/opal/mca/hwloc/hwloc1110/hwloc/Makefile.am new file mode 100644 index 0000000000..69ae667548 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/Makefile.am @@ -0,0 +1,75 @@ +# Copyright © 2009-2015 Inria. All rights reserved. +# Copyright © 2009 Université Bordeaux +# Copyright © 2009-2014 Cisco Systems, Inc. All rights reserved. +# See COPYING in top-level directory. + +# Note that the -I directory must *exactly* match what was specified +# via AC_CONFIG_MACRO_DIR in configure.ac. +ACLOCAL_AMFLAGS = -I ./config + +SUBDIRS = src include +if HWLOC_BUILD_STANDALONE +SUBDIRS += tests utils +# 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 +endif + +# Do not let automake automatically add the non-standalone dirs to the +# distribution tarball if we're building in embedded mode. +DIST_SUBDIRS = $(SUBDIRS) + +# Only install the pkg file if we're building in standalone mode (and not on Windows) +if HWLOC_BUILD_STANDALONE +if !HWLOC_HAVE_WINDOWS +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = hwloc.pc +endif +endif + +# 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 +if HWLOC_BUILD_STANDALONE +EXTRA_DIST += contrib/windows +endif + +if HWLOC_BUILD_STANDALONE +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 +# +# Winball specific rules +# +install-data-local: + sed -e 's/$$/'$$'\015'/ < $(srcdir)/README > $(DESTDIR)$(prefix)/README.txt + sed -e 's/$$/'$$'\015'/ < $(srcdir)/NEWS > $(DESTDIR)$(prefix)/NEWS.txt + sed -e 's/$$/'$$'\015'/ < $(srcdir)/COPYING > $(DESTDIR)$(prefix)/COPYING.txt +uninstall-local: + rm -f $(DESTDIR)$(prefix)/README.txt $(DESTDIR)$(prefix)/NEWS.txt $(DESTDIR)$(prefix)/COPYING.txt +endif HWLOC_HAVE_WINDOWS +endif HWLOC_BUILD_STANDALONE diff --git a/opal/mca/hwloc/hwloc1110/hwloc/NEWS b/opal/mca/hwloc/hwloc1110/hwloc/NEWS new file mode 100644 index 0000000000..01df3258ae --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/NEWS @@ -0,0 +1,1156 @@ +Copyright © 2009 CNRS +Copyright © 2009-2015 Inria. All rights reserved. +Copyright © 2009-2013 Université Bordeaux +Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved. + +$COPYRIGHT$ + +Additional copyrights may follow + +$HEADER$ + +=========================================================================== + +This file contains the main features as well as overviews of specific +bug fixes (and other actions) for each version of hwloc since version +0.9 (as initially released as "libtopology", then re-branded to "hwloc" +in v0.9.1). + + +Version 1.11.0 +-------------- +* API + + Socket objects are renamed into Package to align with the terminology + used by processor vendors. The old HWLOC_OBJ_SOCKET type and "Socket" + name are still supported for backward compatibility. + + HWLOC_OBJ_NODE is replaced with HWLOC_OBJ_NUMANODE for clarification. + HWLOC_OBJ_NODE is still supported for backward compatibility. + "Node" and "NUMANode" strings are supported as in earlier releases. +* Detection improvements + + Add support for Intel Knights Landing Xeon Phi. + Thanks to Grzegorz Andrejczuk and Lukasz Anaczkowski. + + Add Vendor, Model, Revision, SerialNumber, Type and LinuxDeviceID + info attributes to Block OS devices on Linux. Thanks to Vineet Pedaballe + for the help. + - Add --disable-libudev to avoid dependency on the libudev library. + + Add "MemoryDevice" Misc objects with information about DIMMs, on Linux + when privileged and when I/O is enabled. + Thanks to Vineet Pedaballe for the help. + + Add a PCISlot attribute to PCI devices on Linux when supported to + identify the physical PCI slot where the board is plugged. + + Add CPUStepping info attribute on x86 processors, + thanks to Thomas Röhl for the suggestion. + + Ignore the device-tree on non-Power architectures to avoid buggy + detection on ARM. Thanks to Orion Poplawski for reporting the issue. + + Work-around buggy Xeon E5v3 BIOS reporting invalid PCI-NUMA affinity + for the PCI links on the second processor. + + Add support for CUDA compute capability 5.x, thanks Benjamin Worpitz. + + Many fixes to the x86 backend + - Add L1i and fix L2/L3 type on old AMD processors without topoext support. + - Fix Intel CPU family and model numbers when basic family isn't 6 or 15. + - Fix package IDs on recent AMD processors. + - Fix misc issues due to incomplete APIC IDs on x2APIC processors. + - Avoid buggy discovery on old SGI Altix UVs with non-unique APIC IDs. + + Gather total machine memory on NetBSD. +* Tools + + lstopo + - Collapse identical PCI devices unless --no-collapse is given. + This avoids gigantic outputs when a PCI device contains dozens of + identical virtual functions. + - The ASCII art output is now called "ascii", for instance in + "lstopo -.ascii". + The former "txt" extension is retained for backward compatibility. + - Automatically scales graphical box width to the inner text in Cairo, + ASCII and Windows outputs. + - Add --rect to lstopo to force rectangular layout even for NUMA nodes. + - Objects may have a Type info attribute to specific a better type name + and display it in lstopo. + + hwloc-annotate + - May now operate on all types of objects, including I/O. + - May now insert Misc objects in the topology. + - Do not drop instruction caches and I/O devices from the output anymore. + + Fix lstopo path in hwloc-gather-topology after install. +* Misc + + Fix PCI Bridge-specific depth attribute. + + Fix hwloc_bitmap_intersect() for two infinite bitmaps. + + Improve the performance of object insertion by cpuset for large + topologies. + + Prefix verbose XML import errors with the source name. + + Improve pkg-config checks and error messages. + + Fix excluding after a component with an argument in the HWLOC_COMPONENTS + environment variable. + + Fix the recommended way in documentation and examples to allocate memory + on some node, it should use HWLOC_MEMBIND_BIND. + Thanks to Nicolas Bouzat for reporting the issue. + + Add a "Miscellaneous objects" section in the documentation. + + Add a FAQ entry "What happens to my topology if I disable symmetric + multithreading, hyper-threading, etc. ?" to the documentation. + + +Version 1.10.1 +-------------- +* Actually remove disallowed NUMA nodes from nodesets when the whole-system + flag isn't enabled. +* Fix the gathering of PCI domains. Thanks to James Custer for reporting + the issue and providing a patch. +* Fix the merging of identical parent and child in presence of Misc objects. + Thanks to Dave Love for reporting the issue. +* Fix some misordering of children when merging with ignore_keep_structure() + in partially allowed topologies. +* Fix an overzealous assertion in the debug code when running on a single-PU + host with I/O. Thanks to Thomas Van Doren for reporting the issue. +* Don't forget to setup NUMA node object nodesets in x86 backend (for BSDs) + and OSF/Tru64 backend. +* Fix cpuid-x86 build error with gcc -O3 on x86-32. Thanks to Thomas Van Doren + for reporting the issue. +* Fix support for future very large caches in the x86 backend. +* Fix vendor/device names for SR-IOV PCI devices on Linux. +* Fix an unlikely crash in case of buggy hierarchical distance matrix. +* Fix PU os_index on some AIX releases. Thanks to Hendryk Bockelmann and + Erik Schnetter for helping debugging. +* Fix hwloc_bitmap_isincluded() in case of infinite sets. +* Change hwloc-ls.desktop into a lstopo.desktop and only install it if + lstopo is built with Cairo/X11 support. It cannot work with a non-graphical + lstopo or hwloc-ls. +* Add support for the renaming of Socket into Package in future releases. +* Add support for the replacement of HWLOC_OBJ_NODE with HWLOC_OBJ_NUMANODE + in future releases. +* Clarify the documentation of distance matrices in hwloc.h and in the manpage + of the hwloc-distances. Thanks to Dave Love for the suggestion. +* Improve some error messages by displaying more information about the + hwloc library in use. +* Document how to deal with the ABI break when upgrading to the upcoming 2.0 + See "How do I handle ABI breaks and API upgrades ?" in the FAQ. + + +Version 1.10.0 +-------------- +* API + + Add hwloc_topology_export_synthetic() to export a topology to a + synthetic string without using lstopo. See the Synthetic topologies + section in the documentation. + + Add hwloc_topology_set/get_userdata() to let the application save + a private pointer in the topology whenever it needs a way to find + its own object corresponding to a topology. + + Add hwloc_get_numanode_obj_by_os_index() and document that this function + as well as hwloc_get_pu_obj_by_os_index() are good at converting + nodesets and cpusets into objects. + + hwloc_distrib() does not ignore any objects anymore when there are + too many of them. They get merged with others instead. + Thanks to Tim Creech for reporting the issue. +* Tools + + hwloc-bind --get now executes the command after displaying + the binding instead of ignoring the command entirely. + Thanks to John Donners for the suggestion. + + Clarify that memory sizes shown in lstopo are local by default + unless specified (total memory added in the root object). +* Synthetic topologies + + Synthetic topology descriptions may now specify attributes such as + memory sizes and OS indexes. See the Synthetic topologies section + in the documentation. + + lstopo now exports in this fully-detailed format by default. + The new option --export-synthetic-flags may be used to revert + back the old format. +* Documentation + + Add the doc/examples/ subdirectory with several real-life examples, + including the already existing hwloc-hello.C for basics. + Thanks to Rob Aulwes for the suggestion. + + Improve the documentation of CPU and memory binding in the API. + + Add a FAQ entry about operating system errors, especially on AMD + platforms with buggy cache information. + + Add a FAQ entry about loading many topologies in a single program. +* Misc + + Work around buggy Linux kernels reporting 2 sockets instead + 1 socket with 2 NUMA nodes for each Xeon E5 v3 (Haswell) processor. + + pciutils/libpci support is now removed since libpciaccess works + well and there's also a Linux-specific PCI backend. For the record, + pciutils was GPL and therefore disabled by default since v1.6.2. + + Add --disable-cpuid configure flag to work around buggy processor + simulators reporting invalid CPUID information. + Thanks for Andrew Friedley for reporting the issue. + + Fix a racy use of libltdl when manipulating multiple topologies in + different threads. + Thanks to Andra Hugo for reporting the issue and testing patches. + + Fix some build failures in private/misc.h. + Thanks to Pavan Balaji and Ralph Castain for the reports. + + Fix failures to detect X11/Xutil.h on some Solaris platforms. + Thanks to Siegmar Gross for reporting the failure. + + The plugin ABI has changed, this release will not load plugins + built against previous hwloc releases. + + +Version 1.9.1 +------------- +* Fix a crash when the PCI locality is invalid. Attach to the root object + instead. Thanks to Nicolas Denoyelle for reporting the issue. +* Fix -f in lstopo manpage. Thanks to Jirka Hladky for reporting the issue. +* Fix hwloc_obj_type_sscanf() and others when strncasecmp() is not properly + available. Thanks to Nick Papior Andersen for reporting the problem. +* Mark Linux file descriptors as close-on-exec to avoid leaks on exec. +* Fix some minor memory leaks. + + +Version 1.9.0 +------------- +* API + + Add hwloc_obj_type_sscanf() to extend hwloc_obj_type_of_string() with + type-specific attributes such as Cache/Group depth and Cache type. + hwloc_obj_type_of_string() is moved to hwloc/deprecated.h. + + Add hwloc_linux_get_tid_last_cpu_location() for retrieving the + last CPU where a Linux thread given by TID ran. + + Add hwloc_distrib() to extend the old hwloc_distribute[v]() functions. + hwloc_distribute[v]() is moved to hwloc/deprecated.h. + + Don't mix total and local memory when displaying verbose object attributes + with hwloc_obj_attr_snprintf() or in lstopo. +* Backends + + Add CPUVendor, CPUModelNumber and CPUFamilyNumber info attributes for + x86, ia64 and Xeon Phi sockets on Linux, to extend the x86-specific + support added in v1.8.1. Requested by Ralph Castain. + + Add many CPU- and Platform-related info attributes on ARM and POWER + platforms, in the Machine and Socket objects. + + Add CUDA info attributes describing the number of multiprocessors and + cores and the size of the global, shared and L2 cache memories in CUDA + OS devices. + + Add OpenCL info attributes describing the number of compute units and + the global memory size in OpenCL OS devices. + + The synthetic backend now accepts extended types such as L2Cache, L1i or + Group3. lstopo also exports synthetic strings using these extended types. +* Tools + + lstopo + - Do not overwrite output files by default anymore. + Pass -f or --force to enforce it. + - Display OpenCL, CUDA and Xeon Phi numbers of cores and memory sizes + in the graphical output. + - Fix export to stdout when specifying a Cairo-based output type + with --of. + + hwloc-ps + - Add -e or --get-last-cpu-location to report where processes/threads + run instead of where they are bound. + - Report locations as likely-more-useful objects such as Cores or Sockets + instead of Caches when possible. + + hwloc-bind + - Fix failure on Windows when not using --pid. + - Add -e as a synonym to --get-last-cpu-location. + + hwloc-distrib + - Add --reverse to distribute using last objects first and singlify + into last bits first. Thanks to Jirka Hladky for the suggestion. + + hwloc-info + - Report unified caches when looking for data or instruction cache + ancestor objects. +* Misc + + Add experimental Visual Studio support under contrib/windows. + Thanks to Eloi Gaudry for his help and for providing the first draft. + + Fix some overzealous assertions and warnings about the ordering of + objects on a level with respect to cpusets. The ordering is only + guaranteed for complete cpusets (based on the first bit in sets). + + Fix some memory leaks when importing xml diffs and when exporting a + "too complex" entry. + + +Version 1.8.1 +------------- +* Fix the cpuid code on Windows 64bits so that the x86 backend gets + enabled as expected and can populate CPU information. + Thanks to Robin Scher for reporting the problem. +* Add CPUVendor/CPUModelNumber/CPUFamilyNumber attributes when running + on x86 architecture. Thanks to Ralph Castain for the suggestion. +* Work around buggy BIOS reporting duplicate NUMA nodes on Linux. + Thanks to Jeff Becker for reporting the problem and testing the patch. +* Add a name to the lstopo graphical window. Thanks to Michael Prokop + for reporting the issue. + + +Version 1.8.0 +------------- +* New components + + Add the "linuxpci" component that always works on Linux even when + libpciaccess and libpci aren't available (and even with a modified + file-system root). By default the old "pci" component runs first + because "linuxpci" lacks device names (obj->name is always NULL). +* API + + Add the topology difference API in hwloc/diff.h for manipulating + many similar topologies. + + Add hwloc_topology_dup() for duplicating an entire topology. + + hwloc.h and hwloc/helper.h have been reorganized to clarify the + documentation sections. The actual inline code has moved out of hwloc.h + into the new hwloc/inlines.h. + + Deprecated functions are now in hwloc/deprecated.h, and not in the + official documentation anymore. +* Tools + + Add hwloc-diff and hwloc-patch tools together with the new diff API. + + Add hwloc-compress-dir to (de)compress an entire directory of XML files + using hwloc-diff and hwloc-patch. + + Object colors in the graphical output of lstopo may be changed by adding + a "lstopoStyle" info attribute. See CUSTOM COLORS in the lstopo(1) manpage + for details. Thanks to Jirka Hladky for discussing the idea. + + hwloc-gather-topology may now gather I/O-related files on Linux when + --io is given. Only the linuxpci component supports discovering I/O + objects from these extended tarballs. + + hwloc-annotate now supports --ri to remove/replace info attributes with + a given name. + + hwloc-info supports "root" and "all" special locations for dumping + information about the root object. + + lstopo now supports --append-legend to append custom lines of text + to the legend in the graphical output. Thanks to Jirka Hladky for + discussing the idea. + + hwloc-calc and friends have a more robust parsing of locations given + on the command-line and they report useful error messages about it. + + Add --whole-system to hwloc-bind, hwloc-calc, hwloc-distances and + hwloc-distrib, and add --restrict to hwloc-bind for uniformity among + tools. +* Misc + + Calling hwloc_topology_load() or hwloc_topology_set_*() on an already + loaded topology now returns an error (deprecated since release 1.6.1). + + Fix the initialisation of cpusets and nodesets in Group objects added + when inserting PCI hostbridges. + + Never merge Group objects that were added explicitly by the user with + hwloc_custom_insert_group_object_by_parent(). + + Add a sanity check during dynamic plugin loading to prevent some + crashes when hwloc is dynamically loaded by another plugin mechanisms. + + Add --with-hwloc-plugins-path to specify the install/load directories + of plugins. + + Add the MICSerialNumber info attribute to the root object when running + hwloc inside a Xeon Phi to match the same attribute in the MIC OS device + when running in the host. + + +Version 1.7.2 +------------- +* Do not create invalid block OS devices on very old Linux kernel such + as RHEL4 2.6.9. +* Fix PCI subvendor/device IDs. +* Fix the management of Misc objects inserted by parent. + Thanks to Jirka Hladky for reporting the problem. +* Add a PortState into attribute to OpenFabrics OS devices. +* Add a MICSerialNumber info attribute to Xeon PHI/MIC OS devices. +* Improve verbose error messages when failing to load from XML. + + +Version 1.7.1 +------------- +* Fix a failed assertion in the distance grouping code when loading a XML + file that already contains some groups. + Thanks to Laercio Lima Pilla for reporting the problem. +* Remove unexpected Group objects when loading XML topologies with I/O + objects and NUMA distances. + Thanks to Elena Elkina for reporting the problem and testing patches. +* Fix PCI link speed discovery when using libpciaccess. +* Fix invalid libpciaccess virtual function device/vendor IDs when using + SR-IOV PCI devices on Linux. +* Fix GL component build with old NVCtrl releases. + Thanks to Jirka Hladky for reporting the problem. +* Fix embedding breakage caused by libltdl. + Thanks to Pavan Balaji for reporting the problem. +* Always use the system-wide libltdl instead of shipping one inside hwloc. +* Document issues when enabling plugins while embedding hwloc in another + project, in the documentation section Embedding hwloc in Other Software. +* Add a FAQ entry "How to get useful topology information on NetBSD?" + in the documentation. +* Somes fixes in the renaming code for embedding. +* Miscellaneous minor build fixes. + + +Version 1.7.0 +------------- +* New operating system backends + + Add BlueGene/Q compute node kernel (CNK) support. See the FAQ in the + documentation for details. Thanks to Jeff Hammond, Christopher Samuel + and Erik Schnetter for their help. + + Add NetBSD support, thanks to Aleksej Saushev. +* New I/O device discovery + + Add co-processor OS devices such as "mic0" for Intel Xeon Phi (MIC) + on Linux. Thanks to Jerome Vienne for helping. + + Add co-processor OS devices such as "cuda0" for NVIDIA CUDA-capable GPUs. + + Add co-processor OS devices such as "opencl0d0" for OpenCL GPU devices + on the AMD OpenCL implementation. + + Add GPU OS devices such as ":0.0" for NVIDIA X11 displays. + + Add GPU OS devices such as "nvml0" for NVIDIA GPUs. + Thanks to Marwan Abdellah and Stefan Eilemann for helping. + These new OS devices have some string info attributes such as CoProcType, + GPUModel, etc. to better identify them. + See the I/O Devices and Attributes documentation sections for details. +* New components + + Add the "opencl", "cuda", "nvml" and "gl" components for I/O device + discovery. + + "nvml" also improves the discovery of NVIDIA GPU PCIe link speed. + All of these new components may be built as plugins. They may also be + disabled entirely by passing --disable-opencl/cuda/nvml/gl to configure. + See the I/O Devices, Components and Plugins, and FAQ documentation + sections for details. +* API + + Add hwloc_topology_get_flags(). + + Add hwloc/plugins.h for building external plugins. + See the Adding new discovery components and plugins section. +* Interoperability + + Add hwloc/opencl.h, hwloc/nvml.h, hwloc/gl.h and hwloc/intel-mic.h + to retrieve the locality of OS devices that correspond to AMD OpenCL + GPU devices or indexes, to NVML devices or indexes, to NVIDIA X11 + displays, or to Intel Xeon Phi (MIC) device indexes. + + Add new helpers in hwloc/cuda.h and hwloc/cudart.h to convert + between CUDA devices or indexes and hwloc OS devices. + + Add hwloc_ibv_get_device_osdev() and clarify the requirements + of the OpenFabrics Verbs helpers in hwloc/openfabrics-verbs.h. +* Tools + + hwloc-info is not only a synonym of lstopo -s anymore, it also + dumps information about objects given on the command-line. +* Documentation + + Add a section "Existing components and plugins". + + Add a list of common OS devices in section "Software devices". + + Add a new FAQ entry "Why is lstopo slow?" about lstopo slowness + issues because of GPUs. + + Clarify the documentation of inline helpers in hwloc/myriexpress.h + and hwloc/openfabrics-verbs.h. +* Misc + + Improve cache detection on AIX. + + The HWLOC_COMPONENTS variable now excludes the components whose + names are prefixed with '-'. + + lstopo --ignore PU now works when displaying the topology in + graphical and textual mode (not when exporting to XML). + + Make sure I/O options always appear in lstopo usage, not only when + using pciutils/libpci. + + Remove some unneeded Linux specific includes from some interoperability + headers. + + Fix some inconsistencies in hwloc-distrib and hwloc-assembler-remote + manpages. Thanks to Guy Streeter for the report. + + Fix a memory leak on AIX when getting memory binding. + + Fix many small memory leaks on Linux. + + The `libpci' component is now called `pci' but the old name is still + accepted in the HWLOC_COMPONENTS variable for backward compatibility. + + +Version 1.6.2 +------------- +* Use libpciaccess instead of pciutils/libpci by default for I/O discovery. + pciutils/libpci is only used if --enable-libpci is given to configure + because its GPL license may taint hwloc. See the Installation section + in the documentation for details. +* Fix get_cpubind on Solaris when bound to a single PU with + processor_bind(). Thanks to Eugene Loh for reporting the problem + and providing a patch. + + +Version 1.6.1 +------------- +* Fix some crash or buggy detection in the x86 backend when Linux + cgroups/cpusets restrict the available CPUs. +* Fix the pkg-config output with --libs --static. + Thanks to Erik Schnetter for reporting one of the problems. +* Fix the output of hwloc-calc -H --hierarchical when using logical + indexes in the output. +* Calling hwloc_topology_load() multiple times on the same topology + is officially deprecated. hwloc will warn in such cases. +* Add some documentation about existing plugins/components, package + dependencies, and I/O devices specification on the command-line. + + +Version 1.6.0 +------------- +* Major changes + + Reorganize the backend infrastructure to support dynamic selection + of components and dynamic loading of plugins. For details, see the + new documentation section Components and plugins. + - The HWLOC_COMPONENTS variable lets one replace the default discovery + components. + - Dynamic loading of plugins may be enabled with --enable-plugins + (except on AIX and Windows). It will build libxml2 and libpci + support as separated modules. This helps reducing the dependencies + of the core hwloc library when distributed as a binary package. +* Backends + + Add CPUModel detection on Darwin and x86/FreeBSD. + Thanks to Robin Scher for providing ways to implement this. + + The x86 backend now adds CPUModel info attributes to socket objects + created by other backends that do not natively support this attribute. + + Fix detection on FreeBSD in case of cpuset restriction. Thanks to + Sebastian Kuzminsky for reporting the problem. +* XML + + Add hwloc_topology_set_userdata_import/export_callback(), + hwloc_export_obj_userdata() and _userdata_base64() to let + applications specify how to save/restore the custom data they placed + in the userdata private pointer field of hwloc objects. +* Tools + + Add hwloc-annotate program to add string info attributes to XML + topologies. + + Add --pid-cmd to hwloc-ps to append the output of a command to each + PID line. May be used for showing Open MPI process ranks, see the + hwloc-ps(1) manpage for details. + + hwloc-bind now exits with an error if binding fails; the executable + is not launched unless binding suceeeded or --force was given. + + Add --quiet to hwloc-calc and hwloc-bind to hide non-fatal error + messages. + + Fix command-line pid support in windows tools. + + All programs accept --verbose as a synonym to -v. +* Misc + + Fix some DIR descriptor leaks on Linux. + + Fix I/O device lists when some were filtered out after a XML import. + + Fix the removal of I/O objects when importing a I/O-enabled XML topology + without any I/O topology flag. + + When merging objects with HWLOC_IGNORE_TYPE_KEEP_STRUCTURE or + lstopo --merge, compare object types before deciding which one of two + identical object to remove (e.g. keep sockets in favor of caches). + + Add some GUID- and LID-related info attributes to OpenFabrics + OS devices. + + Only add CPUType socket attributes on Solaris/Sparc. Other cases + don't report reliable information (Solaris/x86), and a replacement + is available as the Architecture string info in the Machine object. + + Add missing Backend string info on Solaris in most cases. + + Document object attributes and string infos in a new Attributes + section in the documentation. + + Add a section about Synthetic topologies in the documentation. + + +Version 1.5.2 (some of these changes are in v1.6.2 but not in v1.6) +------------- +* Use libpciaccess instead of pciutils/libpci by default for I/O discovery. + pciutils/libpci is only used if --enable-libpci is given to configure + because its GPL license may taint hwloc. See the Installation section + in the documentation for details. +* Fix get_cpubind on Solaris when bound to a single PU with + processor_bind(). Thanks to Eugene Loh for reporting the problem + and providing a patch. +* Fix some DIR descriptor leaks on Linux. +* Fix I/O device lists when some were filtered out after a XML import. +* Add missing Backend string info on Solaris in most cases. +* Fix the removal of I/O objects when importing a I/O-enabled XML topology + without any I/O topology flag. +* Fix the output of hwloc-calc -H --hierarchical when using logical + indexes in the output. +* Fix the pkg-config output with --libs --static. + Thanks to Erik Schnetter for reporting one of the problems. + + +Version 1.5.1 +------------- +* Fix block OS device detection on Linux kernel 3.3 and later. + Thanks to Guy Streeter for reporting the problem and testing the fix. +* Fix the cpuid code in the x86 backend (for FreeBSD). Thanks to + Sebastian Kuzminsky for reporting problems and testing patches. +* Fix 64bit detection on FreeBSD. +* Fix some corner cases in the management of the thissystem flag with + respect to topology flags and environment variables. +* Fix some corner cases in command-line parsing checks in hwloc-distrib + and hwloc-distances. +* Make sure we do not miss some block OS devices on old Linux kernels + when a single PCI device has multiple IDE hosts/devices behind it. +* Do not disable I/O devices or instruction caches in hwloc-assembler output. + + +Version 1.5.0 +------------- +* Backends + + Do not limit the number of processors to 1024 on Solaris anymore. + + Gather total machine memory on FreeBSD. Thanks to Cyril Roelandt. + + XML topology files do not depend on the locale anymore. Float numbers + such as NUMA distances or PCI link speeds now always use a dot as a + decimal separator. + + Add instruction caches detection on Linux, AIX, Windows and Darwin. + + Add get_last_cpu_location() support for the current thread on AIX. + + Support binding on AIX when threads or processes were bound with + bindprocessor(). Thanks to Hendryk Bockelmann for reporting the issue + and testing patches, and to Farid Parpia for explaining the binding + interfaces. + + Improve AMD topology detection in the x86 backend (for FreeBSD) using + the topoext feature. +* API + + Increase HWLOC_API_VERSION to 0x00010500 so that API changes may be + detected at build-time. + + Add a cache type attribute describind Data, Instruction and Unified + caches. Caches with different types but same depth (for instance L1d + and L1i) are placed on different levels. + + Add hwloc_get_cache_type_depth() to retrieve the hwloc level depth of + of the given cache depth and type, for instance L1i or L2. + It helps disambiguating the case where hwloc_get_type_depth() returns + HWLOC_TYPE_DEPTH_MULTIPLE. + + Instruction caches are ignored unless HWLOC_TOPOLOGY_FLAG_ICACHES is + passed to hwloc_topology_set_flags() before load. + + Add hwloc_ibv_get_device_osdev_by_name() OpenFabrics helper in + openfabrics-verbs.h to find the hwloc OS device object corresponding to + an OpenFabrics device. +* Tools + + Add lstopo-no-graphics, a lstopo built without graphical support to + avoid dependencies on external libraries such as Cairo and X11. When + supported, graphical outputs are only available in the original lstopo + program. + - Packagers splitting lstopo and lstopo-no-graphics into different + packages are advised to use the alternatives system so that lstopo + points to the best available binary. + + Instruction caches are enabled in lstopo by default. Use --no-icaches + to disable them. + + Add -t/--threads to show threads in hwloc-ps. +* Removal of obsolete components + + Remove the old cpuset interface (hwloc/cpuset.h) which is deprecated and + superseded by the bitmap API (hwloc/bitmap.h) since v1.1. + hwloc_cpuset and nodeset types are still defined, but all hwloc_cpuset_* + compatibility wrappers are now gone. + + Remove Linux libnuma conversion helpers for the deprecated and + broken nodemask_t interface. + + Remove support for "Proc" type name, it was superseded by "PU" in v1.0. + + Remove hwloc-mask symlinks, it was replaced by hwloc-calc in v1.0. +* Misc + + Fix PCIe 3.0 link speed computation. + + Non-printable characters are dropped from strings during XML export. + + Fix importing of escaped characters with the minimalistic XML backend. + + Assert hwloc_is_thissystem() in several I/O related helpers. + + Fix some memory leaks in the x86 backend for FreeBSD. + + Minor fixes to ease native builds on Windows. + + Limit the number of retries when operating on all threads within a + process on Linux if the list of threads is heavily getting modified. + + +Version 1.4.3 +------------- +* This release is only meant to fix the pciutils license issue when upgrading + to hwloc v1.5 or later is not possible. It contains several other minor + fixes but ignores many of them that are only in v1.5 or later. +* Use libpciaccess instead of pciutils/libpci by default for I/O discovery. + pciutils/libpci is only used if --enable-libpci is given to configure + because its GPL license may taint hwloc. See the Installation section + in the documentation for details. +* Fix PCIe 3.0 link speed computation. +* Fix importing of escaped characters with the minimalistic XML backend. +* Fix a memory leak in the x86 backend. + + +Version 1.4.2 +------------- +* Fix build on Solaris 9 and earlier when fabsf() is not a compiler + built-in. Thanks to Igor Galić for reporting the problem. +* Fix support for more than 32 processors on Windows. Thanks to Hartmut + Kaiser for reporting the problem. +* Fix process-wide binding and cpulocation routines on Linux when some + threads disappear in the meantime. Thanks to Vlad Roubtsov for reporting + the issue. +* Make installed scripts executable. Thanks to Jirka Hladky for reporting + the problem. +* Fix libtool revision management when building for Windows. This fix was + also released as hwloc v1.4.1.1 Windows builds. Thanks to Hartmut Kaiser + for reporting the problem. +* Fix the __hwloc_inline keyword in public headers when compiling with a + C++ compiler. +* Add Port info attribute to network OS devices inside OpenFabrics PCI + devices so as to identify which interface corresponds to which port. +* Document requirements for interoperability helpers: I/O devices discovery + is required for some of them; the topology must match the current host + for most of them. + + +Version 1.4.1 +------------- +* This release contains all changes from v1.3.2. +* Fix hwloc_alloc_membind, thanks Karl Napf for reporting the issue. +* Fix memory leaks in some get_membind() functions. +* Fix helpers converting from Linux libnuma to hwloc (hwloc/linux-libnuma.h) + in case of out-of-order NUMA node ids. +* Fix some overzealous assertions in the distance grouping code. +* Workaround BIOS reporting empty I/O locality in CUDA and OpenFabrics + helpers on Linux. Thanks to Albert Solernou for reporting the problem. +* Install a valgrind suppressions file hwloc-valgrind.supp (see the FAQ). +* Fix memory binding documentation. Thanks to Karl Napf for reporting the + issues. + + +Version 1.4.0 (does not contain all v1.3.2 changes) +------------- +* Major features + + Add "custom" interface and "assembler" tools to build multi-node + topology. See the Multi-node Topologies section in the documentation + for details. +* Interface improvements + + Add symmetric_subtree object attribute to ease assumptions when consulting + regular symmetric topologies. + + Add a CPUModel and CPUType info attribute to Socket objects on Linux + and Solaris. + + Add hwloc_get_obj_index_inside_cpuset() to retrieve the "logical" index + of an object within a subtree of the topology. + + Add more NVIDIA CUDA helpers in cuda.h and cudart.h to find hwloc objects + corresponding to CUDA devices. +* Discovery improvements + + Add a group object above partial distance matrices to make sure + the matrices are available in the final topology, except when this + new object would contradict the existing hierarchy. + + Grouping by distances now also works when loading from XML. + + Fix some corner cases in object insertion, for instance when dealing + with NUMA nodes without any CPU. +* Backends + + Implement hwloc_get_area_membind() on Linux. + + Honor I/O topology flags when importing from XML. + + Further improve XML-related error checking and reporting. + + Hide synthetic topology error messages unless HWLOC_SYNTHETIC_VERBOSE=1. +* Tools + + Add synthetic exporting of symmetric topologies to lstopo. + + lstopo --horiz and --vert can now be applied to some specific object types. + + lstopo -v -p now displays distance matrices with physical indexes. + + Add hwloc-distances utility to list distances. +* Documentation + + Fix and/or document the behavior of most inline functions in hwloc/helper.h + when the topology contains some I/O or Misc objects. + + Backend documentation enhancements. +* Bug fixes + + Fix missing last bit in hwloc_linux_get_thread_cpubind(). + Thanks to Carolina Gómez-Tostón Gutiérrez for reporting the issue. + + Fix FreeBSD build without cpuid support. + + Fix several Windows build issues. + + Fix inline keyword definition in public headers. + + Fix dependencies in the embedded library. + + Improve visibility support detection. Thanks to Dave Love for providing + the patch. + + Remove references to internal symbols in the tools. + + +Version 1.3.3 +------------- +* This release is only meant to fix the pciutils license issue when upgrading + to hwloc v1.4 or later is not possible. It contains several other minor + fixes but ignores many of them that are only in v1.4 or later. +* Use libpciaccess instead of pciutils/libpci by default for I/O discovery. + pciutils/libpci is only used if --enable-libpci is given to configure + because its GPL license may taint hwloc. See the Installation section + in the documentation for details. + + +Version 1.3.2 +------------- +* Fix missing last bit in hwloc_linux_get_thread_cpubind(). + Thanks to Carolina Gómez-Tostón Gutiérrez for reporting the issue. +* Fix build with -mcmodel=medium. Thanks to Devendar Bureddy for reporting + the issue. +* Fix build with Solaris Studio 12 compiler when XML is disabled. + Thanks to Paul H. Hargrove for reporting the problem. +* Fix installation with old GNU sed, for instance on Red Hat 8. + Thanks to Paul H. Hargrove for reporting the problem. +* Fix PCI locality when Linux cgroups restrict the available CPUs. +* Fix floating point issue when grouping by distance on mips64 architecture. + Thanks to Paul H. Hargrove for reporting the problem. +* Fix conversion from/to Linux libnuma when some NUMA nodes have no memory. +* Fix support for gccfss compilers with broken ffs() support. Thanks to + Paul H. Hargrove for reporting the problem and providing a patch. +* Fix FreeBSD build without cpuid support. +* Fix several Windows build issues. +* Fix inline keyword definition in public headers. +* Fix dependencies in the embedded library. +* Detect when a compiler such as xlc may not report compile errors + properly, causing some configure checks to be wrong. Thanks to + Paul H. Hargrove for reporting the problem and providing a patch. +* Improve visibility support detection. Thanks to Dave Love for providing + the patch. +* Remove references to internal symbols in the tools. +* Fix installation on systems with limited command-line size. + Thanks to Paul H. Hargrove for reporting the problem. +* Further improve XML-related error checking and reporting. + + +Version 1.3.1 +------------- +* Fix pciutils detection with pkg-config when not installed in standard + directories. +* Fix visibility options detection with the Solaris Studio compiler. + Thanks to Igor Galić and Terry Dontje for reporting the problems. +* Fix support for old Linux sched.h headers such as those found + on Red Hat 8. Thanks to Paul H. Hargrove for reporting the problems. +* Fix inline and attribute support for Solaris compilers. Thanks to + Dave Love for reporting the problems. +* Print a short summary at the end of the configure output. Thanks to + Stefan Eilemann for the suggestion. +* Add --disable-libnuma configure option to disable libnuma-based + memory binding support on Linux. Thanks to Rayson Ho for the + suggestion. +* Make hwloc's configure script properly obey $PKG_CONFIG. Thanks to + Nathan Phillip Brink for raising the issue. +* Silence some harmless pciutils warnings, thanks to Paul H. Hargrove + for reporting the problem. +* Fix the documentation with respect to hwloc_pid_t and hwloc_thread_t + being either pid_t and pthread_t on Unix, or HANDLE on Windows. + + +Version 1.3.0 +------------- +* Major features + + Add I/O devices and bridges to the topology using the pciutils + library. Only enabled after setting the relevant flag with + hwloc_topology_set_flags() before hwloc_topology_load(). See the + I/O Devices section in the documentation for details. +* Discovery improvements + + Add associativity to the cache attributes. + + Add support for s390/z11 "books" on Linux. + + Add the HWLOC_GROUPING_ACCURACY environment variable to relax + distance-based grouping constraints. See the Environment Variables + section in the documentation for details about grouping behavior + and configuration. + + Allow user-given distance matrices to remove or replace those + discovered by the OS backend. +* XML improvements + + XML is now always supported: a minimalistic custom import/export + code is used when libxml2 is not available. It is only guaranteed + to read XML files generated by hwloc. + + hwloc_topology_export_xml() and export_xmlbuffer() now return an + integer. + + Add hwloc_free_xmlbuffer() to free the buffer allocated by + hwloc_topology_export_xmlbuffer(). + + Hide XML topology error messages unless HWLOC_XML_VERBOSE=1. +* Minor API updates + + Add hwloc_obj_add_info to customize object info attributes. +* Tools + + lstopo now displays I/O devices by default. Several options are + added to configure the I/O discovery. + + hwloc-calc and hwloc-bind now accept I/O devices as input. + + Add --restrict option to hwloc-calc and hwloc-distribute. + + Add --sep option to change the output field separator in hwloc-calc. + + Add --whole-system option to hwloc-ps. + + +Version 1.2.2 +------------- +* Fix build on AIX 5.2, thanks Utpal Kumar Ray for the report. +* Fix XML import of very large page sizes or counts on 32bits platform, + thanks to Karsten Hopp for the RedHat ticket. +* Fix crash when administrator limitations such as Linux cgroup require + to restrict distance matrices. Thanks to Ake Sandgren for reporting the + problem. +* Fix the removal of objects such as AMD Magny-Cours dual-node sockets + in case of administrator restrictions. +* Improve error reporting and messages in case of wrong synthetic topology + description. +* Several other minor internal fixes and documentation improvements. + + +Version 1.2.1 +------------- +* Improve support of AMD Bulldozer "Compute-Unit" modules by detecting + logical processors with different core IDs on Linux. +* Fix hwloc-ps crash when listing processes from another Linux cpuset. + Thanks to Carl Smith for reporting the problem. +* Fix build on AIX and Solaris. Thanks to Carl Smith and Andreas Kupries + for reporting the problems. +* Fix cache size detection on Darwin. Thanks to Erkcan Özcan for reporting + the problem. +* Make configure fail if --enable-xml or --enable-cairo is given and + proper support cannot be found. Thanks to Andreas Kupries for reporting + the XML problem. +* Fix spurious L1 cache detection on AIX. Thanks to Hendryk Bockelmann + for reporting the problem. +* Fix hwloc_get_last_cpu_location(THREAD) on Linux. Thanks to Gabriele + Fatigati for reporting the problem. +* Fix object distance detection on Solaris. +* Add pthread_self weak symbol to ease static linking. +* Minor documentation fixes. + + +Version 1.2.0 +------------- +* Major features + + Expose latency matrices in the API as an array of distance structures + within objects. Add several helpers to find distances. + + Add hwloc_topology_set_distance_matrix() and environment variables + to provide a matrix of distances between a given set of objects. + + Add hwloc_get_last_cpu_location() and hwloc_get_proc_last_cpu_location() + to retrieve the processors where a process or thread recently ran. + - Add the corresponding --get-last-cpu-location option to hwloc-bind. + + Add hwloc_topology_restrict() to restrict an existing topology to a + given cpuset. + - Add the corresponding --restrict option to lstopo. +* Minor API updates + + Add hwloc_bitmap_list_sscanf/snprintf/asprintf to convert between bitmaps + and strings such as 4-5,7-9,12,15- + + hwloc_bitmap_set/clr_range() now support infinite ranges. + + Clarify the difference between inserting Misc objects by cpuset or by + parent. + + hwloc_insert_misc_object_by_cpuset() now returns NULL in case of error. +* Discovery improvements + + x86 backend (for freebsd): add x2APIC support + + Support standard device-tree phandle, to get better support on e.g. ARM + systems providing it. + + Detect cache size on AIX. Thanks Christopher and IBM. + + Improve grouping to support asymmetric topologies. +* Tools + + Command-line tools now support "all" and "root" special locations + consisting in the entire topology, as well as type names with depth + attributes such as L2 or Group4. + + hwloc-calc improvements: + - Add --number-of/-N option to report the number of objects of a given + type or depth. + - -I is now equivalent to --intersect for listing the indexes of + objects of a given type or depth that intersects the input. + - Add -H to report the output as a hierarchical combination of types + and depths. + + Add --thissystem to lstopo. + + Add lstopo-win, a console-less lstopo variant on Windows. +* Miscellaneous + + Remove C99 usage from code base. + + Rename hwloc-gather-topology.sh into hwloc-gather-topology + + Fix AMD cache discovery on freebsd when there is no L3 cache, thanks + Andriy Gapon for the fix. + + +Version 1.1.2 +------------- +* Fix a segfault in the distance-based grouping code when some objects + are not placed in any group. Thanks to Bernd Kallies for reporting + the problem and providing a patch. +* Fix the command-line parsing of hwloc-bind --mempolicy interleave. + Thanks to Guy Streeter for reporting the problem. +* Stop truncating the output in hwloc_obj_attr_snprintf() and in the + corresponding lstopo output. Thanks to Guy Streeter for reporting the + problem. +* Fix object levels ordering in synthetic topologies. +* Fix potential incoherency between device tree and kernel information, + when SMT is disabled on Power machines. +* Fix and document the behavior of hwloc_topology_set_synthetic() in case + of invalid argument. Thanks to Guy Streeter for reporting the problem. +* Add some verbose error message reporting when it looks like the OS + gives erroneous information. +* Do not include unistd.h and stdint.h in public headers on Windows. +* Move config.h files into their own subdirectories to avoid name + conflicts when AC_CONFIG_HEADERS adds -I's for them. +* Remove the use of declaring variables inside "for" loops. +* Some other minor fixes. +* Many minor documentation fixes. + + +Version 1.1.1 +------------- +* Add hwloc_get_api_version() which returns the version of hwloc used + at runtime. Thanks to Guy Streeter for the suggestion. +* Fix the number of hugepages reported for NUMA nodes on Linux. +* Fix hwloc_bitmap_to_ulong() right after allocating the bitmap. + Thanks to Bernd Kallies for reporting the problem. +* Fix hwloc_bitmap_from_ith_ulong() to properly zero the first ulong. + Thanks to Guy Streeter for reporting the problem. +* Fix hwloc_get_membind_nodeset() on Linux. + Thanks to Bernd Kallies for reporting the problem and providing a patch. +* Fix some file descriptor leaks in the Linux discovery. +* Fix the minimum width of NUMA nodes, caches and the legend in the graphical + lstopo output. Thanks to Jirka Hladky for reporting the problem. +* Various fixes to bitmap conversion from/to taskset-strings. +* Fix and document snprintf functions behavior when the buffer size is too + small or zero. Thanks to Guy Streeter for reporting the problem. +* Fix configure to avoid spurious enabling of the cpuid backend. + Thanks to Tim Anderson for reporting the problem. +* Cleanup error management in hwloc-gather-topology.sh. + Thanks to Jirka Hladky for reporting the problem and providing a patch. +* Add a manpage and usage for hwloc-gather-topology.sh on Linux. + Thanks to Jirka Hladky for providing a patch. +* Memory binding documentation enhancements. + + +Version 1.1.0 +------------- + +* API + + Increase HWLOC_API_VERSION to 0x00010100 so that API changes may be + detected at build-time. + + Add a memory binding interface. + + The cpuset API (hwloc/cpuset.h) is now deprecated. It is replaced by + the bitmap API (hwloc/bitmap.h) which offers the same features with more + generic names since it applies to CPU sets, node sets and more. + Backward compatibility with the cpuset API and ABI is still provided but + it will be removed in a future release. + Old types (hwloc_cpuset_t, ...) are still available as a way to clarify + what kind of hwloc_bitmap_t each API function manipulates. + Upgrading to the new API only requires to replace hwloc_cpuset_ function + calls with the corresponding hwloc_bitmap_ calls, with the following + renaming exceptions: + - hwloc_cpuset_cpu -> hwloc_bitmap_only + - hwloc_cpuset_all_but_cpu -> hwloc_bitmap_allbut + - hwloc_cpuset_from_string -> hwloc_bitmap_sscanf + + Add an `infos' array in each object to store couples of info names and + values. It enables generic storage of things like the old dmi board infos + that were previously stored in machine specific attributes. + + Add linesize cache attribute. +* Features + + Bitmaps (and thus CPU sets and node sets) are dynamically (re-)allocated, + the maximal number of CPUs (HWLOC_NBMAXCPUS) has been removed. + + Improve the distance-based grouping code to better support irregular + distance matrices. + + Add support for device-tree to get cache information (useful on Power + architectures). +* Helpers + + Add NVIDIA CUDA helpers in cuda.h and cudart.h to ease interoperability + with CUDA Runtime and Driver APIs. + + Add Myrinet Express helper in myriexpress.h to ease interoperability. +* Tools + + lstopo now displays physical/OS indexes by default in graphical mode + (use -l to switch back to logical indexes). The textual output still uses + logical by default (use -p to switch to physical indexes). + + lstopo prefixes logical indexes with `L#' and physical indexes with `P#'. + Physical indexes are also printed as `P#N' instead of `phys=N' within + object attributes (in parentheses). + + Add a legend at the bottom of the lstopo graphical output, use --no-legend + to remove it. + + Add hwloc-ps to list process' bindings. + + Add --membind and --mempolicy options to hwloc-bind. + + Improve tools command-line options by adding a generic --input option + (and more) which replaces the old --xml, --synthetic and --fsys-root. + + Cleanup lstopo output configuration by adding --output-format. + + Add --intersect in hwloc-calc, and replace --objects with --largest. + + Add the ability to work on standard input in hwloc-calc. + + Add --from, --to and --at in hwloc-distrib. + + Add taskset-specific functions and command-line tools options to + manipulate CPU set strings in the format of the taskset program. + + Install hwloc-gather-topology.sh on Linux. + + +Version 1.0.3 +------------- + +* Fix support for Linux cpuset when emulated by a cgroup mount point. +* Remove unneeded runtime dependency on libibverbs.so in the library and + all utils programs. +* Fix hwloc_cpuset_to_linux_libnuma_ulongs in case of non-linear OS-indexes + for NUMA nodes. +* lstopo now displays physical/OS indexes by default in graphical mode + (use -l to switch back to logical indexes). The textual output still uses + logical by default (use -p to switch to physical indexes). + + +Version 1.0.2 +------------- + +* Public headers can now be included directly from C++ programs. +* Solaris fix for non-contiguous cpu numbers. Thanks to Rolf vandeVaart for + reporting the issue. +* Darwin 10.4 fix. Thanks to Olivier Cessenat for reporting the issue. +* Revert 1.0.1 patch that ignored sockets with unknown ID values since it + only slightly helped POWER7 machines with old Linux kernels while it + prevents recent kernels from getting the complete POWER7 topology. +* Fix hwloc_get_common_ancestor_obj(). +* Remove arch-specific bits in public headers. +* Some fixes in the lstopo graphical output. +* Various man page clarifications and minor updates. + + +Version 1.0.1 +------------- + +* Various Solaris fixes. Thanks to Yannick Martin for reporting the issue. +* Fix "non-native" builds on x86 platforms (e.g., when building 32 + bit executables with compilers that natively build 64 bit). +* Ignore sockets with unknown ID values (which fixes issues on POWER7 + machines). Thanks to Greg Bauer for reporting the issue. +* Various man page clarifications and minor updates. +* Fixed memory leaks in hwloc_setup_group_from_min_distance_clique(). +* Fix cache type filtering on MS Windows 7. Thanks to Αλέξανδρος + Παπαδογιαννάκ for reporting the issue. +* Fixed warnings when compiling with -DNDEBUG. + + +Version 1.0.0 +------------- + +* The ABI of the library has changed. +* Backend updates + + Add FreeBSD support. + + Add x86 cpuid based backend. + + Add Linux cgroup support to the Linux cpuset code. + + Support binding of entire multithreaded process on Linux. + + Fix and enable Group support in Windows. + + Cleanup XML export/import. +* Objects + + HWLOC_OBJ_PROC is renamed into HWLOC_OBJ_PU for "Processing Unit", + its stringified type name is now "PU". + + Use new HWLOC_OBJ_GROUP objects instead of MISC when grouping + objects according to NUMA distances or arbitrary OS aggregation. + + Rework memory attributes. + + Add different cpusets in each object to specify processors that + are offline, unavailable, ... + + Cleanup the storage of object names and DMI infos. +* Features + + Add support for looking up specific PID topology information. + + Add hwloc_topology_export_xml() to export the topology in a XML file. + + Add hwloc_topology_get_support() to retrieve the supported features + for the current topology context. + + Support non-SYSTEM object as the root of the tree, use MACHINE in + most common cases. + + Add hwloc_get_*cpubind() routines to retrieve the current binding + of processes and threads. +* API + + Add HWLOC_API_VERSION to help detect the currently used API version. + + Add missing ending "e" to *compare* functions. + + Add several routines to emulate PLPA functions. + + Rename and rework the cpuset and/or/xor/not/clear operators to output + their result in a dedicated argument instead of modifying one input. + + Deprecate hwloc_obj_snprintf() in favor of hwloc_obj_type/attr_snprintf(). + + Clarify the use of parent and ancestor in the API, do not use father. + + Replace hwloc_get_system_obj() with hwloc_get_root_obj(). + + Return -1 instead of HWLOC_OBJ_TYPE_MAX in the API since the latter + isn't public. + + Relax constraints in hwloc_obj_type_of_string(). + + Improve displaying of memory sizes. + + Add 0x prefix to cpuset strings. +* Tools + + lstopo now displays logical indexes by default, use --physical to + revert back to OS/physical indexes. + + Add colors in the lstopo graphical outputs to distinguish between online, + offline, reserved, ... objects. + + Extend lstopo to show cpusets, filter objects by type, ... + + Renamed hwloc-mask into hwloc-calc which supports many new options. +* Documentation + + Add a hwloc(7) manpage containing general information. + + Add documentation about how to switch from PLPA to hwloc. + + Cleanup the distributed documentation files. +* Miscellaneous + + Many compilers warning fixes. + + Cleanup the ABI by using the visibility attribute. + + Add project embedding support. + + +Version 0.9.4 (unreleased) +-------------------------- + +* Fix reseting colors to normal in lstopo -.txt output. +* Fix Linux pthread_t binding error report. + + +Version 0.9.3 +------------- + +* Fix autogen.sh to work with Autoconf 2.63. +* Fix various crashes in particular conditions: + - xml files with root attributes + - offline CPUs + - partial sysfs support + - unparseable /proc/cpuinfo + - ignoring NUMA level while Misc level have been generated +* Tweak documentation a bit +* Do not require the pthread library for binding the current thread on Linux +* Do not erroneously consider the sched_setaffinity prototype is the old version + when there is actually none. +* Fix _syscall3 compilation on archs for which we do not have the + sched_setaffinity system call number. +* Fix AIX binding. +* Fix libraries dependencies: now only lstopo depends on libtermcap, fix + binutils-gold link +* Have make check always build and run hwloc-hello.c +* Do not limit size of a cpuset. + + +Version 0.9.2 +------------- + +* Trivial documentation changes. + + +Version 0.9.1 +------------- + +* Re-branded to "hwloc" and moved to the Open MPI project, relicensed under the + BSD license. +* The prefix of all functions and tools is now hwloc, and some public + functions were also renamed for real. +* Group NUMA nodes into Misc objects according to their physical distance + that may be reported by the OS/BIOS. + May be ignored by setting HWLOC_IGNORE_DISTANCES=1 in the environment. +* Ignore offline CPUs on Solaris. +* Improved binding support on AIX. +* Add HP-UX support. +* CPU sets are now allocated/freed dynamically. +* Add command line options to tune the lstopo graphical output, add + semi-graphical textual output +* Extend topobind to support multiple cpusets or objects on the command + line as topomask does. +* Add an Infiniband-specific helper hwloc/openfabrics-verbs.h to retrieve + the physical location of IB devices. + + +Version 0.9 (libtopology) +------------------------- + +* First release. diff --git a/opal/mca/hwloc/hwloc1110/hwloc/README b/opal/mca/hwloc/hwloc1110/hwloc/README new file mode 100644 index 0000000000..fed93191f9 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/README @@ -0,0 +1,612 @@ +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. + +Note that the hwloc project represents the merger of the libtopology project +from inria and the Portable Linux Processor Affinity (PLPA) sub-project from +Open MPI. Both of these prior projects are now deprecated. The first hwloc +release was essentially a "re-branding" of the libtopology code base, but with +both a few genuinely new features and a few PLPA-like features added in. Prior +releases of hwloc included documentation about switching from PLPA to hwloc; +this documentation has been dropped on the assumption that everyone who was +using PLPA has already switched to hwloc. + +hwloc supports the following operating systems: + + * Linux (including old kernels not having sysfs topology information, with + knowledge of cpusets, offline CPUs, ScaleMP vSMP, NumaScale NumaConnect, + and Kerrighed support) on all supported hardware, including Intel Xeon Phi + (either standalone or as a coprocessor). + * 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 + * Remote machine simulation through the gathering of Linux sysfs topology + 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 CLI 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). + +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.10 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 + +The hwloc command-line tool "lstopo" produces human-readable topology maps, as +mentioned above. It can also export maps to the "fig" file format. Support for +PDF, Postscript, and PNG exporting is provided if the "Cairo" development +package (usually cairo-devel or libcairo2-dev) can be found in "lstopo" when +hwloc is configured and build. + +The hwloc core may also benefit from the following development packages: + + * libnuma for memory binding and migration support on Linux (numactl-devel or + libnuma-dev package). + * libpciaccess for full I/O device discovery (libpciaccess-devel or + libpciaccess-dev package). On Linux, PCI discovery may still be performed + (without vendor/device names) even if libpciaccess cannot be used. + + * the AMD OpenCL implementation for OpenCL device discovery. + * the NVIDIA CUDA Toolkit for CUDA device discovery. + * the NVIDIA Tesla Development Kit for NVML device discovery. + * the NV-CONTROL X extension library (NVCtrl) for NVIDIA display discovery. + * libxml2 for full XML import/export support (otherwise, the internal + minimalistic parser will only be able to import XML files that were + exported by the same hwloc release). See Importing and exporting topologies + from/to XML files for details. The relevant development package is usually + libxml2-devel or libxml2-dev. + * libudev on Linux for easier discovery of OS device information (otherwise + hwloc will try to manually parse udev raw files). The relevant development + package is usually libudev-devel or libudev-dev. + * libtool's ltdl library for dynamic plugin loading. The relevant development + package is usually libtool-ltdl-devel or libltdl-dev. + +PCI and XML support may be statically built inside the main hwloc library, or +as separate dynamically-loaded plugins (see the Components and plugins +section). + +Note that because of the possibility of GPL taint, the pciutils library libpci +will not be used (remember that hwloc is BSD-licensed). + +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 ... + +CLI Examples + +On a 4-package 2-core machine with hyper-threading, the lstopo tool may show +the following graphical output: + +dudley.png + +Here's the equivalent output in textual form: + +Machine (16GB) + Package L#0 + L3 L#0 (4096KB) + L2 L#0 (1024KB) + L1 L#0 (16KB) + Core L#0 + PU L#0 (P#0) + PU L#1 (P#8) + L2 L#1 (1024KB) + L1 L#1 (16KB) + Core L#1 + PU L#2 (P#4) + PU L#3 (P#12) + Package L#1 + L3 L#1 (4096KB) + L2 L#2 (1024KB) + L1 L#2 (16KB) + Core L#2 + PU L#4 (P#1) + PU L#5 (P#9) + L2 L#3 (1024KB) + L1 L#3 (16KB) + Core L#3 + PU L#6 (P#5) + PU L#7 (P#13) + Package L#2 + L3 L#2 (4096KB) + L2 L#4 (1024KB) + L1 L#4 (16KB) + Core L#4 + PU L#8 (P#2) + PU L#9 (P#10) + L2 L#5 (1024KB) + L1 L#5 (16KB) + Core L#5 + PU L#10 (P#6) + PU L#11 (P#14) + Package L#3 + L3 L#3 (4096KB) + L2 L#6 (1024KB) + L1 L#6 (16KB) + Core L#6 + PU L#12 (P#3) + PU L#13 (P#11) + L2 L#7 (1024KB) + L1 L#7 (16KB) + Core L#7 + PU L#14 (P#7) + PU L#15 (P#15) + +Note that there is also an equivalent output in XML that is meant for exporting +/importing topologies but it is hardly readable to human-beings (see Importing +and exporting topologies from/to XML files for details). + +On a 4-package 2-core Opteron NUMA machine, the lstopo tool may show the +following graphical output: + +hagrid.png + +Here's the equivalent output in textual form: + +Machine (32GB) + NUMANode L#0 (P#0 8190MB) + Package L#0 + L2 L#0 (1024KB) + L1 L#0 (64KB) + Core L#0 + PU L#0 (P#0) + L2 L#1 (1024KB) + L1 L#1 (64KB) + Core L#1 + PU L#1 (P#1) + NUMANode L#1 (P#1 8192MB) + Package L#1 + L2 L#2 (1024KB) + L1 L#2 (64KB) + Core L#2 + PU L#2 (P#2) + L2 L#3 (1024KB) + L1 L#3 (64KB) + Core L#3 + PU L#3 (P#3) + NUMANode L#2 (P#2 8192MB) + Package L#2 + L2 L#4 (1024KB) + L1 L#4 (64KB) + Core L#4 + PU L#4 (P#4) + L2 L#5 (1024KB) + L1 L#5 (64KB) + Core L#5 + PU L#5 (P#5) + NUMANode L#3 (P#3 8192MB) + Package L#3 + L2 L#6 (1024KB) + L1 L#6 (64KB) + Core L#6 + PU L#6 (P#6) + L2 L#7 (1024KB) + L1 L#7 (64KB) + Core L#7 + PU L#7 (P#7) + +On a 2-package quad-core Xeon (pre-Nehalem, with 2 dual-core dies into each +package): + +emmett.png + +Here's the same output in textual form: + +Machine (16GB) + Package L#0 + L2 L#0 (4096KB) + L1 L#0 (32KB) + Core L#0 + PU L#0 (P#0) + L1 L#1 (32KB) + Core L#1 + PU L#1 (P#4) + L2 L#1 (4096KB) + L1 L#2 (32KB) + Core L#2 + PU L#2 (P#2) + L1 L#3 (32KB) + Core L#3 + PU L#3 (P#6) + Package L#1 + L2 L#2 (4096KB) + L1 L#4 (32KB) + Core L#4 + PU L#4 (P#1) + L1 L#5 (32KB) + Core L#5 + PU L#5 (P#5) + L2 L#3 (4096KB) + L1 L#6 (32KB) + Core L#6 + PU L#6 (P#3) + L1 L#7 (32KB) + Core L#7 + PU L#7 (P#7) + +Programming Interface + +The basic interface is available in hwloc.h. Some higher-level functions are +available in hwloc/helper.h to reduce the need to manually manipulate objects +and follow links between them. Documentation for all these is provided later in +this document. Developers may also want to look at hwloc/inlines.h which +contains the actual inline code of some hwloc.h routines, and at this document, +which provides good higher-level topology traversal examples. + +To precisely define the vocabulary used by hwloc, a Terms and Definitions +section is available and should probably be read first. + +Each hwloc object contains a cpuset describing the list of processing units +that it contains. These bitmaps may be used for CPU binding and Memory binding. +hwloc offers an extensive bitmap manipulation interface in hwloc/bitmap.h. + +Moreover, hwloc also comes with additional helpers for interoperability with +several commonly used environments. See the Interoperability With Other +Software section for details. + +The complete API documentation is available in a full set of HTML pages, man +pages, and self-contained PDF files (formatted for both both US letter and A4 +formats) in the source tarball in doc/doxygen-doc/. + +NOTE: If you are building the documentation from a Git clone, you will need to +have Doxygen and pdflatex installed -- the documentation will be built during +the normal "make" process. The documentation is installed during "make install" +to $prefix/share/doc/hwloc/ and your systems default man page tree (under +$prefix, of course). + +Portability + +As shown in CLI Examples, hwloc can obtain information on a wide variety of +hardware topologies. However, some platforms and/or operating system versions +will only report a subset of this information. For example, on an PPC64-based +system with 32 cores (each with 2 hardware threads) running a default +2.6.18-based kernel from RHEL 5.4, hwloc is only able to glean information +about NUMA nodes and processor units (PUs). No information about caches, +packages, or cores is available. + +Similarly, Operating System have varying support for CPU and memory binding, +e.g. while some Operating Systems provide interfaces for all kinds of CPU and +memory bindings, some others provide only interfaces for a limited number of +kinds of CPU and memory binding, and some do not provide any binding interface +at all. Hwloc's binding functions would then simply return the ENOSYS error +(Function not implemented), meaning that the underlying Operating System does +not provide any interface for them. CPU binding and Memory binding provide more +information on which hwloc binding functions should be preferred because +interfaces for them are usually available on the supported Operating Systems. + +Here's the graphical output from lstopo on this platform when Simultaneous +Multi-Threading (SMT) is enabled: + +ppc64-with-smt.png + +And here's the graphical output from lstopo on this platform when SMT is +disabled: + +ppc64-without-smt.png + +Notice that hwloc only sees half the PUs when SMT is disabled. PU #15, for +example, seems to change location from NUMA node #0 to #1. In reality, no PUs +"moved" -- they were simply re-numbered when hwloc only saw half as many. +Hence, PU #15 in the SMT-disabled picture probably corresponds to PU #30 in the +SMT-enabled picture. + +This same "PUs have disappeared" effect can be seen on other platforms -- even +platforms / OSs that provide much more information than the above PPC64 system. +This is an unfortunate side-effect of how operating systems report information +to hwloc. + +Note that upgrading the Linux kernel on the same PPC64 system mentioned above +to 2.6.34, hwloc is able to discover all the topology information. The +following picture shows the entire topology layout when SMT is enabled: + +ppc64-full-with-smt.png + +Developers using the hwloc API or XML output for portable applications should +therefore be extremely careful to not make any assumptions about the structure +of data that is returned. For example, per the above reported PPC topology, it +is not safe to assume that PUs will always be descendants of cores. + +Additionally, future hardware may insert new topology elements that are not +available in this version of hwloc. Long-lived applications that are meant to +span multiple different hardware platforms should also be careful about making +structure assumptions. For example, there may someday be an element "lower" +than a PU, or perhaps a new element may exist between a core and a PU. + +API Example + +The following small C example (named ``hwloc-hello.c'') prints the topology of +the machine and bring the process to the first logical processor of the second +core of the machine. More examples are available in the doc/examples/ directory +of the source tree. + +/* Example hwloc API program. + * + * See other examples under doc/examples/ in the source tree + * for more details. + * + * Copyright (c) 2009-2015 Inria. All rights reserved. + * Copyright (c) 2009-2011 Universit?eacute; Bordeaux + * Copyright (c) 2009-2010 Cisco Systems, Inc. All rights reserved. + * See COPYING in top-level directory. + * + * hwloc-hello.c + */ + +#include +#include +#include +#include + +static void print_children(hwloc_topology_t topology, hwloc_obj_t obj, + int depth) +{ + char type[32], attr[1024]; + unsigned i; + + hwloc_obj_type_snprintf(type, sizeof(type), obj, 0); + printf("%*s%s", 2*depth, "", type); + if (obj->os_index != (unsigned) -1) + printf("#%u", obj->os_index); + hwloc_obj_attr_snprintf(attr, sizeof(attr), obj, " ", 0); + if (*attr) + printf("(%s)", attr); + printf("\n"); + for (i = 0; i < obj->arity; i++) { + print_children(topology, obj->children[i], depth + 1); + } +} + +int main(void) +{ + int depth; + unsigned i, n; + unsigned long size; + int levels; + char string[128]; + int topodepth; + hwloc_topology_t topology; + hwloc_cpuset_t cpuset; + hwloc_obj_t obj; + + /* Allocate and initialize topology object. */ + hwloc_topology_init(&topology); + + /* ... Optionally, put detection configuration here to ignore + some objects types, define a synthetic topology, etc.... + + The default is to detect all the objects of the machine that + the caller is allowed to access. See Configure Topology + Detection. */ + + /* Perform the topology detection. */ + hwloc_topology_load(topology); + + /* Optionally, get some additional topology information + in case we need the topology depth later. */ + topodepth = hwloc_topology_get_depth(topology); + + /***************************************************************** + * First example: + * Walk the topology with an array style, from level 0 (always + * the system level) to the lowest level (always the proc level). + *****************************************************************/ + for (depth = 0; depth < topodepth; depth++) { + printf("*** Objects at level %d\n", depth); + for (i = 0; i < hwloc_get_nbobjs_by_depth(topology, depth); + i++) { + hwloc_obj_type_snprintf(string, sizeof(string), + hwloc_get_obj_by_depth +(topology, depth, i), 0); + printf("Index %u: %s\n", i, string); + } + } + + /***************************************************************** + * Second example: + * Walk the topology with a tree style. + *****************************************************************/ + printf("*** Printing overall tree\n"); + print_children(topology, hwloc_get_root_obj(topology), 0); + + /***************************************************************** + * Third example: + * Print the number of packages. + *****************************************************************/ + depth = hwloc_get_type_depth(topology, HWLOC_OBJ_PACKAGE); + if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) { + printf("*** The number of packages is unknown\n"); + } else { + printf("*** %u package(s)\n", + hwloc_get_nbobjs_by_depth(topology, depth)); + } + + /***************************************************************** + * Fourth example: + * Compute the amount of cache that the first logical processor + * has above it. + *****************************************************************/ + levels = 0; + size = 0; + for (obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PU, 0); + obj; + obj = obj->parent) + if (obj->type == HWLOC_OBJ_CACHE) { + levels++; + size += obj->attr->cache.size; + } + printf("*** Logical processor 0 has %d caches totaling %luKB\n", + levels, size / 1024); + + /***************************************************************** + * Fifth example: + * Bind to only one thread of the last core of the machine. + * + * First find out where cores are, or else smaller sets of CPUs if + * the OS doesn't have the notion of a "core". + *****************************************************************/ + depth = hwloc_get_type_or_below_depth(topology, HWLOC_OBJ_CORE); + + /* Get last core. */ + obj = hwloc_get_obj_by_depth(topology, depth, + hwloc_get_nbobjs_by_depth(topology, depth) - 1); + if (obj) { + /* Get a copy of its cpuset that we may modify. */ + cpuset = hwloc_bitmap_dup(obj->cpuset); + + /* Get only one logical processor (in case the core is + SMT/hyper-threaded). */ + hwloc_bitmap_singlify(cpuset); + + /* And try to bind ourself there. */ + if (hwloc_set_cpubind(topology, cpuset, 0)) { + char *str; + int error = errno; + hwloc_bitmap_asprintf(&str, obj->cpuset); + printf("Couldn't bind to cpuset %s: %s\n", str, strerror(error)); + free(str); + } + + /* Free our cpuset copy */ + hwloc_bitmap_free(cpuset); + } + + /***************************************************************** + * Sixth example: + * Allocate some memory on the last NUMA node, bind some existing + * memory to the last NUMA node. + *****************************************************************/ + /* Get last node. */ + n = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_NUMANODE); + if (n) { + void *m; + size = 1024*1024; + + obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, n - 1); + m = hwloc_alloc_membind_nodeset(topology, size, obj->nodeset, + HWLOC_MEMBIND_BIND, 0); + hwloc_free(topology, m, size); + + m = malloc(size); + hwloc_set_area_membind_nodeset(topology, m, size, obj->nodeset, + HWLOC_MEMBIND_BIND, 0); + free(m); + } + + /* Destroy topology object. */ + hwloc_topology_destroy(topology); + + return 0; +} + +hwloc provides a pkg-config executable to obtain relevant compiler and linker +flags. For example, it can be used thusly to compile applications that utilize +the hwloc library (assuming GNU Make): + +CFLAGS += $(pkg-config --cflags hwloc) +LDLIBS += $(pkg-config --libs hwloc) +cc hwloc-hello.c $(CFLAGS) -o hwloc-hello $(LDLIBS) + +On a machine with 4GB of RAM and 2 processor packages -- each package of which +has two processing cores -- the output from running hwloc-hello could be +something like the following: + +shell$ ./hwloc-hello +*** Objects at level 0 +Index 0: Machine(3938MB) +*** Objects at level 1 +Index 0: Package#0 +Index 1: Package#1 +*** Objects at level 2 +Index 0: Core#0 +Index 1: Core#1 +Index 2: Core#3 +Index 3: Core#2 +*** Objects at level 3 +Index 0: PU#0 +Index 1: PU#1 +Index 2: PU#2 +Index 3: PU#3 +*** Printing overall tree +Machine(3938MB) + Package#0 + Core#0 + PU#0 + Core#1 + PU#1 + Package#1 + Core#3 + PU#2 + Core#2 + PU#3 +*** 2 package(s) +shell$ + +Questions and Bugs + +Questions should be sent to the devel mailing list (http://www.open-mpi.org/ +community/lists/hwloc.php). Bug reports should be reported in the tracker ( +https://git.open-mpi.org/trac/hwloc/). + +If hwloc discovers an incorrect topology for your machine, the very first thing +you should check is to ensure that you have the most recent updates installed +for your operating system. Indeed, most of hwloc topology discovery relies on +hardware information retrieved through the operation system (e.g., via the /sys +virtual filesystem of the Linux kernel). If upgrading your OS or Linux kernel +does not solve your problem, you may also want to ensure that you are running +the most recent version of the BIOS for your machine. + +If those things fail, contact us on the mailing list for additional help. +Please attach the output of lstopo after having given the --enable-debug option +to ./configure and rebuilt completely, to get debugging output. Also attach the +/proc + /sys tarball generated by the installed script hwloc-gather-topology +when submitting problems about Linux, or send the output of kstat cpu_info in +the Solaris case, or the output of sysctl hw in the Darwin or BSD cases. + +History / Credits + +hwloc is the evolution and merger of the libtopology (http:// +runtime.bordeaux.inria.fr/libtopology/) project and the Portable Linux +Processor Affinity (PLPA) (http://www.open-mpi.org/projects/plpa/) project. +Because of functional and ideological overlap, these two code bases and ideas +were merged and released under the name "hwloc" as an Open MPI sub-project. + +libtopology was initially developed by the inria Runtime Team-Project (http:// +runtime.bordeaux.inria.fr/) (headed by Raymond Namyst (http:// +dept-info.labri.fr/~namyst/). PLPA was initially developed by the Open MPI +development team as a sub-project. Both are now deprecated in favor of hwloc, +which is distributed as an Open MPI sub-project. + +Further Reading + +The documentation chapters include + + * Terms and Definitions + * Command-Line Tools + * Environment Variables + * CPU and Memory Binding Overview + * I/O Devices + * Miscellaneous objects + * Multi-node Topologies + * Object attributes + * Importing and exporting topologies from/to XML files + * Synthetic topologies + * Interoperability With Other Software + * Thread Safety + * Components and plugins + * Embedding hwloc in Other Software + * Frequently Asked Questions + +Make sure to have had a look at those too! + diff --git a/opal/mca/hwloc/hwloc1110/hwloc/VERSION b/opal/mca/hwloc/hwloc1110/hwloc/VERSION new file mode 100644 index 0000000000..5ccd593891 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/VERSION @@ -0,0 +1,42 @@ +# This is the VERSION file for hwloc, describing the precise version +# of hwloc in this distribution. The various components of the version +# number below are combined to form a single version number string. + +# major, minor, and release are generally combined in the form +# ... If release is zero, then it is omitted. + +major=1 +minor=11 +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 +# numeric. Common examples include a1 (alpha release 1), b1 (beta +# release 1), sc2005 (Super Computing 2005 release). The only +# requirement is that it must be entirely printable ASCII characters +# and have no white space. + +greek=rc1 + +# The date when this release was created + +date="Jun 02, 2015" + +# If snapshot=1, then use the value from snapshot_version as the +# entire hwloc version (i.e., ignore major, minor, release, and +# greek). This is only set to 1 when making snapshot tarballs. +snapshot=0 +snapshot_version=${major}.${minor}.${release}${greek}-git + +# The shared library version of hwloc's public library. This version +# is maintained in accordance with the "Library Interface Versions" +# chapter from the GNU Libtool documentation. Notes: + +# 1. Since version numbers are associated with *releases*, the version +# number maintained on the hwloc git master (and developer branches) +# is always 0:0:0. + +# 2. Version numbers are described in the Libtool current:revision:age +# format. + +libhwloc_so_version=11:6:6 diff --git a/opal/mca/hwloc/hwloc1110/hwloc/config/distscript.sh b/opal/mca/hwloc/hwloc1110/hwloc/config/distscript.sh new file mode 100755 index 0000000000..d72a3fd305 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/config/distscript.sh @@ -0,0 +1,130 @@ +#!/bin/sh -f +# +# Copyright © 2004-2005 The Trustees of Indiana University and Indiana +# University Research and Technology +# Corporation. All rights reserved. +# Copyright © 2004-2005 The University of Tennessee and The University +# of Tennessee Research Foundation. All rights +# reserved. +# Copyright © 2004-2005 High Performance Computing Center Stuttgart, +# University of Stuttgart. All rights reserved. +# Copyright © 2004-2005 The Regents of the University of California. +# All rights reserved. +# Copyright © 2010-2014 Inria. All rights reserved. +# Copyright © 2009-2014 Cisco Systems, Inc. All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# + +builddir="`pwd`" + +srcdir=$1 +cd "$srcdir" +srcdir=`pwd` +cd "$builddir" + +distdir="$builddir/$2" +HWLOC_VERSION=$3 + +if test "$distdir" = ""; then + echo "Must supply relative distdir as argv[2] -- aborting" + exit 1 +elif test "$HWLOC_VERSION" = ""; then + echo "Must supply version as argv[1] -- aborting" + exit 1 +fi + +#======================================================================== + +start=`date` +cat < header file.]) + ]) + AC_CHECK_HEADERS([sys/mman.h]) + + old_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -D_WIN32_WINNT=0x0601" + AC_CHECK_TYPES([KAFFINITY, + PROCESSOR_CACHE_TYPE, + CACHE_DESCRIPTOR, + LOGICAL_PROCESSOR_RELATIONSHIP, + RelationProcessorPackage, + SYSTEM_LOGICAL_PROCESSOR_INFORMATION, + GROUP_AFFINITY, + PROCESSOR_RELATIONSHIP, + NUMA_NODE_RELATIONSHIP, + CACHE_RELATIONSHIP, + PROCESSOR_GROUP_INFO, + GROUP_RELATIONSHIP, + SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, + PSAPI_WORKING_SET_EX_BLOCK, + PSAPI_WORKING_SET_EX_INFORMATION], + [],[],[[#include ]]) + CPPFLAGS="$old_CPPFLAGS" + AC_CHECK_LIB([gdi32], [main], + [HWLOC_LIBS="-lgdi32 $HWLOC_LIBS" + AC_DEFINE([HAVE_LIBGDI32], 1, [Define to 1 if we have -lgdi32])]) + + AC_CHECK_HEADER([windows.h], [ + AC_DEFINE([HWLOC_HAVE_WINDOWS_H], [1], [Define to 1 if you have the `windows.h' header.]) + ]) + + AC_CHECK_HEADERS([sys/lgrp_user.h], [ + AC_CHECK_LIB([lgrp], [lgrp_latency_cookie], + [HWLOC_LIBS="-llgrp $HWLOC_LIBS" + AC_DEFINE([HAVE_LIBLGRP], 1, [Define to 1 if we have -llgrp])]) + ]) + AC_CHECK_HEADERS([kstat.h], [ + AC_CHECK_LIB([kstat], [main], + [HWLOC_LIBS="-lkstat $HWLOC_LIBS" + AC_DEFINE([HAVE_LIBKSTAT], 1, [Define to 1 if we have -lkstat])]) + ]) + + AC_CHECK_DECLS([fabsf], [ + AC_CHECK_LIB([m], [fabsf], + [HWLOC_LIBS="-lm $HWLOC_LIBS"]) + ], [], [[#include ]]) + + AC_CHECK_HEADERS([picl.h], [ + AC_CHECK_LIB([picl], [picl_initialize], + [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 ]]) + + AC_HAVE_HEADERS([mach/mach_host.h]) + AC_HAVE_HEADERS([mach/mach_init.h], [ + AC_CHECK_FUNCS([host_info]) + ]) + + AC_CHECK_HEADERS([sys/param.h]) + AC_CHECK_HEADERS([sys/sysctl.h], [ + AC_CHECK_DECLS([CTL_HW, HW_NCPU],,,[[ + #if HAVE_SYS_PARAM_H + #include + #endif + #include + ]]) + ],,[ + AC_INCLUDES_DEFAULT + #if HAVE_SYS_PARAM_H + #include + #endif + ]) + + AC_CHECK_DECLS([strtoull], [], [], [AC_INCLUDES_DEFAULT]) + + # Do a full link test instead of just using AC_CHECK_FUNCS, which + # just checks to see if the symbol exists or not. For example, + # the prototype of sysctl uses u_int, which on some platforms + # (such as FreeBSD) is only defined under __BSD_VISIBLE, __USE_BSD + # or other similar definitions. So while the symbols "sysctl" and + # "sysctlbyname" might still be available in libc (which autoconf + # checks for), they might not be actually usable. + AC_TRY_LINK([ + #include + #include + #include + ], + [return sysctl(NULL,0,NULL,NULL,NULL,0);], + AC_DEFINE([HAVE_SYSCTL],[1],[Define to '1' if sysctl is present and usable])) + AC_TRY_LINK([ + #include + #include + #include + ], + [return sysctlbyname(NULL,NULL,NULL,NULL,0);], + AC_DEFINE([HAVE_SYSCTLBYNAME],[1],[Define to '1' if sysctlbyname is present and usable])) + + AC_CHECK_DECLS([getprogname], [], [], [AC_INCLUDES_DEFAULT]) + AC_CHECK_DECLS([getexecname], [], [], [AC_INCLUDES_DEFAULT]) + AC_CHECK_DECLS([GetModuleFileName], [], [], [#include ]) + # program_invocation_name and __progname may be available but not exported in headers + AC_MSG_CHECKING([for program_invocation_name]) + AC_TRY_LINK([ + #define _GNU_SOURCE + #include + #include + extern char *program_invocation_name; + ],[ + return printf("%s\n", program_invocation_name); + ], + [AC_DEFINE([HAVE_PROGRAM_INVOCATION_NAME], [1], [Define to '1' if program_invocation_name is present and usable]) + AC_MSG_RESULT([yes]) + ],[AC_MSG_RESULT([no])]) + AC_MSG_CHECKING([for __progname]) + AC_TRY_LINK([ + #include + extern char *__progname; + ],[ + return printf("%s\n", __progname); + ], + [AC_DEFINE([HAVE___PROGNAME], [1], [Define to '1' if __progname is present and usable]) + AC_MSG_RESULT([yes]) + ],[AC_MSG_RESULT([no])]) + + case ${target} in + *-*-mingw*|*-*-cygwin*) + hwloc_pid_t=HANDLE + hwloc_thread_t=HANDLE + ;; + *) + hwloc_pid_t=pid_t + AC_CHECK_TYPES([pthread_t], [hwloc_thread_t=pthread_t], [:], [[#include ]]) + ;; + esac + AC_DEFINE_UNQUOTED(hwloc_pid_t, $hwloc_pid_t, [Define this to the process ID type]) + if test "x$hwloc_thread_t" != "x" ; then + AC_DEFINE_UNQUOTED(hwloc_thread_t, $hwloc_thread_t, [Define this to the thread ID type]) + fi + + _HWLOC_CHECK_DECL([sched_setaffinity], [ + AC_DEFINE([HWLOC_HAVE_SCHED_SETAFFINITY], [1], [Define to 1 if glibc provides a prototype of sched_setaffinity()]) + AS_IF([test "$HWLOC_STRICT_ARGS_CFLAGS" = "FAIL"],[ + AC_MSG_WARN([Support for sched_setaffinity() requires a C compiler which]) + AC_MSG_WARN([considers incorrect argument counts to be a fatal error.]) + AC_MSG_ERROR([Cannot continue.]) + ]) + AC_MSG_CHECKING([for old prototype of sched_setaffinity]) + hwloc_save_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS $HWLOC_STRICT_ARGS_CFLAGS" + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([[ + #define _GNU_SOURCE + #include + static unsigned long mask; + ]], [[ sched_setaffinity(0, (void*) &mask); ]])], + [AC_DEFINE([HWLOC_HAVE_OLD_SCHED_SETAFFINITY], [1], [Define to 1 if glibc provides the old prototype (without length) of sched_setaffinity()]) + AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no])]) + CFLAGS=$hwloc_save_CFLAGS + ], , [[ +#define _GNU_SOURCE +#include +]]) + + AC_MSG_CHECKING([for working CPU_SET]) + AC_LINK_IFELSE([ + AC_LANG_PROGRAM([[ + #include + cpu_set_t set; + ]], [[ CPU_ZERO(&set); CPU_SET(0, &set);]])], + [AC_DEFINE([HWLOC_HAVE_CPU_SET], [1], [Define to 1 if the CPU_SET macro works]) + AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no])]) + + AC_MSG_CHECKING([for working CPU_SET_S]) + AC_LINK_IFELSE([ + AC_LANG_PROGRAM([[ + #include + cpu_set_t *set; + ]], [[ + set = CPU_ALLOC(1024); + CPU_ZERO_S(CPU_ALLOC_SIZE(1024), set); + CPU_SET_S(CPU_ALLOC_SIZE(1024), 0, set); + CPU_FREE(set); + ]])], + [AC_DEFINE([HWLOC_HAVE_CPU_SET_S], [1], [Define to 1 if the CPU_SET_S macro works]) + AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no])]) + + AC_MSG_CHECKING([for working _syscall3]) + AC_LINK_IFELSE([ + AC_LANG_PROGRAM([[ + #include + #include + #define __NR_hwloc_test 123 + _syscall3(int, hwloc_test, int, param1, int, param2, int, param3); + ]], [[ hwloc_test(1, 2, 3); ]])], + [AC_DEFINE([HWLOC_HAVE__SYSCALL3], [1], [Define to 1 if the _syscall3 macro works]) + 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]) + + AC_PATH_PROG([BASH], [bash]) + + AC_CHECK_FUNCS([ffs], [ + _HWLOC_CHECK_DECL([ffs],[ + AC_DEFINE([HWLOC_HAVE_DECL_FFS], [1], [Define to 1 if function `ffs' is declared by system headers]) + ]) + AC_DEFINE([HWLOC_HAVE_FFS], [1], [Define to 1 if you have the `ffs' function.]) + if ( $CC --version | grep gccfss ) >/dev/null 2>&1 ; then + dnl May be broken due to + dnl https://forums.oracle.com/forums/thread.jspa?threadID=1997328 + dnl TODO: a more selective test, since bug may be version dependent. + dnl We can't use AC_TRY_LINK because the failure does not appear until + dnl run/load time and there is currently no precedent for AC_TRY_RUN + dnl use in hwloc. --PHH + dnl For now, we're going with "all gccfss compilers are broken". + dnl Better to be safe and correct; it's not like this is + dnl performance-critical code, after all. + AC_DEFINE([HWLOC_HAVE_BROKEN_FFS], [1], + [Define to 1 if your `ffs' function is known to be broken.]) + fi + ]) + AC_CHECK_FUNCS([ffsl], [ + _HWLOC_CHECK_DECL([ffsl],[ + AC_DEFINE([HWLOC_HAVE_DECL_FFSL], [1], [Define to 1 if function `ffsl' is declared by system headers]) + ]) + AC_DEFINE([HWLOC_HAVE_FFSL], [1], [Define to 1 if you have the `ffsl' function.]) + ]) + + AC_CHECK_FUNCS([fls], [ + _HWLOC_CHECK_DECL([fls],[ + AC_DEFINE([HWLOC_HAVE_DECL_FLS], [1], [Define to 1 if function `fls' is declared by system headers]) + ]) + AC_DEFINE([HWLOC_HAVE_FLS], [1], [Define to 1 if you have the `fls' function.]) + ]) + AC_CHECK_FUNCS([flsl], [ + _HWLOC_CHECK_DECL([flsl],[ + AC_DEFINE([HWLOC_HAVE_DECL_FLSL], [1], [Define to 1 if function `flsl' is declared by system headers]) + ]) + AC_DEFINE([HWLOC_HAVE_FLSL], [1], [Define to 1 if you have the `flsl' function.]) + ]) + + AC_CHECK_FUNCS([clz], [ + _HWLOC_CHECK_DECL([clz],[ + AC_DEFINE([HWLOC_HAVE_DECL_CLZ], [1], [Define to 1 if function `clz' is declared by system headers]) + ]) + AC_DEFINE([HWLOC_HAVE_CLZ], [1], [Define to 1 if you have the `clz' function.]) + ]) + AC_CHECK_FUNCS([clzl], [ + _HWLOC_CHECK_DECL([clzl],[ + AC_DEFINE([HWLOC_HAVE_DECL_CLZL], [1], [Define to 1 if function `clzl' is declared by system headers]) + ]) + AC_DEFINE([HWLOC_HAVE_CLZL], [1], [Define to 1 if you have the `clzl' function.]) + ]) + + AC_CHECK_FUNCS([openat], [hwloc_have_openat=yes]) + + AC_CHECK_HEADERS([malloc.h]) + AC_CHECK_FUNCS([getpagesize memalign posix_memalign]) + + AC_CHECK_HEADERS([sys/utsname.h]) + AC_CHECK_FUNCS([uname]) + + AC_CHECK_HEADERS([pthread_np.h]) + AC_CHECK_DECLS([pthread_setaffinity_np],,[:],[[ + #include + #ifdef HAVE_PTHREAD_NP_H + # include + #endif + ]]) + AC_CHECK_DECLS([pthread_getaffinity_np],,[:],[[ + #include + #ifdef HAVE_PTHREAD_NP_H + # include + #endif + ]]) + AC_CHECK_FUNC([sched_setaffinity], [hwloc_have_sched_setaffinity=yes]) + AC_CHECK_HEADERS([sys/cpuset.h],,,[[#include ]]) + AC_CHECK_FUNCS([cpuset_setaffinity]) + AC_SEARCH_LIBS([pthread_getthrds_np], [pthread], + AC_DEFINE([HWLOC_HAVE_PTHREAD_GETTHRDS_NP], 1, `Define to 1 if you have pthread_getthrds_np') + ) + 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.]) + ]) + + LIBS="$tmp_save_LIBS" + fi + + # Linux libudev support + if test "x$enable_libudev" != xno; then + AC_CHECK_HEADERS([libudev.h], [ + AC_CHECK_LIB([udev], [udev_device_new_from_subsystem_sysname], [HWLOC_LIBS="$HWLOC_LIBS -ludev"]) + ]) + fi + + # 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]) + + # 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"], + [AC_CHECK_HEADER([pciaccess.h], + [AC_CHECK_LIB([pciaccess], [pci_slot_match_iterator_create], + [hwloc_pci_happy=yes + HWLOC_PCIACCESS_LIBS="-lpciaccess"]) + ]) + ]) + + AS_IF([test "$hwloc_pci_happy" = "yes"], + [HWLOC_PCIACCESS_REQUIRES=pciaccess + hwloc_pci_lib=pciaccess + 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"], + [AC_MSG_WARN([Specified --enable-pci switch, but could not]) + AC_MSG_WARN([find appropriate support]) + AC_MSG_ERROR([Cannot continue])]) + # don't add LIBS/CFLAGS/REQUIRES yet, depends on plugins + + # OpenCL support + hwloc_opencl_happy=no + if 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]) + ], [hwloc_opencl_happy=no]) + fi + AC_SUBST(HWLOC_OPENCL_LIBS) + # Check if required extensions are available + if test "x$hwloc_opencl_happy" = "xyes"; then + tmp_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $HWLOC_OPENCL_CFLAGS" + tmp_save_LIBS="$LIBS" + LIBS="$LIBS $HWLOC_OPENCL_LIBS" + AC_CHECK_DECLS([CL_DEVICE_TOPOLOGY_AMD],[hwloc_opencl_amd_happy=yes],[:],[[#include ]]) + CFLAGS="$tmp_save_CFLAGS" + LIBS="$tmp_save_LIBS" + # We can't do anything without CL_DEVICE_TOPOLOGY_AMD so far, so disable OpenCL entirely if not found + test "x$hwloc_opencl_amd_happy" != "xyes" && hwloc_opencl_happy=no + fi + # If we asked for opencl support but couldn't deliver, fail + AS_IF([test "$enable_opencl" = "yes" -a "$hwloc_opencl_happy" = "no"], + [AC_MSG_WARN([Specified --enable-opencl switch, but could not]) + AC_MSG_WARN([find appropriate support]) + AC_MSG_ERROR([Cannot continue])]) + if test "x$hwloc_opencl_happy" = "xyes"; then + AC_DEFINE([HWLOC_HAVE_OPENCL], [1], [Define to 1 if you have the `OpenCL' library.]) + AC_SUBST([HWLOC_HAVE_OPENCL], [1]) + hwloc_components="$hwloc_components opencl" + hwloc_opencl_component_maybeplugin=1 + else + AC_SUBST([HWLOC_HAVE_OPENCL], [0]) + fi + # don't add LIBS/CFLAGS/REQUIRES yet, depends on plugins + + # CUDA support + hwloc_have_cuda=no + hwloc_have_cudart=no + if test "x$enable_cuda" != "xno"; then + AC_CHECK_HEADERS([cuda.h], [ + AC_MSG_CHECKING(if CUDA_VERSION >= 3020) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +#ifndef CUDA_VERSION +#error CUDA_VERSION undefined +#elif CUDA_VERSION < 3020 +#error CUDA_VERSION too old +#endif]], [[int i = 3;]])], + [AC_MSG_RESULT(yes) + AC_CHECK_LIB([cuda], [cuInit], + [AC_DEFINE([HAVE_CUDA], 1, [Define to 1 if we have -lcuda]) + hwloc_have_cuda=yes])], + [AC_MSG_RESULT(no)])]) + + AC_CHECK_HEADERS([cuda_runtime_api.h], [ + AC_MSG_CHECKING(if CUDART_VERSION >= 3020) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +#ifndef CUDART_VERSION +#error CUDART_VERSION undefined +#elif CUDART_VERSION < 3020 +#error CUDART_VERSION too old +#endif]], [[int i = 3;]])], + [AC_MSG_RESULT(yes) + AC_CHECK_LIB([cudart], [cudaGetDeviceProperties], [ + HWLOC_CUDA_LIBS="-lcudart" + AC_SUBST(HWLOC_CUDA_LIBS) + hwloc_have_cudart=yes + AC_DEFINE([HWLOC_HAVE_CUDART], [1], [Define to 1 if you have the `cudart' SDK.]) + ]) + ]) + ]) + + AS_IF([test "$enable_cuda" = "yes" -a "$hwloc_have_cudart" = "no"], + [AC_MSG_WARN([Specified --enable-cuda switch, but could not]) + AC_MSG_WARN([find appropriate support]) + AC_MSG_ERROR([Cannot continue])]) + + if test "x$hwloc_have_cudart" = "xyes"; then + hwloc_components="$hwloc_components cuda" + hwloc_cuda_component_maybeplugin=1 + fi + fi + # don't add LIBS/CFLAGS yet, depends on plugins + + # NVML support + hwloc_nvml_happy=no + if 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]) + ], [hwloc_nvml_happy=no]) + fi + if test "x$hwloc_nvml_happy" = "xyes"; then + tmp_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $HWLOC_NVML_CFLAGS" + tmp_save_LIBS="$LIBS" + LIBS="$LIBS $HWLOC_NVML_LIBS" + AC_CHECK_DECLS([nvmlDeviceGetMaxPcieLinkGeneration],,[:],[[#include ]]) + CFLAGS="$tmp_save_CFLAGS" + LIBS="$tmp_save_LIBS" + fi + AC_SUBST(HWLOC_NVML_LIBS) + # If we asked for nvml support but couldn't deliver, fail + AS_IF([test "$enable_nvml" = "yes" -a "$hwloc_nvml_happy" = "no"], + [AC_MSG_WARN([Specified --enable-nvml switch, but could not]) + AC_MSG_WARN([find appropriate support]) + AC_MSG_ERROR([Cannot continue])]) + if test "x$hwloc_nvml_happy" = "xyes"; then + AC_DEFINE([HWLOC_HAVE_NVML], [1], [Define to 1 if you have the `NVML' library.]) + AC_SUBST([HWLOC_HAVE_NVML], [1]) + hwloc_components="$hwloc_components nvml" + hwloc_nvml_component_maybeplugin=1 + else + AC_SUBST([HWLOC_HAVE_NVML], [0]) + fi + # don't add LIBS/CFLAGS/REQUIRES yet, depends on plugins + + # X11 support + AC_PATH_XTRA + + CPPFLAGS_save=$CPPFLAGS + LIBS_save=$LIBS + + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + LIBS="$LIBS $X_PRE_LIBS $X_LIBS $X_EXTRA_LIBS" + AC_CHECK_HEADERS([X11/Xlib.h], + [AC_CHECK_LIB([X11], [XOpenDisplay], + [ + # the GL backend just needs XOpenDisplay + hwloc_enable_X11=yes + # lstopo needs more + AC_CHECK_HEADERS([X11/Xutil.h], + [AC_CHECK_HEADERS([X11/keysym.h], + [AC_DEFINE([HWLOC_HAVE_X11_KEYSYM], [1], [Define to 1 if X11 headers including Xutil.h and keysym.h are available.])]) + AC_SUBST([HWLOC_X11_LIBS], ["-lX11"]) + ], [], [#include ]) + ]) + ]) + CPPFLAGS=$CPPFLAGS_save + LIBS=$LIBS_save + + # GL Support + hwloc_gl_happy=no + if test "x$enable_gl" != "xno"; then + hwloc_gl_happy=yes + + AS_IF([test "$hwloc_enable_X11" != "yes"], + [AC_MSG_WARN([X11 not found; GL disabled]) + hwloc_gl_happy=no]) + + AC_CHECK_HEADERS([NVCtrl/NVCtrl.h], [ + AC_CHECK_LIB([XNVCtrl], [XNVCTRLQueryTargetAttribute], [:], [hwloc_gl_happy=no], [-lXext]) + ], [hwloc_gl_happy=no]) + + if test "x$hwloc_gl_happy" = "xyes"; then + AC_DEFINE([HWLOC_HAVE_GL], [1], [Define to 1 if you have the GL module components.]) + HWLOC_GL_LIBS="-lXNVCtrl -lXext -lX11" + AC_SUBST(HWLOC_GL_LIBS) + HWLOC_GL_REQUIRES="xext x11" + hwloc_have_gl=yes + hwloc_components="$hwloc_components gl" + hwloc_gl_component_maybeplugin=1 + else + AS_IF([test "$enable_gl" = "yes"], [ + AC_MSG_WARN([Specified --enable-gl switch, but could not]) + AC_MSG_WARN([find appropriate support]) + AC_MSG_ERROR([Cannot continue]) + ]) + fi + fi + # don't add LIBS/CFLAGS yet, depends on plugins + + # libxml2 support + hwloc_libxml2_happy= + if test "x$enable_libxml2" != "xno"; then + HWLOC_PKG_CHECK_MODULES([LIBXML2], [libxml-2.0], [xmlNewDoc], [libxml/parser.h], + [hwloc_libxml2_happy=yes], + [hwloc_libxml2_happy=no]) + fi + if test "x$hwloc_libxml2_happy" = "xyes"; then + HWLOC_LIBXML2_REQUIRES="libxml-2.0" + AC_DEFINE([HWLOC_HAVE_LIBXML2], [1], [Define to 1 if you have the `libxml2' library.]) + AC_SUBST([HWLOC_HAVE_LIBXML2], [1]) + + hwloc_components="$hwloc_components xml_libxml" + hwloc_xml_libxml_component_maybeplugin=1 + else + AC_SUBST([HWLOC_HAVE_LIBXML2], [0]) + AS_IF([test "$enable_libxml2" = "yes"], + [AC_MSG_WARN([--enable-libxml2 requested, but libxml2 was not found]) + AC_MSG_ERROR([Cannot continue])]) + fi + # don't add LIBS/CFLAGS/REQUIRES yet, depends on plugins + + # Try to compile the x86 cpuid inlines + if test "x$enable_cpuid" != "xno"; then + 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. + # So pass #include/#define manually here for now. + CPUID_CHECK_HEADERS= + CPUID_CHECK_DEFINE= + if test "x$hwloc_windows" = xyes; then + X86_CPUID_CHECK_HEADERS="#include " + X86_CPUID_CHECK_DEFINE="#define hwloc_uint64_t DWORDLONG" + else + X86_CPUID_CHECK_DEFINE="#define hwloc_uint64_t uint64_t" + if test "x$ac_cv_header_stdint_h" = xyes; then + X86_CPUID_CHECK_HEADERS="#include " + fi + fi + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ + #include + $X86_CPUID_CHECK_HEADERS + $X86_CPUID_CHECK_DEFINE + #define __hwloc_inline + #include + ]], [[ + if (hwloc_have_x86_cpuid()) { + unsigned eax = 0, ebx, ecx = 0, edx; + hwloc_x86_cpuid(&eax, &ebx, &ecx, &edx); + printf("highest x86 cpuid %x\n", eax); + return 0; + } + ]])], + [AC_MSG_RESULT([yes]) + AC_DEFINE(HWLOC_HAVE_X86_CPUID, 1, [Define to 1 if you have x86 cpuid]) + hwloc_have_x86_cpuid=yes], + [AC_MSG_RESULT([no])]) + if test "x$hwloc_have_x86_cpuid" = xyes; then + hwloc_components="$hwloc_components x86" + fi + CPPFLAGS="$old_CPPFLAGS" + fi + + # Components require pthread_mutex, see if it needs -lpthread + hwloc_pthread_mutex_happy=no + # Try without explicit -lpthread first + AC_CHECK_FUNC([pthread_mutex_lock], + [hwloc_pthread_mutex_happy=yes + HWLOC_LIBS_PRIVATE="$HWLOC_LIBS_PRIVATE -lpthread" + ], + [AC_MSG_CHECKING([for pthread_mutex_lock with -lpthread]) + # Try again with explicit -lpthread, but don't use AC_CHECK_FUNC to avoid the cache + tmp_save_LIBS=$LIBS + LIBS="$LIBS -lpthread" + AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_mutex_lock])], + [hwloc_pthread_mutex_happy=yes + HWLOC_LIBS="$HWLOC_LIBS -lpthread" + ]) + AC_MSG_RESULT([$hwloc_pthread_mutex_happy]) + LIBS="$tmp_save_LIBS" + ]) + AS_IF([test "x$hwloc_pthread_mutex_happy" = "xyes"], + [AC_DEFINE([HWLOC_HAVE_PTHREAD_MUTEX], 1, [Define to 1 if pthread mutexes are available])]) + + AS_IF([test "x$hwloc_pthread_mutex_happy" != xyes -a "x$hwloc_windows" != xyes], + [AC_MSG_WARN([pthread_mutex_lock not available, required for thread-safe initialization on non-Windows platforms.]) + AC_MSG_WARN([Please report this to the hwloc-devel mailing list.]) + AC_MSG_ERROR([Cannot continue])]) + + # + # Now enable registration of listed components + # + + # Plugin support + AC_MSG_CHECKING([if plugin support is enabled]) + # Plugins (even core support) are totally disabled by default + AS_IF([test "x$enable_plugins" = "x"], [enable_plugins=no]) + AS_IF([test "x$enable_plugins" != "xno"], [hwloc_have_plugins=yes], [hwloc_have_plugins=no]) + AC_MSG_RESULT([$hwloc_have_plugins]) + AS_IF([test "x$hwloc_have_plugins" = "xyes"], + [AC_DEFINE([HWLOC_HAVE_PLUGINS], 1, [Define to 1 if the hwloc library should support dynamically-loaded plugins])]) + + # Some sanity checks about plugins + # libltdl doesn't work on AIX as of 2.4.2 + AS_IF([test "x$enable_plugins" = "xyes" -a "x$hwloc_aix" = "xyes"], + [AC_MSG_WARN([libltdl does not work on AIX, plugins support cannot be enabled.]) + AC_MSG_ERROR([Cannot continue])]) + # posix linkers don't work well with plugins and windows dll constraints + AS_IF([test "x$enable_plugins" = "xyes" -a "x$hwloc_windows" = "xyes"], + [AC_MSG_WARN([Plugins not supported on non-native Windows build, plugins support cannot be enabled.]) + AC_MSG_ERROR([Cannot continue])]) + + # If we want plugins, look for ltdl.h and libltdl + if test "x$hwloc_have_plugins" = xyes; then + AC_CHECK_HEADER([ltdl.h], [], + [AC_MSG_WARN([Plugin support requested, but could not find ltdl.h]) + AC_MSG_ERROR([Cannot continue])]) + AC_CHECK_LIB([ltdl], [lt_dlopenext], + [HWLOC_LIBS="$HWLOC_LIBS -lltdl"], + [AC_MSG_WARN([Plugin support requested, but could not find libltdl]) + AC_MSG_ERROR([Cannot continue])]) + # Add libltdl static-build dependencies to hwloc.pc + HWLOC_CHECK_LTDL_DEPS + fi + + AC_ARG_WITH([hwloc-plugins-path], + AC_HELP_STRING([--with-hwloc-plugins-path=dir:...], + [Colon-separated list of plugin directories. Default: "$prefix/lib/hwloc". Plugins will be installed in the first directory. They will be loaded from all of them, in order.]), + [HWLOC_PLUGINS_PATH="$with_hwloc_plugins_path"], + [HWLOC_PLUGINS_PATH="\$(libdir)/hwloc"]) + AC_SUBST(HWLOC_PLUGINS_PATH) + HWLOC_PLUGINS_DIR=`echo "$HWLOC_PLUGINS_PATH" | cut -d: -f1` + AC_SUBST(HWLOC_PLUGINS_DIR) + + # Static components output file + hwloc_static_components_dir=${HWLOC_top_builddir}/src + mkdir -p ${hwloc_static_components_dir} + hwloc_static_components_file=${hwloc_static_components_dir}/static-components.h + rm -f ${hwloc_static_components_file} + + # Make $enable_plugins easier to use (it contains either "yes" (all) or a list of ) + HWLOC_PREPARE_FILTER_COMPONENTS([$enable_plugins]) + # Now we have some hwloc__component_wantplugin=1 + + # See which core components want plugin and support it + HWLOC_FILTER_COMPONENTS + # Now we have some hwloc__component=plugin/static + # and hwloc_static/plugin_components + AC_MSG_CHECKING([components to build statically]) + AC_MSG_RESULT($hwloc_static_components) + HWLOC_LIST_STATIC_COMPONENTS([$hwloc_static_components_file], [$hwloc_static_components]) + AC_MSG_CHECKING([components to build as plugins]) + AC_MSG_RESULT([$hwloc_plugin_components]) + + AS_IF([test "$hwloc_pci_component" = "static"], + [HWLOC_LIBS="$HWLOC_LIBS $HWLOC_PCIACCESS_LIBS" + HWLOC_CFLAGS="$HWLOC_CFLAGS $HWLOC_PCIACCESS_CFLAGS" + HWLOC_REQUIRES="$HWLOC_PCIACCESS_REQUIRES $HWLOC_REQUIRES"]) + AS_IF([test "$hwloc_opencl_component" = "static"], + [HWLOC_LIBS="$HWLOC_LIBS $HWLOC_OPENCL_LIBS" + HWLOC_CFLAGS="$HWLOC_CFLAGS $HWLOC_OPENCL_CFLAGS" + HWLOC_REQUIRES="$HWLOC_OPENCL_REQUIRES $HWLOC_REQUIRES"]) + AS_IF([test "$hwloc_cuda_component" = "static"], + [HWLOC_LIBS="$HWLOC_LIBS $HWLOC_CUDA_LIBS" + HWLOC_CFLAGS="$HWLOC_CFLAGS $HWLOC_CUDA_CFLAGS" + HWLOC_REQUIRES="$HWLOC_CUDA_REQUIRES $HWLOC_REQUIRES"]) + AS_IF([test "$hwloc_nvml_component" = "static"], + [HWLOC_LIBS="$HWLOC_LIBS $HWLOC_NVML_LIBS" + HWLOC_CFLAGS="$HWLOC_CFLAGS $HWLOC_NVML_CFLAGS" + HWLOC_REQUIRES="$HWLOC_NVML_REQUIRES $HWLOC_REQUIRES"]) + AS_IF([test "$hwloc_gl_component" = "static"], + [HWLOC_LIBS="$HWLOC_LIBS $HWLOC_GL_LIBS" + HWLOC_CFLAGS="$HWLOC_CFLAGS $HWLOC_GL_CFLAGS" + HWLOC_REQUIRES="$HWLOC_GL_REQUIRES $HWLOC_REQUIRES"]) + AS_IF([test "$hwloc_xml_libxml_component" = "static"], + [HWLOC_LIBS="$HWLOC_LIBS $HWLOC_LIBXML2_LIBS" + HWLOC_CFLAGS="$HWLOC_CFLAGS $HWLOC_LIBXML2_CFLAGS" + HWLOC_REQUIRES="$HWLOC_LIBXML2_REQUIRES $HWLOC_REQUIRES"]) + + # + # Setup HWLOC's C, CPP, and LD flags, and LIBS + # + AC_SUBST(HWLOC_REQUIRES) + AC_SUBST(HWLOC_CFLAGS) + HWLOC_CPPFLAGS='-I$(HWLOC_top_builddir)/include -I$(HWLOC_top_srcdir)/include' + AC_SUBST(HWLOC_CPPFLAGS) + AC_SUBST(HWLOC_LDFLAGS) + AC_SUBST(HWLOC_LIBS) + AC_SUBST(HWLOC_LIBS_PRIVATE) + + # Set these values explicitly for embedded builds. Exporting + # these values through *_EMBEDDED_* values gives us the freedom to + # do something different someday if we ever need to. There's no + # need to fill these values in unless we're in embedded mode. + # Indeed, if we're building in embedded mode, we want HWLOC_LIBS + # to be empty so that nothing is linked into libhwloc_embedded.la + # itself -- only the upper-layer will link in anything required. + + 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_LIBS=$HWLOC_LIBS + HWLOC_LIBS=]) + AC_SUBST(HWLOC_EMBEDDED_CFLAGS) + AC_SUBST(HWLOC_EMBEDDED_CPPFLAGS) + AC_SUBST(HWLOC_EMBEDDED_LDADD) + AC_SUBST(HWLOC_EMBEDDED_LIBS) + + # Always generate these files + AC_CONFIG_FILES( + hwloc_config_prefix[Makefile] + hwloc_config_prefix[include/Makefile] + hwloc_config_prefix[src/Makefile ] + ) + + # Cleanup + AC_LANG_POP + + # Success + $2 +])dnl + +#----------------------------------------------------------------------- + +# Specify the symbol prefix +AC_DEFUN([HWLOC_SET_SYMBOL_PREFIX],[ + hwloc_symbol_prefix_value=$1 +])dnl + +#----------------------------------------------------------------------- + +# This must be a standalone routine so that it can be called both by +# HWLOC_INIT and an external caller (if HWLOC_INIT is not invoked). +AC_DEFUN([HWLOC_DO_AM_CONDITIONALS],[ + AS_IF([test "$hwloc_did_am_conditionals" != "yes"],[ + AM_CONDITIONAL([HWLOC_BUILD_STANDALONE], [test "$hwloc_mode" = "standalone"]) + + 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_LIBIBVERBS], + [test "x$hwloc_have_libibverbs" = "xyes"]) + AM_CONDITIONAL([HWLOC_HAVE_CUDA], + [test "x$hwloc_have_cuda" = "xyes"]) + AM_CONDITIONAL([HWLOC_HAVE_GL], + [test "x$hwloc_have_gl" = "xyes"]) + AM_CONDITIONAL([HWLOC_HAVE_MYRIEXPRESS], + [test "x$hwloc_have_myriexpress" = "xyes"]) + AM_CONDITIONAL([HWLOC_HAVE_CUDART], + [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_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_BUILD_DOXYGEN], + [test "x$hwloc_generate_doxs" = "xyes"]) + AM_CONDITIONAL([HWLOC_BUILD_README], + [test "x$hwloc_generate_readme" = "xyes" -a \( "x$hwloc_install_doxs" = "xyes" -o "x$hwloc_generate_doxs" = "xyes" \) ]) + AM_CONDITIONAL([HWLOC_INSTALL_DOXYGEN], + [test "x$hwloc_install_doxs" = "xyes"]) + + AM_CONDITIONAL([HWLOC_HAVE_LINUX], [test "x$hwloc_linux" = "xyes"]) + AM_CONDITIONAL([HWLOC_HAVE_BGQ], [test "x$hwloc_bgq" = "xyes"]) + AM_CONDITIONAL([HWLOC_HAVE_IRIX], [test "x$hwloc_irix" = "xyes"]) + AM_CONDITIONAL([HWLOC_HAVE_DARWIN], [test "x$hwloc_darwin" = "xyes"]) + AM_CONDITIONAL([HWLOC_HAVE_FREEBSD], [test "x$hwloc_freebsd" = "xyes"]) + 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"]) + + AM_CONDITIONAL([HWLOC_HAVE_X86_32], [test "x$hwloc_x86_32" = "xyes"]) + AM_CONDITIONAL([HWLOC_HAVE_X86_64], [test "x$hwloc_x86_64" = "xyes"]) + AM_CONDITIONAL([HWLOC_HAVE_X86_CPUID], [test "x$hwloc_have_x86_cpuid" = "xyes"]) + + AM_CONDITIONAL([HWLOC_HAVE_PLUGINS], [test "x$hwloc_have_plugins" = "xyes"]) + AM_CONDITIONAL([HWLOC_PCI_BUILD_STATIC], [test "x$hwloc_pci_component" = "xstatic"]) + AM_CONDITIONAL([HWLOC_OPENCL_BUILD_STATIC], [test "x$hwloc_opencl_component" = "xstatic"]) + AM_CONDITIONAL([HWLOC_CUDA_BUILD_STATIC], [test "x$hwloc_cuda_component" = "xstatic"]) + AM_CONDITIONAL([HWLOC_NVML_BUILD_STATIC], [test "x$hwloc_nvml_component" = "xstatic"]) + AM_CONDITIONAL([HWLOC_GL_BUILD_STATIC], [test "x$hwloc_gl_component" = "xstatic"]) + AM_CONDITIONAL([HWLOC_XML_LIBXML_BUILD_STATIC], [test "x$hwloc_xml_libxml_component" = "xstatic"]) + + AM_CONDITIONAL([HWLOC_HAVE_CXX], [test "x$hwloc_have_cxx" = "xyes"]) + ]) + hwloc_did_am_conditionals=yes +])dnl + +#----------------------------------------------------------------------- + +AC_DEFUN([_HWLOC_CHECK_DIFF_U], [ + AC_MSG_CHECKING([whether diff accepts -u]) + if diff -u /dev/null /dev/null 2> /dev/null + then + HWLOC_DIFF_U="-u" + else + HWLOC_DIFF_U="" + fi + AC_SUBST([HWLOC_DIFF_U]) + AC_MSG_RESULT([$HWLOC_DIFF_U]) +]) + +AC_DEFUN([_HWLOC_CHECK_DIFF_W], [ + AC_MSG_CHECKING([whether diff accepts -w]) + if diff -w /dev/null /dev/null 2> /dev/null + then + HWLOC_DIFF_W="-w" + else + HWLOC_DIFF_W="" + fi + AC_SUBST([HWLOC_DIFF_W]) + AC_MSG_RESULT([$HWLOC_DIFF_W]) +]) + +#----------------------------------------------------------------------- + +dnl HWLOC_CHECK_DECL +dnl +dnl Check declaration of given function by trying to call it with an insane +dnl number of arguments (10). Success means the compiler couldn't really check. +AC_DEFUN([_HWLOC_CHECK_DECL], [ + AC_MSG_CHECKING([whether function $1 is declared]) + AC_REQUIRE([AC_PROG_CC]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM( + [AC_INCLUDES_DEFAULT([$4]) + void * $1;], + )], + [AC_MSG_RESULT([no]) + $3], + [AC_MSG_RESULT([yes]) + $2] + ) +]) + +#----------------------------------------------------------------------- + +dnl HWLOC_CHECK_DECLS +dnl +dnl Same as HWLOCK_CHECK_DECL, but defines HAVE_DECL_foo to 1 or 0 depending on +dnl the result. +AC_DEFUN([_HWLOC_CHECK_DECLS], [ + HWLOC_CHECK_DECL([$1], [ac_have_decl=1], [ac_have_decl=0], [$4]) + AC_DEFINE_UNQUOTED(AS_TR_CPP([HAVE_DECL_$1]), [$ac_have_decl], + [Define to 1 if you have the declaration of `$1', and to 0 if you don't]) +]) + +#----------------------------------------------------------------------- + +dnl HWLOC_CHECK_LTDL_DEPS +dnl +dnl Add ltdl dependencies to HWLOC_LIBS_PRIVATE +AC_DEFUN([HWLOC_CHECK_LTDL_DEPS], [ + # save variables that we'll modify below + save_lt_cv_dlopen="$lt_cv_dlopen" + save_lt_cv_dlopen_libs="$lt_cv_dlopen_libs" + save_lt_cv_dlopen_self="$lt_cv_dlopen_self" + ########################################################### + # code stolen from LT_SYS_DLOPEN_SELF in libtool.m4 + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + # end of code stolen from LT_SYS_DLOPEN_SELF in libtool.m4 + ########################################################### + + HWLOC_LIBS_PRIVATE="$HWLOC_LIBS_PRIVATE $lt_cv_dlopen_libs" + + # restore modified variable in case the actual libtool code uses them + lt_cv_dlopen="$save_lt_cv_dlopen" + lt_cv_dlopen_libs="$save_lt_cv_dlopen_libs" + lt_cv_dlopen_self="$save_lt_cv_dlopen_self" +]) diff --git a/opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_check_attributes.m4 b/opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_check_attributes.m4 new file mode 100644 index 0000000000..765407168b --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_check_attributes.m4 @@ -0,0 +1,533 @@ +# This macro set originally copied from Open MPI: +# Copyright © 2004-2007 The Trustees of Indiana University and Indiana +# University Research and Technology +# Corporation. All rights reserved. +# Copyright © 2004-2005 The University of Tennessee and The University +# of Tennessee Research Foundation. All rights +# reserved. +# Copyright © 2004-2007 High Performance Computing Center Stuttgart, +# University of Stuttgart. All rights reserved. +# Copyright © 2004-2005 The Regents of the University of California. +# All rights reserved. +# and renamed for hwloc: +# Copyright © 2009 Inria. All rights reserved. +# Copyright © 2009 Université Bordeaux +# Copyright © 2010 Cisco Systems, Inc. All rights reserved. +# See COPYING in top-level directory. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer listed +# in this license in the documentation and/or other materials +# provided with the distribution. +# +# - Neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# The copyright holders provide no reassurances that the source code +# provided does not infringe any patent, copyright, or any other +# intellectual property rights of third parties. The copyright holders +# disclaim any liability to any recipient for claims brought against +# recipient by any third party for infringement of that parties +# intellectual property rights. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# Search the generated warnings for +# keywords regarding skipping or ignoring certain attributes +# Intel: ignore +# Sun C++: skip +# +AC_DEFUN([_HWLOC_ATTRIBUTE_FAIL_SEARCH],[ + # Be safe for systems that have ancient Autoconf's (e.g., RHEL5) + m4_ifdef([AC_PROG_GREP], + [AC_REQUIRE([AC_PROG_GREP])], + [GREP=grep]) + + if test -s conftest.err ; then + for i in ignore skip ; do + $GREP -iq $i conftest.err + if test "$?" = "0" ; then + hwloc_cv___attribute__[$1]=0 + break; + fi + done + fi +]) + +# +# HWLOC: Remove C++ compiler check. It can result in a circular +# dependency in embedded situations. +# +# Check for one specific attribute by compiling with C +# and possibly using a cross-check. +# +# If the cross-check is defined, a static function "usage" should be +# defined, which is to be called from main (to circumvent warnings +# regarding unused function in main file) +# static int usage (int * argument); +# +# The last argument is for specific CFLAGS, that need to be set +# for the compiler to generate a warning on the cross-check. +# This may need adaption for future compilers / CFLAG-settings. +# +AC_DEFUN([_HWLOC_CHECK_SPECIFIC_ATTRIBUTE], [ + AC_MSG_CHECKING([for __attribute__([$1])]) + AC_CACHE_VAL(hwloc_cv___attribute__[$1], [ + # + # Try to compile using the C compiler + # + AC_TRY_COMPILE([$2],[], + [ + # + # In case we did succeed: Fine, but was this due to the + # attribute being ignored/skipped? Grep for IgNoRe/skip in conftest.err + # and if found, reset the hwloc_cv__attribute__var=0 + # + hwloc_cv___attribute__[$1]=1 + _HWLOC_ATTRIBUTE_FAIL_SEARCH([$1]) + ], + [hwloc_cv___attribute__[$1]=0]) + + # + # If the attribute is supported by both compilers, + # try to recompile a *cross-check*, IFF defined. + # + if test '(' "$hwloc_cv___attribute__[$1]" = "1" -a "[$3]" != "" ')' ; then + ac_c_werror_flag_safe=$ac_c_werror_flag + ac_c_werror_flag="yes" + CFLAGS_safe=$CFLAGS + CFLAGS="$CFLAGS [$4]" + + AC_TRY_COMPILE([$3], + [ + int i=4711; + i=usage(&i); + ], + [hwloc_cv___attribute__[$1]=0], + [ + # + # In case we did NOT succeed: Fine, but was this due to the + # attribute being ignored? Grep for IgNoRe in conftest.err + # and if found, reset the hwloc_cv__attribute__var=0 + # + hwloc_cv___attribute__[$1]=1 + _HWLOC_ATTRIBUTE_FAIL_SEARCH([$1]) + ]) + + ac_c_werror_flag=$ac_c_werror_flag_safe + CFLAGS=$CFLAGS_safe + fi + ]) + + if test "$hwloc_cv___attribute__[$1]" = "1" ; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi +]) + + +# +# Test the availability of __attribute__ and with the help +# of _HWLOC_CHECK_SPECIFIC_ATTRIBUTE for the support of +# particular attributes. Compilers, that do not support an +# attribute most often fail with a warning (when the warning +# level is set). +# The compilers output is parsed in _HWLOC_ATTRIBUTE_FAIL_SEARCH +# +# To add a new attributes __NAME__ add the +# hwloc_cv___attribute__NAME +# add a new check with _HWLOC_CHECK_SPECIFIC_ATTRIBUTE (possibly with a cross-check) +# _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([name], [int foo (int arg) __attribute__ ((__name__));], [], []) +# and define the corresponding +# AC_DEFINE_UNQUOTED(_HWLOC_HAVE_ATTRIBUTE_NAME, [$hwloc_cv___attribute__NAME], +# [Whether your compiler has __attribute__ NAME or not]) +# and decide on a correct macro (in opal/include/opal_config_bottom.h): +# # define __opal_attribute_NAME(x) __attribute__(__NAME__) +# +# Please use the "__"-notation of the attribute in order not to +# clash with predefined names or macros (e.g. const, which some compilers +# do not like..) +# + + +AC_DEFUN([_HWLOC_CHECK_ATTRIBUTES], [ + AC_MSG_CHECKING(for __attribute__) + + AC_CACHE_VAL(hwloc_cv___attribute__, [ + AC_TRY_COMPILE( + [#include + /* Check for the longest available __attribute__ (since gcc-2.3) */ + struct foo { + char a; + int x[2] __attribute__ ((__packed__)); + }; + ], + [], + [hwloc_cv___attribute__=1], + [hwloc_cv___attribute__=0], + ) + + if test "$hwloc_cv___attribute__" = "1" ; then + AC_TRY_COMPILE( + [#include + /* Check for the longest available __attribute__ (since gcc-2.3) */ + struct foo { + char a; + int x[2] __attribute__ ((__packed__)); + }; + ], + [], + [hwloc_cv___attribute__=1], + [hwloc_cv___attribute__=0], + ) + fi + ]) + AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE, [$hwloc_cv___attribute__], + [Whether your compiler has __attribute__ or not]) + +# +# Now that we know the compiler support __attribute__ let's check which kind of +# attributed are supported. +# + if test "$hwloc_cv___attribute__" = "0" ; then + AC_MSG_RESULT([no]) + hwloc_cv___attribute__aligned=0 + hwloc_cv___attribute__always_inline=0 + hwloc_cv___attribute__cold=0 + hwloc_cv___attribute__const=0 + hwloc_cv___attribute__deprecated=0 + hwloc_cv___attribute__format=0 + hwloc_cv___attribute__hot=0 + hwloc_cv___attribute__malloc=0 + hwloc_cv___attribute__may_alias=0 + hwloc_cv___attribute__no_instrument_function=0 + hwloc_cv___attribute__nonnull=0 + hwloc_cv___attribute__noreturn=0 + hwloc_cv___attribute__packed=0 + hwloc_cv___attribute__pure=0 + hwloc_cv___attribute__sentinel=0 + hwloc_cv___attribute__unused=0 + hwloc_cv___attribute__warn_unused_result=0 + hwloc_cv___attribute__weak_alias=0 + else + AC_MSG_RESULT([yes]) + + _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([aligned], + [struct foo { char text[4]; } __attribute__ ((__aligned__(8)));], + [], + []) + + # + # Ignored by PGI-6.2.5; -- recognized by output-parser + # + _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([always_inline], + [int foo (int arg) __attribute__ ((__always_inline__));], + [], + []) + + _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([cold], + [ + int foo(int arg1, int arg2) __attribute__ ((__cold__)); + int foo(int arg1, int arg2) { return arg1 * arg2 + arg1; } + ], + [], + []) + + _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([const], + [ + int foo(int arg1, int arg2) __attribute__ ((__const__)); + int foo(int arg1, int arg2) { return arg1 * arg2 + arg1; } + ], + [], + []) + + + _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([deprecated], + [ + int foo(int arg1, int arg2) __attribute__ ((__deprecated__)); + int foo(int arg1, int arg2) { return arg1 * arg2 + arg1; } + ], + [], + []) + + + HWLOC_ATTRIBUTE_CFLAGS= + case "$hwloc_c_vendor" in + gnu) + HWLOC_ATTRIBUTE_CFLAGS="-Wall" + ;; + intel) + # we want specifically the warning on format string conversion + HWLOC_ATTRIBUTE_CFLAGS="-we181" + ;; + esac + _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([format], + [ + int this_printf (void *my_object, const char *my_format, ...) __attribute__ ((__format__ (__printf__, 2, 3))); + ], + [ + static int usage (int * argument); + extern int this_printf (int arg1, const char *my_format, ...) __attribute__ ((__format__ (__printf__, 2, 3))); + + static int usage (int * argument) { + return this_printf (*argument, "%d", argument); /* This should produce a format warning */ + } + /* The autoconf-generated main-function is int main(), which produces a warning by itself */ + int main(void); + ], + [$HWLOC_ATTRIBUTE_CFLAGS]) + + _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([hot], + [ + int foo(int arg1, int arg2) __attribute__ ((__hot__)); + int foo(int arg1, int arg2) { return arg1 * arg2 + arg1; } + ], + [], + []) + + _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([malloc], + [ +#ifdef HAVE_STDLIB_H +# include +#endif + int * foo(int arg1) __attribute__ ((__malloc__)); + int * foo(int arg1) { return (int*) malloc(arg1); } + ], + [], + []) + + + # + # Attribute may_alias: No suitable cross-check available, that works for non-supporting compilers + # Ignored by intel-9.1.045 -- turn off with -wd1292 + # Ignored by PGI-6.2.5; ignore not detected due to missing cross-check + # + _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([may_alias], + [int * p_value __attribute__ ((__may_alias__));], + [], + []) + + + _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([no_instrument_function], + [int * foo(int arg1) __attribute__ ((__no_instrument_function__));], + [], + []) + + + # + # Attribute nonnull: + # Ignored by intel-compiler 9.1.045 -- recognized by cross-check + # Ignored by PGI-6.2.5 (pgCC) -- recognized by cross-check + # + HWLOC_ATTRIBUTE_CFLAGS= + case "$hwloc_c_vendor" in + gnu) + HWLOC_ATTRIBUTE_CFLAGS="-Wall" + ;; + intel) + # we do not want to get ignored attributes warnings, but rather real warnings + HWLOC_ATTRIBUTE_CFLAGS="-wd1292" + ;; + esac + _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([nonnull], + [ + int square(int *arg) __attribute__ ((__nonnull__)); + int square(int *arg) { return *arg; } + ], + [ + static int usage(int * argument); + int square(int * argument) __attribute__ ((__nonnull__)); + int square(int * argument) { return (*argument) * (*argument); } + + static int usage(int * argument) { + return square( ((void*)0) ); /* This should produce an argument must be nonnull warning */ + } + /* The autoconf-generated main-function is int main(), which produces a warning by itself */ + int main(void); + ], + [$HWLOC_ATTRIBUTE_CFLAGS]) + + + _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([noreturn], + [ +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_STDLIB_H +# include +#endif + void fatal(int arg1) __attribute__ ((__noreturn__)); + void fatal(int arg1) { exit(arg1); } + ], + [], + []) + + _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([packed], + [ + struct foo { + char a; + int x[2] __attribute__ ((__packed__)); + }; + ], + [], + []) + + _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([pure], + [ + int square(int arg) __attribute__ ((__pure__)); + int square(int arg) { return arg * arg; } + ], + [], + []) + + # + # Attribute sentinel: + # Ignored by the intel-9.1.045 -- recognized by cross-check + # intel-10.0beta works fine + # Ignored by PGI-6.2.5 (pgCC) -- recognized by output-parser and cross-check + # Ignored by pathcc-2.2.1 -- recognized by cross-check (through grep ignore) + # + HWLOC_ATTRIBUTE_CFLAGS= + case "$hwloc_c_vendor" in + gnu) + HWLOC_ATTRIBUTE_CFLAGS="-Wall" + ;; + intel) + # we do not want to get ignored attributes warnings + HWLOC_ATTRIBUTE_CFLAGS="-wd1292" + ;; + esac + _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([sentinel], + [ + int my_execlp(const char * file, const char *arg, ...) __attribute__ ((__sentinel__)); + ], + [ + static int usage(int * argument); + int my_execlp(const char * file, const char *arg, ...) __attribute__ ((__sentinel__)); + + static int usage(int * argument) { + void * last_arg_should_be_null = argument; + return my_execlp ("lala", "/home/there", last_arg_should_be_null); /* This should produce a warning */ + } + /* The autoconf-generated main-function is int main(), which produces a warning by itself */ + int main(void); + ], + [$HWLOC_ATTRIBUTE_CFLAGS]) + + _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([unused], + [ + int square(int arg1 __attribute__ ((__unused__)), int arg2); + int square(int arg1, int arg2) { return arg2; } + ], + [], + []) + + + # + # Attribute warn_unused_result: + # Ignored by the intel-compiler 9.1.045 -- recognized by cross-check + # Ignored by pathcc-2.2.1 -- recognized by cross-check (through grep ignore) + # + HWLOC_ATTRIBUTE_CFLAGS= + case "$hwloc_c_vendor" in + gnu) + HWLOC_ATTRIBUTE_CFLAGS="-Wall" + ;; + intel) + # we do not want to get ignored attributes warnings + HWLOC_ATTRIBUTE_CFLAGS="-wd1292" + ;; + esac + _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([warn_unused_result], + [ + int foo(int arg) __attribute__ ((__warn_unused_result__)); + int foo(int arg) { return arg + 3; } + ], + [ + static int usage(int * argument); + int foo(int arg) __attribute__ ((__warn_unused_result__)); + + int foo(int arg) { return arg + 3; } + static int usage(int * argument) { + foo (*argument); /* Should produce an unused result warning */ + return 0; + } + + /* The autoconf-generated main-function is int main(), which produces a warning by itself */ + int main(void); + ], + [$HWLOC_ATTRIBUTE_CFLAGS]) + + + _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([weak_alias], + [ + int foo(int arg); + int foo(int arg) { return arg + 3; } + int foo2(int arg) __attribute__ ((__weak__, __alias__("foo"))); + ], + [], + []) + + fi + + # Now that all the values are set, define them + + AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_ALIGNED, [$hwloc_cv___attribute__aligned], + [Whether your compiler has __attribute__ aligned or not]) + AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_ALWAYS_INLINE, [$hwloc_cv___attribute__always_inline], + [Whether your compiler has __attribute__ always_inline or not]) + AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_COLD, [$hwloc_cv___attribute__cold], + [Whether your compiler has __attribute__ cold or not]) + AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_CONST, [$hwloc_cv___attribute__const], + [Whether your compiler has __attribute__ const or not]) + AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_DEPRECATED, [$hwloc_cv___attribute__deprecated], + [Whether your compiler has __attribute__ deprecated or not]) + AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_FORMAT, [$hwloc_cv___attribute__format], + [Whether your compiler has __attribute__ format or not]) + AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_HOT, [$hwloc_cv___attribute__hot], + [Whether your compiler has __attribute__ hot or not]) + AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_MALLOC, [$hwloc_cv___attribute__malloc], + [Whether your compiler has __attribute__ malloc or not]) + AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_MAY_ALIAS, [$hwloc_cv___attribute__may_alias], + [Whether your compiler has __attribute__ may_alias or not]) + AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_NO_INSTRUMENT_FUNCTION, [$hwloc_cv___attribute__no_instrument_function], + [Whether your compiler has __attribute__ no_instrument_function or not]) + AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_NONNULL, [$hwloc_cv___attribute__nonnull], + [Whether your compiler has __attribute__ nonnull or not]) + AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_NORETURN, [$hwloc_cv___attribute__noreturn], + [Whether your compiler has __attribute__ noreturn or not]) + AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_PACKED, [$hwloc_cv___attribute__packed], + [Whether your compiler has __attribute__ packed or not]) + AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_PURE, [$hwloc_cv___attribute__pure], + [Whether your compiler has __attribute__ pure or not]) + AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_SENTINEL, [$hwloc_cv___attribute__sentinel], + [Whether your compiler has __attribute__ sentinel or not]) + AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_UNUSED, [$hwloc_cv___attribute__unused], + [Whether your compiler has __attribute__ unused or not]) + AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_WARN_UNUSED_RESULT, [$hwloc_cv___attribute__warn_unused_result], + [Whether your compiler has __attribute__ warn unused result or not]) + 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/hwloc1110/hwloc/config/hwloc_check_vendor.m4 b/opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_check_vendor.m4 new file mode 100644 index 0000000000..0963bc1749 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_check_vendor.m4 @@ -0,0 +1,239 @@ +dnl -*- shell-script -*- +dnl +dnl Copyright © 2004-2005 The Trustees of Indiana University and Indiana +dnl University Research and Technology +dnl Corporation. All rights reserved. +dnl Copyright © 2004-2005 The University of Tennessee and The University +dnl of Tennessee Research Foundation. All rights +dnl reserved. +dnl Copyright © 2004-2005 High Performance Computing Center Stuttgart, +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$ +dnl +dnl Additional copyrights may follow +dnl +dnl $HEADER$ +dnl + +dnl ------------------------------------------------------------------ +dnl This m4 file originally copied from Open MPI +dnl config/ompi_check_vendor.m4. +dnl ------------------------------------------------------------------ + + +# HWLOC_C_COMPILER_VENDOR(VENDOR_VARIABLE) +# --------------------------------------- +# Set shell variable VENDOR_VARIABLE to the name of the compiler +# vendor for the current C compiler. +# +# See comment for _HWLOC_CHECK_COMPILER_VENDOR for a complete +# list of currently detected compilers. +AC_DEFUN([_HWLOC_C_COMPILER_VENDOR], [ + AC_REQUIRE([AC_PROG_CC]) + + AC_CACHE_CHECK([for the C compiler vendor], + [hwloc_cv_c_compiler_vendor], + [AC_LANG_PUSH(C) + _HWLOC_CHECK_COMPILER_VENDOR([hwloc_cv_c_compiler_vendor]) + AC_LANG_POP(C)]) + + $1="$hwloc_cv_c_compiler_vendor" +]) + + +# workaround to avoid syntax error with Autoconf < 2.68: +m4_ifndef([AC_LANG_DEFINES_PROVIDED], + [m4_define([AC_LANG_DEFINES_PROVIDED])]) + +# HWLOC_IFDEF_IFELSE(symbol, [action-if-defined], +# [action-if-not-defined]) +# ---------------------------------------------- +# Run compiler to determine if preprocessor symbol "symbol" is +# defined by the compiler. +AC_DEFUN([HWLOC_IFDEF_IFELSE], [ + AC_COMPILE_IFELSE([AC_LANG_DEFINES_PROVIDED +#ifndef $1 +#error "symbol $1 not defined" +choke me +#endif], [$2], [$3])]) + + +# HWLOC_IF_IFELSE(symbol, [action-if-defined], +# [action-if-not-defined]) +# ---------------------------------------------- +# Run compiler to determine if preprocessor symbol "symbol" is +# defined by the compiler. +AC_DEFUN([HWLOC_IF_IFELSE], [ + AC_COMPILE_IFELSE([AC_LANG_DEFINES_PROVIDED +#if !( $1 ) +#error "condition $1 not met" +choke me +#endif], [$2], [$3])]) + + +# _HWLOC_CHECK_COMPILER_VENDOR(VENDOR_VARIABLE) +# -------------------------------------------- +# Set shell variable VENDOR_VARIABLE to the name of the compiler +# vendor for the compiler for the current language. Language must be +# one of C, OBJC, or C++. +# +# thanks to http://predef.sourceforge.net/precomp.html for the list +# of defines to check. +AC_DEFUN([_HWLOC_CHECK_COMPILER_VENDOR], [ + hwloc_check_compiler_vendor_result="unknown" + + # GNU is probably the most common, so check that one as soon as + # possible. Intel pretends to be GNU, so need to check Intel + # before checking for GNU. + + # Intel + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IF_IFELSE([defined(__INTEL_COMPILER) || defined(__ICC)], + [hwloc_check_compiler_vendor_result="intel"])]) + + # GNU + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IFDEF_IFELSE([__GNUC__], + [hwloc_check_compiler_vendor_result="gnu"])]) + + # Borland Turbo C + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IFDEF_IFELSE([__TURBOC__], + [hwloc_check_compiler_vendor_result="borland"])]) + + # Borland C++ + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IFDEF_IFELSE([__BORLANDC__], + [hwloc_check_compiler_vendor_result="borland"])]) + + # Comeau C++ + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IFDEF_IFELSE([__COMO__], + [hwloc_check_compiler_vendor_result="comeau"])]) + + # Compaq C/C++ + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IF_IFELSE([defined(__DECC) || defined(VAXC) || defined(__VAXC)], + [hwloc_check_compiler_vendor_result="compaq"], + [HWLOC_IF_IFELSE([defined(__osf__) && defined(__LANGUAGE_C__)], + [hwloc_check_compiler_vendor_result="compaq"], + [HWLOC_IFDEF_IFELSE([__DECCXX], + [hwloc_check_compiler_vendor_result="compaq"])])])]) + + # Cray C/C++ + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IFDEF_IFELSE([_CRAYC], + [hwloc_check_compiler_vendor_result="cray"])]) + + # Diab C/C++ + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IFDEF_IFELSE([__DCC__], + [hwloc_check_compiler_vendor_result="diab"])]) + + # Digital Mars + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IF_IFELSE([defined(__DMC__) || defined(__SC__) || defined(__ZTC__)], + [hwloc_check_compiler_vendor_result="digital mars"])]) + + # HP ANSI C / aC++ + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IF_IFELSE([defined(__HP_cc) || defined(__HP_aCC)], + [hwloc_check_compiler_vendor_result="hp"])]) + + # IBM XL C/C++ + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IF_IFELSE([defined(__xlC__) || defined(__IBMC__) || defined(__IBMCPP__)], + [hwloc_check_compiler_vendor_result="ibm"], + [HWLOC_IF_IFELSE([defined(_AIX) && !defined(__GNUC__)], + [hwloc_check_compiler_vendor_result="ibm"])])]) + + # KAI C++ (rest in peace) + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IFDEF_IFELSE([__KCC], + [hwloc_check_compiler_vendor_result="kai"])]) + + # LCC + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IFDEF_IFELSE([__LCC__], + [hwloc_check_compiler_vendor_result="lcc"])]) + + # MetaWare High C/C++ + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IFDEF_IFELSE([__HIGHC__], + [hwloc_check_compiler_vendor_result="metaware high"])]) + + # Metrowerks Codewarrior + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IFDEF_IFELSE([__MWERKS__], + [hwloc_check_compiler_vendor_result="metrowerks"])]) + + # MIPSpro (SGI) + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IF_IFELSE([defined(sgi) || defined(__sgi)], + [hwloc_check_compiler_vendor_result="sgi"])]) + + # MPW C++ + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IF_IFELSE([defined(__MRC__) || defined(MPW_C) || defined(MPW_CPLUS)], + [hwloc_check_compiler_vendor_result="mpw"])]) + + # Microsoft + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [# Always use C compiler when checking for Microsoft, as + # Visual C++ doesn't recognize .cc as a C++ file. + AC_LANG_PUSH(C) + HWLOC_IF_IFELSE([defined(_MSC_VER) || defined(__MSC_VER)], + [hwloc_check_compiler_vendor_result="microsoft"]) + AC_LANG_POP(C)]) + + # Norcroft C + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IFDEF_IFELSE([__CC_NORCROFT], + [hwloc_check_compiler_vendor_result="norcroft"])]) + + # Pelles C + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IFDEF_IFELSE([__POCC__], + [hwloc_check_compiler_vendor_result="pelles"])]) + + # Portland Group + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IFDEF_IFELSE([__PGI], + [hwloc_check_compiler_vendor_result="portland group"])]) + + # SAS/C + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IF_IFELSE([defined(SASC) || defined(__SASC) || defined(__SASC__)], + [hwloc_check_compiler_vendor_result="sas"])]) + + # Sun Workshop C/C++ + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IF_IFELSE([defined(__SUNPRO_C) || defined(__SUNPRO_CC)], + [hwloc_check_compiler_vendor_result="sun"])]) + + # TenDRA C/C++ + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IFDEF_IFELSE([__TenDRA__], + [hwloc_check_compiler_vendor_result="tendra"])]) + + # Tiny C + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IFDEF_IFELSE([__TINYC__], + [hwloc_check_compiler_vendor_result="tiny"])]) + + # USL C + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IFDEF_IFELSE([__USLC__], + [hwloc_check_compiler_vendor_result="usl"])]) + + # Watcom C++ + AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], + [HWLOC_IFDEF_IFELSE([__WATCOMC__], + [hwloc_check_compiler_vendor_result="watcom"])]) + + $1="$hwloc_check_compiler_vendor_result" + unset hwloc_check_compiler_vendor_result +]) diff --git a/opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_check_visibility.m4 b/opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_check_visibility.m4 new file mode 100644 index 0000000000..885fe3d8df --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_check_visibility.m4 @@ -0,0 +1,131 @@ +# This macro set originally copied from Open MPI: +# Copyright © 2004-2005 The Trustees of Indiana University and Indiana +# University Research and Technology +# Corporation. All rights reserved. +# Copyright © 2004-2005 The University of Tennessee and The University +# of Tennessee Research Foundation. All rights +# reserved. +# Copyright © 2004-2007 High Performance Computing Center Stuttgart, +# University of Stuttgart. All rights reserved. +# Copyright © 2004-2005 The Regents of the University of California. +# All rights reserved. +# Copyright © 2006-2007 Cisco Systems, Inc. All rights reserved. +# and renamed/modified for hwloc: +# Copyright © 2009 Inria. All rights reserved. +# Copyright © 2009-2010 Université Bordeaux +# Copyright © 2010-2012 Cisco Systems, Inc. All rights reserved. +# See COPYING in top-level directory. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer listed +# in this license in the documentation and/or other materials +# provided with the distribution. +# +# - Neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# The copyright holders provide no reassurances that the source code +# provided does not infringe any patent, copyright, or any other +# intellectual property rights of third parties. The copyright holders +# disclaim any liability to any recipient for claims brought against +# recipient by any third party for infringement of that parties +# intellectual property rights. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# _HWLOC_CHECK_VISIBILITY +# -------------------------------------------------------- +AC_DEFUN([_HWLOC_CHECK_VISIBILITY],[ + # Be safe for systems that have ancient Autoconf's (e.g., RHEL5) + m4_ifdef([AC_PROG_GREP], + [AC_REQUIRE([AC_PROG_GREP])], + [GREP=grep]) + + # Check if the compiler has support for visibility, like some + # versions of gcc, icc, Sun Studio cc. + AC_ARG_ENABLE(visibility, + AC_HELP_STRING([--enable-visibility], + [enable visibility feature of certain compilers/linkers (default: enabled on platforms that support it)])) + + case ${target} in + *-*-aix*|*-*-mingw*|*-*-cygwin*|*-*-hpux*) + enable_visibility=no + ;; + esac + + hwloc_visibility_define=0 + hwloc_msg="whether to enable symbol visibility" + if test "$enable_visibility" = "no"; then + AC_MSG_CHECKING([$hwloc_msg]) + AC_MSG_RESULT([no (disabled)]) + else + CFLAGS_orig=$CFLAGS + + hwloc_add= + case "$hwloc_c_vendor" in + sun) + # Check using Sun Studio -xldscope=hidden flag + hwloc_add=-xldscope=hidden + CFLAGS="$CFLAGS_orig $hwloc_add -errwarn=%all" + ;; + + *) + # Check using -fvisibility=hidden + hwloc_add=-fvisibility=hidden + CFLAGS="$CFLAGS_orig $hwloc_add -Werror" + ;; + esac + + AC_MSG_CHECKING([if $CC supports $hwloc_add]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ + #include + __attribute__((visibility("default"))) int foo; + ]],[[fprintf(stderr, "Hello, world\n");]])], + [AS_IF([test -s conftest.err], + [$GREP -iq visibility conftest.err + # If we find "visibility" in the stderr, then + # assume it doesn't work + AS_IF([test "$?" = "0"], [hwloc_add=])]) + ], [hwloc_add=]) + AS_IF([test "$hwloc_add" = ""], + [AC_MSG_RESULT([no])], + [AC_MSG_RESULT([yes])]) + + CFLAGS=$CFLAGS_orig + HWLOC_VISIBILITY_CFLAGS=$hwloc_add + + if test "$hwloc_add" != "" ; then + hwloc_visibility_define=1 + AC_MSG_CHECKING([$hwloc_msg]) + AC_MSG_RESULT([yes (via $hwloc_add)]) + elif test "$enable_visibility" = "yes"; then + AC_MSG_ERROR([Symbol visibility support requested but compiler does not seem to support it. Aborting]) + else + AC_MSG_CHECKING([$hwloc_msg]) + AC_MSG_RESULT([no (unsupported)]) + fi + unset hwloc_add + fi + + AC_DEFINE_UNQUOTED([HWLOC_C_HAVE_VISIBILITY], [$hwloc_visibility_define], + [Whether C compiler supports symbol visibility or not]) +]) diff --git a/opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_components.m4 b/opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_components.m4 new file mode 100644 index 0000000000..7d5c1fa194 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_components.m4 @@ -0,0 +1,66 @@ +# Copyright © 2012 Inria. All rights reserved. +# See COPYING in top-level directory. + + +# HWLOC_PREPARE_FILTER_COMPONENTS +# +# Given a comma-separated list of names, define hwloc__component_maybeplugin=1. +# +# $1 = command-line given list of components to build as plugins +# +AC_DEFUN([HWLOC_PREPARE_FILTER_COMPONENTS], [ + for name in `echo [$1] | sed -e 's/,/ /g'` ; do + str="hwloc_${name}_component_wantplugin=1" + eval $str + done +]) + + +# HWLOC_FILTER_COMPONENTS +# +# For each component in hwloc_components, +# check if hwloc__component_wantplugin=1 or enable_plugin=yes, +# and check if hwloc__component_maybeplugin=1. +# Add to hwloc_[static|plugin]_components accordingly. +# And set hwloc__component=[static|plugin] accordingly. +# +AC_DEFUN([HWLOC_FILTER_COMPONENTS], [ +for name in $hwloc_components ; do + str="maybeplugin=\$hwloc_${name}_component_maybeplugin" + eval $str + str="wantplugin=\$hwloc_${name}_component_wantplugin" + eval $str + if test x$hwloc_have_plugins = xyes && test x$maybeplugin = x1 && test x$wantplugin = x1 -o x$enable_plugins = xyes; then + hwloc_plugin_components="$hwloc_plugin_components $name" + str="hwloc_${name}_component=plugin" + else + hwloc_static_components="$hwloc_static_components $name" + str="hwloc_${name}_component=static" + fi + eval $str +done +]) + + +# HWLOC_LIST_STATIC_COMPONENTS +# +# Append to file $1 an array of components by listing component names in $2. +# +# $1 = filename +# $2 = list of component names +# +AC_DEFUN([HWLOC_LIST_STATIC_COMPONENTS], [ +for comp in [$2]; do + echo "HWLOC_DECLSPEC extern const struct hwloc_component hwloc_${comp}_component;" >>[$1] +done +cat <>[$1] +static const struct hwloc_component * hwloc_static_components[[]] = { +EOF +for comp in [$2]; do + echo " &hwloc_${comp}_component," >>[$1] +done +cat <>[$1] + NULL +}; +EOF +]) diff --git a/opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_get_version.sh b/opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_get_version.sh new file mode 100755 index 0000000000..74bca537ce --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/config/hwloc_get_version.sh @@ -0,0 +1,98 @@ +#!/bin/sh +# +# Copyright © 2004-2006 The Trustees of Indiana University and Indiana +# University Research and Technology +# Corporation. All rights reserved. +# Copyright © 2004-2005 The University of Tennessee and The University +# of Tennessee Research Foundation. All rights +# reserved. +# Copyright © 2004-2005 High Performance Computing Center Stuttgart, +# University of Stuttgart. All rights reserved. +# Copyright © 2004-2005 The Regents of the University of California. +# All rights reserved. +# Copyright © 2008-2014 Cisco Systems, Inc. All rights reserved. +# Copyright © 2014 Inria. All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# + +srcfile="$1" +option="$2" + +if test -z "$srcfile"; then + option="--help" +else + : ${srcdir=.} + + 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" + + HWLOC_VERSION="$HWLOC_MAJOR_VERSION.$HWLOC_MINOR_VERSION.$HWLOC_RELEASE_VERSION${HWLOC_GREEK_VERSION}" + + # If HWLOC_SNAPSHOT=1, then use HWLOC_SNAPSHOT_VERSION + if test "$HWLOC_SNAPSHOT" = "1"; then + # First, verify that HWLOC_SNAPSHOT_VERSION isn't empty. + if test -z "$HWLOC_SNAPSHOT_VERSION"; then + echo "*** ERROR: $1 contains snapshot=1, but an empty value for snapshot_version" 1>&2 + exit 1 + fi + HWLOC_VERSION=$HWLOC_SNAPSHOT_VERSION + fi + fi + + if test "$option" = ""; then + option="--version" + fi +fi + +case "$option" in + --version) + echo $HWLOC_VERSION + ;; + --release-date) + echo $HWLOC_RELEASE_DATE + ;; + --snapshot) + echo $HWLOC_SNAPSHOT + ;; + -h|--help) + cat < */ + void (*close_child)(struct hwloc__xml_import_state_s * state); + int (*get_content)(struct hwloc__xml_import_state_s * state, char **beginp, size_t expected_length); + void (*close_content)(struct hwloc__xml_import_state_s * state); + char * msgprefix; + void *data; /* libxml2 doc, or nolibxml buffer */ + struct hwloc_xml_imported_distances_s { + hwloc_obj_t root; + struct hwloc_distances_s distances; + struct hwloc_xml_imported_distances_s *prev, *next; + } *first_distances, *last_distances; +}; + +/************** + * XML export * + **************/ + +typedef struct hwloc__xml_export_state_s { + struct hwloc__xml_export_state_s *parent; + + void (*new_child)(struct hwloc__xml_export_state_s *parentstate, struct hwloc__xml_export_state_s *state, const char *name); + void (*new_prop)(struct hwloc__xml_export_state_s *state, const char *name, const char *value); + void (*add_content)(struct hwloc__xml_export_state_s *state, const char *buffer, size_t length); + void (*end_object)(struct hwloc__xml_export_state_s *state, const char *name); + + /* opaque data used to store backend-specific data. + * statically allocated to allow stack-allocation by the common code without knowing actual backend needs. + */ + char data[40]; +} * hwloc__xml_export_state_t; + +HWLOC_DECLSPEC void hwloc__xml_export_object (hwloc__xml_export_state_t state, struct hwloc_topology *topology, struct hwloc_obj *obj); + +HWLOC_DECLSPEC void hwloc__xml_export_diff(hwloc__xml_export_state_t parentstate, hwloc_topology_diff_t diff); + +/****************** + * XML components * + ******************/ + +struct hwloc_xml_callbacks { + int (*backend_init)(struct hwloc_xml_backend_data_s *bdata, const char *xmlpath, const char *xmlbuffer, int xmlbuflen); + int (*export_file)(struct hwloc_topology *topology, const char *filename); + int (*export_buffer)(struct hwloc_topology *topology, char **xmlbuffer, int *buflen); + void (*free_buffer)(void *xmlbuffer); + int (*import_diff)(struct hwloc__xml_import_state_s *state, const char *xmlpath, const char *xmlbuffer, int xmlbuflen, hwloc_topology_diff_t *diff, char **refnamep); + int (*export_diff_file)(union hwloc_topology_diff_u *diff, const char *refname, const char *filename); + int (*export_diff_buffer)(union hwloc_topology_diff_u *diff, const char *refname, char **xmlbuffer, int *buflen); +}; + +struct hwloc_xml_component { + struct hwloc_xml_callbacks *nolibxml_callbacks; + struct hwloc_xml_callbacks *libxml_callbacks; +}; + +HWLOC_DECLSPEC void hwloc_xml_callbacks_register(struct hwloc_xml_component *component); +HWLOC_DECLSPEC void hwloc_xml_callbacks_reset(void); + +#endif /* PRIVATE_XML_H */ diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/Makefile.am b/opal/mca/hwloc/hwloc1110/hwloc/src/Makefile.am new file mode 100644 index 0000000000..41aa35c14e --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/Makefile.am @@ -0,0 +1,235 @@ +# Copyright © 2009-2014 Inria. All rights reserved. +# Copyright © 2009-2012 Université Bordeaux +# Copyright © 2009-2014 Cisco Systems, Inc. All rights reserved. +# Copyright © 2011-2012 Oracle and/or its affiliates. All rights reserved. +# See COPYING in top-level directory. + +AM_CFLAGS = $(HWLOC_CFLAGS) +AM_CPPFLAGS = $(HWLOC_CPPFLAGS) -DHWLOC_INSIDE_LIBHWLOC +AM_LDFLAGS = $(HWLOC_LDFLAGS) + +EXTRA_DIST = dolib.c + +# If we're in standalone mode, build the installable library. +# Otherwise, build the embedded library. + +if HWLOC_BUILD_STANDALONE +lib_LTLIBRARIES = libhwloc.la +else +noinst_LTLIBRARIES = libhwloc_embedded.la +endif + +pluginsdir = @HWLOC_PLUGINS_DIR@ +plugins_LTLIBRARIES = +plugins_ldflags = -module -avoid-version -lltdl +AM_CPPFLAGS += -DHWLOC_PLUGINS_PATH=\"$(HWLOC_PLUGINS_PATH)\" + +# Sources and ldflags + +sources = \ + topology.c \ + traversal.c \ + distances.c \ + components.c \ + bind.c \ + bitmap.c \ + pci-common.c \ + diff.c \ + misc.c \ + base64.c \ + topology-noos.c \ + topology-synthetic.c \ + topology-custom.c \ + topology-xml.c \ + topology-xml-nolibxml.c +ldflags = + +# Conditionally add to the sources and ldflags + +if HWLOC_HAVE_LIBXML2 +if HWLOC_XML_LIBXML_BUILD_STATIC +sources += topology-xml-libxml.c +else +plugins_LTLIBRARIES += hwloc_xml_libxml.la +hwloc_xml_libxml_la_SOURCES = topology-xml-libxml.c +hwloc_xml_libxml_la_CFLAGS = $(AM_CFLAGS) $(HWLOC_LIBXML2_CFLAGS) -DHWLOC_INSIDE_PLUGIN +hwloc_xml_libxml_la_LDFLAGS = $(plugins_ldflags) $(HWLOC_LIBXML2_LIBS) +endif +endif HWLOC_HAVE_LIBXML2 + +if HWLOC_HAVE_PCI +if HWLOC_PCI_BUILD_STATIC +sources += topology-pci.c +else +plugins_LTLIBRARIES += hwloc_pci.la +hwloc_pci_la_SOURCES = topology-pci.c +hwloc_pci_la_CFLAGS = $(AM_CFLAGS) $(HWLOC_PCIACCESS_CFLAGS) -DHWLOC_INSIDE_PLUGIN +hwloc_pci_la_LDFLAGS = $(plugins_ldflags) $(HWLOC_PCIACCESS_LIBS) +endif +endif HWLOC_HAVE_PCI + +if HWLOC_HAVE_OPENCL +if HWLOC_OPENCL_BUILD_STATIC +sources += topology-opencl.c +else +plugins_LTLIBRARIES += hwloc_opencl.la +hwloc_opencl_la_SOURCES = topology-opencl.c +hwloc_opencl_la_CFLAGS = $(AM_CFLAGS) $(HWLOC_OPENCL_CFLAGS) -DHWLOC_INSIDE_PLUGIN +hwloc_opencl_la_LDFLAGS = $(plugins_ldflags) $(HWLOC_OPENCL_LIBS) +endif +endif HWLOC_HAVE_OPENCL + +if HWLOC_HAVE_CUDART +if HWLOC_CUDA_BUILD_STATIC +sources += topology-cuda.c +else +plugins_LTLIBRARIES += hwloc_cuda.la +hwloc_cuda_la_SOURCES = topology-cuda.c +hwloc_cuda_la_CFLAGS = $(AM_CFLAGS) $(HWLOC_CUDA_CFLAGS) -DHWLOC_INSIDE_PLUGIN +hwloc_cuda_la_LDFLAGS = $(plugins_ldflags) $(HWLOC_CUDA_LIBS) +endif +endif HWLOC_HAVE_CUDART + +if HWLOC_HAVE_NVML +if HWLOC_NVML_BUILD_STATIC +sources += topology-nvml.c +else +plugins_LTLIBRARIES += hwloc_nvml.la +hwloc_nvml_la_SOURCES = topology-nvml.c +hwloc_nvml_la_CFLAGS = $(AM_CFLAGS) $(HWLOC_NVML_CFLAGS) -DHWLOC_INSIDE_PLUGIN +hwloc_nvml_la_LDFLAGS = $(plugins_ldflags) $(HWLOC_NVML_LIBS) +endif +endif HWLOC_HAVE_NVML + +if HWLOC_HAVE_GL +if HWLOC_GL_BUILD_STATIC +sources += topology-gl.c +else +plugins_LTLIBRARIES += hwloc_gl.la +hwloc_gl_la_SOURCES = topology-gl.c +hwloc_gl_la_CFLAGS = $(AM_CFLAGS) $(HWLOC_GL_CFLAGS) -DHWLOC_INSIDE_PLUGIN +hwloc_gl_la_LDFLAGS = $(plugins_ldflags) $(HWLOC_GL_LIBS) +endif +endif HWLOC_HAVE_GL + +if HWLOC_HAVE_SOLARIS +sources += topology-solaris.c +sources += topology-solaris-chiptype.c +endif HWLOC_HAVE_SOLARIS + +if HWLOC_HAVE_LINUX +sources += topology-linux.c +endif HWLOC_HAVE_LINUX + +if HWLOC_HAVE_BGQ +sources += topology-bgq.c +endif HWLOC_HAVE_BGQ + +if HWLOC_HAVE_AIX +sources += topology-aix.c +ldflags += -lpthread +endif HWLOC_HAVE_AIX + +if HWLOC_HAVE_OSF +sources += topology-osf.c +ldflags += -lnuma -lpthread +endif HWLOC_HAVE_OSF + +if HWLOC_HAVE_HPUX +sources += topology-hpux.c +ldflags += -lpthread +endif HWLOC_HAVE_HPUX + +if HWLOC_HAVE_WINDOWS +sources += topology-windows.c +endif HWLOC_HAVE_WINDOWS + +if HWLOC_HAVE_DARWIN +sources += topology-darwin.c +endif HWLOC_HAVE_DARWIN + +if HWLOC_HAVE_FREEBSD +sources += topology-freebsd.c +endif HWLOC_HAVE_FREEBSD + +if HWLOC_HAVE_NETBSD +sources += topology-netbsd.c +ldflags += -lpthread +endif HWLOC_HAVE_NETBSD + +if HWLOC_HAVE_X86_CPUID +sources += topology-x86.c +endif HWLOC_HAVE_X86_CPUID + +if HWLOC_HAVE_GCC +ldflags += -no-undefined +endif HWLOC_HAVE_GCC + + +if HWLOC_HAVE_WINDOWS +# Windows specific rules + +LC_MESSAGES=C +export LC_MESSAGES +ldflags += -Xlinker --output-def -Xlinker .libs/libhwloc.def + +if HWLOC_HAVE_MS_LIB +dolib$(EXEEXT): dolib.c + $(CC_FOR_BUILD) $< -o $@ +.libs/libhwloc.lib: libhwloc.la dolib$(EXEEXT) + [ ! -r .libs/libhwloc.def ] || ./dolib$(EXEEXT) "$(HWLOC_MS_LIB)" $(HWLOC_MS_LIB_ARCH) .libs/libhwloc.def $(libhwloc_so_version) .libs/libhwloc.lib +all-local: .libs/libhwloc.lib +clean-local: + $(RM) dolib$(EXEEXT) +endif HWLOC_HAVE_MS_LIB + +install-exec-hook: + [ ! -r .libs/libhwloc.def ] || $(INSTALL) .libs/libhwloc.def $(DESTDIR)$(libdir) +if HWLOC_HAVE_MS_LIB + [ ! -r .libs/libhwloc.def ] || $(INSTALL) .libs/libhwloc.lib $(DESTDIR)$(libdir) + [ ! -r .libs/libhwloc.def ] || $(INSTALL) .libs/libhwloc.exp $(DESTDIR)$(libdir) +endif HWLOC_HAVE_MS_LIB + +uninstall-local: + rm -f $(DESTDIR)$(libdir)/libhwloc.def +if HWLOC_HAVE_MS_LIB + rm -f $(DESTDIR)$(libdir)/libhwloc.lib $(DESTDIR)$(libdir)/libhwloc.exp +endif HWLOC_HAVE_MS_LIB + +# End of Windows specific rules +endif HWLOC_HAVE_WINDOWS + + +# Installable library + +libhwloc_la_SOURCES = $(sources) +libhwloc_la_LDFLAGS = $(ldflags) -version-info $(libhwloc_so_version) $(HWLOC_LIBS) + +if HWLOC_HAVE_PLUGINS +AM_CPPFLAGS += $(LTDLINCL) +libhwloc_la_LDFLAGS += -export-dynamic +libhwloc_la_LIBADD = $(LIBLTDL) +endif + +# Embedded library (note the lack of a .so version number -- that +# intentionally only appears in the installable library). Also note +# the lack of _LDFLAGS -- all libs are added by the upper layer (via +# HWLOC_EMBEDDED_LIBS). + +libhwloc_embedded_la_SOURCES = $(sources) + +# XML data (only install if we're building in standalone mode) + +if HWLOC_BUILD_STANDALONE +xml_DATA = $(srcdir)/hwloc.dtd +xmldir = $(pkgdatadir) +EXTRA_DIST += hwloc.dtd +endif + +DISTCLEANFILES = static-components.h + +if HWLOC_HAVE_PLUGINS +check_LTLIBRARIES = hwloc_fake.la +hwloc_fake_la_SOURCES = topology-fake.c +hwloc_fake_la_LDFLAGS = $(plugins_ldflags) -rpath /nowhere # force libtool to build a shared-library even it's check-only +endif diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/base64.c b/opal/mca/hwloc/hwloc1110/hwloc/src/base64.c new file mode 100644 index 0000000000..7a3392fab8 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/base64.c @@ -0,0 +1,306 @@ +/* + * 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 (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] = (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/hwloc1110/hwloc/src/bind.c b/opal/mca/hwloc/hwloc1110/hwloc/src/bind.c new file mode 100644 index 0000000000..e2b5a063e4 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/bind.c @@ -0,0 +1,781 @@ +/* + * Copyright © 2009 CNRS + * Copyright © 2009-2011 inria. All rights reserved. + * Copyright © 2009-2010, 2012 Université Bordeaux + * Copyright © 2011 Cisco Systems, Inc. All rights reserved. + * See COPYING in top-level directory. + */ + +#include +#include +#include +#include +#ifdef HAVE_SYS_MMAN_H +# include +#endif +/* is only needed if we don't have posix_memalign() */ +#if defined(hwloc_getpagesize) && !defined(HAVE_POSIX_MEMALIGN) && defined(HAVE_MEMALIGN) && defined(HAVE_MALLOC_H) +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include + +/* TODO: HWLOC_GNU_SYS, HWLOC_IRIX_SYS, + * + * IRIX: see MP_MUSTRUN / _DSM_MUSTRUN, pthread_setrunon_np, /hw, procss_cpulink, numa_create + * + * We could use glibc's sched_setaffinity generically when it is available + * + * Darwin and OpenBSD don't seem to have binding facilities. + */ + +static hwloc_const_bitmap_t +hwloc_fix_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t set) +{ + hwloc_const_bitmap_t topology_set = hwloc_topology_get_topology_cpuset(topology); + hwloc_const_bitmap_t complete_set = hwloc_topology_get_complete_cpuset(topology); + + if (!topology_set) { + /* The topology is composed of several systems, the cpuset is ambiguous. */ + errno = EXDEV; + return NULL; + } + + if (hwloc_bitmap_iszero(set)) { + errno = EINVAL; + return NULL; + } + + if (!hwloc_bitmap_isincluded(set, complete_set)) { + errno = EINVAL; + return NULL; + } + + if (hwloc_bitmap_isincluded(topology_set, set)) + set = complete_set; + + return set; +} + +int +hwloc_set_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t set, int flags) +{ + set = hwloc_fix_cpubind(topology, set); + if (!set) + return -1; + + if (flags & HWLOC_CPUBIND_PROCESS) { + if (topology->binding_hooks.set_thisproc_cpubind) + return topology->binding_hooks.set_thisproc_cpubind(topology, set, flags); + } else if (flags & HWLOC_CPUBIND_THREAD) { + if (topology->binding_hooks.set_thisthread_cpubind) + return topology->binding_hooks.set_thisthread_cpubind(topology, set, flags); + } else { + if (topology->binding_hooks.set_thisproc_cpubind) + return topology->binding_hooks.set_thisproc_cpubind(topology, set, flags); + else if (topology->binding_hooks.set_thisthread_cpubind) + return topology->binding_hooks.set_thisthread_cpubind(topology, set, flags); + } + + errno = ENOSYS; + return -1; +} + +int +hwloc_get_cpubind(hwloc_topology_t topology, hwloc_bitmap_t set, int flags) +{ + if (flags & HWLOC_CPUBIND_PROCESS) { + if (topology->binding_hooks.get_thisproc_cpubind) + return topology->binding_hooks.get_thisproc_cpubind(topology, set, flags); + } else if (flags & HWLOC_CPUBIND_THREAD) { + if (topology->binding_hooks.get_thisthread_cpubind) + return topology->binding_hooks.get_thisthread_cpubind(topology, set, flags); + } else { + if (topology->binding_hooks.get_thisproc_cpubind) + return topology->binding_hooks.get_thisproc_cpubind(topology, set, flags); + else if (topology->binding_hooks.get_thisthread_cpubind) + return topology->binding_hooks.get_thisthread_cpubind(topology, set, flags); + } + + errno = ENOSYS; + return -1; +} + +int +hwloc_set_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_bitmap_t set, int flags) +{ + set = hwloc_fix_cpubind(topology, set); + if (!set) + return -1; + + if (topology->binding_hooks.set_proc_cpubind) + return topology->binding_hooks.set_proc_cpubind(topology, pid, set, flags); + + errno = ENOSYS; + return -1; +} + +int +hwloc_get_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_bitmap_t set, int flags) +{ + if (topology->binding_hooks.get_proc_cpubind) + return topology->binding_hooks.get_proc_cpubind(topology, pid, set, flags); + + errno = ENOSYS; + return -1; +} + +#ifdef hwloc_thread_t +int +hwloc_set_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t tid, hwloc_const_bitmap_t set, int flags) +{ + set = hwloc_fix_cpubind(topology, set); + if (!set) + return -1; + + if (topology->binding_hooks.set_thread_cpubind) + return topology->binding_hooks.set_thread_cpubind(topology, tid, set, flags); + + errno = ENOSYS; + return -1; +} + +int +hwloc_get_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t tid, hwloc_bitmap_t set, int flags) +{ + if (topology->binding_hooks.get_thread_cpubind) + return topology->binding_hooks.get_thread_cpubind(topology, tid, set, flags); + + errno = ENOSYS; + return -1; +} +#endif + +int +hwloc_get_last_cpu_location(hwloc_topology_t topology, hwloc_bitmap_t set, int flags) +{ + if (flags & HWLOC_CPUBIND_PROCESS) { + if (topology->binding_hooks.get_thisproc_last_cpu_location) + return topology->binding_hooks.get_thisproc_last_cpu_location(topology, set, flags); + } else if (flags & HWLOC_CPUBIND_THREAD) { + if (topology->binding_hooks.get_thisthread_last_cpu_location) + return topology->binding_hooks.get_thisthread_last_cpu_location(topology, set, flags); + } else { + if (topology->binding_hooks.get_thisproc_last_cpu_location) + return topology->binding_hooks.get_thisproc_last_cpu_location(topology, set, flags); + else if (topology->binding_hooks.get_thisthread_last_cpu_location) + return topology->binding_hooks.get_thisthread_last_cpu_location(topology, set, flags); + } + + errno = ENOSYS; + return -1; +} + +int +hwloc_get_proc_last_cpu_location(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_bitmap_t set, int flags) +{ + if (topology->binding_hooks.get_proc_last_cpu_location) + return topology->binding_hooks.get_proc_last_cpu_location(topology, pid, set, flags); + + errno = ENOSYS; + return -1; +} + +static hwloc_const_nodeset_t +hwloc_fix_membind(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset) +{ + hwloc_const_bitmap_t topology_nodeset = hwloc_topology_get_topology_nodeset(topology); + hwloc_const_bitmap_t complete_nodeset = hwloc_topology_get_complete_nodeset(topology); + + if (!hwloc_topology_get_topology_cpuset(topology)) { + /* The topology is composed of several systems, the nodeset is thus + * ambiguous. */ + errno = EXDEV; + return NULL; + } + + if (!complete_nodeset) { + /* There is no NUMA node */ + errno = ENODEV; + return NULL; + } + + if (hwloc_bitmap_iszero(nodeset)) { + errno = EINVAL; + return NULL; + } + + if (!hwloc_bitmap_isincluded(nodeset, complete_nodeset)) { + errno = EINVAL; + return NULL; + } + + if (hwloc_bitmap_isincluded(topology_nodeset, nodeset)) + return complete_nodeset; + + return nodeset; +} + +static int +hwloc_fix_membind_cpuset(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_const_cpuset_t cpuset) +{ + hwloc_const_bitmap_t topology_set = hwloc_topology_get_topology_cpuset(topology); + hwloc_const_bitmap_t complete_set = hwloc_topology_get_complete_cpuset(topology); + hwloc_const_bitmap_t complete_nodeset = hwloc_topology_get_complete_nodeset(topology); + + if (!topology_set) { + /* The topology is composed of several systems, the cpuset is thus + * ambiguous. */ + errno = EXDEV; + return -1; + } + + if (!complete_nodeset) { + /* There is no NUMA node */ + errno = ENODEV; + return -1; + } + + if (hwloc_bitmap_iszero(cpuset)) { + errno = EINVAL; + return -1; + } + + if (!hwloc_bitmap_isincluded(cpuset, complete_set)) { + errno = EINVAL; + return -1; + } + + if (hwloc_bitmap_isincluded(topology_set, cpuset)) { + hwloc_bitmap_copy(nodeset, complete_nodeset); + return 0; + } + + hwloc_cpuset_to_nodeset(topology, cpuset, nodeset); + return 0; +} + +int +hwloc_set_membind_nodeset(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) +{ + nodeset = hwloc_fix_membind(topology, nodeset); + if (!nodeset) + return -1; + + if (flags & HWLOC_MEMBIND_PROCESS) { + if (topology->binding_hooks.set_thisproc_membind) + return topology->binding_hooks.set_thisproc_membind(topology, nodeset, policy, flags); + } else if (flags & HWLOC_MEMBIND_THREAD) { + if (topology->binding_hooks.set_thisthread_membind) + return topology->binding_hooks.set_thisthread_membind(topology, nodeset, policy, flags); + } else { + if (topology->binding_hooks.set_thisproc_membind) + return topology->binding_hooks.set_thisproc_membind(topology, nodeset, policy, flags); + else if (topology->binding_hooks.set_thisthread_membind) + return topology->binding_hooks.set_thisthread_membind(topology, nodeset, policy, flags); + } + + errno = ENOSYS; + return -1; +} + +int +hwloc_set_membind(hwloc_topology_t topology, hwloc_const_cpuset_t set, hwloc_membind_policy_t policy, int flags) +{ + hwloc_nodeset_t nodeset = hwloc_bitmap_alloc(); + int ret; + + if (hwloc_fix_membind_cpuset(topology, nodeset, set)) + ret = -1; + else + ret = hwloc_set_membind_nodeset(topology, nodeset, policy, flags); + + hwloc_bitmap_free(nodeset); + return ret; +} + +int +hwloc_get_membind_nodeset(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags) +{ + if (flags & HWLOC_MEMBIND_PROCESS) { + if (topology->binding_hooks.get_thisproc_membind) + return topology->binding_hooks.get_thisproc_membind(topology, nodeset, policy, flags); + } else if (flags & HWLOC_MEMBIND_THREAD) { + if (topology->binding_hooks.get_thisthread_membind) + return topology->binding_hooks.get_thisthread_membind(topology, nodeset, policy, flags); + } else { + if (topology->binding_hooks.get_thisproc_membind) + return topology->binding_hooks.get_thisproc_membind(topology, nodeset, policy, flags); + else if (topology->binding_hooks.get_thisthread_membind) + return topology->binding_hooks.get_thisthread_membind(topology, nodeset, policy, flags); + } + + errno = ENOSYS; + return -1; +} + +int +hwloc_get_membind(hwloc_topology_t topology, hwloc_cpuset_t set, hwloc_membind_policy_t * policy, int flags) +{ + hwloc_nodeset_t nodeset; + int ret; + + nodeset = hwloc_bitmap_alloc(); + ret = hwloc_get_membind_nodeset(topology, nodeset, policy, flags); + + if (!ret) + hwloc_cpuset_from_nodeset(topology, set, nodeset); + + hwloc_bitmap_free(nodeset); + return ret; +} + +int +hwloc_set_proc_membind_nodeset(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) +{ + nodeset = hwloc_fix_membind(topology, nodeset); + if (!nodeset) + return -1; + + if (topology->binding_hooks.set_proc_membind) + return topology->binding_hooks.set_proc_membind(topology, pid, nodeset, policy, flags); + + errno = ENOSYS; + return -1; +} + + +int +hwloc_set_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_cpuset_t set, hwloc_membind_policy_t policy, int flags) +{ + hwloc_nodeset_t nodeset = hwloc_bitmap_alloc(); + int ret; + + if (hwloc_fix_membind_cpuset(topology, nodeset, set)) + ret = -1; + else + ret = hwloc_set_proc_membind_nodeset(topology, pid, nodeset, policy, flags); + + hwloc_bitmap_free(nodeset); + return ret; +} + +int +hwloc_get_proc_membind_nodeset(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags) +{ + if (topology->binding_hooks.get_proc_membind) + return topology->binding_hooks.get_proc_membind(topology, pid, nodeset, policy, flags); + + errno = ENOSYS; + return -1; +} + +int +hwloc_get_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_cpuset_t set, hwloc_membind_policy_t * policy, int flags) +{ + hwloc_nodeset_t nodeset; + int ret; + + nodeset = hwloc_bitmap_alloc(); + ret = hwloc_get_proc_membind_nodeset(topology, pid, nodeset, policy, flags); + + if (!ret) + hwloc_cpuset_from_nodeset(topology, set, nodeset); + + hwloc_bitmap_free(nodeset); + return ret; +} + +int +hwloc_set_area_membind_nodeset(hwloc_topology_t topology, const void *addr, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) +{ + nodeset = hwloc_fix_membind(topology, nodeset); + if (!nodeset) + return -1; + + if (topology->binding_hooks.set_area_membind) + return topology->binding_hooks.set_area_membind(topology, addr, len, nodeset, policy, flags); + + errno = ENOSYS; + return -1; +} + +int +hwloc_set_area_membind(hwloc_topology_t topology, const void *addr, size_t len, hwloc_const_cpuset_t set, hwloc_membind_policy_t policy, int flags) +{ + hwloc_nodeset_t nodeset = hwloc_bitmap_alloc(); + int ret; + + if (hwloc_fix_membind_cpuset(topology, nodeset, set)) + ret = -1; + else + ret = hwloc_set_area_membind_nodeset(topology, addr, len, nodeset, policy, flags); + + hwloc_bitmap_free(nodeset); + return ret; +} + +int +hwloc_get_area_membind_nodeset(hwloc_topology_t topology, const void *addr, size_t len, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags) +{ + if (topology->binding_hooks.get_area_membind) + return topology->binding_hooks.get_area_membind(topology, addr, len, nodeset, policy, flags); + + errno = ENOSYS; + return -1; +} + +int +hwloc_get_area_membind(hwloc_topology_t topology, const void *addr, size_t len, hwloc_cpuset_t set, hwloc_membind_policy_t * policy, int flags) +{ + hwloc_nodeset_t nodeset; + int ret; + + nodeset = hwloc_bitmap_alloc(); + ret = hwloc_get_area_membind_nodeset(topology, addr, len, nodeset, policy, flags); + + if (!ret) + hwloc_cpuset_from_nodeset(topology, set, nodeset); + + hwloc_bitmap_free(nodeset); + return ret; +} + +void * +hwloc_alloc_heap(hwloc_topology_t topology __hwloc_attribute_unused, size_t len) +{ + void *p; +#if defined(hwloc_getpagesize) && defined(HAVE_POSIX_MEMALIGN) + errno = posix_memalign(&p, hwloc_getpagesize(), len); + if (errno) + p = NULL; +#elif defined(hwloc_getpagesize) && defined(HAVE_MEMALIGN) + p = memalign(hwloc_getpagesize(), len); +#else + p = malloc(len); +#endif + return p; +} + +#ifdef MAP_ANONYMOUS +void * +hwloc_alloc_mmap(hwloc_topology_t topology __hwloc_attribute_unused, size_t len) +{ + return mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); +} +#endif + +int +hwloc_free_heap(hwloc_topology_t topology __hwloc_attribute_unused, void *addr, size_t len __hwloc_attribute_unused) +{ + free(addr); + return 0; +} + +#ifdef MAP_ANONYMOUS +int +hwloc_free_mmap(hwloc_topology_t topology __hwloc_attribute_unused, void *addr, size_t len) +{ + if (!addr) + return 0; + return munmap(addr, len); +} +#endif + +void * +hwloc_alloc(hwloc_topology_t topology, size_t len) +{ + if (topology->binding_hooks.alloc) + return topology->binding_hooks.alloc(topology, len); + return hwloc_alloc_heap(topology, len); +} + +void * +hwloc_alloc_membind_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) +{ + void *p; + nodeset = hwloc_fix_membind(topology, nodeset); + if (!nodeset) + goto fallback; + if (flags & HWLOC_MEMBIND_MIGRATE) { + errno = EINVAL; + goto fallback; + } + + if (topology->binding_hooks.alloc_membind) + return topology->binding_hooks.alloc_membind(topology, len, nodeset, policy, flags); + else if (topology->binding_hooks.set_area_membind) { + p = hwloc_alloc(topology, len); + if (!p) + return NULL; + if (topology->binding_hooks.set_area_membind(topology, p, len, nodeset, policy, flags) && flags & HWLOC_MEMBIND_STRICT) { + int error = errno; + free(p); + errno = error; + return NULL; + } + return p; + } else { + errno = ENOSYS; + } + +fallback: + if (flags & HWLOC_MEMBIND_STRICT) + /* Report error */ + return NULL; + /* Never mind, allocate anyway */ + return hwloc_alloc(topology, len); +} + +void * +hwloc_alloc_membind(hwloc_topology_t topology, size_t len, hwloc_const_cpuset_t set, hwloc_membind_policy_t policy, int flags) +{ + hwloc_nodeset_t nodeset = hwloc_bitmap_alloc(); + void *ret; + + if (hwloc_fix_membind_cpuset(topology, nodeset, set)) { + if (flags & HWLOC_MEMBIND_STRICT) + ret = NULL; + else + ret = hwloc_alloc(topology, len); + } else + ret = hwloc_alloc_membind_nodeset(topology, len, nodeset, policy, flags); + + hwloc_bitmap_free(nodeset); + return ret; +} + +int +hwloc_free(hwloc_topology_t topology, void *addr, size_t len) +{ + if (topology->binding_hooks.free_membind) + return topology->binding_hooks.free_membind(topology, addr, len); + return hwloc_free_heap(topology, addr, len); +} + +/* + * Empty binding hooks always returning success + */ + +static int dontset_return_complete_cpuset(hwloc_topology_t topology, hwloc_cpuset_t set) +{ + hwloc_const_cpuset_t cpuset = hwloc_topology_get_complete_cpuset(topology); + if (cpuset) { + hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology)); + return 0; + } else + return -1; +} + +static int dontset_thisthread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, int flags __hwloc_attribute_unused) +{ + return 0; +} +static int dontget_thisthread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_bitmap_t set, int flags __hwloc_attribute_unused) +{ + return dontset_return_complete_cpuset(topology, set); +} +static int dontset_thisproc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, int flags __hwloc_attribute_unused) +{ + return 0; +} +static int dontget_thisproc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_bitmap_t set, int flags __hwloc_attribute_unused) +{ + return dontset_return_complete_cpuset(topology, set); +} +static int dontset_proc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_pid_t pid __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, int flags __hwloc_attribute_unused) +{ + return 0; +} +static int dontget_proc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_pid_t pid __hwloc_attribute_unused, hwloc_bitmap_t cpuset, int flags __hwloc_attribute_unused) +{ + return dontset_return_complete_cpuset(topology, cpuset); +} +#ifdef hwloc_thread_t +static int dontset_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_thread_t tid __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, int flags __hwloc_attribute_unused) +{ + return 0; +} +static int dontget_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_thread_t tid __hwloc_attribute_unused, hwloc_bitmap_t cpuset, int flags __hwloc_attribute_unused) +{ + return dontset_return_complete_cpuset(topology, cpuset); +} +#endif + +static int dontset_return_complete_nodeset(hwloc_topology_t topology, hwloc_nodeset_t set, hwloc_membind_policy_t *policy) +{ + hwloc_const_nodeset_t nodeset = hwloc_topology_get_complete_nodeset(topology); + if (nodeset) { + hwloc_bitmap_copy(set, hwloc_topology_get_complete_nodeset(topology)); + *policy = HWLOC_MEMBIND_DEFAULT; + return 0; + } else + return -1; +} + +static int dontset_thisproc_membind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, hwloc_membind_policy_t policy __hwloc_attribute_unused, int flags __hwloc_attribute_unused) +{ + return 0; +} +static int dontget_thisproc_membind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_bitmap_t set, hwloc_membind_policy_t * policy, int flags __hwloc_attribute_unused) +{ + return dontset_return_complete_nodeset(topology, set, policy); +} + +static int dontset_thisthread_membind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, hwloc_membind_policy_t policy __hwloc_attribute_unused, int flags __hwloc_attribute_unused) +{ + return 0; +} +static int dontget_thisthread_membind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_bitmap_t set, hwloc_membind_policy_t * policy, int flags __hwloc_attribute_unused) +{ + return dontset_return_complete_nodeset(topology, set, policy); +} + +static int dontset_proc_membind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_pid_t pid __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, hwloc_membind_policy_t policy __hwloc_attribute_unused, int flags __hwloc_attribute_unused) +{ + return 0; +} +static int dontget_proc_membind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_pid_t pid __hwloc_attribute_unused, hwloc_bitmap_t set, hwloc_membind_policy_t * policy, int flags __hwloc_attribute_unused) +{ + return dontset_return_complete_nodeset(topology, set, policy); +} + +static int dontset_area_membind(hwloc_topology_t topology __hwloc_attribute_unused, const void *addr __hwloc_attribute_unused, size_t size __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, hwloc_membind_policy_t policy __hwloc_attribute_unused, int flags __hwloc_attribute_unused) +{ + return 0; +} +static int dontget_area_membind(hwloc_topology_t topology __hwloc_attribute_unused, const void *addr __hwloc_attribute_unused, size_t size __hwloc_attribute_unused, hwloc_bitmap_t set, hwloc_membind_policy_t * policy, int flags __hwloc_attribute_unused) +{ + return dontset_return_complete_nodeset(topology, set, policy); +} + +static void * dontalloc_membind(hwloc_topology_t topology __hwloc_attribute_unused, size_t size __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, hwloc_membind_policy_t policy __hwloc_attribute_unused, int flags __hwloc_attribute_unused) +{ + return malloc(size); +} +static int dontfree_membind(hwloc_topology_t topology __hwloc_attribute_unused, void *addr __hwloc_attribute_unused, size_t size __hwloc_attribute_unused) +{ + free(addr); + return 0; +} + +static void hwloc_set_dummy_hooks(struct hwloc_binding_hooks *hooks, + struct hwloc_topology_support *support __hwloc_attribute_unused) +{ + hooks->set_thisproc_cpubind = dontset_thisproc_cpubind; + hooks->get_thisproc_cpubind = dontget_thisproc_cpubind; + hooks->set_thisthread_cpubind = dontset_thisthread_cpubind; + hooks->get_thisthread_cpubind = dontget_thisthread_cpubind; + hooks->set_proc_cpubind = dontset_proc_cpubind; + hooks->get_proc_cpubind = dontget_proc_cpubind; +#ifdef hwloc_thread_t + hooks->set_thread_cpubind = dontset_thread_cpubind; + hooks->get_thread_cpubind = dontget_thread_cpubind; +#endif + hooks->get_thisproc_last_cpu_location = dontget_thisproc_cpubind; /* cpubind instead of last_cpu_location is ok */ + hooks->get_thisthread_last_cpu_location = dontget_thisthread_cpubind; /* cpubind instead of last_cpu_location is ok */ + hooks->get_proc_last_cpu_location = dontget_proc_cpubind; /* cpubind instead of last_cpu_location is ok */ + /* TODO: get_thread_last_cpu_location */ + hooks->set_thisproc_membind = dontset_thisproc_membind; + hooks->get_thisproc_membind = dontget_thisproc_membind; + hooks->set_thisthread_membind = dontset_thisthread_membind; + hooks->get_thisthread_membind = dontget_thisthread_membind; + hooks->set_proc_membind = dontset_proc_membind; + hooks->get_proc_membind = dontget_proc_membind; + hooks->set_area_membind = dontset_area_membind; + hooks->get_area_membind = dontget_area_membind; + hooks->alloc_membind = dontalloc_membind; + hooks->free_membind = dontfree_membind; +} + +void +hwloc_set_native_binding_hooks(struct hwloc_binding_hooks *hooks, struct hwloc_topology_support *support) +{ +# ifdef HWLOC_LINUX_SYS + hwloc_set_linuxfs_hooks(hooks, support); +# endif /* HWLOC_LINUX_SYS */ + +# ifdef HWLOC_BGQ_SYS + hwloc_set_bgq_hooks(hooks, support); +# endif /* HWLOC_BGQ_SYS */ + +# ifdef HWLOC_AIX_SYS + hwloc_set_aix_hooks(hooks, support); +# endif /* HWLOC_AIX_SYS */ + +# ifdef HWLOC_OSF_SYS + hwloc_set_osf_hooks(hooks, support); +# endif /* HWLOC_OSF_SYS */ + +# ifdef HWLOC_SOLARIS_SYS + hwloc_set_solaris_hooks(hooks, support); +# endif /* HWLOC_SOLARIS_SYS */ + +# ifdef HWLOC_WIN_SYS + hwloc_set_windows_hooks(hooks, support); +# endif /* HWLOC_WIN_SYS */ + +# ifdef HWLOC_DARWIN_SYS + hwloc_set_darwin_hooks(hooks, support); +# endif /* HWLOC_DARWIN_SYS */ + +# ifdef HWLOC_FREEBSD_SYS + hwloc_set_freebsd_hooks(hooks, support); +# endif /* HWLOC_FREEBSD_SYS */ + +# ifdef HWLOC_NETBSD_SYS + hwloc_set_netbsd_hooks(hooks, support); +# endif /* HWLOC_NETBSD_SYS */ + +# ifdef HWLOC_HPUX_SYS + hwloc_set_hpux_hooks(hooks, support); +# endif /* HWLOC_HPUX_SYS */ +} + +/* If the represented system is actually not this system, use dummy binding hooks. */ +void +hwloc_set_binding_hooks(struct hwloc_topology *topology) +{ + if (topology->is_thissystem) { + hwloc_set_native_binding_hooks(&topology->binding_hooks, &topology->support); + /* every hook not set above will return ENOSYS */ + } else { + /* not this system, use dummy binding hooks that do nothing (but don't return ENOSYS) */ + hwloc_set_dummy_hooks(&topology->binding_hooks, &topology->support); + } + + /* if not is_thissystem, set_cpubind is fake + * and get_cpubind returns the whole system cpuset, + * so don't report that set/get_cpubind as supported + */ + if (topology->is_thissystem) { +#define DO(which,kind) \ + if (topology->binding_hooks.kind) \ + topology->support.which##bind->kind = 1; + DO(cpu,set_thisproc_cpubind); + DO(cpu,get_thisproc_cpubind); + DO(cpu,set_proc_cpubind); + DO(cpu,get_proc_cpubind); + DO(cpu,set_thisthread_cpubind); + DO(cpu,get_thisthread_cpubind); +#ifdef hwloc_thread_t + DO(cpu,set_thread_cpubind); + DO(cpu,get_thread_cpubind); +#endif + DO(cpu,get_thisproc_last_cpu_location); + DO(cpu,get_proc_last_cpu_location); + DO(cpu,get_thisthread_last_cpu_location); + DO(mem,set_thisproc_membind); + DO(mem,get_thisproc_membind); + DO(mem,set_thisthread_membind); + DO(mem,get_thisthread_membind); + DO(mem,set_proc_membind); + DO(mem,get_proc_membind); + DO(mem,set_area_membind); + DO(mem,get_area_membind); + DO(mem,alloc_membind); + } +} diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/bitmap.c b/opal/mca/hwloc/hwloc1110/hwloc/src/bitmap.c new file mode 100644 index 0000000000..1e78a96bf3 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/bitmap.c @@ -0,0 +1,1485 @@ +/* + * 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 ? 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 ? 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 ? 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 ? 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 ? 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 = 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 == -1) { + set->infinite = 1; + /* keep endcpu == -1 since this unsigned is actually larger than anything else */ + } + + if (set->infinite) { + /* truncate the range according to the infinite part of the bitmap */ + if (endcpu >= set->ulongs_count * HWLOC_BITS_PER_LONG) + endcpu = set->ulongs_count * HWLOC_BITS_PER_LONG - 1; + if (begincpu >= set->ulongs_count * HWLOC_BITS_PER_LONG) + return; + } + if (endcpu < begincpu) + return; + hwloc_bitmap_realloc_by_cpu_index(set, endcpu); + + beginset = HWLOC_SUBBITMAP_INDEX(begincpu); + endset = HWLOC_SUBBITMAP_INDEX(endcpu); + for(i=beginset+1; iulongs[i] = HWLOC_SUBBITMAP_FULL; + 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)); + } +} + +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 == -1) { + set->infinite = 0; + /* keep endcpu == -1 since this unsigned is actually larger than anything else */ + } + + if (!set->infinite) { + /* truncate the range according to the infinitely-unset part of the bitmap */ + if (endcpu >= set->ulongs_count * HWLOC_BITS_PER_LONG) + endcpu = set->ulongs_count * HWLOC_BITS_PER_LONG - 1; + if (begincpu >= set->ulongs_count * HWLOC_BITS_PER_LONG) + return; + } + if (endcpu < begincpu) + return; + hwloc_bitmap_realloc_by_cpu_index(set, endcpu); + + beginset = HWLOC_SUBBITMAP_INDEX(begincpu); + endset = HWLOC_SUBBITMAP_INDEX(endcpu); + for(i=beginset+1; iulongs[i] = HWLOC_SUBBITMAP_ZERO; + 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)); + } +} + +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/hwloc1110/hwloc/src/components.c b/opal/mca/hwloc/hwloc1110/hwloc/src/components.c new file mode 100644 index 0000000000..dc656e3985 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/components.c @@ -0,0 +1,811 @@ +/* + * Copyright © 2009-2015 Inria. All rights reserved. + * Copyright © 2012 Université Bordeau 1 + * See COPYING in top-level directory. + */ + +#include +#include +#include +#include + +#define HWLOC_COMPONENT_STOP_NAME "stop" +#define HWLOC_COMPONENT_EXCLUDE_CHAR '-' +#define HWLOC_COMPONENT_SEPS "," + +/* list of all registered discovery components, sorted by priority, higher priority first. + * noos is last because its priority is 0. + * others' priority is 10. + */ +static struct hwloc_disc_component * hwloc_disc_components = NULL; + +static unsigned hwloc_components_users = 0; /* first one initializes, last ones destroys */ + +static int hwloc_components_verbose = 0; +#ifdef HWLOC_HAVE_PLUGINS +static int hwloc_plugins_verbose = 0; +#endif + +/* hwloc_components_mutex serializes: + * - loading/unloading plugins, and modifications of the hwloc_plugins list + * - calls to ltdl, including in hwloc_check_plugin_namespace() + * - registration of components with hwloc_disc_component_register() + * and hwloc_xml_callbacks_register() + */ +#ifdef HWLOC_WIN_SYS +/* Basic mutex on top of InterlockedCompareExchange() on windows, + * Far from perfect, but easy to maintain, and way enough given that this code will never be needed for real. */ +#include +static LONG hwloc_components_mutex = 0; +#define HWLOC_COMPONENTS_LOCK() do { \ + while (InterlockedCompareExchange(&hwloc_components_mutex, 1, 0) != 0) \ + SwitchToThread(); \ +} while (0) +#define HWLOC_COMPONENTS_UNLOCK() do { \ + assert(hwloc_components_mutex == 1); \ + hwloc_components_mutex = 0; \ +} while (0) + +#elif defined HWLOC_HAVE_PTHREAD_MUTEX +/* pthread mutex if available (except on windows) */ +#include +static pthread_mutex_t hwloc_components_mutex = PTHREAD_MUTEX_INITIALIZER; +#define HWLOC_COMPONENTS_LOCK() pthread_mutex_lock(&hwloc_components_mutex) +#define HWLOC_COMPONENTS_UNLOCK() pthread_mutex_unlock(&hwloc_components_mutex) + +#else /* HWLOC_WIN_SYS || HWLOC_HAVE_PTHREAD_MUTEX */ +#error No mutex implementation available +#endif + + +#ifdef HWLOC_HAVE_PLUGINS + +#include + +/* array of pointers to dynamically loaded plugins */ +static struct hwloc__plugin_desc { + char *name; + struct hwloc_component *component; + char *filename; + lt_dlhandle handle; + struct hwloc__plugin_desc *next; +} *hwloc_plugins = NULL; + +static int +hwloc__dlforeach_cb(const char *filename, void *_data __hwloc_attribute_unused) +{ + const char *basename; + lt_dlhandle handle; + char *componentsymbolname = NULL; + struct hwloc_component *component; + struct hwloc__plugin_desc *desc, **prevdesc; + + if (hwloc_plugins_verbose) + fprintf(stderr, "Plugin dlforeach found `%s'\n", filename); + + basename = strrchr(filename, '/'); + if (!basename) + basename = filename; + else + basename++; + + /* dlopen and get the component structure */ + handle = lt_dlopenext(filename); + if (!handle) { + if (hwloc_plugins_verbose) + fprintf(stderr, "Failed to load plugin: %s\n", lt_dlerror()); + goto out; + } + componentsymbolname = malloc(strlen(basename)+10+1); + sprintf(componentsymbolname, "%s_component", basename); + component = lt_dlsym(handle, componentsymbolname); + if (!component) { + if (hwloc_plugins_verbose) + fprintf(stderr, "Failed to find component symbol `%s'\n", + componentsymbolname); + goto out_with_handle; + } + if (component->abi != HWLOC_COMPONENT_ABI) { + if (hwloc_plugins_verbose) + fprintf(stderr, "Plugin symbol ABI %u instead of %u\n", + component->abi, HWLOC_COMPONENT_ABI); + goto out_with_handle; + } + if (hwloc_plugins_verbose) + fprintf(stderr, "Plugin contains expected symbol `%s'\n", + componentsymbolname); + free(componentsymbolname); + componentsymbolname = NULL; + + if (HWLOC_COMPONENT_TYPE_DISC == component->type) { + if (strncmp(basename, "hwloc_", 6)) { + if (hwloc_plugins_verbose) + fprintf(stderr, "Plugin name `%s' doesn't match its type DISCOVERY\n", basename); + goto out_with_handle; + } + } else if (HWLOC_COMPONENT_TYPE_XML == component->type) { + if (strncmp(basename, "hwloc_xml_", 10)) { + if (hwloc_plugins_verbose) + fprintf(stderr, "Plugin name `%s' doesn't match its type XML\n", basename); + goto out_with_handle; + } + } else { + if (hwloc_plugins_verbose) + fprintf(stderr, "Plugin name `%s' has invalid type %u\n", + basename, (unsigned) component->type); + goto out_with_handle; + } + + /* allocate a plugin_desc and queue it */ + desc = malloc(sizeof(*desc)); + if (!desc) + goto out_with_handle; + desc->name = strdup(basename); + desc->filename = strdup(filename); + desc->component = component; + desc->handle = handle; + desc->next = NULL; + if (hwloc_plugins_verbose) + fprintf(stderr, "Plugin descriptor `%s' ready\n", basename); + + /* append to the list */ + prevdesc = &hwloc_plugins; + while (*prevdesc) + prevdesc = &((*prevdesc)->next); + *prevdesc = desc; + if (hwloc_plugins_verbose) + fprintf(stderr, "Plugin descriptor `%s' queued\n", basename); + return 0; + + out_with_handle: + lt_dlclose(handle); + free(componentsymbolname); /* NULL if already freed */ + out: + return 0; +} + +static void +hwloc_plugins_exit(void) +{ + struct hwloc__plugin_desc *desc, *next; + + if (hwloc_plugins_verbose) + fprintf(stderr, "Closing all plugins\n"); + + desc = hwloc_plugins; + while (desc) { + next = desc->next; + lt_dlclose(desc->handle); + free(desc->name); + free(desc->filename); + free(desc); + desc = next; + } + hwloc_plugins = NULL; + + lt_dlexit(); +} + +static int +hwloc_plugins_init(void) +{ + const char *verboseenv; + char *path = HWLOC_PLUGINS_PATH; + const char *env; + int err; + + verboseenv = getenv("HWLOC_PLUGINS_VERBOSE"); + hwloc_plugins_verbose = verboseenv ? atoi(verboseenv) : 0; + + err = lt_dlinit(); + if (err) + goto out; + + env = getenv("HWLOC_PLUGINS_PATH"); + if (env) + path = env; + + hwloc_plugins = NULL; + + if (hwloc_plugins_verbose) + fprintf(stderr, "Starting plugin dlforeach in %s\n", path); + err = lt_dlforeachfile(path, hwloc__dlforeach_cb, NULL); + if (err) + goto out_with_init; + + return 0; + + out_with_init: + hwloc_plugins_exit(); + out: + return -1; +} + +#endif /* HWLOC_HAVE_PLUGINS */ + +static const char * +hwloc_disc_component_type_string(hwloc_disc_component_type_t type) +{ + switch (type) { + case HWLOC_DISC_COMPONENT_TYPE_CPU: return "cpu"; + case HWLOC_DISC_COMPONENT_TYPE_GLOBAL: return "global"; + case HWLOC_DISC_COMPONENT_TYPE_MISC: return "misc"; + default: return "**unknown**"; + } +} + +static int +hwloc_disc_component_register(struct hwloc_disc_component *component, + const char *filename) +{ + struct hwloc_disc_component **prev; + + /* check that the component name is valid */ + if (!strcmp(component->name, HWLOC_COMPONENT_STOP_NAME)) { + if (hwloc_components_verbose) + fprintf(stderr, "Cannot register discovery component with reserved name `" HWLOC_COMPONENT_STOP_NAME "'\n"); + return -1; + } + if (strchr(component->name, HWLOC_COMPONENT_EXCLUDE_CHAR) + || strcspn(component->name, HWLOC_COMPONENT_SEPS) != strlen(component->name)) { + if (hwloc_components_verbose) + fprintf(stderr, "Cannot register discovery component with name `%s' containing reserved characters `%c" HWLOC_COMPONENT_SEPS "'\n", + component->name, HWLOC_COMPONENT_EXCLUDE_CHAR); + return -1; + } + /* check that the component type is valid */ + switch ((unsigned) component->type) { + case HWLOC_DISC_COMPONENT_TYPE_CPU: + case HWLOC_DISC_COMPONENT_TYPE_GLOBAL: + case HWLOC_DISC_COMPONENT_TYPE_MISC: + break; + default: + fprintf(stderr, "Cannot register discovery component `%s' with unknown type %u\n", + component->name, (unsigned) component->type); + return -1; + } + + prev = &hwloc_disc_components; + while (NULL != *prev) { + if (!strcmp((*prev)->name, component->name)) { + /* if two components have the same name, only keep the highest priority one */ + if ((*prev)->priority < component->priority) { + /* drop the existing component */ + if (hwloc_components_verbose) + fprintf(stderr, "Dropping previously registered discovery component `%s', priority %u lower than new one %u\n", + (*prev)->name, (*prev)->priority, component->priority); + *prev = (*prev)->next; + } else { + /* drop the new one */ + if (hwloc_components_verbose) + fprintf(stderr, "Ignoring new discovery component `%s', priority %u lower than previously registered one %u\n", + component->name, component->priority, (*prev)->priority); + return -1; + } + } + prev = &((*prev)->next); + } + if (hwloc_components_verbose) + fprintf(stderr, "Registered %s discovery component `%s' with priority %u (%s%s)\n", + hwloc_disc_component_type_string(component->type), component->name, component->priority, + filename ? "from plugin " : "statically build", filename ? filename : ""); + + prev = &hwloc_disc_components; + while (NULL != *prev) { + if ((*prev)->priority < component->priority) + break; + prev = &((*prev)->next); + } + component->next = *prev; + *prev = component; + return 0; +} + +#include + +static void (**hwloc_component_finalize_cbs)(unsigned long); +static unsigned hwloc_component_finalize_cb_count; + +void +hwloc_components_init(struct hwloc_topology *topology __hwloc_attribute_unused) +{ +#ifdef HWLOC_HAVE_PLUGINS + struct hwloc__plugin_desc *desc; +#endif + const char *verboseenv; + unsigned i; + + HWLOC_COMPONENTS_LOCK(); + assert((unsigned) -1 != hwloc_components_users); + if (0 != hwloc_components_users++) { + HWLOC_COMPONENTS_UNLOCK(); + goto ok; + } + + verboseenv = getenv("HWLOC_COMPONENTS_VERBOSE"); + hwloc_components_verbose = verboseenv ? atoi(verboseenv) : 0; + +#ifdef HWLOC_HAVE_PLUGINS + hwloc_plugins_init(); +#endif + + hwloc_component_finalize_cbs = NULL; + hwloc_component_finalize_cb_count = 0; + /* count the max number of finalize callbacks */ + for(i=0; NULL != hwloc_static_components[i]; i++) + hwloc_component_finalize_cb_count++; +#ifdef HWLOC_HAVE_PLUGINS + for(desc = hwloc_plugins; NULL != desc; desc = desc->next) + hwloc_component_finalize_cb_count++; +#endif + if (hwloc_component_finalize_cb_count) { + hwloc_component_finalize_cbs = calloc(hwloc_component_finalize_cb_count, + sizeof(*hwloc_component_finalize_cbs)); + assert(hwloc_component_finalize_cbs); + /* forget that max number and recompute the real one below */ + hwloc_component_finalize_cb_count = 0; + } + + /* hwloc_static_components is created by configure in static-components.h */ + for(i=0; NULL != hwloc_static_components[i]; i++) { + if (hwloc_static_components[i]->flags) { + fprintf(stderr, "Ignoring static component with invalid flags %lx\n", + hwloc_static_components[i]->flags); + continue; + } + + /* initialize the component */ + if (hwloc_static_components[i]->init && hwloc_static_components[i]->init(0) < 0) { + if (hwloc_components_verbose) + fprintf(stderr, "Ignoring static component, failed to initialize\n"); + continue; + } + /* queue ->finalize() callback if any */ + if (hwloc_static_components[i]->finalize) + hwloc_component_finalize_cbs[hwloc_component_finalize_cb_count++] = hwloc_static_components[i]->finalize; + + /* register for real now */ + if (HWLOC_COMPONENT_TYPE_DISC == hwloc_static_components[i]->type) + hwloc_disc_component_register(hwloc_static_components[i]->data, NULL); + else if (HWLOC_COMPONENT_TYPE_XML == hwloc_static_components[i]->type) + hwloc_xml_callbacks_register(hwloc_static_components[i]->data); + else + assert(0); + } + + /* dynamic plugins */ +#ifdef HWLOC_HAVE_PLUGINS + for(desc = hwloc_plugins; NULL != desc; desc = desc->next) { + if (desc->component->flags) { + fprintf(stderr, "Ignoring plugin `%s' component with invalid flags %lx\n", + desc->name, desc->component->flags); + continue; + } + + /* initialize the component */ + if (desc->component->init && desc->component->init(0) < 0) { + if (hwloc_components_verbose) + fprintf(stderr, "Ignoring plugin `%s', failed to initialize\n", desc->name); + continue; + } + /* queue ->finalize() callback if any */ + if (desc->component->finalize) + hwloc_component_finalize_cbs[hwloc_component_finalize_cb_count++] = desc->component->finalize; + + /* register for real now */ + if (HWLOC_COMPONENT_TYPE_DISC == desc->component->type) + hwloc_disc_component_register(desc->component->data, desc->filename); + else if (HWLOC_COMPONENT_TYPE_XML == desc->component->type) + hwloc_xml_callbacks_register(desc->component->data); + else + assert(0); + } +#endif + + HWLOC_COMPONENTS_UNLOCK(); + + ok: + topology->backends = NULL; +} + +static struct hwloc_disc_component * +hwloc_disc_component_find(int type /* hwloc_disc_component_type_t or -1 if any */, + const char *name /* name of NULL if any */) +{ + struct hwloc_disc_component *comp = hwloc_disc_components; + while (NULL != comp) { + if ((-1 == type || type == (int) comp->type) + && (NULL == name || !strcmp(name, comp->name))) + return comp; + comp = comp->next; + } + return NULL; +} + +/* used by set_xml(), set_synthetic(), ... environment variables, ... to force the first backend */ +int +hwloc_disc_component_force_enable(struct hwloc_topology *topology, + int envvar_forced, + int type, const char *name, + const void *data1, const void *data2, const void *data3) +{ + struct hwloc_disc_component *comp; + struct hwloc_backend *backend; + + if (topology->is_loaded) { + errno = EBUSY; + return -1; + } + + comp = hwloc_disc_component_find(type, name); + if (!comp) { + errno = ENOSYS; + return -1; + } + + backend = comp->instantiate(comp, data1, data2, data3); + if (backend) { + backend->envvar_forced = envvar_forced; + if (topology->backends) + hwloc_backends_disable_all(topology); + return hwloc_backend_enable(topology, backend); + } else + return -1; +} + +static int +hwloc_disc_component_try_enable(struct hwloc_topology *topology, + struct hwloc_disc_component *comp, + const char *comparg, + unsigned *excludes, + int envvar_forced, + int verbose_errors) +{ + struct hwloc_backend *backend; + int err; + + if ((*excludes) & comp->type) { + if (hwloc_components_verbose || verbose_errors) + fprintf(stderr, "Excluding %s discovery component `%s', conflicts with excludes 0x%x\n", + hwloc_disc_component_type_string(comp->type), comp->name, *excludes); + return -1; + } + + backend = comp->instantiate(comp, comparg, NULL, NULL); + if (!backend) { + if (hwloc_components_verbose || verbose_errors) + fprintf(stderr, "Failed to instantiate discovery component `%s'\n", comp->name); + return -1; + } + + backend->envvar_forced = envvar_forced; + err = hwloc_backend_enable(topology, backend); + if (err < 0) + return -1; + + *excludes |= comp->excludes; + + return 0; +} + +void +hwloc_disc_components_enable_others(struct hwloc_topology *topology) +{ + struct hwloc_disc_component *comp; + struct hwloc_backend *backend; + unsigned excludes = 0; + int tryall = 1; + const char *_env; + char *env; /* we'll to modify the env value, so duplicate it */ + + _env = getenv("HWLOC_COMPONENTS"); + env = _env ? strdup(_env) : NULL; + + /* compute current excludes */ + backend = topology->backends; + while (backend) { + excludes |= backend->component->excludes; + backend = backend->next; + } + + /* enable explicitly listed components */ + if (env) { + char *curenv = env; + size_t s; + + while (*curenv) { + s = strcspn(curenv, HWLOC_COMPONENT_SEPS); + if (s) { + char *arg; + char c, d; + + /* replace libpci with pci for backward compatibility with v1.6 */ + if (!strncmp(curenv, "libpci", s)) { + curenv[0] = curenv[1] = curenv[2] = *HWLOC_COMPONENT_SEPS; + curenv += 3; + s -= 3; + } else if (curenv[0] == HWLOC_COMPONENT_EXCLUDE_CHAR && !strncmp(curenv+1, "libpci", s-1)) { + curenv[3] = curenv[0]; + curenv[0] = curenv[1] = curenv[2] = *HWLOC_COMPONENT_SEPS; + curenv += 3; + s -= 3; + /* skip this name, it's a negated one */ + goto nextname; + } + + if (curenv[0] == HWLOC_COMPONENT_EXCLUDE_CHAR) + goto nextname; + + if (!strncmp(curenv, HWLOC_COMPONENT_STOP_NAME, s)) { + tryall = 0; + break; + } + + /* save the last char and replace with \0 */ + c = curenv[s]; + curenv[s] = '\0'; + + arg = strchr(curenv, '='); + if (arg) { + d = *arg; + *arg = '\0'; + } + + comp = hwloc_disc_component_find(-1, curenv); + if (comp) { + hwloc_disc_component_try_enable(topology, comp, arg ? arg+1 : NULL, &excludes, 1 /* envvar forced */, 1 /* envvar forced need warnings */); + } else { + fprintf(stderr, "Cannot find discovery component `%s'\n", curenv); + } + + /* restore chars (the second loop below needs env to be unmodified) */ + curenv[s] = c; + if (arg) + *arg = d; + } + +nextname: + curenv += s; + if (*curenv) + /* Skip comma */ + curenv++; + } + } + + /* env is still the same, the above loop didn't modify it */ + + /* now enable remaining components (except the explicitly '-'-listed ones) */ + if (tryall) { + comp = hwloc_disc_components; + while (NULL != comp) { + /* check if this component was explicitly excluded in env */ + if (env) { + char *curenv = env; + while (*curenv) { + size_t s = strcspn(curenv, HWLOC_COMPONENT_SEPS); + if (curenv[0] == HWLOC_COMPONENT_EXCLUDE_CHAR && !strncmp(curenv+1, comp->name, s-1)) { + if (hwloc_components_verbose) + fprintf(stderr, "Excluding %s discovery component `%s' because of HWLOC_COMPONENTS environment variable\n", + hwloc_disc_component_type_string(comp->type), comp->name); + goto nextcomp; + } + curenv += s; + if (*curenv) + /* Skip comma */ + curenv++; + } + } + hwloc_disc_component_try_enable(topology, comp, NULL, &excludes, 0 /* defaults, not envvar forced */, 0 /* defaults don't need warnings on conflicts */); +nextcomp: + comp = comp->next; + } + } + + if (hwloc_components_verbose) { + /* print a summary */ + int first = 1; + backend = topology->backends; + fprintf(stderr, "Final list of enabled discovery components: "); + while (backend != NULL) { + fprintf(stderr, "%s%s", first ? "" : ",", backend->component->name); + backend = backend->next; + first = 0; + } + fprintf(stderr, "\n"); + } + + if (env) + free(env); +} + +void +hwloc_components_destroy_all(struct hwloc_topology *topology __hwloc_attribute_unused) +{ + unsigned i; + + HWLOC_COMPONENTS_LOCK(); + assert(0 != hwloc_components_users); + if (0 != --hwloc_components_users) { + HWLOC_COMPONENTS_UNLOCK(); + return; + } + + for(i=0; icomponent = component; + backend->flags = 0; + backend->discover = NULL; + backend->get_obj_cpuset = NULL; + backend->notify_new_object = NULL; + backend->disable = NULL; + backend->is_custom = 0; + backend->is_thissystem = -1; + backend->next = NULL; + backend->envvar_forced = 0; + return backend; +} + +static void +hwloc_backend_disable(struct hwloc_backend *backend) +{ + if (backend->disable) + backend->disable(backend); + free(backend); +} + +int +hwloc_backend_enable(struct hwloc_topology *topology, struct hwloc_backend *backend) +{ + struct hwloc_backend **pprev; + + /* check backend flags */ + if (backend->flags & (~(HWLOC_BACKEND_FLAG_NEED_LEVELS))) { + fprintf(stderr, "Cannot enable %s discovery component `%s' with unknown flags %lx\n", + hwloc_disc_component_type_string(backend->component->type), backend->component->name, backend->flags); + return -1; + } + + /* make sure we didn't already enable this backend, we don't want duplicates */ + pprev = &topology->backends; + while (NULL != *pprev) { + if ((*pprev)->component == backend->component) { + if (hwloc_components_verbose) + fprintf(stderr, "Cannot enable %s discovery component `%s' twice\n", + hwloc_disc_component_type_string(backend->component->type), backend->component->name); + hwloc_backend_disable(backend); + errno = EBUSY; + return -1; + } + pprev = &((*pprev)->next); + } + + if (hwloc_components_verbose) + fprintf(stderr, "Enabling %s discovery component `%s'\n", + hwloc_disc_component_type_string(backend->component->type), backend->component->name); + + /* enqueue at the end */ + pprev = &topology->backends; + while (NULL != *pprev) + pprev = &((*pprev)->next); + backend->next = *pprev; + *pprev = backend; + + backend->topology = topology; + + return 0; +} + +void +hwloc_backends_is_thissystem(struct hwloc_topology *topology) +{ + struct hwloc_backend *backend; + const char *local_env; + + /* Apply is_thissystem topology flag before we enforce envvar backends. + * If the application changed the backend with set_foo(), + * it may use set_flags() update the is_thissystem flag here. + * If it changes the backend with environment variables below, + * it may use HWLOC_THISSYSTEM envvar below as well. + */ + + topology->is_thissystem = 1; + + /* apply thissystem from normally-given backends (envvar_forced=0, either set_foo() or defaults) */ + backend = topology->backends; + while (backend != NULL) { + if (backend->envvar_forced == 0 && backend->is_thissystem != -1) { + assert(backend->is_thissystem == 0); + topology->is_thissystem = 0; + } + backend = backend->next; + } + + /* override set_foo() with flags */ + if (topology->flags & HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM) + topology->is_thissystem = 1; + + /* now apply envvar-forced backend (envvar_forced=1) */ + backend = topology->backends; + while (backend != NULL) { + if (backend->envvar_forced == 1 && backend->is_thissystem != -1) { + assert(backend->is_thissystem == 0); + topology->is_thissystem = 0; + } + backend = backend->next; + } + + /* override with envvar-given flag */ + local_env = getenv("HWLOC_THISSYSTEM"); + if (local_env) + topology->is_thissystem = atoi(local_env); +} + +int +hwloc_backends_get_obj_cpuset(struct hwloc_backend *caller, struct hwloc_obj *obj, hwloc_bitmap_t cpuset) +{ + struct hwloc_topology *topology = caller->topology; + struct hwloc_backend *backend = topology->backends; + /* use the first backend's get_obj_cpuset callback */ + while (backend != NULL) { + if (backend->get_obj_cpuset) + return backend->get_obj_cpuset(backend, caller, obj, cpuset); + backend = backend->next; + } + return -1; +} + +int +hwloc_backends_notify_new_object(struct hwloc_backend *caller, struct hwloc_obj *obj) +{ + struct hwloc_backend *backend; + int res = 0; + + backend = caller->topology->backends; + while (NULL != backend) { + if (backend != caller && backend->notify_new_object) + res += backend->notify_new_object(backend, caller, obj); + backend = backend->next; + } + + return res; +} + +void +hwloc_backends_disable_all(struct hwloc_topology *topology) +{ + struct hwloc_backend *backend; + + while (NULL != (backend = topology->backends)) { + struct hwloc_backend *next = backend->next; + if (hwloc_components_verbose) + fprintf(stderr, "Disabling %s discovery component `%s'\n", + hwloc_disc_component_type_string(backend->component->type), backend->component->name); + hwloc_backend_disable(backend); + topology->backends = next; + } + topology->backends = NULL; +} diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/diff.c b/opal/mca/hwloc/hwloc1110/hwloc/src/diff.c new file mode 100644 index 0000000000..060aa93f55 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/diff.c @@ -0,0 +1,408 @@ +/* + * 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/hwloc1110/hwloc/src/distances.c b/opal/mca/hwloc/hwloc1110/hwloc/src/distances.c new file mode 100644 index 0000000000..5288680368 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/distances.c @@ -0,0 +1,1040 @@ +/* + * Copyright © 2010-2015 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 + +/************************** + * 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; + + /* 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) +{ + unsigned i, j, li, lj, minl; + float min = FLT_MAX, max = FLT_MIN; + hwloc_obj_t root; + float *matrix; + hwloc_cpuset_t cpuset, complete_cpuset; + hwloc_nodeset_t nodeset, complete_nodeset; + unsigned relative_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); + if (root->depth >= objs[0]->depth) { + /* strange topology led us to find invalid relative depth, ignore */ + return; + } + relative_depth = objs[0]->depth - root->depth; /* this assume that we have distances between objects of the same level */ + + if (nbobjs != hwloc_get_nbobjs_inside_cpuset_by_depth(topology, root->cpuset, root->depth + relative_depth)) + /* 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 */ + idx = root->distances_count++; + root->distances = realloc(root->distances, root->distances_count * sizeof(struct hwloc_distances_s *)); + root->distances[idx] = malloc(sizeof(struct hwloc_distances_s)); + root->distances[idx]->relative_depth = relative_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/hwloc1110/hwloc/src/dolib.c b/opal/mca/hwloc/hwloc1110/hwloc/src/dolib.c new file mode 100644 index 0000000000..0b2835a5da --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/dolib.c @@ -0,0 +1,47 @@ +/* + * Copyright © 2009 CNRS + * Copyright © 2009 inria. All rights reserved. + * Copyright © 2009, 2012 Université Bordeaux + * See COPYING in top-level directory. + */ + +/* Wrapper to avoid msys' tendency to turn / into \ and : into ; */ + +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include + +int main(int argc, char *argv[]) { + char *prog, *arch, *def, *version, *lib; + char s[1024]; + char name[16]; + int current, age, revision; + + if (argc != 6) { + fprintf(stderr,"bad number of arguments"); + exit(EXIT_FAILURE); + } + + prog = argv[1]; + arch = argv[2]; + def = argv[3]; + version = argv[4]; + lib = argv[5]; + + if (sscanf(version, "%d:%d:%d", ¤t, &revision, &age) != 3) + exit(EXIT_FAILURE); + + _snprintf(name, sizeof(name), "libhwloc-%d", current - age); + printf("using soname %s\n", name); + + _snprintf(s, sizeof(s), "\"%s\" /machine:%s /def:%s /name:%s /out:%s", + prog, arch, def, name, lib); + if (system(s)) { + fprintf(stderr, "%s failed\n", s); + exit(EXIT_FAILURE); + } + + exit(EXIT_SUCCESS); +} diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/hwloc.dtd b/opal/mca/hwloc/hwloc1110/hwloc/src/hwloc.dtd new file mode 100644 index 0000000000..5e494f80a8 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/hwloc.dtd @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/misc.c b/opal/mca/hwloc/hwloc1110/hwloc/src/misc.c new file mode 100644 index 0000000000..3da6687d4e --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/misc.c @@ -0,0 +1,166 @@ +/* + * Copyright © 2009 CNRS + * Copyright © 2009-2014 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 +#ifdef HAVE_SYS_UTSNAME_H +#include +#endif +#include +#include +#include +#include +#include + +#ifdef HAVE_PROGRAM_INVOCATION_NAME +#include +extern char *program_invocation_name; +#endif +#ifdef HAVE___PROGNAME +extern char *__progname; +#endif + +int hwloc_snprintf(char *str, size_t size, const char *format, ...) +{ + int ret; + va_list ap; + static char bin; + size_t fakesize; + char *fakestr; + + /* Some systems crash on str == NULL */ + if (!size) { + str = &bin; + size = 1; + } + + va_start(ap, format); + ret = vsnprintf(str, size, format, ap); + va_end(ap); + + if (ret >= 0 && (size_t) ret != size-1) + return ret; + + /* vsnprintf returned size-1 or -1. That could be a system which reports the + * written data and not the actually required room. Try increasing buffer + * size to get the latter. */ + + fakesize = size; + fakestr = NULL; + do { + fakesize *= 2; + free(fakestr); + fakestr = malloc(fakesize); + if (NULL == fakestr) + return -1; + va_start(ap, format); + errno = 0; + ret = vsnprintf(fakestr, fakesize, format, ap); + va_end(ap); + } while ((size_t) ret == fakesize-1 || (ret < 0 && (!errno || errno == ERANGE))); + + if (ret >= 0 && size) { + if (size > (size_t) ret+1) + size = ret+1; + memcpy(str, fakestr, size-1); + str[size-1] = 0; + } + free(fakestr); + + return ret; +} + +int hwloc_namecoloncmp(const char *haystack, const char *needle, size_t n) +{ + size_t i = 0; + while (*haystack && *haystack != ':') { + int ha = *haystack++; + int low_h = tolower(ha); + int ne = *needle++; + int low_n = tolower(ne); + if (low_h != low_n) + return 1; + i++; + } + return i < n; +} + +void hwloc_add_uname_info(struct hwloc_topology *topology __hwloc_attribute_unused, + void *cached_uname __hwloc_attribute_unused) +{ +#ifdef HAVE_UNAME + struct utsname _utsname, *utsname; + + if (hwloc_obj_get_info_by_name(topology->levels[0][0], "OSName")) + /* don't annotate twice */ + return; + + if (cached_uname) + utsname = (struct utsname *) cached_uname; + else { + utsname = &_utsname; + if (uname(utsname) < 0) + return; + } + + if (*utsname->sysname) + hwloc_obj_add_info(topology->levels[0][0], "OSName", utsname->sysname); + if (*utsname->release) + hwloc_obj_add_info(topology->levels[0][0], "OSRelease", utsname->release); + if (*utsname->version) + hwloc_obj_add_info(topology->levels[0][0], "OSVersion", utsname->version); + if (*utsname->nodename) + hwloc_obj_add_info(topology->levels[0][0], "HostName", utsname->nodename); + if (*utsname->machine) + hwloc_obj_add_info(topology->levels[0][0], "Architecture", utsname->machine); +#endif /* HAVE_UNAME */ +} + +char * +hwloc_progname(struct hwloc_topology *topology __hwloc_attribute_unused) +{ +#if HAVE_DECL_GETMODULEFILENAME + char name[256], *basename; + unsigned res = GetModuleFileName(NULL, name, sizeof(name)); + if (res == sizeof(name) || !res) + return NULL; + basename = strrchr(name, '\\'); + if (!basename) + basename = name; + else + basename++; + return strdup(basename); +#else /* !HAVE_GETMODULEFILENAME */ + const char *name, *basename; +#if HAVE_DECL_GETPROGNAME + name = getprogname(); /* FreeBSD, NetBSD, some Solaris */ +#elif HAVE_DECL_GETEXECNAME + name = getexecname(); /* Solaris */ +#elif defined HAVE_PROGRAM_INVOCATION_NAME + name = program_invocation_name; /* Glibc. BGQ CNK. */ + /* could use program_invocation_short_name directly, but we have the code to remove the path below anyway */ +#elif defined HAVE___PROGNAME + name = __progname; /* fallback for most unix, used for OpenBSD */ +#else + /* TODO: _NSGetExecutablePath(path, &size) on Darwin */ + /* TODO: AIX, HPUX, OSF */ + name = NULL; +#endif + if (!name) + return NULL; + basename = strrchr(name, '/'); + if (!basename) + basename = name; + else + basename++; + return strdup(basename); +#endif /* !HAVE_GETMODULEFILENAME */ +} diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/pci-common.c b/opal/mca/hwloc/hwloc1110/hwloc/src/pci-common.c new file mode 100644 index 0000000000..01d4e79b66 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/pci-common.c @@ -0,0 +1,514 @@ +/* + * Copyright © 2009-2015 Inria. All rights reserved. + * See COPYING in top-level directory. + */ + +#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 + */ + lanespeed = speed <= 2 ? 2.5 * speed * 0.8 : 8.0 * 128/130; /* Gbit/s per lane */ + *linkspeed = lanespeed * width / 8; /* GB/s */ + 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) + 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]; + + return 0; +} diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/topology-aix.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-aix.c new file mode 100644 index 0000000000..1b98ba6b92 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-aix.c @@ -0,0 +1,872 @@ +/* + * Copyright © 2009 CNRS + * Copyright © 2009-2015 Inria. All rights reserved. + * Copyright © 2009-2011, 2013 Université Bordeaux + * Copyright © 2011 Cisco Systems, Inc. All rights reserved. + * See COPYING in top-level directory. + */ + +/* TODO: use SIGRECONFIG & dr_reconfig for state change */ + +#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 +#include +#include +#include + +#ifndef __power_pc +#define __power_pc() 0 +#endif +#ifndef __power_4 +#define __power_4() 0 +#endif +#ifndef __power_5 +#define __power_5() 0 +#endif +#ifndef __power_6 +#define __power_6() 0 +#endif +#ifndef __power_7 +#define __power_7() 0 +#endif + +static int +hwloc_aix_set_sth_cpubind(hwloc_topology_t topology, rstype_t what, rsid_t who, pid_t pid, hwloc_const_bitmap_t hwloc_set, int flags __hwloc_attribute_unused) +{ + rsethandle_t rad; + int res; + unsigned cpu; + + if (flags & HWLOC_CPUBIND_NOMEMBIND) { + errno = ENOSYS; + return -1; + } + + /* The resulting binding is always strict */ + + if (hwloc_bitmap_isequal(hwloc_set, hwloc_topology_get_complete_cpuset(topology))) { + if (ra_detachrset(what, who, 0)) + return -1; + return 0; + } + + rad = rs_alloc(RS_EMPTY); + hwloc_bitmap_foreach_begin(cpu, hwloc_set) + rs_op(RS_ADDRESOURCE, rad, NULL, R_PROCS, cpu); + hwloc_bitmap_foreach_end(); + + res = ra_attachrset(what, who, rad, 0); + if (res < 0 && errno == EPERM) { + /* EPERM may mean that one thread has ben bound with bindprocessor(). + * Unbind the entire process (we can't unbind individual threads) + * and try again. + */ + bindprocessor(BINDPROCESS, pid, PROCESSOR_CLASS_ANY); + res = ra_attachrset(what, who, rad, 0); + } + + rs_free(rad); + return res; +} + +static int +hwloc_aix_get_sth_rset_cpubind(hwloc_topology_t topology, rstype_t what, rsid_t who, hwloc_bitmap_t hwloc_set, int flags __hwloc_attribute_unused, int *boundp) +{ + rsethandle_t rset; + unsigned cpu, maxcpus; + int res = -1; + int bound = 0; + + rset = rs_alloc(RS_EMPTY); + + if (ra_getrset(what, who, 0, rset) == -1) + goto out; + + hwloc_bitmap_zero(hwloc_set); + maxcpus = rs_getinfo(rset, R_MAXPROCS, 0); + for (cpu = 0; cpu < maxcpus; cpu++) + if (rs_op(RS_TESTRESOURCE, rset, NULL, R_PROCS, cpu) == 1) + hwloc_bitmap_set(hwloc_set, cpu); + else + bound = 1; + hwloc_bitmap_and(hwloc_set, hwloc_set, hwloc_topology_get_complete_cpuset(topology)); + res = 0; + *boundp = bound; + +out: + rs_free(rset); + return res; +} + +static int +hwloc_aix_get_pid_getthrds_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, pid_t pid, hwloc_bitmap_t hwloc_set, int flags __hwloc_attribute_unused) +{ +#if HWLOC_BITS_PER_LONG == 64 + struct thrdentry64 thread_info; + tid64_t next_thread; +#else + struct thrdsinfo thread_info; + tid_t next_thread; +#endif + + next_thread = 0; + /* TODO: get multiple at once */ +#if HWLOC_BITS_PER_LONG == 64 + while (getthrds64 (pid, &thread_info, sizeof (thread_info), + &next_thread, 1) == 1) { +#else + while (getthrds (pid, &thread_info, sizeof (thread_info), + &next_thread, 1) == 1) { +#endif + if (PROCESSOR_CLASS_ANY != thread_info.ti_cpuid) + hwloc_bitmap_set(hwloc_set, thread_info.ti_cpuid); + else + hwloc_bitmap_fill(hwloc_set); + } + /* TODO: what if the thread list changes and we get nothing? */ + + return 0; +} + +static int +hwloc_aix_get_tid_getthrds_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, tid_t tid, hwloc_bitmap_t hwloc_set, int flags __hwloc_attribute_unused) +{ +#if HWLOC_BITS_PER_LONG == 64 + struct thrdentry64 thread_info; + tid64_t next_thread; +#else + struct thrdsinfo thread_info; + tid_t next_thread; +#endif + pid_t pid = getpid(); + + next_thread = 0; + /* TODO: get multiple at once */ +#if HWLOC_BITS_PER_LONG == 64 + while (getthrds64 (pid, &thread_info, sizeof (thread_info), + &next_thread, 1) == 1) { +#else + while (getthrds (pid, &thread_info, sizeof (thread_info), + &next_thread, 1) == 1) { +#endif + if (thread_info.ti_tid == tid) { + if (PROCESSOR_CLASS_ANY != thread_info.ti_cpuid) + hwloc_bitmap_set(hwloc_set, thread_info.ti_cpuid); + else + hwloc_bitmap_fill(hwloc_set); + break; + } + } + /* TODO: what if the thread goes away in the meantime? */ + + return 0; +} + +static int +hwloc_aix_set_thisproc_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags) +{ + rsid_t who; + who.at_pid = getpid(); + return hwloc_aix_set_sth_cpubind(topology, R_PROCESS, who, who.at_pid, hwloc_set, flags); +} + +static int +hwloc_aix_get_thisproc_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_set, int flags) +{ + int ret, bound; + rsid_t who; + who.at_pid = getpid(); + ret = hwloc_aix_get_sth_rset_cpubind(topology, R_PROCESS, who, hwloc_set, flags, &bound); + if (!ret && !bound) { + hwloc_bitmap_zero(hwloc_set); + ret = hwloc_aix_get_pid_getthrds_cpubind(topology, who.at_pid, hwloc_set, flags); + } + return ret; +} + +#ifdef R_THREAD +static int +hwloc_aix_set_thisthread_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags) +{ + rsid_t who; + who.at_tid = thread_self(); + return hwloc_aix_set_sth_cpubind(topology, R_THREAD, who, getpid(), hwloc_set, flags); +} + +static int +hwloc_aix_get_thisthread_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_set, int flags) +{ + int ret, bound; + rsid_t who; + who.at_tid = thread_self(); + ret = hwloc_aix_get_sth_rset_cpubind(topology, R_THREAD, who, hwloc_set, flags, &bound); + if (!ret && !bound) { + hwloc_bitmap_zero(hwloc_set); + ret = hwloc_aix_get_tid_getthrds_cpubind(topology, who.at_tid, hwloc_set, flags); + } + return ret; +} +#endif /* R_THREAD */ + +static int +hwloc_aix_set_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_bitmap_t hwloc_set, int flags) +{ + rsid_t who; + who.at_pid = pid; + return hwloc_aix_set_sth_cpubind(topology, R_PROCESS, who, pid, hwloc_set, flags); +} + +static int +hwloc_aix_get_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_bitmap_t hwloc_set, int flags) +{ + int ret, bound; + rsid_t who; + who.at_pid = pid; + ret = hwloc_aix_get_sth_rset_cpubind(topology, R_PROCESS, who, hwloc_set, flags, &bound); + if (!ret && !bound) { + hwloc_bitmap_zero(hwloc_set); + ret = hwloc_aix_get_pid_getthrds_cpubind(topology, who.at_pid, hwloc_set, flags); + } + return ret; +} + +#ifdef R_THREAD +#ifdef HWLOC_HAVE_PTHREAD_GETTHRDS_NP +static int +hwloc_aix_set_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t pthread, hwloc_const_bitmap_t hwloc_set, int flags) +{ + struct __pthrdsinfo info; + int size; + if ((errno = pthread_getthrds_np(&pthread, PTHRDSINFO_QUERY_TID, &info, sizeof(info), NULL, &size))) + return -1; + { + rsid_t who; + who.at_tid = info.__pi_tid; + return hwloc_aix_set_sth_cpubind(topology, R_THREAD, who, getpid(), hwloc_set, flags); + } +} + +static int +hwloc_aix_get_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t pthread, hwloc_bitmap_t hwloc_set, int flags) +{ + struct __pthrdsinfo info; + int size; + if (pthread_getthrds_np(&pthread, PTHRDSINFO_QUERY_TID, &info, sizeof(info), NULL, &size)) + return -1; + { + int ret, bound; + rsid_t who; + who.at_tid = info.__pi_tid; + ret = hwloc_aix_get_sth_rset_cpubind(topology, R_THREAD, who, hwloc_set, flags, &bound); + if (!ret && !bound) { + hwloc_bitmap_zero(hwloc_set); + ret = hwloc_aix_get_tid_getthrds_cpubind(topology, who.at_tid, hwloc_set, flags); + } + return ret; + } +} +#endif /* HWLOC_HAVE_PTHREAD_GETTHRDS_NP */ +#endif /* R_THREAD */ + +static int +hwloc_aix_get_thisthread_last_cpu_location(hwloc_topology_t topology, hwloc_bitmap_t hwloc_set, int flags __hwloc_attribute_unused) +{ + cpu_t cpu; + + if (topology->pid) { + errno = ENOSYS; + return -1; + } + + cpu = mycpu(); + if (cpu < 0) + return -1; + + hwloc_bitmap_only(hwloc_set, cpu); + return 0; +} + +#ifdef P_DEFAULT + +static int +hwloc_aix_membind_policy_from_hwloc(uint_t *aix_policy, int policy) +{ + switch (policy) { + case HWLOC_MEMBIND_DEFAULT: + case HWLOC_MEMBIND_BIND: + *aix_policy = P_DEFAULT; + break; + case HWLOC_MEMBIND_FIRSTTOUCH: + *aix_policy = P_FIRST_TOUCH; + break; + case HWLOC_MEMBIND_INTERLEAVE: + *aix_policy = P_BALANCED; + break; + default: + errno = ENOSYS; + return -1; + } + return 0; +} + +static int +hwloc_aix_prepare_membind(hwloc_topology_t topology, rsethandle_t *rad, hwloc_const_nodeset_t nodeset, int flags __hwloc_attribute_unused) +{ + rsethandle_t rset, noderad; + int MCMlevel; + int node; + + MCMlevel = rs_getinfo(NULL, R_MCMSDL, 0); + if ((topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM)) + rset = rs_alloc(RS_ALL); + else + rset = rs_alloc(RS_PARTITION); + *rad = rs_alloc(RS_EMPTY); + noderad = rs_alloc(RS_EMPTY); + + hwloc_bitmap_foreach_begin(node, nodeset) + /* we used MCMlevel rad number for node->os_index during lookup */ + rs_getrad(rset, noderad, MCMlevel, node, 0); + rs_op(RS_UNION, noderad, *rad, 0, 0); + hwloc_bitmap_foreach_end(); + + rs_free(rset); + rs_free(noderad); + + return 0; +} + +static int +hwloc_aix_set_sth_membind(hwloc_topology_t topology, rstype_t what, rsid_t who, pid_t pid, hwloc_const_bitmap_t nodeset, hwloc_membind_policy_t policy, int flags) +{ + rsethandle_t rad; + int res; + + if (flags & HWLOC_MEMBIND_NOCPUBIND) { + errno = ENOSYS; + return -1; + } + + switch (policy) { + case HWLOC_MEMBIND_DEFAULT: + case HWLOC_MEMBIND_BIND: + break; + default: + errno = ENOSYS; + return -1; + } + + if (hwloc_aix_prepare_membind(topology, &rad, nodeset, flags)) + return -1; + + res = ra_attachrset(what, who, rad, 0); + if (res < 0 && errno == EPERM) { + /* EPERM may mean that one thread has ben bound with bindprocessor(). + * Unbind the entire process (we can't unbind individual threads) + * and try again. + */ + bindprocessor(BINDPROCESS, pid, PROCESSOR_CLASS_ANY); + res = ra_attachrset(what, who, rad, 0); + } + + rs_free(rad); + return res; +} + +static int +hwloc_aix_get_sth_membind(hwloc_topology_t topology, rstype_t what, rsid_t who, hwloc_bitmap_t nodeset, hwloc_membind_policy_t *policy, int flags __hwloc_attribute_unused) +{ + hwloc_bitmap_t hwloc_set; + rsethandle_t rset; + unsigned cpu, maxcpus; + int res = -1; + int depth, n, i; + + depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE); + if (depth < 0) { + errno = EXDEV; + return -1; + } + n = hwloc_get_nbobjs_by_depth(topology, depth); + + rset = rs_alloc(RS_EMPTY); + + if (ra_getrset(what, who, 0, rset) == -1) + goto out; + + hwloc_set = hwloc_bitmap_alloc(); + + maxcpus = rs_getinfo(rset, R_MAXPROCS, 0); + for (cpu = 0; cpu < maxcpus; cpu++) + if (rs_op(RS_TESTRESOURCE, rset, NULL, R_PROCS, cpu) == 1) + hwloc_bitmap_set(hwloc_set, cpu); + hwloc_bitmap_and(hwloc_set, hwloc_set, hwloc_topology_get_complete_cpuset(topology)); + + hwloc_bitmap_zero(nodeset); + for (i = 0; i < n; i++) { + hwloc_obj_t obj = hwloc_get_obj_by_depth(topology, depth, i); + if (hwloc_bitmap_isincluded(obj->cpuset, hwloc_set)) + hwloc_bitmap_set(nodeset, obj->os_index); + } + + hwloc_bitmap_free(hwloc_set); + + *policy = HWLOC_MEMBIND_DEFAULT; + res = 0; + +out: + rs_free(rset); + return res; +} + +static int +hwloc_aix_set_thisproc_membind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, hwloc_membind_policy_t policy, int flags) +{ + rsid_t who; + who.at_pid = getpid(); + return hwloc_aix_set_sth_membind(topology, R_PROCESS, who, who.at_pid, hwloc_set, policy, flags); +} + +static int +hwloc_aix_get_thisproc_membind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_set, hwloc_membind_policy_t *policy, int flags) +{ + rsid_t who; + who.at_pid = getpid(); + return hwloc_aix_get_sth_membind(topology, R_PROCESS, who, hwloc_set, policy, flags); +} + +#ifdef R_THREAD +static int +hwloc_aix_set_thisthread_membind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, hwloc_membind_policy_t policy, int flags) +{ + rsid_t who; + who.at_tid = thread_self(); + return hwloc_aix_set_sth_membind(topology, R_THREAD, who, getpid(), hwloc_set, policy, flags); +} + +static int +hwloc_aix_get_thisthread_membind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_set, hwloc_membind_policy_t *policy, int flags) +{ + rsid_t who; + who.at_tid = thread_self(); + return hwloc_aix_get_sth_membind(topology, R_THREAD, who, hwloc_set, policy, flags); +} +#endif /* R_THREAD */ + +static int +hwloc_aix_set_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_bitmap_t hwloc_set, hwloc_membind_policy_t policy, int flags) +{ + rsid_t who; + who.at_pid = pid; + return hwloc_aix_set_sth_membind(topology, R_PROCESS, who, pid, hwloc_set, policy, flags); +} + +static int +hwloc_aix_get_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_bitmap_t hwloc_set, hwloc_membind_policy_t *policy, int flags) +{ + rsid_t who; + who.at_pid = pid; + return hwloc_aix_get_sth_membind(topology, R_PROCESS, who, hwloc_set, policy, flags); +} + +#ifdef R_THREAD +#if 0 /* def HWLOC_HAVE_PTHREAD_GETTHRDS_NP */ +static int +hwloc_aix_set_thread_membind(hwloc_topology_t topology, hwloc_thread_t pthread, hwloc_const_bitmap_t hwloc_set, hwloc_membind_policy_t policy, int flags) +{ + struct __pthrdsinfo info; + int size; + if ((errno = pthread_getthrds_np(&pthread, PTHRDSINFO_QUERY_TID, &info, sizeof(info), NULL, &size))) + return -1; + { + rsid_t who; + who.at_tid = info.__pi_tid; + return hwloc_aix_set_sth_membind(topology, R_THREAD, who, getpid(), hwloc_set, policy, flags); + } +} + +static int +hwloc_aix_get_thread_membind(hwloc_topology_t topology, hwloc_thread_t pthread, hwloc_bitmap_t hwloc_set, hwloc_membind_policy_t *policy, int flags) +{ + struct __pthrdsinfo info; + int size; + if (pthread_getthrds_np(&pthread, PTHRDSINFO_QUERY_TID, &info, sizeof(info), NULL, &size)) + return -1; + { + rsid_t who; + who.at_tid = info.__pi_tid; + return hwloc_aix_get_sth_membind(topology, R_THREAD, who, hwloc_set, policy, flags); + } +} +#endif /* HWLOC_HAVE_PTHREAD_GETTHRDS_NP */ +#endif /* R_THREAD */ + +#if 0 +/* TODO: seems to be right, but doesn't seem to be working (EINVAL), even after + * aligning the range on 64K... */ +static int +hwloc_aix_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) +{ + subrange_t subrange; + rsid_t rsid = { .at_subrange = &subrange }; + uint_t aix_policy; + int ret; + fprintf(stderr,"yop\n"); + + if ((flags & (HWLOC_MEMBIND_MIGRATE|HWLOC_MEMBIND_STRICT)) + == (HWLOC_MEMBIND_MIGRATE|HWLOC_MEMBIND_STRICT)) { + errno = ENOSYS; + return -1; + } + + subrange.su_offset = (uintptr_t) addr; + subrange.su_length = len; + subrange.su_rstype = R_RSET; + + if (hwloc_aix_membind_policy_from_hwloc(&aix_policy, policy)) + return -1; + + if (hwloc_aix_prepare_membind(topology, &subrange.su_rsid.at_rset, nodeset, flags)) + return -1; + + subrange.su_policy = aix_policy; + + res = ra_attachrset(R_SUBRANGE, rsid, subrange.su_rsid.at_rset, 0); + if (res < 0 && errno == EPERM) { + /* EPERM may mean that one thread has ben bound with bindprocessor(). + * Unbind the entire process (we can't unbind individual threads) + * and try again. + * FIXME: actually check that this EPERM can happen + */ + bindprocessor(BINDPROCESS, getpid(), PROCESSOR_CLASS_ANY); + res = ra_attachrset(R_SUBRANGE, rsid, subrange.su_rsid.at_rset, 0); + } + + rs_free(subrange.su_rsid.at_rset); + return ret; +} +#endif + +static void * +hwloc_aix_alloc_membind(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) +{ + void *ret; + rsid_t rsid; + uint_t aix_policy; + + if (hwloc_aix_membind_policy_from_hwloc(&aix_policy, policy)) + return hwloc_alloc_or_fail(topology, len, flags); + + if (hwloc_aix_prepare_membind(topology, &rsid.at_rset, nodeset, flags)) + return hwloc_alloc_or_fail(topology, len, flags); + + ret = ra_mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0, R_RSET, rsid, aix_policy); + + rs_free(rsid.at_rset); + return ret; +} +#endif /* P_DEFAULT */ + +static void +look_rset(int sdl, hwloc_obj_type_t type, struct hwloc_topology *topology, int level) +{ + rsethandle_t rset, rad; + int i,maxcpus,j; + int nbnodes; + struct hwloc_obj *obj; + + if ((topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM)) + rset = rs_alloc(RS_ALL); + else + rset = rs_alloc(RS_PARTITION); + rad = rs_alloc(RS_EMPTY); + nbnodes = rs_numrads(rset, sdl, 0); + if (nbnodes == -1) { + perror("rs_numrads"); + return; + } + + for (i = 0; i < nbnodes; i++) { + hwloc_bitmap_t cpuset; + unsigned os_index = (unsigned) -1; /* no os_index except for PU and NUMANODE below */ + + if (rs_getrad(rset, rad, sdl, i, 0)) { + fprintf(stderr,"rs_getrad(%d) failed: %s\n", i, strerror(errno)); + continue; + } + if (!rs_getinfo(rad, R_NUMPROCS, 0)) + continue; + + maxcpus = rs_getinfo(rad, R_MAXPROCS, 0); + cpuset = hwloc_bitmap_alloc(); + for (j = 0; j < maxcpus; j++) { + if (rs_op(RS_TESTRESOURCE, rad, NULL, R_PROCS, j)) + hwloc_bitmap_set(cpuset, j); + } + + if (type == HWLOC_OBJ_PU) { + os_index = hwloc_bitmap_first(cpuset); + hwloc_debug("Found PU #%u inside node %d for sdl %d\n", os_index, i, sdl); + assert(hwloc_bitmap_weight(cpuset) == 1); + } else if (type == HWLOC_OBJ_NUMANODE) { + /* NUMA node os_index isn't used for binding, just use the rad number to get unique values. + * Note that we'll use that fact in hwloc_aix_prepare_membind(). */ + os_index = i; + hwloc_debug("Using os_index #%u for NUMA node inside node %d for sdl %d\n", os_index, i, sdl); + } + + obj = hwloc_alloc_setup_object(type, os_index); + obj->cpuset = cpuset; + obj->os_level = sdl; + + switch(type) { + case HWLOC_OBJ_NUMANODE: + obj->nodeset = hwloc_bitmap_alloc(); + hwloc_bitmap_set(obj->nodeset, i); + obj->memory.local_memory = 0; /* TODO: odd, rs_getinfo(rad, R_MEMSIZE, 0) << 10 returns the total memory ... */ + 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(); +#ifdef HAVE__SC_LARGE_PAGESIZE + obj->memory.page_types[1].size = sysconf(_SC_LARGE_PAGESIZE); +#endif + /* TODO: obj->memory.page_types[1].count = rs_getinfo(rset, R_LGPGFREE, 0) / hugepagesize */ + break; + case HWLOC_OBJ_CACHE: + obj->attr->cache.size = _system_configuration.L2_cache_size; + obj->attr->cache.associativity = _system_configuration.L2_cache_asc; + + obj->attr->cache.linesize = 0; /* unknown by default */ + if (__power_pc()) + if (__power_4() || __power_5() || __power_6() || __power_7()) + obj->attr->cache.linesize = 128; + + obj->attr->cache.depth = 2; + obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED; /* OK for power[4567], unknown for others */ + break; + case HWLOC_OBJ_GROUP: + obj->attr->group.depth = level; + break; + case HWLOC_OBJ_CORE: + { + hwloc_obj_t obj2, obj3; + obj2 = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, i); + obj2->cpuset = hwloc_bitmap_dup(obj->cpuset); + obj2->attr->cache.size = _system_configuration.dcache_size; + obj2->attr->cache.associativity = _system_configuration.dcache_asc; + obj2->attr->cache.linesize = _system_configuration.dcache_line; + obj2->attr->cache.depth = 1; + if (_system_configuration.cache_attrib & (1<<30)) { + /* Unified cache */ + obj2->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED; + hwloc_debug("Adding an L1u cache for core %d\n", i); + hwloc_insert_object_by_cpuset(topology, obj2); + } else { + /* Separate Instruction and Data caches */ + obj2->attr->cache.type = HWLOC_OBJ_CACHE_DATA; + hwloc_debug("Adding an L1d cache for core %d\n", i); + hwloc_insert_object_by_cpuset(topology, obj2); + + obj3 = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, i); + obj3->cpuset = hwloc_bitmap_dup(obj->cpuset); + obj3->attr->cache.size = _system_configuration.icache_size; + obj3->attr->cache.associativity = _system_configuration.icache_asc; + obj3->attr->cache.linesize = _system_configuration.icache_line; + obj3->attr->cache.depth = 1; + obj3->attr->cache.type = HWLOC_OBJ_CACHE_INSTRUCTION; + hwloc_debug("Adding an L1i cache for core %d\n", i); + hwloc_insert_object_by_cpuset(topology, obj3); + } + break; + } + default: + break; + } + hwloc_debug_2args_bitmap("%s %d has cpuset %s\n", + hwloc_obj_type_string(type), + i, obj->cpuset); + hwloc_insert_object_by_cpuset(topology, obj); + } + + rs_free(rset); + rs_free(rad); +} + +static int +hwloc_look_aix(struct hwloc_backend *backend) +{ + struct hwloc_topology *topology = backend->topology; + int i; + + if (topology->levels[0][0]->cpuset) + /* somebody discovered things */ + return 0; + + hwloc_alloc_obj_cpusets(topology->levels[0][0]); + + /* TODO: R_LGPGDEF/R_LGPGFREE for large pages */ + + hwloc_debug("Note: SMPSDL is at %d\n", rs_getinfo(NULL, R_SMPSDL, 0)); +#ifdef R_REF1SDL + hwloc_debug("Note: REF1SDL is at %d\n", rs_getinfo(NULL, R_REF1SDL, 0)); +#endif + + for (i=0; i<=rs_getinfo(NULL, R_MAXSDL, 0); i++) + { + int known = 0; +#if 0 + if (i == rs_getinfo(NULL, R_SMPSDL, 0)) + /* Not enabled for now because I'm not sure what it corresponds to. On + * decrypthon it contains all the cpus. Is it a "machine" or a "system" + * level ? + */ + { + hwloc_debug("looking AIX \"SMP\" sdl %d\n", i); + look_rset(i, HWLOC_OBJ_MACHINE, topology, i); + known = 1; + } +#endif + if (i == rs_getinfo(NULL, R_MCMSDL, 0)) + { + hwloc_debug("looking AIX node sdl %d\n", i); + look_rset(i, HWLOC_OBJ_NUMANODE, topology, i); + known = 1; + } +# ifdef R_L2CSDL + if (i == rs_getinfo(NULL, R_L2CSDL, 0)) + { + hwloc_debug("looking AIX L2 sdl %d\n", i); + look_rset(i, HWLOC_OBJ_CACHE, topology, i); + known = 1; + } +# endif +# ifdef R_PCORESDL + if (i == rs_getinfo(NULL, R_PCORESDL, 0)) + { + hwloc_debug("looking AIX core sdl %d\n", i); + look_rset(i, HWLOC_OBJ_CORE, topology, i); + known = 1; + } +# endif + if (i == rs_getinfo(NULL, R_MAXSDL, 0)) + { + hwloc_debug("looking AIX max sdl %d\n", i); + look_rset(i, HWLOC_OBJ_PU, topology, i); + known = 1; + topology->support.discovery->pu = 1; + } + + /* Don't know how it should be rendered, make a misc object for it. */ + if (!known) + { + hwloc_debug("looking AIX unknown sdl %d\n", i); + look_rset(i, HWLOC_OBJ_GROUP, topology, i); + } + } + + hwloc_obj_add_info(topology->levels[0][0], "Backend", "AIX"); + if (topology->is_thissystem) + hwloc_add_uname_info(topology, NULL); + return 1; +} + +void +hwloc_set_aix_hooks(struct hwloc_binding_hooks *hooks, + struct hwloc_topology_support *support __hwloc_attribute_unused) +{ + hooks->set_proc_cpubind = hwloc_aix_set_proc_cpubind; + hooks->get_proc_cpubind = hwloc_aix_get_proc_cpubind; +#ifdef R_THREAD +#ifdef HWLOC_HAVE_PTHREAD_GETTHRDS_NP + hooks->set_thread_cpubind = hwloc_aix_set_thread_cpubind; + hooks->get_thread_cpubind = hwloc_aix_get_thread_cpubind; +#endif /* HWLOC_HAVE_PTHREAD_GETTHRDS_NP */ +#endif /* R_THREAD */ + hooks->set_thisproc_cpubind = hwloc_aix_set_thisproc_cpubind; + hooks->get_thisproc_cpubind = hwloc_aix_get_thisproc_cpubind; +#ifdef R_THREAD + hooks->set_thisthread_cpubind = hwloc_aix_set_thisthread_cpubind; + hooks->get_thisthread_cpubind = hwloc_aix_get_thisthread_cpubind; +#endif /* R_THREAD */ + hooks->get_thisthread_last_cpu_location = hwloc_aix_get_thisthread_last_cpu_location; + /* TODO: get_last_cpu_location: mycpu() only works for the current thread? */ +#ifdef P_DEFAULT + hooks->set_proc_membind = hwloc_aix_set_proc_membind; + hooks->get_proc_membind = hwloc_aix_get_proc_membind; +#ifdef R_THREAD +#if 0 /* def HWLOC_HAVE_PTHREAD_GETTHRDS_NP */ + /* Does it really make sense to set the memory binding of another thread? */ + hooks->set_thread_membind = hwloc_aix_set_thread_membind; + hooks->get_thread_membind = hwloc_aix_get_thread_membind; +#endif /* HWLOC_HAVE_PTHREAD_GETTHRDS_NP */ +#endif /* R_THREAD */ + hooks->set_thisproc_membind = hwloc_aix_set_thisproc_membind; + hooks->get_thisproc_membind = hwloc_aix_get_thisproc_membind; +#ifdef R_THREAD + hooks->set_thisthread_membind = hwloc_aix_set_thisthread_membind; + hooks->get_thisthread_membind = hwloc_aix_get_thisthread_membind; +#endif /* R_THREAD */ + /* hooks->set_area_membind = hwloc_aix_set_area_membind; */ + /* get_area_membind is not available */ + hooks->alloc_membind = hwloc_aix_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; +#endif /* P_DEFAULT */ +} + +static struct hwloc_backend * +hwloc_aix_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_aix; + return backend; +} + +static struct hwloc_disc_component hwloc_aix_disc_component = { + HWLOC_DISC_COMPONENT_TYPE_CPU, + "aix", + HWLOC_DISC_COMPONENT_TYPE_GLOBAL, + hwloc_aix_component_instantiate, + 50, + NULL +}; + +const struct hwloc_component hwloc_aix_component = { + HWLOC_COMPONENT_ABI, + NULL, NULL, + HWLOC_COMPONENT_TYPE_DISC, + 0, + &hwloc_aix_disc_component +}; diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/topology-bgq.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-bgq.c new file mode 100644 index 0000000000..1258b65420 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-bgq.c @@ -0,0 +1,241 @@ +/* + * Copyright © 2013-2015 Inria. All rights reserved. + * See COPYING in top-level directory. + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +static int +hwloc_look_bgq(struct hwloc_backend *backend) +{ + struct hwloc_topology *topology = backend->topology; + unsigned i; + const char *env; + + if (!topology->levels[0][0]->cpuset) { + /* Nobody created objects yet, setup everything */ + hwloc_bitmap_t set; + hwloc_obj_t obj; + +#define HWLOC_BGQ_CORES 17 /* spare core ignored for now */ + + hwloc_alloc_obj_cpusets(topology->levels[0][0]); + /* mark the 17th core (OS-reserved) as disallowed */ + hwloc_bitmap_clr_range(topology->levels[0][0]->allowed_cpuset, (HWLOC_BGQ_CORES-1)*4, HWLOC_BGQ_CORES*4-1); + + env = getenv("BG_THREADMODEL"); + if (!env || atoi(env) != 2) { + /* process cannot use cores/threads outside of its Kernel_ThreadMask() */ + uint64_t bgmask = Kernel_ThreadMask(Kernel_MyTcoord()); + /* the mask is reversed, manually reverse it */ + for(i=0; i<64; i++) + if (((bgmask >> i) & 1) == 0) + hwloc_bitmap_clr(topology->levels[0][0]->allowed_cpuset, 63-i); + } + + /* a single memory bank */ + set = hwloc_bitmap_alloc(); + hwloc_bitmap_set(set, 0); + topology->levels[0][0]->nodeset = set; + topology->levels[0][0]->memory.local_memory = 16ULL*1024*1024*1024ULL; + + /* package */ + obj = hwloc_alloc_setup_object(HWLOC_OBJ_PACKAGE, 0); + set = hwloc_bitmap_alloc(); + hwloc_bitmap_set_range(set, 0, HWLOC_BGQ_CORES*4-1); + obj->cpuset = set; + hwloc_obj_add_info(obj, "CPUModel", "IBM PowerPC A2"); + hwloc_insert_object_by_cpuset(topology, obj); + + /* shared L2 */ + 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 = 32*1024*1024; + obj->attr->cache.linesize = 128; + obj->attr->cache.associativity = 16; + hwloc_insert_object_by_cpuset(topology, obj); + + /* Cores */ + for(i=0; icpuset = set; + hwloc_insert_object_by_cpuset(topology, obj); + /* L1d */ + 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 = 16*1024; + obj->attr->cache.linesize = 64; + obj->attr->cache.associativity = 8; + hwloc_insert_object_by_cpuset(topology, obj); + /* L1i */ + 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 = 16*1024; + obj->attr->cache.linesize = 64; + obj->attr->cache.associativity = 4; + hwloc_insert_object_by_cpuset(topology, obj); + /* there's also a L1p "prefetch cache" of 4kB with 128B lines */ + } + + /* PUs */ + hwloc_setup_pu_level(topology, HWLOC_BGQ_CORES*4); + } + + /* Add BGQ specific information */ + + hwloc_obj_add_info(topology->levels[0][0], "Backend", "BGQ"); + if (topology->is_thissystem) + hwloc_add_uname_info(topology, NULL); + return 1; +} + +static int +hwloc_bgq_get_thread_cpubind(hwloc_topology_t topology, pthread_t thread, hwloc_bitmap_t hwloc_set, int flags __hwloc_attribute_unused) +{ + unsigned pu; + cpu_set_t bg_set; + int err; + + if (topology->pid) { + errno = ENOSYS; + return -1; + } + err = pthread_getaffinity_np(thread, sizeof(bg_set), &bg_set); + if (err) { + errno = err; + return -1; + } + for(pu=0; pu<64; pu++) + if (CPU_ISSET(pu, &bg_set)) { + /* the binding cannot contain multiple PUs */ + hwloc_bitmap_only(hwloc_set, pu); + break; + } + return 0; +} + +static int +hwloc_bgq_get_thisthread_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_set, int flags __hwloc_attribute_unused) +{ + if (topology->pid) { + errno = ENOSYS; + return -1; + } + hwloc_bitmap_only(hwloc_set, Kernel_ProcessorID()); + return 0; +} + +static int +hwloc_bgq_set_thread_cpubind(hwloc_topology_t topology, pthread_t thread, hwloc_const_bitmap_t hwloc_set, int flags) +{ + unsigned pu; + cpu_set_t bg_set; + int err; + + if (topology->pid) { + errno = ENOSYS; + return -1; + } + /* the binding cannot contain multiple PUs. + * keep the first PU only, and error out if STRICT. + */ + if (hwloc_bitmap_weight(hwloc_set) != 1) { + if ((flags & HWLOC_CPUBIND_STRICT)) { + errno = ENOSYS; + return -1; + } + } + pu = hwloc_bitmap_first(hwloc_set); + CPU_ZERO(&bg_set); + CPU_SET(pu, &bg_set); + err = pthread_setaffinity_np(thread, sizeof(bg_set), &bg_set); + if (err) { + errno = err; + return -1; + } + return 0; +} + +static int +hwloc_bgq_set_thisthread_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags) +{ + return hwloc_bgq_set_thread_cpubind(topology, pthread_self(), hwloc_set, flags); +} + +void +hwloc_set_bgq_hooks(struct hwloc_binding_hooks *hooks __hwloc_attribute_unused, + struct hwloc_topology_support *support __hwloc_attribute_unused) +{ + hooks->set_thisthread_cpubind = hwloc_bgq_set_thisthread_cpubind; + hooks->set_thread_cpubind = hwloc_bgq_set_thread_cpubind; + hooks->get_thisthread_cpubind = hwloc_bgq_get_thisthread_cpubind; + hooks->get_thread_cpubind = hwloc_bgq_get_thread_cpubind; + /* threads cannot be bound to more than one PU, so get_last_cpu_location == get_cpubind */ + hooks->get_thisthread_last_cpu_location = hwloc_bgq_get_thisthread_cpubind; + /* hooks->get_thread_last_cpu_location = hwloc_bgq_get_thread_cpubind; */ +} + +static struct hwloc_backend * +hwloc_bgq_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 utsname utsname; + struct hwloc_backend *backend; + const char *env; + int err; + + env = getenv("HWLOC_FORCE_BGQ"); + if (!env || !atoi(env)) { + err = uname(&utsname); + if (err || strcmp(utsname.sysname, "CNK") || strcmp(utsname.machine, "BGQ")) { + fprintf(stderr, "*** Found unexpected uname sysname `%s' machine `%s'\n", utsname.sysname, utsname.machine); + fprintf(stderr, "*** The BGQ backend is only enabled on compute nodes by default (sysname=CNK machine=BGQ)\n"); + fprintf(stderr, "*** Set HWLOC_FORCE_BGQ=1 in the environment to enforce the BGQ backend anyway.\n"); + return NULL; + } + } + + backend = hwloc_backend_alloc(component); + if (!backend) + return NULL; + backend->discover = hwloc_look_bgq; + return backend; +} + +static struct hwloc_disc_component hwloc_bgq_disc_component = { + HWLOC_DISC_COMPONENT_TYPE_GLOBAL, + "bgq", + ~0, + hwloc_bgq_component_instantiate, + 50, + NULL +}; + +const struct hwloc_component hwloc_bgq_component = { + HWLOC_COMPONENT_ABI, + NULL, NULL, + HWLOC_COMPONENT_TYPE_DISC, + 0, + &hwloc_bgq_disc_component +}; diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/topology-cuda.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-cuda.c new file mode 100644 index 0000000000..a1c6bffab4 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-cuda.c @@ -0,0 +1,248 @@ +/* + * Copyright © 2011 Université Bordeaux + * Copyright © 2012-2014 Inria. All rights reserved. + * See COPYING in top-level directory. + */ + +#include +#include +#include +#include + +/* private headers allowed for convenience because this plugin is built within hwloc */ +#include +#include + +#include + +struct hwloc_cuda_backend_data_s { + unsigned nr_devices; /* -1 when unknown yet, first callback will setup */ + struct hwloc_cuda_device_info_s { + int idx; + unsigned pcidomain, pcibus, pcidev, pcifunc; + } * devices; +}; + +/* query all PCI bus ids for later */ +static void +hwloc_cuda_query_devices(struct hwloc_cuda_backend_data_s *data) +{ + cudaError_t cures; + int 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; + + cures = cudaGetDeviceCount(&nb); + if (cures) + return; + + /* allocate structs */ + data->devices = malloc(nb * sizeof(*data->devices)); + if (!data->devices) + return; + + for (i = 0; i < nb; i++) { + struct hwloc_cuda_device_info_s *info = &data->devices[data->nr_devices]; + int domain, bus, dev; + + if (hwloc_cudart_get_device_pci_ids(NULL /* topology unused */, i, &domain, &bus, &dev)) + continue; + + info->idx = i; + info->pcidomain = (unsigned) domain; + info->pcibus = (unsigned) bus; + info->pcidev = (unsigned) dev; + info->pcifunc = 0; + + /* validate this device */ + data->nr_devices++; + } + + return; +} + +static unsigned hwloc_cuda_cores_per_MP(int major, int minor) +{ + /* based on CUDA C Programming Guide, Annex G */ + switch (major) { + case 1: + switch (minor) { + case 0: + case 1: + case 2: + case 3: return 8; + } + break; + case 2: + switch (minor) { + case 0: return 32; + case 1: return 48; + } + break; + case 3: + return 192; + case 5: + return 128; + } + hwloc_debug("unknown compute capability %u.%u, disabling core display.\n", major, minor); + return 0; +} + +static int +hwloc_cuda_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_cuda_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 CUDA 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_cuda_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; + + for(i=0; inr_devices; i++) { + struct hwloc_cuda_device_info_s *info = &data->devices[i]; + char cuda_name[32]; + char number[32]; + struct cudaDeviceProp prop; + hwloc_obj_t cuda_device; + cudaError_t cures; + unsigned cores; + + 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; + + cuda_device = hwloc_alloc_setup_object(HWLOC_OBJ_OS_DEVICE, -1); + snprintf(cuda_name, sizeof(cuda_name), "cuda%d", info->idx); + cuda_device->name = strdup(cuda_name); + cuda_device->depth = (unsigned) HWLOC_TYPE_DEPTH_UNKNOWN; + cuda_device->attr->osdev.type = HWLOC_OBJ_OSDEV_COPROC; + + hwloc_obj_add_info(cuda_device, "CoProcType", "CUDA"); + hwloc_obj_add_info(cuda_device, "Backend", "CUDA"); + hwloc_obj_add_info(cuda_device, "GPUVendor", "NVIDIA Corporation"); + + cures = cudaGetDeviceProperties(&prop, info->idx); + if (!cures) + hwloc_obj_add_info(cuda_device, "GPUModel", prop.name); + + snprintf(number, sizeof(number), "%llu", ((unsigned long long) prop.totalGlobalMem) >> 10); + hwloc_obj_add_info(cuda_device, "CUDAGlobalMemorySize", number); + + snprintf(number, sizeof(number), "%llu", ((unsigned long long) prop.l2CacheSize) >> 10); + hwloc_obj_add_info(cuda_device, "CUDAL2CacheSize", number); + + snprintf(number, sizeof(number), "%d", prop.multiProcessorCount); + hwloc_obj_add_info(cuda_device, "CUDAMultiProcessors", number); + + cores = hwloc_cuda_cores_per_MP(prop.major, prop.minor); + if (cores) { + snprintf(number, sizeof(number), "%u", cores); + hwloc_obj_add_info(cuda_device, "CUDACoresPerMP", number); + } + + snprintf(number, sizeof(number), "%llu", ((unsigned long long) prop.sharedMemPerBlock) >> 10); + hwloc_obj_add_info(cuda_device, "CUDASharedMemorySizePerMP", number); + + hwloc_insert_object_by_parent(topology, pcidev, cuda_device); + return 1; + } + + return 0; +} + +static void +hwloc_cuda_backend_disable(struct hwloc_backend *backend) +{ + struct hwloc_cuda_backend_data_s *data = backend->private_data; + free(data->devices); + free(data); +} + +static struct hwloc_backend * +hwloc_cuda_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_cuda_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_cuda_backend_disable; + + backend->notify_new_object = hwloc_cuda_backend_notify_new_object; + return backend; +} + +static struct hwloc_disc_component hwloc_cuda_disc_component = { + HWLOC_DISC_COMPONENT_TYPE_MISC, + "cuda", + HWLOC_DISC_COMPONENT_TYPE_GLOBAL, + hwloc_cuda_component_instantiate, + 10, /* after pci */ + NULL +}; + +static int +hwloc_cuda_component_init(unsigned long flags) +{ + if (flags) + return -1; + if (hwloc_plugin_check_namespace("cuda", "hwloc_backend_alloc") < 0) + return -1; + return 0; +} + +#ifdef HWLOC_INSIDE_PLUGIN +HWLOC_DECLSPEC extern const struct hwloc_component hwloc_cuda_component; +#endif + +const struct hwloc_component hwloc_cuda_component = { + HWLOC_COMPONENT_ABI, + hwloc_cuda_component_init, NULL, + HWLOC_COMPONENT_TYPE_DISC, + 0, + &hwloc_cuda_disc_component +}; diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/topology-custom.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-custom.c new file mode 100644 index 0000000000..c3ccfaadc9 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-custom.c @@ -0,0 +1,100 @@ +/* + * 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/hwloc1110/hwloc/src/topology-darwin.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-darwin.c new file mode 100644 index 0000000000..1062a1d0c0 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-darwin.c @@ -0,0 +1,307 @@ +/* + * Copyright © 2009 CNRS + * Copyright © 2009-2014 Inria. All rights reserved. + * Copyright © 2009-2013 Université Bordeaux + * Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved. + * See COPYING in top-level directory. + */ + +/* Detect topology change: registering for power management changes and check + * if for example hw.activecpu changed */ + +/* Apparently, Darwin people do not _want_ to provide binding functions. */ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +static int +hwloc_look_darwin(struct hwloc_backend *backend) +{ + struct hwloc_topology *topology = backend->topology; + int64_t _nprocs; + unsigned nprocs; + int64_t _npackages; + unsigned i, j, cpu; + struct hwloc_obj *obj; + size_t size; + int64_t l1dcachesize, l1icachesize; + int64_t cacheways[2]; + int64_t l2cachesize; + int64_t cachelinesize; + int64_t memsize; + char cpumodel[64]; + + if (topology->levels[0][0]->cpuset) + /* somebody discovered things */ + return 0; + + hwloc_alloc_obj_cpusets(topology->levels[0][0]); + + if (hwloc_get_sysctlbyname("hw.ncpu", &_nprocs) || _nprocs <= 0) + return -1; + nprocs = _nprocs; + topology->support.discovery->pu = 1; + + hwloc_debug("%u procs\n", nprocs); + + size = sizeof(cpumodel); + if (sysctlbyname("machdep.cpu.brand_string", cpumodel, &size, NULL, 0)) + cpumodel[0] = '\0'; + + if (!hwloc_get_sysctlbyname("hw.packages", &_npackages) && _npackages > 0) { + unsigned npackages = _npackages; + int64_t _cores_per_package; + int64_t _logical_per_package; + unsigned logical_per_package; + + hwloc_debug("%u packages\n", npackages); + + if (!hwloc_get_sysctlbyname("machdep.cpu.logical_per_package", &_logical_per_package) && _logical_per_package > 0) + logical_per_package = _logical_per_package; + else + /* Assume the trivia. */ + logical_per_package = nprocs / npackages; + + hwloc_debug("%u threads per package\n", logical_per_package); + + + if (nprocs == npackages * logical_per_package) + for (i = 0; i < npackages; i++) { + obj = hwloc_alloc_setup_object(HWLOC_OBJ_PACKAGE, i); + obj->cpuset = hwloc_bitmap_alloc(); + for (cpu = i*logical_per_package; cpu < (i+1)*logical_per_package; cpu++) + hwloc_bitmap_set(obj->cpuset, cpu); + + hwloc_debug_1arg_bitmap("package %u has cpuset %s\n", + i, obj->cpuset); + + if (cpumodel[0] != '\0') + hwloc_obj_add_info(obj, "CPUModel", cpumodel); + hwloc_insert_object_by_cpuset(topology, obj); + } + else + if (cpumodel[0] != '\0') + hwloc_obj_add_info(topology->levels[0][0], "CPUModel", cpumodel); + + if (!hwloc_get_sysctlbyname("machdep.cpu.cores_per_package", &_cores_per_package) && _cores_per_package > 0) { + unsigned cores_per_package = _cores_per_package; + hwloc_debug("%u cores per package\n", cores_per_package); + + if (!(logical_per_package % cores_per_package)) + for (i = 0; i < npackages * cores_per_package; i++) { + obj = hwloc_alloc_setup_object(HWLOC_OBJ_CORE, i); + obj->cpuset = hwloc_bitmap_alloc(); + for (cpu = i*(logical_per_package/cores_per_package); + cpu < (i+1)*(logical_per_package/cores_per_package); + cpu++) + hwloc_bitmap_set(obj->cpuset, cpu); + + hwloc_debug_1arg_bitmap("core %u has cpuset %s\n", + i, obj->cpuset); + hwloc_insert_object_by_cpuset(topology, obj); + } + } + } else + if (cpumodel[0] != '\0') + hwloc_obj_add_info(topology->levels[0][0], "CPUModel", cpumodel); + + if (hwloc_get_sysctlbyname("hw.l1dcachesize", &l1dcachesize)) + l1dcachesize = 0; + + if (hwloc_get_sysctlbyname("hw.l1icachesize", &l1icachesize)) + l1icachesize = 0; + + if (hwloc_get_sysctlbyname("hw.l2cachesize", &l2cachesize)) + l2cachesize = 0; + + if (hwloc_get_sysctlbyname("machdep.cpu.cache.L1_associativity", &cacheways[0])) + cacheways[0] = 0; + else if (cacheways[0] == 0xff) + cacheways[0] = -1; + + if (hwloc_get_sysctlbyname("machdep.cpu.cache.L2_associativity", &cacheways[1])) + cacheways[1] = 0; + else if (cacheways[1] == 0xff) + cacheways[1] = -1; + + if (hwloc_get_sysctlbyname("hw.cachelinesize", &cachelinesize)) + cachelinesize = 0; + + if (hwloc_get_sysctlbyname("hw.memsize", &memsize)) + memsize = 0; + + if (!sysctlbyname("hw.cacheconfig", NULL, &size, NULL, 0)) { + unsigned n = size / sizeof(uint32_t); + uint64_t *cacheconfig = NULL; + uint64_t *cachesize = NULL; + uint32_t *cacheconfig32 = NULL; + + cacheconfig = malloc(sizeof(uint64_t) * n); + if (NULL == cacheconfig) { + goto out; + } + cachesize = malloc(sizeof(uint64_t) * n); + if (NULL == cachesize) { + goto out; + } + cacheconfig32 = malloc(sizeof(uint32_t) * n); + if (NULL == cacheconfig32) { + goto out; + } + + if ((!sysctlbyname("hw.cacheconfig", cacheconfig, &size, NULL, 0))) { + /* Yeech. Darwin seemingly has changed from 32bit to 64bit integers for + * cacheconfig, with apparently no way for detection. Assume the machine + * won't have more than 4 billion cpus */ + if (cacheconfig[0] > 0xFFFFFFFFUL) { + memcpy(cacheconfig32, cacheconfig, size); + for (i = 0 ; i < size / sizeof(uint32_t); i++) + cacheconfig[i] = cacheconfig32[i]; + } + + memset(cachesize, 0, sizeof(uint64_t) * n); + size = sizeof(uint64_t) * n; + if (sysctlbyname("hw.cachesize", cachesize, &size, NULL, 0)) { + if (n > 0) + cachesize[0] = memsize; + if (n > 1) + cachesize[1] = l1dcachesize; + if (n > 2) + cachesize[2] = l2cachesize; + } + + hwloc_debug("%s", "caches"); + for (i = 0; i < n && cacheconfig[i]; i++) + hwloc_debug(" %"PRIu64"(%"PRIu64"kB)", cacheconfig[i], cachesize[i] / 1024); + + /* Now we know how many caches there are */ + n = i; + hwloc_debug("\n%u cache levels\n", n - 1); + + /* For each cache level (0 is memory) */ + for (i = 0; i < n; i++) { + /* cacheconfig tells us how many cpus share it, let's iterate on each cache */ + for (j = 0; j < (nprocs / cacheconfig[i]); j++) { + obj = hwloc_alloc_setup_object(i?HWLOC_OBJ_CACHE:HWLOC_OBJ_NUMANODE, j); + if (!i) { + obj->nodeset = hwloc_bitmap_alloc(); + hwloc_bitmap_set(obj->nodeset, j); + } + obj->cpuset = hwloc_bitmap_alloc(); + for (cpu = j*cacheconfig[i]; + cpu < ((j+1)*cacheconfig[i]); + cpu++) + hwloc_bitmap_set(obj->cpuset, cpu); + + if (i == 1 && l1icachesize) { + /* FIXME assuming that L1i and L1d are shared the same way. Darwin + * does not yet provide a way to know. */ + hwloc_obj_t l1i = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, j); + l1i->cpuset = hwloc_bitmap_dup(obj->cpuset); + hwloc_debug_1arg_bitmap("L1icache %u has cpuset %s\n", + j, l1i->cpuset); + l1i->attr->cache.depth = i; + l1i->attr->cache.size = l1icachesize; + l1i->attr->cache.linesize = cachelinesize; + l1i->attr->cache.associativity = 0; + l1i->attr->cache.type = HWLOC_OBJ_CACHE_INSTRUCTION; + + hwloc_insert_object_by_cpuset(topology, l1i); + } + if (i) { + hwloc_debug_2args_bitmap("L%ucache %u has cpuset %s\n", + i, j, obj->cpuset); + obj->attr->cache.depth = i; + obj->attr->cache.size = cachesize[i]; + obj->attr->cache.linesize = cachelinesize; + if (i <= sizeof(cacheways) / sizeof(cacheways[0])) + obj->attr->cache.associativity = cacheways[i-1]; + else + obj->attr->cache.associativity = 0; + if (i == 1 && l1icachesize) + obj->attr->cache.type = HWLOC_OBJ_CACHE_DATA; + else + obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED; + } else { + hwloc_debug_1arg_bitmap("node %u has cpuset %s\n", + j, obj->cpuset); + obj->memory.local_memory = cachesize[i]; + 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(); +#ifdef HAVE__SC_LARGE_PAGESIZE + obj->memory.page_types[1].size = sysconf(_SC_LARGE_PAGESIZE); +#endif + } + + hwloc_insert_object_by_cpuset(topology, obj); + } + } + } + out: + if (NULL != cacheconfig) { + free(cacheconfig); + } + if (NULL != cachesize) { + free(cachesize); + } + if (NULL != cacheconfig32) { + free(cacheconfig32); + } + } + + + /* add PU objects */ + hwloc_setup_pu_level(topology, nprocs); + + hwloc_obj_add_info(topology->levels[0][0], "Backend", "Darwin"); + if (topology->is_thissystem) + hwloc_add_uname_info(topology, NULL); + return 1; +} + +void +hwloc_set_darwin_hooks(struct hwloc_binding_hooks *hooks __hwloc_attribute_unused, + struct hwloc_topology_support *support __hwloc_attribute_unused) +{ +} + +static struct hwloc_backend * +hwloc_darwin_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_darwin; + return backend; +} + +static struct hwloc_disc_component hwloc_darwin_disc_component = { + HWLOC_DISC_COMPONENT_TYPE_CPU, + "darwin", + HWLOC_DISC_COMPONENT_TYPE_GLOBAL, + hwloc_darwin_component_instantiate, + 50, + NULL +}; + +const struct hwloc_component hwloc_darwin_component = { + HWLOC_COMPONENT_ABI, + NULL, NULL, + HWLOC_COMPONENT_TYPE_DISC, + 0, + &hwloc_darwin_disc_component +}; diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/topology-fake.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-fake.c new file mode 100644 index 0000000000..e3e22a0a13 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-fake.c @@ -0,0 +1,61 @@ +/* + * Copyright © 2012-2014 Inria. All rights reserved. + * See COPYING in top-level directory. + */ + +#include +#include +#include + +#include + +static struct hwloc_backend * +hwloc_fake_component_instantiate(struct hwloc_disc_component *component __hwloc_attribute_unused, + const void *_data1 __hwloc_attribute_unused, + const void *_data2 __hwloc_attribute_unused, + const void *_data3 __hwloc_attribute_unused) +{ + if (getenv("HWLOC_DEBUG_FAKE_COMPONENT")) + printf("fake component instantiated\n"); + return NULL; +} + +static struct hwloc_disc_component hwloc_fake_disc_component = { + HWLOC_DISC_COMPONENT_TYPE_MISC, /* so that it's always enabled when using the OS discovery */ + "fake", + 0, /* nothing to exclude */ + hwloc_fake_component_instantiate, + 100, /* make sure it's loaded before anything conflicting excludes it */ + NULL +}; + +static int +hwloc_fake_component_init(unsigned long flags) +{ + if (flags) + return -1; + if (hwloc_plugin_check_namespace("fake", "hwloc_backend_alloc") < 0) + return -1; + if (getenv("HWLOC_DEBUG_FAKE_COMPONENT")) + printf("fake component initialized\n"); + return 0; +} + +static void +hwloc_fake_component_finalize(unsigned long flags) +{ + if (flags) + return; + if (getenv("HWLOC_DEBUG_FAKE_COMPONENT")) + printf("fake component finalized\n"); +} + +HWLOC_DECLSPEC extern const struct hwloc_component hwloc_fake_component; /* never linked statically in the core */ + +const struct hwloc_component hwloc_fake_component = { + HWLOC_COMPONENT_ABI, + hwloc_fake_component_init, hwloc_fake_component_finalize, + HWLOC_COMPONENT_TYPE_DISC, + 0, + &hwloc_fake_disc_component +}; diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/topology-freebsd.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-freebsd.c new file mode 100644 index 0000000000..4901209eee --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-freebsd.c @@ -0,0 +1,253 @@ +/* + * Copyright © 2009 CNRS + * Copyright © 2009-2014 Inria. All rights reserved. + * Copyright © 2009-2010, 2012 Université Bordeaux + * Copyright © 2011 Cisco Systems, Inc. All rights reserved. + * See COPYING in top-level directory. + */ + +#include + +#include +#include +#include +#include +#include +#ifdef HAVE_PTHREAD_NP_H +#include +#endif +#ifdef HAVE_SYS_CPUSET_H +#include +#endif +#ifdef HAVE_SYS_SYSCTL_H +#include +#endif + +#include +#include +#include + +#if defined(HAVE_SYS_CPUSET_H) && defined(HAVE_CPUSET_SETAFFINITY) +static void +hwloc_freebsd_bsd2hwloc(hwloc_bitmap_t hwloc_cpuset, const cpuset_t *cset) +{ + unsigned cpu; + hwloc_bitmap_zero(hwloc_cpuset); + for (cpu = 0; cpu < CPU_SETSIZE; cpu++) + if (CPU_ISSET(cpu, cset)) + hwloc_bitmap_set(hwloc_cpuset, cpu); +} + +static void +hwloc_freebsd_hwloc2bsd(hwloc_const_bitmap_t hwloc_cpuset, cpuset_t *cset) +{ + unsigned cpu; + CPU_ZERO(cset); + for (cpu = 0; cpu < CPU_SETSIZE; cpu++) + if (hwloc_bitmap_isset(hwloc_cpuset, cpu)) + CPU_SET(cpu, cset); +} + +static int +hwloc_freebsd_set_sth_affinity(hwloc_topology_t topology __hwloc_attribute_unused, cpulevel_t level, cpuwhich_t which, id_t id, hwloc_const_bitmap_t hwloc_cpuset, int flags __hwloc_attribute_unused) +{ + cpuset_t cset; + + hwloc_freebsd_hwloc2bsd(hwloc_cpuset, &cset); + + if (cpuset_setaffinity(level, which, id, sizeof(cset), &cset)) + return -1; + + return 0; +} + +static int +hwloc_freebsd_get_sth_affinity(hwloc_topology_t topology __hwloc_attribute_unused, cpulevel_t level, cpuwhich_t which, id_t id, hwloc_bitmap_t hwloc_cpuset, int flags __hwloc_attribute_unused) +{ + cpuset_t cset; + + if (cpuset_getaffinity(level, which, id, sizeof(cset), &cset)) + return -1; + + hwloc_freebsd_bsd2hwloc(hwloc_cpuset, &cset); + return 0; +} + +static int +hwloc_freebsd_set_thisproc_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_cpuset, int flags) +{ + return hwloc_freebsd_set_sth_affinity(topology, CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, hwloc_cpuset, flags); +} + +static int +hwloc_freebsd_get_thisproc_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_cpuset, int flags) +{ + return hwloc_freebsd_get_sth_affinity(topology, CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, hwloc_cpuset, flags); +} + +static int +hwloc_freebsd_set_thisthread_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_cpuset, int flags) +{ + return hwloc_freebsd_set_sth_affinity(topology, CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, hwloc_cpuset, flags); +} + +static int +hwloc_freebsd_get_thisthread_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_cpuset, int flags) +{ + return hwloc_freebsd_get_sth_affinity(topology, CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, hwloc_cpuset, flags); +} + +static int +hwloc_freebsd_set_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_bitmap_t hwloc_cpuset, int flags) +{ + return hwloc_freebsd_set_sth_affinity(topology, CPU_LEVEL_WHICH, CPU_WHICH_PID, pid, hwloc_cpuset, flags); +} + +static int +hwloc_freebsd_get_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_bitmap_t hwloc_cpuset, int flags) +{ + return hwloc_freebsd_get_sth_affinity(topology, CPU_LEVEL_WHICH, CPU_WHICH_PID, pid, hwloc_cpuset, flags); +} + +#ifdef hwloc_thread_t + +#if HAVE_DECL_PTHREAD_SETAFFINITY_NP +#pragma weak pthread_setaffinity_np +static int +hwloc_freebsd_set_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_thread_t tid, hwloc_const_bitmap_t hwloc_cpuset, int flags __hwloc_attribute_unused) +{ + int err; + cpuset_t cset; + + if (!pthread_setaffinity_np) { + errno = ENOSYS; + return -1; + } + + hwloc_freebsd_hwloc2bsd(hwloc_cpuset, &cset); + + err = pthread_setaffinity_np(tid, sizeof(cset), &cset); + + if (err) { + errno = err; + return -1; + } + + return 0; +} +#endif + +#if HAVE_DECL_PTHREAD_GETAFFINITY_NP +#pragma weak pthread_getaffinity_np +static int +hwloc_freebsd_get_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_thread_t tid, hwloc_bitmap_t hwloc_cpuset, int flags __hwloc_attribute_unused) +{ + int err; + cpuset_t cset; + + if (!pthread_getaffinity_np) { + errno = ENOSYS; + return -1; + } + + err = pthread_getaffinity_np(tid, sizeof(cset), &cset); + + if (err) { + errno = err; + return -1; + } + + hwloc_freebsd_bsd2hwloc(hwloc_cpuset, &cset); + return 0; +} +#endif +#endif +#endif + +#if (defined HAVE_SYSCTL) && (defined HAVE_SYS_SYSCTL_H) +static void +hwloc_freebsd_node_meminfo_info(struct hwloc_topology *topology) +{ + int mib[2] = { CTL_HW, HW_PHYSMEM }; + unsigned long physmem; + size_t len = sizeof(physmem); + sysctl(mib, 2, &physmem, &len, NULL, 0); + topology->levels[0][0]->memory.local_memory = physmem; +} +#endif + +static int +hwloc_look_freebsd(struct hwloc_backend *backend) +{ + struct hwloc_topology *topology = backend->topology; + unsigned nbprocs = hwloc_fallback_nbprocessors(topology); + + if (!topology->levels[0][0]->cpuset) { + /* Nobody (even the x86 backend) created objects yet, setup basic objects */ + hwloc_alloc_obj_cpusets(topology->levels[0][0]); + hwloc_setup_pu_level(topology, nbprocs); + } + + /* Add FreeBSD specific information */ +#if (defined HAVE_SYSCTL) && (defined HAVE_SYS_SYSCTL_H) + hwloc_freebsd_node_meminfo_info(topology); +#endif + hwloc_obj_add_info(topology->levels[0][0], "Backend", "FreeBSD"); + if (topology->is_thissystem) + hwloc_add_uname_info(topology, NULL); + return 1; +} + +void +hwloc_set_freebsd_hooks(struct hwloc_binding_hooks *hooks __hwloc_attribute_unused, + struct hwloc_topology_support *support __hwloc_attribute_unused) +{ +#if defined(HAVE_SYS_CPUSET_H) && defined(HAVE_CPUSET_SETAFFINITY) + hooks->set_thisproc_cpubind = hwloc_freebsd_set_thisproc_cpubind; + hooks->get_thisproc_cpubind = hwloc_freebsd_get_thisproc_cpubind; + hooks->set_thisthread_cpubind = hwloc_freebsd_set_thisthread_cpubind; + hooks->get_thisthread_cpubind = hwloc_freebsd_get_thisthread_cpubind; + hooks->set_proc_cpubind = hwloc_freebsd_set_proc_cpubind; + hooks->get_proc_cpubind = hwloc_freebsd_get_proc_cpubind; +#ifdef hwloc_thread_t +#if HAVE_DECL_PTHREAD_SETAFFINITY_NP + hooks->set_thread_cpubind = hwloc_freebsd_set_thread_cpubind; +#endif +#if HAVE_DECL_PTHREAD_GETAFFINITY_NP + hooks->get_thread_cpubind = hwloc_freebsd_get_thread_cpubind; +#endif +#endif +#endif + /* TODO: get_last_cpu_location: find out ki_lastcpu */ +} + +static struct hwloc_backend * +hwloc_freebsd_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_freebsd; + return backend; +} + +static struct hwloc_disc_component hwloc_freebsd_disc_component = { + HWLOC_DISC_COMPONENT_TYPE_CPU, + "freebsd", + HWLOC_DISC_COMPONENT_TYPE_GLOBAL, + hwloc_freebsd_component_instantiate, + 50, + NULL +}; + +const struct hwloc_component hwloc_freebsd_component = { + HWLOC_COMPONENT_ABI, + NULL, NULL, + HWLOC_COMPONENT_TYPE_DISC, + 0, + &hwloc_freebsd_disc_component +}; diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/topology-gl.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-gl.c new file mode 100644 index 0000000000..45e9e2dff6 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-gl.c @@ -0,0 +1,271 @@ +/* + * Copyright © 2012-2013 Blue Brain Project, BBP/EPFL. All rights reserved. + * 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 +#include +#include +#include +#include + +#define HWLOC_GL_SERVER_MAX 10 +#define HWLOC_GL_SCREEN_MAX 10 +struct hwloc_gl_backend_data_s { + unsigned nr_display; + struct hwloc_gl_display_info_s { + char name[10]; + unsigned port, device; + unsigned pcidomain, pcibus, pcidevice, pcifunc; + char *productname; + } display[HWLOC_GL_SERVER_MAX*HWLOC_GL_SCREEN_MAX]; +}; + +static void +hwloc_gl_query_devices(struct hwloc_gl_backend_data_s *data) +{ + int err; + unsigned i,j; + + /* mark the number of display as 0 in case we fail below, + * so that we don't try again later. + */ + data->nr_display = 0; + + for (i = 0; i < HWLOC_GL_SERVER_MAX; ++i) { + Display* display; + char displayName[10]; + int opcode, event, error; + + /* open X server */ + snprintf(displayName, sizeof(displayName), ":%u", i); + display = XOpenDisplay(displayName); + if (!display) + continue; + + /* Check for NV-CONTROL extension (it's per server) */ + if(!XQueryExtension(display, "NV-CONTROL", &opcode, &event, &error)) { + XCloseDisplay(display); + continue; + } + + for (j = 0; j < (unsigned) ScreenCount(display) && j < HWLOC_GL_SCREEN_MAX; j++) { + struct hwloc_gl_display_info_s *info = &data->display[data->nr_display]; + const int screen = j; + unsigned int *ptr_binary_data; + int data_length; + int gpu_number; + int nv_ctrl_pci_bus; + int nv_ctrl_pci_device; + int nv_ctrl_pci_domain; + int nv_ctrl_pci_func; + char *productname; + + /* the server supports NV-CONTROL but it may contain non-NVIDIA screen that don't support it */ + if (!XNVCTRLIsNvScreen(display, screen)) + continue; + + /* Gets the GPU number attached to the default screen. */ + /* For further details, see the */ + err = XNVCTRLQueryTargetBinaryData (display, NV_CTRL_TARGET_TYPE_X_SCREEN, screen, 0, + NV_CTRL_BINARY_DATA_GPUS_USED_BY_XSCREEN, + (unsigned char **) &ptr_binary_data, &data_length); + if (!err) + continue; + + gpu_number = ptr_binary_data[1]; + free(ptr_binary_data); + +#ifdef NV_CTRL_PCI_DOMAIN + /* Gets the ID's of the GPU defined by gpu_number + * For further details, see the */ + err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, + NV_CTRL_PCI_DOMAIN, &nv_ctrl_pci_domain); + if (!err) + continue; +#else + nv_ctrl_pci_domain = 0; +#endif + + err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, + NV_CTRL_PCI_BUS, &nv_ctrl_pci_bus); + if (!err) + continue; + + err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, + NV_CTRL_PCI_DEVICE, &nv_ctrl_pci_device); + if (!err) + continue; + + err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, + NV_CTRL_PCI_FUNCTION, &nv_ctrl_pci_func); + if (!err) + continue; + + productname = NULL; + err = XNVCTRLQueryTargetStringAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0, + NV_CTRL_STRING_PRODUCT_NAME, &productname); + + snprintf(info->name, sizeof(info->name), ":%u.%u", i, j); + info->port = i; + info->device = j; + info->pcidomain = nv_ctrl_pci_domain; + info->pcibus = nv_ctrl_pci_bus; + info->pcidevice = nv_ctrl_pci_device; + info->pcifunc = nv_ctrl_pci_func; + info->productname = productname; + + hwloc_debug("GL device %s (product %s) on PCI 0000:%02x:%02x.%u\n", info->name, productname, + nv_ctrl_pci_domain, nv_ctrl_pci_bus, nv_ctrl_pci_device, nv_ctrl_pci_func); + + /* validate this device */ + data->nr_display++; + } + XCloseDisplay(display); + } +} + +static int +hwloc_gl_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_gl_backend_data_s *data = backend->private_data; + unsigned i, res; + + 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 GL detection (not thissystem)\n"); + return 0; + } + + if (HWLOC_OBJ_PCI_DEVICE != pcidev->type) + return 0; + + if (data->nr_display == (unsigned) -1) { + /* first call, lookup all display */ + hwloc_gl_query_devices(data); + /* if it fails, data->nr_display = 0 so we won't do anything below and in next callbacks */ + } + + if (!data->nr_display) + /* found no display */ + return 0; + + /* now the display array is ready to use */ + res = 0; + for(i=0; inr_display; i++) { + struct hwloc_gl_display_info_s *info = &data->display[i]; + hwloc_obj_t osdev; + + if (info->pcidomain != pcidev->attr->pcidev.domain) + continue; + if (info->pcibus != pcidev->attr->pcidev.bus) + continue; + if (info->pcidevice != pcidev->attr->pcidev.dev) + continue; + if (info->pcifunc != pcidev->attr->pcidev.func) + continue; + + osdev = hwloc_alloc_setup_object(HWLOC_OBJ_OS_DEVICE, -1); + osdev->name = strdup(info->name); + osdev->logical_index = -1; + osdev->attr->osdev.type = HWLOC_OBJ_OSDEV_GPU; + hwloc_obj_add_info(osdev, "Backend", "GL"); + hwloc_obj_add_info(osdev, "GPUVendor", "NVIDIA Corporation"); + if (info->productname) + hwloc_obj_add_info(osdev, "GPUModel", info->productname); + hwloc_insert_object_by_parent(topology, pcidev, osdev); + + res++; + /* there may be others */ + } + + return res; +} + +static void +hwloc_gl_backend_disable(struct hwloc_backend *backend) +{ + struct hwloc_gl_backend_data_s *data = backend->private_data; + unsigned i; + if (data->nr_display != (unsigned) -1) { /* could be -1 if --no-io */ + for(i=0; inr_display; i++) { + struct hwloc_gl_display_info_s *info = &data->display[i]; + free(info->productname); + } + } + free(backend->private_data); +} + +static struct hwloc_backend * +hwloc_gl_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_gl_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_display = (unsigned) -1; /* unknown yet */ + + backend->private_data = data; + backend->disable = hwloc_gl_backend_disable; + + backend->notify_new_object = hwloc_gl_backend_notify_new_object; + return backend; +} + +static struct hwloc_disc_component hwloc_gl_disc_component = { + HWLOC_DISC_COMPONENT_TYPE_MISC, + "gl", + HWLOC_DISC_COMPONENT_TYPE_GLOBAL, + hwloc_gl_component_instantiate, + 10, /* after pci */ + NULL +}; + +static int +hwloc_gl_component_init(unsigned long flags) +{ + if (flags) + return -1; + if (hwloc_plugin_check_namespace("gl", "hwloc_backend_alloc") < 0) + return -1; + return 0; +} + +#ifdef HWLOC_INSIDE_PLUGIN +HWLOC_DECLSPEC extern const struct hwloc_component hwloc_gl_component; +#endif + +const struct hwloc_component hwloc_gl_component = { + HWLOC_COMPONENT_ABI, + hwloc_gl_component_init, NULL, + HWLOC_COMPONENT_TYPE_DISC, + 0, + &hwloc_gl_disc_component +}; diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/topology-hpux.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-hpux.c new file mode 100644 index 0000000000..44a4a4c41a --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-hpux.c @@ -0,0 +1,311 @@ +/* + * Copyright © 2009 CNRS + * Copyright © 2009-2014 Inria. All rights reserved. + * Copyright © 2009-2010, 2013 Université Bordeaux + * Copyright © 2011 Cisco Systems, Inc. All rights reserved. + * See COPYING in top-level directory. + */ + +/* TODO: psets? (Only for root) + * since 11i 1.6: + _SC_PSET_SUPPORT + pset_create/destroy/assign/setattr + pset_ctl/getattr + pset_bind() + pthread_pset_bind_np() + */ + +#include + +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +static ldom_t +hwloc_hpux_find_ldom(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set) +{ + int has_numa = sysconf(_SC_CCNUMA_SUPPORT) == 1; + hwloc_obj_t obj; + + if (!has_numa) + return -1; + + obj = hwloc_get_first_largest_obj_inside_cpuset(topology, hwloc_set); + if (!hwloc_bitmap_isequal(obj->cpuset, hwloc_set)) + /* Does not correspond to exactly one node */ + return -1; + /* obj is the highest possibly matching object, but some (single) child (with same cpuset) could match too */ + while (obj->type != HWLOC_OBJ_NUMANODE) { + /* try the first child, in case it has the same cpuset */ + if (!obj->first_child + || !obj->first_child->cpuset + || !hwloc_bitmap_isequal(obj->cpuset, obj->first_child->cpuset)) + return -1; + obj = obj->first_child; + } + + return obj->os_index; +} + +static spu_t +hwloc_hpux_find_spu(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_const_bitmap_t hwloc_set) +{ + spu_t cpu; + + cpu = hwloc_bitmap_first(hwloc_set); + if (cpu != -1 && hwloc_bitmap_weight(hwloc_set) == 1) + return cpu; + return -1; +} + +/* Note: get_cpubind not available on HP-UX */ +static int +hwloc_hpux_set_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_bitmap_t hwloc_set, int flags) +{ + ldom_t ldom; + spu_t cpu; + + /* Drop previous binding */ + mpctl(MPC_SETLDOM, MPC_LDOMFLOAT, pid); + mpctl(MPC_SETPROCESS, MPC_SPUFLOAT, pid); + + if (hwloc_bitmap_isequal(hwloc_set, hwloc_topology_get_complete_cpuset(topology))) + return 0; + + ldom = hwloc_hpux_find_ldom(topology, hwloc_set); + if (ldom != -1) + return mpctl(MPC_SETLDOM, ldom, pid); + + cpu = hwloc_hpux_find_spu(topology, hwloc_set); + if (cpu != -1) + return mpctl(flags & HWLOC_CPUBIND_STRICT ? MPC_SETPROCESS_FORCE : MPC_SETPROCESS, cpu, pid); + + errno = EXDEV; + return -1; +} + +static int +hwloc_hpux_set_thisproc_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags) +{ + return hwloc_hpux_set_proc_cpubind(topology, MPC_SELFPID, hwloc_set, flags); +} + +#ifdef hwloc_thread_t +static int +hwloc_hpux_set_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t pthread, hwloc_const_bitmap_t hwloc_set, int flags) +{ + ldom_t ldom, ldom2; + spu_t cpu, cpu2; + + /* Drop previous binding */ + pthread_ldom_bind_np(&ldom2, PTHREAD_LDOMFLOAT_NP, pthread); + pthread_processor_bind_np(PTHREAD_BIND_ADVISORY_NP, &cpu2, PTHREAD_SPUFLOAT_NP, pthread); + + if (hwloc_bitmap_isequal(hwloc_set, hwloc_topology_get_complete_cpuset(topology))) + return 0; + + ldom = hwloc_hpux_find_ldom(topology, hwloc_set); + if (ldom != -1) + return pthread_ldom_bind_np(&ldom2, ldom, pthread); + + cpu = hwloc_hpux_find_spu(topology, hwloc_set); + if (cpu != -1) + return pthread_processor_bind_np(flags & HWLOC_CPUBIND_STRICT ? PTHREAD_BIND_FORCED_NP : PTHREAD_BIND_ADVISORY_NP, &cpu2, cpu, pthread); + + errno = EXDEV; + return -1; +} + +static int +hwloc_hpux_set_thisthread_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags) +{ + return hwloc_hpux_set_thread_cpubind(topology, PTHREAD_SELFTID_NP, hwloc_set, flags); +} +#endif + +/* According to HP docs, HP-UX up to 11iv2 don't support migration */ + +#ifdef MAP_MEM_FIRST_TOUCH +static void* +hwloc_hpux_alloc_membind(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) +{ + int mmap_flags; + + /* Can not give a set of nodes. */ + if (!hwloc_bitmap_isequal(nodeset, hwloc_topology_get_complete_nodeset(topology))) { + errno = EXDEV; + return hwloc_alloc_or_fail(topology, len, flags); + } + + switch (policy) { + case HWLOC_MEMBIND_DEFAULT: + case HWLOC_MEMBIND_BIND: + mmap_flags = 0; + break; + case HWLOC_MEMBIND_FIRSTTOUCH: + mmap_flags = MAP_MEM_FIRST_TOUCH; + break; + case HWLOC_MEMBIND_INTERLEAVE: + mmap_flags = MAP_MEM_INTERLEAVED; + break; + default: + errno = ENOSYS; + return NULL; + } + + return mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | mmap_flags, -1, 0); +} +#endif /* MAP_MEM_FIRST_TOUCH */ + +static int +hwloc_look_hpux(struct hwloc_backend *backend) +{ + struct hwloc_topology *topology = backend->topology; + int has_numa = sysconf(_SC_CCNUMA_SUPPORT) == 1; + hwloc_obj_t *nodes = NULL, obj; + spu_t currentcpu; + ldom_t currentnode; + int i, nbnodes = 0; + + if (topology->levels[0][0]->cpuset) + /* somebody discovered things */ + return 0; + + hwloc_alloc_obj_cpusets(topology->levels[0][0]); + + if (has_numa) { + nbnodes = mpctl(topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM ? + MPC_GETNUMLDOMS_SYS : MPC_GETNUMLDOMS, 0, 0); + + hwloc_debug("%d nodes\n", nbnodes); + + nodes = malloc(nbnodes * sizeof(*nodes)); + + i = 0; + currentnode = mpctl(topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM ? + MPC_GETFIRSTLDOM_SYS : MPC_GETFIRSTLDOM, 0, 0); + while (currentnode != -1 && i < nbnodes) { + hwloc_debug("node %d is %d\n", i, currentnode); + nodes[i] = obj = hwloc_alloc_setup_object(HWLOC_OBJ_NUMANODE, currentnode); + obj->cpuset = hwloc_bitmap_alloc(); + obj->nodeset = hwloc_bitmap_alloc(); + hwloc_bitmap_set(obj->nodeset, currentnode); + /* TODO: obj->attr->node.memory_kB */ + /* TODO: obj->attr->node.huge_page_free */ + + currentnode = mpctl(topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM ? + MPC_GETNEXTLDOM_SYS : MPC_GETNEXTLDOM, currentnode, 0); + i++; + } + } + + i = 0; + currentcpu = mpctl(topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM ? + MPC_GETFIRSTSPU_SYS : MPC_GETFIRSTSPU, 0,0); + while (currentcpu != -1) { + obj = hwloc_alloc_setup_object(HWLOC_OBJ_PU, currentcpu); + obj->cpuset = hwloc_bitmap_alloc(); + hwloc_bitmap_set(obj->cpuset, currentcpu); + + hwloc_debug("cpu %d\n", currentcpu); + + if (nodes) { + /* Add this cpu to its node */ + currentnode = mpctl(MPC_SPUTOLDOM, currentcpu, 0); + /* Hopefully it's just the same as previous cpu */ + if (i >= nbnodes || (ldom_t) nodes[i]->os_index != currentnode) + for (i = 0; i < nbnodes; i++) + if ((ldom_t) nodes[i]->os_index == currentnode) + break; + if (i < nbnodes) { + hwloc_bitmap_set(nodes[i]->cpuset, currentcpu); + hwloc_debug("is in node %d\n", i); + } else { + hwloc_debug("%s", "is in no node?!\n"); + } + } + + /* Add cpu */ + hwloc_insert_object_by_cpuset(topology, obj); + + currentcpu = mpctl(topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM ? + MPC_GETNEXTSPU_SYS : MPC_GETNEXTSPU, currentcpu, 0); + } + + if (nodes) { + /* Add nodes */ + for (i = 0 ; i < nbnodes ; i++) + hwloc_insert_object_by_cpuset(topology, nodes[i]); + free(nodes); + } + + topology->support.discovery->pu = 1; + + hwloc_obj_add_info(topology->levels[0][0], "Backend", "HP-UX"); + if (topology->is_thissystem) + hwloc_add_uname_info(topology, NULL); + return 1; +} + +void +hwloc_set_hpux_hooks(struct hwloc_binding_hooks *hooks, + struct hwloc_topology_support *support __hwloc_attribute_unused) +{ + hooks->set_proc_cpubind = hwloc_hpux_set_proc_cpubind; + hooks->set_thisproc_cpubind = hwloc_hpux_set_thisproc_cpubind; +#ifdef hwloc_thread_t + hooks->set_thread_cpubind = hwloc_hpux_set_thread_cpubind; + hooks->set_thisthread_cpubind = hwloc_hpux_set_thisthread_cpubind; +#endif +#ifdef MAP_MEM_FIRST_TOUCH + hooks->alloc_membind = hwloc_hpux_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; +#endif /* MAP_MEM_FIRST_TOUCH */ +} + +static struct hwloc_backend * +hwloc_hpux_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_hpux; + return backend; +} + +static struct hwloc_disc_component hwloc_hpux_disc_component = { + HWLOC_DISC_COMPONENT_TYPE_CPU, + "hpux", + HWLOC_DISC_COMPONENT_TYPE_GLOBAL, + hwloc_hpux_component_instantiate, + 50, + NULL +}; + +const struct hwloc_component hwloc_hpux_component = { + HWLOC_COMPONENT_ABI, + NULL, NULL, + HWLOC_COMPONENT_TYPE_DISC, + 0, + &hwloc_hpux_disc_component +}; diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/topology-linux.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-linux.c new file mode 100644 index 0000000000..2d9d4da9cd --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-linux.c @@ -0,0 +1,5229 @@ +/* + * Copyright © 2009 CNRS + * Copyright © 2009-2015 Inria. All rights reserved. + * Copyright © 2009-2013 Université Bordeaux + * Copyright © 2009-2014 Cisco Systems, Inc. All rights reserved. + * Copyright © 2015 Intel, Inc. All rights reserved. + * Copyright © 2010 IBM + * See COPYING in top-level directory. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#ifdef HAVE_DIRENT_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_LIBUDEV_H +#include +#endif +#include +#include +#include +#include +#include +#include +#if defined HWLOC_HAVE_SET_MEMPOLICY || defined HWLOC_HAVE_MBIND +#define migratepages migrate_pages /* workaround broken migratepages prototype in numaif.h before libnuma 2.0.2 */ +#include +#endif + +struct hwloc_linux_backend_data_s { + int root_fd; /* The file descriptor for the file system root, used when browsing, e.g., Linux' sysfs and procfs. */ + int is_real_fsroot; /* Boolean saying whether root_fd points to the real filesystem root of the system */ +#ifdef HAVE_LIBUDEV_H + struct udev *udev; /* Global udev context */ +#endif + + struct utsname utsname; /* fields contain \0 when unknown */ + + int deprecated_classlinks_model; /* -2 if never tried, -1 if unknown, 0 if new (device contains class/name), 1 if old (device contains class:name) */ + int mic_need_directlookup; /* if not tried yet, 0 if not needed, 1 if needed */ + unsigned mic_directlookup_id_max; /* -1 if not tried yet, 0 if none to lookup, maxid+1 otherwise */ +}; + + + +/*************************** + * Misc Abstraction layers * + ***************************/ + +#if !(defined HWLOC_HAVE_SCHED_SETAFFINITY) && (defined HWLOC_HAVE__SYSCALL3) +/* libc doesn't have support for sched_setaffinity, build system call + * ourselves: */ +# include +# ifndef __NR_sched_setaffinity +# ifdef __i386__ +# define __NR_sched_setaffinity 241 +# elif defined(__x86_64__) +# define __NR_sched_setaffinity 203 +# elif defined(__ia64__) +# define __NR_sched_setaffinity 1231 +# elif defined(__hppa__) +# define __NR_sched_setaffinity 211 +# elif defined(__alpha__) +# define __NR_sched_setaffinity 395 +# elif defined(__s390__) +# define __NR_sched_setaffinity 239 +# elif defined(__sparc__) +# define __NR_sched_setaffinity 261 +# elif defined(__m68k__) +# define __NR_sched_setaffinity 311 +# elif defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) || defined(__powerpc64__) || defined(__ppc64__) +# define __NR_sched_setaffinity 222 +# elif defined(__arm__) +# define __NR_sched_setaffinity 241 +# elif defined(__cris__) +# define __NR_sched_setaffinity 241 +/*# elif defined(__mips__) + # define __NR_sched_setaffinity TODO (32/64/nabi) */ +# else +# warning "don't know the syscall number for sched_setaffinity on this architecture, will not support binding" +# define sched_setaffinity(pid, lg, mask) (errno = ENOSYS, -1) +# endif +# endif +# ifndef sched_setaffinity + _syscall3(int, sched_setaffinity, pid_t, pid, unsigned int, lg, const void *, mask) +# endif +# ifndef __NR_sched_getaffinity +# ifdef __i386__ +# define __NR_sched_getaffinity 242 +# elif defined(__x86_64__) +# define __NR_sched_getaffinity 204 +# elif defined(__ia64__) +# define __NR_sched_getaffinity 1232 +# elif defined(__hppa__) +# define __NR_sched_getaffinity 212 +# elif defined(__alpha__) +# define __NR_sched_getaffinity 396 +# elif defined(__s390__) +# define __NR_sched_getaffinity 240 +# elif defined(__sparc__) +# define __NR_sched_getaffinity 260 +# elif defined(__m68k__) +# define __NR_sched_getaffinity 312 +# elif defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) || defined(__powerpc64__) || defined(__ppc64__) +# define __NR_sched_getaffinity 223 +# elif defined(__arm__) +# define __NR_sched_getaffinity 242 +# elif defined(__cris__) +# define __NR_sched_getaffinity 242 +/*# elif defined(__mips__) + # define __NR_sched_getaffinity TODO (32/64/nabi) */ +# else +# warning "don't know the syscall number for sched_getaffinity on this architecture, will not support getting binding" +# define sched_getaffinity(pid, lg, mask) (errno = ENOSYS, -1) +# endif +# endif +# ifndef sched_getaffinity + _syscall3(int, sched_getaffinity, pid_t, pid, unsigned int, lg, void *, mask) +# endif +#endif + +/* Added for ntohl() */ +#include + +#ifdef HAVE_OPENAT +/* Use our own filesystem functions if we have openat */ + +static const char * +hwloc_checkat(const char *path, int fsroot_fd) +{ + const char *relative_path; + if (fsroot_fd < 0) { + errno = EBADF; + return NULL; + } + + /* Skip leading slashes. */ + for (relative_path = path; *relative_path == '/'; relative_path++); + + return relative_path; +} + +static int +hwloc_openat(const char *path, int fsroot_fd) +{ + const char *relative_path; + + relative_path = hwloc_checkat(path, fsroot_fd); + if (!relative_path) + return -1; + + return openat (fsroot_fd, relative_path, O_RDONLY); +} + +static FILE * +hwloc_fopenat(const char *path, const char *mode, int fsroot_fd) +{ + int fd; + + if (strcmp(mode, "r")) { + errno = ENOTSUP; + return NULL; + } + + fd = hwloc_openat (path, fsroot_fd); + if (fd == -1) + return NULL; + + return fdopen(fd, mode); +} + +static int +hwloc_accessat(const char *path, int mode, int fsroot_fd) +{ + const char *relative_path; + + relative_path = hwloc_checkat(path, fsroot_fd); + if (!relative_path) + return -1; + + return faccessat(fsroot_fd, relative_path, mode, 0); +} + +static int +hwloc_fstatat(const char *path, struct stat *st, int flags, int fsroot_fd) +{ + const char *relative_path; + + relative_path = hwloc_checkat(path, fsroot_fd); + if (!relative_path) + return -1; + + return fstatat(fsroot_fd, relative_path, st, flags); +} + +static DIR* +hwloc_opendirat(const char *path, int fsroot_fd) +{ + int dir_fd; + const char *relative_path; + + relative_path = hwloc_checkat(path, fsroot_fd); + if (!relative_path) + return NULL; + + dir_fd = openat(fsroot_fd, relative_path, O_RDONLY | O_DIRECTORY); + if (dir_fd < 0) + return NULL; + + return fdopendir(dir_fd); +} + +#endif /* HAVE_OPENAT */ + +/* Static inline version of fopen so that we can use openat if we have + it, but still preserve compiler parameter checking */ +static __hwloc_inline int +hwloc_open(const char *p, int d __hwloc_attribute_unused) +{ +#ifdef HAVE_OPENAT + return hwloc_openat(p, d); +#else + return open(p, O_RDONLY); +#endif +} + +static __hwloc_inline FILE * +hwloc_fopen(const char *p, const char *m, int d __hwloc_attribute_unused) +{ +#ifdef HAVE_OPENAT + return hwloc_fopenat(p, m, d); +#else + return fopen(p, m); +#endif +} + +/* Static inline version of access so that we can use openat if we have + it, but still preserve compiler parameter checking */ +static __hwloc_inline int +hwloc_access(const char *p, int m, int d __hwloc_attribute_unused) +{ +#ifdef HAVE_OPENAT + return hwloc_accessat(p, m, d); +#else + return access(p, m); +#endif +} + +static __hwloc_inline int +hwloc_stat(const char *p, struct stat *st, int d __hwloc_attribute_unused) +{ +#ifdef HAVE_OPENAT + return hwloc_fstatat(p, st, 0, d); +#else + return stat(p, st); +#endif +} + +static __hwloc_inline int +hwloc_lstat(const char *p, struct stat *st, int d __hwloc_attribute_unused) +{ +#ifdef HAVE_OPENAT + return hwloc_fstatat(p, st, AT_SYMLINK_NOFOLLOW, d); +#else + return lstat(p, st); +#endif +} + +/* Static inline version of opendir so that we can use openat if we have + it, but still preserve compiler parameter checking */ +static __hwloc_inline DIR * +hwloc_opendir(const char *p, int d __hwloc_attribute_unused) +{ +#ifdef HAVE_OPENAT + return hwloc_opendirat(p, d); +#else + return opendir(p); +#endif +} + + +/***************************** + ******* CpuBind Hooks ******* + *****************************/ + +int +hwloc_linux_set_tid_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, pid_t tid __hwloc_attribute_unused, hwloc_const_bitmap_t hwloc_set __hwloc_attribute_unused) +{ + /* TODO Kerrighed: Use + * int migrate (pid_t pid, int destination_node); + * int migrate_self (int destination_node); + * int thread_migrate (int thread_id, int destination_node); + */ + + /* The resulting binding is always strict */ + +#if defined(HWLOC_HAVE_CPU_SET_S) && !defined(HWLOC_HAVE_OLD_SCHED_SETAFFINITY) + cpu_set_t *plinux_set; + unsigned cpu; + int last; + size_t setsize; + int err; + + last = hwloc_bitmap_last(hwloc_set); + if (last == -1) { + errno = EINVAL; + return -1; + } + + setsize = CPU_ALLOC_SIZE(last+1); + plinux_set = CPU_ALLOC(last+1); + + CPU_ZERO_S(setsize, plinux_set); + hwloc_bitmap_foreach_begin(cpu, hwloc_set) + CPU_SET_S(cpu, setsize, plinux_set); + hwloc_bitmap_foreach_end(); + + err = sched_setaffinity(tid, setsize, plinux_set); + + CPU_FREE(plinux_set); + return err; +#elif defined(HWLOC_HAVE_CPU_SET) + cpu_set_t linux_set; + unsigned cpu; + + CPU_ZERO(&linux_set); + hwloc_bitmap_foreach_begin(cpu, hwloc_set) + CPU_SET(cpu, &linux_set); + hwloc_bitmap_foreach_end(); + +#ifdef HWLOC_HAVE_OLD_SCHED_SETAFFINITY + return sched_setaffinity(tid, &linux_set); +#else /* HWLOC_HAVE_OLD_SCHED_SETAFFINITY */ + return sched_setaffinity(tid, sizeof(linux_set), &linux_set); +#endif /* HWLOC_HAVE_OLD_SCHED_SETAFFINITY */ +#elif defined(HWLOC_HAVE__SYSCALL3) + unsigned long mask = hwloc_bitmap_to_ulong(hwloc_set); + +#ifdef HWLOC_HAVE_OLD_SCHED_SETAFFINITY + return sched_setaffinity(tid, (void*) &mask); +#else /* HWLOC_HAVE_OLD_SCHED_SETAFFINITY */ + return sched_setaffinity(tid, sizeof(mask), (void*) &mask); +#endif /* HWLOC_HAVE_OLD_SCHED_SETAFFINITY */ +#else /* !_SYSCALL3 */ + errno = ENOSYS; + return -1; +#endif /* !_SYSCALL3 */ +} + +#if defined(HWLOC_HAVE_CPU_SET_S) && !defined(HWLOC_HAVE_OLD_SCHED_SETAFFINITY) +static int +hwloc_linux_parse_cpuset_file(FILE *file, hwloc_bitmap_t set) +{ + unsigned long start, stop; + + /* reset to zero first */ + hwloc_bitmap_zero(set); + + while (fscanf(file, "%lu", &start) == 1) + { + int c = fgetc(file); + + stop = start; + + if (c == '-') { + /* Range */ + if (fscanf(file, "%lu", &stop) != 1) { + /* Expected a number here */ + errno = EINVAL; + return -1; + } + c = fgetc(file); + } + + if (c == EOF || c == '\n') { + hwloc_bitmap_set_range(set, start, stop); + break; + } + + if (c != ',') { + /* Expected EOF, EOL, or a comma */ + errno = EINVAL; + return -1; + } + + hwloc_bitmap_set_range(set, start, stop); + } + + return 0; +} + +/* + * On some kernels, sched_getaffinity requires the output size to be larger + * than the kernel cpu_set size (defined by CONFIG_NR_CPUS). + * Try sched_affinity on ourself until we find a nr_cpus value that makes + * the kernel happy. + */ +static int +hwloc_linux_find_kernel_nr_cpus(hwloc_topology_t topology) +{ + static int _nr_cpus = -1; + int nr_cpus = _nr_cpus; + FILE *possible; + + if (nr_cpus != -1) + /* already computed */ + return nr_cpus; + + if (topology->levels[0][0]->complete_cpuset) + /* start with a nr_cpus that may contain the whole topology */ + nr_cpus = hwloc_bitmap_last(topology->levels[0][0]->complete_cpuset) + 1; + if (nr_cpus <= 0) + /* start from scratch, the topology isn't ready yet (complete_cpuset is missing (-1) or empty (0))*/ + nr_cpus = 1; + + possible = fopen("/sys/devices/system/cpu/possible", "r"); + if (possible) { + hwloc_bitmap_t possible_bitmap = hwloc_bitmap_alloc(); + if (hwloc_linux_parse_cpuset_file(possible, possible_bitmap) == 0) { + int max_possible = hwloc_bitmap_last(possible_bitmap); + + hwloc_debug_bitmap("possible CPUs are %s\n", possible_bitmap); + + if (nr_cpus < max_possible + 1) + nr_cpus = max_possible + 1; + } + fclose(possible); + hwloc_bitmap_free(possible_bitmap); + } + + while (1) { + cpu_set_t *set = CPU_ALLOC(nr_cpus); + size_t setsize = CPU_ALLOC_SIZE(nr_cpus); + int err = sched_getaffinity(0, setsize, set); /* always works, unless setsize is too small */ + CPU_FREE(set); + nr_cpus = setsize * 8; /* that's the value that was actually tested */ + if (!err) + /* found it */ + return _nr_cpus = nr_cpus; + nr_cpus *= 2; + } +} +#endif + +int +hwloc_linux_get_tid_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, pid_t tid __hwloc_attribute_unused, hwloc_bitmap_t hwloc_set __hwloc_attribute_unused) +{ + int err __hwloc_attribute_unused; + /* TODO Kerrighed */ + +#if defined(HWLOC_HAVE_CPU_SET_S) && !defined(HWLOC_HAVE_OLD_SCHED_SETAFFINITY) + cpu_set_t *plinux_set; + unsigned cpu; + int last; + size_t setsize; + int kernel_nr_cpus; + + /* find the kernel nr_cpus so as to use a large enough cpu_set size */ + kernel_nr_cpus = hwloc_linux_find_kernel_nr_cpus(topology); + setsize = CPU_ALLOC_SIZE(kernel_nr_cpus); + plinux_set = CPU_ALLOC(kernel_nr_cpus); + + err = sched_getaffinity(tid, setsize, plinux_set); + + if (err < 0) { + CPU_FREE(plinux_set); + return -1; + } + + last = -1; + if (topology->levels[0][0]->complete_cpuset) + last = hwloc_bitmap_last(topology->levels[0][0]->complete_cpuset); + if (last == -1) + /* round the maximal support number, the topology isn't ready yet (complete_cpuset is missing or empty)*/ + last = kernel_nr_cpus-1; + + hwloc_bitmap_zero(hwloc_set); + for(cpu=0; cpu<=(unsigned) last; cpu++) + if (CPU_ISSET_S(cpu, setsize, plinux_set)) + hwloc_bitmap_set(hwloc_set, cpu); + + CPU_FREE(plinux_set); +#elif defined(HWLOC_HAVE_CPU_SET) + cpu_set_t linux_set; + unsigned cpu; + +#ifdef HWLOC_HAVE_OLD_SCHED_SETAFFINITY + err = sched_getaffinity(tid, &linux_set); +#else /* HWLOC_HAVE_OLD_SCHED_SETAFFINITY */ + err = sched_getaffinity(tid, sizeof(linux_set), &linux_set); +#endif /* HWLOC_HAVE_OLD_SCHED_SETAFFINITY */ + if (err < 0) + return -1; + + hwloc_bitmap_zero(hwloc_set); + for(cpu=0; cpud_name, ".") || !strcmp(dirent->d_name, "..")) + continue; + tids[nr_tids++] = atoi(dirent->d_name); + } + + *nr_tidsp = nr_tids; + *tidsp = tids; + return 0; +} + +/* Per-tid callbacks */ +typedef int (*hwloc_linux_foreach_proc_tid_cb_t)(hwloc_topology_t topology, pid_t tid, void *data, int idx); + +static int +hwloc_linux_foreach_proc_tid(hwloc_topology_t topology, + pid_t pid, hwloc_linux_foreach_proc_tid_cb_t cb, + void *data) +{ + char taskdir_path[128]; + DIR *taskdir; + pid_t *tids, *newtids; + unsigned i, nr, newnr, failed = 0, failed_errno = 0; + unsigned retrynr = 0; + int err; + + if (pid) + snprintf(taskdir_path, sizeof(taskdir_path), "/proc/%u/task", (unsigned) pid); + else + snprintf(taskdir_path, sizeof(taskdir_path), "/proc/self/task"); + + taskdir = opendir(taskdir_path); + if (!taskdir) { + if (errno == ENOENT) + errno = EINVAL; + err = -1; + goto out; + } + + /* read the current list of threads */ + err = hwloc_linux_get_proc_tids(taskdir, &nr, &tids); + if (err < 0) + goto out_with_dir; + + retry: + /* apply the callback to all threads */ + failed=0; + for(i=0; i 10) { + /* we tried 10 times, it didn't work, the application is probably creating/destroying many threads, stop trying */ + errno = EAGAIN; + err = -1; + goto out_with_tids; + } + goto retry; + } else { + free(newtids); + } + + /* if all threads failed, return the last errno. */ + if (failed) { + err = -1; + errno = failed_errno; + goto out_with_tids; + } + + err = 0; + out_with_tids: + free(tids); + out_with_dir: + closedir(taskdir); + out: + return err; +} + +/* Per-tid proc_set_cpubind callback and caller. + * Callback data is a hwloc_bitmap_t. */ +static int +hwloc_linux_foreach_proc_tid_set_cpubind_cb(hwloc_topology_t topology, pid_t tid, void *data, int idx __hwloc_attribute_unused) +{ + return hwloc_linux_set_tid_cpubind(topology, tid, (hwloc_bitmap_t) data); +} + +static int +hwloc_linux_set_pid_cpubind(hwloc_topology_t topology, pid_t pid, hwloc_const_bitmap_t hwloc_set, int flags __hwloc_attribute_unused) +{ + return hwloc_linux_foreach_proc_tid(topology, pid, + hwloc_linux_foreach_proc_tid_set_cpubind_cb, + (void*) hwloc_set); +} + +/* Per-tid proc_get_cpubind callback data, callback function and caller */ +struct hwloc_linux_foreach_proc_tid_get_cpubind_cb_data_s { + hwloc_bitmap_t cpuset; + hwloc_bitmap_t tidset; + int flags; +}; + +static int +hwloc_linux_foreach_proc_tid_get_cpubind_cb(hwloc_topology_t topology, pid_t tid, void *_data, int idx) +{ + struct hwloc_linux_foreach_proc_tid_get_cpubind_cb_data_s *data = _data; + hwloc_bitmap_t cpuset = data->cpuset; + hwloc_bitmap_t tidset = data->tidset; + int flags = data->flags; + + if (hwloc_linux_get_tid_cpubind(topology, tid, tidset)) + return -1; + + /* reset the cpuset on first iteration */ + if (!idx) + hwloc_bitmap_zero(cpuset); + + if (flags & HWLOC_CPUBIND_STRICT) { + /* if STRICT, we want all threads to have the same binding */ + if (!idx) { + /* this is the first thread, copy its binding */ + hwloc_bitmap_copy(cpuset, tidset); + } else if (!hwloc_bitmap_isequal(cpuset, tidset)) { + /* this is not the first thread, and it's binding is different */ + errno = EXDEV; + return -1; + } + } else { + /* if not STRICT, just OR all thread bindings */ + hwloc_bitmap_or(cpuset, cpuset, tidset); + } + return 0; +} + +static int +hwloc_linux_get_pid_cpubind(hwloc_topology_t topology, pid_t pid, hwloc_bitmap_t hwloc_set, int flags) +{ + struct hwloc_linux_foreach_proc_tid_get_cpubind_cb_data_s data; + hwloc_bitmap_t tidset = hwloc_bitmap_alloc(); + int ret; + + data.cpuset = hwloc_set; + data.tidset = tidset; + data.flags = flags; + ret = hwloc_linux_foreach_proc_tid(topology, pid, + hwloc_linux_foreach_proc_tid_get_cpubind_cb, + (void*) &data); + hwloc_bitmap_free(tidset); + return ret; +} + +static int +hwloc_linux_set_proc_cpubind(hwloc_topology_t topology, pid_t pid, hwloc_const_bitmap_t hwloc_set, int flags) +{ + if (pid == 0) + pid = topology->pid; + if (flags & HWLOC_CPUBIND_THREAD) + return hwloc_linux_set_tid_cpubind(topology, pid, hwloc_set); + else + return hwloc_linux_set_pid_cpubind(topology, pid, hwloc_set, flags); +} + +static int +hwloc_linux_get_proc_cpubind(hwloc_topology_t topology, pid_t pid, hwloc_bitmap_t hwloc_set, int flags) +{ + if (pid == 0) + pid = topology->pid; + if (flags & HWLOC_CPUBIND_THREAD) + return hwloc_linux_get_tid_cpubind(topology, pid, hwloc_set); + else + return hwloc_linux_get_pid_cpubind(topology, pid, hwloc_set, flags); +} + +static int +hwloc_linux_set_thisproc_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags) +{ + return hwloc_linux_set_pid_cpubind(topology, topology->pid, hwloc_set, flags); +} + +static int +hwloc_linux_get_thisproc_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_set, int flags) +{ + return hwloc_linux_get_pid_cpubind(topology, topology->pid, hwloc_set, flags); +} + +static int +hwloc_linux_set_thisthread_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags __hwloc_attribute_unused) +{ + if (topology->pid) { + errno = ENOSYS; + return -1; + } + return hwloc_linux_set_tid_cpubind(topology, 0, hwloc_set); +} + +static int +hwloc_linux_get_thisthread_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_set, int flags __hwloc_attribute_unused) +{ + if (topology->pid) { + errno = ENOSYS; + return -1; + } + return hwloc_linux_get_tid_cpubind(topology, 0, hwloc_set); +} + +#if HAVE_DECL_PTHREAD_SETAFFINITY_NP +#pragma weak pthread_setaffinity_np +#pragma weak pthread_self + +static int +hwloc_linux_set_thread_cpubind(hwloc_topology_t topology, pthread_t tid, hwloc_const_bitmap_t hwloc_set, int flags __hwloc_attribute_unused) +{ + int err; + + if (topology->pid) { + errno = ENOSYS; + return -1; + } + + if (!pthread_self) { + /* ?! Application uses set_thread_cpubind, but doesn't link against libpthread ?! */ + errno = ENOSYS; + return -1; + } + if (tid == pthread_self()) + return hwloc_linux_set_tid_cpubind(topology, 0, hwloc_set); + + if (!pthread_setaffinity_np) { + errno = ENOSYS; + return -1; + } + /* TODO Kerrighed: Use + * int migrate (pid_t pid, int destination_node); + * int migrate_self (int destination_node); + * int thread_migrate (int thread_id, int destination_node); + */ + +#if defined(HWLOC_HAVE_CPU_SET_S) && !defined(HWLOC_HAVE_OLD_SCHED_SETAFFINITY) + /* Use a separate block so that we can define specific variable + types here */ + { + cpu_set_t *plinux_set; + unsigned cpu; + int last; + size_t setsize; + + last = hwloc_bitmap_last(hwloc_set); + if (last == -1) { + errno = EINVAL; + return -1; + } + + setsize = CPU_ALLOC_SIZE(last+1); + plinux_set = CPU_ALLOC(last+1); + + CPU_ZERO_S(setsize, plinux_set); + hwloc_bitmap_foreach_begin(cpu, hwloc_set) + CPU_SET_S(cpu, setsize, plinux_set); + hwloc_bitmap_foreach_end(); + + err = pthread_setaffinity_np(tid, setsize, plinux_set); + + CPU_FREE(plinux_set); + } +#elif defined(HWLOC_HAVE_CPU_SET) + /* Use a separate block so that we can define specific variable + types here */ + { + cpu_set_t linux_set; + unsigned cpu; + + CPU_ZERO(&linux_set); + hwloc_bitmap_foreach_begin(cpu, hwloc_set) + CPU_SET(cpu, &linux_set); + hwloc_bitmap_foreach_end(); + +#ifdef HWLOC_HAVE_OLD_SCHED_SETAFFINITY + err = pthread_setaffinity_np(tid, &linux_set); +#else /* HWLOC_HAVE_OLD_SCHED_SETAFFINITY */ + err = pthread_setaffinity_np(tid, sizeof(linux_set), &linux_set); +#endif /* HWLOC_HAVE_OLD_SCHED_SETAFFINITY */ + } +#else /* CPU_SET */ + /* Use a separate block so that we can define specific variable + types here */ + { + unsigned long mask = hwloc_bitmap_to_ulong(hwloc_set); + +#ifdef HWLOC_HAVE_OLD_SCHED_SETAFFINITY + err = pthread_setaffinity_np(tid, (void*) &mask); +#else /* HWLOC_HAVE_OLD_SCHED_SETAFFINITY */ + err = pthread_setaffinity_np(tid, sizeof(mask), (void*) &mask); +#endif /* HWLOC_HAVE_OLD_SCHED_SETAFFINITY */ + } +#endif /* CPU_SET */ + + if (err) { + errno = err; + return -1; + } + return 0; +} +#endif /* HAVE_DECL_PTHREAD_SETAFFINITY_NP */ + +#if HAVE_DECL_PTHREAD_GETAFFINITY_NP +#pragma weak pthread_getaffinity_np +#pragma weak pthread_self + +static int +hwloc_linux_get_thread_cpubind(hwloc_topology_t topology, pthread_t tid, hwloc_bitmap_t hwloc_set, int flags __hwloc_attribute_unused) +{ + int err; + + if (topology->pid) { + errno = ENOSYS; + return -1; + } + + if (!pthread_self) { + /* ?! Application uses set_thread_cpubind, but doesn't link against libpthread ?! */ + errno = ENOSYS; + return -1; + } + if (tid == pthread_self()) + return hwloc_linux_get_tid_cpubind(topology, 0, hwloc_set); + + if (!pthread_getaffinity_np) { + errno = ENOSYS; + return -1; + } + /* TODO Kerrighed */ + +#if defined(HWLOC_HAVE_CPU_SET_S) && !defined(HWLOC_HAVE_OLD_SCHED_SETAFFINITY) + /* Use a separate block so that we can define specific variable + types here */ + { + cpu_set_t *plinux_set; + unsigned cpu; + int last; + size_t setsize; + + last = hwloc_bitmap_last(topology->levels[0][0]->complete_cpuset); + assert (last != -1); + + setsize = CPU_ALLOC_SIZE(last+1); + plinux_set = CPU_ALLOC(last+1); + + err = pthread_getaffinity_np(tid, setsize, plinux_set); + if (err) { + CPU_FREE(plinux_set); + errno = err; + return -1; + } + + hwloc_bitmap_zero(hwloc_set); + for(cpu=0; cpu<=(unsigned) last; cpu++) + if (CPU_ISSET_S(cpu, setsize, plinux_set)) + hwloc_bitmap_set(hwloc_set, cpu); + + CPU_FREE(plinux_set); + } +#elif defined(HWLOC_HAVE_CPU_SET) + /* Use a separate block so that we can define specific variable + types here */ + { + cpu_set_t linux_set; + unsigned cpu; + +#ifdef HWLOC_HAVE_OLD_SCHED_SETAFFINITY + err = pthread_getaffinity_np(tid, &linux_set); +#else /* HWLOC_HAVE_OLD_SCHED_SETAFFINITY */ + err = pthread_getaffinity_np(tid, sizeof(linux_set), &linux_set); +#endif /* HWLOC_HAVE_OLD_SCHED_SETAFFINITY */ + if (err) { + errno = err; + return -1; + } + + hwloc_bitmap_zero(hwloc_set); + for(cpu=0; cpucpuset; + hwloc_bitmap_t tidset = data->tidset; + + if (hwloc_linux_get_tid_last_cpu_location(topology, tid, tidset)) + return -1; + + /* reset the cpuset on first iteration */ + if (!idx) + hwloc_bitmap_zero(cpuset); + + hwloc_bitmap_or(cpuset, cpuset, tidset); + return 0; +} + +static int +hwloc_linux_get_pid_last_cpu_location(hwloc_topology_t topology, pid_t pid, hwloc_bitmap_t hwloc_set, int flags __hwloc_attribute_unused) +{ + struct hwloc_linux_foreach_proc_tid_get_last_cpu_location_cb_data_s data; + hwloc_bitmap_t tidset = hwloc_bitmap_alloc(); + int ret; + + data.cpuset = hwloc_set; + data.tidset = tidset; + ret = hwloc_linux_foreach_proc_tid(topology, pid, + hwloc_linux_foreach_proc_tid_get_last_cpu_location_cb, + &data); + hwloc_bitmap_free(tidset); + return ret; +} + +static int +hwloc_linux_get_proc_last_cpu_location(hwloc_topology_t topology, pid_t pid, hwloc_bitmap_t hwloc_set, int flags) +{ + if (pid == 0) + pid = topology->pid; + if (flags & HWLOC_CPUBIND_THREAD) + return hwloc_linux_get_tid_last_cpu_location(topology, pid, hwloc_set); + else + return hwloc_linux_get_pid_last_cpu_location(topology, pid, hwloc_set, flags); +} + +static int +hwloc_linux_get_thisproc_last_cpu_location(hwloc_topology_t topology, hwloc_bitmap_t hwloc_set, int flags) +{ + return hwloc_linux_get_pid_last_cpu_location(topology, topology->pid, hwloc_set, flags); +} + +static int +hwloc_linux_get_thisthread_last_cpu_location(hwloc_topology_t topology, hwloc_bitmap_t hwloc_set, int flags __hwloc_attribute_unused) +{ + if (topology->pid) { + errno = ENOSYS; + return -1; + } + return hwloc_linux_get_tid_last_cpu_location(topology, 0, hwloc_set); +} + + + +/*************************** + ****** Membind hooks ****** + ***************************/ + +#if defined HWLOC_HAVE_SET_MEMPOLICY || defined HWLOC_HAVE_MBIND +static int +hwloc_linux_membind_policy_from_hwloc(int *linuxpolicy, hwloc_membind_policy_t policy, int flags) +{ + switch (policy) { + case HWLOC_MEMBIND_DEFAULT: + case HWLOC_MEMBIND_FIRSTTOUCH: + *linuxpolicy = MPOL_DEFAULT; + break; + case HWLOC_MEMBIND_BIND: + if (flags & HWLOC_MEMBIND_STRICT) + *linuxpolicy = MPOL_BIND; + else + *linuxpolicy = MPOL_PREFERRED; + break; + case HWLOC_MEMBIND_INTERLEAVE: + *linuxpolicy = MPOL_INTERLEAVE; + break; + /* TODO: next-touch when (if?) patch applied upstream */ + default: + errno = ENOSYS; + return -1; + } + return 0; +} + +static int +hwloc_linux_membind_mask_from_nodeset(hwloc_topology_t topology __hwloc_attribute_unused, + hwloc_const_nodeset_t nodeset, + unsigned *max_os_index_p, unsigned long **linuxmaskp) +{ + unsigned max_os_index = 0; /* highest os_index + 1 */ + unsigned long *linuxmask; + unsigned i; + hwloc_nodeset_t linux_nodeset = NULL; + + if (hwloc_bitmap_isfull(nodeset)) { + linux_nodeset = hwloc_bitmap_alloc(); + hwloc_bitmap_only(linux_nodeset, 0); + nodeset = linux_nodeset; + } + + max_os_index = hwloc_bitmap_last(nodeset); + if (max_os_index == (unsigned) -1) + max_os_index = 0; + /* add 1 to convert the last os_index into a max_os_index, + * and round up to the nearest multiple of BITS_PER_LONG */ + max_os_index = (max_os_index + 1 + HWLOC_BITS_PER_LONG - 1) & ~(HWLOC_BITS_PER_LONG - 1); + + linuxmask = calloc(max_os_index/HWLOC_BITS_PER_LONG, sizeof(long)); + if (!linuxmask) { + hwloc_bitmap_free(linux_nodeset); + errno = ENOMEM; + return -1; + } + + for(i=0; iset_thisthread_cpubind = hwloc_linux_set_thisthread_cpubind; + hooks->get_thisthread_cpubind = hwloc_linux_get_thisthread_cpubind; + hooks->set_thisproc_cpubind = hwloc_linux_set_thisproc_cpubind; + hooks->get_thisproc_cpubind = hwloc_linux_get_thisproc_cpubind; + hooks->set_proc_cpubind = hwloc_linux_set_proc_cpubind; + hooks->get_proc_cpubind = hwloc_linux_get_proc_cpubind; +#if HAVE_DECL_PTHREAD_SETAFFINITY_NP + hooks->set_thread_cpubind = hwloc_linux_set_thread_cpubind; +#endif /* HAVE_DECL_PTHREAD_SETAFFINITY_NP */ +#if HAVE_DECL_PTHREAD_GETAFFINITY_NP + hooks->get_thread_cpubind = hwloc_linux_get_thread_cpubind; +#endif /* HAVE_DECL_PTHREAD_GETAFFINITY_NP */ + hooks->get_thisthread_last_cpu_location = hwloc_linux_get_thisthread_last_cpu_location; + hooks->get_thisproc_last_cpu_location = hwloc_linux_get_thisproc_last_cpu_location; + hooks->get_proc_last_cpu_location = hwloc_linux_get_proc_last_cpu_location; +#ifdef HWLOC_HAVE_SET_MEMPOLICY + hooks->set_thisthread_membind = hwloc_linux_set_thisthread_membind; + hooks->get_thisthread_membind = hwloc_linux_get_thisthread_membind; + hooks->get_area_membind = hwloc_linux_get_area_membind; +#endif /* HWLOC_HAVE_SET_MEMPOLICY */ +#ifdef HWLOC_HAVE_MBIND + hooks->set_area_membind = hwloc_linux_set_area_membind; + hooks->alloc_membind = hwloc_linux_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; +#endif /* HWLOC_HAVE_MBIND */ +#if (defined HWLOC_HAVE_MIGRATE_PAGES) || ((defined HWLOC_HAVE_MBIND) && (defined MPOL_MF_MOVE)) + support->membind->migrate_membind = 1; +#endif +} + + + +/******************************************* + *** Misc Helpers for Topology Discovery *** + *******************************************/ + +/* cpuinfo array */ +struct hwloc_linux_cpuinfo_proc { + /* set during hwloc_linux_parse_cpuinfo */ + unsigned long Pproc; + /* set during hwloc_linux_parse_cpuinfo or -1 if unknown*/ + long Pcore, Ppkg; + /* set later, or -1 if unknown */ + long Lcore, Lpkg; + + /* custom info, set during hwloc_linux_parse_cpuinfo */ + struct hwloc_obj_info_s *infos; + unsigned infos_count; +}; + +static int +hwloc_parse_sysfs_unsigned(const char *mappath, unsigned *value, int fsroot_fd) +{ + char string[11]; + FILE * fd; + + fd = hwloc_fopen(mappath, "r", fsroot_fd); + if (!fd) { + *value = -1; + return -1; + } + + if (!fgets(string, 11, fd)) { + *value = -1; + fclose(fd); + return -1; + } + *value = strtoul(string, NULL, 10); + + fclose(fd); + + return 0; +} + + +/* kernel cpumaps are composed of an array of 32bits cpumasks */ +#define KERNEL_CPU_MASK_BITS 32 +#define KERNEL_CPU_MAP_LEN (KERNEL_CPU_MASK_BITS/4+2) + +int +hwloc_linux_parse_cpumap_file(FILE *file, hwloc_bitmap_t set) +{ + unsigned long *maps; + unsigned long map; + int nr_maps = 0; + static int nr_maps_allocated = 8; /* only compute the power-of-two above the kernel cpumask size once */ + int i; + + maps = malloc(nr_maps_allocated * sizeof(*maps)); + + /* reset to zero first */ + hwloc_bitmap_zero(set); + + /* parse the whole mask */ + while (fscanf(file, "%lx,", &map) == 1) /* read one kernel cpu mask and the ending comma */ + { + if (nr_maps == nr_maps_allocated) { + nr_maps_allocated *= 2; + maps = realloc(maps, nr_maps_allocated * sizeof(*maps)); + } + + if (!map && !nr_maps) + /* ignore the first map if it's empty */ + continue; + + memmove(&maps[1], &maps[0], nr_maps*sizeof(*maps)); + maps[0] = map; + nr_maps++; + } + + /* convert into a set */ +#if KERNEL_CPU_MASK_BITS == HWLOC_BITS_PER_LONG + for(i=0; i. If cpuset are used they get /proc/pid/cpuset + * containing . + */ +static char * +hwloc_read_linux_cpuset_name(int fsroot_fd, hwloc_pid_t pid) +{ +#define CPUSET_NAME_LEN 128 + char cpuset_name[CPUSET_NAME_LEN]; + FILE *fd; + char *tmp; + + /* check whether a cgroup-cpuset is enabled */ + if (!pid) + fd = hwloc_fopen("/proc/self/cgroup", "r", fsroot_fd); + else { + char path[] = "/proc/XXXXXXXXXX/cgroup"; + snprintf(path, sizeof(path), "/proc/%d/cgroup", pid); + fd = hwloc_fopen(path, "r", fsroot_fd); + } + if (fd) { + /* find a cpuset line */ +#define CGROUP_LINE_LEN 256 + char line[CGROUP_LINE_LEN]; + while (fgets(line, sizeof(line), fd)) { + char *end, *colon = strchr(line, ':'); + if (!colon) + continue; + if (strncmp(colon, ":cpuset:", 8)) + continue; + + /* found a cgroup-cpuset line, return the name */ + fclose(fd); + end = strchr(colon, '\n'); + if (end) + *end = '\0'; + hwloc_debug("Found cgroup-cpuset %s\n", colon+8); + return strdup(colon+8); + } + fclose(fd); + } + + /* check whether a cpuset is enabled */ + if (!pid) + fd = hwloc_fopen("/proc/self/cpuset", "r", fsroot_fd); + else { + char path[] = "/proc/XXXXXXXXXX/cpuset"; + snprintf(path, sizeof(path), "/proc/%d/cpuset", pid); + fd = hwloc_fopen(path, "r", fsroot_fd); + } + if (!fd) { + /* found nothing */ + hwloc_debug("%s", "No cgroup or cpuset found\n"); + return NULL; + } + + /* found a cpuset, return the name */ + tmp = fgets(cpuset_name, sizeof(cpuset_name), fd); + fclose(fd); + if (!tmp) + return NULL; + tmp = strchr(cpuset_name, '\n'); + if (tmp) + *tmp = '\0'; + hwloc_debug("Found cpuset %s\n", cpuset_name); + return strdup(cpuset_name); +} + +/* + * Then, the cpuset description is available from either the cgroup or + * the cpuset filesystem (usually mounted in / or /dev) where there + * are cgroup/cpuset.{cpus,mems} or cpuset/{cpus,mems} files. + */ +static char * +hwloc_read_linux_cpuset_mask(const char *cgroup_mntpnt, const char *cpuset_mntpnt, const char *cpuset_name, const char *attr_name, int fsroot_fd) +{ +#define CPUSET_FILENAME_LEN 256 + char cpuset_filename[CPUSET_FILENAME_LEN]; + FILE *fd; + char *info = NULL, *tmp; + ssize_t ssize; + size_t size; + + if (cgroup_mntpnt) { + /* try to read the cpuset from cgroup */ + snprintf(cpuset_filename, CPUSET_FILENAME_LEN, "%s%s/cpuset.%s", cgroup_mntpnt, cpuset_name, attr_name); + hwloc_debug("Trying to read cgroup file <%s>\n", cpuset_filename); + fd = hwloc_fopen(cpuset_filename, "r", fsroot_fd); + if (fd) + goto gotfile; + } else if (cpuset_mntpnt) { + /* try to read the cpuset directly */ + snprintf(cpuset_filename, CPUSET_FILENAME_LEN, "%s%s/%s", cpuset_mntpnt, cpuset_name, attr_name); + hwloc_debug("Trying to read cpuset file <%s>\n", cpuset_filename); + fd = hwloc_fopen(cpuset_filename, "r", fsroot_fd); + if (fd) + goto gotfile; + } + + /* found no cpuset description, ignore it */ + hwloc_debug("Couldn't find cpuset <%s> description, ignoring\n", cpuset_name); + goto out; + +gotfile: + ssize = getline(&info, &size, fd); + fclose(fd); + if (ssize < 0) + goto out; + if (!info) + goto out; + + tmp = strchr(info, '\n'); + if (tmp) + *tmp = '\0'; + +out: + return info; +} + +static void +hwloc_admin_disable_set_from_cpuset(struct hwloc_linux_backend_data_s *data, + const char *cgroup_mntpnt, const char *cpuset_mntpnt, const char *cpuset_name, + const char *attr_name, + hwloc_bitmap_t admin_enabled_cpus_set) +{ + char *cpuset_mask; + char *current, *comma, *tmp; + int prevlast, nextfirst, nextlast; /* beginning/end of enabled-segments */ + hwloc_bitmap_t tmpset; + + cpuset_mask = hwloc_read_linux_cpuset_mask(cgroup_mntpnt, cpuset_mntpnt, cpuset_name, + attr_name, data->root_fd); + if (!cpuset_mask) + return; + + hwloc_debug("found cpuset %s: %s\n", attr_name, cpuset_mask); + + current = cpuset_mask; + prevlast = -1; + + while (1) { + /* save a pointer to the next comma and erase it to simplify things */ + comma = strchr(current, ','); + if (comma) + *comma = '\0'; + + /* find current enabled-segment bounds */ + nextfirst = strtoul(current, &tmp, 0); + if (*tmp == '-') + nextlast = strtoul(tmp+1, NULL, 0); + else + nextlast = nextfirst; + if (prevlast+1 <= nextfirst-1) { + hwloc_debug("%s [%d:%d] excluded by cpuset\n", attr_name, prevlast+1, nextfirst-1); + hwloc_bitmap_clr_range(admin_enabled_cpus_set, prevlast+1, nextfirst-1); + } + + /* switch to next enabled-segment */ + prevlast = nextlast; + if (!comma) + break; + current = comma+1; + } + + hwloc_debug("%s [%d:%d] excluded by cpuset\n", attr_name, prevlast+1, nextfirst-1); + /* no easy way to clear until the infinity */ + tmpset = hwloc_bitmap_alloc(); + hwloc_bitmap_set_range(tmpset, 0, prevlast); + hwloc_bitmap_and(admin_enabled_cpus_set, admin_enabled_cpus_set, tmpset); + hwloc_bitmap_free(tmpset); + + free(cpuset_mask); +} + +static void +hwloc_parse_meminfo_info(struct hwloc_linux_backend_data_s *data, + const char *path, + int prefixlength, + uint64_t *local_memory, + uint64_t *meminfo_hugepages_count, + uint64_t *meminfo_hugepages_size, + int onlytotal) +{ + char string[64]; + FILE *fd; + + fd = hwloc_fopen(path, "r", data->root_fd); + if (!fd) + return; + + while (fgets(string, sizeof(string), fd) && *string != '\0') + { + unsigned long long number; + if (strlen(string) < (size_t) prefixlength) + continue; + if (sscanf(string+prefixlength, "MemTotal: %llu kB", (unsigned long long *) &number) == 1) { + *local_memory = number << 10; + if (onlytotal) + break; + } + else if (!onlytotal) { + if (sscanf(string+prefixlength, "Hugepagesize: %llu", (unsigned long long *) &number) == 1) + *meminfo_hugepages_size = number << 10; + else if (sscanf(string+prefixlength, "HugePages_Free: %llu", (unsigned long long *) &number) == 1) + /* these are free hugepages, not the total amount of huge pages */ + *meminfo_hugepages_count = number; + } + } + + fclose(fd); +} + +#define SYSFS_NUMA_NODE_PATH_LEN 128 + +static void +hwloc_parse_hugepages_info(struct hwloc_linux_backend_data_s *data, + const char *dirpath, + struct hwloc_obj_memory_s *memory, + uint64_t *remaining_local_memory) +{ + DIR *dir; + struct dirent *dirent; + unsigned long index_ = 1; + FILE *hpfd; + char line[64]; + char path[SYSFS_NUMA_NODE_PATH_LEN]; + + dir = hwloc_opendir(dirpath, data->root_fd); + if (dir) { + while ((dirent = readdir(dir)) != NULL) { + if (strncmp(dirent->d_name, "hugepages-", 10)) + continue; + memory->page_types[index_].size = strtoul(dirent->d_name+10, NULL, 0) * 1024ULL; + sprintf(path, "%s/%s/nr_hugepages", dirpath, dirent->d_name); + hpfd = hwloc_fopen(path, "r", data->root_fd); + if (hpfd) { + if (fgets(line, sizeof(line), hpfd)) { + /* these are the actual total amount of huge pages */ + memory->page_types[index_].count = strtoull(line, NULL, 0); + *remaining_local_memory -= memory->page_types[index_].count * memory->page_types[index_].size; + index_++; + } + fclose(hpfd); + } + } + closedir(dir); + memory->page_types_len = index_; + } +} + +static void +hwloc_get_kerrighed_node_meminfo_info(struct hwloc_topology *topology, + struct hwloc_linux_backend_data_s *data, + unsigned long node, struct hwloc_obj_memory_s *memory) +{ + char path[128]; + uint64_t meminfo_hugepages_count, meminfo_hugepages_size = 0; + + if (topology->is_thissystem) { + memory->page_types_len = 2; + memory->page_types = malloc(2*sizeof(*memory->page_types)); + memset(memory->page_types, 0, 2*sizeof(*memory->page_types)); + /* Try to get the hugepage size from sysconf in case we fail to get it from /proc/meminfo later */ +#ifdef HAVE__SC_LARGE_PAGESIZE + memory->page_types[1].size = sysconf(_SC_LARGE_PAGESIZE); +#endif + memory->page_types[0].size = hwloc_getpagesize(); + } + + snprintf(path, sizeof(path), "/proc/nodes/node%lu/meminfo", node); + hwloc_parse_meminfo_info(data, path, 0 /* no prefix */, + &memory->local_memory, + &meminfo_hugepages_count, &meminfo_hugepages_size, + memory->page_types == NULL); + + if (memory->page_types) { + uint64_t remaining_local_memory = memory->local_memory; + if (meminfo_hugepages_size) { + memory->page_types[1].size = meminfo_hugepages_size; + memory->page_types[1].count = meminfo_hugepages_count; + remaining_local_memory -= meminfo_hugepages_count * meminfo_hugepages_size; + } else { + memory->page_types_len = 1; + } + memory->page_types[0].count = remaining_local_memory / memory->page_types[0].size; + } +} + +static void +hwloc_get_procfs_meminfo_info(struct hwloc_topology *topology, + struct hwloc_linux_backend_data_s *data, + struct hwloc_obj_memory_s *memory) +{ + uint64_t meminfo_hugepages_count, meminfo_hugepages_size = 0; + struct stat st; + int has_sysfs_hugepages = 0; + const char *pagesize_env = getenv("HWLOC_DEBUG_PAGESIZE"); + int types = 2; + int err; + + err = hwloc_stat("/sys/kernel/mm/hugepages", &st, data->root_fd); + if (!err) { + types = 1 + st.st_nlink-2; + has_sysfs_hugepages = 1; + } + + if (topology->is_thissystem || pagesize_env) { + /* we cannot report any page_type info unless we have the page size. + * we'll take it either from the system if local, or from the debug env variable + */ + memory->page_types_len = types; + memory->page_types = calloc(types, sizeof(*memory->page_types)); + } + + if (topology->is_thissystem) { + /* Get the page and hugepage sizes from sysconf */ +#ifdef HAVE__SC_LARGE_PAGESIZE + memory->page_types[1].size = sysconf(_SC_LARGE_PAGESIZE); +#endif + memory->page_types[0].size = hwloc_getpagesize(); /* might be overwritten later by /proc/meminfo or sysfs */ + } + + hwloc_parse_meminfo_info(data, "/proc/meminfo", 0 /* no prefix */, + &memory->local_memory, + &meminfo_hugepages_count, &meminfo_hugepages_size, + memory->page_types == NULL); + + if (memory->page_types) { + uint64_t remaining_local_memory = memory->local_memory; + if (has_sysfs_hugepages) { + /* read from node%d/hugepages/hugepages-%skB/nr_hugepages */ + hwloc_parse_hugepages_info(data, "/sys/kernel/mm/hugepages", memory, &remaining_local_memory); + } else { + /* use what we found in meminfo */ + if (meminfo_hugepages_size) { + memory->page_types[1].size = meminfo_hugepages_size; + memory->page_types[1].count = meminfo_hugepages_count; + remaining_local_memory -= meminfo_hugepages_count * meminfo_hugepages_size; + } else { + memory->page_types_len = 1; + } + } + + if (pagesize_env) { + /* We cannot get the pagesize if not thissystem, use the env-given one to experience the code during make check */ + memory->page_types[0].size = strtoull(pagesize_env, NULL, 10); + /* If failed, use 4kB */ + if (!memory->page_types[0].size) + memory->page_types[0].size = 4096; + } + assert(memory->page_types[0].size); /* from sysconf if local or from the env */ + /* memory->page_types[1].size from sysconf if local, or from /proc/meminfo, or from sysfs, + * may be 0 if no hugepage support in the kernel */ + + memory->page_types[0].count = remaining_local_memory / memory->page_types[0].size; + } +} + +static void +hwloc_sysfs_node_meminfo_info(struct hwloc_topology *topology, + struct hwloc_linux_backend_data_s *data, + const char *syspath, int node, + struct hwloc_obj_memory_s *memory) +{ + char path[SYSFS_NUMA_NODE_PATH_LEN]; + char meminfopath[SYSFS_NUMA_NODE_PATH_LEN]; + uint64_t meminfo_hugepages_count = 0; + uint64_t meminfo_hugepages_size = 0; + struct stat st; + int has_sysfs_hugepages = 0; + int types = 2; + int err; + + sprintf(path, "%s/node%d/hugepages", syspath, node); + err = hwloc_stat(path, &st, data->root_fd); + if (!err) { + types = 1 + st.st_nlink-2; + has_sysfs_hugepages = 1; + } + + if (topology->is_thissystem) { + memory->page_types_len = types; + memory->page_types = malloc(types*sizeof(*memory->page_types)); + memset(memory->page_types, 0, types*sizeof(*memory->page_types)); + } + + sprintf(meminfopath, "%s/node%d/meminfo", syspath, node); + hwloc_parse_meminfo_info(data, meminfopath, + snprintf(NULL, 0, "Node %d ", node), + &memory->local_memory, + &meminfo_hugepages_count, NULL /* no hugepage size in node-specific meminfo */, + memory->page_types == NULL); + + if (memory->page_types) { + uint64_t remaining_local_memory = memory->local_memory; + if (has_sysfs_hugepages) { + /* read from node%d/hugepages/hugepages-%skB/nr_hugepages */ + hwloc_parse_hugepages_info(data, path, memory, &remaining_local_memory); + } else { + /* get hugepage size from machine-specific meminfo since there is no size in node-specific meminfo, + * hwloc_get_procfs_meminfo_info must have been called earlier */ + meminfo_hugepages_size = topology->levels[0][0]->memory.page_types[1].size; + /* use what we found in meminfo */ + if (meminfo_hugepages_size) { + memory->page_types[1].count = meminfo_hugepages_count; + memory->page_types[1].size = meminfo_hugepages_size; + remaining_local_memory -= meminfo_hugepages_count * meminfo_hugepages_size; + } else { + memory->page_types_len = 1; + } + } + /* update what's remaining as normal pages */ + memory->page_types[0].size = hwloc_getpagesize(); + memory->page_types[0].count = remaining_local_memory / memory->page_types[0].size; + } +} + +static void +hwloc_parse_node_distance(const char *distancepath, unsigned nbnodes, float *distances, int fsroot_fd) +{ + char string[4096]; /* enough for hundreds of nodes */ + char *tmp, *next; + FILE * fd; + + fd = hwloc_fopen(distancepath, "r", fsroot_fd); + if (!fd) + return; + + if (!fgets(string, sizeof(string), fd)) { + fclose(fd); + return; + } + + tmp = string; + while (tmp) { + unsigned distance = strtoul(tmp, &next, 0); + if (next == tmp) + break; + *distances = (float) distance; + distances++; + nbnodes--; + if (!nbnodes) + break; + tmp = next+1; + } + + fclose(fd); +} + +static void +hwloc__get_dmi_id_one_info(struct hwloc_linux_backend_data_s *data, + hwloc_obj_t obj, + char *path, unsigned pathlen, + const char *dmi_name, const char *hwloc_name) +{ + char dmi_line[64]; + char *tmp; + FILE *fd; + + strcpy(path+pathlen, dmi_name); + fd = hwloc_fopen(path, "r", data->root_fd); + if (!fd) + return; + + dmi_line[0] = '\0'; + tmp = fgets(dmi_line, sizeof(dmi_line), fd); + fclose (fd); + + if (tmp && dmi_line[0] != '\0') { + tmp = strchr(dmi_line, '\n'); + if (tmp) + *tmp = '\0'; + hwloc_debug("found %s '%s'\n", hwloc_name, dmi_line); + hwloc_obj_add_info(obj, hwloc_name, dmi_line); + } +} + +static void +hwloc__get_dmi_id_info(struct hwloc_linux_backend_data_s *data, hwloc_obj_t obj) +{ + char path[128]; + unsigned pathlen; + DIR *dir; + + strcpy(path, "/sys/devices/virtual/dmi/id"); + dir = hwloc_opendir(path, data->root_fd); + if (dir) { + pathlen = 27; + } else { + strcpy(path, "/sys/class/dmi/id"); + dir = hwloc_opendir(path, data->root_fd); + if (dir) + pathlen = 17; + else + return; + } + closedir(dir); + + path[pathlen++] = '/'; + + hwloc__get_dmi_id_one_info(data, obj, path, pathlen, "product_name", "DMIProductName"); + hwloc__get_dmi_id_one_info(data, obj, path, pathlen, "product_version", "DMIProductVersion"); + hwloc__get_dmi_id_one_info(data, obj, path, pathlen, "product_serial", "DMIProductSerial"); + hwloc__get_dmi_id_one_info(data, obj, path, pathlen, "product_uuid", "DMIProductUUID"); + hwloc__get_dmi_id_one_info(data, obj, path, pathlen, "board_vendor", "DMIBoardVendor"); + hwloc__get_dmi_id_one_info(data, obj, path, pathlen, "board_name", "DMIBoardName"); + hwloc__get_dmi_id_one_info(data, obj, path, pathlen, "board_version", "DMIBoardVersion"); + hwloc__get_dmi_id_one_info(data, obj, path, pathlen, "board_serial", "DMIBoardSerial"); + hwloc__get_dmi_id_one_info(data, obj, path, pathlen, "board_asset_tag", "DMIBoardAssetTag"); + hwloc__get_dmi_id_one_info(data, obj, path, pathlen, "chassis_vendor", "DMIChassisVendor"); + hwloc__get_dmi_id_one_info(data, obj, path, pathlen, "chassis_type", "DMIChassisType"); + hwloc__get_dmi_id_one_info(data, obj, path, pathlen, "chassis_version", "DMIChassisVersion"); + hwloc__get_dmi_id_one_info(data, obj, path, pathlen, "chassis_serial", "DMIChassisSerial"); + hwloc__get_dmi_id_one_info(data, obj, path, pathlen, "chassis_asset_tag", "DMIChassisAssetTag"); + hwloc__get_dmi_id_one_info(data, obj, path, pathlen, "bios_vendor", "DMIBIOSVendor"); + hwloc__get_dmi_id_one_info(data, obj, path, pathlen, "bios_version", "DMIBIOSVersion"); + hwloc__get_dmi_id_one_info(data, obj, path, pathlen, "bios_date", "DMIBIOSDate"); + hwloc__get_dmi_id_one_info(data, obj, path, pathlen, "sys_vendor", "DMISysVendor"); +} + +struct hwloc_firmware_dmi_mem_device_header { + unsigned char type; + unsigned char length; + unsigned char handle[2]; + unsigned char phy_mem_handle[2]; + unsigned char mem_err_handle[2]; + unsigned char tot_width[2]; + unsigned char dat_width[2]; + unsigned char size[2]; + unsigned char ff; + unsigned char dev_set; + unsigned char dev_loc_str_num; + unsigned char bank_loc_str_num; + unsigned char mem_type; + unsigned char type_detail[2]; + unsigned char speed[2]; + unsigned char manuf_str_num; + unsigned char serial_str_num; + unsigned char asset_tag_str_num; + unsigned char part_num_str_num; + /* don't include the following fields since we don't need them, + * some old implementations may miss them. + */ +}; + +static int check_dmi_entry(const char *buffer) +{ + /* reject empty strings */ + if (!*buffer) + return 0; + /* reject strings of spaces (at least Dell use this for empty memory slots) */ + if (strspn(buffer, " ") == strlen(buffer)) + return 0; + return 1; +} + +static void +hwloc__get_firmware_dmi_memory_info_one(struct hwloc_topology *topology, + unsigned idx, const char *path, FILE *fd, + struct hwloc_firmware_dmi_mem_device_header *header) +{ + unsigned slen; + char buffer[256]; /* enough for memory device strings, or at least for each of them */ + unsigned foff; /* offset in raw file */ + unsigned boff; /* offset in buffer read from raw file */ + unsigned i; + struct hwloc_obj_info_s *infos = NULL; + unsigned infos_count = 0; + hwloc_obj_t misc; + int foundinfo = 0; + + hwloc__add_info(&infos, &infos_count, "Type", "MemoryModule"); + + /* start after the header */ + foff = header->length; + i = 1; + while (1) { + /* read one buffer */ + if (fseek(fd, foff, SEEK_SET) < 0) + break; + if (!fgets(buffer, sizeof(buffer), fd)) + break; + /* read string at the beginning of the buffer */ + boff = 0; + while (1) { + /* stop on empty string */ + if (!buffer[boff]) + goto done; + /* stop if this string goes to the end of the buffer */ + slen = strlen(buffer+boff); + if (boff + slen+1 == sizeof(buffer)) + break; + /* string didn't get truncated, should be OK */ + if (i == header->manuf_str_num) { + if (check_dmi_entry(buffer+boff)) { + hwloc__add_info(&infos, &infos_count, "Vendor", buffer+boff); + foundinfo = 1; + } + } else if (i == header->serial_str_num) { + if (check_dmi_entry(buffer+boff)) { + hwloc__add_info(&infos, &infos_count, "SerialNumber", buffer+boff); + foundinfo = 1; + } + } else if (i == header->asset_tag_str_num) { + if (check_dmi_entry(buffer+boff)) { + hwloc__add_info(&infos, &infos_count, "AssetTag", buffer+boff); + foundinfo = 1; + } + } else if (i == header->part_num_str_num) { + if (check_dmi_entry(buffer+boff)) { + hwloc__add_info(&infos, &infos_count, "PartNumber", buffer+boff); + foundinfo = 1; + } + } else if (i == header->dev_loc_str_num) { + if (check_dmi_entry(buffer+boff)) { + hwloc__add_info(&infos, &infos_count, "DeviceLocation", buffer+boff); + /* only a location, not an actual info about the device */ + } + } else if (i == header->bank_loc_str_num) { + if (check_dmi_entry(buffer+boff)) { + hwloc__add_info(&infos, &infos_count, "BankLocation", buffer+boff); + /* only a location, not an actual info about the device */ + } + } else { + goto done; + } + /* next string in buffer */ + boff += slen+1; + i++; + } + /* couldn't read a single full string from that buffer, we're screwed */ + if (!boff) { + fprintf(stderr, "hwloc could read a DMI firmware entry #%u in %s\n", + i, path); + break; + } + /* reread buffer after previous string */ + foff += boff; + } + +done: + if (!foundinfo) { + /* found no actual info about the device. if there's only location info, the slot may be empty */ + goto out_with_infos; + } + + misc = hwloc_alloc_setup_object(HWLOC_OBJ_MISC, idx); + if (!misc) + goto out_with_infos; + + hwloc__move_infos(&misc->infos, &misc->infos_count, &infos, &infos_count); + /* FIXME: find a way to identify the corresponding NUMA node and attach these objects there. + * but it means we need to parse DeviceLocation=DIMM_B4 but these vary significantly + * with the vendor, and it's hard to be 100% sure 'B' is second socket. + * Examples at http://sourceforge.net/p/edac-utils/code/HEAD/tree/trunk/src/etc/labels.db + * or https://github.com/grondo/edac-utils/blob/master/src/etc/labels.db + */ + hwloc_insert_object_by_parent(topology, hwloc_get_root_obj(topology), misc); + return; + + out_with_infos: + hwloc__free_infos(infos, infos_count); +} + +static void +hwloc__get_firmware_dmi_memory_info(struct hwloc_topology *topology, + struct hwloc_linux_backend_data_s *data) +{ + char path[128]; + unsigned i; + + for(i=0; ; i++) { + FILE *fd; + struct hwloc_firmware_dmi_mem_device_header header; + int err; + + snprintf(path, sizeof(path), "/sys/firmware/dmi/entries/17-%u/raw", i); + fd = hwloc_fopen(path, "r", data->root_fd); + if (!fd) + break; + + err = fread(&header, sizeof(header), 1, fd); + if (err != 1) + break; + if (header.length < sizeof(header)) { + /* invalid, or too old entry/spec that doesn't contain what we need */ + fclose(fd); + break; + } + + hwloc__get_firmware_dmi_memory_info_one(topology, i, path, fd, &header); + + fclose(fd); + } +} + + +/*********************************** + ****** Device tree Discovery ****** + ***********************************/ + +/* Reads the entire file and returns bytes read if bytes_read != NULL + * Returned pointer can be freed by using free(). */ +static void * +hwloc_read_raw(const char *p, const char *p1, size_t *bytes_read, int root_fd) +{ + char fname[256]; + char *ret = NULL; + struct stat fs; + int file = -1; + + snprintf(fname, sizeof(fname), "%s/%s", p, p1); + + file = hwloc_open(fname, root_fd); + if (-1 == file) { + goto out_no_close; + } + if (fstat(file, &fs)) { + goto out; + } + + ret = (char *) malloc(fs.st_size); + if (NULL != ret) { + ssize_t cb = read(file, ret, fs.st_size); + if (cb == -1) { + free(ret); + ret = NULL; + } else { + if (NULL != bytes_read) + *bytes_read = cb; + } + } + + out: + close(file); + out_no_close: + return ret; +} + +/* Reads the entire file and returns it as a 0-terminated string + * Returned pointer can be freed by using free(). */ +static char * +hwloc_read_str(const char *p, const char *p1, int root_fd) +{ + size_t cb = 0; + char *ret = hwloc_read_raw(p, p1, &cb, root_fd); + if ((NULL != ret) && (0 < cb) && (0 != ret[cb-1])) { + ret = realloc(ret, cb + 1); + ret[cb] = 0; + } + return ret; +} + +/* Reads first 32bit bigendian value */ +static ssize_t +hwloc_read_unit32be(const char *p, const char *p1, uint32_t *buf, int root_fd) +{ + size_t cb = 0; + uint32_t *tmp = hwloc_read_raw(p, p1, &cb, root_fd); + if (sizeof(*buf) != cb) { + errno = EINVAL; + free(tmp); /* tmp is either NULL or contains useless things */ + return -1; + } + *buf = htonl(*tmp); + free(tmp); + return sizeof(*buf); +} + +typedef struct { + unsigned int n, allocated; + struct { + hwloc_bitmap_t cpuset; + uint32_t phandle; + uint32_t l2_cache; + char *name; + } *p; +} device_tree_cpus_t; + +static void +add_device_tree_cpus_node(device_tree_cpus_t *cpus, hwloc_bitmap_t cpuset, + uint32_t l2_cache, uint32_t phandle, const char *name) +{ + if (cpus->n == cpus->allocated) { + if (!cpus->allocated) + cpus->allocated = 64; + else + cpus->allocated *= 2; + cpus->p = realloc(cpus->p, cpus->allocated * sizeof(cpus->p[0])); + } + cpus->p[cpus->n].phandle = phandle; + cpus->p[cpus->n].cpuset = (NULL == cpuset)?NULL:hwloc_bitmap_dup(cpuset); + cpus->p[cpus->n].l2_cache = l2_cache; + cpus->p[cpus->n].name = strdup(name); + ++cpus->n; +} + +/* Walks over the cache list in order to detect nested caches and CPU mask for each */ +static int +look_powerpc_device_tree_discover_cache(device_tree_cpus_t *cpus, + uint32_t phandle, unsigned int *level, hwloc_bitmap_t cpuset) +{ + unsigned int i; + int ret = -1; + if ((NULL == level) || (NULL == cpuset) || phandle == (uint32_t) -1) + return ret; + for (i = 0; i < cpus->n; ++i) { + if (phandle != cpus->p[i].l2_cache) + continue; + if (NULL != cpus->p[i].cpuset) { + hwloc_bitmap_or(cpuset, cpuset, cpus->p[i].cpuset); + ret = 0; + } else { + ++(*level); + if (0 == look_powerpc_device_tree_discover_cache(cpus, + cpus->p[i].phandle, level, cpuset)) + ret = 0; + } + } + return ret; +} + +static void +try__add_cache_from_device_tree_cpu(struct hwloc_topology *topology, + unsigned int level, hwloc_obj_cache_type_t type, + uint32_t cache_line_size, uint32_t cache_size, uint32_t cache_sets, + hwloc_bitmap_t cpuset) +{ + struct hwloc_obj *c = NULL; + + if (0 == cache_size) + return; + + c = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -1); + c->attr->cache.depth = level; + c->attr->cache.linesize = cache_line_size; + c->attr->cache.size = cache_size; + c->attr->cache.type = type; + if (cache_sets == 1) + /* likely wrong, make it unknown */ + cache_sets = 0; + if (cache_sets && cache_line_size) + c->attr->cache.associativity = cache_size / (cache_sets * cache_line_size); + else + c->attr->cache.associativity = 0; + c->cpuset = hwloc_bitmap_dup(cpuset); + hwloc_debug_2args_bitmap("cache (%s) depth %d has cpuset %s\n", + type == HWLOC_OBJ_CACHE_UNIFIED ? "unified" : (type == HWLOC_OBJ_CACHE_DATA ? "data" : "instruction"), + level, c->cpuset); + hwloc_insert_object_by_cpuset(topology, c); +} + +static void +try_add_cache_from_device_tree_cpu(struct hwloc_topology *topology, + struct hwloc_linux_backend_data_s *data, + const char *cpu, unsigned int level, hwloc_bitmap_t cpuset) +{ + /* d-cache-block-size - ignore */ + /* d-cache-line-size - to read, in bytes */ + /* d-cache-sets - ignore */ + /* d-cache-size - to read, in bytes */ + /* i-cache, same for instruction */ + /* cache-unified only exist if data and instruction caches are unified */ + /* d-tlb-sets - ignore */ + /* d-tlb-size - ignore, always 0 on power6 */ + /* i-tlb-*, same */ + uint32_t d_cache_line_size = 0, d_cache_size = 0, d_cache_sets = 0; + uint32_t i_cache_line_size = 0, i_cache_size = 0, i_cache_sets = 0; + char unified_path[1024]; + struct stat statbuf; + int unified; + + snprintf(unified_path, sizeof(unified_path), "%s/cache-unified", cpu); + unified = (hwloc_stat(unified_path, &statbuf, data->root_fd) == 0); + + hwloc_read_unit32be(cpu, "d-cache-line-size", &d_cache_line_size, + data->root_fd); + hwloc_read_unit32be(cpu, "d-cache-size", &d_cache_size, + data->root_fd); + hwloc_read_unit32be(cpu, "d-cache-sets", &d_cache_sets, + data->root_fd); + hwloc_read_unit32be(cpu, "i-cache-line-size", &i_cache_line_size, + data->root_fd); + hwloc_read_unit32be(cpu, "i-cache-size", &i_cache_size, + data->root_fd); + hwloc_read_unit32be(cpu, "i-cache-sets", &i_cache_sets, + data->root_fd); + + if (!unified) + try__add_cache_from_device_tree_cpu(topology, level, HWLOC_OBJ_CACHE_INSTRUCTION, + i_cache_line_size, i_cache_size, i_cache_sets, cpuset); + try__add_cache_from_device_tree_cpu(topology, level, unified ? HWLOC_OBJ_CACHE_UNIFIED : HWLOC_OBJ_CACHE_DATA, + d_cache_line_size, d_cache_size, d_cache_sets, cpuset); +} + +/* + * Discovers L1/L2/L3 cache information on IBM PowerPC systems for old kernels (RHEL5.*) + * which provide NUMA nodes information without any details + */ +static void +look_powerpc_device_tree(struct hwloc_topology *topology, + struct hwloc_linux_backend_data_s *data) +{ + device_tree_cpus_t cpus; + const char ofroot[] = "/proc/device-tree/cpus"; + unsigned int i; + int root_fd = data->root_fd; + DIR *dt = hwloc_opendir(ofroot, root_fd); + struct dirent *dirent; + + if (NULL == dt) + return; + + /* only works for Power so far, and not useful on ARM */ + if (strncmp(data->utsname.machine, "ppc", 3)) + return; + + cpus.n = 0; + cpus.p = NULL; + cpus.allocated = 0; + + while (NULL != (dirent = readdir(dt))) { + char cpu[256]; + char *device_type; + uint32_t reg = -1, l2_cache = -1, phandle = -1; + + if ('.' == dirent->d_name[0]) + continue; + + snprintf(cpu, sizeof(cpu), "%s/%s", ofroot, dirent->d_name); + + device_type = hwloc_read_str(cpu, "device_type", root_fd); + if (NULL == device_type) + continue; + + hwloc_read_unit32be(cpu, "reg", ®, root_fd); + if (hwloc_read_unit32be(cpu, "next-level-cache", &l2_cache, root_fd) == -1) + hwloc_read_unit32be(cpu, "l2-cache", &l2_cache, root_fd); + if (hwloc_read_unit32be(cpu, "phandle", &phandle, root_fd) == -1) + if (hwloc_read_unit32be(cpu, "ibm,phandle", &phandle, root_fd) == -1) + hwloc_read_unit32be(cpu, "linux,phandle", &phandle, root_fd); + + if (0 == strcmp(device_type, "cache")) { + add_device_tree_cpus_node(&cpus, NULL, l2_cache, phandle, dirent->d_name); + } + else if (0 == strcmp(device_type, "cpu")) { + /* Found CPU */ + hwloc_bitmap_t cpuset = NULL; + size_t cb = 0; + uint32_t *threads = hwloc_read_raw(cpu, "ibm,ppc-interrupt-server#s", &cb, root_fd); + uint32_t nthreads = cb / sizeof(threads[0]); + + if (NULL != threads) { + cpuset = hwloc_bitmap_alloc(); + for (i = 0; i < nthreads; ++i) { + if (hwloc_bitmap_isset(topology->levels[0][0]->complete_cpuset, ntohl(threads[i]))) + hwloc_bitmap_set(cpuset, ntohl(threads[i])); + } + free(threads); + } else if ((unsigned int)-1 != reg) { + /* Doesn't work on ARM because cpu "reg" do not start at 0. + * We know the first cpu "reg" is the lowest. The others are likely + * in order assuming the device-tree shows objects in order. + */ + cpuset = hwloc_bitmap_alloc(); + hwloc_bitmap_set(cpuset, reg); + } + + if (NULL == cpuset) { + hwloc_debug("%s has no \"reg\" property, skipping\n", cpu); + } else { + struct hwloc_obj *core = NULL; + add_device_tree_cpus_node(&cpus, cpuset, l2_cache, phandle, dirent->d_name); + + /* Add core */ + core = hwloc_alloc_setup_object(HWLOC_OBJ_CORE, reg); + core->cpuset = hwloc_bitmap_dup(cpuset); + hwloc_insert_object_by_cpuset(topology, core); + + /* Add L1 cache */ + try_add_cache_from_device_tree_cpu(topology, data, cpu, 1, cpuset); + + hwloc_bitmap_free(cpuset); + } + } + free(device_type); + } + closedir(dt); + + /* No cores and L2 cache were found, exiting */ + if (0 == cpus.n) { + hwloc_debug("No cores and L2 cache were found in %s, exiting\n", ofroot); + return; + } + +#ifdef HWLOC_DEBUG + for (i = 0; i < cpus.n; ++i) { + hwloc_debug("%i: %s ibm,phandle=%08X l2_cache=%08X ", + i, cpus.p[i].name, cpus.p[i].phandle, cpus.p[i].l2_cache); + if (NULL == cpus.p[i].cpuset) { + hwloc_debug("%s\n", "no cpuset"); + } else { + hwloc_debug_bitmap("cpuset %s\n", cpus.p[i].cpuset); + } + } +#endif + + /* Scan L2/L3/... caches */ + for (i = 0; i < cpus.n; ++i) { + unsigned int level = 2; + hwloc_bitmap_t cpuset; + /* Skip real CPUs */ + if (NULL != cpus.p[i].cpuset) + continue; + + /* Calculate cache level and CPU mask */ + cpuset = hwloc_bitmap_alloc(); + if (0 == look_powerpc_device_tree_discover_cache(&cpus, + cpus.p[i].phandle, &level, cpuset)) { + char cpu[256]; + snprintf(cpu, sizeof(cpu), "%s/%s", ofroot, cpus.p[i].name); + try_add_cache_from_device_tree_cpu(topology, data, cpu, level, cpuset); + } + hwloc_bitmap_free(cpuset); + } + + /* Do cleanup */ + for (i = 0; i < cpus.n; ++i) { + hwloc_bitmap_free(cpus.p[i].cpuset); + free(cpus.p[i].name); + } + free(cpus.p); +} + + + +/************************************** + ****** Sysfs Topology Discovery ****** + **************************************/ + +static int +look_sysfsnode(struct hwloc_topology *topology, + struct hwloc_linux_backend_data_s *data, + const char *path, unsigned *found) +{ + unsigned osnode; + unsigned nbnodes = 0; + DIR *dir; + struct dirent *dirent; + hwloc_bitmap_t nodeset; + + *found = 0; + + /* Get the list of nodes first */ + dir = hwloc_opendir(path, data->root_fd); + if (dir) + { + nodeset = hwloc_bitmap_alloc(); + while ((dirent = readdir(dir)) != NULL) + { + if (strncmp(dirent->d_name, "node", 4)) + continue; + osnode = strtoul(dirent->d_name+4, NULL, 0); + hwloc_bitmap_set(nodeset, osnode); + nbnodes++; + } + closedir(dir); + } + else + return -1; + + if (nbnodes <= 1) + { + hwloc_bitmap_free(nodeset); + return 0; + } + + /* For convenience, put these declarations inside a block. */ + + { + hwloc_obj_t * nodes = calloc(nbnodes, sizeof(hwloc_obj_t)); + unsigned *indexes = calloc(nbnodes, sizeof(unsigned)); + float * distances; + int failednodes = 0; + unsigned index_; + + if (NULL == nodes || NULL == indexes) { + free(nodes); + free(indexes); + hwloc_bitmap_free(nodeset); + nbnodes = 0; + goto out; + } + + /* Unsparsify node indexes. + * We'll need them later because Linux groups sparse distances + * and keeps them in order in the sysfs distance files. + * It'll simplify things in the meantime. + */ + index_ = 0; + hwloc_bitmap_foreach_begin (osnode, nodeset) { + indexes[index_] = osnode; + index_++; + } hwloc_bitmap_foreach_end(); + hwloc_bitmap_free(nodeset); + +#ifdef HWLOC_DEBUG + hwloc_debug("%s", "NUMA indexes: "); + for (index_ = 0; index_ < nbnodes; index_++) { + hwloc_debug(" %u", indexes[index_]); + } + hwloc_debug("%s", "\n"); +#endif + + /* Create NUMA objects */ + for (index_ = 0; index_ < nbnodes; index_++) { + char nodepath[SYSFS_NUMA_NODE_PATH_LEN]; + hwloc_bitmap_t cpuset; + hwloc_obj_t node, res_obj; + + osnode = indexes[index_]; + + sprintf(nodepath, "%s/node%u/cpumap", path, osnode); + cpuset = hwloc_parse_cpumap(nodepath, data->root_fd); + if (!cpuset) { + /* This NUMA object won't be inserted, we'll ignore distances */ + failednodes++; + continue; + } + + node = hwloc_alloc_setup_object(HWLOC_OBJ_NUMANODE, osnode); + node->cpuset = cpuset; + node->nodeset = hwloc_bitmap_alloc(); + hwloc_bitmap_set(node->nodeset, osnode); + + hwloc_sysfs_node_meminfo_info(topology, data, path, osnode, &node->memory); + + hwloc_debug_1arg_bitmap("os node %u has cpuset %s\n", + osnode, node->cpuset); + res_obj = hwloc_insert_object_by_cpuset(topology, node); + if (node == res_obj) { + nodes[index_] = node; + } else { + /* We got merged somehow, could be a buggy BIOS reporting wrong NUMA node cpuset. + * This object disappeared, we'll ignore distances */ + failednodes++; + } + } + + if (failednodes) { + /* failed to read/create some nodes, don't bother reading/fixing + * a distance matrix that would likely be wrong anyway. + */ + nbnodes -= failednodes; + distances = NULL; + } else { + distances = calloc(nbnodes*nbnodes, sizeof(float)); + } + + if (NULL == distances) { + free(nodes); + free(indexes); + goto out; + } + + /* Get actual distances now */ + for (index_ = 0; index_ < nbnodes; index_++) { + char nodepath[SYSFS_NUMA_NODE_PATH_LEN]; + + osnode = indexes[index_]; + + /* Linux nodeX/distance file contains distance from X to other localities (from ACPI SLIT table or so), + * store them in slots X*N...X*N+N-1 */ + sprintf(nodepath, "%s/node%u/distance", path, osnode); + hwloc_parse_node_distance(nodepath, nbnodes, distances+index_*nbnodes, data->root_fd); + } + + hwloc_distances_set(topology, HWLOC_OBJ_NUMANODE, nbnodes, indexes, nodes, distances, 0 /* OS cannot force */); + } + + out: + *found = nbnodes; + return 0; +} + +/* Look at Linux' /sys/devices/system/cpu/cpu%d/topology/ */ +static int +look_sysfscpu(struct hwloc_topology *topology, + struct hwloc_linux_backend_data_s *data, + const char *path, + struct hwloc_linux_cpuinfo_proc * cpuinfo_Lprocs, unsigned cpuinfo_numprocs) +{ + hwloc_bitmap_t cpuset; /* Set of cpus for which we have topology information */ +#define CPU_TOPOLOGY_STR_LEN 128 + char str[CPU_TOPOLOGY_STR_LEN]; + DIR *dir; + int i,j; + FILE *fd; + unsigned caches_added, merge_buggy_core_siblings; + hwloc_obj_t packages = NULL; /* temporary list of packages before actual insert in the tree */ + + /* fill the cpuset of interesting cpus */ + dir = hwloc_opendir(path, data->root_fd); + if (!dir) + return -1; + else { + struct dirent *dirent; + cpuset = hwloc_bitmap_alloc(); + + while ((dirent = readdir(dir)) != NULL) { + unsigned long cpu; + char online[2]; + + if (strncmp(dirent->d_name, "cpu", 3)) + continue; + cpu = strtoul(dirent->d_name+3, NULL, 0); + + /* Maybe we don't have topology information but at least it exists */ + hwloc_bitmap_set(topology->levels[0][0]->complete_cpuset, cpu); + + /* check whether this processor is online */ + sprintf(str, "%s/cpu%lu/online", path, cpu); + fd = hwloc_fopen(str, "r", data->root_fd); + if (fd) { + if (fgets(online, sizeof(online), fd)) { + fclose(fd); + if (atoi(online)) { + hwloc_debug("os proc %lu is online\n", cpu); + } else { + hwloc_debug("os proc %lu is offline\n", cpu); + hwloc_bitmap_clr(topology->levels[0][0]->online_cpuset, cpu); + } + } else { + fclose(fd); + } + } + + /* check whether the kernel exports topology information for this cpu */ + sprintf(str, "%s/cpu%lu/topology", path, cpu); + if (hwloc_access(str, X_OK, data->root_fd) < 0 && errno == ENOENT) { + hwloc_debug("os proc %lu has no accessible %s/cpu%lu/topology\n", + cpu, path, cpu); + continue; + } + + hwloc_bitmap_set(cpuset, cpu); + } + closedir(dir); + } + + topology->support.discovery->pu = 1; + hwloc_debug_1arg_bitmap("found %d cpu topologies, cpuset %s\n", + hwloc_bitmap_weight(cpuset), cpuset); + + merge_buggy_core_siblings = (!strcmp(data->utsname.machine, "x86_64")) + || (data->utsname.machine[0] == 'i' && !strcmp(data->utsname.machine+2, "86")); + caches_added = 0; + hwloc_bitmap_foreach_begin(i, cpuset) + { + hwloc_bitmap_t packageset, coreset, bookset, threadset, savedcoreset; + unsigned mypackageid, mycoreid, mybookid; + int threadwithcoreid = 0; + + /* look at the package */ + mypackageid = 0; /* shut-up the compiler */ + sprintf(str, "%s/cpu%d/topology/physical_package_id", path, i); + hwloc_parse_sysfs_unsigned(str, &mypackageid, data->root_fd); + + sprintf(str, "%s/cpu%d/topology/core_siblings", path, i); + packageset = hwloc_parse_cpumap(str, data->root_fd); + if (packageset && hwloc_bitmap_first(packageset) == i) { + /* first cpu in this package, add the package */ + struct hwloc_obj *package; + + if (merge_buggy_core_siblings) { + /* check for another package with same physical_package_id */ + hwloc_obj_t curpackage = packages; + while (curpackage) { + if (curpackage->os_index == mypackageid) { + /* found another package with same physical_package_id but different core_siblings. + * looks like a buggy kernel on Intel Xeon E5 v3 processor with two rings. + * merge these core_siblings to extend the existing first package object. + */ + static int reported = 0; + if (!reported && !hwloc_hide_errors()) { + char *a, *b; + hwloc_bitmap_asprintf(&a, curpackage->cpuset); + hwloc_bitmap_asprintf(&b, packageset); + fprintf(stderr, "****************************************************************************\n"); + fprintf(stderr, "* hwloc %s has detected buggy sysfs package information: Two packages have\n", HWLOC_VERSION); + fprintf(stderr, "* the same physical package id %u but different core_siblings %s and %s\n", + mypackageid, a, b); + fprintf(stderr, "* hwloc is merging these packages into a single one assuming your Linux kernel\n"); + fprintf(stderr, "* does not support this processor correctly.\n"); + fprintf(stderr, "* You may hide this warning by setting HWLOC_HIDE_ERRORS=1 in the environment.\n"); + fprintf(stderr, "*\n"); + fprintf(stderr, "* If hwloc does not report the right number of packages,\n"); + fprintf(stderr, "* please report this error message to the hwloc user's mailing list,\n"); + fprintf(stderr, "* along with the output+tarball generated by the hwloc-gather-topology script.\n"); + fprintf(stderr, "****************************************************************************\n"); + reported = 1; + free(a); + free(b); + } + hwloc_bitmap_or(curpackage->cpuset, curpackage->cpuset, packageset); + goto package_done; + } + curpackage = curpackage->next_cousin; + } + } + + /* no package with same physical_package_id, create a new one */ + package = hwloc_alloc_setup_object(HWLOC_OBJ_PACKAGE, mypackageid); + package->cpuset = packageset; + hwloc_debug_1arg_bitmap("os package %u has cpuset %s\n", + mypackageid, packageset); + /* add cpuinfo */ + if (cpuinfo_Lprocs) { + for(j=0; j<(int) cpuinfo_numprocs; j++) + if ((int) cpuinfo_Lprocs[j].Pproc == i) { + hwloc__move_infos(&package->infos, &package->infos_count, + &cpuinfo_Lprocs[j].infos, &cpuinfo_Lprocs[j].infos_count); + } + } + /* insert in a temporary list in case we have to modify the cpuset by merging other core_siblings later. + * we'll actually insert the tree at the end of the entire sysfs cpu loop. + */ + package->next_cousin = packages; + packages = package; + + packageset = NULL; /* don't free it */ + } +package_done: + hwloc_bitmap_free(packageset); + + /* look at the core */ + mycoreid = 0; /* shut-up the compiler */ + sprintf(str, "%s/cpu%d/topology/core_id", path, i); + hwloc_parse_sysfs_unsigned(str, &mycoreid, data->root_fd); + + sprintf(str, "%s/cpu%d/topology/thread_siblings", path, i); + coreset = hwloc_parse_cpumap(str, data->root_fd); + savedcoreset = coreset; /* store it for later work-arounds */ + + if (coreset && hwloc_bitmap_weight(coreset) > 1) { + /* check if this is hyper-threading or different coreids */ + unsigned siblingid, siblingcoreid; + hwloc_bitmap_t set = hwloc_bitmap_dup(coreset); + hwloc_bitmap_clr(set, i); + siblingid = hwloc_bitmap_first(set); + siblingcoreid = mycoreid; + sprintf(str, "%s/cpu%d/topology/core_id", path, siblingid); + hwloc_parse_sysfs_unsigned(str, &siblingcoreid, data->root_fd); + threadwithcoreid = (siblingcoreid != mycoreid); + hwloc_bitmap_free(set); + } + + + if (coreset && (hwloc_bitmap_first(coreset) == i || threadwithcoreid)) { + /* regular core */ + struct hwloc_obj *core = hwloc_alloc_setup_object(HWLOC_OBJ_CORE, mycoreid); + if (threadwithcoreid) { + /* amd multicore compute-unit, create one core per thread */ + core->cpuset = hwloc_bitmap_alloc(); + hwloc_bitmap_set(core->cpuset, i); + } else { + core->cpuset = coreset; + } + hwloc_debug_1arg_bitmap("os core %u has cpuset %s\n", + mycoreid, coreset); + hwloc_insert_object_by_cpuset(topology, core); + coreset = NULL; /* don't free it */ + } + + /* look at the books */ + mybookid = 0; /* shut-up the compiler */ + sprintf(str, "%s/cpu%d/topology/book_id", path, i); + if (hwloc_parse_sysfs_unsigned(str, &mybookid, data->root_fd) == 0) { + + sprintf(str, "%s/cpu%d/topology/book_siblings", path, i); + bookset = hwloc_parse_cpumap(str, data->root_fd); + if (bookset && hwloc_bitmap_first(bookset) == i) { + struct hwloc_obj *book = hwloc_alloc_setup_object(HWLOC_OBJ_GROUP, mybookid); + book->cpuset = bookset; + hwloc_debug_1arg_bitmap("os book %u has cpuset %s\n", + mybookid, bookset); + hwloc_obj_add_info(book, "Type", "Book"); + hwloc_insert_object_by_cpuset(topology, book); + bookset = NULL; /* don't free it */ + } + } + + { + /* look at the thread */ + struct hwloc_obj *thread = hwloc_alloc_setup_object(HWLOC_OBJ_PU, i); + threadset = hwloc_bitmap_alloc(); + hwloc_bitmap_only(threadset, i); + thread->cpuset = threadset; + hwloc_debug_1arg_bitmap("thread %d has cpuset %s\n", + i, threadset); + hwloc_insert_object_by_cpuset(topology, thread); + } + + /* look at the caches */ + for(j=0; j<10; j++) { +#define SHARED_CPU_MAP_STRLEN 128 + char mappath[SHARED_CPU_MAP_STRLEN]; + char str2[20]; /* enough for a level number (one digit) or a type (Data/Instruction/Unified) */ + hwloc_bitmap_t cacheset; + unsigned long kB = 0; + unsigned linesize = 0; + unsigned sets = 0, lines_per_tag = 1; + int depth; /* 0 for L1, .... */ + hwloc_obj_cache_type_t type = HWLOC_OBJ_CACHE_UNIFIED; /* default */ + + /* get the cache level depth */ + sprintf(mappath, "%s/cpu%d/cache/index%d/level", path, i, j); + fd = hwloc_fopen(mappath, "r", data->root_fd); + if (fd) { + char *res = fgets(str2,sizeof(str2), fd); + fclose(fd); + if (res) + depth = strtoul(str2, NULL, 10)-1; + else + continue; + } else + continue; + + /* cache type */ + sprintf(mappath, "%s/cpu%d/cache/index%d/type", path, i, j); + fd = hwloc_fopen(mappath, "r", data->root_fd); + if (fd) { + if (fgets(str2, sizeof(str2), fd)) { + fclose(fd); + if (!strncmp(str2, "Data", 4)) + type = HWLOC_OBJ_CACHE_DATA; + else if (!strncmp(str2, "Unified", 7)) + type = HWLOC_OBJ_CACHE_UNIFIED; + else if (!strncmp(str2, "Instruction", 11)) + type = HWLOC_OBJ_CACHE_INSTRUCTION; + else + continue; + } else { + fclose(fd); + continue; + } + } else + continue; + + /* get the cache size */ + sprintf(mappath, "%s/cpu%d/cache/index%d/size", path, i, j); + fd = hwloc_fopen(mappath, "r", data->root_fd); + if (fd) { + if (fgets(str2,sizeof(str2), fd)) + kB = atol(str2); /* in kB */ + fclose(fd); + } + + /* get the line size */ + sprintf(mappath, "%s/cpu%d/cache/index%d/coherency_line_size", path, i, j); + fd = hwloc_fopen(mappath, "r", data->root_fd); + if (fd) { + if (fgets(str2,sizeof(str2), fd)) + linesize = atol(str2); /* in bytes */ + fclose(fd); + } + + /* get the number of sets and lines per tag. + * don't take the associativity directly in "ways_of_associativity" because + * some archs (ia64, ppc) put 0 there when fully-associative, while others (x86) put something like -1 there. + */ + sprintf(mappath, "%s/cpu%d/cache/index%d/number_of_sets", path, i, j); + fd = hwloc_fopen(mappath, "r", data->root_fd); + if (fd) { + if (fgets(str2,sizeof(str2), fd)) + sets = atol(str2); + fclose(fd); + } + sprintf(mappath, "%s/cpu%d/cache/index%d/physical_line_partition", path, i, j); + fd = hwloc_fopen(mappath, "r", data->root_fd); + if (fd) { + if (fgets(str2,sizeof(str2), fd)) + lines_per_tag = atol(str2); + fclose(fd); + } + + sprintf(mappath, "%s/cpu%d/cache/index%d/shared_cpu_map", path, i, j); + cacheset = hwloc_parse_cpumap(mappath, data->root_fd); + if (cacheset) { + if (hwloc_bitmap_weight(cacheset) < 1) { + /* mask is wrong (useful for many itaniums) */ + if (savedcoreset) + /* assume it's a core-specific cache */ + hwloc_bitmap_copy(cacheset, savedcoreset); + else + /* assumes it's not shared */ + hwloc_bitmap_only(cacheset, i); + } + + if (hwloc_bitmap_first(cacheset) == i) { + /* first cpu in this cache, add the cache */ + struct hwloc_obj *cache = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -1); + cache->attr->cache.size = kB << 10; + cache->attr->cache.depth = depth+1; + cache->attr->cache.linesize = linesize; + cache->attr->cache.type = type; + if (!linesize || !lines_per_tag || !sets) + cache->attr->cache.associativity = 0; /* unknown */ + else if (sets == 1) + cache->attr->cache.associativity = 0; /* likely wrong, make it unknown */ + else + cache->attr->cache.associativity = (kB << 10) / linesize / lines_per_tag / sets; + cache->cpuset = cacheset; + hwloc_debug_1arg_bitmap("cache depth %d has cpuset %s\n", + depth, cacheset); + hwloc_insert_object_by_cpuset(topology, cache); + cacheset = NULL; /* don't free it */ + ++caches_added; + } + } + hwloc_bitmap_free(cacheset); + } + hwloc_bitmap_free(coreset); + } + hwloc_bitmap_foreach_end(); + + /* actually insert in the tree now that package cpusets have been fixed-up */ + while (packages) { + hwloc_obj_t next = packages->next_cousin; + packages->next_cousin = NULL; + hwloc_insert_object_by_cpuset(topology, packages); + packages = next; + } + + if (0 == caches_added) + look_powerpc_device_tree(topology, data); + + hwloc_bitmap_free(cpuset); + + return 0; +} + + + +/**************************************** + ****** cpuinfo Topology Discovery ****** + ****************************************/ + +static int +hwloc_linux_parse_cpuinfo_x86(const char *prefix, const char *value, + struct hwloc_obj_info_s **infos, unsigned *infos_count, + int is_global __hwloc_attribute_unused) +{ + if (!strcmp("vendor_id", prefix)) { + hwloc__add_info(infos, infos_count, "CPUVendor", value); + } else if (!strcmp("model name", prefix)) { + hwloc__add_info(infos, infos_count, "CPUModel", value); + } else if (!strcmp("model", prefix)) { + hwloc__add_info(infos, infos_count, "CPUModelNumber", value); + } else if (!strcmp("cpu family", prefix)) { + hwloc__add_info(infos, infos_count, "CPUFamilyNumber", value); + } else if (!strcmp("stepping", prefix)) { + hwloc__add_info(infos, infos_count, "CPUStepping", value); + } + return 0; +} + +static int +hwloc_linux_parse_cpuinfo_ia64(const char *prefix, const char *value, + struct hwloc_obj_info_s **infos, unsigned *infos_count, + int is_global __hwloc_attribute_unused) +{ + if (!strcmp("vendor", prefix)) { + hwloc__add_info(infos, infos_count, "CPUVendor", value); + } else if (!strcmp("model name", prefix)) { + hwloc__add_info(infos, infos_count, "CPUModel", value); + } else if (!strcmp("model", prefix)) { + hwloc__add_info(infos, infos_count, "CPUModelNumber", value); + } else if (!strcmp("family", prefix)) { + hwloc__add_info(infos, infos_count, "CPUFamilyNumber", value); + } + return 0; +} + +static int +hwloc_linux_parse_cpuinfo_arm(const char *prefix, const char *value, + struct hwloc_obj_info_s **infos, unsigned *infos_count, + int is_global __hwloc_attribute_unused) +{ + if (!strcmp("Processor", prefix) /* old kernels with one Processor header */ + || !strcmp("model name", prefix) /* new kernels with one model name per core */) { + hwloc__add_info(infos, infos_count, "CPUModel", value); + } else if (!strcmp("CPU implementer", prefix)) { + hwloc__add_info(infos, infos_count, "CPUImplementer", value); + } else if (!strcmp("CPU architecture", prefix)) { + hwloc__add_info(infos, infos_count, "CPUArchitecture", value); + } else if (!strcmp("CPU variant", prefix)) { + hwloc__add_info(infos, infos_count, "CPUVariant", value); + } else if (!strcmp("CPU part", prefix)) { + hwloc__add_info(infos, infos_count, "CPUPart", value); + } else if (!strcmp("CPU revision", prefix)) { + hwloc__add_info(infos, infos_count, "CPURevision", value); + } else if (!strcmp("Hardware", prefix)) { + hwloc__add_info(infos, infos_count, "HardwareName", value); + } else if (!strcmp("Revision", prefix)) { + hwloc__add_info(infos, infos_count, "HardwareRevision", value); + } else if (!strcmp("Serial", prefix)) { + hwloc__add_info(infos, infos_count, "HardwareSerial", value); + } + return 0; +} + +static int +hwloc_linux_parse_cpuinfo_ppc(const char *prefix, const char *value, + struct hwloc_obj_info_s **infos, unsigned *infos_count, + int is_global) +{ + /* common fields */ + if (!strcmp("cpu", prefix)) { + hwloc__add_info(infos, infos_count, "CPUModel", value); + } else if (!strcmp("platform", prefix)) { + hwloc__add_info(infos, infos_count, "PlatformName", value); + } else if (!strcmp("model", prefix)) { + hwloc__add_info(infos, infos_count, "PlatformModel", value); + } + /* platform-specific fields */ + else if (!strcasecmp("vendor", prefix)) { + hwloc__add_info(infos, infos_count, "PlatformVendor", value); + } else if (!strcmp("Board ID", prefix)) { + hwloc__add_info(infos, infos_count, "PlatformBoardID", value); + } else if (!strcmp("Board", prefix) + || !strcasecmp("Machine", prefix)) { + /* machine and board are similar (and often more precise) than model above */ + char **valuep = hwloc__find_info_slot(infos, infos_count, "PlatformModel"); + if (*valuep) + free(*valuep); + *valuep = strdup(value); + } else if (!strcasecmp("Revision", prefix) + || !strcmp("Hardware rev", prefix)) { + hwloc__add_info(infos, infos_count, is_global ? "PlatformRevision" : "CPURevision", value); + } else if (!strcmp("SVR", prefix)) { + hwloc__add_info(infos, infos_count, "SystemVersionRegister", value); + } else if (!strcmp("PVR", prefix)) { + hwloc__add_info(infos, infos_count, "ProcessorVersionRegister", value); + } + /* don't match 'board*' because there's also "board l2" on some platforms */ + return 0; +} + +/* + * avr32: "chip type\t:" => OK + * blackfin: "model name\t:" => OK + * h8300: "CPU:" => OK + * m68k: "CPU:" => OK + * mips: "cpu model\t\t:" => OK + * openrisc: "CPU:" => OK + * sparc: "cpu\t\t:" => OK + * tile: "model name\t:" => OK + * unicore32: "Processor\t:" => OK + * alpha: "cpu\t\t\t: Alpha" + "cpu model\t\t:" => "cpu" overwritten by "cpu model", no processor indexes + * cris: "cpu\t\t:" + "cpu model\t:" => only "cpu" + * frv: "CPU-Core:" + "CPU:" => only "CPU" + * mn10300: "cpu core :" + "model name :" => only "model name" + * parisc: "cpu family\t:" + "cpu\t\t:" => only "cpu" + * + * not supported because of conflicts with other arch minor lines: + * m32r: "cpu family\t:" => KO (adding "cpu family" would break "blackfin") + * microblaze: "CPU-Family:" => KO + * sh: "cpu family\t:" + "cpu type\t:" => KO + * xtensa: "model\t\t:" => KO + */ +static int +hwloc_linux_parse_cpuinfo_generic(const char *prefix, const char *value, + struct hwloc_obj_info_s **infos, unsigned *infos_count, + int is_global __hwloc_attribute_unused) +{ + if (!strcmp("model name", prefix) + || !strcmp("Processor", prefix) + || !strcmp("chip type", prefix) + || !strcmp("cpu model", prefix) + || !strcasecmp("cpu", prefix)) { + /* keep the last one, assume it's more precise than the first one. + * we should have the Architecture keypair for basic information anyway. + */ + char **valuep = hwloc__find_info_slot(infos, infos_count, "CPUModel"); + if (*valuep) + free(*valuep); + *valuep = strdup(value); + } + return 0; +} + +static int +hwloc_linux_parse_cpuinfo(struct hwloc_linux_backend_data_s *data, + const char *path, + struct hwloc_linux_cpuinfo_proc ** Lprocs_p, + struct hwloc_obj_info_s **global_infos, unsigned *global_infos_count) +{ + FILE *fd; + char *str = NULL; + char *endptr; + unsigned len; + unsigned allocated_Lprocs = 0; + struct hwloc_linux_cpuinfo_proc * Lprocs = NULL; + unsigned numprocs = 0; + int curproc = -1; + int (*parse_cpuinfo_func)(const char *, const char *, struct hwloc_obj_info_s **, unsigned *, int) = NULL; + + if (!(fd=hwloc_fopen(path,"r", data->root_fd))) + { + hwloc_debug("could not open %s\n", path); + return -1; + } + +# define PROCESSOR "processor" +# define PACKAGEID "physical id" /* the longest one */ +# define COREID "core id" + len = 128; /* vendor/model can be very long */ + str = malloc(len); + hwloc_debug("\n\n * Topology extraction from %s *\n\n", path); + while (fgets(str,len,fd)!=NULL) { + unsigned long Ppkg, Pcore, Pproc; + char *end, *dot, *prefix, *value; + int noend = 0; + + /* remove the ending \n */ + end = strchr(str, '\n'); + if (end) + *end = 0; + else + noend = 1; + /* if empty line, skip and reset curproc */ + if (!*str) { + curproc = -1; + continue; + } + /* skip lines with no dot */ + dot = strchr(str, ':'); + if (!dot) + continue; + /* skip lines not starting with a letter */ + if ((*str > 'z' || *str < 'a') + && (*str > 'Z' || *str < 'A')) + continue; + + /* mark the end of the prefix */ + prefix = str; + end = dot; + while (end[-1] == ' ' || end[-1] == ' ') end--; /* need a strrspn() */ + *end = 0; + /* find beginning of value, its end is already marked */ + value = dot+1 + strspn(dot+1, " "); + + /* defines for parsing numbers */ +# define getprocnb_begin(field, var) \ + if (!strcmp(field,prefix)) { \ + var = strtoul(value,&endptr,0); \ + if (endptr==value) { \ + hwloc_debug("no number in "field" field of %s\n", path); \ + goto err; \ + } else if (var==ULONG_MAX) { \ + hwloc_debug("too big "field" number in %s\n", path); \ + goto err; \ + } \ + hwloc_debug(field " %lu\n", var) +# define getprocnb_end() \ + } + /* actually parse numbers */ + getprocnb_begin(PROCESSOR, Pproc); + curproc = numprocs++; + if (numprocs > allocated_Lprocs) { + if (!allocated_Lprocs) + allocated_Lprocs = 8; + else + allocated_Lprocs *= 2; + Lprocs = realloc(Lprocs, allocated_Lprocs * sizeof(*Lprocs)); + } + Lprocs[curproc].Pproc = Pproc; + Lprocs[curproc].Pcore = -1; + Lprocs[curproc].Ppkg = -1; + Lprocs[curproc].Lcore = -1; + Lprocs[curproc].Lpkg = -1; + Lprocs[curproc].infos = NULL; + Lprocs[curproc].infos_count = 0; + getprocnb_end() else + getprocnb_begin(PACKAGEID, Ppkg); + Lprocs[curproc].Ppkg = Ppkg; + getprocnb_end() else + getprocnb_begin(COREID, Pcore); + Lprocs[curproc].Pcore = Pcore; + getprocnb_end() else { + + /* architecture specific or default routine for parsing cpumodel */ + if (!parse_cpuinfo_func) { + parse_cpuinfo_func = hwloc_linux_parse_cpuinfo_generic; + if (*data->utsname.machine) { + /* x86_32 x86_64 k1om => x86 */ + if (!strcmp(data->utsname.machine, "x86_64") + || (data->utsname.machine[0] == 'i' && !strcmp(data->utsname.machine+2, "86")) + || !strcmp(data->utsname.machine, "k1om")) + parse_cpuinfo_func = hwloc_linux_parse_cpuinfo_x86; + /* ia64 */ + else if (!strcmp(data->utsname.machine, "ia64")) + parse_cpuinfo_func = hwloc_linux_parse_cpuinfo_ia64; + /* arm */ + else if (!strncmp(data->utsname.machine, "arm", 3)) + parse_cpuinfo_func = hwloc_linux_parse_cpuinfo_arm; + else if (!strncmp(data->utsname.machine, "ppc", 3) + || !strncmp(data->utsname.machine, "power", 5)) + parse_cpuinfo_func = hwloc_linux_parse_cpuinfo_ppc; + } + } + /* we can't assume that we already got a processor index line: + * alpha/frv/h8300/m68k/microblaze/sparc have no processor lines at all, only a global entry. + * tile has a global section with model name before the list of processor lines. + */ + parse_cpuinfo_func(prefix, value, + curproc >= 0 ? &Lprocs[curproc].infos : global_infos, + curproc >= 0 ? &Lprocs[curproc].infos_count : global_infos_count, + curproc < 0); + } + + if (noend) { + /* ignore end of line */ + if (fscanf(fd,"%*[^\n]") == EOF) + break; + getc(fd); + } + } + fclose(fd); + free(str); + + *Lprocs_p = Lprocs; + return numprocs; + + err: + fclose(fd); + free(str); + free(Lprocs); + return -1; +} + +static void +hwloc_linux_free_cpuinfo(struct hwloc_linux_cpuinfo_proc * Lprocs, unsigned numprocs, + struct hwloc_obj_info_s *global_infos, unsigned global_infos_count) +{ + if (Lprocs) { + unsigned i; + for(i=0; iinfos, &hwloc_get_root_obj(topology)->infos_count, + &global_infos, &global_infos_count); + + + if (_numprocs <= 0) + /* found no processor */ + return -1; + numprocs = _numprocs; + + /* initialize misc arrays, there can be at most numprocs entries */ + Lcore_to_Pcore = malloc(numprocs * sizeof(*Lcore_to_Pcore)); + Lcore_to_Ppkg = malloc(numprocs * sizeof(*Lcore_to_Ppkg)); + Lpkg_to_Ppkg = malloc(numprocs * sizeof(*Lpkg_to_Ppkg)); + for (i = 0; i < numprocs; i++) { + Lcore_to_Pcore[i] = -1; + Lcore_to_Ppkg[i] = -1; + Lpkg_to_Ppkg[i] = -1; + } + + cpuset = hwloc_bitmap_alloc(); + + /* create PU objects */ + for(Lproc=0; Lproccpuset = hwloc_bitmap_alloc(); + hwloc_bitmap_only(obj->cpuset, Pproc); + hwloc_debug_2args_bitmap("cpu %lu (os %lu) has cpuset %s\n", + Lproc, Pproc, obj->cpuset); + hwloc_insert_object_by_cpuset(topology, obj); + } + + topology->support.discovery->pu = 1; + hwloc_bitmap_copy(online_cpuset, cpuset); + hwloc_bitmap_free(cpuset); + + hwloc_debug("%u online processors found\n", numprocs); + hwloc_debug_bitmap("online processor cpuset: %s\n", online_cpuset); + + hwloc_debug("%s", "\n * Topology summary *\n"); + hwloc_debug("%u processors)\n", numprocs); + + /* fill Lprocs[].Lpkg and Lpkg_to_Ppkg */ + for(Lproc=0; Lproc0) { + for (i = 0; i < numpkgs; i++) { + struct hwloc_obj *obj = hwloc_alloc_setup_object(HWLOC_OBJ_PACKAGE, Lpkg_to_Ppkg[i]); + int doneinfos = 0; + obj->cpuset = hwloc_bitmap_alloc(); + for(j=0; jcpuset, Lprocs[j].Pproc); + if (!doneinfos) { + hwloc__move_infos(&obj->infos, &obj->infos_count, &Lprocs[j].infos, &Lprocs[j].infos_count); + doneinfos = 1; + } + } + hwloc_debug_1arg_bitmap("package %d has cpuset %s\n", i, obj->cpuset); + hwloc_insert_object_by_cpuset(topology, obj); + } + hwloc_debug("%s", "\n"); + } + + /* fill Lprocs[].Lcore, Lcore_to_Ppkg and Lcore_to_Pcore */ + for(Lproc=0; Lproc0) { + for (i = 0; i < numcores; i++) { + struct hwloc_obj *obj = hwloc_alloc_setup_object(HWLOC_OBJ_CORE, Lcore_to_Pcore[i]); + obj->cpuset = hwloc_bitmap_alloc(); + for(j=0; jcpuset, Lprocs[j].Pproc); + hwloc_debug_1arg_bitmap("Core %d has cpuset %s\n", i, obj->cpuset); + hwloc_insert_object_by_cpuset(topology, obj); + } + hwloc_debug("%s", "\n"); + } + + free(Lcore_to_Pcore); + free(Lcore_to_Ppkg); + free(Lpkg_to_Ppkg); + + hwloc_linux_free_cpuinfo(Lprocs, numprocs, global_infos, global_infos_count); + + look_powerpc_device_tree(topology, data); + return 0; +} + + + +/************************************* + ****** Main Topology Discovery ****** + *************************************/ + +static void +hwloc__linux_get_mic_sn(struct hwloc_topology *topology, struct hwloc_linux_backend_data_s *data) +{ + FILE *file; + char line[64], *tmp, *end; + file = hwloc_fopen("/proc/elog", "r", data->root_fd); + if (!file) + return; + if (!fgets(line, sizeof(line), file)) + goto out_with_file; + if (strncmp(line, "Card ", 5)) + goto out_with_file; + tmp = line + 5; + end = strchr(tmp, ':'); + if (!end) + goto out_with_file; + *end = '\0'; + hwloc_obj_add_info(hwloc_get_root_obj(topology), "MICSerialNumber", tmp); + + out_with_file: + fclose(file); +} + +static void +hwloc_linux_fallback_pu_level(struct hwloc_topology *topology) +{ + if (topology->is_thissystem) + hwloc_setup_pu_level(topology, hwloc_fallback_nbprocessors(topology)); + else + /* fsys-root but not this system, no way, assume there's just 1 + * processor :/ */ + hwloc_setup_pu_level(topology, 1); +} + +static void +hwloc_gather_system_info(struct hwloc_topology *topology, + struct hwloc_linux_backend_data_s *data) +{ + FILE *file; + char line[128]; /* enough for utsname fields */ + const char *env; + + /* initialize to something sane */ + memset(&data->utsname, 0, sizeof(data->utsname)); + + /* read thissystem info */ + if (topology->is_thissystem) + uname(&data->utsname); + + /* overwrite with optional /proc/hwloc-nofile-info */ + file = hwloc_fopen("/proc/hwloc-nofile-info", "r", data->root_fd); + if (file) { + while (fgets(line, sizeof(line), file)) { + char *tmp = strchr(line, '\n'); + if (!strncmp("OSName: ", line, 8)) { + if (tmp) + *tmp = '\0'; + strncpy(data->utsname.sysname, line+8, sizeof(data->utsname.sysname)); + data->utsname.sysname[sizeof(data->utsname.sysname)-1] = '\0'; + } else if (!strncmp("OSRelease: ", line, 11)) { + if (tmp) + *tmp = '\0'; + strncpy(data->utsname.release, line+11, sizeof(data->utsname.release)); + data->utsname.release[sizeof(data->utsname.release)-1] = '\0'; + } else if (!strncmp("OSVersion: ", line, 11)) { + if (tmp) + *tmp = '\0'; + strncpy(data->utsname.version, line+11, sizeof(data->utsname.version)); + data->utsname.version[sizeof(data->utsname.version)-1] = '\0'; + } else if (!strncmp("HostName: ", line, 10)) { + if (tmp) + *tmp = '\0'; + strncpy(data->utsname.nodename, line+10, sizeof(data->utsname.nodename)); + data->utsname.nodename[sizeof(data->utsname.nodename)-1] = '\0'; + } else if (!strncmp("Architecture: ", line, 14)) { + if (tmp) + *tmp = '\0'; + strncpy(data->utsname.machine, line+14, sizeof(data->utsname.machine)); + data->utsname.machine[sizeof(data->utsname.machine)-1] = '\0'; + } else { + hwloc_debug("ignored /proc/hwloc-nofile-info line %s\n", line); + /* ignored */ + } + } + fclose(file); + } + + env = getenv("HWLOC_DUMP_NOFILE_INFO"); + if (env && *env) { + file = fopen(env, "w"); + if (file) { + if (*data->utsname.sysname) + fprintf(file, "OSName: %s\n", data->utsname.sysname); + if (*data->utsname.release) + fprintf(file, "OSRelease: %s\n", data->utsname.release); + if (*data->utsname.version) + fprintf(file, "OSVersion: %s\n", data->utsname.version); + if (*data->utsname.nodename) + fprintf(file, "HostName: %s\n", data->utsname.nodename); + if (*data->utsname.machine) + fprintf(file, "Architecture: %s\n", data->utsname.machine); + fclose(file); + } + } +} + +static int +hwloc_look_linuxfs(struct hwloc_backend *backend) +{ + struct hwloc_topology *topology = backend->topology; + struct hwloc_linux_backend_data_s *data = backend->private_data; + DIR *nodes_dir; + unsigned nbnodes; + char *cpuset_mntpnt, *cgroup_mntpnt, *cpuset_name = NULL; + int err; + + if (topology->levels[0][0]->cpuset) + /* somebody discovered things */ + return 0; + + hwloc_gather_system_info(topology, data); + + hwloc_alloc_obj_cpusets(topology->levels[0][0]); + + /* Gather the list of admin-disabled cpus and mems */ + hwloc_find_linux_cpuset_mntpnt(&cgroup_mntpnt, &cpuset_mntpnt, data->root_fd); + if (cgroup_mntpnt || cpuset_mntpnt) { + cpuset_name = hwloc_read_linux_cpuset_name(data->root_fd, topology->pid); + if (cpuset_name) { + hwloc_admin_disable_set_from_cpuset(data, cgroup_mntpnt, cpuset_mntpnt, cpuset_name, "cpus", topology->levels[0][0]->allowed_cpuset); + hwloc_admin_disable_set_from_cpuset(data, cgroup_mntpnt, cpuset_mntpnt, cpuset_name, "mems", topology->levels[0][0]->allowed_nodeset); + } + free(cgroup_mntpnt); + free(cpuset_mntpnt); + } + + nodes_dir = hwloc_opendir("/proc/nodes", data->root_fd); + if (nodes_dir) { + /* Kerrighed */ + struct dirent *dirent; + char path[128]; + hwloc_obj_t machine; + hwloc_bitmap_t machine_online_set; + + /* replace top-level object type with SYSTEM and add some MACHINE underneath */ + + topology->levels[0][0]->type = HWLOC_OBJ_SYSTEM; + topology->levels[0][0]->name = strdup("Kerrighed"); + + /* No cpuset support for now. */ + /* No sys support for now. */ + while ((dirent = readdir(nodes_dir)) != NULL) { + unsigned long node; + if (strncmp(dirent->d_name, "node", 4)) + continue; + machine_online_set = hwloc_bitmap_alloc(); + node = strtoul(dirent->d_name+4, NULL, 0); + snprintf(path, sizeof(path), "/proc/nodes/node%lu/cpuinfo", node); + err = look_cpuinfo(topology, data, path, machine_online_set); + if (err < 0) { + hwloc_bitmap_free(machine_online_set); + continue; + } + hwloc_bitmap_or(topology->levels[0][0]->online_cpuset, topology->levels[0][0]->online_cpuset, machine_online_set); + machine = hwloc_alloc_setup_object(HWLOC_OBJ_MACHINE, node); + machine->cpuset = machine_online_set; + hwloc_debug_1arg_bitmap("machine number %lu has cpuset %s\n", + node, machine_online_set); + + /* Get the machine memory attributes */ + hwloc_get_kerrighed_node_meminfo_info(topology, data, node, &machine->memory); + + /* Gather DMI info */ + /* FIXME: get the right DMI info of each machine */ + hwloc__get_dmi_id_info(data, machine); + + hwloc_insert_object_by_cpuset(topology, machine); + } + closedir(nodes_dir); + } else { + /* Get the machine memory attributes */ + hwloc_get_procfs_meminfo_info(topology, data, &topology->levels[0][0]->memory); + + /* Gather NUMA information. Must be after hwloc_get_procfs_meminfo_info so that the hugepage size is known */ + if (look_sysfsnode(topology, data, "/sys/bus/node/devices", &nbnodes) < 0) + look_sysfsnode(topology, data, "/sys/devices/system/node", &nbnodes); + + /* if we found some numa nodes, the machine object has no local memory */ + if (nbnodes) { + unsigned i; + topology->levels[0][0]->memory.local_memory = 0; + if (topology->levels[0][0]->memory.page_types) + for(i=0; ilevels[0][0]->memory.page_types_len; i++) + topology->levels[0][0]->memory.page_types[i].count = 0; + } + + /* Gather the list of cpus now */ + if (getenv("HWLOC_LINUX_USE_CPUINFO") + || (hwloc_access("/sys/devices/system/cpu/cpu0/topology/core_siblings", R_OK, data->root_fd) < 0 + && hwloc_access("/sys/devices/system/cpu/cpu0/topology/thread_siblings", R_OK, data->root_fd) < 0 + && hwloc_access("/sys/bus/cpu/devices/cpu0/topology/thread_siblings", R_OK, data->root_fd) < 0 + && hwloc_access("/sys/bus/cpu/devices/cpu0/topology/core_siblings", R_OK, data->root_fd) < 0)) { + /* revert to reading cpuinfo only if /sys/.../topology unavailable (before 2.6.16) + * or not containing anything interesting */ + err = look_cpuinfo(topology, data, "/proc/cpuinfo", topology->levels[0][0]->online_cpuset); + if (err < 0) + hwloc_linux_fallback_pu_level(topology); + + } else { + struct hwloc_linux_cpuinfo_proc * Lprocs = NULL; + struct hwloc_obj_info_s *global_infos = NULL; + unsigned global_infos_count = 0; + int numprocs = hwloc_linux_parse_cpuinfo(data, "/proc/cpuinfo", &Lprocs, &global_infos, &global_infos_count); + if (numprocs <= 0) + Lprocs = NULL; + if (look_sysfscpu(topology, data, "/sys/bus/cpu/devices", Lprocs, numprocs) < 0) + if (look_sysfscpu(topology, data, "/sys/devices/system/cpu", Lprocs, numprocs) < 0) + /* sysfs but we failed to read cpu topology, fallback */ + hwloc_linux_fallback_pu_level(topology); + hwloc__move_infos(&hwloc_get_root_obj(topology)->infos, &hwloc_get_root_obj(topology)->infos_count, + &global_infos, &global_infos_count); + hwloc_linux_free_cpuinfo(Lprocs, numprocs, global_infos, global_infos_count); + } + + /* Gather DMI info */ + hwloc__get_dmi_id_info(data, topology->levels[0][0]); + if (hwloc_topology_get_flags(topology) & (HWLOC_TOPOLOGY_FLAG_IO_DEVICES|HWLOC_TOPOLOGY_FLAG_WHOLE_IO)) + hwloc__get_firmware_dmi_memory_info(topology, data); + } + + hwloc_obj_add_info(topology->levels[0][0], "Backend", "Linux"); + if (cpuset_name) { + hwloc_obj_add_info(topology->levels[0][0], "LinuxCgroup", cpuset_name); + free(cpuset_name); + } + + hwloc__linux_get_mic_sn(topology, data); + + /* data->utsname was filled with real uname or \0, we can safely pass it */ + hwloc_add_uname_info(topology, &data->utsname); + + return 1; +} + + + +/**************************************** + ***** Linux PCI backend callbacks ****** + **************************************** + * Do not support changing the fsroot (use sysfs) + */ + +static hwloc_obj_t +hwloc_linux_add_os_device(struct hwloc_backend *backend, struct hwloc_obj *pcidev, hwloc_obj_osdev_type_t type, const char *name) +{ + struct hwloc_topology *topology = backend->topology; + struct hwloc_obj *obj = hwloc_alloc_setup_object(HWLOC_OBJ_OS_DEVICE, -1); + obj->name = strdup(name); + obj->logical_index = -1; + obj->attr->osdev.type = type; + + hwloc_insert_object_by_parent(topology, pcidev, obj); + /* insert_object_by_parent() doesn't merge during insert, so obj is still valid */ + + return obj; +} + +typedef void (*hwloc_linux_class_fillinfos_t)(struct hwloc_backend *backend, struct hwloc_obj *osdev, const char *osdevpath); + +/* cannot be used in fsroot-aware code, would have to move to a per-topology variable */ + +static void +hwloc_linux_check_deprecated_classlinks_model(struct hwloc_linux_backend_data_s *data) +{ + int root_fd = data->root_fd; + DIR *dir; + struct dirent *dirent; + char path[128]; + struct stat st; + + data->deprecated_classlinks_model = -1; + + dir = hwloc_opendir("/sys/class/net", root_fd); + if (!dir) + return; + while ((dirent = readdir(dir)) != NULL) { + if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, "..") || !strcmp(dirent->d_name, "lo")) + continue; + snprintf(path, sizeof(path), "/sys/class/net/%s/device/net/%s", dirent->d_name, dirent->d_name); + if (hwloc_stat(path, &st, root_fd) == 0) { + data->deprecated_classlinks_model = 0; + goto out; + } + snprintf(path, sizeof(path), "/sys/class/net/%s/device/net:%s", dirent->d_name, dirent->d_name); + if (hwloc_stat(path, &st, root_fd) == 0) { + data->deprecated_classlinks_model = 1; + goto out; + } + } +out: + closedir(dir); +} + +/* class objects that are immediately below pci devices: + * look for objects of the given classname below a sysfs (pcidev) directory + */ +static int +hwloc_linux_class_readdir(struct hwloc_backend *backend, + struct hwloc_obj *pcidev, const char *devicepath, + hwloc_obj_osdev_type_t type, const char *classname, + hwloc_linux_class_fillinfos_t fillinfo) +{ + struct hwloc_linux_backend_data_s *data = backend->private_data; + int root_fd = data->root_fd; + size_t classnamelen = strlen(classname); + char path[256]; + DIR *dir; + struct dirent *dirent; + hwloc_obj_t obj; + int res = 0, err; + + if (data->deprecated_classlinks_model == -2) + hwloc_linux_check_deprecated_classlinks_model(data); + + if (data->deprecated_classlinks_model != 1) { + /* modern sysfs: // */ + struct stat st; + snprintf(path, sizeof(path), "%s/%s", devicepath, classname); + + /* some very host kernel (2.6.9/RHEL4) have / symlink without any way to find . + * make sure / is a directory to avoid this case. + */ + err = hwloc_lstat(path, &st, root_fd); + if (err < 0 || !S_ISDIR(st.st_mode)) + goto trydeprecated; + + dir = hwloc_opendir(path, root_fd); + if (dir) { + data->deprecated_classlinks_model = 0; + while ((dirent = readdir(dir)) != NULL) { + if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, "..")) + continue; + obj = hwloc_linux_add_os_device(backend, pcidev, type, dirent->d_name); + if (fillinfo) { + snprintf(path, sizeof(path), "%s/%s/%s", devicepath, classname, dirent->d_name); + fillinfo(backend, obj, path); + } + res++; + } + closedir(dir); + return res; + } + } + +trydeprecated: + if (data->deprecated_classlinks_model != 0) { + /* deprecated sysfs: /: */ + dir = hwloc_opendir(devicepath, root_fd); + if (dir) { + while ((dirent = readdir(dir)) != NULL) { + if (strncmp(dirent->d_name, classname, classnamelen) || dirent->d_name[classnamelen] != ':') + continue; + data->deprecated_classlinks_model = 1; + obj = hwloc_linux_add_os_device(backend, pcidev, type, dirent->d_name + classnamelen+1); + if (fillinfo) { + snprintf(path, sizeof(path), "%s/%s", devicepath, dirent->d_name); + fillinfo(backend, obj, path); + } + res++; + } + closedir(dir); + return res; + } + } + + return 0; +} + +/* + * look for net objects below a pcidev in sysfs + */ +static void +hwloc_linux_net_class_fillinfos(struct hwloc_backend *backend, + struct hwloc_obj *obj, const char *osdevpath) +{ + struct hwloc_linux_backend_data_s *data = backend->private_data; + int root_fd = data->root_fd; + FILE *fd; + struct stat st; + char path[256]; + snprintf(path, sizeof(path), "%s/address", osdevpath); + fd = hwloc_fopen(path, "r", root_fd); + if (fd) { + char address[128]; + if (fgets(address, sizeof(address), fd)) { + char *eol = strchr(address, '\n'); + if (eol) + *eol = 0; + hwloc_obj_add_info(obj, "Address", address); + } + fclose(fd); + } + snprintf(path, sizeof(path), "%s/device/infiniband", osdevpath); + if (!hwloc_stat(path, &st, root_fd)) { + snprintf(path, sizeof(path), "%s/dev_id", osdevpath); + fd = hwloc_fopen(path, "r", root_fd); + if (fd) { + char hexid[16]; + if (fgets(hexid, sizeof(hexid), fd)) { + char *eoid; + unsigned long port; + port = strtoul(hexid, &eoid, 0); + if (eoid != hexid) { + char portstr[16]; + snprintf(portstr, sizeof(portstr), "%ld", port+1); + hwloc_obj_add_info(obj, "Port", portstr); + } + } + fclose(fd); + } + } +} + +static int +hwloc_linux_lookup_net_class(struct hwloc_backend *backend, + struct hwloc_obj *pcidev, const char *pcidevpath) +{ + return hwloc_linux_class_readdir(backend, pcidev, pcidevpath, HWLOC_OBJ_OSDEV_NETWORK, "net", hwloc_linux_net_class_fillinfos); +} + +/* + * look for infiniband objects below a pcidev in sysfs + */ +static void +hwloc_linux_infiniband_class_fillinfos(struct hwloc_backend *backend, + struct hwloc_obj *obj, const char *osdevpath) +{ + struct hwloc_linux_backend_data_s *data = backend->private_data; + int root_fd = data->root_fd; + FILE *fd; + char path[256]; + unsigned i,j; + + snprintf(path, sizeof(path), "%s/node_guid", osdevpath); + fd = hwloc_fopen(path, "r", root_fd); + if (fd) { + char guidvalue[20]; + if (fgets(guidvalue, sizeof(guidvalue), fd)) { + size_t len; + len = strspn(guidvalue, "0123456789abcdefx:"); + assert(len == 19); + guidvalue[len] = '\0'; + hwloc_obj_add_info(obj, "NodeGUID", guidvalue); + } + fclose(fd); + } + + snprintf(path, sizeof(path), "%s/sys_image_guid", osdevpath); + fd = hwloc_fopen(path, "r", root_fd); + if (fd) { + char guidvalue[20]; + if (fgets(guidvalue, sizeof(guidvalue), fd)) { + size_t len; + len = strspn(guidvalue, "0123456789abcdefx:"); + assert(len == 19); + guidvalue[len] = '\0'; + hwloc_obj_add_info(obj, "SysImageGUID", guidvalue); + } + fclose(fd); + } + + for(i=1; ; i++) { + snprintf(path, sizeof(path), "%s/ports/%u/state", osdevpath, i); + fd = hwloc_fopen(path, "r", root_fd); + if (fd) { + char statevalue[2]; + if (fgets(statevalue, sizeof(statevalue), fd)) { + char statename[32]; + statevalue[1] = '\0'; /* only keep the first byte/digit */ + snprintf(statename, sizeof(statename), "Port%uState", i); + hwloc_obj_add_info(obj, statename, statevalue); + } + fclose(fd); + } else { + /* no such port */ + break; + } + + snprintf(path, sizeof(path), "%s/ports/%u/lid", osdevpath, i); + fd = hwloc_fopen(path, "r", root_fd); + if (fd) { + char lidvalue[11]; + if (fgets(lidvalue, sizeof(lidvalue), fd)) { + char lidname[32]; + size_t len; + len = strspn(lidvalue, "0123456789abcdefx"); + lidvalue[len] = '\0'; + snprintf(lidname, sizeof(lidname), "Port%uLID", i); + hwloc_obj_add_info(obj, lidname, lidvalue); + } + fclose(fd); + } + + snprintf(path, sizeof(path), "%s/ports/%u/lid_mask_count", osdevpath, i); + fd = hwloc_fopen(path, "r", root_fd); + if (fd) { + char lidvalue[11]; + if (fgets(lidvalue, sizeof(lidvalue), fd)) { + char lidname[32]; + size_t len; + len = strspn(lidvalue, "0123456789"); + lidvalue[len] = '\0'; + snprintf(lidname, sizeof(lidname), "Port%uLMC", i); + hwloc_obj_add_info(obj, lidname, lidvalue); + } + fclose(fd); + } + + for(j=0; ; j++) { + snprintf(path, sizeof(path), "%s/ports/%u/gids/%u", osdevpath, i, j); + fd = hwloc_fopen(path, "r", root_fd); + if (fd) { + char gidvalue[40]; + if (fgets(gidvalue, sizeof(gidvalue), fd)) { + char gidname[32]; + size_t len; + len = strspn(gidvalue, "0123456789abcdefx:"); + assert(len == 39); + gidvalue[len] = '\0'; + if (strncmp(gidvalue+20, "0000:0000:0000:0000", 19)) { + /* only keep initialized GIDs */ + snprintf(gidname, sizeof(gidname), "Port%uGID%u", i, j); + hwloc_obj_add_info(obj, gidname, gidvalue); + } + } + fclose(fd); + } else { + /* no such port */ + break; + } + } + } +} + +static int +hwloc_linux_lookup_openfabrics_class(struct hwloc_backend *backend, + struct hwloc_obj *pcidev, const char *pcidevpath) +{ + return hwloc_linux_class_readdir(backend, pcidev, pcidevpath, HWLOC_OBJ_OSDEV_OPENFABRICS, "infiniband", hwloc_linux_infiniband_class_fillinfos); +} + +/* look for dma objects below a pcidev in sysfs */ +static int +hwloc_linux_lookup_dma_class(struct hwloc_backend *backend, + struct hwloc_obj *pcidev, const char *pcidevpath) +{ + return hwloc_linux_class_readdir(backend, pcidev, pcidevpath, HWLOC_OBJ_OSDEV_DMA, "dma", NULL); +} + +/* look for drm objects below a pcidev in sysfs */ +static int +hwloc_linux_lookup_drm_class(struct hwloc_backend *backend, + struct hwloc_obj *pcidev, const char *pcidevpath) +{ + return hwloc_linux_class_readdir(backend, pcidev, pcidevpath, HWLOC_OBJ_OSDEV_GPU, "drm", NULL); + + /* we could look at the "graphics" class too, but it doesn't help for proprietary drivers either */ + + /* GPU devices (even with a proprietary driver) seem to have a boot_vga field in their PCI device directory (since 2.6.30), + * so we could create a OS device for each PCI devices with such a field. + * boot_vga is actually created when class >> 8 == VGA (it contains 1 for boot vga device), so it's trivial anyway. + */ +} + +/* + * look for block objects below a pcidev in sysfs + */ + +static void +hwloc_linux_block_class_fillinfos(struct hwloc_backend *backend, + struct hwloc_obj *obj, const char *osdevpath) +{ + struct hwloc_linux_backend_data_s *data = backend->private_data; + int root_fd = data->root_fd; + FILE *fd; + char path[256]; + char line[128]; + char vendor[64] = ""; + char model[64] = ""; + char serial[64] = ""; + char revision[64] = ""; + char blocktype[64] = ""; + unsigned major_id, minor_id; + char *tmp; + + snprintf(path, sizeof(path), "%s/dev", osdevpath); + fd = hwloc_fopen(path, "r", root_fd); + if (!fd) + return; + + if (NULL == fgets(line, sizeof(line), fd)) { + fclose(fd); + return; + } + fclose(fd); + + if (sscanf(line, "%u:%u", &major_id, &minor_id) != 2) + return; + tmp = strchr(line, '\n'); + if (tmp) + *tmp = '\0'; + hwloc_obj_add_info(obj, "LinuxDeviceID", line); + +#ifdef HAVE_LIBUDEV_H + if (data->udev) { + struct udev_device *dev; + const char *prop; + dev = udev_device_new_from_subsystem_sysname(data->udev, "block", obj->name); + if (!dev) + return; + prop = udev_device_get_property_value(dev, "ID_VENDOR"); + if (prop) + strcpy(vendor, prop); + prop = udev_device_get_property_value(dev, "ID_MODEL"); + if (prop) + strcpy(model, prop); + prop = udev_device_get_property_value(dev, "ID_REVISION"); + if (prop) + strcpy(revision, prop); + prop = udev_device_get_property_value(dev, "ID_SERIAL_SHORT"); + if (prop) + strcpy(serial, prop); + prop = udev_device_get_property_value(dev, "ID_TYPE"); + if (prop) + strcpy(blocktype, prop); + + udev_device_unref(dev); + } else + /* fallback to reading files, works with any fsroot */ +#endif + { + snprintf(path, sizeof(path), "/run/udev/data/b%u:%u", major_id, minor_id); + fd = hwloc_fopen(path, "r", root_fd); + if (!fd) + return; + + while (NULL != fgets(line, sizeof(line), fd)) { + tmp = strchr(line, '\n'); + if (tmp) + *tmp = '\0'; + if (!strncmp(line, "E:ID_VENDOR=", strlen("E:ID_VENDOR="))) { + strcpy(vendor, line+strlen("E:ID_VENDOR=")); + } else if (!strncmp(line, "E:ID_MODEL=", strlen("E:ID_MODEL="))) { + strcpy(model, line+strlen("E:ID_MODEL=")); + } else if (!strncmp(line, "E:ID_REVISION=", strlen("E:ID_REVISION="))) { + strcpy(revision, line+strlen("E:ID_REVISION=")); + } else if (!strncmp(line, "E:ID_SERIAL_SHORT=", strlen("E:ID_SERIAL_SHORT="))) { + strcpy(serial, line+strlen("E:ID_SERIAL_SHORT=")); + } else if (!strncmp(line, "E:ID_TYPE=", strlen("E:ID_TYPE="))) { + strcpy(blocktype, line+strlen("E:ID_TYPE=")); + } + } + fclose(fd); + } + + /* clear fake "ATA" vendor name */ + if (!strcasecmp(vendor, "ATA")) + *vendor = '\0'; + /* overwrite vendor name from model when possible */ + if (!*vendor) { + if (!strncasecmp(model, "wd", 2)) + strcpy(vendor, "Western Digital"); + else if (!strncasecmp(model, "st", 2)) + strcpy(vendor, "Seagate"); + else if (!strncasecmp(model, "samsung", 7)) + strcpy(vendor, "Samsung"); + else if (!strncasecmp(model, "sandisk", 7)) + strcpy(vendor, "SanDisk"); + else if (!strncasecmp(model, "toshiba", 7)) + strcpy(vendor, "Toshiba"); + } + + if (*vendor) + hwloc_obj_add_info(obj, "Vendor", vendor); + if (*model) + hwloc_obj_add_info(obj, "Model", model); + if (*revision) + hwloc_obj_add_info(obj, "Revision", revision); + if (*serial) + hwloc_obj_add_info(obj, "SerialNumber", serial); + + if (!strcmp(blocktype, "disk")) + hwloc_obj_add_info(obj, "Type", "Disk"); + else if (!strcmp(blocktype, "tape")) + hwloc_obj_add_info(obj, "Type", "Tape"); + else if (!strcmp(blocktype, "cd") || !strcmp(blocktype, "floppy") || !strcmp(blocktype, "optical")) + hwloc_obj_add_info(obj, "Type", "Removable Media Device"); + else /* generic, usb mass storage/rbc, usb mass storage/scsi */ + hwloc_obj_add_info(obj, "Type", "Other"); +} + +/* block class objects are in + * host%d/target%d:%d:%d/%d:%d:%d:%d/ + * or + * host%d/port-%d:%d/end_device-%d:%d/target%d:%d:%d/%d:%d:%d:%d/ + * or + * ide%d/%d.%d/ + * below pci devices */ +static int +hwloc_linux_lookup_host_block_class(struct hwloc_backend *backend, + struct hwloc_obj *pcidev, char *path, size_t pathlen) +{ + struct hwloc_linux_backend_data_s *data = backend->private_data; + int root_fd = data->root_fd; + DIR *hostdir, *portdir, *targetdir; + struct dirent *hostdirent, *portdirent, *targetdirent; + size_t hostdlen, portdlen, targetdlen; + int dummy; + int res = 0; + + hostdir = hwloc_opendir(path, root_fd); + if (!hostdir) + return 0; + + while ((hostdirent = readdir(hostdir)) != NULL) { + if (sscanf(hostdirent->d_name, "port-%d:%d", &dummy, &dummy) == 2) + { + /* found host%d/port-%d:%d */ + path[pathlen] = '/'; + strcpy(&path[pathlen+1], hostdirent->d_name); + pathlen += hostdlen = 1+strlen(hostdirent->d_name); + portdir = hwloc_opendir(path, root_fd); + if (!portdir) + continue; + while ((portdirent = readdir(portdir)) != NULL) { + if (sscanf(portdirent->d_name, "end_device-%d:%d", &dummy, &dummy) == 2) { + /* found host%d/port-%d:%d/end_device-%d:%d */ + path[pathlen] = '/'; + strcpy(&path[pathlen+1], portdirent->d_name); + pathlen += portdlen = 1+strlen(portdirent->d_name); + res += hwloc_linux_lookup_host_block_class(backend, pcidev, path, pathlen); + /* restore parent path */ + pathlen -= portdlen; + path[pathlen] = '\0'; + } + } + closedir(portdir); + /* restore parent path */ + pathlen -= hostdlen; + path[pathlen] = '\0'; + continue; + } else if (sscanf(hostdirent->d_name, "target%d:%d:%d", &dummy, &dummy, &dummy) == 3) { + /* found host%d/target%d:%d:%d */ + path[pathlen] = '/'; + strcpy(&path[pathlen+1], hostdirent->d_name); + pathlen += hostdlen = 1+strlen(hostdirent->d_name); + targetdir = hwloc_opendir(path, root_fd); + if (!targetdir) + continue; + while ((targetdirent = readdir(targetdir)) != NULL) { + if (sscanf(targetdirent->d_name, "%d:%d:%d:%d", &dummy, &dummy, &dummy, &dummy) != 4) + continue; + /* found host%d/target%d:%d:%d/%d:%d:%d:%d */ + path[pathlen] = '/'; + strcpy(&path[pathlen+1], targetdirent->d_name); + pathlen += targetdlen = 1+strlen(targetdirent->d_name); + /* lookup block class for real */ + res += hwloc_linux_class_readdir(backend, pcidev, path, HWLOC_OBJ_OSDEV_BLOCK, "block", hwloc_linux_block_class_fillinfos); + /* restore parent path */ + pathlen -= targetdlen; + path[pathlen] = '\0'; + } + closedir(targetdir); + /* restore parent path */ + pathlen -= hostdlen; + path[pathlen] = '\0'; + } + } + closedir(hostdir); + + return res; +} + +static int +hwloc_linux_lookup_block_class(struct hwloc_backend *backend, + struct hwloc_obj *pcidev, const char *pcidevpath) +{ + struct hwloc_linux_backend_data_s *data = backend->private_data; + int root_fd = data->root_fd; + size_t pathlen; + DIR *devicedir, *hostdir; + struct dirent *devicedirent, *hostdirent; + size_t devicedlen, hostdlen; + char path[256]; + int dummy; + int res = 0; + + strcpy(path, pcidevpath); + pathlen = strlen(path); + + devicedir = hwloc_opendir(pcidevpath, root_fd); + if (!devicedir) + return 0; + + while ((devicedirent = readdir(devicedir)) != NULL) { + if (sscanf(devicedirent->d_name, "ide%d", &dummy) == 1) { + /* found ide%d */ + path[pathlen] = '/'; + strcpy(&path[pathlen+1], devicedirent->d_name); + pathlen += devicedlen = 1+strlen(devicedirent->d_name); + hostdir = hwloc_opendir(path, root_fd); + if (!hostdir) + continue; + while ((hostdirent = readdir(hostdir)) != NULL) { + if (sscanf(hostdirent->d_name, "%d.%d", &dummy, &dummy) == 2) { + /* found ide%d/%d.%d */ + path[pathlen] = '/'; + strcpy(&path[pathlen+1], hostdirent->d_name); + pathlen += hostdlen = 1+strlen(hostdirent->d_name); + /* lookup block class for real */ + res += hwloc_linux_class_readdir(backend, pcidev, path, HWLOC_OBJ_OSDEV_BLOCK, "block", NULL); + /* restore parent path */ + pathlen -= hostdlen; + path[pathlen] = '\0'; + } + } + closedir(hostdir); + /* restore parent path */ + pathlen -= devicedlen; + path[pathlen] = '\0'; + } else if (sscanf(devicedirent->d_name, "host%d", &dummy) == 1) { + /* found host%d */ + path[pathlen] = '/'; + strcpy(&path[pathlen+1], devicedirent->d_name); + pathlen += devicedlen = 1+strlen(devicedirent->d_name); + res += hwloc_linux_lookup_host_block_class(backend, pcidev, path, pathlen); + /* restore parent path */ + pathlen -= devicedlen; + path[pathlen] = '\0'; + } else if (sscanf(devicedirent->d_name, "ata%d", &dummy) == 1) { + /* found ata%d */ + path[pathlen] = '/'; + strcpy(&path[pathlen+1], devicedirent->d_name); + pathlen += devicedlen = 1+strlen(devicedirent->d_name); + hostdir = hwloc_opendir(path, root_fd); + if (!hostdir) + continue; + while ((hostdirent = readdir(hostdir)) != NULL) { + if (sscanf(hostdirent->d_name, "host%d", &dummy) == 1) { + /* found ata%d/host%d */ + path[pathlen] = '/'; + strcpy(&path[pathlen+1], hostdirent->d_name); + pathlen += hostdlen = 1+strlen(hostdirent->d_name); + /* lookup block class for real */ + res += hwloc_linux_lookup_host_block_class(backend, pcidev, path, pathlen); + /* restore parent path */ + pathlen -= hostdlen; + path[pathlen] = '\0'; + } + } + closedir(hostdir); + /* restore parent path */ + pathlen -= devicedlen; + path[pathlen] = '\0'; + } + } + closedir(devicedir); + + return res; +} + +static void +hwloc_linux_mic_class_fillinfos(struct hwloc_backend *backend, + struct hwloc_obj *obj, const char *osdevpath) +{ + struct hwloc_linux_backend_data_s *data = backend->private_data; + int root_fd = data->root_fd; + FILE *fd; + char path[256]; + + hwloc_obj_add_info(obj, "CoProcType", "MIC"); + + snprintf(path, sizeof(path), "%s/family", osdevpath); + fd = hwloc_fopen(path, "r", root_fd); + if (fd) { + char family[64]; + if (fgets(family, sizeof(family), fd)) { + char *eol = strchr(family, '\n'); + if (eol) + *eol = 0; + hwloc_obj_add_info(obj, "MICFamily", family); + } + fclose(fd); + } + + snprintf(path, sizeof(path), "%s/sku", osdevpath); + fd = hwloc_fopen(path, "r", root_fd); + if (fd) { + char sku[64]; + if (fgets(sku, sizeof(sku), fd)) { + char *eol = strchr(sku, '\n'); + if (eol) + *eol = 0; + hwloc_obj_add_info(obj, "MICSKU", sku); + } + fclose(fd); + } + + snprintf(path, sizeof(path), "%s/serialnumber", osdevpath); + fd = hwloc_fopen(path, "r", root_fd); + if (fd) { + char sn[64]; + if (fgets(sn, sizeof(sn), fd)) { + char *eol = strchr(sn, '\n'); + if (eol) + *eol = 0; + hwloc_obj_add_info(obj, "MICSerialNumber", sn); + } + fclose(fd); + } + + snprintf(path, sizeof(path), "%s/active_cores", osdevpath); + fd = hwloc_fopen(path, "r", root_fd); + if (fd) { + char string[10]; + if (fgets(string, sizeof(string), fd)) { + unsigned long count = strtoul(string, NULL, 16); + snprintf(string, sizeof(string), "%lu", count); + hwloc_obj_add_info(obj, "MICActiveCores", string); + } + fclose(fd); + } + + snprintf(path, sizeof(path), "%s/memsize", osdevpath); + fd = hwloc_fopen(path, "r", root_fd); + if (fd) { + char string[20]; + if (fgets(string, sizeof(string), fd)) { + unsigned long count = strtoul(string, NULL, 16); + snprintf(string, sizeof(string), "%lu", count); + hwloc_obj_add_info(obj, "MICMemorySize", string); + } + fclose(fd); + } +} + +static int +hwloc_linux_lookup_mic_class(struct hwloc_backend *backend, + struct hwloc_obj *pcidev, const char *pcidevpath) +{ + return hwloc_linux_class_readdir(backend, pcidev, pcidevpath, HWLOC_OBJ_OSDEV_COPROC, "mic", hwloc_linux_mic_class_fillinfos); +} + +static int +hwloc_linux_directlookup_mic_class(struct hwloc_backend *backend, + struct hwloc_obj *pcidev) +{ + struct hwloc_linux_backend_data_s *data = backend->private_data; + int root_fd = data->root_fd; + char path[256]; + struct stat st; + hwloc_obj_t obj; + unsigned idx; + int res = 0; + + if (!data->mic_directlookup_id_max) + /* already tried, nothing to do */ + return 0; + + if (data->mic_directlookup_id_max == (unsigned) -1) { + /* never tried, find out the max id */ + DIR *dir; + struct dirent *dirent; + + /* make sure we never do this lookup again */ + data->mic_directlookup_id_max = 0; + + /* read the entire class and find the max id of mic%u dirents */ + dir = hwloc_opendir("/sys/devices/virtual/mic", root_fd); + if (!dir) { + dir = opendir("/sys/class/mic"); + if (!dir) + return 0; + } + while ((dirent = readdir(dir)) != NULL) { + if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, "..")) + continue; + if (sscanf(dirent->d_name, "mic%u", &idx) != 1) + continue; + if (idx >= data->mic_directlookup_id_max) + data->mic_directlookup_id_max = idx+1; + } + closedir(dir); + } + + /* now iterate over the mic ids and see if one matches our pcidev */ + for(idx=0; idxmic_directlookup_id_max; idx++) { + snprintf(path, sizeof(path), "/sys/class/mic/mic%u/pci_%02x:%02x.%02x", + idx, pcidev->attr->pcidev.bus, pcidev->attr->pcidev.dev, pcidev->attr->pcidev.func); + if (hwloc_stat(path, &st, root_fd) < 0) + continue; + snprintf(path, sizeof(path), "mic%u", idx); + obj = hwloc_linux_add_os_device(backend, pcidev, HWLOC_OBJ_OSDEV_COPROC, path); + snprintf(path, sizeof(path), "/sys/class/mic/mic%u", idx); + hwloc_linux_mic_class_fillinfos(backend, obj, path); + res++; + } + + return res; +} + +/* + * backend callback for inserting objects inside a pci device + */ +static int +hwloc_linux_backend_notify_new_object(struct hwloc_backend *backend, struct hwloc_backend *caller __hwloc_attribute_unused, + struct hwloc_obj *obj) +{ + struct hwloc_linux_backend_data_s *data = backend->private_data; + char pcidevpath[256]; + int res = 0; + + /* this callback is only used in the libpci backend for now */ + assert(obj->type == HWLOC_OBJ_PCI_DEVICE); + + snprintf(pcidevpath, sizeof(pcidevpath), "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/", + obj->attr->pcidev.domain, obj->attr->pcidev.bus, + obj->attr->pcidev.dev, obj->attr->pcidev.func); + + res += hwloc_linux_lookup_net_class(backend, obj, pcidevpath); + res += hwloc_linux_lookup_openfabrics_class(backend, obj, pcidevpath); + res += hwloc_linux_lookup_dma_class(backend, obj, pcidevpath); + res += hwloc_linux_lookup_drm_class(backend, obj, pcidevpath); + res += hwloc_linux_lookup_block_class(backend, obj, pcidevpath); + + if (data->mic_need_directlookup == -1) { + struct stat st; + if (hwloc_stat("/sys/class/mic/mic0", &st, data->root_fd) == 0 + && hwloc_stat("/sys/class/mic/mic0/device/mic/mic0", &st, data->root_fd) == -1) + /* hwloc_linux_lookup_mic_class will fail because pcidev sysfs directories + * do not have mic/mic%u symlinks to mic devices (old mic driver). + * if so, try from the mic class. + */ + data->mic_need_directlookup = 1; + else + data->mic_need_directlookup = 0; + } + if (data->mic_need_directlookup) + res += hwloc_linux_directlookup_mic_class(backend, obj); + else + res += hwloc_linux_lookup_mic_class(backend, obj, pcidevpath); + + return res; +} + +/* + * backend callback for retrieving the location of a pci device + */ +static int +hwloc_linux_backend_get_obj_cpuset(struct hwloc_backend *backend, + struct hwloc_backend *caller __hwloc_attribute_unused, + struct hwloc_obj *obj, hwloc_bitmap_t cpuset) +{ + struct hwloc_linux_backend_data_s *data = backend->private_data; + char path[256]; + FILE *file; + int err; + + /* this callback is only used in the libpci backend for now */ + assert(obj->type == HWLOC_OBJ_PCI_DEVICE + || (obj->type == HWLOC_OBJ_BRIDGE && obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI)); + + snprintf(path, sizeof(path), "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/local_cpus", + obj->attr->pcidev.domain, obj->attr->pcidev.bus, + obj->attr->pcidev.dev, obj->attr->pcidev.func); + file = hwloc_fopen(path, "r", data->root_fd); + if (file) { + err = hwloc_linux_parse_cpumap_file(file, cpuset); + fclose(file); + if (!err && !hwloc_bitmap_iszero(cpuset)) + return 0; + } + return -1; +} + + + +/******************************* + ******* Linux component ******* + *******************************/ + +static void +hwloc_linux_backend_disable(struct hwloc_backend *backend) +{ + struct hwloc_linux_backend_data_s *data = backend->private_data; +#ifdef HAVE_OPENAT + close(data->root_fd); +#endif +#ifdef HAVE_LIBUDEV_H + if (data->udev) + udev_unref(data->udev); +#endif + free(data); +} + +static struct hwloc_backend * +hwloc_linux_component_instantiate(struct hwloc_disc_component *component, + const void *_data1, + const void *_data2 __hwloc_attribute_unused, + const void *_data3 __hwloc_attribute_unused) +{ + struct hwloc_backend *backend; + struct hwloc_linux_backend_data_s *data; + const char * fsroot_path = _data1; + int flags, root = -1; + + 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_linuxfs; + backend->get_obj_cpuset = hwloc_linux_backend_get_obj_cpuset; + backend->notify_new_object = hwloc_linux_backend_notify_new_object; + backend->disable = hwloc_linux_backend_disable; + + /* default values */ + data->is_real_fsroot = 1; + if (!fsroot_path) + fsroot_path = "/"; + +#ifdef HAVE_OPENAT + root = open(fsroot_path, O_RDONLY | O_DIRECTORY); + if (root < 0) + goto out_with_data; + + if (strcmp(fsroot_path, "/")) { + backend->is_thissystem = 0; + data->is_real_fsroot = 0; + } + + /* Since this fd stays open after hwloc returns, mark it as + close-on-exec so that children don't inherit it. Stevens says + that we should GETFD before we SETFD, so we do. */ + flags = fcntl(root, F_GETFD, 0); + if (-1 == flags || + -1 == fcntl(root, F_SETFD, FD_CLOEXEC | flags)) { + close(root); + root = -1; + goto out_with_data; + } +#else + if (strcmp(fsroot_path, "/")) { + errno = ENOSYS; + goto out_with_data; + } +#endif + data->root_fd = root; + +#ifdef HAVE_LIBUDEV_H + data->udev = NULL; + if (data->is_real_fsroot) { + data->udev = udev_new(); + } +#endif + + data->deprecated_classlinks_model = -2; /* never tried */ + data->mic_need_directlookup = -1; /* not initialized */ + data->mic_directlookup_id_max = -1; /* not initialized */ + + return backend; + + out_with_data: + free(data); + out_with_backend: + free(backend); + out: + return NULL; +} + +static struct hwloc_disc_component hwloc_linux_disc_component = { + HWLOC_DISC_COMPONENT_TYPE_CPU, + "linux", + HWLOC_DISC_COMPONENT_TYPE_GLOBAL, + hwloc_linux_component_instantiate, + 50, + NULL +}; + +const struct hwloc_component hwloc_linux_component = { + HWLOC_COMPONENT_ABI, + NULL, NULL, + HWLOC_COMPONENT_TYPE_DISC, + 0, + &hwloc_linux_disc_component +}; + + + + +#ifdef HWLOC_HAVE_LINUXPCI + +/*********************************** + ******* Linux PCI component ******* + ***********************************/ + +#define HWLOC_PCI_REVISION_ID 0x08 +#define HWLOC_PCI_CAP_ID_EXP 0x10 +#define HWLOC_PCI_CLASS_NOT_DEFINED 0x0000 + +static int +hwloc_look_linuxfs_pci(struct hwloc_backend *backend) +{ + struct hwloc_topology *topology = backend->topology; + struct hwloc_backend *tmpbackend; + hwloc_obj_t first_obj = NULL, last_obj = NULL; + int root_fd = -1; + DIR *dir; + struct dirent *dirent; + int res = 0; + + if (!(hwloc_topology_get_flags(topology) & (HWLOC_TOPOLOGY_FLAG_IO_DEVICES|HWLOC_TOPOLOGY_FLAG_WHOLE_IO))) + return 0; + + if (hwloc_get_next_pcidev(topology, NULL)) { + hwloc_debug("%s", "PCI objects already added, ignoring linuxpci backend.\n"); + return 0; + } + + /* hackily find the linux backend to steal its fsroot */ + tmpbackend = topology->backends; + while (tmpbackend) { + if (tmpbackend->component == &hwloc_linux_disc_component) { + root_fd = ((struct hwloc_linux_backend_data_s *) tmpbackend->private_data)->root_fd; + hwloc_debug("linuxpci backend stole linux backend root_fd %d\n", root_fd); + break; } + tmpbackend = tmpbackend->next; + } + /* take our own descriptor, either pointing to linux fsroot, or to / if not found */ + if (root_fd >= 0) + root_fd = dup(root_fd); + else + root_fd = open("/", O_RDONLY | O_DIRECTORY); + + dir = hwloc_opendir("/sys/bus/pci/devices/", root_fd); + if (!dir) + goto out_with_rootfd; + + while ((dirent = readdir(dir)) != NULL) { + unsigned domain, bus, dev, func; + hwloc_obj_t obj; + struct hwloc_pcidev_attr_s *attr; + unsigned os_index; + char path[64]; + char value[16]; + size_t read; + FILE *file; + + if (sscanf(dirent->d_name, "%04x:%02x:%02x.%01x", &domain, &bus, &dev, &func) != 4) + continue; + + os_index = (domain << 20) + (bus << 12) + (dev << 4) + func; + obj = hwloc_alloc_setup_object(HWLOC_OBJ_PCI_DEVICE, os_index); + if (!obj) + break; + attr = &obj->attr->pcidev; + + attr->domain = domain; + attr->bus = bus; + attr->dev = dev; + attr->func = func; + + /* default (unknown) values */ + attr->vendor_id = 0; + attr->device_id = 0; + attr->class_id = HWLOC_PCI_CLASS_NOT_DEFINED; + attr->revision = 0; + attr->subvendor_id = 0; + attr->subdevice_id = 0; + attr->linkspeed = 0; + + snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/vendor", dirent->d_name); + file = hwloc_fopen(path, "r", root_fd); + if (file) { + read = fread(value, 1, sizeof(value), file); + fclose(file); + if (read) + attr->vendor_id = strtoul(value, NULL, 16); + } + snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/device", dirent->d_name); + file = hwloc_fopen(path, "r", root_fd); + if (file) { + read = fread(value, 1, sizeof(value), file); + fclose(file); + if (read) + attr->device_id = strtoul(value, NULL, 16); + } + snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/class", dirent->d_name); + file = hwloc_fopen(path, "r", root_fd); + if (file) { + read = fread(value, 1, sizeof(value), file); + fclose(file); + if (read) + attr->class_id = strtoul(value, NULL, 16) >> 8; + } + snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/subsystem_vendor", dirent->d_name); + file = hwloc_fopen(path, "r", root_fd); + if (file) { + read = fread(value, 1, sizeof(value), file); + fclose(file); + if (read) + attr->subvendor_id = strtoul(value, NULL, 16); + } + snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/subsystem_device", dirent->d_name); + file = hwloc_fopen(path, "r", root_fd); + if (file) { + read = fread(value, 1, sizeof(value), file); + fclose(file); + if (read) + attr->subdevice_id = strtoul(value, NULL, 16); + } + + snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/config", dirent->d_name); + file = hwloc_fopen(path, "r", root_fd); + if (file) { +#define CONFIG_SPACE_CACHESIZE 256 + unsigned char config_space_cache[CONFIG_SPACE_CACHESIZE]; + unsigned offset; + + /* initialize the config space in case we fail to read it (missing permissions, etc). */ + memset(config_space_cache, 0xff, CONFIG_SPACE_CACHESIZE); + read = fread(config_space_cache, 1, CONFIG_SPACE_CACHESIZE, file); + (void) read; /* we initialized config_space_cache in case we don't read enough, ignore the read length */ + fclose(file); + + /* is this a bridge? */ + hwloc_pci_prepare_bridge(obj, config_space_cache); + + /* get the revision */ + attr->revision = config_space_cache[HWLOC_PCI_REVISION_ID]; + + /* try to get the link speed */ + offset = hwloc_pci_find_cap(config_space_cache, HWLOC_PCI_CAP_ID_EXP); + if (offset > 0 && offset + 20 /* size of PCI express block up to link status */ <= CONFIG_SPACE_CACHESIZE) + hwloc_pci_find_linkspeed(config_space_cache, offset, &attr->linkspeed); + } + + if (first_obj) + last_obj->next_sibling = obj; + else + first_obj = obj; + last_obj = obj; + } + + closedir(dir); + + dir = hwloc_opendir("/sys/bus/pci/slots/", root_fd); + if (dir) { + while ((dirent = readdir(dir)) != NULL) { + char path[64]; + FILE *file; + if (dirent->d_name[0] == '.') + continue; + snprintf(path, sizeof(path), "/sys/bus/pci/slots/%s/address", dirent->d_name); + file = hwloc_fopen(path, "r", root_fd); + if (file) { + unsigned domain, bus, dev; + if (fscanf(file, "%x:%x:%x", &domain, &bus, &dev) == 3) { + hwloc_obj_t obj = first_obj; + while (obj) { + if (obj->attr->pcidev.domain == domain + && obj->attr->pcidev.bus == bus + && obj->attr->pcidev.dev == dev + && obj->attr->pcidev.func == 0) { + hwloc_obj_add_info(obj, "PCISlot", dirent->d_name); + break; + } + obj = obj->next_sibling; + } + } + fclose(file); + } + } + closedir(dir); + } + + res = hwloc_insert_pci_device_list(backend, first_obj); + + out_with_rootfd: + close(root_fd); + return res; +} + +static struct hwloc_backend * +hwloc_linuxpci_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; + + /* thissystem may not be fully initialized yet, we'll check flags in discover() */ + + backend = hwloc_backend_alloc(component); + if (!backend) + return NULL; + backend->flags = HWLOC_BACKEND_FLAG_NEED_LEVELS; + backend->discover = hwloc_look_linuxfs_pci; + return backend; +} + +static struct hwloc_disc_component hwloc_linuxpci_disc_component = { + HWLOC_DISC_COMPONENT_TYPE_MISC, + "linuxpci", + HWLOC_DISC_COMPONENT_TYPE_GLOBAL, + hwloc_linuxpci_component_instantiate, + 19, /* after pci */ + NULL +}; + +const struct hwloc_component hwloc_linuxpci_component = { + HWLOC_COMPONENT_ABI, + NULL, NULL, + HWLOC_COMPONENT_TYPE_DISC, + 0, + &hwloc_linuxpci_disc_component +}; + +#endif /* HWLOC_HAVE_LINUXPCI */ diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/topology-netbsd.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-netbsd.c new file mode 100644 index 0000000000..2c5fbaa0c3 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-netbsd.c @@ -0,0 +1,214 @@ +/* + * Copyright © 2012 Aleksej Saushev, The NetBSD Foundation + * Copyright © 2009-2014 Inria. All rights reserved. + * Copyright © 2009-2010 Université Bordeaux + * Copyright © 2011 Cisco Systems, Inc. All rights reserved. + * See COPYING in top-level directory. + */ + +#define _NETBSD_SOURCE /* request "_np" functions */ + +#include + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_SYSCTL_H +#include +#endif + +#include +#include +#include + +static void +hwloc_netbsd_bsd2hwloc(hwloc_bitmap_t hwloc_cpuset, const cpuset_t *cpuset) +{ + unsigned cpu, cpulimit; + int found = 0; + hwloc_bitmap_zero(hwloc_cpuset); + cpulimit = cpuset_size(cpuset) * CHAR_BIT; + for (cpu = 0; cpu < cpulimit; cpu++) + if (cpuset_isset(cpu, cpuset)) { + hwloc_bitmap_set(hwloc_cpuset, cpu); + found++; + } + /* when never bound, it returns an empty set, fill it instead */ + if (!found) + hwloc_bitmap_fill(hwloc_cpuset); +} + +static void +hwloc_netbsd_hwloc2bsd(hwloc_const_bitmap_t hwloc_cpuset, cpuset_t *cpuset) +{ + unsigned cpu, cpulimit; + cpuset_zero(cpuset); + cpulimit = cpuset_size(cpuset) * CHAR_BIT; + for (cpu = 0; cpu < cpulimit; cpu++) + if (hwloc_bitmap_isset(hwloc_cpuset, cpu)) + cpuset_set(cpu, cpuset); +} + +static int +hwloc_netbsd_set_proc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_pid_t pid, hwloc_const_bitmap_t hwloc_cpuset, int flags __hwloc_attribute_unused) +{ + int status; + cpuset_t *cpuset = cpuset_create(); + hwloc_netbsd_hwloc2bsd(hwloc_cpuset, cpuset); + status = sched_setaffinity_np(pid, cpuset_size(cpuset), cpuset); + cpuset_destroy(cpuset); + return status; +} + +static int +hwloc_netbsd_get_proc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_pid_t pid, hwloc_bitmap_t hwloc_cpuset, int flags __hwloc_attribute_unused) +{ + int status; + cpuset_t *cpuset = cpuset_create(); + status = sched_getaffinity_np(pid, cpuset_size(cpuset), cpuset); + hwloc_netbsd_bsd2hwloc(hwloc_cpuset, cpuset); + cpuset_destroy(cpuset); + return status; +} + + +static int +hwloc_netbsd_set_thisproc_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_cpuset, int flags) +{ + return hwloc_netbsd_set_proc_cpubind(topology, 0, hwloc_cpuset, flags); +} + +static int +hwloc_netbsd_get_thisproc_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_cpuset, int flags) +{ + return hwloc_netbsd_get_proc_cpubind(topology, 0, hwloc_cpuset, flags); +} + + +static int +hwloc_netbsd_set_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_thread_t tid, hwloc_const_bitmap_t hwloc_cpuset, int flags __hwloc_attribute_unused) +{ + int status; + cpuset_t *cpuset = cpuset_create(); + hwloc_netbsd_hwloc2bsd(hwloc_cpuset, cpuset); + status = pthread_setaffinity_np(tid, cpuset_size(cpuset), cpuset); + cpuset_destroy(cpuset); + + if (status) { + errno = status; + return -1; + } + return 0; +} + +static int +hwloc_netbsd_get_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_thread_t tid, hwloc_bitmap_t hwloc_cpuset, int flags __hwloc_attribute_unused) +{ + int status; + cpuset_t *cpuset = cpuset_create(); + status = pthread_getaffinity_np(tid, cpuset_size(cpuset), cpuset); + hwloc_netbsd_bsd2hwloc(hwloc_cpuset, cpuset); + cpuset_destroy(cpuset); + + if (status) { + errno = status; + return -1; + } + return 0; +} + + +static int +hwloc_netbsd_set_thisthread_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_cpuset, int flags) +{ + return hwloc_netbsd_set_thread_cpubind(topology, pthread_self(), hwloc_cpuset, flags); +} + +static int +hwloc_netbsd_get_thisthread_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_cpuset, int flags) +{ + return hwloc_netbsd_get_thread_cpubind(topology, pthread_self(), hwloc_cpuset, flags); +} + +#if (defined HAVE_SYSCTL) && (defined HAVE_SYS_SYSCTL_H) +static void +hwloc_netbsd_node_meminfo_info(struct hwloc_topology *topology) +{ + int mib[2] = { CTL_HW, HW_PHYSMEM64 }; + unsigned long physmem; + size_t len = sizeof(physmem); + sysctl(mib, 2, &physmem, &len, NULL, 0); + topology->levels[0][0]->memory.local_memory = physmem; +} +#endif + +static int +hwloc_look_netbsd(struct hwloc_backend *backend) +{ + struct hwloc_topology *topology = backend->topology; + unsigned nbprocs = hwloc_fallback_nbprocessors(topology); + + if (!topology->levels[0][0]->cpuset) { + /* Nobody (even the x86 backend) created objects yet, setup basic objects */ + hwloc_alloc_obj_cpusets(topology->levels[0][0]); + hwloc_setup_pu_level(topology, nbprocs); + } + + /* Add NetBSD specific information */ +#if (defined HAVE_SYSCTL) && (defined HAVE_SYS_SYSCTL_H) + hwloc_netbsd_node_meminfo_info(topology); +#endif + hwloc_obj_add_info(topology->levels[0][0], "Backend", "NetBSD"); + if (topology->is_thissystem) + hwloc_add_uname_info(topology, NULL); + return 1; +} + +void +hwloc_set_netbsd_hooks(struct hwloc_binding_hooks *hooks __hwloc_attribute_unused, + struct hwloc_topology_support *support __hwloc_attribute_unused) +{ + hooks->set_proc_cpubind = hwloc_netbsd_set_proc_cpubind; + hooks->get_proc_cpubind = hwloc_netbsd_get_proc_cpubind; + hooks->set_thisproc_cpubind = hwloc_netbsd_set_thisproc_cpubind; + hooks->get_thisproc_cpubind = hwloc_netbsd_get_thisproc_cpubind; + + hooks->set_thread_cpubind = hwloc_netbsd_set_thread_cpubind; + hooks->get_thread_cpubind = hwloc_netbsd_get_thread_cpubind; + hooks->set_thisthread_cpubind = hwloc_netbsd_set_thisthread_cpubind; + hooks->get_thisthread_cpubind = hwloc_netbsd_get_thisthread_cpubind; +} + +static struct hwloc_backend * +hwloc_netbsd_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_netbsd; + return backend; +} + +static struct hwloc_disc_component hwloc_netbsd_disc_component = { + HWLOC_DISC_COMPONENT_TYPE_CPU, + "netbsd", + HWLOC_DISC_COMPONENT_TYPE_GLOBAL, + hwloc_netbsd_component_instantiate, + 50, + NULL +}; + +const struct hwloc_component hwloc_netbsd_component = { + HWLOC_COMPONENT_ABI, + NULL, NULL, + HWLOC_COMPONENT_TYPE_DISC, + 0, + &hwloc_netbsd_disc_component +}; diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/topology-noos.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-noos.c new file mode 100644 index 0000000000..a926428e96 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-noos.c @@ -0,0 +1,58 @@ +/* + * Copyright © 2009 CNRS + * Copyright © 2009-2014 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 +#include +#include + +static int +hwloc_look_noos(struct hwloc_backend *backend) +{ + struct hwloc_topology *topology = backend->topology; + + if (topology->levels[0][0]->cpuset) + /* somebody discovered things */ + return 0; + + hwloc_alloc_obj_cpusets(topology->levels[0][0]); + hwloc_setup_pu_level(topology, hwloc_fallback_nbprocessors(topology)); + if (topology->is_thissystem) + hwloc_add_uname_info(topology, NULL); + return 1; +} + +static struct hwloc_backend * +hwloc_noos_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_noos; + return backend; +} + +static struct hwloc_disc_component hwloc_noos_disc_component = { + HWLOC_DISC_COMPONENT_TYPE_CPU, + "no_os", + HWLOC_DISC_COMPONENT_TYPE_GLOBAL, + hwloc_noos_component_instantiate, + 40, /* lower than native OS component, higher than globals */ + NULL +}; + +const struct hwloc_component hwloc_noos_component = { + HWLOC_COMPONENT_ABI, + NULL, NULL, + HWLOC_COMPONENT_TYPE_DISC, + 0, + &hwloc_noos_disc_component +}; diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/topology-nvml.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-nvml.c new file mode 100644 index 0000000000..9c36d0a40b --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-nvml.c @@ -0,0 +1,239 @@ +/* + * 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/hwloc1110/hwloc/src/topology-opencl.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-opencl.c new file mode 100644 index 0000000000..85057c7c15 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-opencl.c @@ -0,0 +1,346 @@ +/* + * 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/hwloc1110/hwloc/src/topology-osf.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-osf.c new file mode 100644 index 0000000000..57158883d6 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-osf.c @@ -0,0 +1,392 @@ +/* + * Copyright © 2009 CNRS + * Copyright © 2009-2014 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; +} + +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(); +#ifdef HAVE__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/hwloc1110/hwloc/src/topology-pci.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-pci.c new file mode 100644 index 0000000000..3a3ad6bb55 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-pci.c @@ -0,0 +1,341 @@ +/* + * Copyright © 2009 CNRS + * Copyright © 2009-2014 Inria. All rights reserved. + * Copyright © 2009-2011, 2013 Université Bordeaux + * Copyright © 2014 Cisco Systems, Inc. All rights reserved. + * See COPYING in top-level directory. + */ + +#include +#include +#include +#include + +/* private headers allowed for convenience because this plugin is built within hwloc */ +#include +#include + +#include +#include +#include +#include +#include +#include +#ifdef HWLOC_LINUX_SYS +#include +#endif + +#include + +#ifndef PCI_HEADER_TYPE +#define PCI_HEADER_TYPE 0x0e +#endif +#ifndef PCI_HEADER_TYPE_BRIDGE +#define PCI_HEADER_TYPE_BRIDGE 1 +#endif + +#ifndef PCI_CLASS_DEVICE +#define PCI_CLASS_DEVICE 0x0a +#endif +#ifndef PCI_CLASS_BRIDGE_PCI +#define PCI_CLASS_BRIDGE_PCI 0x0604 +#endif + +#ifndef PCI_REVISION_ID +#define PCI_REVISION_ID 0x08 +#endif + +#ifndef PCI_SUBSYSTEM_VENDOR_ID +#define PCI_SUBSYSTEM_VENDOR_ID 0x2c +#endif +#ifndef PCI_SUBSYSTEM_ID +#define PCI_SUBSYSTEM_ID 0x2e +#endif + +#ifndef PCI_PRIMARY_BUS +#define PCI_PRIMARY_BUS 0x18 +#endif +#ifndef PCI_SECONDARY_BUS +#define PCI_SECONDARY_BUS 0x19 +#endif +#ifndef PCI_SUBORDINATE_BUS +#define PCI_SUBORDINATE_BUS 0x1a +#endif + +#ifndef PCI_CAP_ID_EXP +#define PCI_CAP_ID_EXP 0x10 +#endif + +#ifndef PCI_CAP_NORMAL +#define PCI_CAP_NORMAL 1 +#endif + +#define CONFIG_SPACE_CACHESIZE 256 + + +static int +hwloc_look_pci(struct hwloc_backend *backend) +{ + struct hwloc_topology *topology = backend->topology; + struct hwloc_obj *first_obj = NULL, *last_obj = NULL; + int ret; + struct pci_device_iterator *iter; + struct pci_device *pcidev; +#ifdef HWLOC_LINUX_SYS + DIR *dir; +#endif + + if (!(hwloc_topology_get_flags(topology) & (HWLOC_TOPOLOGY_FLAG_IO_DEVICES|HWLOC_TOPOLOGY_FLAG_WHOLE_IO))) + return 0; + + if (hwloc_get_next_pcidev(topology, NULL)) { + hwloc_debug("%s", "PCI objects already added, ignoring pci backend.\n"); + return 0; + } + + if (!hwloc_topology_is_thissystem(topology)) { + hwloc_debug("%s", "\nno PCI detection (not thissystem)\n"); + return 0; + } + + hwloc_debug("%s", "\nScanning PCI buses...\n"); + + /* initialize PCI scanning */ + ret = pci_system_init(); + if (ret) { + hwloc_debug("%s", "Can not initialize libpciaccess\n"); + return -1; + } + + iter = pci_slot_match_iterator_create(NULL); + + /* iterate over devices */ + for (pcidev = pci_device_next(iter); + pcidev; + pcidev = pci_device_next(iter)) + { + const char *vendorname, *devicename, *fullname; + unsigned char config_space_cache[CONFIG_SPACE_CACHESIZE]; + struct hwloc_obj *obj; + unsigned os_index; + unsigned domain; + unsigned device_class; + unsigned short tmp16; + char name[128]; + unsigned offset; + + /* initialize the config space in case we fail to read it (missing permissions, etc). */ + memset(config_space_cache, 0xff, CONFIG_SPACE_CACHESIZE); + pci_device_probe(pcidev); + pci_device_cfg_read(pcidev, config_space_cache, 0, CONFIG_SPACE_CACHESIZE, NULL); + + /* try to read the domain */ + domain = pcidev->domain; + + /* try to read the device_class */ + device_class = pcidev->device_class >> 8; + + /* fixup SR-IOV buggy VF device/vendor IDs */ + if (0xffff == pcidev->vendor_id && 0xffff == pcidev->device_id) { + /* SR-IOV puts ffff:ffff in Virtual Function config space. + * The actual VF device ID is stored at a special (dynamic) location in the Physical Function config space. + * VF and PF have the same vendor ID. + * + * libpciaccess just returns ffff:ffff, needs to be fixed. + * linuxpci is OK because sysfs files are already fixed the kernel. + * (pciutils is OK when it uses those Linux sysfs files.) + * + * Reading these files is an easy way to work around the libpciaccess issue on Linux, + * but we have no way to know if this is caused by SR-IOV or not. + * + * TODO: + * If PF has CAP_ID_PCIX or CAP_ID_EXP (offset>0), + * look for extended capability PCI_EXT_CAP_ID_SRIOV (need extended config space (more than 256 bytes)), + * then read the VF device ID after it (PCI_IOV_DID bytes later). + * Needs access to extended config space (needs root on Linux). + * TODO: + * Add string info attributes in VF and PF objects? + */ +#ifdef HWLOC_LINUX_SYS + /* Workaround for Linux (the kernel returns the VF device/vendor IDs). */ + char path[64]; + char value[16]; + FILE *file; + size_t read; + + snprintf(path, sizeof(path), "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/vendor", + domain, pcidev->bus, pcidev->dev, pcidev->func); + file = fopen(path, "r"); + if (file) { + read = fread(value, 1, sizeof(value), file); + fclose(file); + if (read) + /* fixup the pciaccess struct so that pci_device_get_vendor_name() is correct later. */ + pcidev->vendor_id = strtoul(value, NULL, 16); + } + + snprintf(path, sizeof(path), "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/device", + domain, pcidev->bus, pcidev->dev, pcidev->func); + file = fopen(path, "r"); + if (file) { + read = fread(value, 1, sizeof(value), file); + fclose(file); + if (read) + /* fixup the pciaccess struct so that pci_device_get_device_name() is correct later. */ + pcidev->device_id = strtoul(value, NULL, 16); + } +#endif + } + + /* might be useful for debugging (note that domain might be truncated) */ + os_index = (domain << 20) + (pcidev->bus << 12) + (pcidev->dev << 4) + pcidev->func; + + obj = hwloc_alloc_setup_object(HWLOC_OBJ_PCI_DEVICE, os_index); + obj->attr->pcidev.domain = domain; + obj->attr->pcidev.bus = pcidev->bus; + obj->attr->pcidev.dev = pcidev->dev; + obj->attr->pcidev.func = pcidev->func; + obj->attr->pcidev.vendor_id = pcidev->vendor_id; + obj->attr->pcidev.device_id = pcidev->device_id; + obj->attr->pcidev.class_id = device_class; + obj->attr->pcidev.revision = config_space_cache[PCI_REVISION_ID]; + + obj->attr->pcidev.linkspeed = 0; /* unknown */ + offset = hwloc_pci_find_cap(config_space_cache, PCI_CAP_ID_EXP); + + if (offset > 0 && offset + 20 /* size of PCI express block up to link status */ <= CONFIG_SPACE_CACHESIZE) + hwloc_pci_find_linkspeed(config_space_cache, offset, &obj->attr->pcidev.linkspeed); + + hwloc_pci_prepare_bridge(obj, config_space_cache); + + if (obj->type == HWLOC_OBJ_PCI_DEVICE) { + memcpy(&tmp16, &config_space_cache[PCI_SUBSYSTEM_VENDOR_ID], sizeof(tmp16)); + obj->attr->pcidev.subvendor_id = tmp16; + memcpy(&tmp16, &config_space_cache[PCI_SUBSYSTEM_ID], sizeof(tmp16)); + obj->attr->pcidev.subdevice_id = tmp16; + } else { + /* TODO: + * bridge must lookup PCI_CAP_ID_SSVID and then look at offset+PCI_SSVID_VENDOR/DEVICE_ID + * cardbus must look at PCI_CB_SUBSYSTEM_VENDOR_ID and PCI_CB_SUBSYSTEM_ID + */ + } + + /* get the vendor name */ + vendorname = pci_device_get_vendor_name(pcidev); + if (vendorname && *vendorname) + hwloc_obj_add_info(obj, "PCIVendor", vendorname); + + /* get the device name */ + devicename = pci_device_get_device_name(pcidev); + if (devicename && *devicename) + hwloc_obj_add_info(obj, "PCIDevice", devicename); + + /* generate or get the fullname */ + snprintf(name, sizeof(name), "%s%s%s", + vendorname ? vendorname : "", + vendorname && devicename ? " " : "", + devicename ? devicename : ""); + fullname = name; + if (*name) + obj->name = strdup(name); + hwloc_debug(" %04x:%02x:%02x.%01x %04x %04x:%04x %s\n", + domain, pcidev->bus, pcidev->dev, pcidev->func, + device_class, pcidev->vendor_id, pcidev->device_id, + fullname && *fullname ? fullname : "??"); + + /* queue the object for now */ + if (first_obj) + last_obj->next_sibling = obj; + else + first_obj = obj; + last_obj = obj; + } + + /* finalize device scanning */ + pci_iterator_destroy(iter); + pci_system_cleanup(); + +#ifdef HWLOC_LINUX_SYS + dir = opendir("/sys/bus/pci/slots/"); + if (dir) { + struct dirent *dirent; + while ((dirent = readdir(dir)) != NULL) { + char path[64]; + FILE *file; + if (dirent->d_name[0] == '.') + continue; + snprintf(path, sizeof(path), "/sys/bus/pci/slots/%s/address", dirent->d_name); + file = fopen(path, "r"); + if (file) { + unsigned domain, bus, dev; + if (fscanf(file, "%x:%x:%x", &domain, &bus, &dev) == 3) { + hwloc_obj_t obj = first_obj; + while (obj) { + if (obj->attr->pcidev.domain == domain + && obj->attr->pcidev.bus == bus + && obj->attr->pcidev.dev == dev + && obj->attr->pcidev.func == 0) { + hwloc_obj_add_info(obj, "PCISlot", dirent->d_name); + break; + } + obj = obj->next_sibling; + } + } + fclose(file); + } + } + closedir(dir); + } +#endif + + return hwloc_insert_pci_device_list(backend, first_obj); +} + +static struct hwloc_backend * +hwloc_pci_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; + + /* thissystem may not be fully initialized yet, we'll check flags in discover() */ + + backend = hwloc_backend_alloc(component); + if (!backend) + return NULL; + backend->flags = HWLOC_BACKEND_FLAG_NEED_LEVELS; + backend->discover = hwloc_look_pci; + return backend; +} + +static struct hwloc_disc_component hwloc_pci_disc_component = { + HWLOC_DISC_COMPONENT_TYPE_MISC, + "pci", + HWLOC_DISC_COMPONENT_TYPE_GLOBAL, + hwloc_pci_component_instantiate, + 20, + NULL +}; + +static int +hwloc_pci_component_init(unsigned long flags) +{ + if (flags) + return -1; + if (hwloc_plugin_check_namespace("pci", "hwloc_backend_alloc") < 0) + return -1; + return 0; +} + +#ifdef HWLOC_INSIDE_PLUGIN +HWLOC_DECLSPEC extern const struct hwloc_component hwloc_pci_component; +#endif + +const struct hwloc_component hwloc_pci_component = { + HWLOC_COMPONENT_ABI, + hwloc_pci_component_init, NULL, + HWLOC_COMPONENT_TYPE_DISC, + 0, + &hwloc_pci_disc_component +}; diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/topology-solaris-chiptype.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-solaris-chiptype.c new file mode 100644 index 0000000000..2127e128ff --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-solaris-chiptype.c @@ -0,0 +1,339 @@ +/* + * Copyright © 2009-2010 Oracle and/or its affiliates. All rights reserved. + * Copyright © 2013 Université Bordeaux. All rights reserved. + * + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#include +#include +#include +#include +#include + +#ifdef HAVE_PICL_H +#include +#include + +/***************************************************************************** + Order of this list is important for the assign_value and + assign_string_value routines +*****************************************************************************/ + +static const char* items[] = { + "clock-frequency", + "cpu-mhz", + "ecache-size", + "l2-cache-size", + "sectored-l2-cache-size", + "implementation#", + "manufacturer#", + "compatible", + "ProcessorType", + "vendor-id", + "brand-string" +}; + +#define NUM_ITEMS (sizeof(items) / sizeof(items[0])) + +/***************************************************************************** +SPARC strings for chip modes and implementation +*****************************************************************************/ +static const char* sparc_modes[] = { + "UNKNOWN", + "SPITFIRE", + "BLACKBIRD", + "CHEETAH", + "SPARC64_VI", + "T1", + "T2", + "SPARC64_VII", + "ROCK" +}; + +/***************************************************************************** +Default values are for Unknown so we can build up from there. +*****************************************************************************/ + +static long dss_chip_mode = MODE_UNKNOWN; +static long dss_chip_impl = IMPL_SPITFIRE; +static long dss_chip_cache = TWO_MEG_CACHE; +static long dss_chip_manufacturer = TI_MANUFACTURER; +static long long dss_chip_speed = SPITFIRE_SPEED; +static char dss_chip_type[PICL_PROPNAMELEN_MAX]; +static char dss_chip_model[PICL_PROPNAMELEN_MAX]; +static int called_cpu_probe = 0; + +/***************************************************************************** +Assigns values based on the value of index. For this reason, the order of +the items array is important. +*****************************************************************************/ +static void assign_value(int index, long long val) { + if (index == 0) { /* clock-frequency */ + dss_chip_speed = val; + } + if (index == 1) { /* cpu-mhz */ + dss_chip_speed = val * 1000000; /* Scale since value was in MHz */ + } + else if ((index >= 2) && (index <= 4)) { + /* ecache-size, l2-cache-size, sectored-l2-cache-size */ + dss_chip_cache = val; + } + else if (index == 5) { + /* implementation# T1, T2, and Rock do not have this, see RFE 6615268 */ + dss_chip_impl = val; + if (dss_chip_impl == IMPL_SPITFIRE) { + dss_chip_mode = 1; + } + else if ((dss_chip_impl >= IMPL_BLACKBIRD) && + (dss_chip_impl <= IMPL_HUMMINGBIRD)) { + dss_chip_mode = 2; + } + else if ((dss_chip_impl >= IMPL_CHEETAH) && + (dss_chip_impl <= IMPL_PANTHER)) { + dss_chip_mode = 3; + } + else if (dss_chip_impl == IMPL_SPARC64_VI) { + dss_chip_mode = 4; + } + else if (dss_chip_impl == IMPL_NIAGARA) { + dss_chip_mode = 5; + } + else if (dss_chip_impl == IMPL_NIAGARA_2) { + dss_chip_mode = 6; + } + else if (dss_chip_impl == IMPL_SPARC64_VII) { + dss_chip_mode = 7; + } + else if (dss_chip_impl == IMPL_ROCK) { + dss_chip_mode = 8; + } + } + else if (index == 6) { /* manufacturer# */ + dss_chip_manufacturer = val; + } +} + +/***************************************************************************** +Assigns values based on the value of index. For this reason, the order of +the items array is important. +*****************************************************************************/ +static void assign_string_value(int index, char* string_val) { + if (index == 7) { /* compatible */ + if (strncasecmp(string_val, "FJSV,SPARC64-VI", + PICL_PROPNAMELEN_MAX) == 0) { + dss_chip_mode = 4; + } + else if (strncasecmp(string_val, "SUNW,UltraSPARC-T1", + PICL_PROPNAMELEN_MAX) == 0) { + dss_chip_mode = 5; + } + else if (strncasecmp(string_val, "SUNW,UltraSPARC-T2", + PICL_PROPNAMELEN_MAX) == 0) { + dss_chip_mode = 6; + } + else if (strncasecmp(string_val, "FJSV,SPARC64-VII", + PICL_PROPNAMELEN_MAX) == 0) { + dss_chip_mode = 7; + } + else if (strncasecmp(string_val, "SUNW,Rock", + PICL_PROPNAMELEN_MAX) == 0) { + dss_chip_mode = 8; + } + } else if (index == 8) { /* ProcessorType */ + strncpy(&dss_chip_type[0], string_val, PICL_PROPNAMELEN_MAX); + } else if (index == 10) { /* brand-string */ + strncpy(&dss_chip_model[0], string_val, PICL_PROPNAMELEN_MAX); + } + +} + +/***************************************************************************** +Gets called by probe_cpu. Cycles through the table values until we find +what we are looking for. +*****************************************************************************/ +static void search_table(int index, picl_prophdl_t table_hdl) { + + picl_prophdl_t col_hdl; + picl_prophdl_t row_hdl; + picl_propinfo_t p_info; + int val; + char string_val[PICL_PROPNAMELEN_MAX]; + + for (val = picl_get_next_by_col(table_hdl, &row_hdl); val != PICL_ENDOFLIST; + val = picl_get_next_by_col(row_hdl, &row_hdl)) { + if (val == PICL_SUCCESS) { + for (col_hdl = row_hdl; val != PICL_ENDOFLIST; + val = picl_get_next_by_row(col_hdl, &col_hdl)) { + if (val == PICL_SUCCESS) { + val = picl_get_propinfo(col_hdl, &p_info); + if (val == PICL_SUCCESS) { + if (p_info.type == PICL_PTYPE_CHARSTRING) { + val = picl_get_propval(col_hdl, &string_val, sizeof(string_val)); + if (val == PICL_SUCCESS) { + assign_string_value(index, string_val); + } + } + } + } + } + } + } +} + +/***************************************************************************** +Gets called by picl_walk_tree_by_class. Then it cycles through the properties +until we find what we are looking for. Once we are done, we return +PICL_WALK_TERMINATE to stop picl_walk_tree_by_class from traversing the tree. + +Note that PICL_PTYPE_UNSIGNED_INT and PICL_PTYPE_INT can either be 4-bytes +or 8-bytes. +*****************************************************************************/ +static int probe_cpu(picl_nodehdl_t node_hdl, void* dummy_arg __hwloc_attribute_unused) { + + picl_prophdl_t p_hdl; + picl_prophdl_t table_hdl; + picl_propinfo_t p_info; + long long long_long_val; + unsigned int uint_val; + unsigned int index; + int int_val; + int val; + char string_val[PICL_PROPNAMELEN_MAX]; + + val = picl_get_first_prop(node_hdl, &p_hdl); + while (val == PICL_SUCCESS) { + called_cpu_probe = 1; + val = picl_get_propinfo(p_hdl, &p_info); + if (val == PICL_SUCCESS) { + for (index = 0; index < NUM_ITEMS; index++) { + if (strcasecmp(p_info.name, items[index]) == 0) { + if (p_info.type == PICL_PTYPE_UNSIGNED_INT) { + if (p_info.size == sizeof(uint_val)) { + val = picl_get_propval(p_hdl, &uint_val, sizeof(uint_val)); + if (val == PICL_SUCCESS) { + long_long_val = uint_val; + assign_value(index, long_long_val); + } + } + else if (p_info.size == sizeof(long_long_val)) { + val = picl_get_propval(p_hdl, &long_long_val, + sizeof(long_long_val)); + if (val == PICL_SUCCESS) { + assign_value(index, long_long_val); + } + } + } + else if (p_info.type == PICL_PTYPE_INT) { + if (p_info.size == sizeof(int_val)) { + val = picl_get_propval(p_hdl, &int_val, sizeof(int_val)); + if (val == PICL_SUCCESS) { + long_long_val = int_val; + assign_value(index, long_long_val); + } + } + else if (p_info.size == sizeof(long_long_val)) { + val = picl_get_propval(p_hdl, &long_long_val, + sizeof(long_long_val)); + if (val == PICL_SUCCESS) { + assign_value(index, long_long_val); + } + } + } + else if (p_info.type == PICL_PTYPE_CHARSTRING) { + val = picl_get_propval(p_hdl, &string_val, sizeof(string_val)); + if (val == PICL_SUCCESS) { + assign_string_value(index, string_val); + } + } + else if (p_info.type == PICL_PTYPE_TABLE) { + val = picl_get_propval(p_hdl, &table_hdl, p_info.size); + if (val == PICL_SUCCESS) { + search_table(index, table_hdl); + } + } + break; + } else if (index == NUM_ITEMS-1) { + if (p_info.type == PICL_PTYPE_CHARSTRING) { + val = picl_get_propval(p_hdl, &string_val, sizeof(string_val)); + if (val == PICL_SUCCESS) { + } + } + } + } + } + + val = picl_get_next_prop(p_hdl, &p_hdl); + } + return PICL_WALK_TERMINATE; +} + + +/***************************************************************************** +Initializes, gets the root, then walks the picl tree looking for information + +Currently, the "core" class is only needed for OPL systems +*****************************************************************************/ +char* hwloc_solaris_get_chip_type(void) { + picl_nodehdl_t root; + int val; + static char chip_type[PICL_PROPNAMELEN_MAX]; + + val = picl_initialize(); + if (val != PICL_SUCCESS) { /* Can't initialize session with PICL daemon */ + return(NULL); + } + val = picl_get_root(&root); + if (val != PICL_SUCCESS) { /* Failed to get root node of the PICL tree */ + return(NULL); + } + val = picl_walk_tree_by_class(root, "cpu", (void *)NULL, probe_cpu); + val = picl_walk_tree_by_class(root, "core", (void *)NULL, probe_cpu); + picl_shutdown(); + + if (called_cpu_probe) { +#if (defined HWLOC_X86_64_ARCH) || (defined HWLOC_X86_32_ARCH) + /* PICL returns some corrupted chip_type strings on x86, + * and CPUType only used on Sparc anyway, at least for now. + * So we just ignore this attribute on x86. */ +#else + strncpy(chip_type, dss_chip_type, PICL_PROPNAMELEN_MAX); +#endif + } else { + /* no picl information on machine available */ + sysinfo(SI_HW_PROVIDER, chip_type, PICL_PROPNAMELEN_MAX); + } + return(chip_type); +} + +/***************************************************************************** +Initializes, gets the root, then walks the picl tree looking for information + +Currently, the "core" class is only needed for OPL systems +*****************************************************************************/ +char *hwloc_solaris_get_chip_model(void) { + + if (called_cpu_probe) { + if (dss_chip_mode != MODE_UNKNOWN) { /* SPARC chip */ + strncpy(dss_chip_model, sparc_modes[dss_chip_mode], + PICL_PROPNAMELEN_MAX); + } + } else { + /* no picl information on machine available */ + sysinfo(SI_PLATFORM, dss_chip_model, PICL_PROPNAMELEN_MAX); + } + return(dss_chip_model); +} + +#else +char* hwloc_solaris_get_chip_type(void) { + return NULL; +} +char *hwloc_solaris_get_chip_model(void) { + return NULL; +} +#endif diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/topology-solaris.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-solaris.c new file mode 100644 index 0000000000..cd0e5aa339 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-solaris.c @@ -0,0 +1,804 @@ +/* + * Copyright © 2009 CNRS + * Copyright © 2009-2014 Inria. All rights reserved. + * Copyright © 2009-2011 Université Bordeaux + * Copyright © 2011 Cisco Systems, Inc. All rights reserved. + * Copyright © 2011 Oracle and/or its affiliates. All rights reserved. + * See COPYING in top-level directory. + */ + +#include +#include +#include +#include +#include + +#include +#include +#ifdef HAVE_DIRENT_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#include + +#ifdef HAVE_LIBLGRP +# include +#endif + +/* TODO: use psets? (only for root) + * TODO: get cache info from prtdiag? (it is setgid sys to be able to read from + * crw-r----- 1 root sys 88, 0 nov 3 14:35 /devices/pseudo/devinfo@0:devinfo + * and run (apparently undocumented) ioctls on it. + */ + +static int +hwloc_solaris_set_sth_cpubind(hwloc_topology_t topology, idtype_t idtype, id_t id, hwloc_const_bitmap_t hwloc_set, int flags) +{ + unsigned target_cpu; + + /* The resulting binding is always strict */ + + if (hwloc_bitmap_isequal(hwloc_set, hwloc_topology_get_complete_cpuset(topology))) { + if (processor_bind(idtype, id, PBIND_NONE, NULL) != 0) + return -1; +#ifdef HAVE_LIBLGRP + if (!(flags & HWLOC_CPUBIND_NOMEMBIND)) { + int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE); + if (depth >= 0) { + int n = hwloc_get_nbobjs_by_depth(topology, depth); + int i; + + for (i = 0; i < n; i++) { + hwloc_obj_t obj = hwloc_get_obj_by_depth(topology, depth, i); + lgrp_affinity_set(idtype, id, obj->os_index, LGRP_AFF_NONE); + } + } + } +#endif /* HAVE_LIBLGRP */ + return 0; + } + +#ifdef HAVE_LIBLGRP + if (!(flags & HWLOC_CPUBIND_NOMEMBIND)) { + int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE); + if (depth >= 0) { + int n = hwloc_get_nbobjs_by_depth(topology, depth); + int i; + int ok; + hwloc_bitmap_t target = hwloc_bitmap_alloc(); + + for (i = 0; i < n; i++) { + hwloc_obj_t obj = hwloc_get_obj_by_depth(topology, depth, i); + if (hwloc_bitmap_isincluded(obj->cpuset, hwloc_set)) + hwloc_bitmap_or(target, target, obj->cpuset); + } + + ok = hwloc_bitmap_isequal(target, hwloc_set); + hwloc_bitmap_free(target); + + if (ok) { + /* Ok, managed to achieve hwloc_set by just combining NUMA nodes */ + + for (i = 0; i < n; i++) { + hwloc_obj_t obj = hwloc_get_obj_by_depth(topology, depth, i); + + if (hwloc_bitmap_isincluded(obj->cpuset, hwloc_set)) { + lgrp_affinity_set(idtype, id, obj->os_index, LGRP_AFF_STRONG); + } else { + if (flags & HWLOC_CPUBIND_STRICT) + lgrp_affinity_set(idtype, id, obj->os_index, LGRP_AFF_NONE); + else + lgrp_affinity_set(idtype, id, obj->os_index, LGRP_AFF_WEAK); + } + } + + return 0; + } + } + } +#endif /* HAVE_LIBLGRP */ + + if (hwloc_bitmap_weight(hwloc_set) != 1) { + errno = EXDEV; + return -1; + } + + target_cpu = hwloc_bitmap_first(hwloc_set); + + if (processor_bind(idtype, id, + (processorid_t) (target_cpu), NULL) != 0) + return -1; + + return 0; +} + +static int +hwloc_solaris_set_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_bitmap_t hwloc_set, int flags) +{ + return hwloc_solaris_set_sth_cpubind(topology, P_PID, pid, hwloc_set, flags); +} + +static int +hwloc_solaris_set_thisproc_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags) +{ + return hwloc_solaris_set_sth_cpubind(topology, P_PID, P_MYID, hwloc_set, flags); +} + +static int +hwloc_solaris_set_thisthread_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags) +{ + return hwloc_solaris_set_sth_cpubind(topology, P_LWPID, P_MYID, hwloc_set, flags); +} + +#ifdef HAVE_LIBLGRP +static int +hwloc_solaris_get_sth_cpubind(hwloc_topology_t topology, idtype_t idtype, id_t id, hwloc_bitmap_t hwloc_set, int flags __hwloc_attribute_unused) +{ + processorid_t binding; + int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE); + int n; + int i; + + if (depth < 0) { + errno = ENOSYS; + return -1; + } + + /* first check if processor_bind() was used to bind to a single processor rather than to an lgroup */ + if ( processor_bind(idtype, id, PBIND_QUERY, &binding) == 0 && binding != PBIND_NONE ) { + hwloc_bitmap_only(hwloc_set, binding); + return 0; + } + + /* if not, check lgroups */ + hwloc_bitmap_zero(hwloc_set); + n = hwloc_get_nbobjs_by_depth(topology, depth); + for (i = 0; i < n; i++) { + hwloc_obj_t obj = hwloc_get_obj_by_depth(topology, depth, i); + lgrp_affinity_t aff = lgrp_affinity_get(idtype, id, obj->os_index); + + if (aff == LGRP_AFF_STRONG) + hwloc_bitmap_or(hwloc_set, hwloc_set, obj->cpuset); + } + + if (hwloc_bitmap_iszero(hwloc_set)) + hwloc_bitmap_copy(hwloc_set, hwloc_topology_get_complete_cpuset(topology)); + + return 0; +} + +static int +hwloc_solaris_get_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_bitmap_t hwloc_set, int flags) +{ + return hwloc_solaris_get_sth_cpubind(topology, P_PID, pid, hwloc_set, flags); +} + +static int +hwloc_solaris_get_thisproc_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_set, int flags) +{ + return hwloc_solaris_get_sth_cpubind(topology, P_PID, P_MYID, hwloc_set, flags); +} + +static int +hwloc_solaris_get_thisthread_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_set, int flags) +{ + return hwloc_solaris_get_sth_cpubind(topology, P_LWPID, P_MYID, hwloc_set, flags); +} +#endif /* HAVE_LIBLGRP */ + +/* TODO: given thread, probably not easy because of the historical n:m implementation */ +#ifdef HAVE_LIBLGRP +static int +hwloc_solaris_set_sth_membind(hwloc_topology_t topology, idtype_t idtype, id_t id, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) +{ + int depth; + int n, i; + + switch (policy) { + case HWLOC_MEMBIND_DEFAULT: + case HWLOC_MEMBIND_BIND: + break; + default: + errno = ENOSYS; + return -1; + } + + if (flags & HWLOC_MEMBIND_NOCPUBIND) { + errno = ENOSYS; + return -1; + } + + depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE); + if (depth < 0) { + errno = EXDEV; + return -1; + } + n = hwloc_get_nbobjs_by_depth(topology, depth); + + for (i = 0; i < n; i++) { + hwloc_obj_t obj = hwloc_get_obj_by_depth(topology, depth, i); + if (hwloc_bitmap_isset(nodeset, obj->os_index)) { + lgrp_affinity_set(idtype, id, obj->os_index, LGRP_AFF_STRONG); + } else { + if (flags & HWLOC_CPUBIND_STRICT) + lgrp_affinity_set(idtype, id, obj->os_index, LGRP_AFF_NONE); + else + lgrp_affinity_set(idtype, id, obj->os_index, LGRP_AFF_WEAK); + } + } + + return 0; +} + +static int +hwloc_solaris_set_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) +{ + return hwloc_solaris_set_sth_membind(topology, P_PID, pid, nodeset, policy, flags); +} + +static int +hwloc_solaris_set_thisproc_membind(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) +{ + return hwloc_solaris_set_sth_membind(topology, P_PID, P_MYID, nodeset, policy, flags); +} + +static int +hwloc_solaris_set_thisthread_membind(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) +{ + return hwloc_solaris_set_sth_membind(topology, P_LWPID, P_MYID, nodeset, policy, flags); +} + +static int +hwloc_solaris_get_sth_membind(hwloc_topology_t topology, idtype_t idtype, id_t id, hwloc_nodeset_t nodeset, hwloc_membind_policy_t *policy, int flags __hwloc_attribute_unused) +{ + int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE); + int n; + int i; + + if (depth < 0) { + errno = ENOSYS; + return -1; + } + + hwloc_bitmap_zero(nodeset); + n = hwloc_get_nbobjs_by_depth(topology, depth); + + for (i = 0; i < n; i++) { + hwloc_obj_t obj = hwloc_get_obj_by_depth(topology, depth, i); + lgrp_affinity_t aff = lgrp_affinity_get(idtype, id, obj->os_index); + + if (aff == LGRP_AFF_STRONG) + hwloc_bitmap_set(nodeset, obj->os_index); + } + + if (hwloc_bitmap_iszero(nodeset)) + hwloc_bitmap_copy(nodeset, hwloc_topology_get_complete_nodeset(topology)); + + *policy = HWLOC_MEMBIND_DEFAULT; + return 0; +} + +static int +hwloc_solaris_get_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_nodeset_t nodeset, hwloc_membind_policy_t *policy, int flags) +{ + return hwloc_solaris_get_sth_membind(topology, P_PID, pid, nodeset, policy, flags); +} + +static int +hwloc_solaris_get_thisproc_membind(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t *policy, int flags) +{ + return hwloc_solaris_get_sth_membind(topology, P_PID, P_MYID, nodeset, policy, flags); +} + +static int +hwloc_solaris_get_thisthread_membind(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t *policy, int flags) +{ + return hwloc_solaris_get_sth_membind(topology, P_LWPID, P_MYID, nodeset, policy, flags); +} +#endif /* HAVE_LIBLGRP */ + + +#ifdef MADV_ACCESS_LWP +static int +hwloc_solaris_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 __hwloc_attribute_unused) +{ + int advice; + size_t remainder; + + /* Can not give a set of nodes just for an area. */ + if (!hwloc_bitmap_isequal(nodeset, hwloc_topology_get_complete_nodeset(topology))) { + errno = EXDEV; + return -1; + } + + switch (policy) { + case HWLOC_MEMBIND_DEFAULT: + case HWLOC_MEMBIND_BIND: + advice = MADV_ACCESS_DEFAULT; + break; + case HWLOC_MEMBIND_FIRSTTOUCH: + case HWLOC_MEMBIND_NEXTTOUCH: + advice = MADV_ACCESS_LWP; + break; + case HWLOC_MEMBIND_INTERLEAVE: + advice = MADV_ACCESS_MANY; + break; + default: + errno = ENOSYS; + return -1; + } + + remainder = (uintptr_t) addr & (sysconf(_SC_PAGESIZE)-1); + addr = (char*) addr - remainder; + len += remainder; + return madvise((void*) addr, len, advice); +} +#endif + +#ifdef HAVE_LIBLGRP +static void +browse(struct hwloc_topology *topology, lgrp_cookie_t cookie, lgrp_id_t lgrp, hwloc_obj_t *glob_lgrps, unsigned *curlgrp) +{ + int n; + hwloc_obj_t obj; + lgrp_mem_size_t mem_size; + + n = lgrp_cpus(cookie, lgrp, NULL, 0, LGRP_CONTENT_HIERARCHY); + if (n == -1) + return; + + /* Is this lgrp a NUMA node? */ + if ((mem_size = lgrp_mem_size(cookie, lgrp, LGRP_MEM_SZ_INSTALLED, LGRP_CONTENT_DIRECT)) > 0) + { + int i; + processorid_t *cpuids; + cpuids = malloc(sizeof(processorid_t) * n); + assert(cpuids != NULL); + + obj = hwloc_alloc_setup_object(HWLOC_OBJ_NUMANODE, lgrp); + obj->nodeset = hwloc_bitmap_alloc(); + hwloc_bitmap_set(obj->nodeset, lgrp); + obj->cpuset = hwloc_bitmap_alloc(); + glob_lgrps[(*curlgrp)++] = obj; + + lgrp_cpus(cookie, lgrp, cpuids, n, LGRP_CONTENT_HIERARCHY); + for (i = 0; i < n ; i++) { + hwloc_debug("node %ld's cpu %d is %d\n", lgrp, i, cpuids[i]); + hwloc_bitmap_set(obj->cpuset, cpuids[i]); + } + hwloc_debug_1arg_bitmap("node %ld has cpuset %s\n", + lgrp, obj->cpuset); + + /* or LGRP_MEM_SZ_FREE */ + hwloc_debug("node %ld has %lldkB\n", lgrp, mem_size/1024); + obj->memory.local_memory = mem_size; + 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(); +#ifdef HAVE__SC_LARGE_PAGESIZE + obj->memory.page_types[1].size = sysconf(_SC_LARGE_PAGESIZE); +#endif + hwloc_insert_object_by_cpuset(topology, obj); + free(cpuids); + } + + n = lgrp_children(cookie, lgrp, NULL, 0); + { + lgrp_id_t *lgrps; + int i; + + lgrps = malloc(sizeof(lgrp_id_t) * n); + assert(lgrps != NULL); + lgrp_children(cookie, lgrp, lgrps, n); + hwloc_debug("lgrp %ld has %d children\n", lgrp, n); + for (i = 0; i < n ; i++) + { + browse(topology, cookie, lgrps[i], glob_lgrps, curlgrp); + } + hwloc_debug("lgrp %ld's children done\n", lgrp); + free(lgrps); + } +} + +static void +hwloc_look_lgrp(struct hwloc_topology *topology) +{ + lgrp_cookie_t cookie; + unsigned curlgrp = 0; + int nlgrps; + lgrp_id_t root; + + if ((topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM)) + cookie = lgrp_init(LGRP_VIEW_OS); + else + cookie = lgrp_init(LGRP_VIEW_CALLER); + if (cookie == LGRP_COOKIE_NONE) + { + hwloc_debug("lgrp_init failed: %s\n", strerror(errno)); + return; + } + nlgrps = lgrp_nlgrps(cookie); + root = lgrp_root(cookie); + { + hwloc_obj_t *glob_lgrps = calloc(nlgrps, sizeof(hwloc_obj_t)); + browse(topology, cookie, root, glob_lgrps, &curlgrp); +#ifdef HAVE_LGRP_LATENCY_COOKIE + { + float *distances = calloc(curlgrp*curlgrp, sizeof(float)); + unsigned *indexes = calloc(curlgrp,sizeof(unsigned)); + unsigned i, j; + for (i = 0; i < curlgrp; i++) { + indexes[i] = glob_lgrps[i]->os_index; + for (j = 0; j < curlgrp; j++) + distances[i*curlgrp+j] = (float) lgrp_latency_cookie(cookie, glob_lgrps[i]->os_index, glob_lgrps[j]->os_index, LGRP_LAT_CPU_TO_MEM); + } + hwloc_distances_set(topology, HWLOC_OBJ_NUMANODE, curlgrp, indexes, glob_lgrps, distances, 0 /* OS cannot force */); + } +#endif /* HAVE_LGRP_LATENCY_COOKIE */ + } + lgrp_fini(cookie); +} +#endif /* LIBLGRP */ + +#ifdef HAVE_LIBKSTAT +#include +static int +hwloc_look_kstat(struct hwloc_topology *topology) +{ + /* FIXME this assumes that all packages are identical */ + char *CPUType = hwloc_solaris_get_chip_type(); + char *CPUModel = hwloc_solaris_get_chip_model(); + + kstat_ctl_t *kc = kstat_open(); + kstat_t *ksp; + kstat_named_t *stat; + unsigned look_cores = 1, look_chips = 1; + + unsigned Pproc_max = 0; + unsigned Pproc_alloc = 256; + struct hwloc_solaris_Pproc { + unsigned Lpkg, Ppkg, Lcore, Lproc; + } * Pproc = malloc(Pproc_alloc * sizeof(*Pproc)); + + unsigned Lproc_num = 0; + unsigned Lproc_alloc = 256; + struct hwloc_solaris_Lproc { + unsigned Pproc; + } * Lproc = malloc(Lproc_alloc * sizeof(*Lproc)); + + unsigned Lcore_num = 0; + unsigned Lcore_alloc = 256; + struct hwloc_solaris_Lcore { + unsigned Pcore, Ppkg; + } * Lcore = malloc(Lcore_alloc * sizeof(*Lcore)); + + unsigned Lpkg_num = 0; + unsigned Lpkg_alloc = 256; + struct hwloc_solaris_Lpkg { + unsigned Ppkg; + } * Lpkg = malloc(Lpkg_alloc * sizeof(*Lpkg)); + + unsigned pkgid, coreid, cpuid; + unsigned i; + + for (i = 0; i < Pproc_alloc; i++) { + Pproc[i].Lproc = -1; + Pproc[i].Lpkg = -1; + Pproc[i].Ppkg = -1; + Pproc[i].Lcore = -1; + } + + if (!kc) { + hwloc_debug("kstat_open failed: %s\n", strerror(errno)); + free(Pproc); + free(Lproc); + free(Lcore); + free(Lpkg); + return 0; + } + + for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) + { + if (strncmp("cpu_info", ksp->ks_module, 8)) + continue; + + cpuid = ksp->ks_instance; + + if (kstat_read(kc, ksp, NULL) == -1) + { + fprintf(stderr, "kstat_read failed for CPU%u: %s\n", cpuid, strerror(errno)); + continue; + } + + hwloc_debug("cpu%u\n", cpuid); + + if (cpuid >= Pproc_alloc) { + Pproc_alloc *= 2; + Pproc = realloc(Pproc, Pproc_alloc * sizeof(*Pproc)); + for(i = Pproc_alloc/2; i < Pproc_alloc; i++) { + Pproc[i].Lproc = -1; + Pproc[i].Lpkg = -1; + Pproc[i].Ppkg = -1; + Pproc[i].Lcore = -1; + } + } + Pproc[cpuid].Lproc = Lproc_num; + + if (Lproc_num >= Lproc_alloc) { + Lproc_alloc *= 2; + Lproc = realloc(Lproc, Lproc_alloc * sizeof(*Lproc)); + } + Lproc[Lproc_num].Pproc = cpuid; + Lproc_num++; + + if (cpuid >= Pproc_max) + Pproc_max = cpuid + 1; + + stat = (kstat_named_t *) kstat_data_lookup(ksp, "state"); + if (!stat) + hwloc_debug("could not read state for CPU%u: %s\n", cpuid, strerror(errno)); + else if (stat->data_type != KSTAT_DATA_CHAR) + hwloc_debug("unknown kstat type %d for cpu state\n", stat->data_type); + else + { + hwloc_debug("cpu%u's state is %s\n", cpuid, stat->value.c); + if (strcmp(stat->value.c, "on-line")) + /* not online */ + hwloc_bitmap_clr(topology->levels[0][0]->online_cpuset, cpuid); + } + + if (look_chips) do { + /* Get Chip ID */ + stat = (kstat_named_t *) kstat_data_lookup(ksp, "chip_id"); + if (!stat) + { + if (Lpkg_num) + fprintf(stderr, "could not read package id for CPU%u: %s\n", cpuid, strerror(errno)); + else + hwloc_debug("could not read package id for CPU%u: %s\n", cpuid, strerror(errno)); + look_chips = 0; + continue; + } + switch (stat->data_type) { + case KSTAT_DATA_INT32: + pkgid = stat->value.i32; + break; + case KSTAT_DATA_UINT32: + pkgid = stat->value.ui32; + break; +#ifdef _INT64_TYPE + case KSTAT_DATA_UINT64: + pkgid = stat->value.ui64; + break; + case KSTAT_DATA_INT64: + pkgid = stat->value.i64; + break; +#endif + default: + fprintf(stderr, "chip_id type %d unknown\n", stat->data_type); + look_chips = 0; + continue; + } + Pproc[cpuid].Ppkg = pkgid; + for (i = 0; i < Lpkg_num; i++) + if (pkgid == Lpkg[i].Ppkg) + break; + Pproc[cpuid].Lpkg = i; + hwloc_debug("%u on package %u (%u)\n", cpuid, i, pkgid); + if (i == Lpkg_num) { + if (Lpkg_num == Lpkg_alloc) { + Lpkg_alloc *= 2; + Lpkg = realloc(Lpkg, Lpkg_alloc * sizeof(*Lpkg)); + } + Lpkg[Lpkg_num++].Ppkg = pkgid; + } + } while(0); + + if (look_cores) do { + /* Get Core ID */ + stat = (kstat_named_t *) kstat_data_lookup(ksp, "core_id"); + if (!stat) + { + if (Lcore_num) + fprintf(stderr, "could not read core id for CPU%u: %s\n", cpuid, strerror(errno)); + else + hwloc_debug("could not read core id for CPU%u: %s\n", cpuid, strerror(errno)); + look_cores = 0; + continue; + } + switch (stat->data_type) { + case KSTAT_DATA_INT32: + coreid = stat->value.i32; + break; + case KSTAT_DATA_UINT32: + coreid = stat->value.ui32; + break; +#ifdef _INT64_TYPE + case KSTAT_DATA_UINT64: + coreid = stat->value.ui64; + break; + case KSTAT_DATA_INT64: + coreid = stat->value.i64; + break; +#endif + default: + fprintf(stderr, "core_id type %d unknown\n", stat->data_type); + look_cores = 0; + continue; + } + for (i = 0; i < Lcore_num; i++) + if (coreid == Lcore[i].Pcore && Pproc[cpuid].Ppkg == Lcore[i].Ppkg) + break; + Pproc[cpuid].Lcore = i; + hwloc_debug("%u on core %u (%u)\n", cpuid, i, coreid); + if (i == Lcore_num) { + if (Lcore_num == Lcore_alloc) { + Lcore_alloc *= 2; + Lcore = realloc(Lcore, Lcore_alloc * sizeof(*Lcore)); + } + Lcore[Lcore_num].Ppkg = Pproc[cpuid].Ppkg; + Lcore[Lcore_num++].Pcore = coreid; + } + } while(0); + + /* Note: there is also clog_id for the Thread ID (not unique) and + * pkg_core_id for the core ID (not unique). They are not useful to us + * however. */ + } + + if (look_chips) { + struct hwloc_obj *obj; + unsigned j,k; + hwloc_debug("%d Packages\n", Lpkg_num); + for (j = 0; j < Lpkg_num; j++) { + obj = hwloc_alloc_setup_object(HWLOC_OBJ_PACKAGE, Lpkg[j].Ppkg); + if (CPUType) + hwloc_obj_add_info(obj, "CPUType", CPUType); + if (CPUModel) + hwloc_obj_add_info(obj, "CPUModel", CPUModel); + obj->cpuset = hwloc_bitmap_alloc(); + for(k=0; kcpuset, k); + hwloc_debug_1arg_bitmap("Package %d has cpuset %s\n", j, obj->cpuset); + hwloc_insert_object_by_cpuset(topology, obj); + } + hwloc_debug("%s", "\n"); + } + + if (look_cores) { + struct hwloc_obj *obj; + unsigned j,k; + hwloc_debug("%d Cores\n", Lcore_num); + for (j = 0; j < Lcore_num; j++) { + obj = hwloc_alloc_setup_object(HWLOC_OBJ_CORE, Lcore[j].Pcore); + obj->cpuset = hwloc_bitmap_alloc(); + for(k=0; kcpuset, k); + hwloc_debug_1arg_bitmap("Core %d has cpuset %s\n", j, obj->cpuset); + hwloc_insert_object_by_cpuset(topology, obj); + } + hwloc_debug("%s", "\n"); + } + if (Lproc_num) { + struct hwloc_obj *obj; + unsigned j,k; + hwloc_debug("%d PUs\n", Lproc_num); + for (j = 0; j < Lproc_num; j++) { + obj = hwloc_alloc_setup_object(HWLOC_OBJ_PU, Lproc[j].Pproc); + obj->cpuset = hwloc_bitmap_alloc(); + for(k=0; kcpuset, k); + hwloc_debug_1arg_bitmap("PU %d has cpuset %s\n", j, obj->cpuset); + hwloc_insert_object_by_cpuset(topology, obj); + } + hwloc_debug("%s", "\n"); + } + + kstat_close(kc); + + free(Pproc); + free(Lproc); + free(Lcore); + free(Lpkg); + + return Lproc_num > 0; +} +#endif /* LIBKSTAT */ + +static int +hwloc_look_solaris(struct hwloc_backend *backend) +{ + struct hwloc_topology *topology = backend->topology; + unsigned nbprocs = hwloc_fallback_nbprocessors (topology); + int alreadypus = 0; + + if (topology->levels[0][0]->cpuset) + /* somebody discovered things */ + return 0; + + hwloc_alloc_obj_cpusets(topology->levels[0][0]); + +#ifdef HAVE_LIBLGRP + hwloc_look_lgrp(topology); +#endif /* HAVE_LIBLGRP */ +#ifdef HAVE_LIBKSTAT + nbprocs = 0; + if (hwloc_look_kstat(topology) > 0) + alreadypus = 1; +#endif /* HAVE_LIBKSTAT */ + if (!alreadypus) + hwloc_setup_pu_level(topology, nbprocs); + + hwloc_obj_add_info(topology->levels[0][0], "Backend", "Solaris"); + if (topology->is_thissystem) + hwloc_add_uname_info(topology, NULL); + return 1; +} + +void +hwloc_set_solaris_hooks(struct hwloc_binding_hooks *hooks, + struct hwloc_topology_support *support __hwloc_attribute_unused) +{ + hooks->set_proc_cpubind = hwloc_solaris_set_proc_cpubind; + hooks->set_thisproc_cpubind = hwloc_solaris_set_thisproc_cpubind; + hooks->set_thisthread_cpubind = hwloc_solaris_set_thisthread_cpubind; +#ifdef HAVE_LIBLGRP + hooks->get_proc_cpubind = hwloc_solaris_get_proc_cpubind; + hooks->get_thisproc_cpubind = hwloc_solaris_get_thisproc_cpubind; + hooks->get_thisthread_cpubind = hwloc_solaris_get_thisthread_cpubind; + hooks->set_proc_membind = hwloc_solaris_set_proc_membind; + hooks->set_thisproc_membind = hwloc_solaris_set_thisproc_membind; + hooks->set_thisthread_membind = hwloc_solaris_set_thisthread_membind; + hooks->get_proc_membind = hwloc_solaris_get_proc_membind; + hooks->get_thisproc_membind = hwloc_solaris_get_thisproc_membind; + hooks->get_thisthread_membind = hwloc_solaris_get_thisthread_membind; +#endif /* HAVE_LIBLGRP */ +#ifdef MADV_ACCESS_LWP + hooks->set_area_membind = hwloc_solaris_set_area_membind; + support->membind->firsttouch_membind = 1; + support->membind->bind_membind = 1; + support->membind->interleave_membind = 1; + support->membind->nexttouch_membind = 1; +#endif +} + +static struct hwloc_backend * +hwloc_solaris_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_solaris; + return backend; +} + +static struct hwloc_disc_component hwloc_solaris_disc_component = { + HWLOC_DISC_COMPONENT_TYPE_CPU, + "solaris", + HWLOC_DISC_COMPONENT_TYPE_GLOBAL, + hwloc_solaris_component_instantiate, + 50, + NULL +}; + +const struct hwloc_component hwloc_solaris_component = { + HWLOC_COMPONENT_ABI, + NULL, NULL, + HWLOC_COMPONENT_TYPE_DISC, + 0, + &hwloc_solaris_disc_component +}; diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/topology-synthetic.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-synthetic.c new file mode 100644 index 0000000000..db7087bb92 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-synthetic.c @@ -0,0 +1,1098 @@ +/* + * Copyright © 2009 CNRS + * Copyright © 2009-2015 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 + +#include +#include +#ifdef HAVE_STRINGS_H +#include +#endif + +struct hwloc_synthetic_level_data_s { + unsigned arity; + unsigned long totalwidth; + hwloc_obj_type_t type; + unsigned depth; /* For caches/groups */ + hwloc_obj_cache_type_t cachetype; /* For caches */ + hwloc_uint64_t memorysize; /* For caches/memory */ + + /* the indexes= attribute before parsing */ + const char *index_string; + unsigned long index_string_length; + /* the array of explicit indexes after parsing */ + unsigned *index_array; + + /* used while filling the topology */ + unsigned next_os_index; /* id of the next object for that level */ +}; + +struct hwloc_synthetic_backend_data_s { + /* synthetic backend parameters */ + char *string; +#define HWLOC_SYNTHETIC_MAX_DEPTH 128 + struct hwloc_synthetic_level_data_s level[HWLOC_SYNTHETIC_MAX_DEPTH]; +}; + +struct hwloc_synthetic_intlv_loop_s { + unsigned step; + unsigned nb; + unsigned level_depth; +}; + +static void +hwloc_synthetic_process_level_indexes(struct hwloc_synthetic_backend_data_s *data, + unsigned curleveldepth, + int verbose) +{ + struct hwloc_synthetic_level_data_s *curlevel = &data->level[curleveldepth]; + unsigned long total = curlevel->totalwidth; + const char *attr = curlevel->index_string; + unsigned long length = curlevel->index_string_length; + unsigned *array = NULL; + struct hwloc_synthetic_intlv_loop_s * loops = NULL; + unsigned long i; + + if (!attr) + return; + + array = calloc(total, sizeof(*array)); + if (!array) { + if (verbose) + fprintf(stderr, "Failed to allocate synthetic index array of size %lu\n", total); + goto out; + } + + i = strspn(attr, "0123456789,"); + if (i == length) { + /* explicit array of indexes */ + + for(i=0; iindex_array = array; + + } else { + /* interleaving */ + unsigned nr_loops = 1, cur_loop; + unsigned minstep = total; + unsigned long nbs = 1; + unsigned j, mul; + const char *tmp; + + tmp = attr; + while (tmp) { + tmp = strchr(tmp, ':'); + if (!tmp || tmp >= attr+length) + break; + nr_loops++; + tmp++; + } + /* nr_loops colon-separated fields, but we may need one more at the end */ + loops = malloc((nr_loops+1)*sizeof(*loops)); + if (!loops) { + if (verbose) + fprintf(stderr, "Failed to allocate synthetic index interleave loop array of size %u\n", nr_loops); + goto out_with_array; + } + + if (*attr >= '0' && *attr <= '9') { + /* interleaving as x*y:z*t:... */ + unsigned step, nb; + + tmp = attr; + cur_loop = 0; + while (tmp) { + char *tmp2, *tmp3; + step = (unsigned) strtol(tmp, &tmp2, 0); + if (tmp2 == tmp || *tmp2 != '*') { + if (verbose) + fprintf(stderr, "Failed to read synthetic index interleaving loop '%s' without number before '*'\n", tmp); + goto out_with_loops; + } + if (!step) { + if (verbose) + fprintf(stderr, "Invalid interleaving loop with step 0 at '%s'\n", tmp); + goto out_with_loops; + } + tmp2++; + nb = (unsigned) strtol(tmp2, &tmp3, 0); + if (tmp3 == tmp2 || (*tmp3 && *tmp3 != ':' && *tmp3 != ')' && *tmp3 != ' ')) { + if (verbose) + fprintf(stderr, "Failed to read synthetic index interleaving loop '%s' without number between '*' and ':'\n", tmp); + goto out_with_loops; + } + if (!nb) { + if (verbose) + fprintf(stderr, "Invalid interleaving loop with number 0 at '%s'\n", tmp2); + goto out_with_loops; + } + loops[cur_loop].step = step; + loops[cur_loop].nb = nb; + if (step < minstep) + minstep = step; + nbs *= nb; + cur_loop++; + if (*tmp3 == ')' || *tmp3 == ' ') + break; + tmp = (const char*) (tmp3+1); + } + + } else { + /* interleaving as type1:type2:... */ + hwloc_obj_type_t type; + hwloc_obj_cache_type_t cachetypeattr; + int depthattr; + int err; + + /* find level depths for each interleaving loop */ + tmp = attr; + cur_loop = 0; + while (tmp) { + err = hwloc_obj_type_sscanf(tmp, &type, &depthattr, &cachetypeattr, sizeof(cachetypeattr)); + if (err < 0) { + if (verbose) + fprintf(stderr, "Failed to read synthetic index interleaving loop type '%s'\n", tmp); + goto out_with_loops; + } + if (type == HWLOC_OBJ_MISC || type == HWLOC_OBJ_BRIDGE || type == HWLOC_OBJ_PCI_DEVICE || type == HWLOC_OBJ_OS_DEVICE) { + if (verbose) + fprintf(stderr, "Misc object type disallowed in synthetic index interleaving loop type '%s'\n", tmp); + goto out_with_loops; + } + for(i=0; ilevel[i].type) + continue; + if ((type == HWLOC_OBJ_GROUP || type == HWLOC_OBJ_CACHE) + && depthattr != -1 + && (unsigned) depthattr != data->level[i].depth) + continue; + if (type == HWLOC_OBJ_CACHE + && cachetypeattr != (hwloc_obj_cache_type_t) -1 + && cachetypeattr != data->level[i].cachetype) + continue; + loops[cur_loop].level_depth = i; + break; + } + if (i == curleveldepth) { + if (verbose) + fprintf(stderr, "Failed to find level for synthetic index interleaving loop type '%s' above '%s'\n", + tmp, hwloc_obj_type_string(curlevel->type)); + goto out_with_loops; + } + tmp = strchr(tmp, ':'); + if (!tmp || tmp > attr+length) + break; + tmp++; + cur_loop++; + } + + /* compute actual loop step/nb */ + for(cur_loop=0; cur_loop prevdepth) + prevdepth = loops[i].level_depth; + } + step = curlevel->totalwidth / data->level[mydepth].totalwidth; /* number of objects below us */ + nb = data->level[mydepth].totalwidth / data->level[prevdepth].totalwidth; /* number of us within parent */ + + loops[cur_loop].step = step; + loops[cur_loop].nb = nb; + assert(nb); + assert(step); + if (step < minstep) + minstep = step; + nbs *= nb; + } + } + assert(nbs); + + if (nbs != total) { + /* one loop of total/nbs steps is missing, add it if it's just the smallest one */ + if (minstep == total/nbs) { + loops[nr_loops].step = 1; + loops[nr_loops].nb = total/nbs; + nr_loops++; + } else { + if (verbose) + fprintf(stderr, "Invalid index interleaving total width %lu instead of %lu\n", nbs, total); + goto out_with_loops; + } + } + + /* generate the array of indexes */ + mul = 1; + for(i=0; i= total) { + if (verbose) + fprintf(stderr, "Invalid index interleaving generates out-of-range index %u\n", array[j]); + goto out_with_loops; + } + if (!array[j] && j) { + if (verbose) + fprintf(stderr, "Invalid index interleaving generates duplicate index values\n"); + goto out_with_loops; + } + } + + free(loops); + curlevel->index_array = array; + } + + return; + + out_with_loops: + free(loops); + out_with_array: + free(array); + out: + return; +} + +static hwloc_uint64_t +hwloc_synthetic_parse_memory_attr(const char *attr, const char **endp) +{ + const char *endptr; + hwloc_uint64_t size; + size = strtoull(attr, (char **) &endptr, 0); + if (!hwloc_strncasecmp(endptr, "TB", 2)) { + size <<= 40; + endptr += 2; + } else if (!hwloc_strncasecmp(endptr, "GB", 2)) { + size <<= 30; + endptr += 2; + } else if (!hwloc_strncasecmp(endptr, "MB", 2)) { + size <<= 20; + endptr += 2; + } else if (!hwloc_strncasecmp(endptr, "kB", 2)) { + size <<= 10; + endptr += 2; + } + *endp = endptr; + return size; +} + +static int +hwloc_synthetic_parse_level_attrs(const char *attrs, const char **next_posp, + struct hwloc_synthetic_level_data_s *curlevel, + int verbose) +{ + hwloc_obj_type_t type = curlevel->type; + const char *next_pos; + hwloc_uint64_t memorysize = 0; + const char *index_string = NULL; + unsigned long index_string_length = 0; + + next_pos = (const char *) strchr(attrs, ')'); + if (!next_pos) { + if (verbose) + fprintf(stderr, "Missing attribute closing bracket in synthetic string doesn't have a number of objects at '%s'\n", attrs); + errno = EINVAL; + return -1; + } + + while (')' != *attrs) { + if (HWLOC_OBJ_CACHE == type && !strncmp("size=", attrs, 5)) { + memorysize = hwloc_synthetic_parse_memory_attr(attrs+5, &attrs); + + } else if (HWLOC_OBJ_CACHE != type && !strncmp("memory=", attrs, 7)) { + memorysize = hwloc_synthetic_parse_memory_attr(attrs+7, &attrs); + + } else if (!strncmp("indexes=", attrs, 8)) { + index_string = attrs+8; + attrs += 8; + index_string_length = strcspn(attrs, " )"); + attrs += index_string_length; + + } else { + if (verbose) + fprintf(stderr, "Unknown attribute at '%s'\n", attrs); + errno = EINVAL; + return -1; + } + + if (' ' == *attrs) + attrs++; + else if (')' != *attrs) { + if (verbose) + fprintf(stderr, "Missing parameter separator at '%s'\n", attrs); + errno = EINVAL; + return -1; + } + } + + curlevel->memorysize = memorysize; + curlevel->index_string = index_string; + curlevel->index_string_length = index_string_length; + *next_posp = next_pos+1; + return 0; +} + +/* Read from description a series of integers describing a symmetrical + topology and update the hwloc_synthetic_backend_data_s accordingly. On + success, return zero. */ +static int +hwloc_backend_synthetic_init(struct hwloc_synthetic_backend_data_s *data, + const char *description) +{ + const char *pos, *next_pos; + unsigned long item, count; + unsigned i; + int cache_depth = 0, group_depth = 0; + int nb_machine_levels = 0, nb_node_levels = 0; + int nb_pu_levels = 0; + int verbose = 0; + const char *env = getenv("HWLOC_SYNTHETIC_VERBOSE"); + int err; + unsigned long totalarity = 1; + + if (env) + verbose = atoi(env); + + /* default values before we add root attributes */ + data->level[0].totalwidth = 1; + data->level[0].type = HWLOC_OBJ_MACHINE; + data->level[0].index_string = NULL; + data->level[0].index_array = NULL; + data->level[0].memorysize = 0; + if (*description == '(') { + err = hwloc_synthetic_parse_level_attrs(description+1, &description, &data->level[0], verbose); + if (err < 0) + return err; + } + + for (pos = description, count = 1; *pos; pos = next_pos) { +#define HWLOC_OBJ_TYPE_UNKNOWN ((hwloc_obj_type_t) -1) + hwloc_obj_type_t type = HWLOC_OBJ_TYPE_UNKNOWN; + int typedepth = -1; + hwloc_obj_cache_type_t cachetype = (hwloc_obj_cache_type_t) -1; + + /* initialize parent arity to 0 so that the levels are not infinite */ + data->level[count-1].arity = 0; + + while (*pos == ' ') + pos++; + + if (!*pos) + break; + + if (*pos < '0' || *pos > '9') { + if (hwloc_obj_type_sscanf(pos, &type, &typedepth, &cachetype, sizeof(cachetype)) < 0) { + if (verbose) + fprintf(stderr, "Synthetic string with unknown object type at '%s'\n", pos); + errno = EINVAL; + goto error; + } + if (type == HWLOC_OBJ_MISC || type == HWLOC_OBJ_BRIDGE || type == HWLOC_OBJ_PCI_DEVICE || type == HWLOC_OBJ_OS_DEVICE) { + if (verbose) + fprintf(stderr, "Synthetic string with disallowed object type at '%s'\n", pos); + errno = EINVAL; + goto error; + } + + next_pos = strchr(pos, ':'); + if (!next_pos) { + if (verbose) + fprintf(stderr,"Synthetic string doesn't have a `:' after object type at '%s'\n", pos); + errno = EINVAL; + goto error; + } + pos = next_pos + 1; + } + data->level[count].type = type; + data->level[count].depth = (unsigned) typedepth; + data->level[count].cachetype = cachetype; + + item = strtoul(pos, (char **)&next_pos, 0); + if (next_pos == pos) { + if (verbose) + fprintf(stderr,"Synthetic string doesn't have a number of objects at '%s'\n", pos); + errno = EINVAL; + goto error; + } + data->level[count-1].arity = (unsigned)item; + + totalarity *= item; + data->level[count].totalwidth = totalarity; + data->level[count].index_string = NULL; + data->level[count].index_array = NULL; + data->level[count].memorysize = 0; + if (*next_pos == '(') { + err = hwloc_synthetic_parse_level_attrs(next_pos+1, &next_pos, &data->level[count], verbose); + if (err < 0) + goto error; + } + + if (count + 1 >= HWLOC_SYNTHETIC_MAX_DEPTH) { + if (verbose) + fprintf(stderr,"Too many synthetic levels, max %d\n", HWLOC_SYNTHETIC_MAX_DEPTH); + errno = EINVAL; + goto error; + } + if (item > UINT_MAX) { + if (verbose) + fprintf(stderr,"Too big arity, max %u\n", UINT_MAX); + errno = EINVAL; + goto error; + } + + count++; + } + + if (count <= 0) { + if (verbose) + fprintf(stderr, "Synthetic string doesn't contain any object\n"); + errno = EINVAL; + goto error; + } + + for(i=count-1; i>0; i--) { + struct hwloc_synthetic_level_data_s *curlevel = &data->level[i]; + hwloc_obj_type_t type; + + type = curlevel->type; + + if (type == HWLOC_OBJ_TYPE_UNKNOWN) { + if (i == count-1) + type = HWLOC_OBJ_PU; + else { + switch (data->level[i+1].type) { + case HWLOC_OBJ_PU: type = HWLOC_OBJ_CORE; break; + case HWLOC_OBJ_CORE: type = HWLOC_OBJ_CACHE; break; + case HWLOC_OBJ_CACHE: type = HWLOC_OBJ_PACKAGE; break; + case HWLOC_OBJ_PACKAGE: type = HWLOC_OBJ_NUMANODE; break; + case HWLOC_OBJ_NUMANODE: + case HWLOC_OBJ_MACHINE: + case HWLOC_OBJ_GROUP: type = HWLOC_OBJ_GROUP; break; + default: + assert(0); + } + } + curlevel->type = type; + } + switch (type) { + case HWLOC_OBJ_PU: + nb_pu_levels++; + break; + case HWLOC_OBJ_CACHE: + cache_depth++; + break; + case HWLOC_OBJ_GROUP: + group_depth++; + break; + case HWLOC_OBJ_NUMANODE: + nb_node_levels++; + break; + case HWLOC_OBJ_MACHINE: + nb_machine_levels++; + break; + default: + break; + } + } + + if (!nb_pu_levels) { + if (verbose) + fprintf(stderr, "Synthetic string missing ending number of PUs\n"); + errno = EINVAL; + return -1; + } + if (nb_pu_levels > 1) { + if (verbose) + fprintf(stderr, "Synthetic string can not have several PU levels\n"); + errno = EINVAL; + return -1; + } + if (nb_node_levels > 1) { + if (verbose) + fprintf(stderr, "Synthetic string can not have several NUMA node levels\n"); + errno = EINVAL; + return -1; + } + if (nb_machine_levels > 1) { + if (verbose) + fprintf(stderr, "Synthetic string can not have several machine levels\n"); + errno = EINVAL; + return -1; + } + + if (nb_machine_levels) + data->level[0].type = HWLOC_OBJ_SYSTEM; + else { + data->level[0].type = HWLOC_OBJ_MACHINE; + nb_machine_levels++; + } + + if (cache_depth == 1) + /* if there is a single cache level, make it L2 */ + cache_depth = 2; + + for (i=0; ilevel[i]; + hwloc_obj_type_t type = curlevel->type; + + if (type == HWLOC_OBJ_GROUP) { + if (curlevel->depth == (unsigned)-1) + curlevel->depth = group_depth--; + + } else if (type == HWLOC_OBJ_CACHE) { + if (curlevel->depth == (unsigned)-1) + curlevel->depth = cache_depth--; + if (curlevel->cachetype == (hwloc_obj_cache_type_t) -1) + curlevel->cachetype = curlevel->depth == 1 ? HWLOC_OBJ_CACHE_DATA : HWLOC_OBJ_CACHE_UNIFIED; + if (!curlevel->memorysize) { + if (1 == curlevel->depth) + /* 32Kb in L1 */ + curlevel->memorysize = 32*1024; + else + /* *4 at each level, starting from 1MB for L2, unified */ + curlevel->memorysize = 256*1024 << (2*curlevel->depth); + } + + } else if (type == HWLOC_OBJ_NUMANODE && !curlevel->memorysize) { + /* 1GB in memory nodes. */ + curlevel->memorysize = 1024*1024*1024; + } + + hwloc_synthetic_process_level_indexes(data, i, verbose); + } + + data->string = strdup(description); + data->level[count-1].arity = 0; + return 0; + + error: + for(i=0; ilevel[i]; + free(curlevel->index_array); + if (!curlevel->arity) + break; + } + return -1; +} + +static void +hwloc_synthetic__post_look_hooks(struct hwloc_synthetic_level_data_s *curlevel, + hwloc_obj_t obj) +{ + switch (obj->type) { + case HWLOC_OBJ_GROUP: + obj->attr->group.depth = curlevel->depth; + break; + case HWLOC_OBJ_SYSTEM: + break; + case HWLOC_OBJ_MACHINE: + break; + case HWLOC_OBJ_NUMANODE: + break; + case HWLOC_OBJ_PACKAGE: + break; + case HWLOC_OBJ_CACHE: + obj->attr->cache.depth = curlevel->depth; + obj->attr->cache.linesize = 64; + obj->attr->cache.type = curlevel->cachetype; + obj->attr->cache.size = curlevel->memorysize; + break; + case HWLOC_OBJ_CORE: + break; + case HWLOC_OBJ_PU: + break; + case HWLOC_OBJ_BRIDGE: + case HWLOC_OBJ_PCI_DEVICE: + case HWLOC_OBJ_OS_DEVICE: + case HWLOC_OBJ_MISC: + case HWLOC_OBJ_TYPE_MAX: + /* Should never happen */ + assert(0); + break; + } + if (curlevel->memorysize && HWLOC_OBJ_CACHE != obj->type) { + obj->memory.local_memory = curlevel->memorysize; + obj->memory.page_types_len = 1; + obj->memory.page_types = malloc(sizeof(*obj->memory.page_types)); + memset(obj->memory.page_types, 0, sizeof(*obj->memory.page_types)); + obj->memory.page_types[0].size = 4096; + obj->memory.page_types[0].count = curlevel->memorysize / 4096; + } +} + +/* + * Recursively build objects whose cpu start at first_cpu + * - level gives where to look in the type, arity and id arrays + * - the id array is used as a variable to get unique IDs for a given level. + * - generated memory should be added to *memory_kB. + * - generated cpus should be added to parent_cpuset. + * - next cpu number to be used should be returned. + */ +static void +hwloc__look_synthetic(struct hwloc_topology *topology, + struct hwloc_synthetic_backend_data_s *data, + int level, + hwloc_bitmap_t parent_cpuset) +{ + hwloc_obj_t obj; + unsigned i; + struct hwloc_synthetic_level_data_s *curlevel = &data->level[level]; + hwloc_obj_type_t type = curlevel->type; + unsigned os_index; + + /* pre-hooks */ + switch (type) { + case HWLOC_OBJ_GROUP: + break; + case HWLOC_OBJ_MACHINE: + break; + case HWLOC_OBJ_NUMANODE: + break; + case HWLOC_OBJ_PACKAGE: + break; + case HWLOC_OBJ_CACHE: + break; + case HWLOC_OBJ_CORE: + break; + case HWLOC_OBJ_PU: + break; + case HWLOC_OBJ_SYSTEM: + case HWLOC_OBJ_BRIDGE: + case HWLOC_OBJ_PCI_DEVICE: + case HWLOC_OBJ_OS_DEVICE: + case HWLOC_OBJ_MISC: + case HWLOC_OBJ_TYPE_MAX: + /* Should never happen */ + assert(0); + break; + } + + os_index = curlevel->next_os_index++; + if (curlevel->index_array) + os_index = curlevel->index_array[os_index]; + obj = hwloc_alloc_setup_object(type, os_index); + obj->cpuset = hwloc_bitmap_alloc(); + + if (!curlevel->arity) { + hwloc_bitmap_set(obj->cpuset, os_index); + } else { + for (i = 0; i < curlevel->arity; i++) + hwloc__look_synthetic(topology, data, level + 1, obj->cpuset); + } + + if (type == HWLOC_OBJ_NUMANODE) { + obj->nodeset = hwloc_bitmap_alloc(); + hwloc_bitmap_set(obj->nodeset, os_index); + } + + hwloc_bitmap_or(parent_cpuset, parent_cpuset, obj->cpuset); + + hwloc_synthetic__post_look_hooks(curlevel, obj); + + hwloc_insert_object_by_cpuset(topology, obj); +} + +static int +hwloc_look_synthetic(struct hwloc_backend *backend) +{ + struct hwloc_topology *topology = backend->topology; + struct hwloc_synthetic_backend_data_s *data = backend->private_data; + hwloc_bitmap_t cpuset = hwloc_bitmap_alloc(); + unsigned i; + + assert(!topology->levels[0][0]->cpuset); + + hwloc_alloc_obj_cpusets(topology->levels[0][0]); + + topology->support.discovery->pu = 1; + + /* start with os_index 0 for each level */ + for (i = 0; data->level[i].arity > 0; i++) + data->level[i].next_os_index = 0; + /* ... including the last one */ + data->level[i].next_os_index = 0; + + /* update first level type according to the synthetic type array */ + topology->levels[0][0]->type = data->level[0].type; + hwloc_synthetic__post_look_hooks(&data->level[0], topology->levels[0][0]); + + for (i = 0; i < data->level[0].arity; i++) + hwloc__look_synthetic(topology, data, 1, cpuset); + + hwloc_bitmap_free(cpuset); + + hwloc_obj_add_info(topology->levels[0][0], "Backend", "Synthetic"); + hwloc_obj_add_info(topology->levels[0][0], "SyntheticDescription", data->string); + return 1; +} + +static void +hwloc_synthetic_backend_disable(struct hwloc_backend *backend) +{ + struct hwloc_synthetic_backend_data_s *data = backend->private_data; + unsigned i; + for(i=0; ilevel[i]; + free(curlevel->index_array); + if (!curlevel->arity) + break; + } + free(data->string); + free(data); +} + +static struct hwloc_backend * +hwloc_synthetic_component_instantiate(struct hwloc_disc_component *component, + const void *_data1, + const void *_data2 __hwloc_attribute_unused, + const void *_data3 __hwloc_attribute_unused) +{ + struct hwloc_backend *backend; + struct hwloc_synthetic_backend_data_s *data; + int err; + + if (!_data1) { + 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; + } + + err = hwloc_backend_synthetic_init(data, (const char *) _data1); + if (err < 0) + goto out_with_data; + + backend->private_data = data; + backend->discover = hwloc_look_synthetic; + backend->disable = hwloc_synthetic_backend_disable; + backend->is_thissystem = 0; + + return backend; + + out_with_data: + free(data); + out_with_backend: + free(backend); + out: + return NULL; +} + +static struct hwloc_disc_component hwloc_synthetic_disc_component = { + HWLOC_DISC_COMPONENT_TYPE_GLOBAL, + "synthetic", + ~0, + hwloc_synthetic_component_instantiate, + 30, + NULL +}; + +const struct hwloc_component hwloc_synthetic_component = { + HWLOC_COMPONENT_ABI, + NULL, NULL, + HWLOC_COMPONENT_TYPE_DISC, + 0, + &hwloc_synthetic_disc_component +}; + +static int hwloc_topology_export_synthetic_indexes(struct hwloc_topology * topology, + hwloc_obj_t obj, + char *buffer, size_t buflen) +{ + unsigned depth = obj->depth; + unsigned total = topology->level_nbobjects[depth]; + unsigned step = 1; + unsigned nr_loops = 0; + struct hwloc_synthetic_intlv_loop_s *loops = NULL; + hwloc_obj_t cur; + unsigned i, j; + ssize_t tmplen = buflen; + char *tmp = buffer; + int res, ret = 0; + + /* must start with 0 */ + if (obj->os_index) + goto exportall; + + while (step != total) { + /* must be a divider of the total */ + if (total % step) + goto exportall; + + /* look for os_index == step */ + for(i=1; ilevels[depth][i]->os_index == step) + break; + if (i == total) + goto exportall; + for(j=2; jlevels[depth][i*j]->os_index != step*j) + break; + + nr_loops++; + loops = realloc(loops, nr_loops*sizeof(*loops)); + if (!loops) + goto exportall; + loops[nr_loops-1].step = i; + loops[nr_loops-1].nb = j; + step *= j; + } + + /* check this interleaving */ + for(i=0; ilevels[depth][i]->os_index != ind) + goto exportall; + } + + /* success, print it */ + for(j=0; j= tmplen) + res = tmplen>0 ? tmplen - 1 : 0; + tmp += res; + tmplen -= res; + } + + if (loops) + free(loops); + + return ret; + + exportall: + if (loops) + free(loops); + + /* dump all indexes */ + cur = obj; + while (cur) { + res = snprintf(tmp, tmplen, "%u%s", cur->os_index, + cur->next_cousin ? "," : ")"); + if (res < 0) + return -1; + ret += res; + if (res >= tmplen) + res = tmplen>0 ? tmplen - 1 : 0; + tmp += res; + tmplen -= res; + cur = cur->next_cousin; + } + return ret; +} + +static int hwloc_topology_export_synthetic_obj_attr(struct hwloc_topology * topology, + hwloc_obj_t obj, + char *buffer, size_t buflen) +{ + const char * separator = " "; + const char * prefix = "("; + char cachesize[64] = ""; + char memsize[64] = ""; + int needindexes = 0; + + if (HWLOC_OBJ_CACHE == obj->type && obj->attr->cache.size) { + snprintf(cachesize, sizeof(cachesize), "%ssize=%llu", + prefix, (unsigned long long) obj->attr->cache.size); + prefix = separator; + } + if (obj->memory.local_memory) { + snprintf(memsize, sizeof(memsize), "%smemory=%llu", + prefix, (unsigned long long) obj->memory.local_memory); + prefix = separator; + } + if (obj->type == HWLOC_OBJ_PU || obj->type == HWLOC_OBJ_NUMANODE) { + hwloc_obj_t cur = obj; + while (cur) { + if (cur->os_index != cur->logical_index) { + needindexes = 1; + break; + } + cur = cur->next_cousin; + } + } + if (*cachesize || *memsize || needindexes) { + ssize_t tmplen = buflen; + char *tmp = buffer; + int res, ret = 0; + + res = hwloc_snprintf(tmp, tmplen, "%s%s%s", cachesize, memsize, needindexes ? "" : ")"); + if (res < 0) + return -1; + ret += res; + if (res >= tmplen) + res = tmplen>0 ? tmplen - 1 : 0; + tmp += res; + tmplen -= res; + + if (needindexes) { + res = snprintf(tmp, tmplen, "%sindexes=", prefix); + if (res < 0) + return -1; + ret += res; + if (res >= tmplen) + res = tmplen>0 ? tmplen - 1 : 0; + tmp += res; + tmplen -= res; + + res = hwloc_topology_export_synthetic_indexes(topology, obj, tmp, tmplen); + if (res < 0) + return -1; + ret += res; + if (res >= tmplen) + res = tmplen>0 ? tmplen - 1 : 0; + tmp += res; + tmplen -= res; + } + return ret; + } else { + return 0; + } +} + +int +hwloc_topology_export_synthetic(struct hwloc_topology * topology, + char *buffer, size_t buflen, + unsigned long flags) +{ + hwloc_obj_t obj = hwloc_get_root_obj(topology); + ssize_t tmplen = buflen; + char *tmp = buffer; + int res, ret = 0; + int arity; + const char * separator = " "; + const char * prefix = ""; + + if (flags & ~(HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_EXTENDED_TYPES|HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_ATTRS)) { + errno = EINVAL; + return -1; + } + + /* TODO: add a flag to ignore symmetric_subtree and I/Os. + * just assume things are symmetric with the left branches of the tree. + * but the number of objects per level may be wrong, what to do with OS index array in this case? + * only allow ignoring symmetric_subtree if the level width remains OK? + */ + + /* TODO: add a root object by default, with a prefix such as tree= + * so that we can backward-compatibly recognize whether there's a root or not. + * and add a flag to disable it. + */ + + /* TODO: flag to force all indexes, not only for PU and NUMA? */ + + if (!obj->symmetric_subtree) { + errno = EINVAL; + return -1; + } + + if (!(flags & HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_ATTRS)) { + /* root attributes */ + res = hwloc_topology_export_synthetic_obj_attr(topology, obj, tmp, tmplen); + if (res < 0) + return -1; + ret += res; + if (ret > 0) + prefix = separator; + if (res >= tmplen) + res = tmplen>0 ? tmplen - 1 : 0; + tmp += res; + tmplen -= res; + } + + arity = obj->arity; + while (arity) { + /* for each level */ + obj = obj->first_child; + if (flags & HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_EXTENDED_TYPES) { + res = hwloc_snprintf(tmp, tmplen, "%s%s:%u", prefix, hwloc_obj_type_string(obj->type), arity); + } else { + char types[64]; + hwloc_obj_type_snprintf(types, sizeof(types), obj, 1); + res = hwloc_snprintf(tmp, tmplen, "%s%s:%u", prefix, types, arity); + } + if (res < 0) + return -1; + ret += res; + if (res >= tmplen) + res = tmplen>0 ? tmplen - 1 : 0; + tmp += res; + tmplen -= res; + + if (!(flags & HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_ATTRS)) { + /* obj attributes */ + res = hwloc_topology_export_synthetic_obj_attr(topology, obj, tmp, tmplen); + if (res < 0) + return -1; + ret += res; + if (res >= tmplen) + res = tmplen>0 ? tmplen - 1 : 0; + tmp += res; + tmplen -= res; + } + + /* next level */ + prefix = separator; + arity = obj->arity; + } + + return ret; +} diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/topology-windows.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-windows.c new file mode 100644 index 0000000000..371aaa1c8b --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-windows.c @@ -0,0 +1,812 @@ +/* + * Copyright © 2009 CNRS + * Copyright © 2009-2015 Inria. All rights reserved. + * Copyright © 2009-2012 Université Bordeaux + * Copyright © 2011 Cisco Systems, Inc. All rights reserved. + * See COPYING in top-level directory. + */ + +/* To try to get all declarations duplicated below. */ +#define _WIN32_WINNT 0x0601 + +#include +#include +#include +#include + +#include + +#ifndef HAVE_KAFFINITY +typedef ULONG_PTR KAFFINITY, *PKAFFINITY; +#endif + +#ifndef HAVE_PROCESSOR_CACHE_TYPE +typedef enum _PROCESSOR_CACHE_TYPE { + CacheUnified, + CacheInstruction, + CacheData, + CacheTrace +} PROCESSOR_CACHE_TYPE; +#endif + +#ifndef CACHE_FULLY_ASSOCIATIVE +#define CACHE_FULLY_ASSOCIATIVE 0xFF +#endif + +#ifndef HAVE_CACHE_DESCRIPTOR +typedef struct _CACHE_DESCRIPTOR { + BYTE Level; + BYTE Associativity; + WORD LineSize; + DWORD Size; /* in bytes */ + PROCESSOR_CACHE_TYPE Type; +} CACHE_DESCRIPTOR, *PCACHE_DESCRIPTOR; +#endif + +#ifndef HAVE_LOGICAL_PROCESSOR_RELATIONSHIP +typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP { + RelationProcessorCore, + RelationNumaNode, + RelationCache, + RelationProcessorPackage, + RelationGroup, + RelationAll = 0xffff +} LOGICAL_PROCESSOR_RELATIONSHIP; +#else /* HAVE_LOGICAL_PROCESSOR_RELATIONSHIP */ +# ifndef HAVE_RELATIONPROCESSORPACKAGE +# define RelationProcessorPackage 3 +# define RelationGroup 4 +# define RelationAll 0xffff +# endif /* HAVE_RELATIONPROCESSORPACKAGE */ +#endif /* HAVE_LOGICAL_PROCESSOR_RELATIONSHIP */ + +#ifndef HAVE_SYSTEM_LOGICAL_PROCESSOR_INFORMATION +typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION { + ULONG_PTR ProcessorMask; + LOGICAL_PROCESSOR_RELATIONSHIP Relationship; + _ANONYMOUS_UNION + union { + struct { + BYTE flags; + } ProcessorCore; + struct { + DWORD NodeNumber; + } NumaNode; + CACHE_DESCRIPTOR Cache; + ULONGLONG Reserved[2]; + } DUMMYUNIONNAME; +} SYSTEM_LOGICAL_PROCESSOR_INFORMATION, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION; +#endif + +/* Extended interface, for group support */ + +#ifndef HAVE_GROUP_AFFINITY +typedef struct _GROUP_AFFINITY { + KAFFINITY Mask; + WORD Group; + WORD Reserved[3]; +} GROUP_AFFINITY, *PGROUP_AFFINITY; +#endif + +#ifndef HAVE_PROCESSOR_RELATIONSHIP +typedef struct _PROCESSOR_RELATIONSHIP { + BYTE Flags; + BYTE Reserved[21]; + WORD GroupCount; + GROUP_AFFINITY GroupMask[ANYSIZE_ARRAY]; +} PROCESSOR_RELATIONSHIP, *PPROCESSOR_RELATIONSHIP; +#endif + +#ifndef HAVE_NUMA_NODE_RELATIONSHIP +typedef struct _NUMA_NODE_RELATIONSHIP { + DWORD NodeNumber; + BYTE Reserved[20]; + GROUP_AFFINITY GroupMask; +} NUMA_NODE_RELATIONSHIP, *PNUMA_NODE_RELATIONSHIP; +#endif + +#ifndef HAVE_CACHE_RELATIONSHIP +typedef struct _CACHE_RELATIONSHIP { + BYTE Level; + BYTE Associativity; + WORD LineSize; + DWORD CacheSize; + PROCESSOR_CACHE_TYPE Type; + BYTE Reserved[20]; + GROUP_AFFINITY GroupMask; +} CACHE_RELATIONSHIP, *PCACHE_RELATIONSHIP; +#endif + +#ifndef HAVE_PROCESSOR_GROUP_INFO +typedef struct _PROCESSOR_GROUP_INFO { + BYTE MaximumProcessorCount; + BYTE ActiveProcessorCount; + BYTE Reserved[38]; + KAFFINITY ActiveProcessorMask; +} PROCESSOR_GROUP_INFO, *PPROCESSOR_GROUP_INFO; +#endif + +#ifndef HAVE_GROUP_RELATIONSHIP +typedef struct _GROUP_RELATIONSHIP { + WORD MaximumGroupCount; + WORD ActiveGroupCount; + ULONGLONG Reserved[2]; + PROCESSOR_GROUP_INFO GroupInfo[ANYSIZE_ARRAY]; +} GROUP_RELATIONSHIP, *PGROUP_RELATIONSHIP; +#endif + +#ifndef HAVE_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX +typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX { + LOGICAL_PROCESSOR_RELATIONSHIP Relationship; + DWORD Size; + _ANONYMOUS_UNION + union { + PROCESSOR_RELATIONSHIP Processor; + NUMA_NODE_RELATIONSHIP NumaNode; + CACHE_RELATIONSHIP Cache; + GROUP_RELATIONSHIP Group; + /* Odd: no member to tell the cpu mask of the package... */ + } DUMMYUNIONNAME; +} SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX; +#endif + +#ifndef HAVE_PSAPI_WORKING_SET_EX_BLOCK +typedef union _PSAPI_WORKING_SET_EX_BLOCK { + ULONG_PTR Flags; + struct { + unsigned Valid :1; + unsigned ShareCount :3; + unsigned Win32Protection :11; + unsigned Shared :1; + unsigned Node :6; + unsigned Locked :1; + unsigned LargePage :1; + }; +} PSAPI_WORKING_SET_EX_BLOCK; +#endif + +#ifndef HAVE_PSAPI_WORKING_SET_EX_INFORMATION +typedef struct _PSAPI_WORKING_SET_EX_INFORMATION { + PVOID VirtualAddress; + PSAPI_WORKING_SET_EX_BLOCK VirtualAttributes; +} PSAPI_WORKING_SET_EX_INFORMATION; +#endif + +static void hwloc_bitmap_set_ith_ULONG_PTR(hwloc_bitmap_t set, unsigned i, ULONG_PTR mask) +{ + /* ULONG_PTR is 64/32bits depending on the arch + * while unsigned long is always 32bits */ +#if SIZEOF_VOID_P == 8 + hwloc_bitmap_set_ith_ulong(set, 2*i, mask & 0xffffffff); + hwloc_bitmap_set_ith_ulong(set, 2*i+1, mask >> 32); +#else + hwloc_bitmap_set_ith_ulong(set, i, mask); +#endif +} + +/* TODO: SetThreadIdealProcessor */ + +static int +hwloc_win_set_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_thread_t thread, hwloc_const_bitmap_t hwloc_set, int flags) +{ + DWORD mask; + + if (flags & HWLOC_CPUBIND_NOMEMBIND) { + errno = ENOSYS; + return -1; + } + /* TODO: groups SetThreadGroupAffinity */ + /* The resulting binding is always strict */ + mask = hwloc_bitmap_to_ulong(hwloc_set); + if (!SetThreadAffinityMask(thread, mask)) + return -1; + return 0; +} + +/* TODO: SetThreadGroupAffinity to get affinity */ + +static int +hwloc_win_set_thisthread_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags) +{ + return hwloc_win_set_thread_cpubind(topology, GetCurrentThread(), hwloc_set, flags); +} + +static int +hwloc_win_set_thisthread_membind(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) +{ + int ret; + hwloc_cpuset_t cpuset; + + if ((policy != HWLOC_MEMBIND_DEFAULT && policy != HWLOC_MEMBIND_BIND) + || flags & HWLOC_MEMBIND_NOCPUBIND) { + errno = ENOSYS; + return -1; + } + + cpuset = hwloc_bitmap_alloc(); + hwloc_cpuset_from_nodeset(topology, cpuset, nodeset); + ret = hwloc_win_set_thisthread_cpubind(topology, cpuset, flags & HWLOC_MEMBIND_STRICT?HWLOC_CPUBIND_STRICT:0); + hwloc_bitmap_free(cpuset); + return ret; +} + +static int +hwloc_win_set_proc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_pid_t proc, hwloc_const_bitmap_t hwloc_set, int flags) +{ + DWORD mask; + if (flags & HWLOC_CPUBIND_NOMEMBIND) { + errno = ENOSYS; + return -1; + } + /* TODO: groups, hard: has to manually bind all threads into the other group, + * and the bind the process inside the group */ + /* The resulting binding is always strict */ + mask = hwloc_bitmap_to_ulong(hwloc_set); + if (!SetProcessAffinityMask(proc, mask)) + return -1; + return 0; +} + +static int +hwloc_win_set_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) +{ + int ret; + hwloc_cpuset_t cpuset; + + if ((policy != HWLOC_MEMBIND_DEFAULT && policy != HWLOC_MEMBIND_BIND) + || flags & HWLOC_MEMBIND_NOCPUBIND) { + errno = ENOSYS; + return -1; + } + + cpuset = hwloc_bitmap_alloc(); + hwloc_cpuset_from_nodeset(topology, cpuset, nodeset); + ret = hwloc_win_set_proc_cpubind(topology, pid, cpuset, flags & HWLOC_MEMBIND_STRICT?HWLOC_CPUBIND_STRICT:0); + hwloc_bitmap_free(cpuset); + return ret; +} + +static int +hwloc_win_get_proc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_pid_t proc, hwloc_bitmap_t hwloc_set, int flags) +{ + DWORD_PTR proc_mask, sys_mask; + if (flags & HWLOC_CPUBIND_NOMEMBIND) { + errno = ENOSYS; + return -1; + } + /* TODO: groups, GetProcessGroupAffinity, or merge SetThreadGroupAffinity for all threads */ + if (!GetProcessAffinityMask(proc, &proc_mask, &sys_mask)) + return -1; + hwloc_bitmap_from_ulong(hwloc_set, proc_mask); + return 0; +} + +static int +hwloc_win_get_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags) +{ + int ret; + hwloc_cpuset_t cpuset = hwloc_bitmap_alloc(); + ret = hwloc_win_get_proc_cpubind(topology, pid, cpuset, flags & HWLOC_MEMBIND_STRICT?HWLOC_CPUBIND_STRICT:0); + if (!ret) { + *policy = HWLOC_MEMBIND_BIND; + hwloc_cpuset_to_nodeset(topology, cpuset, nodeset); + } + hwloc_bitmap_free(cpuset); + return ret; +} + +static int +hwloc_win_set_thisproc_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags) +{ + return hwloc_win_set_proc_cpubind(topology, GetCurrentProcess(), hwloc_set, flags); +} + +static int +hwloc_win_set_thisproc_membind(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) +{ + return hwloc_win_set_proc_membind(topology, GetCurrentProcess(), nodeset, policy, flags); +} + +static int +hwloc_win_get_thisproc_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_cpuset, int flags) +{ + return hwloc_win_get_proc_cpubind(topology, GetCurrentProcess(), hwloc_cpuset, flags); +} + +static int +hwloc_win_get_thisproc_membind(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags) +{ + return hwloc_win_get_proc_membind(topology, GetCurrentProcess(), nodeset, policy, flags); +} + +static LPVOID (WINAPI *VirtualAllocExNumaProc)(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect, DWORD nndPreferred); +static BOOL (WINAPI *VirtualFreeExProc)(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType); +static BOOL (WINAPI *QueryWorkingSetExProc)(HANDLE hProcess, PVOID pv, DWORD cb); + +static int hwloc_win_get_VirtualAllocExNumaProc(void) { + if (VirtualAllocExNumaProc == NULL) { + FARPROC alloc_fun = NULL, free_fun = NULL; + HMODULE kernel32; + + kernel32 = LoadLibrary("kernel32.dll"); + if (kernel32) { + alloc_fun = GetProcAddress(kernel32, "VirtualAllocExNuma"); + free_fun = GetProcAddress(kernel32, "VirtualFreeEx"); + } + + if (!alloc_fun || !free_fun) { + VirtualAllocExNumaProc = (FARPROC) -1; + errno = ENOSYS; + return -1; + } + + VirtualAllocExNumaProc = alloc_fun; + VirtualFreeExProc = free_fun; + } else if ((FARPROC) VirtualAllocExNumaProc == (FARPROC)-1) { + errno = ENOSYS; + return -1; + } + + return 0; +} + +static void * +hwloc_win_alloc(hwloc_topology_t topology __hwloc_attribute_unused, size_t len) { + return VirtualAlloc(NULL, len, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE); +} + +static void * +hwloc_win_alloc_membind(hwloc_topology_t topology __hwloc_attribute_unused, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) { + int node; + + switch (policy) { + case HWLOC_MEMBIND_DEFAULT: + case HWLOC_MEMBIND_BIND: + break; + default: + errno = ENOSYS; + return hwloc_alloc_or_fail(topology, len, flags); + } + + if (flags & HWLOC_MEMBIND_STRICT) { + errno = ENOSYS; + return NULL; + } + + if (hwloc_bitmap_weight(nodeset) != 1) { + /* Not a single node, can't do this */ + errno = EXDEV; + return hwloc_alloc_or_fail(topology, len, flags); + } + + node = hwloc_bitmap_first(nodeset); + return VirtualAllocExNumaProc(GetCurrentProcess(), NULL, len, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE, node); +} + +static int +hwloc_win_free_membind(hwloc_topology_t topology __hwloc_attribute_unused, void *addr, size_t len __hwloc_attribute_unused) { + if (!addr) + return 0; + if (!VirtualFreeExProc(GetCurrentProcess(), addr, 0, MEM_RELEASE)) + return -1; + return 0; +} + +static int hwloc_win_get_QueryWorkingSetExProc(void) { + if (QueryWorkingSetExProc == NULL) { + FARPROC fun = NULL; + HMODULE kernel32, psapi; + + kernel32 = LoadLibrary("kernel32.dll"); + if (kernel32) + fun = GetProcAddress(kernel32, "K32QueryWorkingSetEx"); + if (!fun) { + psapi = LoadLibrary("psapi.dll"); + if (psapi) + fun = GetProcAddress(psapi, "QueryWorkingSetEx"); + } + + if (!fun) { + QueryWorkingSetExProc = (FARPROC) -1; + errno = ENOSYS; + return -1; + } + + QueryWorkingSetExProc = fun; + } else if ((FARPROC) QueryWorkingSetExProc == (FARPROC)-1) { + errno = ENOSYS; + return -1; + } + + return 0; +} + +static int +hwloc_win_get_area_membind(hwloc_topology_t topology __hwloc_attribute_unused, const void *addr, size_t len, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags) +{ + SYSTEM_INFO SystemInfo; + DWORD page_size; + uintptr_t start; + unsigned nb; + + GetSystemInfo(&SystemInfo); + page_size = SystemInfo.dwPageSize; + + start = (((uintptr_t) addr) / page_size) * page_size; + nb = (((uintptr_t) addr + len - start) + page_size - 1) / page_size; + + if (!nb) + nb = 1; + + { + PSAPI_WORKING_SET_EX_INFORMATION *pv; + unsigned i; + + pv = calloc(nb, sizeof(*pv)); + + for (i = 0; i < nb; i++) + pv[i].VirtualAddress = (void*) (start + i * page_size); + if (!QueryWorkingSetExProc(GetCurrentProcess(), pv, nb * sizeof(*pv))) { + free(pv); + return -1; + } + *policy = HWLOC_MEMBIND_BIND; + if (flags & HWLOC_MEMBIND_STRICT) { + unsigned node = pv[0].VirtualAttributes.Node; + for (i = 1; i < nb; i++) { + if (pv[i].VirtualAttributes.Node != node) { + errno = EXDEV; + free(pv); + return -1; + } + } + hwloc_bitmap_only(nodeset, node); + free(pv); + return 0; + } + hwloc_bitmap_zero(nodeset); + for (i = 0; i < nb; i++) + hwloc_bitmap_set(nodeset, pv[i].VirtualAttributes.Node); + free(pv); + return 0; + } +} + +static int +hwloc_look_windows(struct hwloc_backend *backend) +{ + struct hwloc_topology *topology = backend->topology; + BOOL (WINAPI *GetLogicalProcessorInformationProc)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer, PDWORD ReturnLength); + BOOL (WINAPI *GetLogicalProcessorInformationExProc)(LOGICAL_PROCESSOR_RELATIONSHIP relationship, PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Buffer, PDWORD ReturnLength); + BOOL (WINAPI *GetNumaAvailableMemoryNodeProc)(UCHAR Node, PULONGLONG AvailableBytes); + BOOL (WINAPI *GetNumaAvailableMemoryNodeExProc)(USHORT Node, PULONGLONG AvailableBytes); + SYSTEM_INFO SystemInfo; + + DWORD length; + + HMODULE kernel32; + + if (topology->levels[0][0]->cpuset) + /* somebody discovered things */ + return 0; + + hwloc_alloc_obj_cpusets(topology->levels[0][0]); + + GetSystemInfo(&SystemInfo); + + kernel32 = LoadLibrary("kernel32.dll"); + if (kernel32) { + GetLogicalProcessorInformationProc = GetProcAddress(kernel32, "GetLogicalProcessorInformation"); + GetNumaAvailableMemoryNodeProc = GetProcAddress(kernel32, "GetNumaAvailableMemoryNode"); + GetNumaAvailableMemoryNodeExProc = GetProcAddress(kernel32, "GetNumaAvailableMemoryNodeEx"); + GetLogicalProcessorInformationExProc = GetProcAddress(kernel32, "GetLogicalProcessorInformationEx"); + + if (!GetLogicalProcessorInformationExProc && GetLogicalProcessorInformationProc) { + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION procInfo; + unsigned id; + unsigned i; + struct hwloc_obj *obj; + hwloc_obj_type_t type; + + length = 0; + procInfo = NULL; + + while (1) { + if (GetLogicalProcessorInformationProc(procInfo, &length)) + break; + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + return -1; + procInfo = realloc(procInfo, length); + } + + assert(!length || procInfo); + + for (i = 0; i < length / sizeof(*procInfo); i++) { + + /* Ignore unknown caches */ + if (procInfo->Relationship == RelationCache + && procInfo->Cache.Type != CacheUnified + && procInfo->Cache.Type != CacheData + && procInfo->Cache.Type != CacheInstruction) + continue; + + id = -1; + switch (procInfo[i].Relationship) { + case RelationNumaNode: + type = HWLOC_OBJ_NUMANODE; + id = procInfo[i].NumaNode.NodeNumber; + break; + case RelationProcessorPackage: + type = HWLOC_OBJ_PACKAGE; + break; + case RelationCache: + type = HWLOC_OBJ_CACHE; + break; + case RelationProcessorCore: + type = HWLOC_OBJ_CORE; + break; + case RelationGroup: + default: + type = HWLOC_OBJ_GROUP; + break; + } + + obj = hwloc_alloc_setup_object(type, id); + obj->cpuset = hwloc_bitmap_alloc(); + hwloc_debug("%s#%u mask %lx\n", hwloc_obj_type_string(type), id, procInfo[i].ProcessorMask); + /* ProcessorMask is a ULONG_PTR */ + hwloc_bitmap_set_ith_ULONG_PTR(obj->cpuset, 0, procInfo[i].ProcessorMask); + hwloc_debug_2args_bitmap("%s#%u bitmap %s\n", hwloc_obj_type_string(type), id, obj->cpuset); + + switch (type) { + case HWLOC_OBJ_NUMANODE: + { + ULONGLONG avail; + obj->nodeset = hwloc_bitmap_alloc(); + hwloc_bitmap_set(obj->nodeset, id); + if ((GetNumaAvailableMemoryNodeExProc && GetNumaAvailableMemoryNodeExProc(id, &avail)) + || (GetNumaAvailableMemoryNodeProc && GetNumaAvailableMemoryNodeProc(id, &avail))) + obj->memory.local_memory = avail; + 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_len = 1; + obj->memory.page_types[0].size = SystemInfo.dwPageSize; +#ifdef HAVE__SC_LARGE_PAGESIZE + obj->memory.page_types_len++; + obj->memory.page_types[1].size = sysconf(_SC_LARGE_PAGESIZE); +#endif + break; + } + case HWLOC_OBJ_CACHE: + obj->attr->cache.size = procInfo[i].Cache.Size; + obj->attr->cache.associativity = procInfo[i].Cache.Associativity == CACHE_FULLY_ASSOCIATIVE ? -1 : procInfo[i].Cache.Associativity ; + obj->attr->cache.linesize = procInfo[i].Cache.LineSize; + obj->attr->cache.depth = procInfo[i].Cache.Level; + switch (procInfo->Cache.Type) { + case CacheUnified: + obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED; + break; + case CacheData: + obj->attr->cache.type = HWLOC_OBJ_CACHE_DATA; + break; + case CacheInstruction: + obj->attr->cache.type = HWLOC_OBJ_CACHE_INSTRUCTION; + break; + default: + hwloc_free_unlinked_object(obj); + continue; + } + break; + case HWLOC_OBJ_GROUP: + obj->attr->group.depth = procInfo[i].Relationship == RelationGroup; + break; + default: + break; + } + hwloc_insert_object_by_cpuset(topology, obj); + } + + free(procInfo); + } + + if (GetLogicalProcessorInformationExProc) { + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX procInfoTotal, procInfo; + + unsigned id; + struct hwloc_obj *obj; + hwloc_obj_type_t type; + + length = 0; + procInfoTotal = NULL; + + while (1) { + if (GetLogicalProcessorInformationExProc(RelationAll, procInfoTotal, &length)) + break; + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + return -1; + procInfoTotal = realloc(procInfoTotal, length); + } + + for (procInfo = procInfoTotal; + (void*) procInfo < (void*) ((uintptr_t) procInfoTotal + length); + procInfo = (void*) ((uintptr_t) procInfo + procInfo->Size)) { + unsigned num, i; + GROUP_AFFINITY *GroupMask; + + /* Ignore unknown caches */ + if (procInfo->Relationship == RelationCache + && procInfo->Cache.Type != CacheUnified + && procInfo->Cache.Type != CacheData + && procInfo->Cache.Type != CacheInstruction) + continue; + + id = -1; + switch (procInfo->Relationship) { + case RelationNumaNode: + type = HWLOC_OBJ_NUMANODE; + num = 1; + GroupMask = &procInfo->NumaNode.GroupMask; + id = procInfo->NumaNode.NodeNumber; + break; + case RelationProcessorPackage: + type = HWLOC_OBJ_PACKAGE; + num = procInfo->Processor.GroupCount; + GroupMask = procInfo->Processor.GroupMask; + break; + case RelationCache: + type = HWLOC_OBJ_CACHE; + num = 1; + GroupMask = &procInfo->Cache.GroupMask; + break; + case RelationProcessorCore: + type = HWLOC_OBJ_CORE; + num = procInfo->Processor.GroupCount; + GroupMask = procInfo->Processor.GroupMask; + break; + case RelationGroup: + /* So strange an interface... */ + for (id = 0; id < procInfo->Group.ActiveGroupCount; id++) { + KAFFINITY mask; + obj = hwloc_alloc_setup_object(HWLOC_OBJ_GROUP, id); + obj->cpuset = hwloc_bitmap_alloc(); + mask = procInfo->Group.GroupInfo[id].ActiveProcessorMask; + hwloc_debug("group %u %d cpus mask %lx\n", id, + procInfo->Group.GroupInfo[id].ActiveProcessorCount, mask); + /* KAFFINITY is ULONG_PTR */ + hwloc_bitmap_set_ith_ULONG_PTR(obj->cpuset, id, mask); + hwloc_debug_2args_bitmap("group %u %d bitmap %s\n", id, procInfo->Group.GroupInfo[id].ActiveProcessorCount, obj->cpuset); + hwloc_insert_object_by_cpuset(topology, obj); + } + continue; + default: + /* Don't know how to get the mask. */ + hwloc_debug("unknown relation %d\n", procInfo->Relationship); + continue; + } + + obj = hwloc_alloc_setup_object(type, id); + obj->cpuset = hwloc_bitmap_alloc(); + for (i = 0; i < num; i++) { + hwloc_debug("%s#%u %d: mask %d:%lx\n", hwloc_obj_type_string(type), id, i, GroupMask[i].Group, GroupMask[i].Mask); + /* GROUP_AFFINITY.Mask is KAFFINITY, which is ULONG_PTR */ + hwloc_bitmap_set_ith_ULONG_PTR(obj->cpuset, GroupMask[i].Group, GroupMask[i].Mask); + } + hwloc_debug("%s#%u bitmap %s\n", hwloc_obj_type_string(type), id, obj->cpuset); + + switch (type) { + case HWLOC_OBJ_NUMANODE: + { + ULONGLONG avail; + obj->nodeset = hwloc_bitmap_alloc(); + hwloc_bitmap_set(obj->nodeset, id); + if ((GetNumaAvailableMemoryNodeExProc && GetNumaAvailableMemoryNodeExProc(id, &avail)) + || (GetNumaAvailableMemoryNodeProc && GetNumaAvailableMemoryNodeProc(id, &avail))) + obj->memory.local_memory = avail; + 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_len = 1; + obj->memory.page_types[0].size = SystemInfo.dwPageSize; +#ifdef HAVE__SC_LARGE_PAGESIZE + obj->memory.page_types_len++; + obj->memory.page_types[1].size = sysconf(_SC_LARGE_PAGESIZE); +#endif + break; + } + case HWLOC_OBJ_CACHE: + obj->attr->cache.size = procInfo->Cache.CacheSize; + obj->attr->cache.associativity = procInfo->Cache.Associativity == CACHE_FULLY_ASSOCIATIVE ? -1 : procInfo->Cache.Associativity ; + obj->attr->cache.linesize = procInfo->Cache.LineSize; + obj->attr->cache.depth = procInfo->Cache.Level; + switch (procInfo->Cache.Type) { + case CacheUnified: + obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED; + break; + case CacheData: + obj->attr->cache.type = HWLOC_OBJ_CACHE_DATA; + break; + case CacheInstruction: + obj->attr->cache.type = HWLOC_OBJ_CACHE_INSTRUCTION; + break; + default: + hwloc_free_unlinked_object(obj); + continue; + } + break; + default: + break; + } + hwloc_insert_object_by_cpuset(topology, obj); + } + free(procInfoTotal); + } + } + + /* add PU objects */ + hwloc_setup_pu_level(topology, hwloc_fallback_nbprocessors(topology)); + + hwloc_obj_add_info(topology->levels[0][0], "Backend", "Windows"); + if (topology->is_thissystem) + hwloc_add_uname_info(topology, NULL); + return 1; +} + +void +hwloc_set_windows_hooks(struct hwloc_binding_hooks *hooks, + struct hwloc_topology_support *support) +{ + hooks->set_proc_cpubind = hwloc_win_set_proc_cpubind; + hooks->get_proc_cpubind = hwloc_win_get_proc_cpubind; + hooks->set_thread_cpubind = hwloc_win_set_thread_cpubind; + hooks->set_thisproc_cpubind = hwloc_win_set_thisproc_cpubind; + hooks->get_thisproc_cpubind = hwloc_win_get_thisproc_cpubind; + hooks->set_thisthread_cpubind = hwloc_win_set_thisthread_cpubind; + /* TODO: get_last_cpu_location: use GetCurrentProcessorNumber */ + + hooks->set_proc_membind = hwloc_win_set_proc_membind; + hooks->get_proc_membind = hwloc_win_get_proc_membind; + hooks->set_thisproc_membind = hwloc_win_set_thisproc_membind; + hooks->get_thisproc_membind = hwloc_win_get_thisproc_membind; + hooks->set_thisthread_membind = hwloc_win_set_thisthread_membind; + + if (!hwloc_win_get_VirtualAllocExNumaProc()) { + hooks->alloc_membind = hwloc_win_alloc_membind; + hooks->alloc = hwloc_win_alloc; + hooks->free_membind = hwloc_win_free_membind; + support->membind->bind_membind = 1; + } + + if (!hwloc_win_get_QueryWorkingSetExProc()) + hooks->get_area_membind = hwloc_win_get_area_membind; +} + +static struct hwloc_backend * +hwloc_windows_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_windows; + return backend; +} + +static struct hwloc_disc_component hwloc_windows_disc_component = { + HWLOC_DISC_COMPONENT_TYPE_CPU, + "windows", + HWLOC_DISC_COMPONENT_TYPE_GLOBAL, + hwloc_windows_component_instantiate, + 50, + NULL +}; + +const struct hwloc_component hwloc_windows_component = { + HWLOC_COMPONENT_ABI, + NULL, NULL, + HWLOC_COMPONENT_TYPE_DISC, + 0, + &hwloc_windows_disc_component +}; diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/topology-x86.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-x86.c new file mode 100644 index 0000000000..db91a5ef6d --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-x86.c @@ -0,0 +1,1104 @@ +/* + * Copyright © 2010-2015 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 + +struct hwloc_x86_backend_data_s { + unsigned nbprocs; + hwloc_bitmap_t apicid_set; + int apicid_unique; +}; + +#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 linesize; + unsigned linepart; + 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; + 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; + + cachenum = infos->numcaches++; + infos->cache = realloc(infos->cache, infos->numcaches*sizeof(*infos->cache)); + 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; + 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; + + /* 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, unit_id, cores_per_unit; + + eax = 0x8000001e; + hwloc_x86_cpuid(&eax, &ebx, &ecx, &edx); + infos->apicid = apic_id = eax; + infos->nodeid = node_id = ecx & 0xff; + nodes_per_proc = ((ecx >> 8) & 7) + 1; + if (nodes_per_proc > 2) { + hwloc_debug("warning: undefined value %d, assuming it means %d\n", nodes_per_proc, nodes_per_proc); + } + infos->unitid = unit_id = ebx & 0xff; + cores_per_unit = ((ebx >> 8) & 3) + 1; + hwloc_debug("x2APIC %08x, %d nodes, node %d, %d cores in unit %d\n", apic_id, nodes_per_proc, node_id, cores_per_unit, unit_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; + + 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 */ + /* FIXME: AMD MagnyCours family 0x10 model 0x9 with 8 cores or more actually + * have the L3 split in two halves, and associativity is divided as well (48) + */ + } + } + + /* Get thread/core + cache information from cpuid 0x04 + * (not supported on AMD) + */ + if (cpuid_type != amd && highest_cpuid >= 0x04) { + 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; + 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; + + cache->type = type; + cache->level = (eax >> 5) & 0x7; + 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; + + 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 && 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); + } + } + + 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 void 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; + + 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; + } + + /* 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 packages_cpuset = hwloc_bitmap_dup(complete_cpuset); + hwloc_bitmap_t package_cpuset; + hwloc_obj_t package; + + while ((i = hwloc_bitmap_first(packages_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(packages_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++; + } + hwloc_bitmap_free(packages_cpuset); + + } 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 nodes_cpuset = hwloc_bitmap_dup(complete_cpuset); + hwloc_bitmap_t node_cpuset; + hwloc_obj_t node; + + while ((i = hwloc_bitmap_first(nodes_cpuset)) != (unsigned) -1) { + unsigned packageid = infos[i].packageid; + unsigned nodeid = infos[i].nodeid; + + if (nodeid == (unsigned)-1) { + hwloc_bitmap_clr(nodes_cpuset, i); + continue; + } + + node_cpuset = hwloc_bitmap_alloc(); + for (j = i; j < nbprocs; j++) { + if (infos[j].nodeid == (unsigned) -1) { + hwloc_bitmap_clr(nodes_cpuset, j); + continue; + } + + if (infos[j].packageid == packageid && infos[j].nodeid == nodeid) { + hwloc_bitmap_set(node_cpuset, j); + hwloc_bitmap_clr(nodes_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); + } + hwloc_bitmap_free(nodes_cpuset); + } + + /* Look for Compute units inside packages */ + if (fulldiscovery) { + hwloc_bitmap_t units_cpuset = hwloc_bitmap_dup(complete_cpuset); + hwloc_bitmap_t unit_cpuset; + hwloc_obj_t unit; + + while ((i = hwloc_bitmap_first(units_cpuset)) != (unsigned) -1) { + unsigned packageid = infos[i].packageid; + unsigned unitid = infos[i].unitid; + + if (unitid == (unsigned)-1) { + hwloc_bitmap_clr(units_cpuset, i); + continue; + } + + unit_cpuset = hwloc_bitmap_alloc(); + for (j = i; j < nbprocs; j++) { + if (infos[j].unitid == (unsigned) -1) { + hwloc_bitmap_clr(units_cpuset, j); + continue; + } + + if (infos[j].packageid == packageid && infos[j].unitid == unitid) { + hwloc_bitmap_set(unit_cpuset, j); + hwloc_bitmap_clr(units_cpuset, j); + } + } + unit = hwloc_alloc_setup_object(HWLOC_OBJ_GROUP, unitid); + unit->cpuset = unit_cpuset; + hwloc_debug_1arg_bitmap("os unit %u has cpuset %s\n", + unitid, unit_cpuset); + hwloc_insert_object_by_cpuset(topology, unit); + } + hwloc_bitmap_free(units_cpuset); + } + + /* 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 unknowns_cpuset = hwloc_bitmap_dup(complete_cpuset); + hwloc_bitmap_t unknown_cpuset; + hwloc_obj_t unknown_obj; + + while ((i = hwloc_bitmap_first(unknowns_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(unknowns_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); + } + hwloc_bitmap_free(unknowns_cpuset); + } + } + } + + /* Look for cores */ + if (fulldiscovery) { + hwloc_bitmap_t cores_cpuset = hwloc_bitmap_dup(complete_cpuset); + hwloc_bitmap_t core_cpuset; + hwloc_obj_t core; + + while ((i = hwloc_bitmap_first(cores_cpuset)) != (unsigned) -1) { + unsigned packageid = infos[i].packageid; + unsigned coreid = infos[i].coreid; + + if (coreid == (unsigned) -1) { + hwloc_bitmap_clr(cores_cpuset, i); + continue; + } + + core_cpuset = hwloc_bitmap_alloc(); + for (j = i; j < nbprocs; j++) { + if (infos[j].coreid == (unsigned) -1) { + hwloc_bitmap_clr(cores_cpuset, j); + continue; + } + + if (infos[j].packageid == packageid && infos[j].coreid == coreid) { + hwloc_bitmap_set(core_cpuset, j); + hwloc_bitmap_clr(cores_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); + } + hwloc_bitmap_free(cores_cpuset); + } + + /* 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; + + /* Look for known types */ + if (fulldiscovery) while (level > 0) { + for (type = 1; type <= 3; type++) { + /* Look for caches of that type at level level */ + { + hwloc_bitmap_t caches_cpuset = hwloc_bitmap_dup(complete_cpuset); + hwloc_bitmap_t cache_cpuset; + hwloc_obj_t cache; + + while ((i = hwloc_bitmap_first(caches_cpuset)) != (unsigned) -1) { + unsigned packageid = infos[i].packageid; + + 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(caches_cpuset, i); + continue; + } + + /* Found a matching cache, now look for others sharing it */ + { + unsigned cacheid = infos[i].apicid / infos[i].cache[l].nbthreads_sharing; + + 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(caches_cpuset, j); + continue; + } + if (infos[j].packageid == packageid && infos[j].apicid / infos[j].cache[l2].nbthreads_sharing == cacheid) { + hwloc_bitmap_set(cache_cpuset, j); + hwloc_bitmap_clr(caches_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_debug_2args_bitmap("os L%u cache %u has cpuset %s\n", + level, cacheid, cache_cpuset); + hwloc_insert_object_by_cpuset(topology, cache); + } + } + hwloc_bitmap_free(caches_cpuset); + } + } + level--; + } + + for (i = 0; i < nbprocs; i++) { + free(infos[i].cache); + if (infos[i].otherids) + free(infos[i].otherids); + } + + hwloc_bitmap_free(complete_cpuset); + topology->next_group_depth = next_group_depth; +} + +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; + + 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; + summarize(backend, infos, fulldiscovery); + return fulldiscovery; /* success, but objects added only if fulldiscovery */ +} + +#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_thisproc_cpubind && hooks.set_thisproc_cpubind) { + get_cpubind = hooks.get_thisproc_cpubind; + set_cpubind = hooks.set_thisproc_cpubind; + } else if (hooks.get_thisthread_cpubind && hooks.set_thisthread_cpubind) { + get_cpubind = hooks.get_thisthread_cpubind; + set_cpubind = hooks.set_thisthread_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; + 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); + summarize(backend, infos, fulldiscovery); + ret = fulldiscovery; + } + +out_with_os_state: + hwloc_x86_os_state_restore(&os_state); + +out_with_infos: + if (NULL != infos) { + 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; + + 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 annotate a bit */ + ret = hwloc_look_x86(backend, 0); + if (ret) + hwloc_obj_add_info(topology->levels[0][0], "Backend", "x86"); + return 0; + } else { + /* topology is empty, initialize it */ + hwloc_alloc_obj_cpusets(topology->levels[0][0]); + } + +fulldiscovery: + hwloc_look_x86(backend, 1); + /* if failed, just continue and 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->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/hwloc1110/hwloc/src/topology-xml-libxml.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-xml-libxml.c new file mode 100644 index 0000000000..ce3250c285 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-xml-libxml.c @@ -0,0 +1,543 @@ +/* + * Copyright © 2009 CNRS + * Copyright © 2009-2014 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 + +/* private headers allowed because this plugin is built within hwloc */ +#include +#include + +#include +#include + +/******************* + * Common routines * + *******************/ + +static void hwloc_libxml2_error_callback(void * ctx __hwloc_attribute_unused, const char * msg __hwloc_attribute_unused, ...) { /* do nothing */ } + +static void +hwloc_libxml2_disable_stderrwarnings(void) +{ + static int first = 1; + if (first) { + xmlSetGenericErrorFunc(NULL, hwloc__xml_verbose() ? xmlGenericError : hwloc_libxml2_error_callback); + first = 0; + } +} + +/******************* + * Import routines * + *******************/ + +typedef struct hwloc__libxml_import_state_data_s { + xmlNode *node; /* current libxml node, always valid */ + xmlNode *child; /* last processed child, or NULL if none yet */ + xmlAttr *attr; /* last processed attribute, or NULL if none yet */ +} __hwloc_attribute_may_alias * hwloc__libxml_import_state_data_t; + +static int +hwloc__libxml_import_next_attr(hwloc__xml_import_state_t state, char **namep, char **valuep) +{ + hwloc__libxml_import_state_data_t lstate = (void*) state->data; + + xmlAttr *attr; + if (lstate->attr) + attr = lstate->attr->next; + else + attr = lstate->node->properties; + for (; attr; attr = attr->next) + if (attr->type == XML_ATTRIBUTE_NODE) { + /* use the first valid attribute content */ + xmlNode *subnode; + for (subnode = attr->children; subnode; subnode = subnode->next) { + if (subnode->type == XML_TEXT_NODE) { + if (subnode->content && subnode->content[0] != '\0' && subnode->content[0] != '\n') { + *namep = (char *) attr->name; + *valuep = (char *) subnode->content; + lstate->attr = attr; + return 0; + } + } else { + if (hwloc__xml_verbose()) + fprintf(stderr, "ignoring unexpected xml attr node type %u\n", subnode->type); + } + } + } else { + if (hwloc__xml_verbose()) + fprintf(stderr, "ignoring unexpected xml attr type %u\n", attr->type); + } + return -1; +} + +static int +hwloc__libxml_import_find_child(hwloc__xml_import_state_t state, + hwloc__xml_import_state_t childstate, + char **tagp) +{ + hwloc__libxml_import_state_data_t lstate = (void*) state->data; + hwloc__libxml_import_state_data_t lchildstate = (void*) childstate->data; + xmlNode *child; + childstate->parent = state; + childstate->global = state->global; + if (!lstate->child) + return 0; + child = lstate->child->next; + for (; child; child = child->next) + if (child->type == XML_ELEMENT_NODE) { + lstate->child = lchildstate->node = child; + lchildstate->child = child->children; + lchildstate->attr = NULL; + *tagp = (char*) child->name; + return 1; + } else if (child->type == XML_TEXT_NODE) { + if (child->content && child->content[0] != '\0' && child->content[0] != '\n') + if (hwloc__xml_verbose()) + fprintf(stderr, "ignoring object text content %s\n", (const char*) child->content); + } else if (child->type != XML_COMMENT_NODE) { + if (hwloc__xml_verbose()) + fprintf(stderr, "ignoring unexpected xml node type %u\n", child->type); + } + + return 0; +} + +static int +hwloc__libxml_import_close_tag(hwloc__xml_import_state_t state __hwloc_attribute_unused) +{ + return 0; +} + +static void +hwloc__libxml_import_close_child(hwloc__xml_import_state_t state __hwloc_attribute_unused) +{ + /* nothing to do */ +} + +static int +hwloc__libxml_import_get_content(hwloc__xml_import_state_t state, + char **beginp, size_t expected_length) +{ + hwloc__libxml_import_state_data_t lstate = (void*) state->data; + xmlNode *child; + size_t length; + + child = lstate->node->children; + if (!child) + return 0; + if (child->type != XML_TEXT_NODE) + return 0; + + length = strlen((char *) child->content); + if (length != expected_length) + return -1; + *beginp = (char *) child->content; + return 1; +} + +static void +hwloc__libxml_import_close_content(hwloc__xml_import_state_t state __hwloc_attribute_unused) +{ + /* nothing to do */ +} + +static int +hwloc_libxml_look_init(struct hwloc_xml_backend_data_s *bdata, + struct hwloc__xml_import_state_s *state) +{ + hwloc__libxml_import_state_data_t lstate = (void*) state->data; + xmlNode* root_node; + xmlDtd *dtd; + + assert(sizeof(*lstate) <= sizeof(state->data)); + + dtd = xmlGetIntSubset((xmlDoc*) bdata->data); + if (!dtd) { + if (hwloc__xml_verbose()) + fprintf(stderr, "Loading XML topology without DTD\n"); + } else if (strcmp((char *) dtd->SystemID, "hwloc.dtd")) { + if (hwloc__xml_verbose()) + fprintf(stderr, "Loading XML topology with wrong DTD SystemID (%s instead of %s)\n", + (char *) dtd->SystemID, "hwloc.dtd"); + } + + root_node = xmlDocGetRootElement((xmlDoc*) bdata->data); + + if (strcmp((const char *) root_node->name, "topology") && strcmp((const char *) root_node->name, "root")) { + /* root node should be in "topology" class (or "root" if importing from < 1.0) */ + if (hwloc__xml_verbose()) + fprintf(stderr, "ignoring object of class `%s' not at the top the xml hierarchy\n", (const char *) root_node->name); + goto failed; + } + + state->global->next_attr = hwloc__libxml_import_next_attr; + state->global->find_child = hwloc__libxml_import_find_child; + state->global->close_tag = hwloc__libxml_import_close_tag; + state->global->close_child = hwloc__libxml_import_close_child; + state->global->get_content = hwloc__libxml_import_get_content; + state->global->close_content = hwloc__libxml_import_close_content; + state->parent = NULL; + lstate->node = root_node; + lstate->child = root_node->children; + lstate->attr = NULL; + return 0; /* success */ + + failed: + return -1; /* failed */ +} + +static int +hwloc_libxml_import_diff(struct hwloc__xml_import_state_s *state, const char *xmlpath, const char *xmlbuffer, int xmlbuflen, hwloc_topology_diff_t *firstdiffp, char **refnamep) +{ + hwloc__libxml_import_state_data_t lstate = (void*) state->data; + char *refname = NULL; + xmlDoc *doc = NULL; + xmlNode* root_node; + xmlDtd *dtd; + int ret; + + assert(sizeof(*lstate) <= sizeof(state->data)); + + LIBXML_TEST_VERSION; + hwloc_libxml2_disable_stderrwarnings(); + + errno = 0; /* set to 0 so that we know if libxml2 changed it */ + + if (xmlpath) + doc = xmlReadFile(xmlpath, NULL, 0); + else if (xmlbuffer) + doc = xmlReadMemory(xmlbuffer, xmlbuflen, "", NULL, 0); + + if (!doc) { + if (!errno) + /* libxml2 read the file fine, but it got an error during parsing */ + errno = EINVAL; + goto out; + } + + dtd = xmlGetIntSubset(doc); + if (!dtd) { + if (hwloc__xml_verbose()) + fprintf(stderr, "Loading XML topologydiff without DTD\n"); + } else if (strcmp((char *) dtd->SystemID, "hwloc.dtd")) { + if (hwloc__xml_verbose()) + fprintf(stderr, "Loading XML topologydiff with wrong DTD SystemID (%s instead of %s)\n", + (char *) dtd->SystemID, "hwloc.dtd"); + } + + root_node = xmlDocGetRootElement(doc); + + if (strcmp((const char *) root_node->name, "topologydiff")) { + /* root node should be in "topologydiff" class */ + if (hwloc__xml_verbose()) + fprintf(stderr, "ignoring object of class `%s' not at the top the xml hierarchy\n", (const char *) root_node->name); + goto out_with_doc; + } + + state->global->next_attr = hwloc__libxml_import_next_attr; + state->global->find_child = hwloc__libxml_import_find_child; + state->global->close_tag = hwloc__libxml_import_close_tag; + state->global->close_child = hwloc__libxml_import_close_child; + state->global->get_content = hwloc__libxml_import_get_content; + state->global->close_content = hwloc__libxml_import_close_content; + state->parent = NULL; + lstate->node = root_node; + lstate->child = root_node->children; + lstate->attr = NULL; + + while (1) { + char *attrname, *attrvalue; + if (state->global->next_attr(state, &attrname, &attrvalue) < 0) + break; + if (!strcmp(attrname, "refname")) { + free(refname); + refname = strdup(attrvalue); + } else + goto out_with_doc; + } + + ret = hwloc__xml_import_diff(state, firstdiffp); + if (refnamep && !ret) + *refnamep = refname; + else + free(refname); + + xmlFreeDoc(doc); + return ret; + +out_with_doc: + xmlFreeDoc(doc); +out: + return -1; /* failed */ +} + +/******************** + * Backend routines * + ********************/ + +static void +hwloc_libxml_backend_exit(struct hwloc_xml_backend_data_s *bdata) +{ + xmlFreeDoc((xmlDoc*)bdata->data); +} + +static int +hwloc_libxml_backend_init(struct hwloc_xml_backend_data_s *bdata, + const char *xmlpath, const char *xmlbuffer, int xmlbuflen) +{ + xmlDoc *doc = NULL; + + LIBXML_TEST_VERSION; + hwloc_libxml2_disable_stderrwarnings(); + + errno = 0; /* set to 0 so that we know if libxml2 changed it */ + + if (xmlpath) + doc = xmlReadFile(xmlpath, NULL, 0); + else if (xmlbuffer) + doc = xmlReadMemory(xmlbuffer, xmlbuflen, "", NULL, 0); + + if (!doc) { + if (!errno) + /* libxml2 read the file fine, but it got an error during parsing */ + errno = EINVAL; + return -1; + } + + bdata->look_init = hwloc_libxml_look_init; + bdata->look_failed = NULL; + bdata->backend_exit = hwloc_libxml_backend_exit; + bdata->data = doc; + return 0; +} + +/******************* + * Export routines * + *******************/ + +typedef struct hwloc__libxml_export_state_data_s { + xmlNodePtr current_node; /* current node to output */ +} __hwloc_attribute_may_alias * hwloc__libxml_export_state_data_t; + +static void +hwloc__libxml_export_new_child(hwloc__xml_export_state_t parentstate, + hwloc__xml_export_state_t state, + const char *name) +{ + hwloc__libxml_export_state_data_t lpdata = (void *) parentstate->data; + hwloc__libxml_export_state_data_t ldata = (void *) state->data; + + state->parent = parentstate; + state->new_child = parentstate->new_child; + state->new_prop = parentstate->new_prop; + state->add_content = parentstate->add_content; + state->end_object = parentstate->end_object; + + ldata->current_node = xmlNewChild(lpdata->current_node, NULL, BAD_CAST name, NULL); +} + +static void +hwloc__libxml_export_new_prop(hwloc__xml_export_state_t state, const char *name, const char *value) +{ + hwloc__libxml_export_state_data_t ldata = (void *) state->data; + xmlNewProp(ldata->current_node, BAD_CAST name, BAD_CAST value); +} + +static void +hwloc__libxml_export_end_object(hwloc__xml_export_state_t state __hwloc_attribute_unused, const char *name __hwloc_attribute_unused) +{ + /* nothing to do */ +} + +static void +hwloc__libxml_export_add_content(hwloc__xml_export_state_t state, const char *buffer, size_t length) +{ + hwloc__libxml_export_state_data_t ldata = (void *) state->data; + xmlNodeAddContentLen(ldata->current_node, BAD_CAST buffer, length); +} + +static xmlDocPtr +hwloc__libxml2_prepare_export(hwloc_topology_t topology) +{ + struct hwloc__xml_export_state_s state; + hwloc__libxml_export_state_data_t data = (void *) state.data; + xmlDocPtr doc = NULL; /* document pointer */ + xmlNodePtr root_node = NULL; /* root pointer */ + + assert(sizeof(*data) <= sizeof(state.data)); + + LIBXML_TEST_VERSION; + hwloc_libxml2_disable_stderrwarnings(); + + /* Creates a new document, a node and set it as a root node. */ + doc = xmlNewDoc(BAD_CAST "1.0"); + root_node = xmlNewNode(NULL, BAD_CAST "topology"); + xmlDocSetRootElement(doc, root_node); + + /* Creates a DTD declaration. Isn't mandatory. */ + (void) xmlCreateIntSubset(doc, BAD_CAST "topology", NULL, BAD_CAST "hwloc.dtd"); + + state.new_child = hwloc__libxml_export_new_child; + state.new_prop = hwloc__libxml_export_new_prop; + state.add_content = hwloc__libxml_export_add_content; + state.end_object = hwloc__libxml_export_end_object; + + data->current_node = root_node; + + hwloc__xml_export_object (&state, topology, hwloc_get_root_obj(topology)); + + return doc; +} + +static int +hwloc_libxml_export_file(hwloc_topology_t topology, const char *filename) +{ + xmlDocPtr doc; + int ret; + + errno = 0; /* set to 0 so that we know if libxml2 changed it */ + + doc = hwloc__libxml2_prepare_export(topology); + ret = xmlSaveFormatFileEnc(filename, doc, "UTF-8", 1); + xmlFreeDoc(doc); + + if (ret < 0) { + if (!errno) + /* libxml2 likely got an error before doing I/O */ + errno = EINVAL; + return ret; + } + return 0; +} + +static int +hwloc_libxml_export_buffer(hwloc_topology_t topology, char **xmlbuffer, int *buflen) +{ + xmlDocPtr doc; + + doc = hwloc__libxml2_prepare_export(topology); + xmlDocDumpFormatMemoryEnc(doc, (xmlChar **)xmlbuffer, buflen, "UTF-8", 1); + xmlFreeDoc(doc); + return 0; +} + +static xmlDocPtr +hwloc__libxml2_prepare_export_diff(hwloc_topology_diff_t diff, const char *refname) +{ + struct hwloc__xml_export_state_s state; + hwloc__libxml_export_state_data_t data = (void *) state.data; + xmlDocPtr doc = NULL; /* document pointer */ + xmlNodePtr root_node = NULL; /* root pointer */ + + assert(sizeof(*data) <= sizeof(state.data)); + + LIBXML_TEST_VERSION; + hwloc_libxml2_disable_stderrwarnings(); + + /* Creates a new document, a node and set it as a root node. */ + doc = xmlNewDoc(BAD_CAST "1.0"); + root_node = xmlNewNode(NULL, BAD_CAST "topologydiff"); + if (refname) + xmlNewProp(root_node, BAD_CAST "refname", BAD_CAST refname); + xmlDocSetRootElement(doc, root_node); + + /* Creates a DTD declaration. Isn't mandatory. */ + (void) xmlCreateIntSubset(doc, BAD_CAST "topologydiff", NULL, BAD_CAST "hwloc.dtd"); + + state.new_child = hwloc__libxml_export_new_child; + state.new_prop = hwloc__libxml_export_new_prop; + state.add_content = hwloc__libxml_export_add_content; + state.end_object = hwloc__libxml_export_end_object; + + data->current_node = root_node; + + hwloc__xml_export_diff (&state, diff); + + return doc; +} + +static int +hwloc_libxml_export_diff_file(hwloc_topology_diff_t diff, const char *refname, const char *filename) +{ + xmlDocPtr doc; + int ret; + + errno = 0; /* set to 0 so that we know if libxml2 changed it */ + + doc = hwloc__libxml2_prepare_export_diff(diff, refname); + ret = xmlSaveFormatFileEnc(filename, doc, "UTF-8", 1); + xmlFreeDoc(doc); + + if (ret < 0) { + if (!errno) + /* libxml2 likely got an error before doing I/O */ + errno = EINVAL; + return ret; + } + return 0; +} + +static int +hwloc_libxml_export_diff_buffer(hwloc_topology_diff_t diff, const char *refname, char **xmlbuffer, int *buflen) +{ + xmlDocPtr doc; + + doc = hwloc__libxml2_prepare_export_diff(diff, refname); + xmlDocDumpFormatMemoryEnc(doc, (xmlChar **)xmlbuffer, buflen, "UTF-8", 1); + xmlFreeDoc(doc); + return 0; +} + +static void +hwloc_libxml_free_buffer(void *xmlbuffer) +{ + xmlFree(BAD_CAST xmlbuffer); +} + +/************* + * Callbacks * + *************/ + +static struct hwloc_xml_callbacks hwloc_xml_libxml_callbacks = { + hwloc_libxml_backend_init, + hwloc_libxml_export_file, + hwloc_libxml_export_buffer, + hwloc_libxml_free_buffer, + hwloc_libxml_import_diff, + hwloc_libxml_export_diff_file, + hwloc_libxml_export_diff_buffer +}; + +static struct hwloc_xml_component hwloc_libxml_xml_component = { + NULL, + &hwloc_xml_libxml_callbacks +}; + +static int +hwloc_xml_libxml_component_init(unsigned long flags) +{ + if (flags) + return -1; + if (hwloc_plugin_check_namespace("xml_libxml", "hwloc__xml_verbose") < 0) + return -1; + return 0; +} + +#ifdef HWLOC_INSIDE_PLUGIN +HWLOC_DECLSPEC extern const struct hwloc_component hwloc_xml_libxml_component; +#endif + +const struct hwloc_component hwloc_xml_libxml_component = { + HWLOC_COMPONENT_ABI, + hwloc_xml_libxml_component_init, NULL, + HWLOC_COMPONENT_TYPE_XML, + 0, + &hwloc_libxml_xml_component +}; diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/topology-xml-nolibxml.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-xml-nolibxml.c new file mode 100644 index 0000000000..a93d9d4955 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-xml-nolibxml.c @@ -0,0 +1,850 @@ +/* + * Copyright © 2009 CNRS + * Copyright © 2009-2014 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 +#ifdef HAVE_UNISTD_H +#include +#endif + +/******************* + * Import routines * + *******************/ + +struct hwloc__nolibxml_backend_data_s { + size_t buflen; /* size of both buffer and copy buffers, set during backend_init() */ + char *buffer; /* allocated and filled during backend_init() */ + char *copy; /* allocated during backend_init(), used later during actual parsing */ +}; + +typedef struct hwloc__nolibxml_import_state_data_s { + char *tagbuffer; /* buffer containing the next tag */ + char *attrbuffer; /* buffer containing the next attribute of the current node */ + char *tagname; /* tag name of the current node */ + int closed; /* set if the current node is auto-closing */ +} __hwloc_attribute_may_alias * hwloc__nolibxml_import_state_data_t; + +static char * +hwloc__nolibxml_import_ignore_spaces(char *buffer) +{ + return buffer + strspn(buffer, " \t\n"); +} + +static int +hwloc__nolibxml_import_next_attr(hwloc__xml_import_state_t state, char **namep, char **valuep) +{ + hwloc__nolibxml_import_state_data_t nstate = (void*) state->data; + int namelen; + size_t len, escaped; + char *buffer, *value, *end; + + if (!nstate->attrbuffer) + return -1; + + /* find the beginning of an attribute */ + buffer = hwloc__nolibxml_import_ignore_spaces(nstate->attrbuffer); + namelen = strspn(buffer, "abcdefghijklmnopqrstuvwxyz_"); + if (buffer[namelen] != '=' || buffer[namelen+1] != '\"') + return -1; + buffer[namelen] = '\0'; + *namep = buffer; + + /* find the beginning of its value, and unescape it */ + *valuep = value = buffer+namelen+2; + len = 0; escaped = 0; + while (value[len+escaped] != '\"') { + if (value[len+escaped] == '&') { + if (!strncmp(&value[1+len+escaped], "#10;", 4)) { + escaped += 4; + value[len] = '\n'; + } else if (!strncmp(&value[1+len+escaped], "#13;", 4)) { + escaped += 4; + value[len] = '\r'; + } else if (!strncmp(&value[1+len+escaped], "#9;", 3)) { + escaped += 3; + value[len] = '\t'; + } else if (!strncmp(&value[1+len+escaped], "quot;", 5)) { + escaped += 5; + value[len] = '\"'; + } else if (!strncmp(&value[1+len+escaped], "lt;", 3)) { + escaped += 3; + value[len] = '<'; + } else if (!strncmp(&value[1+len+escaped], "gt;", 3)) { + escaped += 3; + value[len] = '>'; + } else if (!strncmp(&value[1+len+escaped], "amp;", 4)) { + escaped += 4; + value[len] = '&'; + } else { + return -1; + } + } else { + value[len] = value[len+escaped]; + } + len++; + if (value[len+escaped] == '\0') + return -1; + } + value[len] = '\0'; + + /* find next attribute */ + end = &value[len+escaped+1]; /* skip the ending " */ + nstate->attrbuffer = hwloc__nolibxml_import_ignore_spaces(end); + return 0; +} + +static int +hwloc__nolibxml_import_find_child(hwloc__xml_import_state_t state, + hwloc__xml_import_state_t childstate, + char **tagp) +{ + hwloc__nolibxml_import_state_data_t nstate = (void*) state->data; + hwloc__nolibxml_import_state_data_t nchildstate = (void*) childstate->data; + char *buffer = nstate->tagbuffer; + char *end; + int namelen; + + childstate->parent = state; + childstate->global = state->global; + + /* auto-closed tags have no children */ + if (nstate->closed) + return 0; + + /* find the beginning of the tag */ + buffer = hwloc__nolibxml_import_ignore_spaces(buffer); + if (buffer[0] != '<') + return -1; + buffer++; + + /* if closing tag, return nothing and do not advance */ + if (buffer[0] == '/') + return 0; + + /* normal tag */ + *tagp = nchildstate->tagname = buffer; + + /* find the end, mark it and return it */ + end = strchr(buffer, '>'); + if (!end) + return -1; + end[0] = '\0'; + nchildstate->tagbuffer = end+1; + + /* handle auto-closing tags */ + if (end[-1] == '/') { + nchildstate->closed = 1; + end[-1] = '\0'; + } else + nchildstate->closed = 0; + + /* find attributes */ + namelen = strspn(buffer, "abcdefghijklmnopqrstuvwxyz_"); + + if (buffer[namelen] == '\0') { + /* no attributes */ + nchildstate->attrbuffer = NULL; + return 1; + } + + if (buffer[namelen] != ' ') + return -1; + + /* found a space, likely starting attributes */ + buffer[namelen] = '\0'; + nchildstate->attrbuffer = buffer+namelen+1; + return 1; +} + +static int +hwloc__nolibxml_import_close_tag(hwloc__xml_import_state_t state) +{ + hwloc__nolibxml_import_state_data_t nstate = (void*) state->data; + char *buffer = nstate->tagbuffer; + char *end; + + /* auto-closed tags need nothing */ + if (nstate->closed) + return 0; + + /* find the beginning of the tag */ + buffer = hwloc__nolibxml_import_ignore_spaces(buffer); + if (buffer[0] != '<') + return -1; + buffer++; + + /* find the end, mark it and return it to the parent */ + end = strchr(buffer, '>'); + if (!end) + return -1; + end[0] = '\0'; + nstate->tagbuffer = end+1; + + /* if closing tag, return nothing */ + if (buffer[0] != '/' || strcmp(buffer+1, nstate->tagname) ) + return -1; + return 0; +} + +static void +hwloc__nolibxml_import_close_child(hwloc__xml_import_state_t state) +{ + hwloc__nolibxml_import_state_data_t nstate = (void*) state->data; + hwloc__nolibxml_import_state_data_t nparent = (void*) state->parent->data; + nparent->tagbuffer = nstate->tagbuffer; +} + +static int +hwloc__nolibxml_import_get_content(hwloc__xml_import_state_t state, + char **beginp, size_t expected_length) +{ + hwloc__nolibxml_import_state_data_t nstate = (void*) state->data; + char *buffer = nstate->tagbuffer; + size_t length; + char *end; + + /* auto-closed tags have no content */ + if (nstate->closed) + return 0; + + /* find the next tag, where the content ends */ + end = strchr(buffer, '<'); + if (!end) + return -1; + + length = (size_t) (end-buffer); + if (length != expected_length) + return -1; + nstate->tagbuffer = end; + *end = '\0'; /* mark as 0-terminated for now */ + *beginp = buffer; + return 1; +} + +static void +hwloc__nolibxml_import_close_content(hwloc__xml_import_state_t state) +{ + /* put back the '<' that we overwrote to 0-terminate the content */ + hwloc__nolibxml_import_state_data_t nstate = (void*) state->data; + *nstate->tagbuffer = '<'; +} + +static int +hwloc_nolibxml_look_init(struct hwloc_xml_backend_data_s *bdata, + struct hwloc__xml_import_state_s *state) +{ + hwloc__nolibxml_import_state_data_t nstate = (void*) state->data; + struct hwloc__nolibxml_backend_data_s *nbdata = bdata->data; + char *buffer; + + assert(sizeof(*nstate) <= sizeof(state->data)); + + /* use a copy in the temporary buffer, we may modify during parsing */ + buffer = nbdata->copy; + memcpy(buffer, nbdata->buffer, nbdata->buflen); + + /* skip headers */ + while (!strncmp(buffer, "", 10)) + goto failed; + + state->global->next_attr = hwloc__nolibxml_import_next_attr; + state->global->find_child = hwloc__nolibxml_import_find_child; + state->global->close_tag = hwloc__nolibxml_import_close_tag; + state->global->close_child = hwloc__nolibxml_import_close_child; + state->global->get_content = hwloc__nolibxml_import_get_content; + state->global->close_content = hwloc__nolibxml_import_close_content; + state->parent = NULL; + nstate->closed = 0; + nstate->tagbuffer = buffer+10; + nstate->tagname = (char *) "topology"; + nstate->attrbuffer = NULL; + return 0; /* success */ + + failed: + return -1; /* failed */ +} + +static void +hwloc_nolibxml_look_failed(struct hwloc_xml_backend_data_s *bdata __hwloc_attribute_unused) +{ + /* not only when verbose */ + fprintf(stderr, "Failed to parse XML input with the minimalistic parser. If it was not\n" + "generated by hwloc, try enabling full XML support with libxml2.\n"); +} + +/******************** + * Backend routines * + ********************/ + +static void +hwloc_nolibxml_backend_exit(struct hwloc_xml_backend_data_s *bdata) +{ + struct hwloc__nolibxml_backend_data_s *nbdata = bdata->data; + free(nbdata->buffer); + free(nbdata->copy); + free(nbdata); +} + +static int +hwloc_nolibxml_read_file(const char *xmlpath, char **bufferp, size_t *buflenp) +{ + FILE * file; + size_t buflen, offset, readlen; + struct stat statbuf; + char *buffer; + size_t ret; + + if (!strcmp(xmlpath, "-")) + xmlpath = "/dev/stdin"; + + file = fopen(xmlpath, "r"); + if (!file) + goto out; + + /* find the required buffer size for regular files, or use 4k when unknown, we'll realloc later if needed */ + buflen = 4096; + if (!stat(xmlpath, &statbuf)) + if (S_ISREG(statbuf.st_mode)) + buflen = statbuf.st_size+1; /* one additional byte so that the first fread() gets EOF too */ + + buffer = malloc(buflen+1); /* one more byte for the ending \0 */ + if (!buffer) + goto out_with_file; + + offset = 0; readlen = buflen; + while (1) { + ret = fread(buffer+offset, 1, readlen, file); + + offset += ret; + buffer[offset] = 0; + + if (ret != readlen) + break; + + buflen *= 2; + buffer = realloc(buffer, buflen+1); + if (!buffer) + goto out_with_file; + readlen = buflen/2; + } + + fclose(file); + *bufferp = buffer; + *buflenp = offset+1; + return 0; + + out_with_file: + fclose(file); + out: + return -1; +} + +static int +hwloc_nolibxml_backend_init(struct hwloc_xml_backend_data_s *bdata, + const char *xmlpath, const char *xmlbuffer, int xmlbuflen) +{ + struct hwloc__nolibxml_backend_data_s *nbdata = malloc(sizeof(*nbdata)); + + if (!nbdata) + goto out; + bdata->data = nbdata; + + if (xmlbuffer) { + nbdata->buffer = malloc(xmlbuflen); + if (!nbdata->buffer) + goto out_with_nbdata; + nbdata->buflen = xmlbuflen; + memcpy(nbdata->buffer, xmlbuffer, xmlbuflen); + + } else { + int err = hwloc_nolibxml_read_file(xmlpath, &nbdata->buffer, &nbdata->buflen); + if (err < 0) + goto out_with_nbdata; + } + + /* allocate a temporary copy buffer that we may modify during parsing */ + nbdata->copy = malloc(nbdata->buflen); + if (!nbdata->copy) + goto out_with_buffer; + + bdata->look_init = hwloc_nolibxml_look_init; + bdata->look_failed = hwloc_nolibxml_look_failed; + bdata->backend_exit = hwloc_nolibxml_backend_exit; + return 0; + +out_with_buffer: + free(nbdata->buffer); +out_with_nbdata: + free(nbdata); +out: + return -1; +} + +static int +hwloc_nolibxml_import_diff(struct hwloc__xml_import_state_s *state, + const char *xmlpath, const char *xmlbuffer, int xmlbuflen, + hwloc_topology_diff_t *firstdiffp, char **refnamep) +{ + hwloc__nolibxml_import_state_data_t nstate = (void*) state->data; + struct hwloc__xml_import_state_s childstate; + char *refname = NULL; + char *buffer, *tmp, *tag; + size_t buflen; + int ret; + + assert(sizeof(*nstate) <= sizeof(state->data)); + + if (xmlbuffer) { + buffer = malloc(xmlbuflen); + if (!buffer) + goto out; + memcpy(buffer, xmlbuffer, xmlbuflen); + buflen = xmlbuflen; + + } else { + ret = hwloc_nolibxml_read_file(xmlpath, &buffer, &buflen); + if (ret < 0) + goto out; + } + + /* skip headers */ + tmp = buffer; + while (!strncmp(tmp, "global->next_attr = hwloc__nolibxml_import_next_attr; + state->global->find_child = hwloc__nolibxml_import_find_child; + state->global->close_tag = hwloc__nolibxml_import_close_tag; + state->global->close_child = hwloc__nolibxml_import_close_child; + state->global->get_content = hwloc__nolibxml_import_get_content; + state->global->close_content = hwloc__nolibxml_import_close_content; + state->parent = NULL; + nstate->closed = 0; + nstate->tagbuffer = tmp; + nstate->tagname = NULL; + nstate->attrbuffer = NULL; + + /* find root */ + ret = hwloc__nolibxml_import_find_child(state, &childstate, &tag); + if (ret < 0) + goto out_with_buffer; + if (strcmp(tag, "topologydiff")) + goto out_with_buffer; + + while (1) { + char *attrname, *attrvalue; + if (hwloc__nolibxml_import_next_attr(&childstate, &attrname, &attrvalue) < 0) + break; + if (!strcmp(attrname, "refname")) { + free(refname); + refname = strdup(attrvalue); + } else + goto out_with_buffer; + } + + ret = hwloc__xml_import_diff(&childstate, firstdiffp); + if (refnamep && !ret) + *refnamep = refname; + else + free(refname); + + free(buffer); + return ret; + +out_with_buffer: + free(buffer); +out: + return -1; +} + +/******************* + * Export routines * + *******************/ + +typedef struct hwloc__nolibxml_export_state_data_s { + char *buffer; /* (moving) buffer where to write */ + size_t written; /* how many bytes were written (or would have be written if not truncated) */ + size_t remaining; /* how many bytes are still available in the buffer */ + unsigned indent; /* indentation level for the next line */ + unsigned nr_children; + unsigned has_content; +} __hwloc_attribute_may_alias * hwloc__nolibxml_export_state_data_t; + +static void +hwloc__nolibxml_export_update_buffer(hwloc__nolibxml_export_state_data_t ndata, int res) +{ + if (res >= 0) { + ndata->written += res; + if (res >= (int) ndata->remaining) + res = ndata->remaining>0 ? ndata->remaining-1 : 0; + ndata->buffer += res; + ndata->remaining -= res; + } +} + +static char * +hwloc__nolibxml_export_escape_string(const char *src) +{ + int fulllen, sublen; + char *escaped, *dst; + + fulllen = strlen(src); + + sublen = strcspn(src, "\n\r\t\"<>&"); + if (sublen == fulllen) + return NULL; /* nothing to escape */ + + escaped = malloc(fulllen*6+1); /* escaped chars are replaced by at most 6 char */ + dst = escaped; + + memcpy(dst, src, sublen); + src += sublen; + dst += sublen; + + while (*src) { + int replen; + switch (*src) { + case '\n': strcpy(dst, " "); replen=5; break; + case '\r': strcpy(dst, " "); replen=5; break; + case '\t': strcpy(dst, " "); replen=4; break; + case '\"': strcpy(dst, """); replen=6; break; + case '<': strcpy(dst, "<"); replen=4; break; + case '>': strcpy(dst, ">"); replen=4; break; + case '&': strcpy(dst, "&"); replen=5; break; + default: replen=0; break; + } + dst+=replen; src++; + + sublen = strcspn(src, "\n\r\t\"<>&"); + memcpy(dst, src, sublen); + src += sublen; + dst += sublen; + } + + *dst = 0; + return escaped; +} + +static void +hwloc__nolibxml_export_new_child(hwloc__xml_export_state_t parentstate, + hwloc__xml_export_state_t state, + const char *name) +{ + hwloc__nolibxml_export_state_data_t npdata = (void *) parentstate->data; + hwloc__nolibxml_export_state_data_t ndata = (void *) state->data; + int res; + + assert(!npdata->has_content); + if (!npdata->nr_children) { + res = hwloc_snprintf(npdata->buffer, npdata->remaining, ">\n"); + hwloc__nolibxml_export_update_buffer(npdata, res); + } + npdata->nr_children++; + + state->parent = parentstate; + state->new_child = parentstate->new_child; + state->new_prop = parentstate->new_prop; + state->add_content = parentstate->add_content; + state->end_object = parentstate->end_object; + + ndata->buffer = npdata->buffer; + ndata->written = npdata->written; + ndata->remaining = npdata->remaining; + ndata->indent = npdata->indent + 2; + + ndata->nr_children = 0; + ndata->has_content = 0; + + res = hwloc_snprintf(ndata->buffer, ndata->remaining, "%*s<%s", npdata->indent, "", name); + hwloc__nolibxml_export_update_buffer(ndata, res); +} + +static void +hwloc__nolibxml_export_new_prop(hwloc__xml_export_state_t state, const char *name, const char *value) +{ + hwloc__nolibxml_export_state_data_t ndata = (void *) state->data; + char *escaped = hwloc__nolibxml_export_escape_string(value); + int res = hwloc_snprintf(ndata->buffer, ndata->remaining, " %s=\"%s\"", name, escaped ? (const char *) escaped : value); + hwloc__nolibxml_export_update_buffer(ndata, res); + free(escaped); +} + +static void +hwloc__nolibxml_export_end_object(hwloc__xml_export_state_t state, const char *name) +{ + hwloc__nolibxml_export_state_data_t ndata = (void *) state->data; + hwloc__nolibxml_export_state_data_t npdata = (void *) state->parent->data; + int res; + + assert (!(ndata->has_content && ndata->nr_children)); + if (ndata->has_content) { + res = hwloc_snprintf(ndata->buffer, ndata->remaining, "\n", name); + } else if (ndata->nr_children) { + res = hwloc_snprintf(ndata->buffer, ndata->remaining, "%*s\n", npdata->indent, "", name); + } else { + res = hwloc_snprintf(ndata->buffer, ndata->remaining, "/>\n"); + } + hwloc__nolibxml_export_update_buffer(ndata, res); + + npdata->buffer = ndata->buffer; + npdata->written = ndata->written; + npdata->remaining = ndata->remaining; +} + +static void +hwloc__nolibxml_export_add_content(hwloc__xml_export_state_t state, const char *buffer, size_t length) +{ + hwloc__nolibxml_export_state_data_t ndata = (void *) state->data; + int res; + + assert(!ndata->nr_children); + if (!ndata->has_content) { + res = hwloc_snprintf(ndata->buffer, ndata->remaining, ">"); + hwloc__nolibxml_export_update_buffer(ndata, res); + } + ndata->has_content = 1; + + res = hwloc_snprintf(ndata->buffer, ndata->remaining, buffer, length); + hwloc__nolibxml_export_update_buffer(ndata, res); +} + +static size_t +hwloc___nolibxml_prepare_export(hwloc_topology_t topology, char *xmlbuffer, int buflen) +{ + struct hwloc__xml_export_state_s state, childstate; + hwloc__nolibxml_export_state_data_t ndata = (void *) &state.data; + int res; + + assert(sizeof(*ndata) <= sizeof(state.data)); + + state.new_child = hwloc__nolibxml_export_new_child; + state.new_prop = hwloc__nolibxml_export_new_prop; + state.add_content = hwloc__nolibxml_export_add_content; + state.end_object = hwloc__nolibxml_export_end_object; + + ndata->indent = 0; + ndata->written = 0; + ndata->buffer = xmlbuffer; + ndata->remaining = buflen; + + ndata->nr_children = 1; /* don't close a non-existing previous tag when opening the topology tag */ + ndata->has_content = 0; + + res = hwloc_snprintf(ndata->buffer, ndata->remaining, + "\n" + "\n"); + hwloc__nolibxml_export_update_buffer(ndata, res); + hwloc__nolibxml_export_new_child(&state, &childstate, "topology"); + hwloc__xml_export_object (&childstate, topology, hwloc_get_root_obj(topology)); + hwloc__nolibxml_export_end_object(&childstate, "topology"); + + return ndata->written+1; +} + +static int +hwloc_nolibxml_export_buffer(hwloc_topology_t topology, char **bufferp, int *buflenp) +{ + char *buffer; + size_t bufferlen, res; + + bufferlen = 16384; /* random guess for large enough default */ + buffer = malloc(bufferlen); + res = hwloc___nolibxml_prepare_export(topology, buffer, bufferlen); + + if (res > bufferlen) { + buffer = realloc(buffer, res); + hwloc___nolibxml_prepare_export(topology, buffer, res); + } + + *bufferp = buffer; + *buflenp = res; + return 0; +} + +static int +hwloc_nolibxml_export_file(hwloc_topology_t topology, const char *filename) +{ + FILE *file; + char *buffer; + int bufferlen; + int ret; + + ret = hwloc_nolibxml_export_buffer(topology, &buffer, &bufferlen); + if (ret < 0) + return -1; + + if (!strcmp(filename, "-")) { + file = stdout; + } else { + file = fopen(filename, "w"); + if (!file) { + free(buffer); + return -1; + } + } + + ret = fwrite(buffer, 1, bufferlen-1 /* don't write the ending \0 */, file); + if (ret == bufferlen-1) { + ret = 0; + } else { + errno = ferror(file); + ret = -1; + } + + free(buffer); + + if (file != stdout) + fclose(file); + return ret; +} + +static size_t +hwloc___nolibxml_prepare_export_diff(hwloc_topology_diff_t diff, const char *refname, char *xmlbuffer, int buflen) +{ + struct hwloc__xml_export_state_s state, childstate; + hwloc__nolibxml_export_state_data_t ndata = (void *) &state.data; + int res; + + assert(sizeof(*ndata) <= sizeof(state.data)); + + state.new_child = hwloc__nolibxml_export_new_child; + state.new_prop = hwloc__nolibxml_export_new_prop; + state.add_content = hwloc__nolibxml_export_add_content; + state.end_object = hwloc__nolibxml_export_end_object; + + ndata->indent = 0; + ndata->written = 0; + ndata->buffer = xmlbuffer; + ndata->remaining = buflen; + + ndata->nr_children = 1; /* don't close a non-existing previous tag when opening the topology tag */ + ndata->has_content = 0; + + res = hwloc_snprintf(ndata->buffer, ndata->remaining, + "\n" + "\n"); + hwloc__nolibxml_export_update_buffer(ndata, res); + hwloc__nolibxml_export_new_child(&state, &childstate, "topologydiff"); + if (refname) + hwloc__nolibxml_export_new_prop(&childstate, "refname", refname); + hwloc__xml_export_diff (&childstate, diff); + hwloc__nolibxml_export_end_object(&childstate, "topologydiff"); + + return ndata->written+1; +} + +static int +hwloc_nolibxml_export_diff_buffer(hwloc_topology_diff_t diff, const char *refname, char **bufferp, int *buflenp) +{ + char *buffer; + size_t bufferlen, res; + + bufferlen = 16384; /* random guess for large enough default */ + buffer = malloc(bufferlen); + res = hwloc___nolibxml_prepare_export_diff(diff, refname, buffer, bufferlen); + + if (res > bufferlen) { + buffer = realloc(buffer, res); + hwloc___nolibxml_prepare_export_diff(diff, refname, buffer, res); + } + + *bufferp = buffer; + *buflenp = res; + return 0; +} + +static int +hwloc_nolibxml_export_diff_file(hwloc_topology_diff_t diff, const char *refname, const char *filename) +{ + FILE *file; + char *buffer; + int bufferlen; + int ret; + + ret = hwloc_nolibxml_export_diff_buffer(diff, refname, &buffer, &bufferlen); + if (ret < 0) + return -1; + + if (!strcmp(filename, "-")) { + file = stdout; + } else { + file = fopen(filename, "w"); + if (!file) { + free(buffer); + return -1; + } + } + + ret = fwrite(buffer, 1, bufferlen-1 /* don't write the ending \0 */, file); + if (ret == bufferlen-1) { + ret = 0; + } else { + errno = ferror(file); + ret = -1; + } + + free(buffer); + + if (file != stdout) + fclose(file); + return ret; +} + +static void +hwloc_nolibxml_free_buffer(void *xmlbuffer) +{ + free(xmlbuffer); +} + +/************* + * Callbacks * + *************/ + +static struct hwloc_xml_callbacks hwloc_xml_nolibxml_callbacks = { + hwloc_nolibxml_backend_init, + hwloc_nolibxml_export_file, + hwloc_nolibxml_export_buffer, + hwloc_nolibxml_free_buffer, + hwloc_nolibxml_import_diff, + hwloc_nolibxml_export_diff_file, + hwloc_nolibxml_export_diff_buffer +}; + +static struct hwloc_xml_component hwloc_nolibxml_xml_component = { + &hwloc_xml_nolibxml_callbacks, + NULL +}; + +const struct hwloc_component hwloc_xml_nolibxml_component = { + HWLOC_COMPONENT_ABI, + NULL, NULL, + HWLOC_COMPONENT_TYPE_XML, + 0, + &hwloc_nolibxml_xml_component +}; diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/topology-xml.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-xml.c new file mode 100644 index 0000000000..d9e2e46447 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology-xml.c @@ -0,0 +1,1675 @@ +/* + * 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 + +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; +} + +/********************************* + ********* 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; + } + } + + + + + /************************* + * 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; + obj->memory.page_types = realloc(obj->memory.page_types, (idx+1)*sizeof(*obj->memory.page_types)); + 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; + + distances = malloc(sizeof(*distances)); + distances->root = obj; + distances->distances.relative_depth = reldepth; + distances->distances.nbobjs = nbobjs; + distances->distances.latency = matrix = malloc(nbobjs*nbobjs*sizeof(float)); + 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 (data->last_distances) + data->last_distances->next = distances; + else + data->first_distances = distances; + distances->prev = data->last_distances; + distances->next = NULL; + } + + 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 */ + + 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 (length && topology->userdata_import_cb) { + int ret; + + if (encoded) { + char *encoded_buffer; + size_t encoded_length = 4*((length+2)/3); + 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) + return -1; + topology->userdata_import_cb(topology, obj, name, decoded_buffer, length); + free(decoded_buffer); + } + } else { + char *buffer; + 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; + } else { + /* type needed first */ + if (obj->type == (hwloc_obj_type_t)-1) + goto error; + hwloc__xml_import_object_attr(topology, obj, attrname, attrvalue, state); + } + } + + 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: + hwloc_free_unlinked_object(obj); + 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 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, *next = data->first_distances; + + if (!next) + return 0; + + /* 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) + return -1; + + while ((xmldist = next) != NULL) { + hwloc_obj_t root = xmldist->root; + unsigned depth = root->depth + xmldist->distances.relative_depth; + unsigned nbobjs = hwloc_get_nbobjs_inside_cpuset_by_depth(topology, root->cpuset, depth); + if (nbobjs != xmldist->distances.nbobjs) { + /* distances invalid, drop */ + if (hwloc__xml_verbose()) + fprintf(stderr, "%s: ignoring invalid distance matrix with %u objs instead of %u\n", + msgprefix, xmldist->distances.nbobjs, nbobjs); + free(xmldist->distances.latency); + } else { + /* distances valid, add it to the internal OS distances list for grouping */ + unsigned *indexes = malloc(nbobjs * sizeof(unsigned)); + hwloc_obj_t child, *objs = malloc(nbobjs * sizeof(hwloc_obj_t)); + unsigned j; + for(j=0, child = hwloc_get_next_obj_inside_cpuset_by_depth(topology, root->cpuset, depth, NULL); + jcpuset, depth, child)) { + indexes[j] = child->os_index; + objs[j] = child; + } + 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 */); + } + + next = xmldist->next; + 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_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) { + 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 = "xmldiffbuffer"; + + if (!hwloc_libxml_callbacks && !hwloc_nolibxml_callbacks) { + 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(); + 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"); + 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 __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; + + if ((name && hwloc__xml_export_check_buffer(name, strlen(name)) < 0) + || hwloc__xml_export_check_buffer(buffer, length) < 0) { + errno = EINVAL; + return -1; + } + + 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 (name && hwloc__xml_export_check_buffer(name, strlen(name)) < 0) { + errno = EINVAL; + return -1; + } + + encoded_length = 4*((length+2)/3); + 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/hwloc1110/hwloc/src/topology.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology.c new file mode 100644 index 0000000000..8d129d0705 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology.c @@ -0,0 +1,3236 @@ +/* + * Copyright © 2009 CNRS + * Copyright © 2009-2015 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 + +#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. */ +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; +#elif defined(HWLOC_WIN_SYS) + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + n = sysinfo.dwNumberOfProcessors; +#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; +} + +/* + * 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) + +/* Free an object and all its content. */ +void +hwloc_free_unlinked_object(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(obj); +} + +/* 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; + + 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_clear(new); + hwloc_distances_destroy(new); + hwloc_topology_setup_defaults(new); + return -1; +} + +/* + * How to compare objects based on types. + * + * Note that HIGHER/LOWER is only a (consistent) heuristic, used to sort + * objects with same cpuset consistently. + * Only EQUAL / not EQUAL can be relied upon. + */ + +enum hwloc_type_cmp_e { + HWLOC_TYPE_HIGHER, + HWLOC_TYPE_DEEPER, + HWLOC_TYPE_EQUAL +}; + +/* 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; +} + +static enum hwloc_type_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_TYPE_EQUAL; /* we cannot do better */ + if (compare > 0) + return HWLOC_TYPE_DEEPER; + if (compare < 0) + return HWLOC_TYPE_HIGHER; + + /* 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_TYPE_DEEPER; + else if (obj1->attr->cache.depth > obj2->attr->cache.depth) + return HWLOC_TYPE_HIGHER; + else if (obj1->attr->cache.type > obj2->attr->cache.type) + /* consider icache deeper than dcache and dcache deeper than unified */ + return HWLOC_TYPE_DEEPER; + else if (obj1->attr->cache.type < obj2->attr->cache.type) + /* consider icache deeper than dcache and dcache deeper than unified */ + return HWLOC_TYPE_HIGHER; + } + + /* 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_TYPE_EQUAL; + if (obj1->attr->group.depth < obj2->attr->group.depth) + return HWLOC_TYPE_DEEPER; + else if (obj1->attr->group.depth > obj2->attr->group.depth) + return HWLOC_TYPE_HIGHER; + } + + /* 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_TYPE_DEEPER; + else if (obj1->attr->bridge.depth > obj2->attr->bridge.depth) + return HWLOC_TYPE_HIGHER; + } + + return HWLOC_TYPE_EQUAL; +} + +/* + * How to compare objects based on cpusets. + */ + +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 int +hwloc_obj_cmp_sets(hwloc_obj_t obj1, hwloc_obj_t obj2) +{ + hwloc_bitmap_t set1, set2; + + /* compare cpusets if possible, or fallback to nodeset, or return */ + if (obj1->cpuset && !hwloc_bitmap_iszero(obj1->cpuset) + && obj2->cpuset && !hwloc_bitmap_iszero(obj2->cpuset)) { + set1 = obj1->cpuset; + set2 = obj2->cpuset; + } else if (obj1->nodeset && !hwloc_bitmap_iszero(obj1->nodeset) + && obj2->nodeset && !hwloc_bitmap_iszero(obj2->nodeset)) { + set1 = obj1->nodeset; + set2 = obj2->nodeset; + } else { + return HWLOC_OBJ_DIFFERENT; + } + + return hwloc_bitmap_compare_inclusion(set1, set2); +} + +static int +hwloc_obj_cmp_types(hwloc_obj_t obj1, hwloc_obj_t obj2) +{ + /* Same sets, subsort by type to have a consistent ordering. */ + int typeres = hwloc_type_cmp(obj1, obj2); + if (typeres == HWLOC_TYPE_DEEPER) + return HWLOC_OBJ_INCLUDED; + if (typeres == HWLOC_TYPE_HIGHER) + return HWLOC_OBJ_CONTAINS; + + /* HWLOC_TYPE_EQUAL */ + + if (obj1->type == HWLOC_OBJ_MISC) { + /* Misc objects may vary by name */ + int res = strcmp(obj1->name, obj2->name); + if (res < 0) + return HWLOC_OBJ_INCLUDED; + if (res > 0) + return HWLOC_OBJ_CONTAINS; + if (res == 0) + return HWLOC_OBJ_EQUAL; + } + /* Same sets and types! Let's hope it's coherent. */ + return HWLOC_OBJ_EQUAL; +} + +/* 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) { + old->distances_count += new->distances_count; + old->distances = realloc(old->distances, old->distances_count * sizeof(*old->distances)); + 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) { + if (old->name) + free(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: + /* Do not check these, it may change between calls */ + merge_sizes(new, old, memory.local_memory); + merge_sizes(new, old, memory.total_memory); + /* if both newects have a page_types array, just keep the biggest one for now */ + if (new->memory.page_types_len && old->memory.page_types_len) + hwloc_debug("%s", "merging page_types by keeping the biggest one only\n"); + if (new->memory.page_types_len < old->memory.page_types_len) { + free(new->memory.page_types); + } else { + 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; + } + 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) { + /* Group are ignored keep_structure. ignored always are handled earlier. Non-ignored Groups isn't possible. */ + assert(topology->ignored_types[HWLOC_OBJ_GROUP] == HWLOC_IGNORE_TYPE_KEEP_STRUCTURE); + /* Remove the Group now. The normal ignore code path wouldn't tell us whether the Group was removed or not. + * + * Keep EQUAL so that the Group gets merged. + */ + } else { + /* otherwise compare actual types to decide of the inclusion */ + res = hwloc_obj_cmp_types(obj, child); + } + } + + 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; + } + /* Can be two objects with same type. Or one Group and anything else. */ + 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. */ +HWLOC_DECLSPEC 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 != 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 + */ +static int +find_same_type(hwloc_obj_t root, hwloc_obj_t obj) +{ + hwloc_obj_t child; + + if (hwloc_type_cmp(root, obj) == HWLOC_TYPE_EQUAL) + return 1; + + for (child = root->first_child; child; child = child->next_sibling) + if (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_TYPE_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; + + /* 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_TYPE_MAX; 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; + topology->type_depth[HWLOC_OBJ_BRIDGE] = HWLOC_TYPE_DEPTH_BRIDGE; + free(topology->pcidev_level); + topology->pcidev_level = NULL; + topology->pcidev_nbobjects = 0; + topology->first_pcidev = topology->last_pcidev = NULL; + topology->type_depth[HWLOC_OBJ_PCI_DEVICE] = HWLOC_TYPE_DEPTH_PCI_DEVICE; + free(topology->osdev_level); + topology->osdev_level = NULL; + topology->osdev_nbobjects = 0; + topology->first_osdev = topology->last_osdev = NULL; + topology->type_depth[HWLOC_OBJ_OS_DEVICE] = HWLOC_TYPE_DEPTH_OS_DEVICE; + + /* 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_TYPE_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_TYPE_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) +{ + obj->cpuset = hwloc_bitmap_alloc_full(); + obj->complete_cpuset = hwloc_bitmap_alloc(); + obj->online_cpuset = hwloc_bitmap_alloc_full(); + obj->allowed_cpuset = hwloc_bitmap_alloc_full(); + obj->nodeset = hwloc_bitmap_alloc(); + obj->complete_nodeset = hwloc_bitmap_alloc(); + 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); + + 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", VERSION); + /* add a ProcessName */ + value = hwloc_progname(topology); + if (value) { + hwloc_obj_add_info(topology->levels[0][0], "ProcessName", value); + free(value); + } + } + + /* + * Now set binding hooks according to topology->is_thissystem + * what the native OS backend offers. + */ + hwloc_set_binding_hooks(topology); + + 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; + + /* 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; + + /* 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; + + /* 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; + } + + /* 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); + + /* 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; + + /* 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_TYPE_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(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(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/hwloc1110/hwloc/src/traversal.c b/opal/mca/hwloc/hwloc1110/hwloc/src/traversal.c new file mode 100644 index 0000000000..97b3e5b3b8 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/traversal.c @@ -0,0 +1,700 @@ +/* + * Copyright © 2009 CNRS + * Copyright © 2009-2015 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")) 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; + + /* 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", 1) + || !hwloc_strncasecmp(string, "numa", 1)) { /* 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", 2)) { + type = HWLOC_OBJ_MISC; + } else if (!hwloc_strncasecmp(string, "bridge", 2)) { + type = HWLOC_OBJ_BRIDGE; + } else if (!hwloc_strncasecmp(string, "pci", 2)) { + type = HWLOC_OBJ_PCI_DEVICE; + } else if (!hwloc_strncasecmp(string, "os", 2)) { + 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)) { + int 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"; + } + 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 "Fiber"; + 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: + *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 ? 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 ? 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 ? 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/hwloc1110/hwloc/tests/README.txt b/opal/mca/hwloc/hwloc1110/hwloc/tests/README.txt new file mode 100644 index 0000000000..2a72583279 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/tests/README.txt @@ -0,0 +1,4 @@ +Open MPI doesn't need this tree from hwloc. But automake *requires* +that this directory has to be here. So we have an empty directory +with a README in it, a) just to explain why it's here, and b) so that +hg clones won't delete the directory (because it's empty). diff --git a/opal/mca/hwloc/hwloc1110/hwloc/utils/README.txt b/opal/mca/hwloc/hwloc1110/hwloc/utils/README.txt new file mode 100644 index 0000000000..2a72583279 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc/utils/README.txt @@ -0,0 +1,4 @@ +Open MPI doesn't need this tree from hwloc. But automake *requires* +that this directory has to be here. So we have an empty directory +with a README in it, a) just to explain why it's here, and b) so that +hg clones won't delete the directory (because it's empty). diff --git a/opal/mca/hwloc/hwloc1110/hwloc1110.h b/opal/mca/hwloc/hwloc1110/hwloc1110.h new file mode 100644 index 0000000000..35215b4557 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc1110.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2011-2013 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2014-2015 Intel, Inc. All rights reserved. + * + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + * + * When this component is used, this file is included in the rest of + * the OPAL/ORTE/OMPI code base via opal/mca/hwloc/hwloc.h. As such, + * this header represents the public interface to this static component. + */ + +#ifndef MCA_OPAL_HWLOC_HWLOC1110_H +#define MCA_OPAL_HWLOC_HWLOC1110_H + +BEGIN_C_DECLS + +#include "hwloc/include/hwloc.h" + +/* If the including file requested it, also include the hwloc verbs + helper file. We can't just always include this file (even if we + know we have ) because there are some inline + functions in that file that invoke ibv_* functions. Some linkers + (e.g., Solaris Studio Compilers) will instantiate those static + inline functions even if we don't use them, and therefore we need + to be able to resolve the ibv_* symbols at link time. + + Since -libverbs is only specified in places where we use other + ibv_* functions (e.g., the OpenFabrics-based BTLs), that means that + linking random executables can/will fail (e.g., orterun). + */ +#if defined(OPAL_HWLOC_WANT_VERBS_HELPER) && OPAL_HWLOC_WANT_VERBS_HELPER +# if defined(HAVE_INFINIBAND_VERBS_H) +# include "hwloc/include/hwloc/openfabrics-verbs.h" +# else +# error Tried to include hwloc verbs helper file, but hwloc was compiled with no OpenFabrics support +# endif +#endif + +END_C_DECLS + +#endif /* MCA_OPAL_HWLOC_HWLOC1110_H */ diff --git a/opal/mca/hwloc/hwloc1110/hwloc1110_component.c b/opal/mca/hwloc/hwloc1110/hwloc1110_component.c new file mode 100644 index 0000000000..02322fca4b --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/hwloc1110_component.c @@ -0,0 +1,55 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ +/* + * Copyright (c) 2011-2013 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2014-2015 Intel, Inc. All rights reserved. + * Copyright (c) 2015 Los Alamos National Security, LLC. All rights + * reserved. + * + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + * + * These symbols are in a file by themselves to provide nice linker + * semantics. Since linkers generally pull in symbols by object + * files, keeping these symbols as the only symbols in this file + * prevents utility programs such as "ompi_info" from having to import + * entire components just to query their version and parameters. + */ + +#include "opal_config.h" +#include "opal/constants.h" + +#include "opal/mca/hwloc/hwloc.h" +#include "hwloc1110.h" + +/* + * Public string showing the sysinfo ompi_linux component version number + */ +const char *opal_hwloc_hwloc1110_component_version_string = + "OPAL hwloc1110 hwloc MCA component version " OPAL_VERSION; + +/* + * Instantiate the public struct with all of our public information + * and pointers to our public functions in it + */ + +const opal_hwloc_component_t mca_hwloc_hwloc1110_component = { + + /* First, the mca_component_t struct containing meta information + about the component itself */ + + .base_version = { + OPAL_HWLOC_BASE_VERSION_2_0_0, + + /* Component name and version */ + .mca_component_name = "hwloc1110", + MCA_BASE_MAKE_VERSION(component, OPAL_MAJOR_VERSION, OPAL_MINOR_VERSION, + OPAL_RELEASE_VERSION), + }, + .base_data = { + /* The component is checkpoint ready */ + MCA_BASE_METADATA_PARAM_CHECKPOINT + } +}; diff --git a/opal/mca/hwloc/hwloc1110/owner.txt b/opal/mca/hwloc/hwloc1110/owner.txt new file mode 100644 index 0000000000..d72196b959 --- /dev/null +++ b/opal/mca/hwloc/hwloc1110/owner.txt @@ -0,0 +1,7 @@ +# +# owner/status file +# owner: institution that is responsible for this package +# status: e.g. active, maintenance, unmaintained +# +owner:INTEL +status: maintenance diff --git a/opal/mca/hwloc/hwloc191/configure.m4 b/opal/mca/hwloc/hwloc191/configure.m4 index abe75fc59f..d66e68dadb 100644 --- a/opal/mca/hwloc/hwloc191/configure.m4 +++ b/opal/mca/hwloc/hwloc191/configure.m4 @@ -13,7 +13,7 @@ # # Priority # -AC_DEFUN([MCA_opal_hwloc_hwloc191_PRIORITY], [90]) +AC_DEFUN([MCA_opal_hwloc_hwloc191_PRIORITY], [10]) # # Force this component to compile in static-only mode From ff92781ec4db19ab5dcc7db90cfb1866926efae8 Mon Sep 17 00:00:00 2001 From: Ralph Castain Date: Sat, 13 Jun 2015 08:35:09 -0700 Subject: [PATCH 2/2] Replace hwloc191 with hwloc1110 Fix hwloc compile. Ignore LAMA mapper due to deprecated hwloc functions --- opal/mca/hwloc/hwloc1110/hwloc/NEWS | 2 + opal/mca/hwloc/hwloc1110/hwloc/README | 624 +- opal/mca/hwloc/hwloc1110/hwloc/VERSION | 8 +- .../mca/hwloc/hwloc1110/hwloc/config/hwloc.m4 | 6 +- .../hwloc1110/hwloc/include/hwloc/cuda.h | 4 +- .../hwloc1110/hwloc/include/hwloc/cudart.h | 5 +- opal/mca/hwloc/hwloc1110/hwloc/src/topology.c | 2 +- opal/mca/hwloc/hwloc191/Makefile.am | 83 - opal/mca/hwloc/hwloc191/README-ompi.txt | 35 - opal/mca/hwloc/hwloc191/configure.m4 | 170 - opal/mca/hwloc/hwloc191/hwloc/AUTHORS | 8 - opal/mca/hwloc/hwloc191/hwloc/COPYING | 28 - opal/mca/hwloc/hwloc191/hwloc/Makefile.am | 75 - opal/mca/hwloc/hwloc191/hwloc/NEWS | 1002 - opal/mca/hwloc/hwloc191/hwloc/README | 720 - opal/mca/hwloc/hwloc191/hwloc/VERSION | 42 - opal/mca/hwloc/hwloc191/hwloc/aclocal.m4 | 1221 - opal/mca/hwloc/hwloc191/hwloc/config/ar-lib | 270 - opal/mca/hwloc/hwloc191/hwloc/config/compile | 347 - .../hwloc/hwloc191/hwloc/config/config.guess | 1568 - .../hwloc/hwloc191/hwloc/config/config.sub | 1793 - opal/mca/hwloc/hwloc191/hwloc/config/depcomp | 791 - .../hwloc/hwloc191/hwloc/config/distscript.sh | 130 - opal/mca/hwloc/hwloc191/hwloc/config/hwloc.m4 | 1399 - .../hwloc/config/hwloc_check_attributes.m4 | 533 - .../hwloc/config/hwloc_check_vendor.m4 | 239 - .../hwloc/config/hwloc_check_visibility.m4 | 131 - .../hwloc191/hwloc/config/hwloc_components.m4 | 66 - .../hwloc/config/hwloc_get_version.sh | 99 - .../hwloc191/hwloc/config/hwloc_internal.m4 | 425 - .../hwloc/hwloc191/hwloc/config/hwloc_pkg.m4 | 197 - .../hwloc/hwloc191/hwloc/config/install-sh | 527 - .../hwloc/hwloc191/hwloc/config/libtool.m4 | 7982 ---- .../mca/hwloc/hwloc191/hwloc/config/ltmain.sh | 9655 ----- .../hwloc/hwloc191/hwloc/config/ltoptions.m4 | 384 - .../hwloc/hwloc191/hwloc/config/ltsugar.m4 | 123 - .../hwloc/hwloc191/hwloc/config/ltversion.m4 | 23 - .../hwloc191/hwloc/config/lt~obsolete.m4 | 98 - opal/mca/hwloc/hwloc191/hwloc/config/missing | 215 - .../hwloc/hwloc191/hwloc/config/test-driver | 139 - opal/mca/hwloc/hwloc191/hwloc/configure | 31402 ---------------- opal/mca/hwloc/hwloc191/hwloc/configure.ac | 250 - .../hwloc/contrib/hwloc-valgrind.supp | 145 - opal/mca/hwloc/hwloc191/hwloc/doc/README.txt | 4 - opal/mca/hwloc/hwloc191/hwloc/hwloc.pc.in | 12 - .../hwloc/hwloc191/hwloc/include/Makefile.am | 55 - opal/mca/hwloc/hwloc191/hwloc/include/hwloc.h | 2290 -- .../hwloc/include/hwloc/autogen/config.h.in | 188 - .../hwloc191/hwloc/include/hwloc/bitmap.h | 350 - .../hwloc/hwloc191/hwloc/include/hwloc/cuda.h | 224 - .../hwloc191/hwloc/include/hwloc/cudart.h | 183 - .../hwloc191/hwloc/include/hwloc/deprecated.h | 93 - .../hwloc/hwloc191/hwloc/include/hwloc/diff.h | 299 - .../hwloc/hwloc191/hwloc/include/hwloc/gl.h | 135 - .../hwloc/include/hwloc/glibc-sched.h | 125 - .../hwloc191/hwloc/include/hwloc/helper.h | 1249 - .../hwloc191/hwloc/include/hwloc/inlines.h | 154 - .../hwloc191/hwloc/include/hwloc/intel-mic.h | 143 - .../hwloc/include/hwloc/linux-libnuma.h | 355 - .../hwloc191/hwloc/include/hwloc/linux.h | 77 - .../hwloc/include/hwloc/myriexpress.h | 127 - .../hwloc/hwloc191/hwloc/include/hwloc/nvml.h | 176 - .../hwloc191/hwloc/include/hwloc/opencl.h | 199 - .../hwloc/include/hwloc/openfabrics-verbs.h | 155 - .../hwloc191/hwloc/include/hwloc/plugins.h | 394 - .../hwloc191/hwloc/include/hwloc/rename.h | 636 - .../hwloc/include/private/autogen/config.h.in | 683 - .../hwloc/include/private/components.h | 40 - .../hwloc/include/private/cpuid-x86.h | 89 - .../hwloc191/hwloc/include/private/debug.h | 57 - .../hwloc191/hwloc/include/private/misc.h | 383 - .../hwloc191/hwloc/include/private/private.h | 308 - .../hwloc/include/private/solaris-chiptype.h | 59 - .../hwloc191/hwloc/include/private/xml.h | 86 - opal/mca/hwloc/hwloc191/hwloc/src/Makefile.am | 235 - opal/mca/hwloc/hwloc191/hwloc/src/base64.c | 306 - opal/mca/hwloc/hwloc191/hwloc/src/bind.c | 781 - opal/mca/hwloc/hwloc191/hwloc/src/bitmap.c | 1163 - .../mca/hwloc/hwloc191/hwloc/src/components.c | 746 - opal/mca/hwloc/hwloc191/hwloc/src/diff.c | 405 - opal/mca/hwloc/hwloc191/hwloc/src/distances.c | 1046 - opal/mca/hwloc/hwloc191/hwloc/src/dolib.c | 47 - opal/mca/hwloc/hwloc191/hwloc/src/hwloc.dtd | 71 - opal/mca/hwloc/hwloc191/hwloc/src/misc.c | 117 - .../mca/hwloc/hwloc191/hwloc/src/pci-common.c | 452 - .../hwloc/hwloc191/hwloc/src/topology-aix.c | 871 - .../hwloc/hwloc191/hwloc/src/topology-bgq.c | 240 - .../hwloc/hwloc191/hwloc/src/topology-cuda.c | 238 - .../hwloc191/hwloc/src/topology-custom.c | 99 - .../hwloc191/hwloc/src/topology-darwin.c | 306 - .../hwloc/hwloc191/hwloc/src/topology-fake.c | 41 - .../hwloc191/hwloc/src/topology-freebsd.c | 250 - .../hwloc/hwloc191/hwloc/src/topology-gl.c | 263 - .../hwloc/hwloc191/hwloc/src/topology-hpux.c | 310 - .../hwloc/hwloc191/hwloc/src/topology-linux.c | 4860 --- .../hwloc191/hwloc/src/topology-netbsd.c | 197 - .../hwloc/hwloc191/hwloc/src/topology-noos.c | 57 - .../hwloc/hwloc191/hwloc/src/topology-nvml.c | 232 - .../hwloc191/hwloc/src/topology-opencl.c | 338 - .../hwloc/hwloc191/hwloc/src/topology-osf.c | 391 - .../hwloc/hwloc191/hwloc/src/topology-pci.c | 419 - .../hwloc/src/topology-solaris-chiptype.c | 339 - .../hwloc191/hwloc/src/topology-solaris.c | 803 - .../hwloc191/hwloc/src/topology-synthetic.c | 446 - .../hwloc191/hwloc/src/topology-windows.c | 812 - .../hwloc/hwloc191/hwloc/src/topology-x86.c | 1002 - .../hwloc191/hwloc/src/topology-xml-libxml.c | 568 - .../hwloc/src/topology-xml-nolibxml.c | 853 - .../hwloc/hwloc191/hwloc/src/topology-xml.c | 1529 - opal/mca/hwloc/hwloc191/hwloc/src/topology.c | 3227 -- opal/mca/hwloc/hwloc191/hwloc/src/traversal.c | 691 - .../mca/hwloc/hwloc191/hwloc/tests/README.txt | 4 - .../mca/hwloc/hwloc191/hwloc/utils/README.txt | 4 - opal/mca/hwloc/hwloc191/hwloc191.h | 45 - opal/mca/hwloc/hwloc191/hwloc191_component.c | 55 - opal/mca/hwloc/hwloc191/owner.txt | 7 - orte/mca/rmaps/lama/.opal_ignore | 0 117 files changed, 244 insertions(+), 96916 deletions(-) delete mode 100644 opal/mca/hwloc/hwloc191/Makefile.am delete mode 100644 opal/mca/hwloc/hwloc191/README-ompi.txt delete mode 100644 opal/mca/hwloc/hwloc191/configure.m4 delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/AUTHORS delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/COPYING delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/Makefile.am delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/NEWS delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/README delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/VERSION delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/aclocal.m4 delete mode 100755 opal/mca/hwloc/hwloc191/hwloc/config/ar-lib delete mode 100755 opal/mca/hwloc/hwloc191/hwloc/config/compile delete mode 100755 opal/mca/hwloc/hwloc191/hwloc/config/config.guess delete mode 100755 opal/mca/hwloc/hwloc191/hwloc/config/config.sub delete mode 100755 opal/mca/hwloc/hwloc191/hwloc/config/depcomp delete mode 100755 opal/mca/hwloc/hwloc191/hwloc/config/distscript.sh delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/config/hwloc.m4 delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/config/hwloc_check_attributes.m4 delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/config/hwloc_check_vendor.m4 delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/config/hwloc_check_visibility.m4 delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/config/hwloc_components.m4 delete mode 100755 opal/mca/hwloc/hwloc191/hwloc/config/hwloc_get_version.sh delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/config/hwloc_internal.m4 delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/config/hwloc_pkg.m4 delete mode 100755 opal/mca/hwloc/hwloc191/hwloc/config/install-sh delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/config/libtool.m4 delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/config/ltmain.sh delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/config/ltoptions.m4 delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/config/ltsugar.m4 delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/config/ltversion.m4 delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/config/lt~obsolete.m4 delete mode 100755 opal/mca/hwloc/hwloc191/hwloc/config/missing delete mode 100755 opal/mca/hwloc/hwloc191/hwloc/config/test-driver delete mode 100755 opal/mca/hwloc/hwloc191/hwloc/configure delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/configure.ac delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/contrib/hwloc-valgrind.supp delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/doc/README.txt delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/hwloc.pc.in delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/Makefile.am delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/hwloc.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/hwloc/autogen/config.h.in delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/hwloc/bitmap.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/hwloc/cuda.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/hwloc/cudart.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/hwloc/deprecated.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/hwloc/diff.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/hwloc/gl.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/hwloc/glibc-sched.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/hwloc/helper.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/hwloc/inlines.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/hwloc/intel-mic.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/hwloc/linux-libnuma.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/hwloc/linux.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/hwloc/myriexpress.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/hwloc/nvml.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/hwloc/opencl.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/hwloc/openfabrics-verbs.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/hwloc/plugins.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/hwloc/rename.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/private/autogen/config.h.in delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/private/components.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/private/cpuid-x86.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/private/debug.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/private/misc.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/private/private.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/private/solaris-chiptype.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/include/private/xml.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/Makefile.am delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/base64.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/bind.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/bitmap.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/components.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/diff.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/distances.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/dolib.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/hwloc.dtd delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/misc.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/pci-common.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology-aix.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology-bgq.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology-cuda.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology-custom.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology-darwin.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology-fake.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology-freebsd.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology-gl.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology-hpux.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology-linux.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology-netbsd.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology-noos.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology-nvml.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology-opencl.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology-osf.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology-pci.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology-solaris-chiptype.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology-solaris.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology-synthetic.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology-windows.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology-x86.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology-xml-libxml.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology-xml-nolibxml.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology-xml.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/topology.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/src/traversal.c delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/tests/README.txt delete mode 100644 opal/mca/hwloc/hwloc191/hwloc/utils/README.txt delete mode 100644 opal/mca/hwloc/hwloc191/hwloc191.h delete mode 100644 opal/mca/hwloc/hwloc191/hwloc191_component.c delete mode 100644 opal/mca/hwloc/hwloc191/owner.txt create mode 100644 orte/mca/rmaps/lama/.opal_ignore diff --git a/opal/mca/hwloc/hwloc1110/hwloc/NEWS b/opal/mca/hwloc/hwloc1110/hwloc/NEWS index 01df3258ae..91f8c654f4 100644 --- a/opal/mca/hwloc/hwloc1110/hwloc/NEWS +++ b/opal/mca/hwloc/hwloc1110/hwloc/NEWS @@ -71,6 +71,8 @@ Version 1.11.0 - Do not drop instruction caches and I/O devices from the output anymore. + Fix lstopo path in hwloc-gather-topology after install. * Misc + + Fix hwloc/cudart.h for machines with multiple PCI domains, + thanks to Imre Kerr for reporting the problem. + Fix PCI Bridge-specific depth attribute. + Fix hwloc_bitmap_intersect() for two infinite bitmaps. + Improve the performance of object insertion by cpuset for large diff --git a/opal/mca/hwloc/hwloc1110/hwloc/README b/opal/mca/hwloc/hwloc1110/hwloc/README index fed93191f9..9c3ae62d28 100644 --- a/opal/mca/hwloc/hwloc1110/hwloc/README +++ b/opal/mca/hwloc/hwloc1110/hwloc/README @@ -1,33 +1,34 @@ 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 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 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. -Note that the hwloc project represents the merger of the libtopology project -from inria and the Portable Linux Processor Affinity (PLPA) sub-project from -Open MPI. Both of these prior projects are now deprecated. The first hwloc -release was essentially a "re-branding" of the libtopology code base, but with -both a few genuinely new features and a few PLPA-like features added in. Prior -releases of hwloc included documentation about switching from PLPA to hwloc; -this documentation has been dropped on the assumption that everyone who was -using PLPA has already switched to hwloc. +Note that the hwloc project represents the merger of the libtopology +project from inria and the Portable Linux Processor Affinity (PLPA) +sub-project from Open MPI. Both of these prior projects are now +deprecated. The first hwloc release was essentially a "re-branding" of +the libtopology code base, but with both a few genuinely new features +and a few PLPA-like features added in. Prior releases of hwloc included +documentation about switching from PLPA to hwloc; this documentation +has been dropped on the assumption that everyone who was using PLPA has +already switched to hwloc. hwloc supports the following operating systems: - - * Linux (including old kernels not having sysfs topology information, with - knowledge of cpusets, offline CPUs, ScaleMP vSMP, NumaScale NumaConnect, - and Kerrighed support) on all supported hardware, including Intel Xeon Phi - (either standalone or as a coprocessor). + * Linux (including old kernels not having sysfs topology information, + with knowledge of cpusets, offline CPUs, ScaleMP vSMP, NumaScale + NumaConnect, and Kerrighed support) on all supported hardware, + including Intel Xeon Phi (either standalone or as a coprocessor). * Solaris * AIX * Darwin / OS X @@ -38,126 +39,127 @@ hwloc supports the following operating systems: * 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). +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. +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. +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: +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 + * Remote machine simulation through the gathering of Linux sysfs + topology files - * Symmetrical tree of resources generated from a list of level arities - * Remote machine simulation through the gathering of Linux sysfs topology - 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 CLI Examples +below). Note that some of the export formats require additional support +libraries. -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 CLI 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. +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). 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: +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.10 and Libtool >=2.2.6 are required -when building from a Git clone. +Note that GNU Autoconf >=2.63, Automake >=1.10 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 -The hwloc command-line tool "lstopo" produces human-readable topology maps, as -mentioned above. It can also export maps to the "fig" file format. Support for -PDF, Postscript, and PNG exporting is provided if the "Cairo" development -package (usually cairo-devel or libcairo2-dev) can be found in "lstopo" when -hwloc is configured and build. +The hwloc command-line tool "lstopo" produces human-readable topology +maps, as mentioned above. It can also export maps to the "fig" file +format. Support for PDF, Postscript, and PNG exporting is provided if +the "Cairo" development package (usually cairo-devel or libcairo2-dev) +can be found in "lstopo" when hwloc is configured and build. -The hwloc core may also benefit from the following development packages: - - * libnuma for memory binding and migration support on Linux (numactl-devel or - libnuma-dev package). +The hwloc core may also benefit from the following development +packages: + * libnuma for memory binding and migration support on Linux + (numactl-devel or libnuma-dev package). * libpciaccess for full I/O device discovery (libpciaccess-devel or - libpciaccess-dev package). On Linux, PCI discovery may still be performed - (without vendor/device names) even if libpciaccess cannot be used. - + libpciaccess-dev package). On Linux, PCI discovery may still be + performed (without vendor/device names) even if libpciaccess cannot + be used. * the AMD OpenCL implementation for OpenCL device discovery. * the NVIDIA CUDA Toolkit for CUDA device discovery. * the NVIDIA Tesla Development Kit for NVML device discovery. - * the NV-CONTROL X extension library (NVCtrl) for NVIDIA display discovery. + * the NV-CONTROL X extension library (NVCtrl) for NVIDIA display + discovery. * libxml2 for full XML import/export support (otherwise, the internal - minimalistic parser will only be able to import XML files that were - exported by the same hwloc release). See Importing and exporting topologies - from/to XML files for details. The relevant development package is usually - libxml2-devel or libxml2-dev. - * libudev on Linux for easier discovery of OS device information (otherwise - hwloc will try to manually parse udev raw files). The relevant development - package is usually libudev-devel or libudev-dev. - * libtool's ltdl library for dynamic plugin loading. The relevant development - package is usually libtool-ltdl-devel or libltdl-dev. + minimalistic parser will only be able to import XML files that were + exported by the same hwloc release). See Importing and exporting + topologies from/to XML files for details. The relevant development + package is usually libxml2-devel or libxml2-dev. + * libudev on Linux for easier discovery of OS device information + (otherwise hwloc will try to manually parse udev raw files). The + relevant development package is usually libudev-devel or + libudev-dev. + * libtool's ltdl library for dynamic plugin loading. The relevant + development package is usually libtool-ltdl-devel or libltdl-dev. -PCI and XML support may be statically built inside the main hwloc library, or -as separate dynamically-loaded plugins (see the Components and plugins -section). +PCI and XML support may be statically built inside the main hwloc +library, or as separate dynamically-loaded plugins (see the Components +and plugins section). -Note that because of the possibility of GPL taint, the pciutils library libpci -will not be used (remember that hwloc is BSD-licensed). +Note that because of the possibility of GPL taint, the pciutils library +libpci will not be used (remember that hwloc is BSD-licensed). -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. +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 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 ... CLI Examples -On a 4-package 2-core machine with hyper-threading, the lstopo tool may show -the following graphical output: +On a 4-package 2-core machine with hyper-threading, the lstopo tool may +show the following graphical output: -dudley.png + dudley.png Here's the equivalent output in textual form: - Machine (16GB) Package L#0 + L3 L#0 (4096KB) L2 L#0 (1024KB) + L1 L#0 (16KB) + Core L#0 @@ -188,17 +190,17 @@ Machine (16GB) PU L#14 (P#7) PU L#15 (P#15) -Note that there is also an equivalent output in XML that is meant for exporting -/importing topologies but it is hardly readable to human-beings (see Importing -and exporting topologies from/to XML files for details). +Note that there is also an equivalent output in XML that is meant for +exporting/importing topologies but it is hardly readable to +human-beings (see Importing and exporting topologies from/to XML files +for details). -On a 4-package 2-core Opteron NUMA machine, the lstopo tool may show the -following graphical output: +On a 4-package 2-core Opteron NUMA machine, the lstopo tool may show +the following graphical output: -hagrid.png + hagrid.png Here's the equivalent output in textual form: - Machine (32GB) NUMANode L#0 (P#0 8190MB) + Package L#0 L2 L#0 (1024KB) + L1 L#0 (64KB) + Core L#0 + PU L#0 (P#0) @@ -213,13 +215,12 @@ Machine (32GB) L2 L#6 (1024KB) + L1 L#6 (64KB) + Core L#6 + PU L#6 (P#6) L2 L#7 (1024KB) + L1 L#7 (64KB) + Core L#7 + PU L#7 (P#7) -On a 2-package quad-core Xeon (pre-Nehalem, with 2 dual-core dies into each -package): +On a 2-package quad-core Xeon (pre-Nehalem, with 2 dual-core dies into +each package): -emmett.png + emmett.png Here's the same output in textual form: - Machine (16GB) Package L#0 L2 L#0 (4096KB) @@ -238,290 +239,117 @@ Machine (16GB) Programming Interface -The basic interface is available in hwloc.h. Some higher-level functions are -available in hwloc/helper.h to reduce the need to manually manipulate objects -and follow links between them. Documentation for all these is provided later in -this document. Developers may also want to look at hwloc/inlines.h which -contains the actual inline code of some hwloc.h routines, and at this document, +The basic interface is available in hwloc.h. Some higher-level +functions are available in hwloc/helper.h to reduce the need to +manually manipulate objects and follow links between them. +Documentation for all these is provided later in this document. +Developers may also want to look at hwloc/inlines.h which contains the +actual inline code of some hwloc.h routines, and at this document, which provides good higher-level topology traversal examples. -To precisely define the vocabulary used by hwloc, a Terms and Definitions -section is available and should probably be read first. +To precisely define the vocabulary used by hwloc, a Terms and +Definitions section is available and should probably be read first. -Each hwloc object contains a cpuset describing the list of processing units -that it contains. These bitmaps may be used for CPU binding and Memory binding. -hwloc offers an extensive bitmap manipulation interface in hwloc/bitmap.h. +Each hwloc object contains a cpuset describing the list of processing +units that it contains. These bitmaps may be used for CPU binding and +Memory binding. hwloc offers an extensive bitmap manipulation interface +in hwloc/bitmap.h. -Moreover, hwloc also comes with additional helpers for interoperability with -several commonly used environments. See the Interoperability With Other -Software section for details. +Moreover, hwloc also comes with additional helpers for interoperability +with several commonly used environments. See the Interoperability With +Other Software section for details. -The complete API documentation is available in a full set of HTML pages, man -pages, and self-contained PDF files (formatted for both both US letter and A4 -formats) in the source tarball in doc/doxygen-doc/. +The complete API documentation is available in a full set of HTML +pages, man pages, and self-contained PDF files (formatted for both both +US letter and A4 formats) in the source tarball in doc/doxygen-doc/. -NOTE: If you are building the documentation from a Git clone, you will need to -have Doxygen and pdflatex installed -- the documentation will be built during -the normal "make" process. The documentation is installed during "make install" -to $prefix/share/doc/hwloc/ and your systems default man page tree (under -$prefix, of course). +NOTE: If you are building the documentation from a Git clone, you will +need to have Doxygen and pdflatex installed -- the documentation will +be built during the normal "make" process. The documentation is +installed during "make install" to $prefix/share/doc/hwloc/ and your +systems default man page tree (under $prefix, of course). Portability -As shown in CLI Examples, hwloc can obtain information on a wide variety of -hardware topologies. However, some platforms and/or operating system versions -will only report a subset of this information. For example, on an PPC64-based -system with 32 cores (each with 2 hardware threads) running a default -2.6.18-based kernel from RHEL 5.4, hwloc is only able to glean information -about NUMA nodes and processor units (PUs). No information about caches, -packages, or cores is available. +As shown in CLI Examples, hwloc can obtain information on a wide +variety of hardware topologies. However, some platforms and/or +operating system versions will only report a subset of this +information. For example, on an PPC64-based system with 32 cores (each +with 2 hardware threads) running a default 2.6.18-based kernel from +RHEL 5.4, hwloc is only able to glean information about NUMA nodes and +processor units (PUs). No information about caches, packages, or cores +is available. -Similarly, Operating System have varying support for CPU and memory binding, -e.g. while some Operating Systems provide interfaces for all kinds of CPU and -memory bindings, some others provide only interfaces for a limited number of -kinds of CPU and memory binding, and some do not provide any binding interface -at all. Hwloc's binding functions would then simply return the ENOSYS error -(Function not implemented), meaning that the underlying Operating System does -not provide any interface for them. CPU binding and Memory binding provide more -information on which hwloc binding functions should be preferred because -interfaces for them are usually available on the supported Operating Systems. +Similarly, Operating System have varying support for CPU and memory +binding, e.g. while some Operating Systems provide interfaces for all +kinds of CPU and memory bindings, some others provide only interfaces +for a limited number of kinds of CPU and memory binding, and some do +not provide any binding interface at all. Hwloc's binding functions +would then simply return the ENOSYS error (Function not implemented), +meaning that the underlying Operating System does not provide any +interface for them. CPU binding and Memory binding provide more +information on which hwloc binding functions should be preferred +because interfaces for them are usually available on the supported +Operating Systems. -Here's the graphical output from lstopo on this platform when Simultaneous -Multi-Threading (SMT) is enabled: +Here's the graphical output from lstopo on this platform when +Simultaneous Multi-Threading (SMT) is enabled: -ppc64-with-smt.png + ppc64-with-smt.png -And here's the graphical output from lstopo on this platform when SMT is -disabled: +And here's the graphical output from lstopo on this platform when SMT +is disabled: -ppc64-without-smt.png + ppc64-without-smt.png -Notice that hwloc only sees half the PUs when SMT is disabled. PU #15, for -example, seems to change location from NUMA node #0 to #1. In reality, no PUs -"moved" -- they were simply re-numbered when hwloc only saw half as many. -Hence, PU #15 in the SMT-disabled picture probably corresponds to PU #30 in the -SMT-enabled picture. +Notice that hwloc only sees half the PUs when SMT is disabled. PU #15, +for example, seems to change location from NUMA node #0 to #1. In +reality, no PUs "moved" -- they were simply re-numbered when hwloc only +saw half as many. Hence, PU #15 in the SMT-disabled picture probably +corresponds to PU #30 in the SMT-enabled picture. -This same "PUs have disappeared" effect can be seen on other platforms -- even -platforms / OSs that provide much more information than the above PPC64 system. -This is an unfortunate side-effect of how operating systems report information -to hwloc. +This same "PUs have disappeared" effect can be seen on other platforms +-- even platforms / OSs that provide much more information than the +above PPC64 system. This is an unfortunate side-effect of how operating +systems report information to hwloc. -Note that upgrading the Linux kernel on the same PPC64 system mentioned above -to 2.6.34, hwloc is able to discover all the topology information. The -following picture shows the entire topology layout when SMT is enabled: +Note that upgrading the Linux kernel on the same PPC64 system mentioned +above to 2.6.34, hwloc is able to discover all the topology +information. The following picture shows the entire topology layout +when SMT is enabled: -ppc64-full-with-smt.png + ppc64-full-with-smt.png -Developers using the hwloc API or XML output for portable applications should -therefore be extremely careful to not make any assumptions about the structure -of data that is returned. For example, per the above reported PPC topology, it -is not safe to assume that PUs will always be descendants of cores. +Developers using the hwloc API or XML output for portable applications +should therefore be extremely careful to not make any assumptions about +the structure of data that is returned. For example, per the above +reported PPC topology, it is not safe to assume that PUs will always be +descendants of cores. -Additionally, future hardware may insert new topology elements that are not -available in this version of hwloc. Long-lived applications that are meant to -span multiple different hardware platforms should also be careful about making -structure assumptions. For example, there may someday be an element "lower" -than a PU, or perhaps a new element may exist between a core and a PU. +Additionally, future hardware may insert new topology elements that are +not available in this version of hwloc. Long-lived applications that +are meant to span multiple different hardware platforms should also be +careful about making structure assumptions. For example, there may +someday be an element "lower" than a PU, or perhaps a new element may +exist between a core and a PU. API Example -The following small C example (named ``hwloc-hello.c'') prints the topology of -the machine and bring the process to the first logical processor of the second -core of the machine. More examples are available in the doc/examples/ directory -of the source tree. - -/* Example hwloc API program. - * - * See other examples under doc/examples/ in the source tree - * for more details. - * - * Copyright (c) 2009-2015 Inria. All rights reserved. - * Copyright (c) 2009-2011 Universit?eacute; Bordeaux - * Copyright (c) 2009-2010 Cisco Systems, Inc. All rights reserved. - * See COPYING in top-level directory. - * - * hwloc-hello.c - */ - -#include -#include -#include -#include - -static void print_children(hwloc_topology_t topology, hwloc_obj_t obj, - int depth) -{ - char type[32], attr[1024]; - unsigned i; - - hwloc_obj_type_snprintf(type, sizeof(type), obj, 0); - printf("%*s%s", 2*depth, "", type); - if (obj->os_index != (unsigned) -1) - printf("#%u", obj->os_index); - hwloc_obj_attr_snprintf(attr, sizeof(attr), obj, " ", 0); - if (*attr) - printf("(%s)", attr); - printf("\n"); - for (i = 0; i < obj->arity; i++) { - print_children(topology, obj->children[i], depth + 1); - } -} - -int main(void) -{ - int depth; - unsigned i, n; - unsigned long size; - int levels; - char string[128]; - int topodepth; - hwloc_topology_t topology; - hwloc_cpuset_t cpuset; - hwloc_obj_t obj; - - /* Allocate and initialize topology object. */ - hwloc_topology_init(&topology); - - /* ... Optionally, put detection configuration here to ignore - some objects types, define a synthetic topology, etc.... - - The default is to detect all the objects of the machine that - the caller is allowed to access. See Configure Topology - Detection. */ - - /* Perform the topology detection. */ - hwloc_topology_load(topology); - - /* Optionally, get some additional topology information - in case we need the topology depth later. */ - topodepth = hwloc_topology_get_depth(topology); - - /***************************************************************** - * First example: - * Walk the topology with an array style, from level 0 (always - * the system level) to the lowest level (always the proc level). - *****************************************************************/ - for (depth = 0; depth < topodepth; depth++) { - printf("*** Objects at level %d\n", depth); - for (i = 0; i < hwloc_get_nbobjs_by_depth(topology, depth); - i++) { - hwloc_obj_type_snprintf(string, sizeof(string), - hwloc_get_obj_by_depth -(topology, depth, i), 0); - printf("Index %u: %s\n", i, string); - } - } - - /***************************************************************** - * Second example: - * Walk the topology with a tree style. - *****************************************************************/ - printf("*** Printing overall tree\n"); - print_children(topology, hwloc_get_root_obj(topology), 0); - - /***************************************************************** - * Third example: - * Print the number of packages. - *****************************************************************/ - depth = hwloc_get_type_depth(topology, HWLOC_OBJ_PACKAGE); - if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) { - printf("*** The number of packages is unknown\n"); - } else { - printf("*** %u package(s)\n", - hwloc_get_nbobjs_by_depth(topology, depth)); - } - - /***************************************************************** - * Fourth example: - * Compute the amount of cache that the first logical processor - * has above it. - *****************************************************************/ - levels = 0; - size = 0; - for (obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PU, 0); - obj; - obj = obj->parent) - if (obj->type == HWLOC_OBJ_CACHE) { - levels++; - size += obj->attr->cache.size; - } - printf("*** Logical processor 0 has %d caches totaling %luKB\n", - levels, size / 1024); - - /***************************************************************** - * Fifth example: - * Bind to only one thread of the last core of the machine. - * - * First find out where cores are, or else smaller sets of CPUs if - * the OS doesn't have the notion of a "core". - *****************************************************************/ - depth = hwloc_get_type_or_below_depth(topology, HWLOC_OBJ_CORE); - - /* Get last core. */ - obj = hwloc_get_obj_by_depth(topology, depth, - hwloc_get_nbobjs_by_depth(topology, depth) - 1); - if (obj) { - /* Get a copy of its cpuset that we may modify. */ - cpuset = hwloc_bitmap_dup(obj->cpuset); - - /* Get only one logical processor (in case the core is - SMT/hyper-threaded). */ - hwloc_bitmap_singlify(cpuset); - - /* And try to bind ourself there. */ - if (hwloc_set_cpubind(topology, cpuset, 0)) { - char *str; - int error = errno; - hwloc_bitmap_asprintf(&str, obj->cpuset); - printf("Couldn't bind to cpuset %s: %s\n", str, strerror(error)); - free(str); - } - - /* Free our cpuset copy */ - hwloc_bitmap_free(cpuset); - } - - /***************************************************************** - * Sixth example: - * Allocate some memory on the last NUMA node, bind some existing - * memory to the last NUMA node. - *****************************************************************/ - /* Get last node. */ - n = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_NUMANODE); - if (n) { - void *m; - size = 1024*1024; - - obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, n - 1); - m = hwloc_alloc_membind_nodeset(topology, size, obj->nodeset, - HWLOC_MEMBIND_BIND, 0); - hwloc_free(topology, m, size); - - m = malloc(size); - hwloc_set_area_membind_nodeset(topology, m, size, obj->nodeset, - HWLOC_MEMBIND_BIND, 0); - free(m); - } - - /* Destroy topology object. */ - hwloc_topology_destroy(topology); - - return 0; -} - -hwloc provides a pkg-config executable to obtain relevant compiler and linker -flags. For example, it can be used thusly to compile applications that utilize -the hwloc library (assuming GNU Make): +The following small C example (named ``hwloc-hello.c'') prints the +topology of the machine and bring the process to the first logical +processor of the second core of the machine. More examples are +available in the doc/examples/ directory of the source tree. +hwloc provides a pkg-config executable to obtain relevant compiler and +linker flags. For example, it can be used thusly to compile +applications that utilize the hwloc library (assuming GNU Make): CFLAGS += $(pkg-config --cflags hwloc) LDLIBS += $(pkg-config --libs hwloc) cc hwloc-hello.c $(CFLAGS) -o hwloc-hello $(LDLIBS) -On a machine with 4GB of RAM and 2 processor packages -- each package of which -has two processing cores -- the output from running hwloc-hello could be -something like the following: - +On a machine with 4GB of RAM and 2 processor packages -- each package +of which has two processing cores -- the output from running +hwloc-hello could be something like the following: shell$ ./hwloc-hello *** Objects at level 0 Index 0: Machine(3938MB) @@ -555,43 +383,45 @@ shell$ Questions and Bugs -Questions should be sent to the devel mailing list (http://www.open-mpi.org/ -community/lists/hwloc.php). Bug reports should be reported in the tracker ( -https://git.open-mpi.org/trac/hwloc/). +Questions should be sent to the devel mailing list +(http://www.open-mpi.org/community/lists/hwloc.php). Bug reports should +be reported in the tracker (https://git.open-mpi.org/trac/hwloc/). -If hwloc discovers an incorrect topology for your machine, the very first thing -you should check is to ensure that you have the most recent updates installed -for your operating system. Indeed, most of hwloc topology discovery relies on -hardware information retrieved through the operation system (e.g., via the /sys -virtual filesystem of the Linux kernel). If upgrading your OS or Linux kernel -does not solve your problem, you may also want to ensure that you are running -the most recent version of the BIOS for your machine. +If hwloc discovers an incorrect topology for your machine, the very +first thing you should check is to ensure that you have the most recent +updates installed for your operating system. Indeed, most of hwloc +topology discovery relies on hardware information retrieved through the +operation system (e.g., via the /sys virtual filesystem of the Linux +kernel). If upgrading your OS or Linux kernel does not solve your +problem, you may also want to ensure that you are running the most +recent version of the BIOS for your machine. -If those things fail, contact us on the mailing list for additional help. -Please attach the output of lstopo after having given the --enable-debug option -to ./configure and rebuilt completely, to get debugging output. Also attach the -/proc + /sys tarball generated by the installed script hwloc-gather-topology -when submitting problems about Linux, or send the output of kstat cpu_info in -the Solaris case, or the output of sysctl hw in the Darwin or BSD cases. +If those things fail, contact us on the mailing list for additional +help. Please attach the output of lstopo after having given the +--enable-debug option to ./configure and rebuilt completely, to get +debugging output. Also attach the /proc + /sys tarball generated by the +installed script hwloc-gather-topology when submitting problems about +Linux, or send the output of kstat cpu_info in the Solaris case, or the +output of sysctl hw in the Darwin or BSD cases. History / Credits -hwloc is the evolution and merger of the libtopology (http:// -runtime.bordeaux.inria.fr/libtopology/) project and the Portable Linux -Processor Affinity (PLPA) (http://www.open-mpi.org/projects/plpa/) project. -Because of functional and ideological overlap, these two code bases and ideas -were merged and released under the name "hwloc" as an Open MPI sub-project. +hwloc is the evolution and merger of the libtopology +(http://runtime.bordeaux.inria.fr/libtopology/) project and the +Portable Linux Processor Affinity (PLPA) +(http://www.open-mpi.org/projects/plpa/) project. Because of functional +and ideological overlap, these two code bases and ideas were merged and +released under the name "hwloc" as an Open MPI sub-project. -libtopology was initially developed by the inria Runtime Team-Project (http:// -runtime.bordeaux.inria.fr/) (headed by Raymond Namyst (http:// -dept-info.labri.fr/~namyst/). PLPA was initially developed by the Open MPI -development team as a sub-project. Both are now deprecated in favor of hwloc, -which is distributed as an Open MPI sub-project. +libtopology was initially developed by the inria Runtime Team-Project +(http://runtime.bordeaux.inria.fr/) (headed by Raymond Namyst +(http://dept-info.labri.fr/~namyst/). PLPA was initially developed by +the Open MPI development team as a sub-project. Both are now deprecated +in favor of hwloc, which is distributed as an Open MPI sub-project. Further Reading The documentation chapters include - * Terms and Definitions * Command-Line Tools * Environment Variables @@ -609,4 +439,8 @@ The documentation chapters include * Frequently Asked Questions Make sure to have had a look at those too! + __________________________________________________________________ + + Generated on 5 Jun 2015 for Hardware Locality (hwloc) by doxygen + 1.6.1 diff --git a/opal/mca/hwloc/hwloc1110/hwloc/VERSION b/opal/mca/hwloc/hwloc1110/hwloc/VERSION index 5ccd593891..fae47659b6 100644 --- a/opal/mca/hwloc/hwloc1110/hwloc/VERSION +++ b/opal/mca/hwloc/hwloc1110/hwloc/VERSION @@ -16,17 +16,17 @@ release=0 # requirement is that it must be entirely printable ASCII characters # and have no white space. -greek=rc1 +greek=rc2 # The date when this release was created -date="Jun 02, 2015" +date="Unreleased developer copy" # If snapshot=1, then use the value from snapshot_version as the # entire hwloc version (i.e., ignore major, minor, release, and # greek). This is only set to 1 when making snapshot tarballs. -snapshot=0 -snapshot_version=${major}.${minor}.${release}${greek}-git +snapshot=1 +snapshot_version=dev-450-g1cc3012 # The shared library version of hwloc's public library. This version # is maintained in accordance with the "Library Interface Versions" diff --git a/opal/mca/hwloc/hwloc1110/hwloc/config/hwloc.m4 b/opal/mca/hwloc/hwloc1110/hwloc/config/hwloc.m4 index 2b39af1cea..2f44504fd1 100644 --- a/opal/mca/hwloc/hwloc1110/hwloc/config/hwloc.m4 +++ b/opal/mca/hwloc/hwloc1110/hwloc/config/hwloc.m4 @@ -9,7 +9,7 @@ dnl Copyright © 2004-2012 The Regents of the University of California. dnl All rights reserved. dnl Copyright © 2004-2008 High Performance Computing Center Stuttgart, dnl University of Stuttgart. All rights reserved. -dnl Copyright © 2006-2014 Cisco Systems, Inc. All rights reserved. +dnl Copyright © 2006-2015 Cisco Systems, Inc. All rights reserved. dnl Copyright © 2012 Blue Brain Project, BBP/EPFL. All rights reserved. dnl Copyright © 2012 Oracle and/or its affiliates. All rights reserved. dnl See COPYING in top-level directory. @@ -80,11 +80,11 @@ EOF]) # Get the version of hwloc that we are installing AC_MSG_CHECKING([for hwloc version]) - HWLOC_VERSION="`$srcdir/config/hwloc_get_version.sh $srcdir/VERSION`" + HWLOC_VERSION="`$HWLOC_top_srcdir/config/hwloc_get_version.sh $HWLOC_top_srcdir/VERSION`" if test "$?" != "0"; then AC_MSG_ERROR([Cannot continue]) fi - HWLOC_RELEASE_DATE="`$srcdir/config/hwloc_get_version.sh $srcdir/VERSION --release-date`" + HWLOC_RELEASE_DATE="`$HWLOC_top_srcdir/config/hwloc_get_version.sh $HWLOC_top_srcdir/VERSION --release-date`" AC_SUBST(HWLOC_VERSION) AC_DEFINE_UNQUOTED([HWLOC_VERSION], ["$HWLOC_VERSION"], [The library version, always available, even in embedded mode, contrary to VERSION]) diff --git a/opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/cuda.h b/opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/cuda.h index 1b13ffd8ab..a02d677699 100644 --- a/opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/cuda.h +++ b/opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/cuda.h @@ -1,5 +1,5 @@ /* - * Copyright © 2010-2013 Inria. All rights reserved. + * Copyright © 2010-2015 Inria. All rights reserved. * Copyright © 2010-2011 Université Bordeaux * Copyright © 2011 Cisco Systems, Inc. All rights reserved. * See COPYING in top-level directory. @@ -49,7 +49,7 @@ hwloc_cuda_get_device_pci_ids(hwloc_topology_t topology __hwloc_attribute_unused { CUresult cres; -#ifdef CU_DEVICE_ATTRIBUTE_PCI_DOMAIN_ID +#if CUDA_VERSION >= 4000 cres = cuDeviceGetAttribute(domain, CU_DEVICE_ATTRIBUTE_PCI_DOMAIN_ID, cudevice); if (cres != CUDA_SUCCESS) { errno = ENOSYS; diff --git a/opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/cudart.h b/opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/cudart.h index 243e0fdd56..759c3cf4fe 100644 --- a/opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/cudart.h +++ b/opal/mca/hwloc/hwloc1110/hwloc/include/hwloc/cudart.h @@ -1,5 +1,5 @@ /* - * Copyright © 2010-2013 Inria. All rights reserved. + * Copyright © 2010-2015 Inria. All rights reserved. * Copyright © 2010-2011 Université Bordeaux * Copyright © 2011 Cisco Systems, Inc. All rights reserved. * See COPYING in top-level directory. @@ -23,6 +23,7 @@ #include #endif +#include /* for CUDA_VERSION */ #include @@ -56,7 +57,7 @@ hwloc_cudart_get_device_pci_ids(hwloc_topology_t topology __hwloc_attribute_unus return -1; } -#ifdef CU_DEVICE_ATTRIBUTE_PCI_DOMAIN_ID +#if CUDA_VERSION >= 4000 *domain = prop.pciDomainID; #else *domain = 0; diff --git a/opal/mca/hwloc/hwloc1110/hwloc/src/topology.c b/opal/mca/hwloc/hwloc1110/hwloc/src/topology.c index 8d129d0705..01be27453b 100644 --- a/opal/mca/hwloc/hwloc1110/hwloc/src/topology.c +++ b/opal/mca/hwloc/hwloc1110/hwloc/src/topology.c @@ -2599,7 +2599,7 @@ next_noncpubackend: && strcmp(topology->backends->component->name, "xml")) { char *value; /* add a hwlocVersion */ - hwloc_obj_add_info(topology->levels[0][0], "hwlocVersion", VERSION); + hwloc_obj_add_info(topology->levels[0][0], "hwlocVersion", HWLOC_VERSION); /* add a ProcessName */ value = hwloc_progname(topology); if (value) { diff --git a/opal/mca/hwloc/hwloc191/Makefile.am b/opal/mca/hwloc/hwloc191/Makefile.am deleted file mode 100644 index 992c19bb0f..0000000000 --- a/opal/mca/hwloc/hwloc191/Makefile.am +++ /dev/null @@ -1,83 +0,0 @@ -# -# Copyright (c) 2011-2014 Cisco Systems, Inc. All rights reserved. -# Copyright (c) 2014 Intel, Inc. All right reserved. -# $COPYRIGHT$ -# -# Additional copyrights may follow -# -# $HEADER$ -# - -# Due to what might be a bug in Automake, we need to remove stamp-h? -# files manually. See -# http://debbugs.gnu.org/cgi/bugreport.cgi?bug=19418. -DISTCLEANFILES = \ - hwloc/include/hwloc/autogen/stamp-h? \ - hwloc/include/private/autogen/stamp-h? - -# Need to include these files so that these directories are carried in -# the tarball (in case someone invokes autogen.sh on a dist tarball). -EXTRA_DIST = \ - hwloc/doc/README.txt \ - hwloc/tests/README.txt \ - hwloc/utils/README.txt - -SUBDIRS = hwloc - -# Headers and sources -headers = hwloc191.h -sources = hwloc191_component.c - -# We only ever build this component statically -noinst_LTLIBRARIES = libmca_hwloc_hwloc191.la -libmca_hwloc_hwloc191_la_SOURCES = $(headers) $(sources) -nodist_libmca_hwloc_hwloc191_la_SOURCES = $(nodist_headers) -libmca_hwloc_hwloc191_la_LDFLAGS = -module -avoid-version $(opal_hwloc_hwloc191_LDFLAGS) -libmca_hwloc_hwloc191_la_LIBADD = $(opal_hwloc_hwloc191_LIBS) -libmca_hwloc_hwloc191_la_DEPENDENCIES = \ - $(HWLOC_top_builddir)/src/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 -# --with-devel-headers is specified. hwloc doesn't support this; the -# least gross way to make this happen is just to list all of hwloc's -# header files here. :-( -headers += \ - hwloc/include/hwloc.h \ - hwloc/include/hwloc/bitmap.h \ - hwloc/include/hwloc/cuda.h \ - hwloc/include/hwloc/cudart.h \ - hwloc/include/hwloc/deprecated.h \ - hwloc/include/hwloc/diff.h \ - hwloc/include/hwloc/gl.h \ - hwloc/include/hwloc/helper.h \ - hwloc/include/hwloc/inlines.h \ - hwloc/include/hwloc/intel-mic.h \ - hwloc/include/hwloc/myriexpress.h \ - hwloc/include/hwloc/nvml.h \ - hwloc/include/hwloc/opencl.h \ - hwloc/include/hwloc/openfabrics-verbs.h \ - hwloc/include/hwloc/plugins.h \ - hwloc/include/hwloc/rename.h \ - hwloc/include/private/private.h \ - hwloc/include/private/debug.h \ - hwloc/include/private/misc.h \ - hwloc/include/private/cpuid-x86.h -nodist_headers = hwloc/include/hwloc/autogen/config.h - -if HWLOC_HAVE_LINUX -headers += \ - hwloc/include/hwloc/linux.h \ - hwloc/include/hwloc/linux-libnuma.h -endif HWLOC_HAVE_LINUX - -if HWLOC_HAVE_SCHED_SETAFFINITY -headers += hwloc/include/hwloc/glibc-sched.h -endif HWLOC_HAVE_SCHED_SETAFFINITY - -# Conditionally install the header files -if WANT_INSTALL_HEADERS -opaldir = $(opalincludedir)/$(subdir) -nobase_opal_HEADERS = $(headers) -nobase_nodist_opal_HEADERS = $(nodist_headers) -endif diff --git a/opal/mca/hwloc/hwloc191/README-ompi.txt b/opal/mca/hwloc/hwloc191/README-ompi.txt deleted file mode 100644 index 948285aaff..0000000000 --- a/opal/mca/hwloc/hwloc191/README-ompi.txt +++ /dev/null @@ -1,35 +0,0 @@ -Applied the following patches from the upstream hwloc 1.9 branch after -the v1.9.1 release: - -All relevant commits up to open-mpi/hwloc@4e23b12 (i.e., the HEAD as -of 27 March 2015). "Relevant" commits are defined as those that -included files that are embedded in the Open MPI tree (e.g., updates -to files in docs/, utils/, etc. aren't relevant because they are not -embedded in the Open MPI tree). To be specific, the following commits -have been cherry-picked over to Open MPI: - -* open-mpi/hwloc@7c03216 v1.9.1 released, doing 1.9.2rc1 now -* open-mpi/hwloc@b35ced8 misc.h: Fix hwloc_strncasecmp() build under strict flags on BSD -* open-mpi/hwloc@d8c3f3d misc.h: Fix hwloc_strncasecmp() with some icc -* open-mpi/hwloc@f705a23 Use gcc's __asm__ version of the asm extension, which can be used in all standards -* open-mpi/hwloc@307726a configure: fix the check for X11/Xutil.h -* open-mpi/hwloc@ec58c05 errors: improve the advice to send hwloc-gather-topology files in the OS error message -* open-mpi/hwloc@35c743d NEWS update -* open-mpi/hwloc@868170e API: clearly state that os_index isn't unique while logical_index is -* open-mpi/hwloc@851532d x86 and OSF: Don't forget to set NUMA node nodeset -* open-mpi/hwloc@790aa2e cpuid-x86: Fix duplicate asm labels in case of heavy inlining on x86-32 -* open-mpi/hwloc@dd09aa5 debug: fix an overzealous assertion about the parent cpuset vs its children -* open-mpi/hwloc@769b9b5 core: fix the merging of identical objects in presence of Misc objects -* open-mpi/hwloc@71da0f1 core: reorder children in merge_useless_child() as well -* open-mpi/hwloc@c9cef07 hpux: improve hwloc_hpux_find_ldom() looking for NUMA node -* open-mpi/hwloc@cdffea6 x86: use ulong for cache sizes, uint won't be enough in the near future -* open-mpi/hwloc@55b0676 x86: use Group instead of Misc for unknown x2apic levels -* open-mpi/hwloc@7764ce5 synthetic: Misc levels are not allowed in the synthetic description -* open-mpi/hwloc@5b2dce1 error: point to the FAQ when displaying the big OS error message -* open-mpi/hwloc@c7bd9e6 pci: fix SR-IOV VF vendor/device names -* open-mpi/hwloc@a0f72ef distances: when we fail to insert an intermediate group, don't try to group further above -* open-mpi/hwloc@e419811 AIX: Fix PU os_index -* open-mpi/hwloc@08ab793 groups: add complete sets when inserting distance/pci groups -* open-mpi/hwloc@c66e714 core: only update root->complete sets if insert succeeds -* open-mpi/hwloc@01da9b9 bitmap: fix a corner case in hwloc_bitmap_isincluded() with infinite sets -* open-mpi/hwloc@e7b192b pci: fix bridge depth diff --git a/opal/mca/hwloc/hwloc191/configure.m4 b/opal/mca/hwloc/hwloc191/configure.m4 deleted file mode 100644 index d66e68dadb..0000000000 --- a/opal/mca/hwloc/hwloc191/configure.m4 +++ /dev/null @@ -1,170 +0,0 @@ -# -*- shell-script -*- -# -# Copyright (c) 2009-2014 Cisco Systems, Inc. All rights reserved. -# Copyright (c) 2014 Intel, Inc. All rights reserved. -# -# $COPYRIGHT$ -# -# Additional copyrights may follow -# -# $HEADER$ -# - -# -# Priority -# -AC_DEFUN([MCA_opal_hwloc_hwloc191_PRIORITY], [10]) - -# -# Force this component to compile in static-only mode -# -AC_DEFUN([MCA_opal_hwloc_hwloc191_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/hwloc191/hwloc/config/hwloc.m4) -m4_include(opal/mca/hwloc/hwloc191/hwloc/config/hwloc_pkg.m4) -m4_include(opal/mca/hwloc/hwloc191/hwloc/config/hwloc_check_attributes.m4) -m4_include(opal/mca/hwloc/hwloc191/hwloc/config/hwloc_check_visibility.m4) -m4_include(opal/mca/hwloc/hwloc191/hwloc/config/hwloc_check_vendor.m4) -m4_include(opal/mca/hwloc/hwloc191/hwloc/config/hwloc_components.m4) - -# MCA_hwloc_hwloc191_POST_CONFIG() -# --------------------------------- -AC_DEFUN([MCA_opal_hwloc_hwloc191_POST_CONFIG],[ - OPAL_VAR_SCOPE_PUSH([opal_hwloc_hwloc191_basedir]) - - # If we won, then do all the rest of the setup - AS_IF([test "$1" = "1" && test "$opal_hwloc_hwloc191_support" = "yes"], - [ - # Set this variable so that the framework m4 knows what - # file to include in opal/mca/hwloc/hwloc.h - opal_hwloc_hwloc191_basedir=opal/mca/hwloc/hwloc191 - opal_hwloc_base_include="$opal_hwloc_hwloc191_basedir/hwloc191.h" - - # Add some stuff to CPPFLAGS so that the rest of the source - # tree can be built - file=$opal_hwloc_hwloc191_basedir/hwloc - CPPFLAGS="$CPPFLAGS -I$OPAL_TOP_SRCDIR/$file/include" - AS_IF([test "$OPAL_TOP_BUILDDIR" != "$OPAL_TOP_SRCDIR"], - [CPPFLAGS="$CPPFLAGS -I$OPAL_TOP_BUILDDIR/$file/include"]) - unset file - ]) - OPAL_VAR_SCOPE_POP - - # This must be run unconditionally - HWLOC_DO_AM_CONDITIONALS -])dnl - - -# MCA_hwloc_hwloc191_CONFIG([action-if-found], [action-if-not-found]) -# -------------------------------------------------------------------- -AC_DEFUN([MCA_opal_hwloc_hwloc191_CONFIG],[ - # Hwloc needs to know if we have Verbs support - AC_REQUIRE([OPAL_CHECK_VERBS_DIR]) - - AC_CONFIG_FILES([opal/mca/hwloc/hwloc191/Makefile]) - - OPAL_VAR_SCOPE_PUSH([HWLOC_VERSION opal_hwloc_hwloc191_save_CPPFLAGS opal_hwloc_hwloc191_save_LDFLAGS opal_hwloc_hwloc191_save_LIBS opal_hwloc_hwloc191_save_cairo opal_hwloc_hwloc191_save_xml opal_hwloc_hwloc191_basedir opal_hwloc_hwloc191_file opal_hwloc_hwloc191_save_cflags CPPFLAGS_save LIBS_save]) - - # default to this component not providing support - opal_hwloc_hwloc191_basedir=opal/mca/hwloc/hwloc191 - opal_hwloc_hwloc191_support=no - - if test "$with_hwloc" = "internal" -o "$with_hwloc" = "" -o "$with_hwloc" = "yes"; then - opal_hwloc_hwloc191_save_CPPFLAGS=$CPPFLAGS - opal_hwloc_hwloc191_save_LDFLAGS=$LDFLAGS - opal_hwloc_hwloc191_save_LIBS=$LIBS - - # Run the hwloc configuration - set the prefix to minimize - # the chance that someone will use the internal symbols - HWLOC_SET_SYMBOL_PREFIX([opal_hwloc191_]) - - # save XML or graphical options - opal_hwloc_hwloc191_save_cairo=$enable_cairo - opal_hwloc_hwloc191_save_xml=$enable_xml - opal_hwloc_hwloc191_save_static=$enable_static - opal_hwloc_hwloc191_save_shared=$enable_shared - opal_hwloc_hwloc191_save_plugins=$enable_plugins - - # never enable hwloc's graphical option - enable_cairo=no - - # never enable hwloc's plugin system - enable_plugins=no - enable_static=yes - enable_shared=no - - # Override -- disable hwloc's libxml2 support, but enable the - # native hwloc XML support - enable_libxml2=no - enable_xml=yes - - # hwloc checks for compiler visibility, and its needs to do - # this without "picky" flags. - opal_hwloc_hwloc191_save_cflags=$CFLAGS - CFLAGS=$OPAL_CFLAGS_BEFORE_PICKY - HWLOC_SETUP_CORE([opal/mca/hwloc/hwloc191/hwloc], - [AC_MSG_CHECKING([whether hwloc configure succeeded]) - AC_MSG_RESULT([yes]) - HWLOC_VERSION="internal v`$srcdir/$opal_hwloc_hwloc191_basedir/hwloc/config/hwloc_get_version.sh $srcdir/$opal_hwloc_hwloc191_basedir/hwloc/VERSION`" - - # Build flags for our Makefile.am - opal_hwloc_hwloc191_LDFLAGS='$(HWLOC_EMBEDDED_LDFLAGS)' - opal_hwloc_hwloc191_LIBS='$(OPAL_TOP_BUILDDIR)/'"$opal_hwloc_hwloc191_basedir"'/hwloc/src/libhwloc_embedded.la $(HWLOC_EMBEDDED_LIBS)' - opal_hwloc_hwloc191_support=yes - - AC_DEFINE_UNQUOTED([HWLOC_HWLOC191_HWLOC_VERSION], - ["$HWLOC_VERSION"], - [Version of hwloc]) - - # Do we have verbs support? - CPPFLAGS_save=$CPPFLAGS - AS_IF([test "$opal_want_verbs" = "yes"], - [CPPFLAGS="-I$opal_verbs_dir/include $CPPFLAGS"]) - AC_CHECK_HEADERS([infiniband/verbs.h]) - CPPFLAGS=$CPPFLAGS_save - ], - [AC_MSG_CHECKING([whether hwloc configure succeeded]) - AC_MSG_RESULT([no]) - opal_hwloc_hwloc191_support=no]) - CFLAGS=$opal_hwloc_hwloc191_save_cflags - - # Restore some env variables, if necessary - AS_IF([test -n "$opal_hwloc_hwloc191_save_cairo"], - [enable_cairo=$opal_hwloc_hwloc191_save_cairo]) - AS_IF([test -n "$opal_hwloc_hwloc191_save_xml"], - [enable_xml=$opal_hwloc_hwloc191_save_xml]) - AS_IF([test -n "$opal_hwloc_hwloc191_save_static"], - [enable_static=$opal_hwloc_hwloc191_save_static]) - AS_IF([test -n "$opal_hwloc_hwloc191_save_shared"], - [enable_shared=$opal_hwloc_hwloc191_save_shared]) - AS_IF([test -n "$opal_hwloc_hwloc191_save_plugins"], - [enable_plugins=$opal_hwloc_hwloc191_save_shared]) - - CPPFLAGS=$opal_hwloc_hwloc191_save_CPPFLAGS - LDFLAGS=$opal_hwloc_hwloc191_save_LDFLAGS - LIBS=$opal_hwloc_hwloc191_save_LIBS - - AC_SUBST([opal_hwloc_hwloc191_CFLAGS]) - AC_SUBST([opal_hwloc_hwloc191_CPPFLAGS]) - AC_SUBST([opal_hwloc_hwloc191_LDFLAGS]) - AC_SUBST([opal_hwloc_hwloc191_LIBS]) - - # Finally, add some flags to the wrapper compiler so that our - # headers can be found. - hwloc_hwloc191_WRAPPER_EXTRA_LDFLAGS="$HWLOC_EMBEDDED_LDFLAGS" - hwloc_hwloc191_WRAPPER_EXTRA_LIBS="$HWLOC_EMBEDDED_LIBS" - hwloc_hwloc191_WRAPPER_EXTRA_CPPFLAGS='-I${includedir}/openmpi/'"$opal_hwloc_hwloc191_basedir/hwloc/include" - fi - - # Done! - AS_IF([test "$opal_hwloc_hwloc191_support" = "yes"], - [$1], - [$2]) - - OPAL_VAR_SCOPE_POP -])dnl diff --git a/opal/mca/hwloc/hwloc191/hwloc/AUTHORS b/opal/mca/hwloc/hwloc191/hwloc/AUTHORS deleted file mode 100644 index 837b27f2ca..0000000000 --- a/opal/mca/hwloc/hwloc191/hwloc/AUTHORS +++ /dev/null @@ -1,8 +0,0 @@ -Cédric Augonnet -Jérôme Clet-Ortega -Ludovic Courtès -Brice Goglin -Nathalie Furmento -Samuel Thibault -Jeff Squyres -Alexey Kardashevskiy diff --git a/opal/mca/hwloc/hwloc191/hwloc/COPYING b/opal/mca/hwloc/hwloc191/hwloc/COPYING deleted file mode 100644 index 32128c7f20..0000000000 --- a/opal/mca/hwloc/hwloc191/hwloc/COPYING +++ /dev/null @@ -1,28 +0,0 @@ -Copyright © 2009 CNRS -Copyright © 2009 inria. All rights reserved. -Copyright © 2009 Université Bordeaux 1 -Copyright © 2009 Cisco Systems, Inc. All rights reserved. -Copyright © 2012 Blue Brain Project, EPFL. All rights reserved. -See COPYING in top-level directory. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/opal/mca/hwloc/hwloc191/hwloc/Makefile.am b/opal/mca/hwloc/hwloc191/hwloc/Makefile.am deleted file mode 100644 index f49011ff52..0000000000 --- a/opal/mca/hwloc/hwloc191/hwloc/Makefile.am +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright © 2009-2014 Inria. All rights reserved. -# Copyright © 2009 Université Bordeaux 1 -# Copyright © 2009-2014 Cisco Systems, Inc. All rights reserved. -# See COPYING in top-level directory. - -# Note that the -I directory must *exactly* match what was specified -# via AC_CONFIG_MACRO_DIR in configure.ac. -ACLOCAL_AMFLAGS = -I ./config - -SUBDIRS = src include -if HWLOC_BUILD_STANDALONE -SUBDIRS += utils tests -# 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 -endif - -# Do not let automake automatically add the non-standalone dirs to the -# distribution tarball if we're building in embedded mode. -DIST_SUBDIRS = $(SUBDIRS) - -# Only install the pkg file if we're building in standalone mode (and not on Windows) -if HWLOC_BUILD_STANDALONE -if !HWLOC_HAVE_WINDOWS -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = hwloc.pc -endif -endif - -# 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 -if HWLOC_BUILD_STANDALONE -EXTRA_DIST += contrib/windows -endif - -if HWLOC_BUILD_STANDALONE -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 -# -# Winball specific rules -# -install-data-local: - sed -e 's/$$/'$$'\015'/ < $(srcdir)/README > $(DESTDIR)$(prefix)/README.txt - sed -e 's/$$/'$$'\015'/ < $(srcdir)/NEWS > $(DESTDIR)$(prefix)/NEWS.txt - sed -e 's/$$/'$$'\015'/ < $(srcdir)/COPYING > $(DESTDIR)$(prefix)/COPYING.txt -uninstall-local: - rm -f $(DESTDIR)$(prefix)/README.txt $(DESTDIR)$(prefix)/NEWS.txt $(DESTDIR)$(prefix)/COPYING.txt -endif HWLOC_HAVE_WINDOWS -endif HWLOC_BUILD_STANDALONE diff --git a/opal/mca/hwloc/hwloc191/hwloc/NEWS b/opal/mca/hwloc/hwloc191/hwloc/NEWS deleted file mode 100644 index 7c8e48a28a..0000000000 --- a/opal/mca/hwloc/hwloc191/hwloc/NEWS +++ /dev/null @@ -1,1002 +0,0 @@ -Copyright © 2009 CNRS -Copyright © 2009-2014 Inria. All rights reserved. -Copyright © 2009-2013 Université Bordeaux 1 -Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved. - -$COPYRIGHT$ - -Additional copyrights may follow - -$HEADER$ - -=========================================================================== - -This file contains the main features as well as overviews of specific -bug fixes (and other actions) for each version of hwloc since version -0.9 (as initially released as "libtopology", then re-branded to "hwloc" -in v0.9.1). - - -Version 1.9.2 -------------- -* Fix some build failures in private/misc.h. - Thanks to Pavan Balaji and Ralph Castain for the reports. -* Fix failures to detect X11/Xutil.h on some Solaris platforms. - Thanks to Siegmar Gross for reporting the failure. - - -Version 1.9.1 -------------- -* Fix a crash when the PCI locality is invalid. Attach to the root object - instead. Thanks to Nicolas Denoyelle for reporting the issue. -* Fix -f in lstopo manpage. Thanks to Jirka Hladky for reporting the issue. -* Fix hwloc_obj_type_sscanf() and others when strncasecmp() is not properly - available. Thanks to Nick Papior Andersen for reporting the problem. -* Mark Linux file descriptors as close-on-exec to avoid leaks on exec. -* Fix some minor memory leaks. - - -Version 1.9.0 -------------- -* API - + Add hwloc_obj_type_sscanf() to extend hwloc_obj_type_of_string() with - type-specific attributes such as Cache/Group depth and Cache type. - hwloc_obj_type_of_string() is moved to hwloc/deprecated.h. - + Add hwloc_linux_get_tid_last_cpu_location() for retrieving the - last CPU where a Linux thread given by TID ran. - + Add hwloc_distrib() to extend the old hwloc_distribute[v]() functions. - hwloc_distribute[v]() is moved to hwloc/deprecated.h. - + Don't mix total and local memory when displaying verbose object attributes - with hwloc_obj_attr_snprintf() or in lstopo. -* Backends - + Add CPUVendor, CPUModelNumber and CPUFamilyNumber info attributes for - x86, ia64 and Xeon Phi sockets on Linux, to extend the x86-specific - support added in v1.8.1. Requested by Ralph Castain. - + Add many CPU- and Platform-related info attributes on ARM and POWER - platforms, in the Machine and Socket objects. - + Add CUDA info attributes describing the number of multiprocessors and - cores and the size of the global, shared and L2 cache memories in CUDA - OS devices. - + Add OpenCL info attributes describing the number of compute units and - the global memory size in OpenCL OS devices. - + The synthetic backend now accepts extended types such as L2Cache, L1i or - Group3. lstopo also exports synthetic strings using these extended types. -* Tools - + lstopo - - Do not overwrite output files by default anymore. - Pass -f or --force to enforce it. - - Display OpenCL, CUDA and Xeon Phi numbers of cores and memory sizes - in the graphical output. - - Fix export to stdout when specifying a Cairo-based output type - with --of. - + hwloc-ps - - Add -e or --get-last-cpu-location to report where processes/threads - run instead of where they are bound. - - Report locations as likely-more-useful objects such as Cores or Sockets - instead of Caches when possible. - + hwloc-bind - - Fix failure on Windows when not using --pid. - - Add -e as a synonym to --get-last-cpu-location. - + hwloc-distrib - - Add --reverse to distribute using last objects first and singlify - into last bits first. Thanks to Jirka Hladky for the suggestion. - + hwloc-info - - Report unified caches when looking for data or instruction cache - ancestor objects. -* Misc - + Add experimental Visual Studio support under contrib/windows. - Thanks to Eloi Gaudry for his help and for providing the first draft. - + Fix some overzealous assertions and warnings about the ordering of - objects on a level with respect to cpusets. The ordering is only - guaranteed for complete cpusets (based on the first bit in sets). - + Fix some memory leaks when importing xml diffs and when exporting a - "too complex" entry. - - -Version 1.8.1 -------------- -* Fix the cpuid code on Windows 64bits so that the x86 backend gets - enabled as expected and can populate CPU information. - Thanks to Robin Scher for reporting the problem. -* Add CPUVendor/CPUModelNumber/CPUFamilyNumber attributes when running - on x86 architecture. Thanks to Ralph Castain for the suggestion. -* Work around buggy BIOS reporting duplicate NUMA nodes on Linux. - Thanks to Jeff Becker for reporting the problem and testing the patch. -* Add a name to the lstopo graphical window. Thanks to Michael Prokop - for reporting the issue. - - -Version 1.8.0 -------------- -* New components - + Add the "linuxpci" component that always works on Linux even when - libpciaccess and libpci aren't available (and even with a modified - file-system root). By default the old "pci" component runs first - because "linuxpci" lacks device names (obj->name is always NULL). -* API - + Add the topology difference API in hwloc/diff.h for manipulating - many similar topologies. - + Add hwloc_topology_dup() for duplicating an entire topology. - + hwloc.h and hwloc/helper.h have been reorganized to clarify the - documentation sections. The actual inline code has moved out of hwloc.h - into the new hwloc/inlines.h. - + Deprecated functions are now in hwloc/deprecated.h, and not in the - official documentation anymore. -* Tools - + Add hwloc-diff and hwloc-patch tools together with the new diff API. - + Add hwloc-compress-dir to (de)compress an entire directory of XML files - using hwloc-diff and hwloc-patch. - + Object colors in the graphical output of lstopo may be changed by adding - a "lstopoStyle" info attribute. See CUSTOM COLORS in the lstopo(1) manpage - for details. Thanks to Jirka Hladky for discussing the idea. - + hwloc-gather-topology may now gather I/O-related files on Linux when - --io is given. Only the linuxpci component supports discovering I/O - objects from these extended tarballs. - + hwloc-annotate now supports --ri to remove/replace info attributes with - a given name. - + hwloc-info supports "root" and "all" special locations for dumping - information about the root object. - + lstopo now supports --append-legend to append custom lines of text - to the legend in the graphical output. Thanks to Jirka Hladky for - discussing the idea. - + hwloc-calc and friends have a more robust parsing of locations given - on the command-line and they report useful error messages about it. - + Add --whole-system to hwloc-bind, hwloc-calc, hwloc-distances and - hwloc-distrib, and add --restrict to hwloc-bind for uniformity among - tools. -* Misc - + Calling hwloc_topology_load() or hwloc_topology_set_*() on an already - loaded topology now returns an error (deprecated since release 1.6.1). - + Fix the initialisation of cpusets and nodesets in Group objects added - when inserting PCI hostbridges. - + Never merge Group objects that were added explicitly by the user with - hwloc_custom_insert_group_object_by_parent(). - + Add a sanity check during dynamic plugin loading to prevent some - crashes when hwloc is dynamically loaded by another plugin mechanisms. - + Add --with-hwloc-plugins-path to specify the install/load directories - of plugins. - + Add the MICSerialNumber info attribute to the root object when running - hwloc inside a Xeon Phi to match the same attribute in the MIC OS device - when running in the host. - - -Version 1.7.2 -------------- -* Do not create invalid block OS devices on very old Linux kernel such - as RHEL4 2.6.9. -* Fix PCI subvendor/device IDs. -* Fix the management of Misc objects inserted by parent. - Thanks to Jirka Hladky for reporting the problem. -* Add a PortState into attribute to OpenFabrics OS devices. -* Add a MICSerialNumber info attribute to Xeon PHI/MIC OS devices. -* Improve verbose error messages when failing to load from XML. - - -Version 1.7.1 -------------- -* Fix a failed assertion in the distance grouping code when loading a XML - file that already contains some groups. - Thanks to Laercio Lima Pilla for reporting the problem. -* Remove unexpected Group objects when loading XML topologies with I/O - objects and NUMA distances. - Thanks to Elena Elkina for reporting the problem and testing patches. -* Fix PCI link speed discovery when using libpciaccess. -* Fix invalid libpciaccess virtual function device/vendor IDs when using - SR-IOV PCI devices on Linux. -* Fix GL component build with old NVCtrl releases. - Thanks to Jirka Hladky for reporting the problem. -* Fix embedding breakage caused by libltdl. - Thanks to Pavan Balaji for reporting the problem. -* Always use the system-wide libltdl instead of shipping one inside hwloc. -* Document issues when enabling plugins while embedding hwloc in another - project, in the documentation section Embedding hwloc in Other Software. -* Add a FAQ entry "How to get useful topology information on NetBSD?" - in the documentation. -* Somes fixes in the renaming code for embedding. -* Miscellaneous minor build fixes. - - -Version 1.7.0 -------------- -* New operating system backends - + Add BlueGene/Q compute node kernel (CNK) support. See the FAQ in the - documentation for details. Thanks to Jeff Hammond, Christopher Samuel - and Erik Schnetter for their help. - + Add NetBSD support, thanks to Aleksej Saushev. -* New I/O device discovery - + Add co-processor OS devices such as "mic0" for Intel Xeon Phi (MIC) - on Linux. Thanks to Jerome Vienne for helping. - + Add co-processor OS devices such as "cuda0" for NVIDIA CUDA-capable GPUs. - + Add co-processor OS devices such as "opencl0d0" for OpenCL GPU devices - on the AMD OpenCL implementation. - + Add GPU OS devices such as ":0.0" for NVIDIA X11 displays. - + Add GPU OS devices such as "nvml0" for NVIDIA GPUs. - Thanks to Marwan Abdellah and Stefan Eilemann for helping. - These new OS devices have some string info attributes such as CoProcType, - GPUModel, etc. to better identify them. - See the I/O Devices and Attributes documentation sections for details. -* New components - + Add the "opencl", "cuda", "nvml" and "gl" components for I/O device - discovery. - + "nvml" also improves the discovery of NVIDIA GPU PCIe link speed. - All of these new components may be built as plugins. They may also be - disabled entirely by passing --disable-opencl/cuda/nvml/gl to configure. - See the I/O Devices, Components and Plugins, and FAQ documentation - sections for details. -* API - + Add hwloc_topology_get_flags(). - + Add hwloc/plugins.h for building external plugins. - See the Adding new discovery components and plugins section. -* Interoperability - + Add hwloc/opencl.h, hwloc/nvml.h, hwloc/gl.h and hwloc/intel-mic.h - to retrieve the locality of OS devices that correspond to AMD OpenCL - GPU devices or indexes, to NVML devices or indexes, to NVIDIA X11 - displays, or to Intel Xeon Phi (MIC) device indexes. - + Add new helpers in hwloc/cuda.h and hwloc/cudart.h to convert - between CUDA devices or indexes and hwloc OS devices. - + Add hwloc_ibv_get_device_osdev() and clarify the requirements - of the OpenFabrics Verbs helpers in hwloc/openfabrics-verbs.h. -* Tools - + hwloc-info is not only a synonym of lstopo -s anymore, it also - dumps information about objects given on the command-line. -* Documentation - + Add a section "Existing components and plugins". - + Add a list of common OS devices in section "Software devices". - + Add a new FAQ entry "Why is lstopo slow?" about lstopo slowness - issues because of GPUs. - + Clarify the documentation of inline helpers in hwloc/myriexpress.h - and hwloc/openfabrics-verbs.h. -* Misc - + Improve cache detection on AIX. - + The HWLOC_COMPONENTS variable now excludes the components whose - names are prefixed with '-'. - + lstopo --ignore PU now works when displaying the topology in - graphical and textual mode (not when exporting to XML). - + Make sure I/O options always appear in lstopo usage, not only when - using pciutils/libpci. - + Remove some unneeded Linux specific includes from some interoperability - headers. - + Fix some inconsistencies in hwloc-distrib and hwloc-assembler-remote - manpages. Thanks to Guy Streeter for the report. - + Fix a memory leak on AIX when getting memory binding. - + Fix many small memory leaks on Linux. - + The `libpci' component is now called `pci' but the old name is still - accepted in the HWLOC_COMPONENTS variable for backward compatibility. - - -Version 1.6.2 -------------- -* Use libpciaccess instead of pciutils/libpci by default for I/O discovery. - pciutils/libpci is only used if --enable-libpci is given to configure - because its GPL license may taint hwloc. See the Installation section - in the documentation for details. -* Fix get_cpubind on Solaris when bound to a single PU with - processor_bind(). Thanks to Eugene Loh for reporting the problem - and providing a patch. - - -Version 1.6.1 -------------- -* Fix some crash or buggy detection in the x86 backend when Linux - cgroups/cpusets restrict the available CPUs. -* Fix the pkg-config output with --libs --static. - Thanks to Erik Schnetter for reporting one of the problems. -* Fix the output of hwloc-calc -H --hierarchical when using logical - indexes in the output. -* Calling hwloc_topology_load() multiple times on the same topology - is officially deprecated. hwloc will warn in such cases. -* Add some documentation about existing plugins/components, package - dependencies, and I/O devices specification on the command-line. - - -Version 1.6.0 -------------- -* Major changes - + Reorganize the backend infrastructure to support dynamic selection - of components and dynamic loading of plugins. For details, see the - new documentation section Components and plugins. - - The HWLOC_COMPONENTS variable lets one replace the default discovery - components. - - Dynamic loading of plugins may be enabled with --enable-plugins - (except on AIX and Windows). It will build libxml2 and libpci - support as separated modules. This helps reducing the dependencies - of the core hwloc library when distributed as a binary package. -* Backends - + Add CPUModel detection on Darwin and x86/FreeBSD. - Thanks to Robin Scher for providing ways to implement this. - + The x86 backend now adds CPUModel info attributes to socket objects - created by other backends that do not natively support this attribute. - + Fix detection on FreeBSD in case of cpuset restriction. Thanks to - Sebastian Kuzminsky for reporting the problem. -* XML - + Add hwloc_topology_set_userdata_import/export_callback(), - hwloc_export_obj_userdata() and _userdata_base64() to let - applications specify how to save/restore the custom data they placed - in the userdata private pointer field of hwloc objects. -* Tools - + Add hwloc-annotate program to add string info attributes to XML - topologies. - + Add --pid-cmd to hwloc-ps to append the output of a command to each - PID line. May be used for showing Open MPI process ranks, see the - hwloc-ps(1) manpage for details. - + hwloc-bind now exits with an error if binding fails; the executable - is not launched unless binding suceeeded or --force was given. - + Add --quiet to hwloc-calc and hwloc-bind to hide non-fatal error - messages. - + Fix command-line pid support in windows tools. - + All programs accept --verbose as a synonym to -v. -* Misc - + Fix some DIR descriptor leaks on Linux. - + Fix I/O device lists when some were filtered out after a XML import. - + Fix the removal of I/O objects when importing a I/O-enabled XML topology - without any I/O topology flag. - + When merging objects with HWLOC_IGNORE_TYPE_KEEP_STRUCTURE or - lstopo --merge, compare object types before deciding which one of two - identical object to remove (e.g. keep sockets in favor of caches). - + Add some GUID- and LID-related info attributes to OpenFabrics - OS devices. - + Only add CPUType socket attributes on Solaris/Sparc. Other cases - don't report reliable information (Solaris/x86), and a replacement - is available as the Architecture string info in the Machine object. - + Add missing Backend string info on Solaris in most cases. - + Document object attributes and string infos in a new Attributes - section in the documentation. - + Add a section about Synthetic topologies in the documentation. - - -Version 1.5.2 (some of these changes are in v1.6.2 but not in v1.6) -------------- -* Use libpciaccess instead of pciutils/libpci by default for I/O discovery. - pciutils/libpci is only used if --enable-libpci is given to configure - because its GPL license may taint hwloc. See the Installation section - in the documentation for details. -* Fix get_cpubind on Solaris when bound to a single PU with - processor_bind(). Thanks to Eugene Loh for reporting the problem - and providing a patch. -* Fix some DIR descriptor leaks on Linux. -* Fix I/O device lists when some were filtered out after a XML import. -* Add missing Backend string info on Solaris in most cases. -* Fix the removal of I/O objects when importing a I/O-enabled XML topology - without any I/O topology flag. -* Fix the output of hwloc-calc -H --hierarchical when using logical - indexes in the output. -* Fix the pkg-config output with --libs --static. - Thanks to Erik Schnetter for reporting one of the problems. - - -Version 1.5.1 -------------- -* Fix block OS device detection on Linux kernel 3.3 and later. - Thanks to Guy Streeter for reporting the problem and testing the fix. -* Fix the cpuid code in the x86 backend (for FreeBSD). Thanks to - Sebastian Kuzminsky for reporting problems and testing patches. -* Fix 64bit detection on FreeBSD. -* Fix some corner cases in the management of the thissystem flag with - respect to topology flags and environment variables. -* Fix some corner cases in command-line parsing checks in hwloc-distrib - and hwloc-distances. -* Make sure we do not miss some block OS devices on old Linux kernels - when a single PCI device has multiple IDE hosts/devices behind it. -* Do not disable I/O devices or instruction caches in hwloc-assembler output. - - -Version 1.5.0 -------------- -* Backends - + Do not limit the number of processors to 1024 on Solaris anymore. - + Gather total machine memory on FreeBSD. - + XML topology files do not depend on the locale anymore. Float numbers - such as NUMA distances or PCI link speeds now always use a dot as a - decimal separator. - + Add instruction caches detection on Linux, AIX, Windows and Darwin. - + Add get_last_cpu_location() support for the current thread on AIX. - + Support binding on AIX when threads or processes were bound with - bindprocessor(). Thanks to Hendryk Bockelmann for reporting the issue - and testing patches, and to Farid Parpia for explaining the binding - interfaces. - + Improve AMD topology detection in the x86 backend (for FreeBSD) using - the topoext feature. -* API - + Increase HWLOC_API_VERSION to 0x00010500 so that API changes may be - detected at build-time. - + Add a cache type attribute describind Data, Instruction and Unified - caches. Caches with different types but same depth (for instance L1d - and L1i) are placed on different levels. - + Add hwloc_get_cache_type_depth() to retrieve the hwloc level depth of - of the given cache depth and type, for instance L1i or L2. - It helps disambiguating the case where hwloc_get_type_depth() returns - HWLOC_TYPE_DEPTH_MULTIPLE. - + Instruction caches are ignored unless HWLOC_TOPOLOGY_FLAG_ICACHES is - passed to hwloc_topology_set_flags() before load. - + Add hwloc_ibv_get_device_osdev_by_name() OpenFabrics helper in - openfabrics-verbs.h to find the hwloc OS device object corresponding to - an OpenFabrics device. -* Tools - + Add lstopo-no-graphics, a lstopo built without graphical support to - avoid dependencies on external libraries such as Cairo and X11. When - supported, graphical outputs are only available in the original lstopo - program. - - Packagers splitting lstopo and lstopo-no-graphics into different - packages are advised to use the alternatives system so that lstopo - points to the best available binary. - + Instruction caches are enabled in lstopo by default. Use --no-icaches - to disable them. - + Add -t/--threads to show threads in hwloc-ps. -* Removal of obsolete components - + Remove the old cpuset interface (hwloc/cpuset.h) which is deprecated and - superseded by the bitmap API (hwloc/bitmap.h) since v1.1. - hwloc_cpuset and nodeset types are still defined, but all hwloc_cpuset_* - compatibility wrappers are now gone. - + Remove Linux libnuma conversion helpers for the deprecated and - broken nodemask_t interface. - + Remove support for "Proc" type name, it was superseded by "PU" in v1.0. - + Remove hwloc-mask symlinks, it was replaced by hwloc-calc in v1.0. -* Misc - + Fix PCIe 3.0 link speed computation. - + Non-printable characters are dropped from strings during XML export. - + Fix importing of escaped characters with the minimalistic XML backend. - + Assert hwloc_is_thissystem() in several I/O related helpers. - + Fix some memory leaks in the x86 backend for FreeBSD. - + Minor fixes to ease native builds on Windows. - + Limit the number of retries when operating on all threads within a - process on Linux if the list of threads is heavily getting modified. - - -Version 1.4.3 -------------- -* This release is only meant to fix the pciutils license issue when upgrading - to hwloc v1.5 or later is not possible. It contains several other minor - fixes but ignores many of them that are only in v1.5 or later. -* Use libpciaccess instead of pciutils/libpci by default for I/O discovery. - pciutils/libpci is only used if --enable-libpci is given to configure - because its GPL license may taint hwloc. See the Installation section - in the documentation for details. -* Fix PCIe 3.0 link speed computation. -* Fix importing of escaped characters with the minimalistic XML backend. -* Fix a memory leak in the x86 backend. - - -Version 1.4.2 -------------- -* Fix build on Solaris 9 and earlier when fabsf() is not a compiler - built-in. Thanks to Igor Galić for reporting the problem. -* Fix support for more than 32 processors on Windows. Thanks to Hartmut - Kaiser for reporting the problem. -* Fix process-wide binding and cpulocation routines on Linux when some - threads disappear in the meantime. Thanks to Vlad Roubtsov for reporting - the issue. -* Make installed scripts executable. Thanks to Jirka Hladky for reporting - the problem. -* Fix libtool revision management when building for Windows. This fix was - also released as hwloc v1.4.1.1 Windows builds. Thanks to Hartmut Kaiser - for reporting the problem. -* Fix the __hwloc_inline keyword in public headers when compiling with a - C++ compiler. -* Add Port info attribute to network OS devices inside OpenFabrics PCI - devices so as to identify which interface corresponds to which port. -* Document requirements for interoperability helpers: I/O devices discovery - is required for some of them; the topology must match the current host - for most of them. - - -Version 1.4.1 -------------- -* This release contains all changes from v1.3.2. -* Fix hwloc_alloc_membind, thanks Karl Napf for reporting the issue. -* Fix memory leaks in some get_membind() functions. -* Fix helpers converting from Linux libnuma to hwloc (hwloc/linux-libnuma.h) - in case of out-of-order NUMA node ids. -* Fix some overzealous assertions in the distance grouping code. -* Workaround BIOS reporting empty I/O locality in CUDA and OpenFabrics - helpers on Linux. Thanks to Albert Solernou for reporting the problem. -* Install a valgrind suppressions file hwloc-valgrind.supp (see the FAQ). -* Fix memory binding documentation. Thanks to Karl Napf for reporting the - issues. - - -Version 1.4.0 (does not contain all v1.3.2 changes) -------------- -* Major features - + Add "custom" interface and "assembler" tools to build multi-node - topology. See the Multi-node Topologies section in the documentation - for details. -* Interface improvements - + Add symmetric_subtree object attribute to ease assumptions when consulting - regular symmetric topologies. - + Add a CPUModel and CPUType info attribute to Socket objects on Linux - and Solaris. - + Add hwloc_get_obj_index_inside_cpuset() to retrieve the "logical" index - of an object within a subtree of the topology. - + Add more NVIDIA CUDA helpers in cuda.h and cudart.h to find hwloc objects - corresponding to CUDA devices. -* Discovery improvements - + Add a group object above partial distance matrices to make sure - the matrices are available in the final topology, except when this - new object would contradict the existing hierarchy. - + Grouping by distances now also works when loading from XML. - + Fix some corner cases in object insertion, for instance when dealing - with NUMA nodes without any CPU. -* Backends - + Implement hwloc_get_area_membind() on Linux. - + Honor I/O topology flags when importing from XML. - + Further improve XML-related error checking and reporting. - + Hide synthetic topology error messages unless HWLOC_SYNTHETIC_VERBOSE=1. -* Tools - + Add synthetic exporting of symmetric topologies to lstopo. - + lstopo --horiz and --vert can now be applied to some specific object types. - + lstopo -v -p now displays distance matrices with physical indexes. - + Add hwloc-distances utility to list distances. -* Documentation - + Fix and/or document the behavior of most inline functions in hwloc/helper.h - when the topology contains some I/O or Misc objects. - + Backend documentation enhancements. -* Bug fixes - + Fix missing last bit in hwloc_linux_get_thread_cpubind(). - Thanks to Carolina Gómez-Tostón Gutiérrez for reporting the issue. - + Fix FreeBSD build without cpuid support. - + Fix several Windows build issues. - + Fix inline keyword definition in public headers. - + Fix dependencies in the embedded library. - + Improve visibility support detection. Thanks to Dave Love for providing - the patch. - + Remove references to internal symbols in the tools. - - -Version 1.3.3 -------------- -* This release is only meant to fix the pciutils license issue when upgrading - to hwloc v1.4 or later is not possible. It contains several other minor - fixes but ignores many of them that are only in v1.4 or later. -* Use libpciaccess instead of pciutils/libpci by default for I/O discovery. - pciutils/libpci is only used if --enable-libpci is given to configure - because its GPL license may taint hwloc. See the Installation section - in the documentation for details. - - -Version 1.3.2 -------------- -* Fix missing last bit in hwloc_linux_get_thread_cpubind(). - Thanks to Carolina Gómez-Tostón Gutiérrez for reporting the issue. -* Fix build with -mcmodel=medium. Thanks to Devendar Bureddy for reporting - the issue. -* Fix build with Solaris Studio 12 compiler when XML is disabled. - Thanks to Paul H. Hargrove for reporting the problem. -* Fix installation with old GNU sed, for instance on Red Hat 8. - Thanks to Paul H. Hargrove for reporting the problem. -* Fix PCI locality when Linux cgroups restrict the available CPUs. -* Fix floating point issue when grouping by distance on mips64 architecture. - Thanks to Paul H. Hargrove for reporting the problem. -* Fix conversion from/to Linux libnuma when some NUMA nodes have no memory. -* Fix support for gccfss compilers with broken ffs() support. Thanks to - Paul H. Hargrove for reporting the problem and providing a patch. -* Fix FreeBSD build without cpuid support. -* Fix several Windows build issues. -* Fix inline keyword definition in public headers. -* Fix dependencies in the embedded library. -* Detect when a compiler such as xlc may not report compile errors - properly, causing some configure checks to be wrong. Thanks to - Paul H. Hargrove for reporting the problem and providing a patch. -* Improve visibility support detection. Thanks to Dave Love for providing - the patch. -* Remove references to internal symbols in the tools. -* Fix installation on systems with limited command-line size. - Thanks to Paul H. Hargrove for reporting the problem. -* Further improve XML-related error checking and reporting. - - -Version 1.3.1 -------------- -* Fix pciutils detection with pkg-config when not installed in standard - directories. -* Fix visibility options detection with the Solaris Studio compiler. - Thanks to Igor Galić and Terry Dontje for reporting the problems. -* Fix support for old Linux sched.h headers such as those found - on Red Hat 8. Thanks to Paul H. Hargrove for reporting the problems. -* Fix inline and attribute support for Solaris compilers. Thanks to - Dave Love for reporting the problems. -* Print a short summary at the end of the configure output. Thanks to - Stefan Eilemann for the suggestion. -* Add --disable-libnuma configure option to disable libnuma-based - memory binding support on Linux. Thanks to Rayson Ho for the - suggestion. -* Make hwloc's configure script properly obey $PKG_CONFIG. Thanks to - Nathan Phillip Brink for raising the issue. -* Silence some harmless pciutils warnings, thanks to Paul H. Hargrove - for reporting the problem. -* Fix the documentation with respect to hwloc_pid_t and hwloc_thread_t - being either pid_t and pthread_t on Unix, or HANDLE on Windows. - - -Version 1.3.0 -------------- -* Major features - + Add I/O devices and bridges to the topology using the pciutils - library. Only enabled after setting the relevant flag with - hwloc_topology_set_flags() before hwloc_topology_load(). See the - I/O Devices section in the documentation for details. -* Discovery improvements - + Add associativity to the cache attributes. - + Add support for s390/z11 "books" on Linux. - + Add the HWLOC_GROUPING_ACCURACY environment variable to relax - distance-based grouping constraints. See the Environment Variables - section in the documentation for details about grouping behavior - and configuration. - + Allow user-given distance matrices to remove or replace those - discovered by the OS backend. -* XML improvements - + XML is now always supported: a minimalistic custom import/export - code is used when libxml2 is not available. It is only guaranteed - to read XML files generated by hwloc. - + hwloc_topology_export_xml() and export_xmlbuffer() now return an - integer. - + Add hwloc_free_xmlbuffer() to free the buffer allocated by - hwloc_topology_export_xmlbuffer(). - + Hide XML topology error messages unless HWLOC_XML_VERBOSE=1. -* Minor API updates - + Add hwloc_obj_add_info to customize object info attributes. -* Tools - + lstopo now displays I/O devices by default. Several options are - added to configure the I/O discovery. - + hwloc-calc and hwloc-bind now accept I/O devices as input. - + Add --restrict option to hwloc-calc and hwloc-distribute. - + Add --sep option to change the output field separator in hwloc-calc. - + Add --whole-system option to hwloc-ps. - - -Version 1.2.2 -------------- -* Fix build on AIX 5.2, thanks Utpal Kumar Ray for the report. -* Fix XML import of very large page sizes or counts on 32bits platform, - thanks to Karsten Hopp for the RedHat ticket. -* Fix crash when administrator limitations such as Linux cgroup require - to restrict distance matrices. Thanks to Ake Sandgren for reporting the - problem. -* Fix the removal of objects such as AMD Magny-Cours dual-node sockets - in case of administrator restrictions. -* Improve error reporting and messages in case of wrong synthetic topology - description. -* Several other minor internal fixes and documentation improvements. - - -Version 1.2.1 -------------- -* Improve support of AMD Bulldozer "Compute-Unit" modules by detecting - logical processors with different core IDs on Linux. -* Fix hwloc-ps crash when listing processes from another Linux cpuset. - Thanks to Carl Smith for reporting the problem. -* Fix build on AIX and Solaris. Thanks to Carl Smith and Andreas Kupries - for reporting the problems. -* Fix cache size detection on Darwin. Thanks to Erkcan Özcan for reporting - the problem. -* Make configure fail if --enable-xml or --enable-cairo is given and - proper support cannot be found. Thanks to Andreas Kupries for reporting - the XML problem. -* Fix spurious L1 cache detection on AIX. Thanks to Hendryk Bockelmann - for reporting the problem. -* Fix hwloc_get_last_cpu_location(THREAD) on Linux. Thanks to Gabriele - Fatigati for reporting the problem. -* Fix object distance detection on Solaris. -* Add pthread_self weak symbol to ease static linking. -* Minor documentation fixes. - - -Version 1.2.0 -------------- -* Major features - + Expose latency matrices in the API as an array of distance structures - within objects. Add several helpers to find distances. - + Add hwloc_topology_set_distance_matrix() and environment variables - to provide a matrix of distances between a given set of objects. - + Add hwloc_get_last_cpu_location() and hwloc_get_proc_last_cpu_location() - to retrieve the processors where a process or thread recently ran. - - Add the corresponding --get-last-cpu-location option to hwloc-bind. - + Add hwloc_topology_restrict() to restrict an existing topology to a - given cpuset. - - Add the corresponding --restrict option to lstopo. -* Minor API updates - + Add hwloc_bitmap_list_sscanf/snprintf/asprintf to convert between bitmaps - and strings such as 4-5,7-9,12,15- - + hwloc_bitmap_set/clr_range() now support infinite ranges. - + Clarify the difference between inserting Misc objects by cpuset or by - parent. - + hwloc_insert_misc_object_by_cpuset() now returns NULL in case of error. -* Discovery improvements - + x86 backend (for freebsd): add x2APIC support - + Support standard device-tree phandle, to get better support on e.g. ARM - systems providing it. - + Detect cache size on AIX. Thanks Christopher and IBM. - + Improve grouping to support asymmetric topologies. -* Tools - + Command-line tools now support "all" and "root" special locations - consisting in the entire topology, as well as type names with depth - attributes such as L2 or Group4. - + hwloc-calc improvements: - - Add --number-of/-N option to report the number of objects of a given - type or depth. - - -I is now equivalent to --intersect for listing the indexes of - objects of a given type or depth that intersects the input. - - Add -H to report the output as a hierarchical combination of types - and depths. - + Add --thissystem to lstopo. - + Add lstopo-win, a console-less lstopo variant on Windows. -* Miscellaneous - + Remove C99 usage from code base. - + Rename hwloc-gather-topology.sh into hwloc-gather-topology - + Fix AMD cache discovery on freebsd when there is no L3 cache, thanks - Andriy Gapon for the fix. - - -Version 1.1.2 -------------- -* Fix a segfault in the distance-based grouping code when some objects - are not placed in any group. Thanks to Bernd Kallies for reporting - the problem and providing a patch. -* Fix the command-line parsing of hwloc-bind --mempolicy interleave. - Thanks to Guy Streeter for reporting the problem. -* Stop truncating the output in hwloc_obj_attr_snprintf() and in the - corresponding lstopo output. Thanks to Guy Streeter for reporting the - problem. -* Fix object levels ordering in synthetic topologies. -* Fix potential incoherency between device tree and kernel information, - when SMT is disabled on Power machines. -* Fix and document the behavior of hwloc_topology_set_synthetic() in case - of invalid argument. Thanks to Guy Streeter for reporting the problem. -* Add some verbose error message reporting when it looks like the OS - gives erroneous information. -* Do not include unistd.h and stdint.h in public headers on Windows. -* Move config.h files into their own subdirectories to avoid name - conflicts when AC_CONFIG_HEADERS adds -I's for them. -* Remove the use of declaring variables inside "for" loops. -* Some other minor fixes. -* Many minor documentation fixes. - - -Version 1.1.1 -------------- -* Add hwloc_get_api_version() which returns the version of hwloc used - at runtime. Thanks to Guy Streeter for the suggestion. -* Fix the number of hugepages reported for NUMA nodes on Linux. -* Fix hwloc_bitmap_to_ulong() right after allocating the bitmap. - Thanks to Bernd Kallies for reporting the problem. -* Fix hwloc_bitmap_from_ith_ulong() to properly zero the first ulong. - Thanks to Guy Streeter for reporting the problem. -* Fix hwloc_get_membind_nodeset() on Linux. - Thanks to Bernd Kallies for reporting the problem and providing a patch. -* Fix some file descriptor leaks in the Linux discovery. -* Fix the minimum width of NUMA nodes, caches and the legend in the graphical - lstopo output. Thanks to Jirka Hladky for reporting the problem. -* Various fixes to bitmap conversion from/to taskset-strings. -* Fix and document snprintf functions behavior when the buffer size is too - small or zero. Thanks to Guy Streeter for reporting the problem. -* Fix configure to avoid spurious enabling of the cpuid backend. - Thanks to Tim Anderson for reporting the problem. -* Cleanup error management in hwloc-gather-topology.sh. - Thanks to Jirka Hladky for reporting the problem and providing a patch. -* Add a manpage and usage for hwloc-gather-topology.sh on Linux. - Thanks to Jirka Hladky for providing a patch. -* Memory binding documentation enhancements. - - -Version 1.1.0 -------------- - -* API - + Increase HWLOC_API_VERSION to 0x00010100 so that API changes may be - detected at build-time. - + Add a memory binding interface. - + The cpuset API (hwloc/cpuset.h) is now deprecated. It is replaced by - the bitmap API (hwloc/bitmap.h) which offers the same features with more - generic names since it applies to CPU sets, node sets and more. - Backward compatibility with the cpuset API and ABI is still provided but - it will be removed in a future release. - Old types (hwloc_cpuset_t, ...) are still available as a way to clarify - what kind of hwloc_bitmap_t each API function manipulates. - Upgrading to the new API only requires to replace hwloc_cpuset_ function - calls with the corresponding hwloc_bitmap_ calls, with the following - renaming exceptions: - - hwloc_cpuset_cpu -> hwloc_bitmap_only - - hwloc_cpuset_all_but_cpu -> hwloc_bitmap_allbut - - hwloc_cpuset_from_string -> hwloc_bitmap_sscanf - + Add an `infos' array in each object to store couples of info names and - values. It enables generic storage of things like the old dmi board infos - that were previously stored in machine specific attributes. - + Add linesize cache attribute. -* Features - + Bitmaps (and thus CPU sets and node sets) are dynamically (re-)allocated, - the maximal number of CPUs (HWLOC_NBMAXCPUS) has been removed. - + Improve the distance-based grouping code to better support irregular - distance matrices. - + Add support for device-tree to get cache information (useful on Power - architectures). -* Helpers - + Add NVIDIA CUDA helpers in cuda.h and cudart.h to ease interoperability - with CUDA Runtime and Driver APIs. - + Add Myrinet Express helper in myriexpress.h to ease interoperability. -* Tools - + lstopo now displays physical/OS indexes by default in graphical mode - (use -l to switch back to logical indexes). The textual output still uses - logical by default (use -p to switch to physical indexes). - + lstopo prefixes logical indexes with `L#' and physical indexes with `P#'. - Physical indexes are also printed as `P#N' instead of `phys=N' within - object attributes (in parentheses). - + Add a legend at the bottom of the lstopo graphical output, use --no-legend - to remove it. - + Add hwloc-ps to list process' bindings. - + Add --membind and --mempolicy options to hwloc-bind. - + Improve tools command-line options by adding a generic --input option - (and more) which replaces the old --xml, --synthetic and --fsys-root. - + Cleanup lstopo output configuration by adding --output-format. - + Add --intersect in hwloc-calc, and replace --objects with --largest. - + Add the ability to work on standard input in hwloc-calc. - + Add --from, --to and --at in hwloc-distrib. - + Add taskset-specific functions and command-line tools options to - manipulate CPU set strings in the format of the taskset program. - + Install hwloc-gather-topology.sh on Linux. - - -Version 1.0.3 -------------- - -* Fix support for Linux cpuset when emulated by a cgroup mount point. -* Remove unneeded runtime dependency on libibverbs.so in the library and - all utils programs. -* Fix hwloc_cpuset_to_linux_libnuma_ulongs in case of non-linear OS-indexes - for NUMA nodes. -* lstopo now displays physical/OS indexes by default in graphical mode - (use -l to switch back to logical indexes). The textual output still uses - logical by default (use -p to switch to physical indexes). - - -Version 1.0.2 -------------- - -* Public headers can now be included directly from C++ programs. -* Solaris fix for non-contiguous cpu numbers. Thanks to Rolf vandeVaart for - reporting the issue. -* Darwin 10.4 fix. Thanks to Olivier Cessenat for reporting the issue. -* Revert 1.0.1 patch that ignored sockets with unknown ID values since it - only slightly helped POWER7 machines with old Linux kernels while it - prevents recent kernels from getting the complete POWER7 topology. -* Fix hwloc_get_common_ancestor_obj(). -* Remove arch-specific bits in public headers. -* Some fixes in the lstopo graphical output. -* Various man page clarifications and minor updates. - - -Version 1.0.1 -------------- - -* Various Solaris fixes. Thanks to Yannick Martin for reporting the issue. -* Fix "non-native" builds on x86 platforms (e.g., when building 32 - bit executables with compilers that natively build 64 bit). -* Ignore sockets with unknown ID values (which fixes issues on POWER7 - machines). Thanks to Greg Bauer for reporting the issue. -* Various man page clarifications and minor updates. -* Fixed memory leaks in hwloc_setup_group_from_min_distance_clique(). -* Fix cache type filtering on MS Windows 7. Thanks to Αλέξανδρος - Παπαδογιαννάκ for reporting the issue. -* Fixed warnings when compiling with -DNDEBUG. - - -Version 1.0.0 -------------- - -* The ABI of the library has changed. -* Backend updates - + Add FreeBSD support. - + Add x86 cpuid based backend. - + Add Linux cgroup support to the Linux cpuset code. - + Support binding of entire multithreaded process on Linux. - + Fix and enable Group support in Windows. - + Cleanup XML export/import. -* Objects - + HWLOC_OBJ_PROC is renamed into HWLOC_OBJ_PU for "Processing Unit", - its stringified type name is now "PU". - + Use new HWLOC_OBJ_GROUP objects instead of MISC when grouping - objects according to NUMA distances or arbitrary OS aggregation. - + Rework memory attributes. - + Add different cpusets in each object to specify processors that - are offline, unavailable, ... - + Cleanup the storage of object names and DMI infos. -* Features - + Add support for looking up specific PID topology information. - + Add hwloc_topology_export_xml() to export the topology in a XML file. - + Add hwloc_topology_get_support() to retrieve the supported features - for the current topology context. - + Support non-SYSTEM object as the root of the tree, use MACHINE in - most common cases. - + Add hwloc_get_*cpubind() routines to retrieve the current binding - of processes and threads. -* API - + Add HWLOC_API_VERSION to help detect the currently used API version. - + Add missing ending "e" to *compare* functions. - + Add several routines to emulate PLPA functions. - + Rename and rework the cpuset and/or/xor/not/clear operators to output - their result in a dedicated argument instead of modifying one input. - + Deprecate hwloc_obj_snprintf() in favor of hwloc_obj_type/attr_snprintf(). - + Clarify the use of parent and ancestor in the API, do not use father. - + Replace hwloc_get_system_obj() with hwloc_get_root_obj(). - + Return -1 instead of HWLOC_OBJ_TYPE_MAX in the API since the latter - isn't public. - + Relax constraints in hwloc_obj_type_of_string(). - + Improve displaying of memory sizes. - + Add 0x prefix to cpuset strings. -* Tools - + lstopo now displays logical indexes by default, use --physical to - revert back to OS/physical indexes. - + Add colors in the lstopo graphical outputs to distinguish between online, - offline, reserved, ... objects. - + Extend lstopo to show cpusets, filter objects by type, ... - + Renamed hwloc-mask into hwloc-calc which supports many new options. -* Documentation - + Add a hwloc(7) manpage containing general information. - + Add documentation about how to switch from PLPA to hwloc. - + Cleanup the distributed documentation files. -* Miscellaneous - + Many compilers warning fixes. - + Cleanup the ABI by using the visibility attribute. - + Add project embedding support. - - -Version 0.9.4 (unreleased) --------------------------- - -* Fix reseting colors to normal in lstopo -.txt output. -* Fix Linux pthread_t binding error report. - - -Version 0.9.3 -------------- - -* Fix autogen.sh to work with Autoconf 2.63. -* Fix various crashes in particular conditions: - - xml files with root attributes - - offline CPUs - - partial sysfs support - - unparseable /proc/cpuinfo - - ignoring NUMA level while Misc level have been generated -* Tweak documentation a bit -* Do not require the pthread library for binding the current thread on Linux -* Do not erroneously consider the sched_setaffinity prototype is the old version - when there is actually none. -* Fix _syscall3 compilation on archs for which we do not have the - sched_setaffinity system call number. -* Fix AIX binding. -* Fix libraries dependencies: now only lstopo depends on libtermcap, fix - binutils-gold link -* Have make check always build and run hwloc-hello.c -* Do not limit size of a cpuset. - - -Version 0.9.2 -------------- - -* Trivial documentation changes. - - -Version 0.9.1 -------------- - -* Re-branded to "hwloc" and moved to the Open MPI project, relicensed under the - BSD license. -* The prefix of all functions and tools is now hwloc, and some public - functions were also renamed for real. -* Group NUMA nodes into Misc objects according to their physical distance - that may be reported by the OS/BIOS. - May be ignored by setting HWLOC_IGNORE_DISTANCES=1 in the environment. -* Ignore offline CPUs on Solaris. -* Improved binding support on AIX. -* Add HP-UX support. -* CPU sets are now allocated/freed dynamically. -* Add command line options to tune the lstopo graphical output, add - semi-graphical textual output -* Extend topobind to support multiple cpusets or objects on the command - line as topomask does. -* Add an Infiniband-specific helper hwloc/openfabrics-verbs.h to retrieve - the physical location of IB devices. - - -Version 0.9 (libtopology) -------------------------- - -* First release. diff --git a/opal/mca/hwloc/hwloc191/hwloc/README b/opal/mca/hwloc/hwloc191/hwloc/README deleted file mode 100644 index babe22d4ff..0000000000 --- a/opal/mca/hwloc/hwloc191/hwloc/README +++ /dev/null @@ -1,720 +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 -sockets, 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. - -Note that the hwloc project represents the merger of the libtopology project -from inria and the Portable Linux Processor Affinity (PLPA) sub-project from -Open MPI. Both of these prior projects are now deprecated. The first hwloc -release was essentially a "re-branding" of the libtopology code base, but with -both a few genuinely new features and a few PLPA-like features added in. Prior -releases of hwloc included documentation about switching from PLPA to hwloc; -this documentation has been dropped on the assumption that everyone who was -using PLPA has already switched to hwloc. - -hwloc supports the following operating systems: - - * Linux (including old kernels not having sysfs topology information, with - knowledge of cpusets, offline CPUs, ScaleMP vSMP, NumaScale NumaConnect, - and Kerrighed support) - * 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 - * Remote machine simulation through the gathering of Linux sysfs topology - 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 CLI 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). - -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 checked out of Subversion: - -shell$ git clone https://github.com/open-mpi/hwloc.git -shell$ cd hwloc -shell$ ./autogen.sh - -Note that GNU Autoconf >=2.63, Automake >=1.10 and Libtool >=2.2.6 are required -when building from a Subversion checkout. - -Installation by itself is the fairly common GNU-based process: - -shell$ ./configure --prefix=... -shell$ make -shell$ make install - -The hwloc command-line tool "lstopo" produces human-readable topology maps, as -mentioned above. It can also export maps to the "fig" file format. Support for -PDF, Postscript, and PNG exporting is provided if the "Cairo" development -package (usually cairo-devel or libcairo2-dev) can be found in "lstopo" when -hwloc is configured and build. - -The hwloc core may also benefit from the following development packages: - - * libnuma for memory binding and migration support on Linux (numactl-devel or - libnuma-dev package). - * hwloc can use one of two different libraries for full I/O device discovery: - - 1. libpciaccess (BSD). The relevant development package is usually - libpciaccess-devel or libpciaccess-dev. - 2. libpci, from the pciutils package (GPL). The relevant development - package is usually pciutils-devel or libpci-dev. - - On Linux, PCI discovery may still be performed even if none of the above - libraries can be used. - - * the AMD OpenCL implementation for OpenCL device discovery. - * the NVIDIA CUDA Toolkit for CUDA device discovery. - * the NVIDIA Tesla Development Kit for NVML device discovery. - * the NV-CONTROL X extension library (NVCtrl) for NVIDIA display discovery. - * libxml2 for full XML import/export support (otherwise, the internal - minimalistic parser will only be able to import XML files that were - exported by the same hwloc release). See Importing and exporting topologies - from/to XML files for details. The relevant development package is usually - libxml2-devel or libxml2-dev. - * libtool's ltdl library for dynamic plugin loading. The relevant development - package is usually libtool-ltdl-devel or libltdl-dev. - -PCI and XML support may be statically built inside the main hwloc library, or -as separate dynamically-loaded plugins (see the Components and plugins -section). - -Note that because of the possibility of GPL taint (remember that hwloc is -BSD-licensed), hwloc's configure script will prefer libpciaccess to the -pciutils package. Indeed, if libpciaccess is not found, hwloc will not use -pciutils unless it is specifically requested via the --enable-libpci flag is -provided. - -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 ... - -CLI Examples - -On a 4-socket 2-core machine with hyperthreading, the lstopo tool may show the -following graphical output: - -dudley.png - -Here's the equivalent output in textual form: - -Machine (16GB) - Socket L#0 + L3 L#0 (4096KB) - L2 L#0 (1024KB) + L1 L#0 (16KB) + Core L#0 - PU L#0 (P#0) - PU L#1 (P#8) - L2 L#1 (1024KB) + L1 L#1 (16KB) + Core L#1 - PU L#2 (P#4) - PU L#3 (P#12) - Socket L#1 + L3 L#1 (4096KB) - L2 L#2 (1024KB) + L1 L#2 (16KB) + Core L#2 - PU L#4 (P#1) - PU L#5 (P#9) - L2 L#3 (1024KB) + L1 L#3 (16KB) + Core L#3 - PU L#6 (P#5) - PU L#7 (P#13) - Socket L#2 + L3 L#2 (4096KB) - L2 L#4 (1024KB) + L1 L#4 (16KB) + Core L#4 - PU L#8 (P#2) - PU L#9 (P#10) - L2 L#5 (1024KB) + L1 L#5 (16KB) + Core L#5 - PU L#10 (P#6) - PU L#11 (P#14) - Socket L#3 + L3 L#3 (4096KB) - L2 L#6 (1024KB) + L1 L#6 (16KB) + Core L#6 - PU L#12 (P#3) - PU L#13 (P#11) - L2 L#7 (1024KB) + L1 L#7 (16KB) + Core L#7 - PU L#14 (P#7) - PU L#15 (P#15) - -Finally, here's the equivalent output in XML. Long lines were artificially -broken for document clarity (in the real output, each XML tag is on a single -line), and only socket #0 is shown for brevity: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -On a 4-socket 2-core Opteron NUMA machine, the lstopo tool may show the -following graphical output: - -hagrid.png - -Here's the equivalent output in textual form: - -Machine (32GB) - NUMANode L#0 (P#0 8190MB) + Socket L#0 - L2 L#0 (1024KB) + L1 L#0 (64KB) + Core L#0 + PU L#0 (P#0) - L2 L#1 (1024KB) + L1 L#1 (64KB) + Core L#1 + PU L#1 (P#1) - NUMANode L#1 (P#1 8192MB) + Socket L#1 - L2 L#2 (1024KB) + L1 L#2 (64KB) + Core L#2 + PU L#2 (P#2) - L2 L#3 (1024KB) + L1 L#3 (64KB) + Core L#3 + PU L#3 (P#3) - NUMANode L#2 (P#2 8192MB) + Socket L#2 - L2 L#4 (1024KB) + L1 L#4 (64KB) + Core L#4 + PU L#4 (P#4) - L2 L#5 (1024KB) + L1 L#5 (64KB) + Core L#5 + PU L#5 (P#5) - NUMANode L#3 (P#3 8192MB) + Socket L#3 - L2 L#6 (1024KB) + L1 L#6 (64KB) + Core L#6 + PU L#6 (P#6) - L2 L#7 (1024KB) + L1 L#7 (64KB) + Core L#7 + PU L#7 (P#7) - -And here's the equivalent output in XML. Similar to above, line breaks were -added and only PU #0 is shown for brevity: - - - - - - - - - - - - - - - - - - - - - -On a 2-socket quad-core Xeon (pre-Nehalem, with 2 dual-core dies into each -socket): - -emmett.png - -Here's the same output in textual form: - -Machine (16GB) - Socket L#0 - L2 L#0 (4096KB) - L1 L#0 (32KB) + Core L#0 + PU L#0 (P#0) - L1 L#1 (32KB) + Core L#1 + PU L#1 (P#4) - L2 L#1 (4096KB) - L1 L#2 (32KB) + Core L#2 + PU L#2 (P#2) - L1 L#3 (32KB) + Core L#3 + PU L#3 (P#6) - Socket L#1 - L2 L#2 (4096KB) - L1 L#4 (32KB) + Core L#4 + PU L#4 (P#1) - L1 L#5 (32KB) + Core L#5 + PU L#5 (P#5) - L2 L#3 (4096KB) - L1 L#6 (32KB) + Core L#6 + PU L#6 (P#3) - L1 L#7 (32KB) + Core L#7 + PU L#7 (P#7) - -And the same output in XML (line breaks added, only PU #0 shown): - - - - - - - - - - - - - - - - - - - - - - - -Programming Interface - -The basic interface is available in hwloc.h. Some higher-level functions are -available in hwloc/helper.h to reduce the need to manually manipulate objects -and follow links between them. Documentation for all these is provided later in -this document. Developers may also want to look at hwloc/inlines.h which -contains the actual inline code of some hwloc.h routines, and at this document, -which provides good higher-level topology traversal examples. - -To precisely define the vocabulary used by hwloc, a Terms and Definitions -section is available and should probably be read first. - -Each hwloc object contains a cpuset describing the list of processing units -that it contains. These bitmaps may be used for CPU binding and Memory binding. -hwloc offers an extensive bitmap manipulation interface in hwloc/bitmap.h. - -Moreover, hwloc also comes with additional helpers for interoperability with -several commonly used environments. See the Interoperability With Other -Software section for details. - -The complete API documentation is available in a full set of HTML pages, man -pages, and self-contained PDF files (formatted for both both US letter and A4 -formats) in the source tarball in doc/doxygen-doc/. - -NOTE: If you are building the documentation from a Subversion checkout, you -will need to have Doxygen and pdflatex installed -- the documentation will be -built during the normal "make" process. The documentation is installed during -"make install" to $prefix/share/doc/hwloc/ and your systems default man page -tree (under $prefix, of course). - -Portability - -As shown in CLI Examples, hwloc can obtain information on a wide variety of -hardware topologies. However, some platforms and/or operating system versions -will only report a subset of this information. For example, on an PPC64-based -system with 32 cores (each with 2 hardware threads) running a default -2.6.18-based kernel from RHEL 5.4, hwloc is only able to glean information -about NUMA nodes and processor units (PUs). No information about caches, -sockets, or cores is available. - -Similarly, Operating System have varying support for CPU and memory binding, -e.g. while some Operating Systems provide interfaces for all kinds of CPU and -memory bindings, some others provide only interfaces for a limited number of -kinds of CPU and memory binding, and some do not provide any binding interface -at all. Hwloc's binding functions would then simply return the ENOSYS error -(Function not implemented), meaning that the underlying Operating System does -not provide any interface for them. CPU binding and Memory binding provide more -information on which hwloc binding functions should be preferred because -interfaces for them are usually available on the supported Operating Systems. - -Here's the graphical output from lstopo on this platform when Simultaneous -Multi-Threading (SMT) is enabled: - -ppc64-with-smt.png - -And here's the graphical output from lstopo on this platform when SMT is -disabled: - -ppc64-without-smt.png - -Notice that hwloc only sees half the PUs when SMT is disabled. PU #15, for -example, seems to change location from NUMA node #0 to #1. In reality, no PUs -"moved" -- they were simply re-numbered when hwloc only saw half as many. -Hence, PU #15 in the SMT-disabled picture probably corresponds to PU #30 in the -SMT-enabled picture. - -This same "PUs have disappeared" effect can be seen on other platforms -- even -platforms / OSs that provide much more information than the above PPC64 system. -This is an unfortunate side-effect of how operating systems report information -to hwloc. - -Note that upgrading the Linux kernel on the same PPC64 system mentioned above -to 2.6.34, hwloc is able to discover all the topology information. The -following picture shows the entire topology layout when SMT is enabled: - -ppc64-full-with-smt.png - -Developers using the hwloc API or XML output for portable applications should -therefore be extremely careful to not make any assumptions about the structure -of data that is returned. For example, per the above reported PPC topology, it -is not safe to assume that PUs will always be descendants of cores. - -Additionally, future hardware may insert new topology elements that are not -available in this version of hwloc. Long-lived applications that are meant to -span multiple different hardware platforms should also be careful about making -structure assumptions. For example, there may someday be an element "lower" -than a PU, or perhaps a new element may exist between a core and a PU. - -API Example - -The following small C example (named ``hwloc-hello.c'') prints the topology of -the machine and bring the process to the first logical processor of the second -core of the machine. - -/* Example hwloc API program. - * - * Copyright (c) 2009-2010 inria. All rights reserved. - * Copyright (c) 2009-2011 Universit?eacute; Bordeaux 1 - * Copyright (c) 2009-2010 Cisco Systems, Inc. All rights reserved. - * See COPYING in top-level directory. - * - * hwloc-hello.c - */ - -#include -#include -#include -#include - -static void print_children(hwloc_topology_t topology, hwloc_obj_t obj, - int depth) -{ - char string[128]; - unsigned i; - - hwloc_obj_snprintf(string, sizeof(string), topology, obj, "#", 0); - printf("%*s%s\n", 2*depth, "", string); - for (i = 0; i < obj->arity; i++) { - print_children(topology, obj->children[i], depth + 1); - } -} - -int main(void) -{ - int depth; - unsigned i, n; - unsigned long size; - int levels; - char string[128]; - int topodepth; - hwloc_topology_t topology; - hwloc_cpuset_t cpuset; - hwloc_obj_t obj; - - /* Allocate and initialize topology object. */ - hwloc_topology_init(&topology); - - /* ... Optionally, put detection configuration here to ignore - some objects types, define a synthetic topology, etc.... - - The default is to detect all the objects of the machine that - the caller is allowed to access. See Configure Topology - Detection. */ - - /* Perform the topology detection. */ - hwloc_topology_load(topology); - - /* Optionally, get some additional topology information - in case we need the topology depth later. */ - topodepth = hwloc_topology_get_depth(topology); - - /***************************************************************** - * First example: - * Walk the topology with an array style, from level 0 (always - * the system level) to the lowest level (always the proc level). - *****************************************************************/ - for (depth = 0; depth < topodepth; depth++) { - printf("*** Objects at level %d\n", depth); - for (i = 0; i < hwloc_get_nbobjs_by_depth(topology, depth); - i++) { - hwloc_obj_snprintf(string, sizeof(string), topology, - hwloc_get_obj_by_depth(topology, depth, i), - "#", 0); - printf("Index %u: %s\n", i, string); - } - } - - /***************************************************************** - * Second example: - * Walk the topology with a tree style. - *****************************************************************/ - printf("*** Printing overall tree\n"); - print_children(topology, hwloc_get_root_obj(topology), 0); - - /***************************************************************** - * Third example: - * Print the number of sockets. - *****************************************************************/ - depth = hwloc_get_type_depth(topology, HWLOC_OBJ_SOCKET); - if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) { - printf("*** The number of sockets is unknown\n"); - } else { - printf("*** %u socket(s)\n", - hwloc_get_nbobjs_by_depth(topology, depth)); - } - - /***************************************************************** - * Fourth example: - * Compute the amount of cache that the first logical processor - * has above it. - *****************************************************************/ - levels = 0; - size = 0; - for (obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PU, 0); - obj; - obj = obj->parent) - if (obj->type == HWLOC_OBJ_CACHE) { - levels++; - size += obj->attr->cache.size; - } - printf("*** Logical processor 0 has %d caches totaling %luKB\n", - levels, size / 1024); - - /***************************************************************** - * Fifth example: - * Bind to only one thread of the last core of the machine. - * - * First find out where cores are, or else smaller sets of CPUs if - * the OS doesn't have the notion of a "core". - *****************************************************************/ - depth = hwloc_get_type_or_below_depth(topology, HWLOC_OBJ_CORE); - - /* Get last core. */ - obj = hwloc_get_obj_by_depth(topology, depth, - hwloc_get_nbobjs_by_depth(topology, depth) - 1); - if (obj) { - /* Get a copy of its cpuset that we may modify. */ - cpuset = hwloc_bitmap_dup(obj->cpuset); - - /* Get only one logical processor (in case the core is - SMT/hyperthreaded). */ - hwloc_bitmap_singlify(cpuset); - - /* And try to bind ourself there. */ - if (hwloc_set_cpubind(topology, cpuset, 0)) { - char *str; - int error = errno; - hwloc_bitmap_asprintf(&str, obj->cpuset); - printf("Couldn't bind to cpuset %s: %s\n", str, strerror(error)); - free(str); - } - - /* Free our cpuset copy */ - hwloc_bitmap_free(cpuset); - } - - /***************************************************************** - * Sixth example: - * Allocate some memory on the last NUMA node, bind some existing - * memory to the last NUMA node. - *****************************************************************/ - /* Get last node. */ - n = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_NODE); - if (n) { - void *m; - size = 1024*1024; - - obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_NODE, n - 1); - m = hwloc_alloc_membind_nodeset(topology, size, obj->nodeset, - HWLOC_MEMBIND_DEFAULT, 0); - hwloc_free(topology, m, size); - - m = malloc(size); - hwloc_set_area_membind_nodeset(topology, m, size, obj->nodeset, - HWLOC_MEMBIND_DEFAULT, 0); - free(m); - } - - /* Destroy topology object. */ - hwloc_topology_destroy(topology); - - return 0; -} - -hwloc provides a pkg-config executable to obtain relevant compiler and linker -flags. For example, it can be used thusly to compile applications that utilize -the hwloc library (assuming GNU Make): - -CFLAGS += $(pkg-config --cflags hwloc) -LDLIBS += $(pkg-config --libs hwloc) -cc hwloc-hello.c $(CFLAGS) -o hwloc-hello $(LDLIBS) - -On a machine with 4GB of RAM and 2 processor sockets -- each socket of which -has two processing cores -- the output from running hwloc-hello could be -something like the following: - -shell$ ./hwloc-hello -*** Objects at level 0 -Index 0: Machine(3938MB) -*** Objects at level 1 -Index 0: Socket#0 -Index 1: Socket#1 -*** Objects at level 2 -Index 0: Core#0 -Index 1: Core#1 -Index 2: Core#3 -Index 3: Core#2 -*** Objects at level 3 -Index 0: PU#0 -Index 1: PU#1 -Index 2: PU#2 -Index 3: PU#3 -*** Printing overall tree -Machine(3938MB) - Socket#0 - Core#0 - PU#0 - Core#1 - PU#1 - Socket#1 - Core#3 - PU#2 - Core#2 - PU#3 -*** 2 socket(s) -shell$ - -Questions and Bugs - -Questions should be sent to the devel mailing list (http://www.open-mpi.org/ -community/lists/hwloc.php). Bug reports should be reported in the tracker ( -https://git.open-mpi.org/trac/hwloc/). - -If hwloc discovers an incorrect topology for your machine, the very first thing -you should check is to ensure that you have the most recent updates installed -for your operating system. Indeed, most of hwloc topology discovery relies on -hardware information retrieved through the operation system (e.g., via the /sys -virtual filesystem of the Linux kernel). If upgrading your OS or Linux kernel -does not solve your problem, you may also want to ensure that you are running -the most recent version of the BIOS for your machine. - -If those things fail, contact us on the mailing list for additional help. -Please attach the output of lstopo after having given the --enable-debug option -to ./configure and rebuilt completely, to get debugging output. Also attach the -/proc + /sys tarball generated by the installed script hwloc-gather-topology -when submitting problems about Linux, or send the output of kstat cpu_info in -the Solaris case, or the output of sysctl hw in the Darwin or BSD cases. - -History / Credits - -hwloc is the evolution and merger of the libtopology (http:// -runtime.bordeaux.inria.fr/libtopology/) project and the Portable Linux -Processor Affinity (PLPA) (http://www.open-mpi.org/projects/plpa/) project. -Because of functional and ideological overlap, these two code bases and ideas -were merged and released under the name "hwloc" as an Open MPI sub-project. - -libtopology was initially developed by the inria Runtime Team-Project (http:// -runtime.bordeaux.inria.fr/) (headed by Raymond Namyst (http:// -dept-info.labri.fr/~namyst/). PLPA was initially developed by the Open MPI -development team as a sub-project. Both are now deprecated in favor of hwloc, -which is distributed as an Open MPI sub-project. - -Further Reading - -The documentation chapters include - - * Terms and Definitions - * Command-Line Tools - * Environment Variables - * CPU and Memory Binding Overview - * I/O Devices - * Multi-node Topologies - * Object attributes - * Importing and exporting topologies from/to XML files - * Synthetic topologies - * Interoperability With Other Software - * Thread Safety - * Components and plugins - * Embedding hwloc in Other Software - * Frequently Asked Questions - -Make sure to have had a look at those too! - diff --git a/opal/mca/hwloc/hwloc191/hwloc/VERSION b/opal/mca/hwloc/hwloc191/hwloc/VERSION deleted file mode 100644 index 9ba8c8caa1..0000000000 --- a/opal/mca/hwloc/hwloc191/hwloc/VERSION +++ /dev/null @@ -1,42 +0,0 @@ -# This is the VERSION file for hwloc, describing the precise version -# of hwloc in this distribution. The various components of the version -# number below are combined to form a single version number string. - -# If snapshot=1, then use the value from snapshot_version as the -# entire hwloc version (i.e., ignore major, minor, release, and -# greek). This is only set to 1 when making snapshot tarballs. -snapshot=0 -snapshot_version=gitclone - -# major, minor, and release are generally combined in the form -# ... If release is zero, then it is omitted. - -major=1 -minor=9 -release=2 - -# 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 -# numeric. Common examples include a1 (alpha release 1), b1 (beta -# release 1), sc2005 (Super Computing 2005 release). The only -# requirement is that it must be entirely printable ASCII characters -# and have no white space. - -greek= - -# The date when this release was created - -date="Aug 25, 2014" - -# The shared library version of hwloc's public library. This version -# is maintained in accordance with the "Library Interface Versions" -# chapter from the GNU Libtool documentation. Notes: - -# 1. Since version numbers are associated with *releases*, the version -# number maintained on the hwloc git master (and developer branches) -# is always 0:0:0. - -# 2. Version numbers are described in the Libtool current:revision:age -# format. - -libhwloc_so_version=10:1:5 diff --git a/opal/mca/hwloc/hwloc191/hwloc/aclocal.m4 b/opal/mca/hwloc/hwloc191/hwloc/aclocal.m4 deleted file mode 100644 index 700a368f5a..0000000000 --- a/opal/mca/hwloc/hwloc191/hwloc/aclocal.m4 +++ /dev/null @@ -1,1221 +0,0 @@ -# generated automatically by aclocal 1.14.1 -*- Autoconf -*- - -# Copyright (C) 1996-2013 Free Software Foundation, Inc. - -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) -m4_ifndef([AC_AUTOCONF_VERSION], - [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl -m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, -[m4_warning([this file was generated for autoconf 2.69. -You have another version of autoconf. It may work, but is not guaranteed to. -If you have problems, you may need to regenerate the build system entirely. -To do so, use the procedure documented by the package, typically 'autoreconf'.])]) - -# Copyright (C) 2002-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_AUTOMAKE_VERSION(VERSION) -# ---------------------------- -# Automake X.Y traces this macro to ensure aclocal.m4 has been -# generated from the m4 files accompanying Automake X.Y. -# (This private macro should not be called outside this file.) -AC_DEFUN([AM_AUTOMAKE_VERSION], -[am__api_version='1.14' -dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to -dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.14.1], [], - [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl -]) - -# _AM_AUTOCONF_VERSION(VERSION) -# ----------------------------- -# aclocal traces this macro to find the Autoconf version. -# This is a private macro too. Using m4_define simplifies -# the logic in aclocal, which can simply ignore this definition. -m4_define([_AM_AUTOCONF_VERSION], []) - -# AM_SET_CURRENT_AUTOMAKE_VERSION -# ------------------------------- -# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. -# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. -AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.14.1])dnl -m4_ifndef([AC_AUTOCONF_VERSION], - [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl -_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) - -# Copyright (C) 2011-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_PROG_AR([ACT-IF-FAIL]) -# ------------------------- -# Try to determine the archiver interface, and trigger the ar-lib wrapper -# if it is needed. If the detection of archiver interface fails, run -# ACT-IF-FAIL (default is to abort configure with a proper error message). -AC_DEFUN([AM_PROG_AR], -[AC_BEFORE([$0], [LT_INIT])dnl -AC_BEFORE([$0], [AC_PROG_LIBTOOL])dnl -AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -AC_REQUIRE_AUX_FILE([ar-lib])dnl -AC_CHECK_TOOLS([AR], [ar lib "link -lib"], [false]) -: ${AR=ar} - -AC_CACHE_CHECK([the archiver ($AR) interface], [am_cv_ar_interface], - [AC_LANG_PUSH([C]) - am_cv_ar_interface=ar - AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int some_variable = 0;]])], - [am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&AS_MESSAGE_LOG_FD' - AC_TRY_EVAL([am_ar_try]) - if test "$ac_status" -eq 0; then - am_cv_ar_interface=ar - else - am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&AS_MESSAGE_LOG_FD' - AC_TRY_EVAL([am_ar_try]) - if test "$ac_status" -eq 0; then - am_cv_ar_interface=lib - else - am_cv_ar_interface=unknown - fi - fi - rm -f conftest.lib libconftest.a - ]) - AC_LANG_POP([C])]) - -case $am_cv_ar_interface in -ar) - ;; -lib) - # Microsoft lib, so override with the ar-lib wrapper script. - # FIXME: It is wrong to rewrite AR. - # But if we don't then we get into trouble of one sort or another. - # A longer-term fix would be to have automake use am__AR in this case, - # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something - # similar. - AR="$am_aux_dir/ar-lib $AR" - ;; -unknown) - m4_default([$1], - [AC_MSG_ERROR([could not determine $AR interface])]) - ;; -esac -AC_SUBST([AR])dnl -]) - -# AM_AUX_DIR_EXPAND -*- Autoconf -*- - -# Copyright (C) 2001-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets -# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to -# '$srcdir', '$srcdir/..', or '$srcdir/../..'. -# -# Of course, Automake must honor this variable whenever it calls a -# tool from the auxiliary directory. The problem is that $srcdir (and -# therefore $ac_aux_dir as well) can be either absolute or relative, -# depending on how configure is run. This is pretty annoying, since -# it makes $ac_aux_dir quite unusable in subdirectories: in the top -# source directory, any form will work fine, but in subdirectories a -# relative path needs to be adjusted first. -# -# $ac_aux_dir/missing -# fails when called from a subdirectory if $ac_aux_dir is relative -# $top_srcdir/$ac_aux_dir/missing -# fails if $ac_aux_dir is absolute, -# fails when called from a subdirectory in a VPATH build with -# a relative $ac_aux_dir -# -# The reason of the latter failure is that $top_srcdir and $ac_aux_dir -# are both prefixed by $srcdir. In an in-source build this is usually -# harmless because $srcdir is '.', but things will broke when you -# start a VPATH build or use an absolute $srcdir. -# -# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, -# iff we strip the leading $srcdir from $ac_aux_dir. That would be: -# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` -# and then we would define $MISSING as -# MISSING="\${SHELL} $am_aux_dir/missing" -# This will work as long as MISSING is not called from configure, because -# unfortunately $(top_srcdir) has no meaning in configure. -# However there are other variables, like CC, which are often used in -# configure, and could therefore not use this "fixed" $ac_aux_dir. -# -# Another solution, used here, is to always expand $ac_aux_dir to an -# absolute PATH. The drawback is that using absolute paths prevent a -# configured tree to be moved without reconfiguration. - -AC_DEFUN([AM_AUX_DIR_EXPAND], -[dnl Rely on autoconf to set up CDPATH properly. -AC_PREREQ([2.50])dnl -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` -]) - -# AM_CONDITIONAL -*- Autoconf -*- - -# Copyright (C) 1997-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_CONDITIONAL(NAME, SHELL-CONDITION) -# ------------------------------------- -# Define a conditional. -AC_DEFUN([AM_CONDITIONAL], -[AC_PREREQ([2.52])dnl - m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], - [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl -AC_SUBST([$1_TRUE])dnl -AC_SUBST([$1_FALSE])dnl -_AM_SUBST_NOTMAKE([$1_TRUE])dnl -_AM_SUBST_NOTMAKE([$1_FALSE])dnl -m4_define([_AM_COND_VALUE_$1], [$2])dnl -if $2; then - $1_TRUE= - $1_FALSE='#' -else - $1_TRUE='#' - $1_FALSE= -fi -AC_CONFIG_COMMANDS_PRE( -[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then - AC_MSG_ERROR([[conditional "$1" was never defined. -Usually this means the macro was only invoked conditionally.]]) -fi])]) - -# Copyright (C) 1999-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - - -# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be -# written in clear, in which case automake, when reading aclocal.m4, -# will think it sees a *use*, and therefore will trigger all it's -# C support machinery. Also note that it means that autoscan, seeing -# CC etc. in the Makefile, will ask for an AC_PROG_CC use... - - -# _AM_DEPENDENCIES(NAME) -# ---------------------- -# See how the compiler implements dependency checking. -# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". -# We try a few techniques and use that to set a single cache variable. -# -# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was -# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular -# dependency, and given that the user is not expected to run this macro, -# just rely on AC_PROG_CC. -AC_DEFUN([_AM_DEPENDENCIES], -[AC_REQUIRE([AM_SET_DEPDIR])dnl -AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl -AC_REQUIRE([AM_MAKE_INCLUDE])dnl -AC_REQUIRE([AM_DEP_TRACK])dnl - -m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], - [$1], [CXX], [depcc="$CXX" am_compiler_list=], - [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], - [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], - [$1], [UPC], [depcc="$UPC" am_compiler_list=], - [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], - [depcc="$$1" am_compiler_list=]) - -AC_CACHE_CHECK([dependency style of $depcc], - [am_cv_$1_dependencies_compiler_type], -[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named 'D' -- because '-MD' means "put the output - # in D". - rm -rf conftest.dir - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_$1_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` - fi - am__universal=false - m4_case([$1], [CC], - [case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac], - [CXX], - [case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac]) - - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with - # Solaris 10 /bin/sh. - echo '/* dummy */' > sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - # We check with '-c' and '-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle '-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs. - am__obj=sub/conftest.${OBJEXT-o} - am__minus_obj="-o $am__obj" - case $depmode in - gcc) - # This depmode causes a compiler race in universal mode. - test "$am__universal" = false || continue - ;; - nosideeffect) - # After this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested. - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - msvc7 | msvc7msys | msvisualcpp | msvcmsys) - # This compiler won't grok '-c -o', but also, the minuso test has - # not run yet. These depmodes are late enough in the game, and - # so weak that their functioning should not be impacted. - am__obj=conftest.${OBJEXT-o} - am__minus_obj= - ;; - none) break ;; - esac - if depmode=$depmode \ - source=sub/conftest.c object=$am__obj \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep $am__obj sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_$1_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_$1_dependencies_compiler_type=none -fi -]) -AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) -AM_CONDITIONAL([am__fastdep$1], [ - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) -]) - - -# AM_SET_DEPDIR -# ------------- -# Choose a directory name for dependency files. -# This macro is AC_REQUIREd in _AM_DEPENDENCIES. -AC_DEFUN([AM_SET_DEPDIR], -[AC_REQUIRE([AM_SET_LEADING_DOT])dnl -AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl -]) - - -# AM_DEP_TRACK -# ------------ -AC_DEFUN([AM_DEP_TRACK], -[AC_ARG_ENABLE([dependency-tracking], [dnl -AS_HELP_STRING( - [--enable-dependency-tracking], - [do not reject slow dependency extractors]) -AS_HELP_STRING( - [--disable-dependency-tracking], - [speeds up one-time build])]) -if test "x$enable_dependency_tracking" != xno; then - am_depcomp="$ac_aux_dir/depcomp" - AMDEPBACKSLASH='\' - am__nodep='_no' -fi -AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) -AC_SUBST([AMDEPBACKSLASH])dnl -_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl -AC_SUBST([am__nodep])dnl -_AM_SUBST_NOTMAKE([am__nodep])dnl -]) - -# Generate code to set up dependency tracking. -*- Autoconf -*- - -# Copyright (C) 1999-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - - -# _AM_OUTPUT_DEPENDENCY_COMMANDS -# ------------------------------ -AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], -[{ - # Older Autoconf quotes --file arguments for eval, but not when files - # are listed without --file. Let's play safe and only enable the eval - # if we detect the quoting. - case $CONFIG_FILES in - *\'*) eval set x "$CONFIG_FILES" ;; - *) set x $CONFIG_FILES ;; - esac - shift - for mf - do - # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named 'Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # Grep'ing the whole file is not good either: AIX grep has a line - # limit of 2048, but all sed's we know have understand at least 4000. - if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then - dirpart=`AS_DIRNAME("$mf")` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running 'make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "$am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`AS_DIRNAME(["$file"])` - AS_MKDIR_P([$dirpart/$fdir]) - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done - done -} -])# _AM_OUTPUT_DEPENDENCY_COMMANDS - - -# AM_OUTPUT_DEPENDENCY_COMMANDS -# ----------------------------- -# This macro should only be invoked once -- use via AC_REQUIRE. -# -# This code is only required when automatic dependency tracking -# is enabled. FIXME. This creates each '.P' file that we will -# need in order to bootstrap the dependency handling code. -AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], -[AC_CONFIG_COMMANDS([depfiles], - [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], - [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) -]) - -# Do all the work for Automake. -*- Autoconf -*- - -# Copyright (C) 1996-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This macro actually does too much. Some checks are only needed if -# your package does certain things. But this isn't really a big deal. - -dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. -m4_define([AC_PROG_CC], -m4_defn([AC_PROG_CC]) -[_AM_PROG_CC_C_O -]) - -# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) -# AM_INIT_AUTOMAKE([OPTIONS]) -# ----------------------------------------------- -# The call with PACKAGE and VERSION arguments is the old style -# call (pre autoconf-2.50), which is being phased out. PACKAGE -# and VERSION should now be passed to AC_INIT and removed from -# the call to AM_INIT_AUTOMAKE. -# We support both call styles for the transition. After -# the next Automake release, Autoconf can make the AC_INIT -# arguments mandatory, and then we can depend on a new Autoconf -# release and drop the old call support. -AC_DEFUN([AM_INIT_AUTOMAKE], -[AC_PREREQ([2.65])dnl -dnl Autoconf wants to disallow AM_ names. We explicitly allow -dnl the ones we care about. -m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl -AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl -AC_REQUIRE([AC_PROG_INSTALL])dnl -if test "`cd $srcdir && pwd`" != "`pwd`"; then - # Use -I$(srcdir) only when $(srcdir) != ., so that make's output - # is not polluted with repeated "-I." - AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl - # test to see if srcdir already configured - if test -f $srcdir/config.status; then - AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) - fi -fi - -# test whether we have cygpath -if test -z "$CYGPATH_W"; then - if (cygpath --version) >/dev/null 2>/dev/null; then - CYGPATH_W='cygpath -w' - else - CYGPATH_W=echo - fi -fi -AC_SUBST([CYGPATH_W]) - -# Define the identity of the package. -dnl Distinguish between old-style and new-style calls. -m4_ifval([$2], -[AC_DIAGNOSE([obsolete], - [$0: two- and three-arguments forms are deprecated.]) -m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl - AC_SUBST([PACKAGE], [$1])dnl - AC_SUBST([VERSION], [$2])], -[_AM_SET_OPTIONS([$1])dnl -dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. -m4_if( - m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), - [ok:ok],, - [m4_fatal([AC_INIT should be called with package and version arguments])])dnl - AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl - AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl - -_AM_IF_OPTION([no-define],, -[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) - AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl - -# Some tools Automake needs. -AC_REQUIRE([AM_SANITY_CHECK])dnl -AC_REQUIRE([AC_ARG_PROGRAM])dnl -AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) -AM_MISSING_PROG([AUTOCONF], [autoconf]) -AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) -AM_MISSING_PROG([AUTOHEADER], [autoheader]) -AM_MISSING_PROG([MAKEINFO], [makeinfo]) -AC_REQUIRE([AM_PROG_INSTALL_SH])dnl -AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl -AC_REQUIRE([AC_PROG_MKDIR_P])dnl -# For better backward compatibility. To be removed once Automake 1.9.x -# dies out for good. For more background, see: -# -# -AC_SUBST([mkdir_p], ['$(MKDIR_P)']) -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. -AC_REQUIRE([AC_PROG_AWK])dnl -AC_REQUIRE([AC_PROG_MAKE_SET])dnl -AC_REQUIRE([AM_SET_LEADING_DOT])dnl -_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], - [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], - [_AM_PROG_TAR([v7])])]) -_AM_IF_OPTION([no-dependencies],, -[AC_PROVIDE_IFELSE([AC_PROG_CC], - [_AM_DEPENDENCIES([CC])], - [m4_define([AC_PROG_CC], - m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl -AC_PROVIDE_IFELSE([AC_PROG_CXX], - [_AM_DEPENDENCIES([CXX])], - [m4_define([AC_PROG_CXX], - m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl -AC_PROVIDE_IFELSE([AC_PROG_OBJC], - [_AM_DEPENDENCIES([OBJC])], - [m4_define([AC_PROG_OBJC], - m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl -AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], - [_AM_DEPENDENCIES([OBJCXX])], - [m4_define([AC_PROG_OBJCXX], - m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl -]) -AC_REQUIRE([AM_SILENT_RULES])dnl -dnl The testsuite driver may need to know about EXEEXT, so add the -dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This -dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. -AC_CONFIG_COMMANDS_PRE(dnl -[m4_provide_if([_AM_COMPILER_EXEEXT], - [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl - -# POSIX will say in a future version that running "rm -f" with no argument -# is OK; and we want to be able to make that assumption in our Makefile -# recipes. So use an aggressive probe to check that the usage we want is -# actually supported "in the wild" to an acceptable degree. -# See automake bug#10828. -# To make any issue more visible, cause the running configure to be aborted -# by default if the 'rm' program in use doesn't match our expectations; the -# user can still override this though. -if rm -f && rm -fr && rm -rf; then : OK; else - cat >&2 <<'END' -Oops! - -Your 'rm' program seems unable to run without file operands specified -on the command line, even when the '-f' option is present. This is contrary -to the behaviour of most rm programs out there, and not conforming with -the upcoming POSIX standard: - -Please tell bug-automake@gnu.org about your system, including the value -of your $PATH and any error possibly output before this message. This -can help us improve future automake versions. - -END - if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then - echo 'Configuration will proceed anyway, since you have set the' >&2 - echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 - echo >&2 - else - cat >&2 <<'END' -Aborting the configuration process, to ensure you take notice of the issue. - -You can download and install GNU coreutils to get an 'rm' implementation -that behaves properly: . - -If you want to complete the configuration process using your problematic -'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM -to "yes", and re-run configure. - -END - AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) - fi -fi]) - -dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not -dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further -dnl mangled by Autoconf and run in a shell conditional statement. -m4_define([_AC_COMPILER_EXEEXT], -m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) - -# When config.status generates a header, we must update the stamp-h file. -# This file resides in the same directory as the config header -# that is generated. The stamp files are numbered to have different names. - -# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the -# loop where config.status creates the headers, so we can generate -# our stamp files there. -AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], -[# Compute $1's index in $config_headers. -_am_arg=$1 -_am_stamp_count=1 -for _am_header in $config_headers :; do - case $_am_header in - $_am_arg | $_am_arg:* ) - break ;; - * ) - _am_stamp_count=`expr $_am_stamp_count + 1` ;; - esac -done -echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) - -# Copyright (C) 2001-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_PROG_INSTALL_SH -# ------------------ -# Define $install_sh. -AC_DEFUN([AM_PROG_INSTALL_SH], -[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -if test x"${install_sh}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; - *) - install_sh="\${SHELL} $am_aux_dir/install-sh" - esac -fi -AC_SUBST([install_sh])]) - -# Copyright (C) 2003-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# Check whether the underlying file-system supports filenames -# with a leading dot. For instance MS-DOS doesn't. -AC_DEFUN([AM_SET_LEADING_DOT], -[rm -rf .tst 2>/dev/null -mkdir .tst 2>/dev/null -if test -d .tst; then - am__leading_dot=. -else - am__leading_dot=_ -fi -rmdir .tst 2>/dev/null -AC_SUBST([am__leading_dot])]) - -# Check to see how 'make' treats includes. -*- Autoconf -*- - -# Copyright (C) 2001-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_MAKE_INCLUDE() -# ----------------- -# Check to see how make treats includes. -AC_DEFUN([AM_MAKE_INCLUDE], -[am_make=${MAKE-make} -cat > confinc << 'END' -am__doit: - @echo this is the am__doit target -.PHONY: am__doit -END -# If we don't find an include directive, just comment out the code. -AC_MSG_CHECKING([for style of include used by $am_make]) -am__include="#" -am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# Ignore all kinds of additional output from 'make'. -case `$am_make -s -f confmf 2> /dev/null` in #( -*the\ am__doit\ target*) - am__include=include - am__quote= - _am_result=GNU - ;; -esac -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - case `$am_make -s -f confmf 2> /dev/null` in #( - *the\ am__doit\ target*) - am__include=.include - am__quote="\"" - _am_result=BSD - ;; - esac -fi -AC_SUBST([am__include]) -AC_SUBST([am__quote]) -AC_MSG_RESULT([$_am_result]) -rm -f confinc confmf -]) - -# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- - -# Copyright (C) 1997-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_MISSING_PROG(NAME, PROGRAM) -# ------------------------------ -AC_DEFUN([AM_MISSING_PROG], -[AC_REQUIRE([AM_MISSING_HAS_RUN]) -$1=${$1-"${am_missing_run}$2"} -AC_SUBST($1)]) - -# AM_MISSING_HAS_RUN -# ------------------ -# Define MISSING if not defined so far and test if it is modern enough. -# If it is, set am_missing_run to use it, otherwise, to nothing. -AC_DEFUN([AM_MISSING_HAS_RUN], -[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -AC_REQUIRE_AUX_FILE([missing])dnl -if test x"${MISSING+set}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; - *) - MISSING="\${SHELL} $am_aux_dir/missing" ;; - esac -fi -# Use eval to expand $SHELL -if eval "$MISSING --is-lightweight"; then - am_missing_run="$MISSING " -else - am_missing_run= - AC_MSG_WARN(['missing' script is too old or missing]) -fi -]) - -# Helper functions for option handling. -*- Autoconf -*- - -# Copyright (C) 2001-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# _AM_MANGLE_OPTION(NAME) -# ----------------------- -AC_DEFUN([_AM_MANGLE_OPTION], -[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) - -# _AM_SET_OPTION(NAME) -# -------------------- -# Set option NAME. Presently that only means defining a flag for this option. -AC_DEFUN([_AM_SET_OPTION], -[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) - -# _AM_SET_OPTIONS(OPTIONS) -# ------------------------ -# OPTIONS is a space-separated list of Automake options. -AC_DEFUN([_AM_SET_OPTIONS], -[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) - -# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) -# ------------------------------------------- -# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. -AC_DEFUN([_AM_IF_OPTION], -[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) - -# Copyright (C) 1999-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# _AM_PROG_CC_C_O -# --------------- -# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC -# to automatically call this. -AC_DEFUN([_AM_PROG_CC_C_O], -[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -AC_REQUIRE_AUX_FILE([compile])dnl -AC_LANG_PUSH([C])dnl -AC_CACHE_CHECK( - [whether $CC understands -c and -o together], - [am_cv_prog_cc_c_o], - [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) - # Make sure it works both with $CC and with simple cc. - # Following AC_PROG_CC_C_O, we do the test twice because some - # compilers refuse to overwrite an existing .o file with -o, - # though they will create one. - am_cv_prog_cc_c_o=yes - for am_i in 1 2; do - if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ - && test -f conftest2.$ac_objext; then - : OK - else - am_cv_prog_cc_c_o=no - break - fi - done - rm -f core conftest* - unset am_i]) -if test "$am_cv_prog_cc_c_o" != yes; then - # Losing compiler, so override with the script. - # FIXME: It is wrong to rewrite CC. - # But if we don't then we get into trouble of one sort or another. - # A longer-term fix would be to have automake use am__CC in this case, - # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" - CC="$am_aux_dir/compile $CC" -fi -AC_LANG_POP([C])]) - -# For backward compatibility. -AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) - -# Copyright (C) 2001-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_RUN_LOG(COMMAND) -# ------------------- -# Run COMMAND, save the exit status in ac_status, and log it. -# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) -AC_DEFUN([AM_RUN_LOG], -[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD - ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD - (exit $ac_status); }]) - -# Check to make sure that the build environment is sane. -*- Autoconf -*- - -# Copyright (C) 1996-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_SANITY_CHECK -# --------------- -AC_DEFUN([AM_SANITY_CHECK], -[AC_MSG_CHECKING([whether build environment is sane]) -# Reject unsafe characters in $srcdir or the absolute working directory -# name. Accept space and tab only in the latter. -am_lf=' -' -case `pwd` in - *[[\\\"\#\$\&\'\`$am_lf]]*) - AC_MSG_ERROR([unsafe absolute working directory name]);; -esac -case $srcdir in - *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) - AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; -esac - -# Do 'set' in a subshell so we don't clobber the current shell's -# arguments. Must try -L first in case configure is actually a -# symlink; some systems play weird games with the mod time of symlinks -# (eg FreeBSD returns the mod time of the symlink's containing -# directory). -if ( - am_has_slept=no - for am_try in 1 2; do - echo "timestamp, slept: $am_has_slept" > conftest.file - set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` - if test "$[*]" = "X"; then - # -L didn't work. - set X `ls -t "$srcdir/configure" conftest.file` - fi - if test "$[*]" != "X $srcdir/configure conftest.file" \ - && test "$[*]" != "X conftest.file $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken - alias in your environment]) - fi - if test "$[2]" = conftest.file || test $am_try -eq 2; then - break - fi - # Just in case. - sleep 1 - am_has_slept=yes - done - test "$[2]" = conftest.file - ) -then - # Ok. - : -else - AC_MSG_ERROR([newly created file is older than distributed files! -Check your system clock]) -fi -AC_MSG_RESULT([yes]) -# If we didn't sleep, we still need to ensure time stamps of config.status and -# generated files are strictly newer. -am_sleep_pid= -if grep 'slept: no' conftest.file >/dev/null 2>&1; then - ( sleep 1 ) & - am_sleep_pid=$! -fi -AC_CONFIG_COMMANDS_PRE( - [AC_MSG_CHECKING([that generated files are newer than configure]) - if test -n "$am_sleep_pid"; then - # Hide warnings about reused PIDs. - wait $am_sleep_pid 2>/dev/null - fi - AC_MSG_RESULT([done])]) -rm -f conftest.file -]) - -# Copyright (C) 2009-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_SILENT_RULES([DEFAULT]) -# -------------------------- -# Enable less verbose build rules; with the default set to DEFAULT -# ("yes" being less verbose, "no" or empty being verbose). -AC_DEFUN([AM_SILENT_RULES], -[AC_ARG_ENABLE([silent-rules], [dnl -AS_HELP_STRING( - [--enable-silent-rules], - [less verbose build output (undo: "make V=1")]) -AS_HELP_STRING( - [--disable-silent-rules], - [verbose build output (undo: "make V=0")])dnl -]) -case $enable_silent_rules in @%:@ ((( - yes) AM_DEFAULT_VERBOSITY=0;; - no) AM_DEFAULT_VERBOSITY=1;; - *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; -esac -dnl -dnl A few 'make' implementations (e.g., NonStop OS and NextStep) -dnl do not support nested variable expansions. -dnl See automake bug#9928 and bug#10237. -am_make=${MAKE-make} -AC_CACHE_CHECK([whether $am_make supports nested variables], - [am_cv_make_support_nested_variables], - [if AS_ECHO([['TRUE=$(BAR$(V)) -BAR0=false -BAR1=true -V=1 -am__doit: - @$(TRUE) -.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then - am_cv_make_support_nested_variables=yes -else - am_cv_make_support_nested_variables=no -fi]) -if test $am_cv_make_support_nested_variables = yes; then - dnl Using '$V' instead of '$(V)' breaks IRIX make. - AM_V='$(V)' - AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' -else - AM_V=$AM_DEFAULT_VERBOSITY - AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY -fi -AC_SUBST([AM_V])dnl -AM_SUBST_NOTMAKE([AM_V])dnl -AC_SUBST([AM_DEFAULT_V])dnl -AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl -AC_SUBST([AM_DEFAULT_VERBOSITY])dnl -AM_BACKSLASH='\' -AC_SUBST([AM_BACKSLASH])dnl -_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl -]) - -# Copyright (C) 2001-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_PROG_INSTALL_STRIP -# --------------------- -# One issue with vendor 'install' (even GNU) is that you can't -# specify the program used to strip binaries. This is especially -# annoying in cross-compiling environments, where the build's strip -# is unlikely to handle the host's binaries. -# Fortunately install-sh will honor a STRIPPROG variable, so we -# always use install-sh in "make install-strip", and initialize -# STRIPPROG with the value of the STRIP variable (set by the user). -AC_DEFUN([AM_PROG_INSTALL_STRIP], -[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl -# Installed binaries are usually stripped using 'strip' when the user -# run "make install-strip". However 'strip' might not be the right -# tool to use in cross-compilation environments, therefore Automake -# will honor the 'STRIP' environment variable to overrule this program. -dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. -if test "$cross_compiling" != no; then - AC_CHECK_TOOL([STRIP], [strip], :) -fi -INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" -AC_SUBST([INSTALL_STRIP_PROGRAM])]) - -# Copyright (C) 2006-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# _AM_SUBST_NOTMAKE(VARIABLE) -# --------------------------- -# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. -# This macro is traced by Automake. -AC_DEFUN([_AM_SUBST_NOTMAKE]) - -# AM_SUBST_NOTMAKE(VARIABLE) -# -------------------------- -# Public sister of _AM_SUBST_NOTMAKE. -AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) - -# Check how to create a tarball. -*- Autoconf -*- - -# Copyright (C) 2004-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# _AM_PROG_TAR(FORMAT) -# -------------------- -# Check how to create a tarball in format FORMAT. -# FORMAT should be one of 'v7', 'ustar', or 'pax'. -# -# Substitute a variable $(am__tar) that is a command -# writing to stdout a FORMAT-tarball containing the directory -# $tardir. -# tardir=directory && $(am__tar) > result.tar -# -# Substitute a variable $(am__untar) that extract such -# a tarball read from stdin. -# $(am__untar) < result.tar -# -AC_DEFUN([_AM_PROG_TAR], -[# Always define AMTAR for backward compatibility. Yes, it's still used -# in the wild :-( We should find a proper way to deprecate it ... -AC_SUBST([AMTAR], ['$${TAR-tar}']) - -# We'll loop over all known methods to create a tar archive until one works. -_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' - -m4_if([$1], [v7], - [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], - - [m4_case([$1], - [ustar], - [# The POSIX 1988 'ustar' format is defined with fixed-size fields. - # There is notably a 21 bits limit for the UID and the GID. In fact, - # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 - # and bug#13588). - am_max_uid=2097151 # 2^21 - 1 - am_max_gid=$am_max_uid - # The $UID and $GID variables are not portable, so we need to resort - # to the POSIX-mandated id(1) utility. Errors in the 'id' calls - # below are definitely unexpected, so allow the users to see them - # (that is, avoid stderr redirection). - am_uid=`id -u || echo unknown` - am_gid=`id -g || echo unknown` - AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) - if test $am_uid -le $am_max_uid; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - _am_tools=none - fi - AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) - if test $am_gid -le $am_max_gid; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - _am_tools=none - fi], - - [pax], - [], - - [m4_fatal([Unknown tar format])]) - - AC_MSG_CHECKING([how to create a $1 tar archive]) - - # Go ahead even if we have the value already cached. We do so because we - # need to set the values for the 'am__tar' and 'am__untar' variables. - _am_tools=${am_cv_prog_tar_$1-$_am_tools} - - for _am_tool in $_am_tools; do - case $_am_tool in - gnutar) - for _am_tar in tar gnutar gtar; do - AM_RUN_LOG([$_am_tar --version]) && break - done - am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' - am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' - am__untar="$_am_tar -xf -" - ;; - plaintar) - # Must skip GNU tar: if it does not support --format= it doesn't create - # ustar tarball either. - (tar --version) >/dev/null 2>&1 && continue - am__tar='tar chf - "$$tardir"' - am__tar_='tar chf - "$tardir"' - am__untar='tar xf -' - ;; - pax) - am__tar='pax -L -x $1 -w "$$tardir"' - am__tar_='pax -L -x $1 -w "$tardir"' - am__untar='pax -r' - ;; - cpio) - am__tar='find "$$tardir" -print | cpio -o -H $1 -L' - am__tar_='find "$tardir" -print | cpio -o -H $1 -L' - am__untar='cpio -i -H $1 -d' - ;; - none) - am__tar=false - am__tar_=false - am__untar=false - ;; - esac - - # If the value was cached, stop now. We just wanted to have am__tar - # and am__untar set. - test -n "${am_cv_prog_tar_$1}" && break - - # tar/untar a dummy directory, and stop if the command works. - rm -rf conftest.dir - mkdir conftest.dir - echo GrepMe > conftest.dir/file - AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) - rm -rf conftest.dir - if test -s conftest.tar; then - AM_RUN_LOG([$am__untar /dev/null 2>&1 && break - fi - done - rm -rf conftest.dir - - AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) - AC_MSG_RESULT([$am_cv_prog_tar_$1])]) - -AC_SUBST([am__tar]) -AC_SUBST([am__untar]) -]) # _AM_PROG_TAR - -m4_include([config/hwloc.m4]) -m4_include([config/hwloc_check_attributes.m4]) -m4_include([config/hwloc_check_vendor.m4]) -m4_include([config/hwloc_check_visibility.m4]) -m4_include([config/hwloc_components.m4]) -m4_include([config/hwloc_internal.m4]) -m4_include([config/hwloc_pkg.m4]) -m4_include([config/libtool.m4]) -m4_include([config/ltoptions.m4]) -m4_include([config/ltsugar.m4]) -m4_include([config/ltversion.m4]) -m4_include([config/lt~obsolete.m4]) diff --git a/opal/mca/hwloc/hwloc191/hwloc/config/ar-lib b/opal/mca/hwloc/hwloc191/hwloc/config/ar-lib deleted file mode 100755 index fe2301e71a..0000000000 --- a/opal/mca/hwloc/hwloc191/hwloc/config/ar-lib +++ /dev/null @@ -1,270 +0,0 @@ -#! /bin/sh -# Wrapper for Microsoft lib.exe - -me=ar-lib -scriptversion=2012-03-01.08; # UTC - -# Copyright (C) 2010-2013 Free Software Foundation, Inc. -# Written by Peter Rosin . -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# This file is maintained in Automake, please report -# bugs to or send patches to -# . - - -# func_error message -func_error () -{ - echo "$me: $1" 1>&2 - exit 1 -} - -file_conv= - -# func_file_conv build_file -# Convert a $build file to $host form and store it in $file -# Currently only supports Windows hosts. -func_file_conv () -{ - file=$1 - case $file in - / | /[!/]*) # absolute file, and not a UNC file - if test -z "$file_conv"; then - # lazily determine how to convert abs files - case `uname -s` in - MINGW*) - file_conv=mingw - ;; - CYGWIN*) - file_conv=cygwin - ;; - *) - file_conv=wine - ;; - esac - fi - case $file_conv in - mingw) - file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` - ;; - cygwin) - file=`cygpath -m "$file" || echo "$file"` - ;; - wine) - file=`winepath -w "$file" || echo "$file"` - ;; - esac - ;; - esac -} - -# func_at_file at_file operation archive -# Iterate over all members in AT_FILE performing OPERATION on ARCHIVE -# for each of them. -# When interpreting the content of the @FILE, do NOT use func_file_conv, -# since the user would need to supply preconverted file names to -# binutils ar, at least for MinGW. -func_at_file () -{ - operation=$2 - archive=$3 - at_file_contents=`cat "$1"` - eval set x "$at_file_contents" - shift - - for member - do - $AR -NOLOGO $operation:"$member" "$archive" || exit $? - done -} - -case $1 in - '') - func_error "no command. Try '$0 --help' for more information." - ;; - -h | --h*) - cat <. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# This file is maintained in Automake, please report -# bugs to or send patches to -# . - -nl=' -' - -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent tools from complaining about whitespace usage. -IFS=" "" $nl" - -file_conv= - -# func_file_conv build_file lazy -# Convert a $build file to $host form and store it in $file -# Currently only supports Windows hosts. If the determined conversion -# type is listed in (the comma separated) LAZY, no conversion will -# take place. -func_file_conv () -{ - file=$1 - case $file in - / | /[!/]*) # absolute file, and not a UNC file - if test -z "$file_conv"; then - # lazily determine how to convert abs files - case `uname -s` in - MINGW*) - file_conv=mingw - ;; - CYGWIN*) - file_conv=cygwin - ;; - *) - file_conv=wine - ;; - esac - fi - case $file_conv/,$2, in - *,$file_conv,*) - ;; - mingw/*) - file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` - ;; - cygwin/*) - file=`cygpath -m "$file" || echo "$file"` - ;; - wine/*) - file=`winepath -w "$file" || echo "$file"` - ;; - esac - ;; - esac -} - -# func_cl_dashL linkdir -# Make cl look for libraries in LINKDIR -func_cl_dashL () -{ - func_file_conv "$1" - if test -z "$lib_path"; then - lib_path=$file - else - lib_path="$lib_path;$file" - fi - linker_opts="$linker_opts -LIBPATH:$file" -} - -# func_cl_dashl library -# Do a library search-path lookup for cl -func_cl_dashl () -{ - lib=$1 - found=no - save_IFS=$IFS - IFS=';' - for dir in $lib_path $LIB - do - IFS=$save_IFS - if $shared && test -f "$dir/$lib.dll.lib"; then - found=yes - lib=$dir/$lib.dll.lib - break - fi - if test -f "$dir/$lib.lib"; then - found=yes - lib=$dir/$lib.lib - break - fi - if test -f "$dir/lib$lib.a"; then - found=yes - lib=$dir/lib$lib.a - break - fi - done - IFS=$save_IFS - - if test "$found" != yes; then - lib=$lib.lib - fi -} - -# func_cl_wrapper cl arg... -# Adjust compile command to suit cl -func_cl_wrapper () -{ - # Assume a capable shell - lib_path= - shared=: - linker_opts= - for arg - do - if test -n "$eat"; then - eat= - else - case $1 in - -o) - # configure might choose to run compile as 'compile cc -o foo foo.c'. - eat=1 - case $2 in - *.o | *.[oO][bB][jJ]) - func_file_conv "$2" - set x "$@" -Fo"$file" - shift - ;; - *) - func_file_conv "$2" - set x "$@" -Fe"$file" - shift - ;; - esac - ;; - -I) - eat=1 - func_file_conv "$2" mingw - set x "$@" -I"$file" - shift - ;; - -I*) - func_file_conv "${1#-I}" mingw - set x "$@" -I"$file" - shift - ;; - -l) - eat=1 - func_cl_dashl "$2" - set x "$@" "$lib" - shift - ;; - -l*) - func_cl_dashl "${1#-l}" - set x "$@" "$lib" - shift - ;; - -L) - eat=1 - func_cl_dashL "$2" - ;; - -L*) - func_cl_dashL "${1#-L}" - ;; - -static) - shared=false - ;; - -Wl,*) - arg=${1#-Wl,} - save_ifs="$IFS"; IFS=',' - for flag in $arg; do - IFS="$save_ifs" - linker_opts="$linker_opts $flag" - done - IFS="$save_ifs" - ;; - -Xlinker) - eat=1 - linker_opts="$linker_opts $2" - ;; - -*) - set x "$@" "$1" - shift - ;; - *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) - func_file_conv "$1" - set x "$@" -Tp"$file" - shift - ;; - *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) - func_file_conv "$1" mingw - set x "$@" "$file" - shift - ;; - *) - set x "$@" "$1" - shift - ;; - esac - fi - shift - done - if test -n "$linker_opts"; then - linker_opts="-link$linker_opts" - fi - exec "$@" $linker_opts - exit 1 -} - -eat= - -case $1 in - '') - echo "$0: No command. Try '$0 --help' for more information." 1>&2 - exit 1; - ;; - -h | --h*) - cat <<\EOF -Usage: compile [--help] [--version] PROGRAM [ARGS] - -Wrapper for compilers which do not understand '-c -o'. -Remove '-o dest.o' from ARGS, run PROGRAM with the remaining -arguments, and rename the output as expected. - -If you are trying to build a whole package this is not the -right script to run: please start by reading the file 'INSTALL'. - -Report bugs to . -EOF - exit $? - ;; - -v | --v*) - echo "compile $scriptversion" - exit $? - ;; - cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) - func_cl_wrapper "$@" # Doesn't return... - ;; -esac - -ofile= -cfile= - -for arg -do - if test -n "$eat"; then - eat= - else - case $1 in - -o) - # configure might choose to run compile as 'compile cc -o foo foo.c'. - # So we strip '-o arg' only if arg is an object. - eat=1 - case $2 in - *.o | *.obj) - ofile=$2 - ;; - *) - set x "$@" -o "$2" - shift - ;; - esac - ;; - *.c) - cfile=$1 - set x "$@" "$1" - shift - ;; - *) - set x "$@" "$1" - shift - ;; - esac - fi - shift -done - -if test -z "$ofile" || test -z "$cfile"; then - # If no '-o' option was seen then we might have been invoked from a - # pattern rule where we don't need one. That is ok -- this is a - # normal compilation that the losing compiler can handle. If no - # '.c' file was seen then we are probably linking. That is also - # ok. - exec "$@" -fi - -# Name of file we expect compiler to create. -cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` - -# Create the lock directory. -# Note: use '[/\\:.-]' here to ensure that we don't use the same name -# that we are using for the .o file. Also, base the name on the expected -# object file name, since that is what matters with a parallel build. -lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d -while true; do - if mkdir "$lockdir" >/dev/null 2>&1; then - break - fi - sleep 1 -done -# FIXME: race condition here if user kills between mkdir and trap. -trap "rmdir '$lockdir'; exit 1" 1 2 15 - -# Run the compile. -"$@" -ret=$? - -if test -f "$cofile"; then - test "$cofile" = "$ofile" || mv "$cofile" "$ofile" -elif test -f "${cofile}bj"; then - test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" -fi - -rmdir "$lockdir" -exit $ret - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/opal/mca/hwloc/hwloc191/hwloc/config/config.guess b/opal/mca/hwloc/hwloc191/hwloc/config/config.guess deleted file mode 100755 index 9afd676206..0000000000 --- a/opal/mca/hwloc/hwloc191/hwloc/config/config.guess +++ /dev/null @@ -1,1568 +0,0 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright 1992-2013 Free Software Foundation, Inc. - -timestamp='2013-11-29' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that -# program. This Exception is an additional permission under section 7 -# of the GNU General Public License, version 3 ("GPLv3"). -# -# Originally written by Per Bothner. -# -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD -# -# Please send patches with a ChangeLog entry to config-patches@gnu.org. - - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright 1992-2013 Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - -trap 'exit 1' 1 2 15 - -# CC_FOR_BUILD -- compiler used by this script. Note that the use of a -# compiler to aid in system detection is discouraged as it requires -# temporary files to be created and, as you can see below, it is a -# headache to deal with in a portable fashion. - -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -# Portable tmp directory creation inspired by the Autoconf team. - -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; - for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -case "${UNAME_SYSTEM}" in -Linux|GNU|GNU/*) - # If the system lacks a compiler, then just pick glibc. - # We could probably try harder. - LIBC=gnu - - eval $set_cc_for_build - cat <<-EOF > $dummy.c - #include - #if defined(__UCLIBC__) - LIBC=uclibc - #elif defined(__dietlibc__) - LIBC=dietlibc - #else - LIBC=gnu - #endif - EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` - ;; -esac - -# Note: order is significant - the case branches are not exclusive. - -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - *:NetBSD:*:*) - # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # - # Note: NetBSD doesn't particularly care about the vendor - # portion of the name. We always set it to "unknown". - sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` - case "${UNAME_MACHINE_ARCH}" in - armeb) machine=armeb-unknown ;; - arm*) machine=arm-unknown ;; - sh3el) machine=shl-unknown ;; - sh3eb) machine=sh-unknown ;; - sh5el) machine=sh5le-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in - arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ELF__ - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # The OS release - # Debian GNU/NetBSD machines have a different userland, and - # thus, need a distinct triplet. However, they do not need - # kernel version information, so it can be replaced with a - # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in - Debian*) - release='-gnu' - ;; - *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - ;; - esac - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" - exit ;; - *:Bitrig:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} - exit ;; - *:OpenBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} - exit ;; - *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} - exit ;; - *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} - exit ;; - macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} - exit ;; - *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} - exit ;; - alpha:OSF1:*:*) - case $UNAME_RELEASE in - *4.0) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - ;; - *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` - ;; - esac - # According to Compaq, /usr/sbin/psrinfo has been available on - # OSF/1 and Tru64 systems produced since 1995. I hope that - # covers most systems running today. This code pipes the CPU - # types through head -n 1, so we only detect the type of CPU 0. - ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` - case "$ALPHA_CPU_TYPE" in - "EV4 (21064)") - UNAME_MACHINE="alpha" ;; - "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; - "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; - "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; - "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; - "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; - "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; - "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; - "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; - "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; - "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; - "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; - "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; - esac - # A Pn.n version is a patched version. - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Reset EXIT trap before exiting to avoid spurious non-zero exit code. - exitcode=$? - trap '' 0 - exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit ;; - *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos - exit ;; - *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos - exit ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit ;; - *:z/VM:*:*) - echo s390-ibm-zvmoe - exit ;; - *:OS400:*:*) - echo powerpc-ibm-os400 - exit ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit ;; - arm*:riscos:*:*|arm*:RISCOS:*:*) - echo arm-unknown-riscos - exit ;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit ;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit ;; - DRS?6000:unix:4.0:6*) - echo sparc-icl-nx6 - exit ;; - DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) - case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7; exit ;; - esac ;; - s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux${UNAME_RELEASE} - exit ;; - i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build - SUN_ARCH="i386" - # If there is a compiler, see if it is configured for 64-bit objects. - # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. - # This test works for both compilers. - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - SUN_ARCH="x86_64" - fi - fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos${UNAME_RELEASE} - ;; - sun4) - echo sparc-sun-sunos${UNAME_RELEASE} - ;; - esac - exit ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit ;; - m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} - exit ;; - powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && - { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} - exit ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit ;; - Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] - then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] - then - echo m88k-dg-dgux${UNAME_RELEASE} - else - echo m88k-dg-dguxbcs${UNAME_RELEASE} - fi - else - echo i586-dg-dgux${UNAME_RELEASE} - fi - exit ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit ;; - *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - echo i386-ibm-aix - exit ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` - then - echo "$SYSTEM_NAME" - else - echo rs6000-ibm-aix3.2.5 - fi - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit ;; - *:AIX:*:[4567]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 - esac ;; - esac - fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - - #define _HPUX_SOURCE - #include - #include - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` - test -z "$HP_ARCH" && HP_ARCH=hppa - fi ;; - esac - if [ ${HP_ARCH} = "hppa2.0w" ] - then - eval $set_cc_for_build - - # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating - # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler - # generating 64-bit code. GNU and HP use different nomenclature: - # - # $ CC_FOR_BUILD=cc ./config.guess - # => hppa2.0w-hp-hpux11.23 - # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess - # => hppa64-hp-hpux11.23 - - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | - grep -q __LP64__ - then - HP_ARCH="hppa2.0w" - else - HP_ARCH="hppa64" - fi - fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit ;; - 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - echo unknown-hitachi-hiuxwe2 - exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit ;; - *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit ;; - i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk - else - echo ${UNAME_MACHINE}-unknown-osf1 - fi - exit ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ - -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit ;; - sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:FreeBSD:*:*) - UNAME_PROCESSOR=`/usr/bin/uname -p` - case ${UNAME_PROCESSOR} in - amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - esac - exit ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit ;; - *:MINGW64*:*) - echo ${UNAME_MACHINE}-pc-mingw64 - exit ;; - *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit ;; - i*:MSYS*:*) - echo ${UNAME_MACHINE}-pc-msys - exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 - exit ;; - i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit ;; - *:Interix*:*) - case ${UNAME_MACHINE} in - x86) - echo i586-pc-interix${UNAME_RELEASE} - exit ;; - authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix${UNAME_RELEASE} - exit ;; - IA64) - echo ia64-unknown-interix${UNAME_RELEASE} - exit ;; - esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; - i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit ;; - amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-unknown-cygwin - exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit ;; - prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - *:GNU:*:*) - # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit ;; - *:GNU/*:*:*) - # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} - exit ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit ;; - aarch64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - aarch64_be:Linux:*:*) - UNAME_MACHINE=aarch64_be - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="gnulibc1" ; fi - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - arc:Linux:*:* | arceb:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - arm*:Linux:*:*) - eval $set_cc_for_build - if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_EABI__ - then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - else - if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_PCS_VFP - then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi - else - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf - fi - fi - exit ;; - avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - cris:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} - exit ;; - crisv32:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} - exit ;; - frv:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - hexagon:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - i*86:Linux:*:*) - echo ${UNAME_MACHINE}-pc-linux-${LIBC} - exit ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - mips:Linux:*:* | mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef ${UNAME_MACHINE} - #undef ${UNAME_MACHINE}el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=${UNAME_MACHINE}el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=${UNAME_MACHINE} - #else - CPU= - #endif - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } - ;; - or1k:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - or32:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - padre:Linux:*:*) - echo sparc-unknown-linux-${LIBC} - exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-${LIBC} - exit ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; - PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; - *) echo hppa-unknown-linux-${LIBC} ;; - esac - exit ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-${LIBC} - exit ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-${LIBC} - exit ;; - ppc64le:Linux:*:*) - echo powerpc64le-unknown-linux-${LIBC} - exit ;; - ppcle:Linux:*:*) - echo powerpcle-unknown-linux-${LIBC} - exit ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux-${LIBC} - exit ;; - sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - tile*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-${LIBC} - exit ;; - x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - i*86:DYNIX/ptx:4*:*) - # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. - # earlier versions are messed up and put the nodename in both - # sysname and nodename. - echo i386-sequent-sysv4 - exit ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop - exit ;; - i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos - exit ;; - i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable - exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} - fi - exit ;; - i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; - *Pent*|*Celeron) UNAME_MACHINE=i686 ;; - esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` - (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-pc-sysv32 - fi - exit ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i586. - # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configury will decide that - # this is a cross-build. - echo i586-pc-msdosdjgpp - exit ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 - fi - exit ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit ;; - mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit ;; - M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit ;; - M68*:*:R3V[5678]*:*) - test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; - 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; - NCR*:*:4.2:* | MPRAS*:*:4.2:*) - OS_REL='.3' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} - exit ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} - exit ;; - rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit ;; - i*86:VOS:*:*) - # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos - exit ;; - *:VOS:*:*) - # From Paul.Green@stratus.com. - echo hppa1.1-stratus-vos - exit ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit ;; - news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} - else - echo mips-unknown-sysv${UNAME_RELEASE} - fi - exit ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit ;; - BePC:Haiku:*:*) # Haiku running on Intel PC compatible. - echo i586-pc-haiku - exit ;; - x86_64:Haiku:*:*) - echo x86_64-unknown-haiku - exit ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit ;; - SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} - exit ;; - SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} - exit ;; - SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} - exit ;; - SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} - exit ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - eval $set_cc_for_build - if test "$UNAME_PROCESSOR" = unknown ; then - UNAME_PROCESSOR=powerpc - fi - if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac - fi - fi - elif test "$UNAME_PROCESSOR" = i386 ; then - # Avoid executing cc on OS X 10.9, as it ships with a stub - # that puts up a graphical alert prompting to install - # developer tools. Any system running Mac OS X 10.7 or - # later (Darwin 11 and later) is required to have a 64-bit - # processor. This is not true of the ARM version of Darwin - # that Apple uses in portable devices. - UNAME_PROCESSOR=x86_64 - fi - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} - exit ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then - UNAME_PROCESSOR=i386 - UNAME_MACHINE=pc - fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} - exit ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit ;; - NEO-?:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} - exit ;; - NSE-*:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} - exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit ;; - DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "$cputype" = "386"; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo ${UNAME_MACHINE}-unknown-plan9 - exit ;; - *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit ;; - *:TENEX:*:*) - echo pdp10-unknown-tenex - exit ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit ;; - *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit ;; - *:ITS:*:*) - echo pdp10-unknown-its - exit ;; - SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} - exit ;; - *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit ;; - *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in - A*) echo alpha-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; - V*) echo vax-dec-vms ; exit ;; - esac ;; - *:XENIX:*:SysV) - echo i386-pc-xenix - exit ;; - i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' - exit ;; - i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos - exit ;; - i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros - exit ;; - x86_64:VMkernel:*:*) - echo ${UNAME_MACHINE}-unknown-esx - exit ;; -esac - -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix\n"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - c34*) - echo c34-convex-bsd - exit ;; - c38*) - echo c38-convex-bsd - exit ;; - c4*) - echo c4-convex-bsd - exit ;; - esac -fi - -cat >&2 < in order to provide the needed -information to handle your system. - -config.guess timestamp = $timestamp - -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/opal/mca/hwloc/hwloc191/hwloc/config/config.sub b/opal/mca/hwloc/hwloc191/hwloc/config/config.sub deleted file mode 100755 index 61cb4bc22d..0000000000 --- a/opal/mca/hwloc/hwloc191/hwloc/config/config.sub +++ /dev/null @@ -1,1793 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright 1992-2013 Free Software Foundation, Inc. - -timestamp='2013-10-01' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that -# program. This Exception is an additional permission under section 7 -# of the GNU General Public License, version 3 ("GPLv3"). - - -# Please send patches with a ChangeLog entry to config-patches@gnu.org. -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright 1992-2013 Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit ;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ - kopensolaris*-gnu* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - android-linux) - os=-linux-android - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray | -microblaze*) - os= - basic_machine=$1 - ;; - -bluegene*) - os=-cnk - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco6) - os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*178) - os=-lynxos178 - ;; - -lynx*5) - os=-lynxos5 - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | aarch64 | aarch64_be \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arceb \ - | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ - | avr | avr32 \ - | be32 | be64 \ - | bfin \ - | c4x | c8051 | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | epiphany \ - | fido | fr30 | frv \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | hexagon \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | k1om \ - | le32 | le64 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipsr5900 | mipsr5900el \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nios | nios2 | nios2eb | nios2el \ - | ns16k | ns32k \ - | open8 \ - | or1k | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pyramid \ - | rl78 | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | we32k \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown - ;; - c54x) - basic_machine=tic54x-unknown - ;; - c55x) - basic_machine=tic55x-unknown - ;; - c6x) - basic_machine=tic6x-unknown - ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - ms1) - basic_machine=mt-unknown - ;; - - strongarm | thumb | xscale) - basic_machine=arm-unknown - ;; - xgate) - basic_machine=$basic_machine-unknown - os=-none - ;; - xscaleeb) - basic_machine=armeb-unknown - ;; - - xscaleel) - basic_machine=armel-unknown - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | aarch64-* | aarch64_be-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | be32-* | be64-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | c8051-* | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | k1om-* \ - | le32-* | le64-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ - | microblaze-* | microblazeel-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipsr5900-* | mipsr5900el-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* | nios2eb-* | nios2el-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pyramid-* \ - | rl78-* | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile*-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ - | vax-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aros) - basic_machine=i386-pc - os=-aros - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=-linux - ;; - blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - bluegene*) - basic_machine=powerpc-ibm - os=-cnk - ;; - c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - cegcc) - basic_machine=arm-unknown - os=-cegcc - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dicos) - basic_machine=i686-pc - os=-dicos - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m68knommu) - basic_machine=m68k-unknown - os=-linux - ;; - m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - microblaze*) - basic_machine=microblaze-xilinx - ;; - mingw64) - basic_machine=x86_64-pc - os=-mingw64 - ;; - mingw32) - basic_machine=i686-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` - ;; - msys) - basic_machine=i686-pc - os=-msys - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - nacl) - basic_machine=le32-unknown - os=-nacl - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - neo-tandem) - basic_machine=neo-tandem - ;; - nse-tandem) - basic_machine=nse-tandem - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - parisc) - basic_machine=hppa-unknown - os=-linux - ;; - parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pc98) - basic_machine=i386-pc - ;; - pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc | ppcbe) basic_machine=powerpc-unknown - ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rdos | rdos64) - basic_machine=x86_64-pc - os=-rdos - ;; - rdos32) - basic_machine=i386-pc - os=-rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sde) - basic_machine=mipsisa32-sde - os=-elf - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sh5el) - basic_machine=sh5le-unknown - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - tile*) - basic_machine=$basic_machine-unknown - os=-linux-gnu - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xbox) - basic_machine=i686-pc - os=-mingw32 - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - romp) - basic_machine=romp-ibm - ;; - mmix) - basic_machine=mmix-knuth - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown - ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -auroraux) - os=-auroraux - ;; - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ - | -sym* | -kopensolaris* | -plan9* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -bitrig* | -openbsd* | -solidbsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ - | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ - | -linux-newlib* | -linux-musl* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto-qnx*) - ;; - -nto*) - os=`echo $os | sed -e 's|nto|nto-qnx|'` - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux-dietlibc) - os=-linux-dietlibc - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -os400*) - os=-os400 - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -atheos*) - os=-atheos - ;; - -syllable*) - os=-syllable - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -nova*) - os=-rtmk-nova - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -tpf*) - os=-tpf - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -aros*) - os=-aros - ;; - -zvmoe) - os=-zvmoe - ;; - -dicos*) - os=-dicos - ;; - -nacl*) - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - score-*) - os=-elf - ;; - spu-*) - os=-elf - ;; - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - c4x-* | tic4x-*) - os=-coff - ;; - c8051-*) - os=-elf - ;; - hexagon-*) - os=-elf - ;; - tic54x-*) - os=-coff - ;; - tic55x-*) - os=-coff - ;; - tic6x-*) - os=-coff - ;; - # This must come before the *-dec entry. - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - ;; - m68*-cisco) - os=-aout - ;; - mep-*) - os=-elf - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - or1k-*) - os=-elf - ;; - or32-*) - os=-coff - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-haiku) - os=-haiku - ;; - *-ibm) - os=-aix - ;; - *-knuth) - os=-mmixware - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -cnk*|-aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -os400*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -tpf*) - vendor=ibm - ;; - -vxsim* | -vxworks* | -windiss*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/opal/mca/hwloc/hwloc191/hwloc/config/depcomp b/opal/mca/hwloc/hwloc191/hwloc/config/depcomp deleted file mode 100755 index 4ebd5b3a2f..0000000000 --- a/opal/mca/hwloc/hwloc191/hwloc/config/depcomp +++ /dev/null @@ -1,791 +0,0 @@ -#! /bin/sh -# depcomp - compile a program generating dependencies as side-effects - -scriptversion=2013-05-30.07; # UTC - -# Copyright (C) 1999-2013 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Originally written by Alexandre Oliva . - -case $1 in - '') - echo "$0: No command. Try '$0 --help' for more information." 1>&2 - exit 1; - ;; - -h | --h*) - cat <<\EOF -Usage: depcomp [--help] [--version] PROGRAM [ARGS] - -Run PROGRAMS ARGS to compile a file, generating dependencies -as side-effects. - -Environment variables: - depmode Dependency tracking mode. - source Source file read by 'PROGRAMS ARGS'. - object Object file output by 'PROGRAMS ARGS'. - DEPDIR directory where to store dependencies. - depfile Dependency file to output. - tmpdepfile Temporary file to use when outputting dependencies. - libtool Whether libtool is used (yes/no). - -Report bugs to . -EOF - exit $? - ;; - -v | --v*) - echo "depcomp $scriptversion" - exit $? - ;; -esac - -# Get the directory component of the given path, and save it in the -# global variables '$dir'. Note that this directory component will -# be either empty or ending with a '/' character. This is deliberate. -set_dir_from () -{ - case $1 in - */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; - *) dir=;; - esac -} - -# Get the suffix-stripped basename of the given path, and save it the -# global variable '$base'. -set_base_from () -{ - base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` -} - -# If no dependency file was actually created by the compiler invocation, -# we still have to create a dummy depfile, to avoid errors with the -# Makefile "include basename.Plo" scheme. -make_dummy_depfile () -{ - echo "#dummy" > "$depfile" -} - -# Factor out some common post-processing of the generated depfile. -# Requires the auxiliary global variable '$tmpdepfile' to be set. -aix_post_process_depfile () -{ - # If the compiler actually managed to produce a dependency file, - # post-process it. - if test -f "$tmpdepfile"; then - # Each line is of the form 'foo.o: dependency.h'. - # Do two passes, one to just change these to - # $object: dependency.h - # and one to simply output - # dependency.h: - # which is needed to avoid the deleted-header problem. - { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" - sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" - } > "$depfile" - rm -f "$tmpdepfile" - else - make_dummy_depfile - fi -} - -# A tabulation character. -tab=' ' -# A newline character. -nl=' -' -# Character ranges might be problematic outside the C locale. -# These definitions help. -upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ -lower=abcdefghijklmnopqrstuvwxyz -digits=0123456789 -alpha=${upper}${lower} - -if test -z "$depmode" || test -z "$source" || test -z "$object"; then - echo "depcomp: Variables source, object and depmode must be set" 1>&2 - exit 1 -fi - -# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. -depfile=${depfile-`echo "$object" | - sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} -tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} - -rm -f "$tmpdepfile" - -# Avoid interferences from the environment. -gccflag= dashmflag= - -# Some modes work just like other modes, but use different flags. We -# parameterize here, but still list the modes in the big case below, -# to make depend.m4 easier to write. Note that we *cannot* use a case -# here, because this file can only contain one case statement. -if test "$depmode" = hp; then - # HP compiler uses -M and no extra arg. - gccflag=-M - depmode=gcc -fi - -if test "$depmode" = dashXmstdout; then - # This is just like dashmstdout with a different argument. - dashmflag=-xM - depmode=dashmstdout -fi - -cygpath_u="cygpath -u -f -" -if test "$depmode" = msvcmsys; then - # This is just like msvisualcpp but w/o cygpath translation. - # Just convert the backslash-escaped backslashes to single forward - # slashes to satisfy depend.m4 - cygpath_u='sed s,\\\\,/,g' - depmode=msvisualcpp -fi - -if test "$depmode" = msvc7msys; then - # This is just like msvc7 but w/o cygpath translation. - # Just convert the backslash-escaped backslashes to single forward - # slashes to satisfy depend.m4 - cygpath_u='sed s,\\\\,/,g' - depmode=msvc7 -fi - -if test "$depmode" = xlc; then - # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. - gccflag=-qmakedep=gcc,-MF - depmode=gcc -fi - -case "$depmode" in -gcc3) -## gcc 3 implements dependency tracking that does exactly what -## we want. Yay! Note: for some reason libtool 1.4 doesn't like -## it if -MD -MP comes after the -MF stuff. Hmm. -## Unfortunately, FreeBSD c89 acceptance of flags depends upon -## the command line argument order; so add the flags where they -## appear in depend2.am. Note that the slowdown incurred here -## affects only configure: in makefiles, %FASTDEP% shortcuts this. - for arg - do - case $arg in - -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; - *) set fnord "$@" "$arg" ;; - esac - shift # fnord - shift # $arg - done - "$@" - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile" - exit $stat - fi - mv "$tmpdepfile" "$depfile" - ;; - -gcc) -## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. -## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. -## (see the conditional assignment to $gccflag above). -## There are various ways to get dependency output from gcc. Here's -## why we pick this rather obscure method: -## - Don't want to use -MD because we'd like the dependencies to end -## up in a subdir. Having to rename by hand is ugly. -## (We might end up doing this anyway to support other compilers.) -## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like -## -MM, not -M (despite what the docs say). Also, it might not be -## supported by the other compilers which use the 'gcc' depmode. -## - Using -M directly means running the compiler twice (even worse -## than renaming). - if test -z "$gccflag"; then - gccflag=-MD, - fi - "$@" -Wp,"$gccflag$tmpdepfile" - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - echo "$object : \\" > "$depfile" - # The second -e expression handles DOS-style file names with drive - # letters. - sed -e 's/^[^:]*: / /' \ - -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" -## This next piece of magic avoids the "deleted header file" problem. -## The problem is that when a header file which appears in a .P file -## is deleted, the dependency causes make to die (because there is -## typically no way to rebuild the header). We avoid this by adding -## dummy dependencies for each header file. Too bad gcc doesn't do -## this for us directly. -## Some versions of gcc put a space before the ':'. On the theory -## that the space means something, we add a space to the output as -## well. hp depmode also adds that space, but also prefixes the VPATH -## to the object. Take care to not repeat it in the output. -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - tr ' ' "$nl" < "$tmpdepfile" \ - | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ - | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -hp) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -sgi) - if test "$libtool" = yes; then - "$@" "-Wp,-MDupdate,$tmpdepfile" - else - "$@" -MDupdate "$tmpdepfile" - fi - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - - if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files - echo "$object : \\" > "$depfile" - # Clip off the initial element (the dependent). Don't try to be - # clever and replace this with sed code, as IRIX sed won't handle - # lines with more than a fixed number of characters (4096 in - # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; - # the IRIX cc adds comments like '#:fec' to the end of the - # dependency line. - tr ' ' "$nl" < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ - | tr "$nl" ' ' >> "$depfile" - echo >> "$depfile" - # The second pass generates a dummy entry for each header file. - tr ' ' "$nl" < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ - >> "$depfile" - else - make_dummy_depfile - fi - rm -f "$tmpdepfile" - ;; - -xlc) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -aix) - # The C for AIX Compiler uses -M and outputs the dependencies - # in a .u file. In older versions, this file always lives in the - # current directory. Also, the AIX compiler puts '$object:' at the - # start of each line; $object doesn't have directory information. - # Version 6 uses the directory in both cases. - set_dir_from "$object" - set_base_from "$object" - if test "$libtool" = yes; then - tmpdepfile1=$dir$base.u - tmpdepfile2=$base.u - tmpdepfile3=$dir.libs/$base.u - "$@" -Wc,-M - else - tmpdepfile1=$dir$base.u - tmpdepfile2=$dir$base.u - tmpdepfile3=$dir$base.u - "$@" -M - fi - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" - do - test -f "$tmpdepfile" && break - done - aix_post_process_depfile - ;; - -tcc) - # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 - # FIXME: That version still under development at the moment of writing. - # Make that this statement remains true also for stable, released - # versions. - # It will wrap lines (doesn't matter whether long or short) with a - # trailing '\', as in: - # - # foo.o : \ - # foo.c \ - # foo.h \ - # - # It will put a trailing '\' even on the last line, and will use leading - # spaces rather than leading tabs (at least since its commit 0394caf7 - # "Emit spaces for -MD"). - "$@" -MD -MF "$tmpdepfile" - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. - # We have to change lines of the first kind to '$object: \'. - sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" - # And for each line of the second kind, we have to emit a 'dep.h:' - # dummy dependency, to avoid the deleted-header problem. - sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" - rm -f "$tmpdepfile" - ;; - -## The order of this option in the case statement is important, since the -## shell code in configure will try each of these formats in the order -## listed in this file. A plain '-MD' option would be understood by many -## compilers, so we must ensure this comes after the gcc and icc options. -pgcc) - # Portland's C compiler understands '-MD'. - # Will always output deps to 'file.d' where file is the root name of the - # source file under compilation, even if file resides in a subdirectory. - # The object file name does not affect the name of the '.d' file. - # pgcc 10.2 will output - # foo.o: sub/foo.c sub/foo.h - # and will wrap long lines using '\' : - # foo.o: sub/foo.c ... \ - # sub/foo.h ... \ - # ... - set_dir_from "$object" - # Use the source, not the object, to determine the base name, since - # that's sadly what pgcc will do too. - set_base_from "$source" - tmpdepfile=$base.d - - # For projects that build the same source file twice into different object - # files, the pgcc approach of using the *source* file root name can cause - # problems in parallel builds. Use a locking strategy to avoid stomping on - # the same $tmpdepfile. - lockdir=$base.d-lock - trap " - echo '$0: caught signal, cleaning up...' >&2 - rmdir '$lockdir' - exit 1 - " 1 2 13 15 - numtries=100 - i=$numtries - while test $i -gt 0; do - # mkdir is a portable test-and-set. - if mkdir "$lockdir" 2>/dev/null; then - # This process acquired the lock. - "$@" -MD - stat=$? - # Release the lock. - rmdir "$lockdir" - break - else - # If the lock is being held by a different process, wait - # until the winning process is done or we timeout. - while test -d "$lockdir" && test $i -gt 0; do - sleep 1 - i=`expr $i - 1` - done - fi - i=`expr $i - 1` - done - trap - 1 2 13 15 - if test $i -le 0; then - echo "$0: failed to acquire lock after $numtries attempts" >&2 - echo "$0: check lockdir '$lockdir'" >&2 - exit 1 - fi - - if test $stat -ne 0; then - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - # Each line is of the form `foo.o: dependent.h', - # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. - # Do two passes, one to just change these to - # `$object: dependent.h' and one to simply `dependent.h:'. - sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" - # Some versions of the HPUX 10.20 sed can't process this invocation - # correctly. Breaking it into two sed invocations is a workaround. - sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ - | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -hp2) - # The "hp" stanza above does not work with aCC (C++) and HP's ia64 - # compilers, which have integrated preprocessors. The correct option - # to use with these is +Maked; it writes dependencies to a file named - # 'foo.d', which lands next to the object file, wherever that - # happens to be. - # Much of this is similar to the tru64 case; see comments there. - set_dir_from "$object" - set_base_from "$object" - if test "$libtool" = yes; then - tmpdepfile1=$dir$base.d - tmpdepfile2=$dir.libs/$base.d - "$@" -Wc,+Maked - else - tmpdepfile1=$dir$base.d - tmpdepfile2=$dir$base.d - "$@" +Maked - fi - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile1" "$tmpdepfile2" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" - do - test -f "$tmpdepfile" && break - done - if test -f "$tmpdepfile"; then - sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" - # Add 'dependent.h:' lines. - sed -ne '2,${ - s/^ *// - s/ \\*$// - s/$/:/ - p - }' "$tmpdepfile" >> "$depfile" - else - make_dummy_depfile - fi - rm -f "$tmpdepfile" "$tmpdepfile2" - ;; - -tru64) - # The Tru64 compiler uses -MD to generate dependencies as a side - # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. - # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put - # dependencies in 'foo.d' instead, so we check for that too. - # Subdirectories are respected. - set_dir_from "$object" - set_base_from "$object" - - if test "$libtool" = yes; then - # Libtool generates 2 separate objects for the 2 libraries. These - # two compilations output dependencies in $dir.libs/$base.o.d and - # in $dir$base.o.d. We have to check for both files, because - # one of the two compilations can be disabled. We should prefer - # $dir$base.o.d over $dir.libs/$base.o.d because the latter is - # automatically cleaned when .libs/ is deleted, while ignoring - # the former would cause a distcleancheck panic. - tmpdepfile1=$dir$base.o.d # libtool 1.5 - tmpdepfile2=$dir.libs/$base.o.d # Likewise. - tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 - "$@" -Wc,-MD - else - tmpdepfile1=$dir$base.d - tmpdepfile2=$dir$base.d - tmpdepfile3=$dir$base.d - "$@" -MD - fi - - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" - do - test -f "$tmpdepfile" && break - done - # Same post-processing that is required for AIX mode. - aix_post_process_depfile - ;; - -msvc7) - if test "$libtool" = yes; then - showIncludes=-Wc,-showIncludes - else - showIncludes=-showIncludes - fi - "$@" $showIncludes > "$tmpdepfile" - stat=$? - grep -v '^Note: including file: ' "$tmpdepfile" - if test $stat -ne 0; then - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - echo "$object : \\" > "$depfile" - # The first sed program below extracts the file names and escapes - # backslashes for cygpath. The second sed program outputs the file - # name when reading, but also accumulates all include files in the - # hold buffer in order to output them again at the end. This only - # works with sed implementations that can handle large buffers. - sed < "$tmpdepfile" -n ' -/^Note: including file: *\(.*\)/ { - s//\1/ - s/\\/\\\\/g - p -}' | $cygpath_u | sort -u | sed -n ' -s/ /\\ /g -s/\(.*\)/'"$tab"'\1 \\/p -s/.\(.*\) \\/\1:/ -H -$ { - s/.*/'"$tab"'/ - G - p -}' >> "$depfile" - echo >> "$depfile" # make sure the fragment doesn't end with a backslash - rm -f "$tmpdepfile" - ;; - -msvc7msys) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -#nosideeffect) - # This comment above is used by automake to tell side-effect - # dependency tracking mechanisms from slower ones. - -dashmstdout) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout, regardless of -o. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test "X$1" != 'X--mode=compile'; do - shift - done - shift - fi - - # Remove '-o $object'. - IFS=" " - for arg - do - case $arg in - -o) - shift - ;; - $object) - shift - ;; - *) - set fnord "$@" "$arg" - shift # fnord - shift # $arg - ;; - esac - done - - test -z "$dashmflag" && dashmflag=-M - # Require at least two characters before searching for ':' - # in the target name. This is to cope with DOS-style filenames: - # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. - "$@" $dashmflag | - sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" - rm -f "$depfile" - cat < "$tmpdepfile" > "$depfile" - # Some versions of the HPUX 10.20 sed can't process this sed invocation - # correctly. Breaking it into two sed invocations is a workaround. - tr ' ' "$nl" < "$tmpdepfile" \ - | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ - | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -dashXmstdout) - # This case only exists to satisfy depend.m4. It is never actually - # run, as this mode is specially recognized in the preamble. - exit 1 - ;; - -makedepend) - "$@" || exit $? - # Remove any Libtool call - if test "$libtool" = yes; then - while test "X$1" != 'X--mode=compile'; do - shift - done - shift - fi - # X makedepend - shift - cleared=no eat=no - for arg - do - case $cleared in - no) - set ""; shift - cleared=yes ;; - esac - if test $eat = yes; then - eat=no - continue - fi - case "$arg" in - -D*|-I*) - set fnord "$@" "$arg"; shift ;; - # Strip any option that makedepend may not understand. Remove - # the object too, otherwise makedepend will parse it as a source file. - -arch) - eat=yes ;; - -*|$object) - ;; - *) - set fnord "$@" "$arg"; shift ;; - esac - done - obj_suffix=`echo "$object" | sed 's/^.*\././'` - touch "$tmpdepfile" - ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" - rm -f "$depfile" - # makedepend may prepend the VPATH from the source file name to the object. - # No need to regex-escape $object, excess matching of '.' is harmless. - sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" - # Some versions of the HPUX 10.20 sed can't process the last invocation - # correctly. Breaking it into two sed invocations is a workaround. - sed '1,2d' "$tmpdepfile" \ - | tr ' ' "$nl" \ - | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ - | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" "$tmpdepfile".bak - ;; - -cpp) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test "X$1" != 'X--mode=compile'; do - shift - done - shift - fi - - # Remove '-o $object'. - IFS=" " - for arg - do - case $arg in - -o) - shift - ;; - $object) - shift - ;; - *) - set fnord "$@" "$arg" - shift # fnord - shift # $arg - ;; - esac - done - - "$@" -E \ - | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ - -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ - | sed '$ s: \\$::' > "$tmpdepfile" - rm -f "$depfile" - echo "$object : \\" > "$depfile" - cat < "$tmpdepfile" >> "$depfile" - sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -msvisualcpp) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test "X$1" != 'X--mode=compile'; do - shift - done - shift - fi - - IFS=" " - for arg - do - case "$arg" in - -o) - shift - ;; - $object) - shift - ;; - "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") - set fnord "$@" - shift - shift - ;; - *) - set fnord "$@" "$arg" - shift - shift - ;; - esac - done - "$@" -E 2>/dev/null | - sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" - rm -f "$depfile" - echo "$object : \\" > "$depfile" - sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" - echo "$tab" >> "$depfile" - sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -msvcmsys) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -none) - exec "$@" - ;; - -*) - echo "Unknown depmode $depmode" 1>&2 - exit 1 - ;; -esac - -exit 0 - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/opal/mca/hwloc/hwloc191/hwloc/config/distscript.sh b/opal/mca/hwloc/hwloc191/hwloc/config/distscript.sh deleted file mode 100755 index 9f05a2fd2c..0000000000 --- a/opal/mca/hwloc/hwloc191/hwloc/config/distscript.sh +++ /dev/null @@ -1,130 +0,0 @@ -#!/bin/sh -f -# -# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana -# University Research and Technology -# Corporation. All rights reserved. -# Copyright (c) 2004-2005 The University of Tennessee and The University -# of Tennessee Research Foundation. All rights -# reserved. -# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, -# University of Stuttgart. All rights reserved. -# Copyright (c) 2004-2005 The Regents of the University of California. -# All rights reserved. -# Copyright © 2010-2014 Inria. All rights reserved. -# Copyright © 2009-2014 Cisco Systems, Inc. All rights reserved. -# $COPYRIGHT$ -# -# Additional copyrights may follow -# -# $HEADER$ -# - -builddir="`pwd`" - -srcdir=$1 -cd "$srcdir" -srcdir=`pwd` -cd "$builddir" - -distdir="$builddir/$2" -HWLOC_VERSION=$3 - -if test "$distdir" = ""; then - echo "Must supply relative distdir as argv[2] -- aborting" - exit 1 -elif test "$HWLOC_VERSION" = ""; then - echo "Must supply version as argv[1] -- aborting" - exit 1 -fi - -#======================================================================== - -start=`date` -cat < header file.]) - ]) - AC_CHECK_HEADERS([sys/mman.h]) - - old_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS -D_WIN32_WINNT=0x0601" - AC_CHECK_TYPES([KAFFINITY, - PROCESSOR_CACHE_TYPE, - CACHE_DESCRIPTOR, - LOGICAL_PROCESSOR_RELATIONSHIP, - RelationProcessorPackage, - SYSTEM_LOGICAL_PROCESSOR_INFORMATION, - GROUP_AFFINITY, - PROCESSOR_RELATIONSHIP, - NUMA_NODE_RELATIONSHIP, - CACHE_RELATIONSHIP, - PROCESSOR_GROUP_INFO, - GROUP_RELATIONSHIP, - SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, - PSAPI_WORKING_SET_EX_BLOCK, - PSAPI_WORKING_SET_EX_INFORMATION], - [],[],[[#include ]]) - CPPFLAGS="$old_CPPFLAGS" - AC_CHECK_LIB([gdi32], [main], - [HWLOC_LIBS="-lgdi32 $HWLOC_LIBS" - AC_DEFINE([HAVE_LIBGDI32], 1, [Define to 1 if we have -lgdi32])]) - - AC_CHECK_HEADER([windows.h], [ - AC_DEFINE([HWLOC_HAVE_WINDOWS_H], [1], [Define to 1 if you have the `windows.h' header.]) - ]) - - AC_CHECK_HEADERS([sys/lgrp_user.h], [ - AC_CHECK_LIB([lgrp], [lgrp_latency_cookie], - [HWLOC_LIBS="-llgrp $HWLOC_LIBS" - AC_DEFINE([HAVE_LIBLGRP], 1, [Define to 1 if we have -llgrp])]) - ]) - AC_CHECK_HEADERS([kstat.h], [ - AC_CHECK_LIB([kstat], [main], - [HWLOC_LIBS="-lkstat $HWLOC_LIBS" - AC_DEFINE([HAVE_LIBKSTAT], 1, [Define to 1 if we have -lkstat])]) - ]) - - AC_CHECK_DECLS([fabsf], [ - AC_CHECK_LIB([m], [fabsf], - [HWLOC_LIBS="-lm $HWLOC_LIBS"]) - ], [], [[#include ]]) - - AC_CHECK_HEADERS([picl.h], [ - AC_CHECK_LIB([picl], [picl_initialize], - [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 ]]) - - AC_HAVE_HEADERS([mach/mach_host.h]) - AC_HAVE_HEADERS([mach/mach_init.h], [ - AC_CHECK_FUNCS([host_info]) - ]) - - AC_CHECK_HEADERS([sys/param.h]) - AC_CHECK_HEADERS([sys/sysctl.h], [ - AC_CHECK_DECLS([CTL_HW, HW_NCPU],,,[[ - #if HAVE_SYS_PARAM_H - #include - #endif - #include - ]]) - ],,[ - AC_INCLUDES_DEFAULT - #if HAVE_SYS_PARAM_H - #include - #endif - ]) - - AC_CHECK_DECLS([strtoull], [], [], [AC_INCLUDES_DEFAULT]) - - # Do a full link test instead of just using AC_CHECK_FUNCS, which - # just checks to see if the symbol exists or not. For example, - # the prototype of sysctl uses u_int, which on some platforms - # (such as FreeBSD) is only defined under __BSD_VISIBLE, __USE_BSD - # or other similar definitions. So while the symbols "sysctl" and - # "sysctlbyname" might still be available in libc (which autoconf - # checks for), they might not be actually usable. - AC_TRY_LINK([ - #include - #include - #include - ], - [return sysctl(NULL,0,NULL,NULL,NULL,0);], - AC_DEFINE([HAVE_SYSCTL],[1],[Define to '1' if sysctl is present and usable])) - AC_TRY_LINK([ - #include - #include - #include - ], - [return sysctlbyname(NULL,NULL,NULL,NULL,0);], - AC_DEFINE([HAVE_SYSCTLBYNAME],[1],[Define to '1' if sysctlbyname is present and usable])) - - case ${target} in - *-*-mingw*|*-*-cygwin*) - hwloc_pid_t=HANDLE - hwloc_thread_t=HANDLE - ;; - *) - hwloc_pid_t=pid_t - AC_CHECK_TYPES([pthread_t], [hwloc_thread_t=pthread_t], [:], [[#include ]]) - ;; - esac - AC_DEFINE_UNQUOTED(hwloc_pid_t, $hwloc_pid_t, [Define this to the process ID type]) - if test "x$hwloc_thread_t" != "x" ; then - AC_DEFINE_UNQUOTED(hwloc_thread_t, $hwloc_thread_t, [Define this to the thread ID type]) - fi - - _HWLOC_CHECK_DECL([sched_setaffinity], [ - AC_DEFINE([HWLOC_HAVE_SCHED_SETAFFINITY], [1], [Define to 1 if glibc provides a prototype of sched_setaffinity()]) - AS_IF([test "$HWLOC_STRICT_ARGS_CFLAGS" = "FAIL"],[ - AC_MSG_WARN([Support for sched_setaffinity() requires a C compiler which]) - AC_MSG_WARN([considers incorrect argument counts to be a fatal error.]) - AC_MSG_ERROR([Cannot continue.]) - ]) - AC_MSG_CHECKING([for old prototype of sched_setaffinity]) - hwloc_save_CFLAGS=$CFLAGS - CFLAGS="$CFLAGS $HWLOC_STRICT_ARGS_CFLAGS" - AC_COMPILE_IFELSE([ - AC_LANG_PROGRAM([[ - #define _GNU_SOURCE - #include - static unsigned long mask; - ]], [[ sched_setaffinity(0, (void*) &mask); ]])], - [AC_DEFINE([HWLOC_HAVE_OLD_SCHED_SETAFFINITY], [1], [Define to 1 if glibc provides the old prototype (without length) of sched_setaffinity()]) - AC_MSG_RESULT([yes])], - [AC_MSG_RESULT([no])]) - CFLAGS=$hwloc_save_CFLAGS - ], , [[ -#define _GNU_SOURCE -#include -]]) - - AC_MSG_CHECKING([for working CPU_SET]) - AC_LINK_IFELSE([ - AC_LANG_PROGRAM([[ - #include - cpu_set_t set; - ]], [[ CPU_ZERO(&set); CPU_SET(0, &set);]])], - [AC_DEFINE([HWLOC_HAVE_CPU_SET], [1], [Define to 1 if the CPU_SET macro works]) - AC_MSG_RESULT([yes])], - [AC_MSG_RESULT([no])]) - - AC_MSG_CHECKING([for working CPU_SET_S]) - AC_LINK_IFELSE([ - AC_LANG_PROGRAM([[ - #include - cpu_set_t *set; - ]], [[ - set = CPU_ALLOC(1024); - CPU_ZERO_S(CPU_ALLOC_SIZE(1024), set); - CPU_SET_S(CPU_ALLOC_SIZE(1024), 0, set); - CPU_FREE(set); - ]])], - [AC_DEFINE([HWLOC_HAVE_CPU_SET_S], [1], [Define to 1 if the CPU_SET_S macro works]) - AC_MSG_RESULT([yes])], - [AC_MSG_RESULT([no])]) - - AC_MSG_CHECKING([for working _syscall3]) - AC_LINK_IFELSE([ - AC_LANG_PROGRAM([[ - #include - #include - #define __NR_hwloc_test 123 - _syscall3(int, hwloc_test, int, param1, int, param2, int, param3); - ]], [[ hwloc_test(1, 2, 3); ]])], - [AC_DEFINE([HWLOC_HAVE__SYSCALL3], [1], [Define to 1 if the _syscall3 macro works]) - 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], [], [:]) - - AC_PATH_PROGS([HWLOC_MS_LIB], [lib]) - AC_ARG_VAR([HWLOC_MS_LIB], [Path to Microsoft's Visual Studio `lib' tool]) - - AC_PATH_PROG([BASH], [bash]) - - AC_CHECK_FUNCS([ffs], [ - _HWLOC_CHECK_DECL([ffs],[ - AC_DEFINE([HWLOC_HAVE_DECL_FFS], [1], [Define to 1 if function `ffs' is declared by system headers]) - ]) - AC_DEFINE([HWLOC_HAVE_FFS], [1], [Define to 1 if you have the `ffs' function.]) - if ( $CC --version | grep gccfss ) >/dev/null 2>&1 ; then - dnl May be broken due to - dnl https://forums.oracle.com/forums/thread.jspa?threadID=1997328 - dnl TODO: a more selective test, since bug may be version dependent. - dnl We can't use AC_TRY_LINK because the failure does not appear until - dnl run/load time and there is currently no precedent for AC_TRY_RUN - dnl use in hwloc. --PHH - dnl For now, we're going with "all gccfss compilers are broken". - dnl Better to be safe and correct; it's not like this is - dnl performance-critical code, after all. - AC_DEFINE([HWLOC_HAVE_BROKEN_FFS], [1], - [Define to 1 if your `ffs' function is known to be broken.]) - fi - ]) - AC_CHECK_FUNCS([ffsl], [ - _HWLOC_CHECK_DECL([ffsl],[ - AC_DEFINE([HWLOC_HAVE_DECL_FFSL], [1], [Define to 1 if function `ffsl' is declared by system headers]) - ]) - AC_DEFINE([HWLOC_HAVE_FFSL], [1], [Define to 1 if you have the `ffsl' function.]) - ]) - - AC_CHECK_FUNCS([fls], [ - _HWLOC_CHECK_DECL([fls],[ - AC_DEFINE([HWLOC_HAVE_DECL_FLS], [1], [Define to 1 if function `fls' is declared by system headers]) - ]) - AC_DEFINE([HWLOC_HAVE_FLS], [1], [Define to 1 if you have the `fls' function.]) - ]) - AC_CHECK_FUNCS([flsl], [ - _HWLOC_CHECK_DECL([flsl],[ - AC_DEFINE([HWLOC_HAVE_DECL_FLSL], [1], [Define to 1 if function `flsl' is declared by system headers]) - ]) - AC_DEFINE([HWLOC_HAVE_FLSL], [1], [Define to 1 if you have the `flsl' function.]) - ]) - - AC_CHECK_FUNCS([clz], [ - _HWLOC_CHECK_DECL([clz],[ - AC_DEFINE([HWLOC_HAVE_DECL_CLZ], [1], [Define to 1 if function `clz' is declared by system headers]) - ]) - AC_DEFINE([HWLOC_HAVE_CLZ], [1], [Define to 1 if you have the `clz' function.]) - ]) - AC_CHECK_FUNCS([clzl], [ - _HWLOC_CHECK_DECL([clzl],[ - AC_DEFINE([HWLOC_HAVE_DECL_CLZL], [1], [Define to 1 if function `clzl' is declared by system headers]) - ]) - AC_DEFINE([HWLOC_HAVE_CLZL], [1], [Define to 1 if you have the `clzl' function.]) - ]) - - AC_CHECK_FUNCS([openat], [hwloc_have_openat=yes]) - - AC_CHECK_HEADERS([malloc.h]) - AC_CHECK_FUNCS([getpagesize memalign posix_memalign]) - - AC_CHECK_HEADERS([sys/utsname.h]) - AC_CHECK_FUNCS([uname]) - - AC_CHECK_HEADERS([pthread_np.h]) - AC_CHECK_DECLS([pthread_setaffinity_np],,[:],[[ - #include - #ifdef HAVE_PTHREAD_NP_H - # include - #endif - ]]) - AC_CHECK_DECLS([pthread_getaffinity_np],,[:],[[ - #include - #ifdef HAVE_PTHREAD_NP_H - # include - #endif - ]]) - AC_CHECK_FUNC([sched_setaffinity], [hwloc_have_sched_setaffinity=yes]) - AC_CHECK_HEADERS([sys/cpuset.h],,,[[#include ]]) - AC_CHECK_FUNCS([cpuset_setaffinity]) - AC_SEARCH_LIBS([pthread_getthrds_np], [pthread], - AC_DEFINE([HWLOC_HAVE_PTHREAD_GETTHRDS_NP], 1, `Define to 1 if you have pthread_getthrds_np') - ) - 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.]) - ]) - - LIBS="$tmp_save_LIBS" - fi - - # PCI support - hwloc_pci_happy=no - if test "x$enable_pci" != xno -a "x$enable_libpci" != "xyes"; then - hwloc_pci_happy=yes - HWLOC_PKG_CHECK_MODULES([PCIACCESS], [pciaccess], [pci_slot_match_iterator_create], [:], [hwloc_pci_happy=no]) - if test x$hwloc_pci_happy = xyes; then hwloc_pci_lib=pciaccess; fi - fi - # PCI support with pciutils instead of pciaccess - if test "x$enable_pci" != "xno" -a "x$hwloc_pci_lib" != "xpciaccess"; then - hwloc_pci_happy=yes - HWLOC_PKG_CHECK_MODULES([PCIUTILS], [libpci], [pci_cleanup], [:], [ - # manually check pciutils in case a old one without .pc is installed - AC_CHECK_HEADERS([pci/pci.h], [ - # try first without -lz, it's not always needed (RHEL5, Debian Etch) - AC_CHECK_LIB([pci], [pci_init], [ - HWLOC_PCIUTILS_LIBS="-lpci" - ], [ - # try again with -lz because it's needed sometimes (FC7). - # don't use AC_CHECK_LIB again because the cache would - # return "no" without actually rechecking - AC_MSG_CHECKING([for pci_init in -lpci with -lz]) - tmp_save_LIBS=$LIBS - LIBS="-lpci -lz $LIBS" - AC_LINK_IFELSE([AC_LANG_CALL([], [pci_init])], - [HWLOC_PCIUTILS_LIBS="-lpci -lz" - HWLOC_PCIUTILS_ADDITIONAL_LIBS="-lz" - AC_MSG_RESULT(yes)], - [hwloc_pci_happy=no - AC_MSG_RESULT(no)]) - LIBS=$tmp_save_LIBS]) - # Also check with pci_lookup_name, because that sometimes - # requires -lresolv (RHEL5.6). don't use AC_CHECK_LIB twice - # because the cache would return "no" without actually rechecking - AC_CHECK_LIB([pci], [pci_lookup_name], [], - [AC_CHECK_LIB([resolv], [inet_ntoa], - [AC_MSG_CHECKING([for pci_lookup_name in -lpci with -lresolv]) - tmp_save_LIBS=$LIBS - LIBS="-lpci -lresolv $LIBS $HWLOC_PCIUTILS_ADDITIONAL_LIBS" - AC_LINK_IFELSE([AC_LANG_CALL([], [pci_lookup_name])], - [HWLOC_PCIUTILS_LIBS="$HWLOC_PCIUTILS_LIBS -lresolv" - HWLOC_PCIUTILS_ADDITIONAL_LIBS="$HWLOC_PCIUTILS_ADDITIONAL_LIBS -lresolv" - AC_MSG_RESULT(yes)], - [hwloc_pci_happy=no - AC_MSG_RESULT(no)]) - LIBS=$tmp_save_LIBS], - [hwloc_pci_happy=no])]) - ], [hwloc_pci_happy=no]) - ]) - if test x$hwloc_pci_happy = xyes; then - # pciutils could be used, but we don't want to force use it since it may GPL-taint hwloc - if test x$enable_libpci = xyes; then - hwloc_pci_lib=pciutils - else - # user didn't explicit request pciutils, disable PCI and warn the user - hwloc_pci_happy=no - hwloc_warn_may_use_libpci=yes - fi - else - # pciutils not found, error out if it was requested - if test x$enable_libpci = xyes; then - AC_MSG_WARN([Specified --enable-libpci switch, but could not]) - AC_MSG_WARN([find appropriate support]) - AC_MSG_ERROR([Cannot continue]) - fi - fi - fi - AC_SUBST(HWLOC_PCIUTILS_LIBS) - # If we asked for pci support but couldn't deliver, fail - AS_IF([test "$enable_pci" = "yes" -a "$hwloc_pci_happy" = "no" -a "$hwloc_warn_may_use_libpci" != "yes"], - [AC_MSG_WARN([Specified --enable-pci switch, but could not]) - AC_MSG_WARN([find appropriate support]) - AC_MSG_ERROR([Cannot continue])]) - # pciaccess specific enabling - if test "x$hwloc_pci_lib" = "xpciaccess"; then - HWLOC_PCIACCESS_REQUIRES=pciaccess - AC_DEFINE([HWLOC_HAVE_LIBPCIACCESS], [1], [Define to 1 if you have the `libpciaccess' library.]) - fi - # pciutils specific checks and enabling - if test "x$hwloc_pci_lib" = "xpciutils"; then - tmp_save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $HWLOC_PCIUTILS_CFLAGS" - tmp_save_LIBS="$LIBS" - LIBS="$LIBS $HWLOC_PCIUTILS_LIBS" - - AC_CHECK_DECLS([PCI_LOOKUP_NO_NUMBERS],,[:],[[#include ]]) - AC_CHECK_DECLS([PCI_LOOKUP_NO_NUMBERS],,[:],[[#include ]]) - AC_CHECK_LIB([pci], [pci_find_cap], [enable_pci_caps=yes], [enable_pci_caps=no], [$HWLOC_PCIUTILS_ADDITIONAL_LIBS]) - if test "x$enable_pci_caps" = "xyes"; then - AC_DEFINE([HWLOC_HAVE_PCI_FIND_CAP], [1], [Define to 1 if `libpci' has the `pci_find_cap' function.]) - fi - - AC_MSG_CHECKING(whether struct pci_dev has a device_class field) - AC_TRY_COMPILE([#include ], - [int f(struct pci_dev *dev) { return dev->device_class; }], - [pcidev_device_class=yes], [pcidev_device_class=no]) - AC_MSG_RESULT([$pcidev_device_class]) - if test x$pcidev_device_class = xyes; then - AC_DEFINE([HWLOC_HAVE_PCIDEV_DEVICE_CLASS], [1], [Define to 1 if `libpci' struct pci_dev has a `device_class' field.]) - fi - - AC_MSG_CHECKING(whether struct pci_dev has a domain field) - AC_TRY_COMPILE([#include ], - [int f(struct pci_dev *dev) { return dev->domain; }], - [pcidev_domain=yes], [pcidev_domain=no]) - AC_MSG_RESULT([$pcidev_domain]) - if test x$pcidev_domain = xyes; then - AC_DEFINE([HWLOC_HAVE_PCIDEV_DOMAIN], [1], [Define to 1 if `libpci' struct pci_dev has a `domain' field.]) - fi - - CFLAGS="$tmp_save_CFLAGS" - LIBS="$tmp_save_LIBS" - - HWLOC_PCIUTILS_REQUIRES=libpci - AC_DEFINE([HWLOC_HAVE_PCIUTILS], [1], [Define to 1 if you have the pciutils `libpci' library.]) - fi - # final common PCI enabling - if test "x$hwloc_pci_happy" = "xyes"; then - hwloc_components="$hwloc_components pci" - hwloc_pci_component_maybeplugin=1 - fi - # don't add LIBS/CFLAGS/REQUIRES yet, depends on plugins - - # OpenCL support - hwloc_opencl_happy=no - if 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]) - ], [hwloc_opencl_happy=no]) - fi - AC_SUBST(HWLOC_OPENCL_LIBS) - # Check if required extensions are available - if test "x$hwloc_opencl_happy" = "xyes"; then - tmp_save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $HWLOC_OPENCL_CFLAGS" - tmp_save_LIBS="$LIBS" - LIBS="$LIBS $HWLOC_OPENCL_LIBS" - AC_CHECK_DECLS([CL_DEVICE_TOPOLOGY_AMD],[hwloc_opencl_amd_happy=yes],[:],[[#include ]]) - CFLAGS="$tmp_save_CFLAGS" - LIBS="$tmp_save_LIBS" - # We can't do anything without CL_DEVICE_TOPOLOGY_AMD so far, so disable OpenCL entirely if not found - test "x$hwloc_opencl_amd_happy" != "xyes" && hwloc_opencl_happy=no - fi - # If we asked for opencl support but couldn't deliver, fail - AS_IF([test "$enable_opencl" = "yes" -a "$hwloc_opencl_happy" = "no"], - [AC_MSG_WARN([Specified --enable-opencl switch, but could not]) - AC_MSG_WARN([find appropriate support]) - AC_MSG_ERROR([Cannot continue])]) - if test "x$hwloc_opencl_happy" = "xyes"; then - AC_DEFINE([HWLOC_HAVE_OPENCL], [1], [Define to 1 if you have the `OpenCL' library.]) - AC_SUBST([HWLOC_HAVE_OPENCL], [1]) - hwloc_components="$hwloc_components opencl" - hwloc_opencl_component_maybeplugin=1 - else - AC_SUBST([HWLOC_HAVE_OPENCL], [0]) - fi - # don't add LIBS/CFLAGS/REQUIRES yet, depends on plugins - - # CUDA support - hwloc_have_cuda=no - hwloc_have_cudart=no - if test "x$enable_cuda" != "xno"; then - AC_CHECK_HEADERS([cuda.h], [ - AC_MSG_CHECKING(if CUDA_VERSION >= 3020) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#include -#ifndef CUDA_VERSION -#error CUDA_VERSION undefined -#elif CUDA_VERSION < 3020 -#error CUDA_VERSION too old -#endif]], [[int i = 3;]])], - [AC_MSG_RESULT(yes) - AC_CHECK_LIB([cuda], [cuInit], - [AC_DEFINE([HAVE_CUDA], 1, [Define to 1 if we have -lcuda]) - hwloc_have_cuda=yes])], - [AC_MSG_RESULT(no)])]) - - AC_CHECK_HEADERS([cuda_runtime_api.h], [ - AC_MSG_CHECKING(if CUDART_VERSION >= 3020) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#include -#ifndef CUDART_VERSION -#error CUDART_VERSION undefined -#elif CUDART_VERSION < 3020 -#error CUDART_VERSION too old -#endif]], [[int i = 3;]])], - [AC_MSG_RESULT(yes) - AC_CHECK_LIB([cudart], [cudaGetDeviceProperties], [ - HWLOC_CUDA_LIBS="-lcudart" - AC_SUBST(HWLOC_CUDA_LIBS) - hwloc_have_cudart=yes - AC_DEFINE([HWLOC_HAVE_CUDART], [1], [Define to 1 if you have the `cudart' SDK.]) - ]) - ]) - ]) - - AS_IF([test "$enable_cuda" = "yes" -a "$hwloc_have_cudart" = "no"], - [AC_MSG_WARN([Specified --enable-cuda switch, but could not]) - AC_MSG_WARN([find appropriate support]) - AC_MSG_ERROR([Cannot continue])]) - - if test "x$hwloc_have_cudart" = "xyes"; then - hwloc_components="$hwloc_components cuda" - hwloc_cuda_component_maybeplugin=1 - fi - fi - # don't add LIBS/CFLAGS yet, depends on plugins - - # NVML support - hwloc_nvml_happy=no - if 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]) - ], [hwloc_nvml_happy=no]) - fi - if test "x$hwloc_nvml_happy" = "xyes"; then - tmp_save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $HWLOC_NVML_CFLAGS" - tmp_save_LIBS="$LIBS" - LIBS="$LIBS $HWLOC_NVML_LIBS" - AC_CHECK_DECLS([nvmlDeviceGetMaxPcieLinkGeneration],,[:],[[#include ]]) - CFLAGS="$tmp_save_CFLAGS" - LIBS="$tmp_save_LIBS" - fi - AC_SUBST(HWLOC_NVML_LIBS) - # If we asked for nvml support but couldn't deliver, fail - AS_IF([test "$enable_nvml" = "yes" -a "$hwloc_nvml_happy" = "no"], - [AC_MSG_WARN([Specified --enable-nvml switch, but could not]) - AC_MSG_WARN([find appropriate support]) - AC_MSG_ERROR([Cannot continue])]) - if test "x$hwloc_nvml_happy" = "xyes"; then - AC_DEFINE([HWLOC_HAVE_NVML], [1], [Define to 1 if you have the `NVML' library.]) - AC_SUBST([HWLOC_HAVE_NVML], [1]) - hwloc_components="$hwloc_components nvml" - hwloc_nvml_component_maybeplugin=1 - else - AC_SUBST([HWLOC_HAVE_NVML], [0]) - fi - # don't add LIBS/CFLAGS/REQUIRES yet, depends on plugins - - # X11 support - AC_PATH_XTRA - - CPPFLAGS_save=$CPPFLAGS - LIBS_save=$LIBS - - CPPFLAGS="$CPPFLAGS $X_CFLAGS" - LIBS="$LIBS $X_PRE_LIBS $X_LIBS $X_EXTRA_LIBS" - AC_CHECK_HEADERS([X11/Xlib.h], - [AC_CHECK_LIB([X11], [XOpenDisplay], - [ - # the GL backend just needs XOpenDisplay - hwloc_enable_X11=yes - # lstopo needs more - AC_CHECK_HEADERS([X11/Xutil.h], - [AC_CHECK_HEADERS([X11/keysym.h], - [AC_DEFINE([HWLOC_HAVE_X11_KEYSYM], [1], [Define to 1 if X11 headers including Xutil.h and keysym.h are available.])]) - AC_SUBST([HWLOC_X11_LIBS], ["-lX11"]) - ], [], [#include ]) - ]) - ]) - CPPFLAGS=$CPPFLAGS_save - LIBS=$LIBS_save - - # GL Support - hwloc_gl_happy=no - if test "x$enable_gl" != "xno"; then - hwloc_gl_happy=yes - - AS_IF([test "$hwloc_enable_X11" != "yes"], - [AC_MSG_WARN([X11 not found; GL disabled]) - hwloc_gl_happy=no]) - - AC_CHECK_HEADERS([NVCtrl/NVCtrl.h], [ - AC_CHECK_LIB([XNVCtrl], [XNVCTRLQueryTargetAttribute], [:], [hwloc_gl_happy=no], [-lXext]) - ], [hwloc_gl_happy=no]) - - if test "x$hwloc_gl_happy" = "xyes"; then - AC_DEFINE([HWLOC_HAVE_GL], [1], [Define to 1 if you have the GL module components.]) - HWLOC_GL_LIBS="-lXNVCtrl -lXext -lX11" - AC_SUBST(HWLOC_GL_LIBS) - HWLOC_GL_REQUIRES="xext x11" - hwloc_have_gl=yes - hwloc_components="$hwloc_components gl" - hwloc_gl_component_maybeplugin=1 - else - AS_IF([test "$enable_gl" = "yes"], [ - AC_MSG_WARN([Specified --enable-gl switch, but could not]) - AC_MSG_WARN([find appropriate support]) - AC_MSG_ERROR([Cannot continue]) - ]) - fi - fi - # don't add LIBS/CFLAGS yet, depends on plugins - - # libxml2 support - hwloc_libxml2_happy= - if test "x$enable_libxml2" != "xno"; then - HWLOC_PKG_CHECK_MODULES([LIBXML2], [libxml-2.0], [xmlNewDoc], - [hwloc_libxml2_happy=yes], - [hwloc_libxml2_happy=no]) - fi - if test "x$hwloc_libxml2_happy" = "xyes"; then - HWLOC_LIBXML2_REQUIRES="libxml-2.0" - AC_DEFINE([HWLOC_HAVE_LIBXML2], [1], [Define to 1 if you have the `libxml2' library.]) - AC_SUBST([HWLOC_HAVE_LIBXML2], [1]) - - hwloc_components="$hwloc_components xml_libxml" - hwloc_xml_libxml_component_maybeplugin=1 - else - AC_SUBST([HWLOC_HAVE_LIBXML2], [0]) - AS_IF([test "$enable_libxml2" = "yes"], - [AC_MSG_WARN([--enable-libxml2 requested, but libxml2 was not found]) - AC_MSG_ERROR([Cannot continue])]) - fi - # don't add LIBS/CFLAGS/REQUIRES yet, depends on plugins - - # Try to compile the x86 cpuid inlines - 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. - # So pass #include/#define manually here for now. - CPUID_CHECK_HEADERS= - CPUID_CHECK_DEFINE= - if test "x$hwloc_windows" = xyes; then - X86_CPUID_CHECK_HEADERS="#include " - X86_CPUID_CHECK_DEFINE="#define hwloc_uint64_t DWORDLONG" - else - X86_CPUID_CHECK_DEFINE="#define hwloc_uint64_t uint64_t" - if test "x$ac_cv_header_stdint_h" = xyes; then - X86_CPUID_CHECK_HEADERS="#include " - fi - fi - AC_LINK_IFELSE([AC_LANG_PROGRAM([[ - #include - $X86_CPUID_CHECK_HEADERS - $X86_CPUID_CHECK_DEFINE - #define __hwloc_inline - #include - ]], [[ - if (hwloc_have_x86_cpuid()) { - unsigned eax = 0, ebx, ecx = 0, edx; - hwloc_x86_cpuid(&eax, &ebx, &ecx, &edx); - printf("highest x86 cpuid %x\n", eax); - return 0; - } - ]])], - [AC_MSG_RESULT([yes]) - AC_DEFINE(HWLOC_HAVE_X86_CPUID, 1, [Define to 1 if you have x86 cpuid]) - hwloc_have_x86_cpuid=yes], - [AC_MSG_RESULT([no])]) - if test "x$hwloc_have_x86_cpuid" = xyes; then - hwloc_components="$hwloc_components x86" - fi - CPPFLAGS="$old_CPPFLAGS" - - # Components require pthread_mutex, see if it needs -lpthread - hwloc_pthread_mutex_happy=no - # Try without explicit -lpthread first - AC_CHECK_FUNC([pthread_mutex_lock], - [hwloc_pthread_mutex_happy=yes - HWLOC_LIBS_PRIVATE="$HWLOC_LIBS_PRIVATE -lpthread" - ], - [AC_MSG_CHECKING([for pthread_mutex_lock with -lpthread]) - # Try again with explicit -lpthread, but don't use AC_CHECK_FUNC to avoid the cache - tmp_save_LIBS=$LIBS - LIBS="$LIBS -lpthread" - AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_mutex_lock])], - [hwloc_pthread_mutex_happy=yes - HWLOC_LIBS="$HWLOC_LIBS -lpthread" - ]) - AC_MSG_RESULT([$hwloc_pthread_mutex_happy]) - LIBS="$tmp_save_LIBS" - ]) - AS_IF([test "x$hwloc_pthread_mutex_happy" = "xyes"], - [AC_DEFINE([HWLOC_HAVE_PTHREAD_MUTEX], 1, [Define to 1 if pthread mutexes are available])]) - - AS_IF([test "x$hwloc_pthread_mutex_happy" != xyes -a "x$hwloc_windows" != xyes], - [AC_MSG_WARN([pthread_mutex_lock not available, required for thread-safe initialization on non-Windows platforms.]) - AC_MSG_WARN([Please report this to the hwloc-devel mailing list.]) - AC_MSG_ERROR([Cannot continue])]) - - # - # Now enable registration of listed components - # - - # Plugin support - AC_MSG_CHECKING([if plugin support is enabled]) - # Plugins (even core support) are totally disabled by default - AS_IF([test "x$enable_plugins" = "x"], [enable_plugins=no]) - AS_IF([test "x$enable_plugins" != "xno"], [hwloc_have_plugins=yes], [hwloc_have_plugins=no]) - AC_MSG_RESULT([$hwloc_have_plugins]) - AS_IF([test "x$hwloc_have_plugins" = "xyes"], - [AC_DEFINE([HWLOC_HAVE_PLUGINS], 1, [Define to 1 if the hwloc library should support dynamically-loaded plugins])]) - - # Some sanity checks about plugins - # libltdl doesn't work on AIX as of 2.4.2 - AS_IF([test "x$enable_plugins" = "xyes" -a "x$hwloc_aix" = "xyes"], - [AC_MSG_WARN([libltdl does not work on AIX, plugins support cannot be enabled.]) - AC_MSG_ERROR([Cannot continue])]) - # posix linkers don't work well with plugins and windows dll constraints - AS_IF([test "x$enable_plugins" = "xyes" -a "x$hwloc_windows" = "xyes"], - [AC_MSG_WARN([Plugins not supported on non-native Windows build, plugins support cannot be enabled.]) - AC_MSG_ERROR([Cannot continue])]) - - # If we want plugins, look for ltdl.h and libltdl - if test "x$hwloc_have_plugins" = xyes; then - AC_CHECK_HEADER([ltdl.h], [], - [AC_MSG_WARN([Plugin support requested, but could not find ltdl.h]) - AC_MSG_ERROR([Cannot continue])]) - AC_CHECK_LIB([ltdl], [lt_dlopenext], - [HWLOC_LIBS="$HWLOC_LIBS -lltdl"], - [AC_MSG_WARN([Plugin support requested, but could not find libltdl]) - AC_MSG_ERROR([Cannot continue])]) - # Add libltdl static-build dependencies to hwloc.pc - HWLOC_CHECK_LTDL_DEPS - fi - - AC_ARG_WITH([hwloc-plugins-path], - AC_HELP_STRING([--with-hwloc-plugins-path=dir:...], - [Colon-separated list of plugin directories. Default: "$prefix/lib/hwloc". Plugins will be installed in the first directory. They will be loaded from all of them, in order.]), - [HWLOC_PLUGINS_PATH="$with_hwloc_plugins_path"], - [HWLOC_PLUGINS_PATH="\$(libdir)/hwloc"]) - AC_SUBST(HWLOC_PLUGINS_PATH) - HWLOC_PLUGINS_DIR=`echo "$HWLOC_PLUGINS_PATH" | cut -d: -f1` - AC_SUBST(HWLOC_PLUGINS_DIR) - - # Static components output file - hwloc_static_components_dir=${HWLOC_top_builddir}/src - mkdir -p ${hwloc_static_components_dir} - hwloc_static_components_file=${hwloc_static_components_dir}/static-components.h - rm -f ${hwloc_static_components_file} - - # Make $enable_plugins easier to use (it contains either "yes" (all) or a list of ) - HWLOC_PREPARE_FILTER_COMPONENTS([$enable_plugins]) - # Now we have some hwloc__component_wantplugin=1 - - # See which core components want plugin and support it - HWLOC_FILTER_COMPONENTS - # Now we have some hwloc__component=plugin/static - # and hwloc_static/plugin_components - AC_MSG_CHECKING([components to build statically]) - AC_MSG_RESULT($hwloc_static_components) - HWLOC_LIST_STATIC_COMPONENTS([$hwloc_static_components_file], [$hwloc_static_components]) - AC_MSG_CHECKING([components to build as plugins]) - AC_MSG_RESULT([$hwloc_plugin_components]) - - AS_IF([test "$hwloc_pci_component" = "static"], - [HWLOC_LIBS="$HWLOC_LIBS $HWLOC_PCIUTILS_LIBS $HWLOC_PCIACCESS_LIBS" - HWLOC_CFLAGS="$HWLOC_CFLAGS $HWLOC_PCIUTILS_CFLAGS $HWLOC_PCIACCESS_CFLAGS" - HWLOC_REQUIRES="$HWLOC_PCIUTILS_REQUIRES $HWLOC_PCIACCESS_REQUIRES $HWLOC_REQUIRES"]) - AS_IF([test "$hwloc_opencl_component" = "static"], - [HWLOC_LIBS="$HWLOC_LIBS $HWLOC_OPENCL_LIBS" - HWLOC_CFLAGS="$HWLOC_CFLAGS $HWLOC_OPENCL_CFLAGS" - HWLOC_REQUIRES="$HWLOC_OPENCL_REQUIRES $HWLOC_REQUIRES"]) - AS_IF([test "$hwloc_cuda_component" = "static"], - [HWLOC_LIBS="$HWLOC_LIBS $HWLOC_CUDA_LIBS" - HWLOC_CFLAGS="$HWLOC_CFLAGS $HWLOC_CUDA_CFLAGS" - HWLOC_REQUIRES="$HWLOC_CUDA_REQUIRES $HWLOC_REQUIRES"]) - AS_IF([test "$hwloc_nvml_component" = "static"], - [HWLOC_LIBS="$HWLOC_LIBS $HWLOC_NVML_LIBS" - HWLOC_CFLAGS="$HWLOC_CFLAGS $HWLOC_NVML_CFLAGS" - HWLOC_REQUIRES="$HWLOC_NVML_REQUIRES $HWLOC_REQUIRES"]) - AS_IF([test "$hwloc_gl_component" = "static"], - [HWLOC_LIBS="$HWLOC_LIBS $HWLOC_GL_LIBS" - HWLOC_CFLAGS="$HWLOC_CFLAGS $HWLOC_GL_CFLAGS" - HWLOC_REQUIRES="$HWLOC_GL_REQUIRES $HWLOC_REQUIRES"]) - AS_IF([test "$hwloc_xml_libxml_component" = "static"], - [HWLOC_LIBS="$HWLOC_LIBS $HWLOC_LIBXML2_LIBS" - HWLOC_CFLAGS="$HWLOC_CFLAGS $HWLOC_LIBXML2_CFLAGS" - HWLOC_REQUIRES="$HWLOC_LIBXML2_REQUIRES $HWLOC_REQUIRES"]) - - # - # Setup HWLOC's C, CPP, and LD flags, and LIBS - # - AC_SUBST(HWLOC_REQUIRES) - AC_SUBST(HWLOC_CFLAGS) - HWLOC_CPPFLAGS='-I$(HWLOC_top_builddir)/include -I$(HWLOC_top_srcdir)/include' - AC_SUBST(HWLOC_CPPFLAGS) - AC_SUBST(HWLOC_LDFLAGS) - AC_SUBST(HWLOC_LIBS) - AC_SUBST(HWLOC_LIBS_PRIVATE) - - # Set these values explicitly for embedded builds. Exporting - # these values through *_EMBEDDED_* values gives us the freedom to - # do something different someday if we ever need to. There's no - # need to fill these values in unless we're in embedded mode. - # Indeed, if we're building in embedded mode, we want HWLOC_LIBS - # to be empty so that nothing is linked into libhwloc_embedded.la - # itself -- only the upper-layer will link in anything required. - - 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_LIBS=$HWLOC_LIBS - HWLOC_LIBS=]) - AC_SUBST(HWLOC_EMBEDDED_CFLAGS) - AC_SUBST(HWLOC_EMBEDDED_CPPFLAGS) - AC_SUBST(HWLOC_EMBEDDED_LDADD) - AC_SUBST(HWLOC_EMBEDDED_LIBS) - - # Always generate these files - AC_CONFIG_FILES( - hwloc_config_prefix[Makefile] - hwloc_config_prefix[include/Makefile] - hwloc_config_prefix[src/Makefile ] - ) - - # Cleanup - AC_LANG_POP - - # Success - $2 -])dnl - -#----------------------------------------------------------------------- - -# Specify the symbol prefix -AC_DEFUN([HWLOC_SET_SYMBOL_PREFIX],[ - hwloc_symbol_prefix_value=$1 -])dnl - -#----------------------------------------------------------------------- - -# This must be a standalone routine so that it can be called both by -# HWLOC_INIT and an external caller (if HWLOC_INIT is not invoked). -AC_DEFUN([HWLOC_DO_AM_CONDITIONALS],[ - AS_IF([test "$hwloc_did_am_conditionals" != "yes"],[ - AM_CONDITIONAL([HWLOC_BUILD_STANDALONE], [test "$hwloc_mode" = "standalone"]) - - 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_LIBIBVERBS], - [test "x$hwloc_have_libibverbs" = "xyes"]) - AM_CONDITIONAL([HWLOC_HAVE_CUDA], - [test "x$hwloc_have_cuda" = "xyes"]) - AM_CONDITIONAL([HWLOC_HAVE_GL], - [test "x$hwloc_have_gl" = "xyes"]) - AM_CONDITIONAL([HWLOC_HAVE_MYRIEXPRESS], - [test "x$hwloc_have_myriexpress" = "xyes"]) - AM_CONDITIONAL([HWLOC_HAVE_CUDART], - [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_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_BUILD_DOXYGEN], - [test "x$hwloc_generate_doxs" = "xyes"]) - AM_CONDITIONAL([HWLOC_BUILD_README], - [test "x$hwloc_generate_readme" = "xyes" -a \( "x$hwloc_install_doxs" = "xyes" -o "x$hwloc_generate_doxs" = "xyes" \) ]) - AM_CONDITIONAL([HWLOC_INSTALL_DOXYGEN], - [test "x$hwloc_install_doxs" = "xyes"]) - - AM_CONDITIONAL([HWLOC_HAVE_LINUX], [test "x$hwloc_linux" = "xyes"]) - AM_CONDITIONAL([HWLOC_HAVE_BGQ], [test "x$hwloc_bgq" = "xyes"]) - AM_CONDITIONAL([HWLOC_HAVE_IRIX], [test "x$hwloc_irix" = "xyes"]) - AM_CONDITIONAL([HWLOC_HAVE_DARWIN], [test "x$hwloc_darwin" = "xyes"]) - AM_CONDITIONAL([HWLOC_HAVE_FREEBSD], [test "x$hwloc_freebsd" = "xyes"]) - 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"]) - - AM_CONDITIONAL([HWLOC_HAVE_X86_32], [test "x$hwloc_x86_32" = "xyes"]) - AM_CONDITIONAL([HWLOC_HAVE_X86_64], [test "x$hwloc_x86_64" = "xyes"]) - AM_CONDITIONAL([HWLOC_HAVE_X86_CPUID], [test "x$hwloc_have_x86_cpuid" = "xyes"]) - - AM_CONDITIONAL([HWLOC_HAVE_PLUGINS], [test "x$hwloc_have_plugins" = "xyes"]) - AM_CONDITIONAL([HWLOC_PCI_BUILD_STATIC], [test "x$hwloc_pci_component" = "xstatic"]) - AM_CONDITIONAL([HWLOC_OPENCL_BUILD_STATIC], [test "x$hwloc_opencl_component" = "xstatic"]) - AM_CONDITIONAL([HWLOC_CUDA_BUILD_STATIC], [test "x$hwloc_cuda_component" = "xstatic"]) - AM_CONDITIONAL([HWLOC_NVML_BUILD_STATIC], [test "x$hwloc_nvml_component" = "xstatic"]) - AM_CONDITIONAL([HWLOC_GL_BUILD_STATIC], [test "x$hwloc_gl_component" = "xstatic"]) - AM_CONDITIONAL([HWLOC_XML_LIBXML_BUILD_STATIC], [test "x$hwloc_xml_libxml_component" = "xstatic"]) - - AM_CONDITIONAL([HWLOC_HAVE_CXX], [test "x$hwloc_have_cxx" = "xyes"]) - ]) - hwloc_did_am_conditionals=yes -])dnl - -#----------------------------------------------------------------------- - -AC_DEFUN([_HWLOC_CHECK_DIFF_U], [ - AC_MSG_CHECKING([whether diff accepts -u]) - if diff -u /dev/null /dev/null 2> /dev/null - then - HWLOC_DIFF_U="-u" - else - HWLOC_DIFF_U="" - fi - AC_SUBST([HWLOC_DIFF_U]) - AC_MSG_RESULT([$HWLOC_DIFF_U]) -]) - -AC_DEFUN([_HWLOC_CHECK_DIFF_W], [ - AC_MSG_CHECKING([whether diff accepts -w]) - if diff -w /dev/null /dev/null 2> /dev/null - then - HWLOC_DIFF_W="-w" - else - HWLOC_DIFF_W="" - fi - AC_SUBST([HWLOC_DIFF_W]) - AC_MSG_RESULT([$HWLOC_DIFF_W]) -]) - -#----------------------------------------------------------------------- - -dnl HWLOC_CHECK_DECL -dnl -dnl Check declaration of given function by trying to call it with an insane -dnl number of arguments (10). Success means the compiler couldn't really check. -AC_DEFUN([_HWLOC_CHECK_DECL], [ - AC_MSG_CHECKING([whether function $1 is declared]) - AC_REQUIRE([AC_PROG_CC]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM( - [AC_INCLUDES_DEFAULT([$4]) - $1(int,long,int,long,int,long,int,long,int,long);], - [$1(1,2,3,4,5,6,7,8,9,10);])], - [AC_MSG_RESULT([no]) - $3], - [AC_MSG_RESULT([yes]) - $2] - ) -]) - -#----------------------------------------------------------------------- - -dnl HWLOC_CHECK_DECLS -dnl -dnl Same as HWLOCK_CHECK_DECL, but defines HAVE_DECL_foo to 1 or 0 depending on -dnl the result. -AC_DEFUN([_HWLOC_CHECK_DECLS], [ - HWLOC_CHECK_DECL([$1], [ac_have_decl=1], [ac_have_decl=0], [$4]) - AC_DEFINE_UNQUOTED(AS_TR_CPP([HAVE_DECL_$1]), [$ac_have_decl], - [Define to 1 if you have the declaration of `$1', and to 0 if you don't]) -]) - -#----------------------------------------------------------------------- - -dnl HWLOC_CHECK_LTDL_DEPS -dnl -dnl Add ltdl dependencies to HWLOC_LIBS_PRIVATE -AC_DEFUN([HWLOC_CHECK_LTDL_DEPS], [ - # save variables that we'll modify below - save_lt_cv_dlopen="$lt_cv_dlopen" - save_lt_cv_dlopen_libs="$lt_cv_dlopen_libs" - save_lt_cv_dlopen_self="$lt_cv_dlopen_self" - ########################################################### - # code stolen from LT_SYS_DLOPEN_SELF in libtool.m4 - case $host_os in - beos*) - lt_cv_dlopen="load_add_on" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ;; - - mingw* | pw32* | cegcc*) - lt_cv_dlopen="LoadLibrary" - lt_cv_dlopen_libs= - ;; - - cygwin*) - lt_cv_dlopen="dlopen" - lt_cv_dlopen_libs= - ;; - - darwin*) - # if libdl is installed we need to link against it - AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ - lt_cv_dlopen="dyld" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ]) - ;; - - *) - AC_CHECK_FUNC([shl_load], - [lt_cv_dlopen="shl_load"], - [AC_CHECK_LIB([dld], [shl_load], - [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], - [AC_CHECK_FUNC([dlopen], - [lt_cv_dlopen="dlopen"], - [AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], - [AC_CHECK_LIB([svld], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], - [AC_CHECK_LIB([dld], [dld_link], - [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) - ]) - ]) - ]) - ]) - ]) - ;; - esac - # end of code stolen from LT_SYS_DLOPEN_SELF in libtool.m4 - ########################################################### - - HWLOC_LIBS_PRIVATE="$HWLOC_LIBS_PRIVATE $lt_cv_dlopen_libs" - - # restore modified variable in case the actual libtool code uses them - lt_cv_dlopen="$save_lt_cv_dlopen" - lt_cv_dlopen_libs="$save_lt_cv_dlopen_libs" - lt_cv_dlopen_self="$save_lt_cv_dlopen_self" -]) diff --git a/opal/mca/hwloc/hwloc191/hwloc/config/hwloc_check_attributes.m4 b/opal/mca/hwloc/hwloc191/hwloc/config/hwloc_check_attributes.m4 deleted file mode 100644 index 1e3763bd45..0000000000 --- a/opal/mca/hwloc/hwloc191/hwloc/config/hwloc_check_attributes.m4 +++ /dev/null @@ -1,533 +0,0 @@ -# This macro set originally copied from Open MPI: -# Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana -# University Research and Technology -# Corporation. All rights reserved. -# Copyright (c) 2004-2005 The University of Tennessee and The University -# of Tennessee Research Foundation. All rights -# reserved. -# Copyright (c) 2004-2007 High Performance Computing Center Stuttgart, -# University of Stuttgart. All rights reserved. -# Copyright (c) 2004-2005 The Regents of the University of California. -# All rights reserved. -# and renamed for hwloc: -# Copyright (c) 2009 inria. All rights reserved. -# Copyright (c) 2009 Université Bordeaux 1 -# Copyright (c) 2010 Cisco Systems, Inc. All rights reserved. -# See COPYING in top-level directory. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# - Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# - Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer listed -# in this license in the documentation and/or other materials -# provided with the distribution. -# -# - Neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# The copyright holders provide no reassurances that the source code -# provided does not infringe any patent, copyright, or any other -# intellectual property rights of third parties. The copyright holders -# disclaim any liability to any recipient for claims brought against -# recipient by any third party for infringement of that parties -# intellectual property rights. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -# -# Search the generated warnings for -# keywords regarding skipping or ignoring certain attributes -# Intel: ignore -# Sun C++: skip -# -AC_DEFUN([_HWLOC_ATTRIBUTE_FAIL_SEARCH],[ - # Be safe for systems that have ancient Autoconf's (e.g., RHEL5) - m4_ifdef([AC_PROG_GREP], - [AC_REQUIRE([AC_PROG_GREP])], - [GREP=grep]) - - if test -s conftest.err ; then - for i in ignore skip ; do - $GREP -iq $i conftest.err - if test "$?" = "0" ; then - hwloc_cv___attribute__[$1]=0 - break; - fi - done - fi -]) - -# -# HWLOC: Remove C++ compiler check. It can result in a circular -# dependency in embedded situations. -# -# Check for one specific attribute by compiling with C -# and possibly using a cross-check. -# -# If the cross-check is defined, a static function "usage" should be -# defined, which is to be called from main (to circumvent warnings -# regarding unused function in main file) -# static int usage (int * argument); -# -# The last argument is for specific CFLAGS, that need to be set -# for the compiler to generate a warning on the cross-check. -# This may need adaption for future compilers / CFLAG-settings. -# -AC_DEFUN([_HWLOC_CHECK_SPECIFIC_ATTRIBUTE], [ - AC_MSG_CHECKING([for __attribute__([$1])]) - AC_CACHE_VAL(hwloc_cv___attribute__[$1], [ - # - # Try to compile using the C compiler - # - AC_TRY_COMPILE([$2],[], - [ - # - # In case we did succeed: Fine, but was this due to the - # attribute being ignored/skipped? Grep for IgNoRe/skip in conftest.err - # and if found, reset the hwloc_cv__attribute__var=0 - # - hwloc_cv___attribute__[$1]=1 - _HWLOC_ATTRIBUTE_FAIL_SEARCH([$1]) - ], - [hwloc_cv___attribute__[$1]=0]) - - # - # If the attribute is supported by both compilers, - # try to recompile a *cross-check*, IFF defined. - # - if test '(' "$hwloc_cv___attribute__[$1]" = "1" -a "[$3]" != "" ')' ; then - ac_c_werror_flag_safe=$ac_c_werror_flag - ac_c_werror_flag="yes" - CFLAGS_safe=$CFLAGS - CFLAGS="$CFLAGS [$4]" - - AC_TRY_COMPILE([$3], - [ - int i=4711; - i=usage(&i); - ], - [hwloc_cv___attribute__[$1]=0], - [ - # - # In case we did NOT succeed: Fine, but was this due to the - # attribute being ignored? Grep for IgNoRe in conftest.err - # and if found, reset the hwloc_cv__attribute__var=0 - # - hwloc_cv___attribute__[$1]=1 - _HWLOC_ATTRIBUTE_FAIL_SEARCH([$1]) - ]) - - ac_c_werror_flag=$ac_c_werror_flag_safe - CFLAGS=$CFLAGS_safe - fi - ]) - - if test "$hwloc_cv___attribute__[$1]" = "1" ; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - fi -]) - - -# -# Test the availability of __attribute__ and with the help -# of _HWLOC_CHECK_SPECIFIC_ATTRIBUTE for the support of -# particular attributes. Compilers, that do not support an -# attribute most often fail with a warning (when the warning -# level is set). -# The compilers output is parsed in _HWLOC_ATTRIBUTE_FAIL_SEARCH -# -# To add a new attributes __NAME__ add the -# hwloc_cv___attribute__NAME -# add a new check with _HWLOC_CHECK_SPECIFIC_ATTRIBUTE (possibly with a cross-check) -# _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([name], [int foo (int arg) __attribute__ ((__name__));], [], []) -# and define the corresponding -# AC_DEFINE_UNQUOTED(_HWLOC_HAVE_ATTRIBUTE_NAME, [$hwloc_cv___attribute__NAME], -# [Whether your compiler has __attribute__ NAME or not]) -# and decide on a correct macro (in opal/include/opal_config_bottom.h): -# # define __opal_attribute_NAME(x) __attribute__(__NAME__) -# -# Please use the "__"-notation of the attribute in order not to -# clash with predefined names or macros (e.g. const, which some compilers -# do not like..) -# - - -AC_DEFUN([_HWLOC_CHECK_ATTRIBUTES], [ - AC_MSG_CHECKING(for __attribute__) - - AC_CACHE_VAL(hwloc_cv___attribute__, [ - AC_TRY_COMPILE( - [#include - /* Check for the longest available __attribute__ (since gcc-2.3) */ - struct foo { - char a; - int x[2] __attribute__ ((__packed__)); - }; - ], - [], - [hwloc_cv___attribute__=1], - [hwloc_cv___attribute__=0], - ) - - if test "$hwloc_cv___attribute__" = "1" ; then - AC_TRY_COMPILE( - [#include - /* Check for the longest available __attribute__ (since gcc-2.3) */ - struct foo { - char a; - int x[2] __attribute__ ((__packed__)); - }; - ], - [], - [hwloc_cv___attribute__=1], - [hwloc_cv___attribute__=0], - ) - fi - ]) - AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE, [$hwloc_cv___attribute__], - [Whether your compiler has __attribute__ or not]) - -# -# Now that we know the compiler support __attribute__ let's check which kind of -# attributed are supported. -# - if test "$hwloc_cv___attribute__" = "0" ; then - AC_MSG_RESULT([no]) - hwloc_cv___attribute__aligned=0 - hwloc_cv___attribute__always_inline=0 - hwloc_cv___attribute__cold=0 - hwloc_cv___attribute__const=0 - hwloc_cv___attribute__deprecated=0 - hwloc_cv___attribute__format=0 - hwloc_cv___attribute__hot=0 - hwloc_cv___attribute__malloc=0 - hwloc_cv___attribute__may_alias=0 - hwloc_cv___attribute__no_instrument_function=0 - hwloc_cv___attribute__nonnull=0 - hwloc_cv___attribute__noreturn=0 - hwloc_cv___attribute__packed=0 - hwloc_cv___attribute__pure=0 - hwloc_cv___attribute__sentinel=0 - hwloc_cv___attribute__unused=0 - hwloc_cv___attribute__warn_unused_result=0 - hwloc_cv___attribute__weak_alias=0 - else - AC_MSG_RESULT([yes]) - - _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([aligned], - [struct foo { char text[4]; } __attribute__ ((__aligned__(8)));], - [], - []) - - # - # Ignored by PGI-6.2.5; -- recognized by output-parser - # - _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([always_inline], - [int foo (int arg) __attribute__ ((__always_inline__));], - [], - []) - - _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([cold], - [ - int foo(int arg1, int arg2) __attribute__ ((__cold__)); - int foo(int arg1, int arg2) { return arg1 * arg2 + arg1; } - ], - [], - []) - - _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([const], - [ - int foo(int arg1, int arg2) __attribute__ ((__const__)); - int foo(int arg1, int arg2) { return arg1 * arg2 + arg1; } - ], - [], - []) - - - _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([deprecated], - [ - int foo(int arg1, int arg2) __attribute__ ((__deprecated__)); - int foo(int arg1, int arg2) { return arg1 * arg2 + arg1; } - ], - [], - []) - - - HWLOC_ATTRIBUTE_CFLAGS= - case "$hwloc_c_vendor" in - gnu) - HWLOC_ATTRIBUTE_CFLAGS="-Wall" - ;; - intel) - # we want specifically the warning on format string conversion - HWLOC_ATTRIBUTE_CFLAGS="-we181" - ;; - esac - _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([format], - [ - int this_printf (void *my_object, const char *my_format, ...) __attribute__ ((__format__ (__printf__, 2, 3))); - ], - [ - static int usage (int * argument); - extern int this_printf (int arg1, const char *my_format, ...) __attribute__ ((__format__ (__printf__, 2, 3))); - - static int usage (int * argument) { - return this_printf (*argument, "%d", argument); /* This should produce a format warning */ - } - /* The autoconf-generated main-function is int main(), which produces a warning by itself */ - int main(void); - ], - [$HWLOC_ATTRIBUTE_CFLAGS]) - - _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([hot], - [ - int foo(int arg1, int arg2) __attribute__ ((__hot__)); - int foo(int arg1, int arg2) { return arg1 * arg2 + arg1; } - ], - [], - []) - - _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([malloc], - [ -#ifdef HAVE_STDLIB_H -# include -#endif - int * foo(int arg1) __attribute__ ((__malloc__)); - int * foo(int arg1) { return (int*) malloc(arg1); } - ], - [], - []) - - - # - # Attribute may_alias: No suitable cross-check available, that works for non-supporting compilers - # Ignored by intel-9.1.045 -- turn off with -wd1292 - # Ignored by PGI-6.2.5; ignore not detected due to missing cross-check - # - _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([may_alias], - [int * p_value __attribute__ ((__may_alias__));], - [], - []) - - - _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([no_instrument_function], - [int * foo(int arg1) __attribute__ ((__no_instrument_function__));], - [], - []) - - - # - # Attribute nonnull: - # Ignored by intel-compiler 9.1.045 -- recognized by cross-check - # Ignored by PGI-6.2.5 (pgCC) -- recognized by cross-check - # - HWLOC_ATTRIBUTE_CFLAGS= - case "$hwloc_c_vendor" in - gnu) - HWLOC_ATTRIBUTE_CFLAGS="-Wall" - ;; - intel) - # we do not want to get ignored attributes warnings, but rather real warnings - HWLOC_ATTRIBUTE_CFLAGS="-wd1292" - ;; - esac - _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([nonnull], - [ - int square(int *arg) __attribute__ ((__nonnull__)); - int square(int *arg) { return *arg; } - ], - [ - static int usage(int * argument); - int square(int * argument) __attribute__ ((__nonnull__)); - int square(int * argument) { return (*argument) * (*argument); } - - static int usage(int * argument) { - return square( ((void*)0) ); /* This should produce an argument must be nonnull warning */ - } - /* The autoconf-generated main-function is int main(), which produces a warning by itself */ - int main(void); - ], - [$HWLOC_ATTRIBUTE_CFLAGS]) - - - _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([noreturn], - [ -#ifdef HAVE_UNISTD_H -# include -#endif -#ifdef HAVE_STDLIB_H -# include -#endif - void fatal(int arg1) __attribute__ ((__noreturn__)); - void fatal(int arg1) { exit(arg1); } - ], - [], - []) - - _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([packed], - [ - struct foo { - char a; - int x[2] __attribute__ ((__packed__)); - }; - ], - [], - []) - - _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([pure], - [ - int square(int arg) __attribute__ ((__pure__)); - int square(int arg) { return arg * arg; } - ], - [], - []) - - # - # Attribute sentinel: - # Ignored by the intel-9.1.045 -- recognized by cross-check - # intel-10.0beta works fine - # Ignored by PGI-6.2.5 (pgCC) -- recognized by output-parser and cross-check - # Ignored by pathcc-2.2.1 -- recognized by cross-check (through grep ignore) - # - HWLOC_ATTRIBUTE_CFLAGS= - case "$hwloc_c_vendor" in - gnu) - HWLOC_ATTRIBUTE_CFLAGS="-Wall" - ;; - intel) - # we do not want to get ignored attributes warnings - HWLOC_ATTRIBUTE_CFLAGS="-wd1292" - ;; - esac - _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([sentinel], - [ - int my_execlp(const char * file, const char *arg, ...) __attribute__ ((__sentinel__)); - ], - [ - static int usage(int * argument); - int my_execlp(const char * file, const char *arg, ...) __attribute__ ((__sentinel__)); - - static int usage(int * argument) { - void * last_arg_should_be_null = argument; - return my_execlp ("lala", "/home/there", last_arg_should_be_null); /* This should produce a warning */ - } - /* The autoconf-generated main-function is int main(), which produces a warning by itself */ - int main(void); - ], - [$HWLOC_ATTRIBUTE_CFLAGS]) - - _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([unused], - [ - int square(int arg1 __attribute__ ((__unused__)), int arg2); - int square(int arg1, int arg2) { return arg2; } - ], - [], - []) - - - # - # Attribute warn_unused_result: - # Ignored by the intel-compiler 9.1.045 -- recognized by cross-check - # Ignored by pathcc-2.2.1 -- recognized by cross-check (through grep ignore) - # - HWLOC_ATTRIBUTE_CFLAGS= - case "$hwloc_c_vendor" in - gnu) - HWLOC_ATTRIBUTE_CFLAGS="-Wall" - ;; - intel) - # we do not want to get ignored attributes warnings - HWLOC_ATTRIBUTE_CFLAGS="-wd1292" - ;; - esac - _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([warn_unused_result], - [ - int foo(int arg) __attribute__ ((__warn_unused_result__)); - int foo(int arg) { return arg + 3; } - ], - [ - static int usage(int * argument); - int foo(int arg) __attribute__ ((__warn_unused_result__)); - - int foo(int arg) { return arg + 3; } - static int usage(int * argument) { - foo (*argument); /* Should produce an unused result warning */ - return 0; - } - - /* The autoconf-generated main-function is int main(), which produces a warning by itself */ - int main(void); - ], - [$HWLOC_ATTRIBUTE_CFLAGS]) - - - _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([weak_alias], - [ - int foo(int arg); - int foo(int arg) { return arg + 3; } - int foo2(int arg) __attribute__ ((__weak__, __alias__("foo"))); - ], - [], - []) - - fi - - # Now that all the values are set, define them - - AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_ALIGNED, [$hwloc_cv___attribute__aligned], - [Whether your compiler has __attribute__ aligned or not]) - AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_ALWAYS_INLINE, [$hwloc_cv___attribute__always_inline], - [Whether your compiler has __attribute__ always_inline or not]) - AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_COLD, [$hwloc_cv___attribute__cold], - [Whether your compiler has __attribute__ cold or not]) - AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_CONST, [$hwloc_cv___attribute__const], - [Whether your compiler has __attribute__ const or not]) - AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_DEPRECATED, [$hwloc_cv___attribute__deprecated], - [Whether your compiler has __attribute__ deprecated or not]) - AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_FORMAT, [$hwloc_cv___attribute__format], - [Whether your compiler has __attribute__ format or not]) - AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_HOT, [$hwloc_cv___attribute__hot], - [Whether your compiler has __attribute__ hot or not]) - AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_MALLOC, [$hwloc_cv___attribute__malloc], - [Whether your compiler has __attribute__ malloc or not]) - AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_MAY_ALIAS, [$hwloc_cv___attribute__may_alias], - [Whether your compiler has __attribute__ may_alias or not]) - AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_NO_INSTRUMENT_FUNCTION, [$hwloc_cv___attribute__no_instrument_function], - [Whether your compiler has __attribute__ no_instrument_function or not]) - AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_NONNULL, [$hwloc_cv___attribute__nonnull], - [Whether your compiler has __attribute__ nonnull or not]) - AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_NORETURN, [$hwloc_cv___attribute__noreturn], - [Whether your compiler has __attribute__ noreturn or not]) - AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_PACKED, [$hwloc_cv___attribute__packed], - [Whether your compiler has __attribute__ packed or not]) - AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_PURE, [$hwloc_cv___attribute__pure], - [Whether your compiler has __attribute__ pure or not]) - AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_SENTINEL, [$hwloc_cv___attribute__sentinel], - [Whether your compiler has __attribute__ sentinel or not]) - AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_UNUSED, [$hwloc_cv___attribute__unused], - [Whether your compiler has __attribute__ unused or not]) - AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_WARN_UNUSED_RESULT, [$hwloc_cv___attribute__warn_unused_result], - [Whether your compiler has __attribute__ warn unused result or not]) - 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/hwloc191/hwloc/config/hwloc_check_vendor.m4 b/opal/mca/hwloc/hwloc191/hwloc/config/hwloc_check_vendor.m4 deleted file mode 100644 index 1a9b944e25..0000000000 --- a/opal/mca/hwloc/hwloc191/hwloc/config/hwloc_check_vendor.m4 +++ /dev/null @@ -1,239 +0,0 @@ -dnl -*- shell-script -*- -dnl -dnl Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana -dnl University Research and Technology -dnl Corporation. All rights reserved. -dnl Copyright (c) 2004-2005 The University of Tennessee and The University -dnl of Tennessee Research Foundation. All rights -dnl reserved. -dnl Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, -dnl University of Stuttgart. All rights reserved. -dnl Copyright (c) 2004-2005 The Regents of the University of California. -dnl All rights reserved. -dnl Copyright (c) 2011 Cisco Systems, Inc. All rights reserved. -dnl $COPYRIGHT$ -dnl -dnl Additional copyrights may follow -dnl -dnl $HEADER$ -dnl - -dnl ------------------------------------------------------------------ -dnl This m4 file originally copied from Open MPI -dnl config/ompi_check_vendor.m4. -dnl ------------------------------------------------------------------ - - -# HWLOC_C_COMPILER_VENDOR(VENDOR_VARIABLE) -# --------------------------------------- -# Set shell variable VENDOR_VARIABLE to the name of the compiler -# vendor for the current C compiler. -# -# See comment for _HWLOC_CHECK_COMPILER_VENDOR for a complete -# list of currently detected compilers. -AC_DEFUN([_HWLOC_C_COMPILER_VENDOR], [ - AC_REQUIRE([AC_PROG_CC]) - - AC_CACHE_CHECK([for the C compiler vendor], - [hwloc_cv_c_compiler_vendor], - [AC_LANG_PUSH(C) - _HWLOC_CHECK_COMPILER_VENDOR([hwloc_cv_c_compiler_vendor]) - AC_LANG_POP(C)]) - - $1="$hwloc_cv_c_compiler_vendor" -]) - - -# workaround to avoid syntax error with Autoconf < 2.68: -m4_ifndef([AC_LANG_DEFINES_PROVIDED], - [m4_define([AC_LANG_DEFINES_PROVIDED])]) - -# HWLOC_IFDEF_IFELSE(symbol, [action-if-defined], -# [action-if-not-defined]) -# ---------------------------------------------- -# Run compiler to determine if preprocessor symbol "symbol" is -# defined by the compiler. -AC_DEFUN([HWLOC_IFDEF_IFELSE], [ - AC_COMPILE_IFELSE([AC_LANG_DEFINES_PROVIDED -#ifndef $1 -#error "symbol $1 not defined" -choke me -#endif], [$2], [$3])]) - - -# HWLOC_IF_IFELSE(symbol, [action-if-defined], -# [action-if-not-defined]) -# ---------------------------------------------- -# Run compiler to determine if preprocessor symbol "symbol" is -# defined by the compiler. -AC_DEFUN([HWLOC_IF_IFELSE], [ - AC_COMPILE_IFELSE([AC_LANG_DEFINES_PROVIDED -#if !( $1 ) -#error "condition $1 not met" -choke me -#endif], [$2], [$3])]) - - -# _HWLOC_CHECK_COMPILER_VENDOR(VENDOR_VARIABLE) -# -------------------------------------------- -# Set shell variable VENDOR_VARIABLE to the name of the compiler -# vendor for the compiler for the current language. Language must be -# one of C, OBJC, or C++. -# -# thanks to http://predef.sourceforge.net/precomp.html for the list -# of defines to check. -AC_DEFUN([_HWLOC_CHECK_COMPILER_VENDOR], [ - hwloc_check_compiler_vendor_result="unknown" - - # GNU is probably the most common, so check that one as soon as - # possible. Intel pretends to be GNU, so need to check Intel - # before checking for GNU. - - # Intel - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IF_IFELSE([defined(__INTEL_COMPILER) || defined(__ICC)], - [hwloc_check_compiler_vendor_result="intel"])]) - - # GNU - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IFDEF_IFELSE([__GNUC__], - [hwloc_check_compiler_vendor_result="gnu"])]) - - # Borland Turbo C - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IFDEF_IFELSE([__TURBOC__], - [hwloc_check_compiler_vendor_result="borland"])]) - - # Borland C++ - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IFDEF_IFELSE([__BORLANDC__], - [hwloc_check_compiler_vendor_result="borland"])]) - - # Comeau C++ - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IFDEF_IFELSE([__COMO__], - [hwloc_check_compiler_vendor_result="comeau"])]) - - # Compaq C/C++ - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IF_IFELSE([defined(__DECC) || defined(VAXC) || defined(__VAXC)], - [hwloc_check_compiler_vendor_result="compaq"], - [HWLOC_IF_IFELSE([defined(__osf__) && defined(__LANGUAGE_C__)], - [hwloc_check_compiler_vendor_result="compaq"], - [HWLOC_IFDEF_IFELSE([__DECCXX], - [hwloc_check_compiler_vendor_result="compaq"])])])]) - - # Cray C/C++ - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IFDEF_IFELSE([_CRAYC], - [hwloc_check_compiler_vendor_result="cray"])]) - - # Diab C/C++ - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IFDEF_IFELSE([__DCC__], - [hwloc_check_compiler_vendor_result="diab"])]) - - # Digital Mars - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IF_IFELSE([defined(__DMC__) || defined(__SC__) || defined(__ZTC__)], - [hwloc_check_compiler_vendor_result="digital mars"])]) - - # HP ANSI C / aC++ - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IF_IFELSE([defined(__HP_cc) || defined(__HP_aCC)], - [hwloc_check_compiler_vendor_result="hp"])]) - - # IBM XL C/C++ - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IF_IFELSE([defined(__xlC__) || defined(__IBMC__) || defined(__IBMCPP__)], - [hwloc_check_compiler_vendor_result="ibm"], - [HWLOC_IF_IFELSE([defined(_AIX) && !defined(__GNUC__)], - [hwloc_check_compiler_vendor_result="ibm"])])]) - - # KAI C++ (rest in peace) - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IFDEF_IFELSE([__KCC], - [hwloc_check_compiler_vendor_result="kai"])]) - - # LCC - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IFDEF_IFELSE([__LCC__], - [hwloc_check_compiler_vendor_result="lcc"])]) - - # MetaWare High C/C++ - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IFDEF_IFELSE([__HIGHC__], - [hwloc_check_compiler_vendor_result="metaware high"])]) - - # Metrowerks Codewarrior - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IFDEF_IFELSE([__MWERKS__], - [hwloc_check_compiler_vendor_result="metrowerks"])]) - - # MIPSpro (SGI) - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IF_IFELSE([defined(sgi) || defined(__sgi)], - [hwloc_check_compiler_vendor_result="sgi"])]) - - # MPW C++ - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IF_IFELSE([defined(__MRC__) || defined(MPW_C) || defined(MPW_CPLUS)], - [hwloc_check_compiler_vendor_result="mpw"])]) - - # Microsoft - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [# Always use C compiler when checking for Microsoft, as - # Visual C++ doesn't recognize .cc as a C++ file. - AC_LANG_PUSH(C) - HWLOC_IF_IFELSE([defined(_MSC_VER) || defined(__MSC_VER)], - [hwloc_check_compiler_vendor_result="microsoft"]) - AC_LANG_POP(C)]) - - # Norcroft C - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IFDEF_IFELSE([__CC_NORCROFT], - [hwloc_check_compiler_vendor_result="norcroft"])]) - - # Pelles C - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IFDEF_IFELSE([__POCC__], - [hwloc_check_compiler_vendor_result="pelles"])]) - - # Portland Group - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IFDEF_IFELSE([__PGI], - [hwloc_check_compiler_vendor_result="portland group"])]) - - # SAS/C - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IF_IFELSE([defined(SASC) || defined(__SASC) || defined(__SASC__)], - [hwloc_check_compiler_vendor_result="sas"])]) - - # Sun Workshop C/C++ - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IF_IFELSE([defined(__SUNPRO_C) || defined(__SUNPRO_CC)], - [hwloc_check_compiler_vendor_result="sun"])]) - - # TenDRA C/C++ - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IFDEF_IFELSE([__TenDRA__], - [hwloc_check_compiler_vendor_result="tendra"])]) - - # Tiny C - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IFDEF_IFELSE([__TINYC__], - [hwloc_check_compiler_vendor_result="tiny"])]) - - # USL C - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IFDEF_IFELSE([__USLC__], - [hwloc_check_compiler_vendor_result="usl"])]) - - # Watcom C++ - AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"], - [HWLOC_IFDEF_IFELSE([__WATCOMC__], - [hwloc_check_compiler_vendor_result="watcom"])]) - - $1="$hwloc_check_compiler_vendor_result" - unset hwloc_check_compiler_vendor_result -]) diff --git a/opal/mca/hwloc/hwloc191/hwloc/config/hwloc_check_visibility.m4 b/opal/mca/hwloc/hwloc191/hwloc/config/hwloc_check_visibility.m4 deleted file mode 100644 index 654ae7aa94..0000000000 --- a/opal/mca/hwloc/hwloc191/hwloc/config/hwloc_check_visibility.m4 +++ /dev/null @@ -1,131 +0,0 @@ -# This macro set originally copied from Open MPI: -# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana -# University Research and Technology -# Corporation. All rights reserved. -# Copyright (c) 2004-2005 The University of Tennessee and The University -# of Tennessee Research Foundation. All rights -# reserved. -# Copyright (c) 2004-2007 High Performance Computing Center Stuttgart, -# University of Stuttgart. All rights reserved. -# Copyright (c) 2004-2005 The Regents of the University of California. -# All rights reserved. -# Copyright (c) 2006-2007 Cisco Systems, Inc. All rights reserved. -# and renamed/modified for hwloc: -# Copyright (c) 2009 inria. All rights reserved. -# Copyright (c) 2009-2010 Université Bordeaux 1 -# Copyright © 2010-2012 Cisco Systems, Inc. All rights reserved. -# See COPYING in top-level directory. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# - Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# - Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer listed -# in this license in the documentation and/or other materials -# provided with the distribution. -# -# - Neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# The copyright holders provide no reassurances that the source code -# provided does not infringe any patent, copyright, or any other -# intellectual property rights of third parties. The copyright holders -# disclaim any liability to any recipient for claims brought against -# recipient by any third party for infringement of that parties -# intellectual property rights. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -# _HWLOC_CHECK_VISIBILITY -# -------------------------------------------------------- -AC_DEFUN([_HWLOC_CHECK_VISIBILITY],[ - # Be safe for systems that have ancient Autoconf's (e.g., RHEL5) - m4_ifdef([AC_PROG_GREP], - [AC_REQUIRE([AC_PROG_GREP])], - [GREP=grep]) - - # Check if the compiler has support for visibility, like some - # versions of gcc, icc, Sun Studio cc. - AC_ARG_ENABLE(visibility, - AC_HELP_STRING([--enable-visibility], - [enable visibility feature of certain compilers/linkers (default: enabled on platforms that support it)])) - - case ${target} in - *-*-aix*|*-*-mingw*|*-*-cygwin*|*-*-hpux*) - enable_visibility=no - ;; - esac - - hwloc_visibility_define=0 - hwloc_msg="whether to enable symbol visibility" - if test "$enable_visibility" = "no"; then - AC_MSG_CHECKING([$hwloc_msg]) - AC_MSG_RESULT([no (disabled)]) - else - CFLAGS_orig=$CFLAGS - - hwloc_add= - case "$hwloc_c_vendor" in - sun) - # Check using Sun Studio -xldscope=hidden flag - hwloc_add=-xldscope=hidden - CFLAGS="$CFLAGS_orig $hwloc_add -errwarn=%all" - ;; - - *) - # Check using -fvisibility=hidden - hwloc_add=-fvisibility=hidden - CFLAGS="$CFLAGS_orig $hwloc_add -Werror" - ;; - esac - - AC_MSG_CHECKING([if $CC supports $hwloc_add]) - AC_LINK_IFELSE([AC_LANG_PROGRAM([[ - #include - __attribute__((visibility("default"))) int foo; - ]],[[fprintf(stderr, "Hello, world\n");]])], - [AS_IF([test -s conftest.err], - [$GREP -iq visibility conftest.err - # If we find "visibility" in the stderr, then - # assume it doesn't work - AS_IF([test "$?" = "0"], [hwloc_add=])]) - ], [hwloc_add=]) - AS_IF([test "$hwloc_add" = ""], - [AC_MSG_RESULT([no])], - [AC_MSG_RESULT([yes])]) - - CFLAGS=$CFLAGS_orig - HWLOC_VISIBILITY_CFLAGS=$hwloc_add - - if test "$hwloc_add" != "" ; then - hwloc_visibility_define=1 - AC_MSG_CHECKING([$hwloc_msg]) - AC_MSG_RESULT([yes (via $hwloc_add)]) - elif test "$enable_visibility" = "yes"; then - AC_MSG_ERROR([Symbol visibility support requested but compiler does not seem to support it. Aborting]) - else - AC_MSG_CHECKING([$hwloc_msg]) - AC_MSG_RESULT([no (unsupported)]) - fi - unset hwloc_add - fi - - AC_DEFINE_UNQUOTED([HWLOC_C_HAVE_VISIBILITY], [$hwloc_visibility_define], - [Whether C compiler supports symbol visibility or not]) -]) diff --git a/opal/mca/hwloc/hwloc191/hwloc/config/hwloc_components.m4 b/opal/mca/hwloc/hwloc191/hwloc/config/hwloc_components.m4 deleted file mode 100644 index 7d5c1fa194..0000000000 --- a/opal/mca/hwloc/hwloc191/hwloc/config/hwloc_components.m4 +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright © 2012 Inria. All rights reserved. -# See COPYING in top-level directory. - - -# HWLOC_PREPARE_FILTER_COMPONENTS -# -# Given a comma-separated list of names, define hwloc__component_maybeplugin=1. -# -# $1 = command-line given list of components to build as plugins -# -AC_DEFUN([HWLOC_PREPARE_FILTER_COMPONENTS], [ - for name in `echo [$1] | sed -e 's/,/ /g'` ; do - str="hwloc_${name}_component_wantplugin=1" - eval $str - done -]) - - -# HWLOC_FILTER_COMPONENTS -# -# For each component in hwloc_components, -# check if hwloc__component_wantplugin=1 or enable_plugin=yes, -# and check if hwloc__component_maybeplugin=1. -# Add to hwloc_[static|plugin]_components accordingly. -# And set hwloc__component=[static|plugin] accordingly. -# -AC_DEFUN([HWLOC_FILTER_COMPONENTS], [ -for name in $hwloc_components ; do - str="maybeplugin=\$hwloc_${name}_component_maybeplugin" - eval $str - str="wantplugin=\$hwloc_${name}_component_wantplugin" - eval $str - if test x$hwloc_have_plugins = xyes && test x$maybeplugin = x1 && test x$wantplugin = x1 -o x$enable_plugins = xyes; then - hwloc_plugin_components="$hwloc_plugin_components $name" - str="hwloc_${name}_component=plugin" - else - hwloc_static_components="$hwloc_static_components $name" - str="hwloc_${name}_component=static" - fi - eval $str -done -]) - - -# HWLOC_LIST_STATIC_COMPONENTS -# -# Append to file $1 an array of components by listing component names in $2. -# -# $1 = filename -# $2 = list of component names -# -AC_DEFUN([HWLOC_LIST_STATIC_COMPONENTS], [ -for comp in [$2]; do - echo "HWLOC_DECLSPEC extern const struct hwloc_component hwloc_${comp}_component;" >>[$1] -done -cat <>[$1] -static const struct hwloc_component * hwloc_static_components[[]] = { -EOF -for comp in [$2]; do - echo " &hwloc_${comp}_component," >>[$1] -done -cat <>[$1] - NULL -}; -EOF -]) diff --git a/opal/mca/hwloc/hwloc191/hwloc/config/hwloc_get_version.sh b/opal/mca/hwloc/hwloc191/hwloc/config/hwloc_get_version.sh deleted file mode 100755 index c27152e6fa..0000000000 --- a/opal/mca/hwloc/hwloc191/hwloc/config/hwloc_get_version.sh +++ /dev/null @@ -1,99 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana -# University Research and Technology -# Corporation. All rights reserved. -# Copyright (c) 2004-2005 The University of Tennessee and The University -# of Tennessee Research Foundation. All rights -# reserved. -# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, -# University of Stuttgart. All rights reserved. -# Copyright (c) 2004-2005 The Regents of the University of California. -# All rights reserved. -# Copyright © 2008-2013 Cisco Systems, Inc. All rights reserved. -# $COPYRIGHT$ -# -# Additional copyrights may follow -# -# $HEADER$ -# - -srcfile="$1" -option="$2" - -if test -z "$srcfile"; then - option="--help" -else - : ${srcdir=.} - - 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/^date/HWLOC_RELEASE_DATE/ - s/^snapshot_version/HWLOC_SNAPSHOT_VERSION/ - s/^snapshot/HWLOC_SNAPSHOT/ - t print - b - : print - p" < "$srcfile"` - eval "$ompi_vers" - - # Only include the release version if it isn't 0 - if test $HWLOC_RELEASE_VERSION -ne 0 ; then - HWLOC_VERSION="$HWLOC_MAJOR_VERSION.$HWLOC_MINOR_VERSION.$HWLOC_RELEASE_VERSION" - else - HWLOC_VERSION="$HWLOC_MAJOR_VERSION.$HWLOC_MINOR_VERSION" - fi - HWLOC_VERSION="${HWLOC_VERSION}${HWLOC_GREEK_VERSION}" - - # If HWLOC_SNAPSHOT=1, then use HWLOC_SNAPSHOT_VERSION - if test "$HWLOC_SNAPSHOT" = "1"; then - # First, verify that HWLOC_SNAPSHOT_VERSION isn't empty. - if test -z "$HWLOC_SNAPSHOT_VERSION"; then - echo "*** ERROR: $1 contains snapshot=1, but an empty value for snapshot_version" 1>&2 - exit 1 - fi - HWLOC_VERSION=$HWLOC_SNAPSHOT_VERSION - fi - fi - - if test "$option" = ""; then - option="--version" - fi -fi - -case "$option" in - --version) - echo $HWLOC_VERSION - ;; - --release-date) - echo $HWLOC_RELEASE_DATE - ;; - --snapshot) - echo $HWLOC_SNAPSHOT - ;; - -h|--help) - cat <