From 38d3cdd4a619fdf9440e7b8e144630b68f268258 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Tue, 12 Apr 2011 14:16:37 +0000 Subject: [PATCH] Update hwloc to 1.1.1. Next stop: 1.1.2. This commit was SVN r24610. --- opal/mca/common/hwloc/hwloc/NEWS | 33 +- opal/mca/common/hwloc/hwloc/README | 22 +- opal/mca/common/hwloc/hwloc/VERSION | 8 +- opal/mca/common/hwloc/hwloc/config/hwloc.m4 | 12 +- .../hwloc/hwloc/config/hwloc_internal.m4 | 16 + opal/mca/common/hwloc/hwloc/include/hwloc.h | 561 ++++++++++++++---- .../common/hwloc/hwloc/include/hwloc/bitmap.h | 31 +- .../common/hwloc/hwloc/include/hwloc/helper.h | 10 +- .../common/hwloc/hwloc/include/hwloc/rename.h | 51 ++ opal/mca/common/hwloc/hwloc/src/cpuset.c | 76 ++- .../common/hwloc/hwloc/src/topology-linux.c | 25 +- .../hwloc/hwloc/src/topology-synthetic.c | 8 +- .../common/hwloc/hwloc/src/topology-windows.c | 6 +- opal/mca/common/hwloc/hwloc/src/topology.c | 6 + opal/mca/common/hwloc/hwloc/src/traversal.c | 3 +- 15 files changed, 682 insertions(+), 186 deletions(-) diff --git a/opal/mca/common/hwloc/hwloc/NEWS b/opal/mca/common/hwloc/hwloc/NEWS index 120d4ab35e..209c1c43e5 100644 --- a/opal/mca/common/hwloc/hwloc/NEWS +++ b/opal/mca/common/hwloc/hwloc/NEWS @@ -1,7 +1,7 @@ Copyright © 2009 CNRS -Copyright © 2009-2010 INRIA -Copyright © 2009-2010 Université Bordeaux 1 -Copyright © 2009-2010 Cisco Systems, Inc. All rights reserved. +Copyright © 2009-2011 INRIA +Copyright © 2009-2011 Université Bordeaux 1 +Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved. $COPYRIGHT$ @@ -16,6 +16,33 @@ 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.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 ------------- diff --git a/opal/mca/common/hwloc/hwloc/README b/opal/mca/common/hwloc/hwloc/README index 6909839a5c..5a8478f83d 100644 --- a/opal/mca/common/hwloc/hwloc/README +++ b/opal/mca/common/hwloc/hwloc/README @@ -23,7 +23,7 @@ from PLPA 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, and Kerrighed support) + knowledge of cpusets, offline CPUs, ScaleMP vSMP, and Kerrighed support) * Solaris * AIX * Darwin / OS X @@ -345,8 +345,8 @@ 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. +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 @@ -671,12 +671,12 @@ Further Reading The documentation chapters include * Terms and Definitions - * Command-line tools - * Environment variables - * CPU Binding and Memory Binding - * Interoperability with other software - * Thread safety - * Embedding hwloc in other software + * Command-Line Tools + * Environment Variables + * CPU and Memory Binding Overview + * Interoperability With Other Software + * Thread Safety + * Embedding hwloc in Other Software * Switching from PLPA to hwloc * Frequently Asked Questions @@ -684,5 +684,5 @@ Make sure to have had a look at those too! ------------------------------------------------------------------------------- -Generated on Thu Dec 16 2010 16:48:29 for Hardware Locality (hwloc) by doxygen -1.7.1 +Generated on Mon Jan 24 2011 17:12:06 for Hardware Locality (hwloc) by doxygen +1.7.2 diff --git a/opal/mca/common/hwloc/hwloc/VERSION b/opal/mca/common/hwloc/hwloc/VERSION index 87758a1214..d9dabc50f4 100644 --- a/opal/mca/common/hwloc/hwloc/VERSION +++ b/opal/mca/common/hwloc/hwloc/VERSION @@ -7,7 +7,7 @@ major=1 minor=1 -release=0 +release=1 # 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 @@ -33,11 +33,11 @@ want_svn=0 # distribution tarball is being made from an SVN checkout, the value # of svn_r in this file is replaced with the output of "svnversion". -svn_r=r2935 +svn_r=r3129 # The date when this release was created -date="Dec 16, 2010" +date="Jan 24, 2011" # The shared library version of hwloc's public library. This version # is maintained in accordance with the "Library Interface Versions" @@ -50,4 +50,4 @@ date="Dec 16, 2010" # 2. Version numbers are described in the Libtool current:revision:age # format. -libhwloc_so_version=1:0:1 +libhwloc_so_version=2:0:2 diff --git a/opal/mca/common/hwloc/hwloc/config/hwloc.m4 b/opal/mca/common/hwloc/hwloc/config/hwloc.m4 index 72134dc6d9..9eb3d6e2af 100644 --- a/opal/mca/common/hwloc/hwloc/config/hwloc.m4 +++ b/opal/mca/common/hwloc/hwloc/config/hwloc.m4 @@ -1,7 +1,7 @@ dnl -*- Autoconf -*- dnl -dnl Copyright (c) 2009 INRIA -dnl Copyright (c) 2009 Université Bordeaux 1 +dnl Copyright (c) 2009-2010 INRIA +dnl Copyright (c) 2009-2011 Université Bordeaux 1 dnl Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana dnl University Research and Technology dnl Corporation. All rights reserved. @@ -9,8 +9,6 @@ dnl Copyright (c) 2004-2005 The Regents of the University of California. dnl All rights reserved. dnl Copyright (c) 2004-2008 High Performance Computing Center Stuttgart, dnl University of Stuttgart. All rights reserved. -dnl Copyright © 2010 INRIA -dnl Copyright © 2010 Université of Bordeaux dnl Copyright © 2006-2010 Cisco Systems, Inc. All rights reserved. # Main hwloc m4 macro, to be invoked by the user @@ -238,7 +236,7 @@ AC_DEFUN([HWLOC_SETUP_CORE_AFTER_C99],[ AC_MSG_WARN([***********************************************************]) AC_MSG_WARN([*** hwloc does not support this system.]) AC_MSG_WARN([*** hwloc will *attempt* to build (but it may not work).]) - AC_MSG_WARN([*** hwloc's run-time results may be reduced to showing just one processor.]) + AC_MSG_WARN([*** hwloc run-time results may be reduced to showing just one processor.]) AC_MSG_WARN([*** You have been warned.]) AC_MSG_WARN([*** Pausing to give you time to read this message...]) AC_MSG_WARN([***********************************************************]) @@ -283,7 +281,7 @@ AC_DEFUN([HWLOC_SETUP_CORE_AFTER_C99],[ _HWLOC_CHECK_VISIBILITY HWLOC_CFLAGS="$HWLOC_FLAGS $HWLOC_VISIBILITY_CFLAGS" AS_IF([test "$HWLOC_VISIBILITY_CFLAGS" != ""], - [AC_MSG_WARN(["$HWLOC_VISIBILITY_CFLAGS" has been added to hwloc's CFLAGS])]) + [AC_MSG_WARN(["$HWLOC_VISIBILITY_CFLAGS" has been added to the hwloc CFLAGS])]) # # Check for inline compatibility support @@ -584,7 +582,7 @@ AC_DEFUN([HWLOC_SETUP_CORE_AFTER_C99],[ AC_MSG_CHECKING([for cpuid]) old_CPPFLAGS="$CPPFLAGS" CFLAGS="$CFLAGS -I$HWLOC_top_srcdir/include" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ diff --git a/opal/mca/common/hwloc/hwloc/config/hwloc_internal.m4 b/opal/mca/common/hwloc/hwloc/config/hwloc_internal.m4 index 79cfb76e09..ba5a18422f 100644 --- a/opal/mca/common/hwloc/hwloc/config/hwloc_internal.m4 +++ b/opal/mca/common/hwloc/hwloc/config/hwloc_internal.m4 @@ -105,6 +105,22 @@ EOF [hwloc_generate_doxs=yes], [hwloc_generate_doxs=no]) AC_MSG_RESULT([$hwloc_generate_doxs]) + # Linux and OS X take different sed arguments. + AC_PROG_SED + AC_MSG_CHECKING([if the sed -i option requires an argument]) + rm -f conftest + cat > conftest < /dev/null + AS_IF([test -f conftest-e], + [SED_I="$SED -i ''" + AC_MSG_RESULT([yes])], + [SED_I="$SED -i" + AC_MSG_RESULT([no])]) + rm -f conftest conftest-e + AC_SUBST([SED_I]) + # Making the top-level README requires w3m or lynx. AC_ARG_VAR([W3M], [Location of the w3m program (required to building the top-level hwloc README file)]) AC_PATH_TOOL([W3M], [w3m]) diff --git a/opal/mca/common/hwloc/hwloc/include/hwloc.h b/opal/mca/common/hwloc/hwloc/include/hwloc.h index 2a2e4c30e9..58371d70a0 100644 --- a/opal/mca/common/hwloc/hwloc/include/hwloc.h +++ b/opal/mca/common/hwloc/hwloc/include/hwloc.h @@ -1,8 +1,8 @@ /* * Copyright © 2009 CNRS * Copyright © 2009-2010 INRIA - * Copyright © 2009-2010 Université Bordeaux 1 - * Copyright © 2009-2010 Cisco Systems, Inc. All rights reserved. + * Copyright © 2009-2011 Université Bordeaux 1 + * Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved. * See COPYING in top-level directory. */ @@ -50,6 +50,9 @@ extern "C" { /** \brief Indicate at build time which hwloc API version is being used. */ #define HWLOC_API_VERSION 0x00010100 +/** \brief Indicate at runtime which hwloc API version was used at build time. */ +HWLOC_DECLSPEC unsigned hwloc_get_api_version(void); + /** @} */ @@ -69,21 +72,41 @@ typedef struct hwloc_topology * hwloc_topology_t; -/** \defgroup hwlocality_sets Object sets +/** \defgroup hwlocality_sets Object sets (hwloc_cpuset_t and hwloc_nodeset_t) + * + * Hwloc uses bitmaps to represent two distinct kinds of object sets: + * CPU sets (::hwloc_cpuset_t) and NUMA node sets (::hwloc_nodeset_t). + * These types are both typedefs to a common back end type + * (::hwloc_bitmap_t), and therefore all the hwloc bitmap functions + * are applicable to both ::hwloc_cpuset_t and ::hwloc_nodeset_t (see + * \ref hwlocality_bitmap). + * + * The rationale for having two different types is that even though + * the actions one wants to perform on these types are the same (e.g., + * enable and disable individual items in the set/mask), they're used + * in very different contexts: one for specifying which processors to + * use and one for specifying which NUMA nodes to use. Hence, the + * name difference is really just to reflect the intent of where the + * type is used. + * * @{ */ -/** \brief A CPU set is a bitmap whose bits are set according to CPU physical OS indexes. +/** \brief A CPU set is a bitmap whose bits are set according to CPU + * physical OS indexes. * - * It may be consulted and modified with the bitmap API as any ::hwloc_bitmap_t (see hwloc/bitmap.h). + * It may be consulted and modified with the bitmap API as any + * ::hwloc_bitmap_t (see hwloc/bitmap.h). */ typedef hwloc_bitmap_t hwloc_cpuset_t; /** \brief A non-modifiable ::hwloc_cpuset_t. */ typedef hwloc_const_bitmap_t hwloc_const_cpuset_t; -/** \brief A node set is a bitmap whose bits are set according to NUMA memory node physical OS indexes. +/** \brief A node set is a bitmap whose bits are set according to NUMA + * memory node physical OS indexes. * - * It may be consulted and modified with the bitmap API as any ::hwloc_bitmap_t (see hwloc/bitmap.h). + * It may be consulted and modified with the bitmap API as any + * ::hwloc_bitmap_t (see hwloc/bitmap.h). * * When binding memory on a system without any NUMA node * (when the whole memory is considered as a single memory bank), @@ -149,7 +172,7 @@ typedef enum { HWLOC_OBJ_GROUP, /**< \brief Group objects. * Objects which do not fit in the above but are * detected by hwloc and are useful to take into - * account for affinity. For instance, some OSes + * account for affinity. For instance, some operating systems * expose their arbitrary processors aggregation this * way. And hwloc may insert such objects to group * NUMA nodes according to their distances. @@ -216,7 +239,7 @@ struct hwloc_obj_memory_s { /** \brief Structure of a topology object * - * Applications mustn't modify any field except ::userdata . + * Applications must not modify any field except hwloc_obj.userdata. */ struct hwloc_obj { /* physical information */ @@ -800,8 +823,10 @@ HWLOC_DECLSPEC hwloc_obj_type_t hwloc_obj_type_of_string (const char * string) _ * It differs from hwloc_obj_type_string() because it prints type attributes such * as cache depth. * - * \return how many characters were actually written (not including the ending - * \\0), or -1 on error. + * If \p size is 0, \p string may safely be \c NULL. + * + * \return the number of character that were actually written if not truncating, + * or that would have been written (not including the ending \\0). */ HWLOC_DECLSPEC int hwloc_obj_type_snprintf(char * __hwloc_restrict string, size_t size, hwloc_obj_t obj, int verbose); @@ -812,8 +837,10 @@ HWLOC_DECLSPEC int hwloc_obj_type_snprintf(char * __hwloc_restrict string, size_ * * Only the major attributes are printed in non-verbose mode. * - * \return how many characters were actually written (not including the ending - * \\0), or -1 on error. + * If \p size is 0, \p string may safely be \c NULL. + * + * \return the number of character that were actually written if not truncating, + * or that would have been written (not including the ending \\0). */ HWLOC_DECLSPEC int hwloc_obj_attr_snprintf(char * __hwloc_restrict string, size_t size, hwloc_obj_t obj, const char * __hwloc_restrict separator, int verbose); @@ -833,8 +860,10 @@ HWLOC_DECLSPEC int hwloc_obj_attr_snprintf(char * __hwloc_restrict string, size_ * \p indexprefix is used to prefix the \p os_index attribute number of * the object in the description. If \c NULL, the \c # character is used. * - * \return how many characters were actually written (not including the ending - * \\0), or -1 on error. + * If \p size is 0, \p string may safely be \c NULL. + * + * \return the number of character that were actually written if not truncating, + * or that would have been written (not including the ending \\0). */ HWLOC_DECLSPEC int hwloc_obj_snprintf(char * __hwloc_restrict string, size_t size, hwloc_topology_t topology, hwloc_obj_t obj, @@ -842,7 +871,11 @@ HWLOC_DECLSPEC int hwloc_obj_snprintf(char * __hwloc_restrict string, size_t siz /** \brief Stringify the cpuset containing a set of objects. * - * \return how many characters were actually written (not including the ending \\0). */ + * If \p size is 0, \p string may safely be \c NULL. + * + * \return the number of character that were actually written if not truncating, + * or that would have been written (not including the ending \\0). + */ HWLOC_DECLSPEC int hwloc_obj_cpuset_snprintf(char * __hwloc_restrict str, size_t size, size_t nobj, const hwloc_obj_t * __hwloc_restrict objs); /** \brief Search the given key name in object infos and return the corresponding value. @@ -867,14 +900,15 @@ hwloc_obj_get_info_by_name(hwloc_obj_t obj, const char *name) * * It is often useful to call hwloc_bitmap_singlify() first so that a single CPU * remains in the set. This way, the process will not even migrate between - * different CPUs. Some OSes also only support that kind of binding. + * different CPUs. Some operating systems also only support that kind of binding. * - * \note Some OSes do not provide all ways to bind processes, threads, etc and - * the corresponding binding functions may fail. -1 is returned and errno is set - * to ENOSYS when it is not possible to bind the requested kind of object - * processes/threads. errno is set to EXDEV when the requested cpuset can not be - * enforced (e.g. some systems only allow one CPU, and some other systems only - * allow one NUMA node). + * \note Some operating systems do not provide all hwloc-supported + * mechanisms to bind processes, threads, etc. and the corresponding + * binding functions may fail. -1 is returned and errno is set to + * ENOSYS when it is not possible to bind the requested kind of object + * processes/threads. errno is set to EXDEV when the requested cpuset + * can not be enforced (e.g. some systems only allow one CPU, and some + * other systems only allow one NUMA node). * * The most portable version that should be preferred over the others, whenever * possible, is @@ -883,7 +917,7 @@ hwloc_obj_get_info_by_name(hwloc_obj_t obj, const char *name) * hwloc_set_cpubind(topology, set, 0), * \endcode * - * as it just binds the current program, assuming it is monothread, or + * as it just binds the current program, assuming it is single-threaded, or * * \code * hwloc_set_cpubind(topology, set, HWLOC_CPUBIND_THREAD), @@ -895,20 +929,22 @@ hwloc_obj_get_info_by_name(hwloc_obj_t obj, const char *name) * \note To unbind, just call the binding function with either a full cpuset or * a cpuset equal to the system cpuset. * - * \note On some OSes, CPU binding may have effects on memory binding, see + * \note On some operating systems, CPU binding may have effects on memory binding, see * ::HWLOC_CPUBIND_NOMEMBIND * @{ */ /** \brief Process/Thread binding flags. * - * These flags can be used to refine the binding policy. + * These bit flags can be used to refine the binding policy. * - * The default (0) is to bind the current process, assumed to be mono-thread, - * in a non-strict way. This is the most portable way to bind as all OSes - * usually provide it. + * The default (0) is to bind the current process, assumed to be + * single-threaded, in a non-strict way. This is the most portable + * way to bind as all operating systems usually provide it. * - * \note Not all systems support all kinds of binding. + * \note Not all systems support all kinds of binding. See the + * "Detailed Description" section of \ref hwlocality_cpubinding for a + * description of errors that can occur. */ typedef enum { HWLOC_CPUBIND_PROCESS = (1<<0), /**< \brief Bind all threads of the current @@ -920,7 +956,7 @@ typedef enum { * \hideinitializer * * By default, when the designated CPUs are - * all busy while other CPUs are idle, OSes + * all busy while other CPUs are idle, operating systems * may execute the thread/process on those * other CPUs instead of the designated CPUs, * to let them progress anyway. Strict @@ -929,10 +965,10 @@ typedef enum { * designated CPUs, even when those are busy * with other tasks and other CPUs are idle. * - * \note Depending on OSes and - * implementations, strict binding may not be - * possible (implementation reason) or not - * allowed (administrative reasons), and the + * \note Depending on the operating system, + * strict binding may not be + * possible (e.g., the OS does not implement it) or not + * allowed (e.g., for an administrative reasons), and the * function will fail in that case. * * When retrieving the binding of a process, @@ -947,7 +983,7 @@ typedef enum { HWLOC_CPUBIND_NOMEMBIND = (1<<3)/**< \brief Avoid any effect on memory binding * \hideinitializer * - * On some OSes, some CPU binding function + * On some operating systems, some CPU binding function * would also bind the memory on the * corresponding NUMA node. It is often not * a problem for the application, but if it @@ -1016,165 +1052,475 @@ HWLOC_DECLSPEC int hwloc_get_thread_cpubind(hwloc_topology_t topology, hwloc_thr /** \defgroup hwlocality_membinding Memory binding * - * \note Not all OSes support all ways to bind existing allocated memory - * (migration), future memory allocation, explicit memory allocation, etc. and - * the corresponding binding functions may fail. -1 is returned and errno is - * set to ENOSYS when it is not possible to bind the requested kind of object - * processes/threads). errno is set to EXDEV when the requested cpuset can not - * be enforced (e.g. some systems only allow one NUMA node). + * \note Not all operating systems support all ways to bind existing + * allocated memory (e.g., migration), future memory allocation, + * explicit memory allocation, etc. Using a binding flag or policy + * that is not supported by the underlying OS will cause hwloc's + * binding functions to fail and return -1. errno will be set to + * ENOSYS when the system does support the specified action or policy + * (e.g., some systems only allow binding memory on a per-thread + * basis, whereas other systems only allow binding memory for all + * threads in a process). errno will be set to EXDEV when the + * requested cpuset can not be enforced (e.g., some systems only allow + * binding memory to a single NUMA node). * - * The most portable version that should be preferred over the others, whenever - * possible, is + * The most portable form that should be preferred over the others + * whenever possible is as follows: * * \code - * hwloc_alloc_membind_policy(topology, size, set, HWLOC_MEMBIND_DEFAULT, 0), + * hwloc_alloc_membind_policy(topology, size, set, + * HWLOC_MEMBIND_DEFAULT, 0); * \endcode * - * which will try to allocate new data bound to the given set, possibly by - * changing the current memory binding policy, or at worse allocate memory - * without binding it at all. Since HWLOC_MEMBIND_STRICT is not given, this - * will even not fail unless a mere malloc() itself would fail, i.e. ENOMEM. + * This will allocate some memory hopefully bound to the specified set. + * To do so, hwloc will possibly have to change the current memory + * binding policy in order to actually get the memory bound, if the OS + * does not provide any other way to simply allocate bound memory + * without changing the policy for all allocations. That is the + * difference with hwloc_alloc_membind(), which will never change the + * current memory binding policy. Note that since HWLOC_MEMBIND_STRICT + * was not specified, failures to bind will not be reported -- + * generally, only memory allocation failures will be reported (e.g., + * even a plain malloc() would have failed with ENOMEM). * - * Each binding is available with a CPU set argument or a NUMA memory node set - * argument. The name of the latter ends with _nodeset. It is also possible to - * convert between CPU set and node set using ::hwloc_cpuset_to_nodeset or - * ::hwloc_cpuset_from_nodeset. + * Each hwloc memory binding function is available in two forms: one + * that takes a CPU set argument and another that takes a NUMA memory + * node set argument (see \ref hwlocality_sets and \ref + * hwlocality_bitmap for a discussion of CPU sets and NUMA memory node + * sets). The names of the latter form end with _nodeset. It is also + * possible to convert between CPU set and node set using + * hwloc_cpuset_to_nodeset() or hwloc_cpuset_from_nodeset(). * - * \note On some OSes, memory binding may have effects on CPU binding, see - * ::HWLOC_MEMBIND_NOCPUBIND + * \note On some operating systems, memory binding affects the CPU + * binding; see ::HWLOC_MEMBIND_NOCPUBIND * @{ */ /** \brief Memory binding policy. * - * These can be used to choose the binding policy. + * These constants can be used to choose the binding policy. Only one policy can + * be used at a time (i.e., the values cannot be OR'ed together). * - * Note that not all systems support all kinds of binding. + * \note Not all systems support all kinds of binding. See the + * "Detailed Description" section of \ref hwlocality_membinding for a + * description of errors that can occur. */ typedef enum { HWLOC_MEMBIND_DEFAULT = 0, /**< \brief Reset the memory allocation policy to the system default. * \hideinitializer */ - HWLOC_MEMBIND_FIRSTTOUCH = 1, /**< \brief Allocate memory on the given nodes, but preferably on the - node where the first accessor is running. + HWLOC_MEMBIND_FIRSTTOUCH = 1, /**< \brief Allocate memory + * but do not immediately bind + * it to a specific locality. + * Instead, each page in the + * allocation is bound only + * when it is first touched. + * Pages are individually + * bound to the local NUMA + * node of the first thread + * that touches it. + * \hideinitializer */ + HWLOC_MEMBIND_BIND = 2, /**< \brief Allocate memory on the specified nodes. * \hideinitializer */ - HWLOC_MEMBIND_BIND = 2, /**< \brief Allocate memory on the given nodes. + HWLOC_MEMBIND_INTERLEAVE = 3, /**< \brief Allocate memory on + * the given nodes in an + * interleaved / round-robin + * manner. The precise layout + * of the memory across + * multiple NUMA nodes is + * OS/system specific. + * Interleaving can be useful + * when threads distributed across + * the specified NUMA nodes + * will all be accessing the whole + * memory range concurrently, since + * the interleave will then balance + * the memory references. + * \hideinitializer */ + HWLOC_MEMBIND_REPLICATE = 4, /**< \brief Replicate memory + * on the given nodes; reads + * from this memory will + * attempt to be serviced from + * the NUMA node local to the + * reading thread. + * Replicating can be useful + * when multiple threads from + * the specified NUMA nodes + * will be sharing the same + * read-only data. + * + * This policy can only be + * used with existing memory + * allocations (i.e., the + * hwloc_set_*membind*() + * functions); it cannot be + * used with functions that + * allocate new memory (i.e., + * the hwloc_alloc*() + * functions). * \hideinitializer */ - HWLOC_MEMBIND_INTERLEAVE = 3, /**< \brief Allocate memory on the given nodes in a round-robin manner. - * \hideinitializer */ - HWLOC_MEMBIND_REPLICATE = 4, /**< \brief Replicate memory on the given nodes. - * \hideinitializer */ - HWLOC_MEMBIND_NEXTTOUCH = 5 /**< \brief On next touch of existing allocated memory, migrate it to the node - * where the memory reference happened. + HWLOC_MEMBIND_NEXTTOUCH = 5, /**< \brief For each page bound + * with this policy, by next time + * it is touched (and next time only), + * it is moved from + * its current location to the + * local NUMA node of the + * thread where the memory + * reference occurred (if it + * needs to be moved at all). * \hideinitializer */ + HWLOC_MEMBIND_MIXED = -1 /**< \brief Returned by hwloc_get_membind*() + * functions when multiple threads or + * parts of a memory area have + * differing memory binding policies. + * \hideinitializer */ } hwloc_membind_policy_t; /** \brief Memory binding flags. * - * These flags can be used to refine the binding policy. + * These flags can be used to refine the binding policy. All flags + * can be logically OR'ed together with the exception of + * HWLOC_MEMBIND_PROCESS and HWLOC_MEMBIND_THREAD; these two flags are + * mutually exclusive. * - * \note Not all systems support all kinds of binding. + * \note Not all systems support all kinds of binding. See the + * "Detailed Description" section of \ref hwlocality_membinding for a + * description of errors that can occur. */ typedef enum { - HWLOC_MEMBIND_PROCESS = (1<<0), /**< \brief Set policy for all threads of the - * current (possibly multithreaded) process. + HWLOC_MEMBIND_PROCESS = (1<<0), /**< \brief Set policy for all + * threads of the specified + * (possibly multithreaded) + * process. This flag is + * mutually exclusive with + * HWLOC_MEMBIND_THREAD. * \hideinitializer */ - HWLOC_MEMBIND_THREAD = (1<<1), /**< \brief Set policy for the current thread of - * the current process. + HWLOC_MEMBIND_THREAD = (1<<1), /**< \brief Set policy for a + * specific thread of the + * current process. This flag + * is mutually exclusive with + * HWLOC_MEMBIND_PROCESS. * \hideinitializer */ - HWLOC_MEMBIND_STRICT = (1<<2), /**< Request strict binding from the OS. - * The function will fail if the - * binding can not be completely - * enforced. - * \hideinitializer */ - HWLOC_MEMBIND_MIGRATE = (1<<3), /**< \brief Migrate existing allocated memory. - * If memory can not be migrated and the STRICT - * flag is passed, an error will be returned. - * \hideinitializer */ - HWLOC_MEMBIND_NOCPUBIND = (1<<4) /**< \brief Avoid any effect on CPU binding - * \hideinitializer + HWLOC_MEMBIND_STRICT = (1<<2), /**< Request strict binding + * from the OS. The function + * will fail if the binding + * can not be guaranteed / + * completely enforced. * - * On some OSes, some memory binding function - * would also bind the application on - * the corresponding CPUs. It is often - * not a problem for the application, but if it - * is, setting this flag will make hwloc - * avoid using OS functions that would also - * bind on CPUs. This will however reduce the - * support of memory bindings, i.e. potentially - * return ENOSYS in some cases. + * This flag has slightly + * different meanings + * depending on which function + * it is used with. + * \hideinitializer */ + HWLOC_MEMBIND_MIGRATE = (1<<3), /**< \brief Migrate existing + * allocated memory. If the + * memory cannot be migrated + * and the + * HWLOC_MEMBIND_STRICT flag + * is passed, an error will be + * returned. + * \hideinitializer */ + HWLOC_MEMBIND_NOCPUBIND = (1<<4) /**< \brief Avoid any effect + * on CPU binding. + * + * On some operating systems, + * some underlying memory + * binding functions also bind + * the application to the + * corresponding CPU(s). + * Using this flag will cause + * hwloc to avoid using OS + * functions that could + * potentially affect CPU + * bindings. Note, however, + * that using NOCPUBIND may + * reduce hwloc's overall + * memory binding support. + * Specifically: some of + * hwloc's memory binding + * functions may fail with + * errno set to ENOSYS when + * used with NOCPUBIND. + * \hideinitializer */ } hwloc_membind_flags_t; -/** \brief Bind current process memory on the given nodeset \p nodeset +/** \brief Set the default memory binding policy of the current + * process or thread to prefer the NUMA node(s) specified by \p nodeset + * + * If neither HWLOC_MEMBIND_PROCESS nor HWLOC_MEMBIND_THREAD is + * specified, the current process is assumed to be single-threaded. + * This is the most portable form as it permits hwloc to use either + * process-based OS functions or thread-based OS functions, depending + * on which are available. * * \return -1 with errno set to ENOSYS if the action is not supported * \return -1 with errno set to EXDEV if the binding cannot be enforced */ HWLOC_DECLSPEC int hwloc_set_membind_nodeset(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags); -/** \brief Bind current process memory on memory nodes near the given cpuset \p cpuset +/** \brief Set the default memory binding policy of the current + * process or thread to prefer the NUMA node(s) near the specified \p + * cpuset + * + * If neither HWLOC_MEMBIND_PROCESS nor HWLOC_MEMBIND_THREAD is + * specified, the current process is assumed to be single-threaded. + * This is the most portable form as it permits hwloc to use either + * process-based OS functions or thread-based OS functions, depending + * on which are available. * * \return -1 with errno set to ENOSYS if the action is not supported * \return -1 with errno set to EXDEV if the binding cannot be enforced */ HWLOC_DECLSPEC int hwloc_set_membind(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags); -/** \brief Get current process memory binding in nodeset \p nodeset +/** \brief Query the default memory binding policy and locality of the + * current process or thread. + * + * This function has two output parameters: \p nodeset and \p policy. + * The values returned in these parameters depend on both the \p flags + * passed in and the current memory binding policies and nodesets in + * the queried target. + * + * Passing the HWLOC_MEMBIND_PROCESS flag specifies that the query + * target is the current policies and nodesets for all the threads in + * the current process. Passing HWLOC_MEMBIND_THREAD specifies that + * the query target is the current policy and nodeset for only the + * thread invoking this function. + * + * If neither of these flags are passed (which is the most portable + * method), the process is assumed to be single threaded. This allows + * hwloc to use either process-based OS functions or thread-based OS + * functions, depending on which are available. + * + * HWLOC_MEMBIND_STRICT is only meaningful when HWLOC_MEMBIND_PROCESS + * is also specified. In this case, hwloc will check the default + * memory policies and nodesets for all threads in the process. If + * they are not identical, -1 is returned and errno is set to EXDEV. + * If they are identical, the values are returned in \p nodeset and \p + * policy. + * + * Otherwise, if HWLOC_MEMBIND_PROCESS is specified (and + * HWLOC_MEMBIND_STRICT is \em not specified), \p nodeset is set to + * the logical OR of all threads' default nodeset. If all threads' + * default policies are the same, \p policy is set to that policy. If + * they are different, \p policy is set to HWLOC_MEMBIND_MIXED. + * + * In the HWLOC_MEMBIND_THREAD case (or when neither + * HWLOC_MEMBIND_PROCESS or HWLOC_MEMBIND_THREAD is specified), there + * is only one nodeset and policy; they are returned in \p nodeset and + * \p policy, respectively. + * + * If any other flags are specified, -1 is returned and errno is set + * to EINVAL. */ HWLOC_DECLSPEC int hwloc_get_membind_nodeset(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags); -/** \brief Get current process memory binding in cpuset \p cpuset +/** \brief Query the default memory binding policy and locality of the + * current process or thread (the locality is returned in \p cpuset as + * CPUs near the locality's actual NUMA node(s)). + * + * This function has two output parameters: \p cpuset and \p policy. + * The values returned in these parameters depend on both the \p flags + * passed in and the current memory binding policies and nodesets in + * the queried target. + * + * Passing the HWLOC_MEMBIND_PROCESS flag specifies that the query + * target is the current policies and nodesets for all the threads in + * the current process. Passing HWLOC_MEMBIND_THREAD specifies that + * the query target is the current policy and nodeset for only the + * thread invoking this function. + * + * If neither of these flags are passed (which is the most portable + * method), the process is assumed to be single threaded. This allows + * hwloc to use either process-based OS functions or thread-based OS + * functions, depending on which are available. + * + * HWLOC_MEMBIND_STRICT is only meaningful when HWLOC_MEMBIND_PROCESS + * is also specified. In this case, hwloc will check the default + * memory policies and nodesets for all threads in the process. If + * they are not identical, -1 is returned and errno is set to EXDEV. + * If they are identical, the policy is returned in \p policy. \p + * cpuset is set to the union of CPUs near the NUMA node(s) in the + * nodeset. + * + * Otherwise, if HWLOC_MEMBIND_PROCESS is specified (and + * HWLOC_MEMBIND_STRICT is \em not specified), the default nodeset + * from each thread is logically OR'ed together. \p cpuset is set to + * the union of CPUs near the NUMA node(s) in the resulting nodeset. + * If all threads' default policies are the same, \p policy is set to + * that policy. If they are different, \p policy is set to + * HWLOC_MEMBIND_MIXED. + * + * In the HWLOC_MEMBIND_THREAD case (or when neither + * HWLOC_MEMBIND_PROCESS or HWLOC_MEMBIND_THREAD is specified), there + * is only one nodeset and policy. The policy is returned in \p + * policy; \p cpuset is set to the union of CPUs near the NUMA node(s) + * in the \p nodeset. + * + * If any other flags are specified, -1 is returned and errno is set + * to EINVAL. */ HWLOC_DECLSPEC int hwloc_get_membind(hwloc_topology_t topology, hwloc_cpuset_t cpuset, hwloc_membind_policy_t * policy, int flags); -/** \brief Bind given process memory on the given nodeset \p nodeset +/** \brief Set the default memory binding policy of the specified + * process to prefer the NUMA node(s) specified by \p nodeset * * \return -1 with errno set to ENOSYS if the action is not supported * \return -1 with errno set to EXDEV if the binding cannot be enforced */ HWLOC_DECLSPEC 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); -/** \brief Bind given process memory on memory nodes near the given cpuset \p cpuset +/** \brief Set the default memory binding policy of the specified + * process to prefer the NUMA node(s) near the specified \p cpuset * * \return -1 with errno set to ENOSYS if the action is not supported * \return -1 with errno set to EXDEV if the binding cannot be enforced */ HWLOC_DECLSPEC int hwloc_set_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags); -/** \brief Get current process memory binding in nodeset \p nodeset +/** \brief Query the default memory binding policy and locality of the + * specified process. + * + * This function has two output parameters: \p nodeset and \p policy. + * The values returned in these parameters depend on both the \p flags + * passed in and the current memory binding policies and nodesets in + * the queried target. + * + * Passing the HWLOC_MEMBIND_PROCESS flag specifies that the query + * target is the current policies and nodesets for all the threads in + * the specified process. If HWLOC_MEMBIND_PROCESS is not specified + * (which is the most portable method), the process is assumed to be + * single threaded. This allows hwloc to use either process-based OS + * functions or thread-based OS functions, depending on which are + * available. + * + * Note that it does not make sense to pass HWLOC_MEMBIND_THREAD to + * this function. + * + * If HWLOC_MEMBIND_STRICT is specified, hwloc will check the default + * memory policies and nodesets for all threads in the specified + * process. If they are not identical, -1 is returned and errno is + * set to EXDEV. If they are identical, the values are returned in \p + * nodeset and \p policy. + * + * Otherwise, \p nodeset is set to the logical OR of all threads' + * default nodeset. If all threads' default policies are the same, \p + * policy is set to that policy. If they are different, \p policy is + * set to HWLOC_MEMBIND_MIXED. + * + * If any other flags are specified, -1 is returned and errno is set + * to EINVAL. */ HWLOC_DECLSPEC 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); -/** \brief Get current process memory binding in cpuset \p cpuset +/** \brief Query the default memory binding policy and locality of the + * specified process (the locality is returned in \p cpuset as CPUs + * near the locality's actual NUMA node(s)). + * + * This function has two output parameters: \p cpuset and \p policy. + * The values returned in these parameters depend on both the \p flags + * passed in and the current memory binding policies and nodesets in + * the queried target. + * + * Passing the HWLOC_MEMBIND_PROCESS flag specifies that the query + * target is the current policies and nodesets for all the threads in + * the specified process. If HWLOC_MEMBIND_PROCESS is not specified + * (which is the most portable method), the process is assumed to be + * single threaded. This allows hwloc to use either process-based OS + * functions or thread-based OS functions, depending on which are + * available. + * + * Note that it does not make sense to pass HWLOC_MEMBIND_THREAD to + * this function. + * + * If HWLOC_MEMBIND_STRICT is specified, hwloc will check the default + * memory policies and nodesets for all threads in the specified + * process. If they are not identical, -1 is returned and errno is + * set to EXDEV. If they are identical, the policy is returned in \p + * policy. \p cpuset is set to the union of CPUs near the NUMA + * node(s) in the nodeset. + * + * Otherwise, the default nodeset from each thread is logically OR'ed + * together. \p cpuset is set to the union of CPUs near the NUMA + * node(s) in the resulting nodeset. If all threads' default policies + * are the same, \p policy is set to that policy. If they are + * different, \p policy is set to HWLOC_MEMBIND_MIXED. + * + * If any other flags are specified, -1 is returned and errno is set + * to EINVAL. */ HWLOC_DECLSPEC int hwloc_get_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_cpuset_t cpuset, hwloc_membind_policy_t * policy, int flags); -/** \brief Bind some memory range on the given nodeset \p nodeset +/** \brief Bind the already-allocated memory identified by (addr, len) + * to the NUMA node(s) in \p nodeset. * * \return -1 with errno set to ENOSYS if the action is not supported * \return -1 with errno set to EXDEV if the binding cannot be enforced */ HWLOC_DECLSPEC 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); -/** \brief Bind some memory range on memory nodes near the given cpuset \p cpuset +/** \brief Bind the already-allocated memory identified by (addr, len) + * to the NUMA node(s) near \p cpuset. * * \return -1 with errno set to ENOSYS if the action is not supported * \return -1 with errno set to EXDEV if the binding cannot be enforced */ HWLOC_DECLSPEC int hwloc_set_area_membind(hwloc_topology_t topology, const void *addr, size_t len, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags); -/** \brief Get some memory range memory binding in nodeset \p nodeset +/** \brief Query the NUMA node(s) and binding policy of the memory + * identified by (\p addr, \p len ). + * + * This function has two output parameters: \p nodeset and \p policy. + * The values returned in these parameters depend on both the \p flags + * passed in and the memory binding policies and nodesets of the pages + * in the address range. + * + * If HWLOC_MEMBIND_STRICT is specified, the target pages are first + * checked to see if they all have the same memory binding policy and + * nodeset. If they do not, -1 is returned and errno is set to EXDEV. + * If they are identical across all pages, the nodeset and policy are + * returned in \p nodeset and \p policy, respectively. + * + * If HWLOC_MEMBIND_STRICT is not specified, \p nodeset is set to the + * union of all NUMA node(s) containing pages in the address range. + * If all pages in the target have the same policy, it is returned in + * \p policy. Otherwise, \p policy is set to HWLOC_MEMBIND_MIXED. + * + * If any other flags are specified, -1 is returned and errno is set + * to EINVAL. */ HWLOC_DECLSPEC 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); -/** \brief Get some memory range memory binding in cpuset \p cpuset +/** \brief Query the CPUs near the NUMA node(s) and binding policy of + * the memory identified by (\p addr, \p len ). + * + * This function has two output parameters: \p cpuset and \p policy. + * The values returned in these parameters depend on both the \p flags + * passed in and the memory binding policies and nodesets of the pages + * in the address range. + * + * If HWLOC_MEMBIND_STRICT is specified, the target pages are first + * checked to see if they all have the same memory binding policy and + * nodeset. If they do not, -1 is returned and errno is set to EXDEV. + * If they are identical across all pages, the policy is returned in + * \p policy. \p cpuset is set to the union of CPUs near the NUMA + * node(s) in the nodeset. + * + * If HWLOC_MEMBIND_STRICT is not specified, the union of all NUMA + * node(s) containing pages in the address range is calculated. \p + * cpuset is then set to the CPUs near the NUMA node(s) in this union. + * If all pages in the target have the same policy, it is returned in + * \p policy. Otherwise, \p policy is set to HWLOC_MEMBIND_MIXED. + * + * If any other flags are specified, -1 is returned and errno is set + * to EINVAL. */ HWLOC_DECLSPEC int hwloc_get_area_membind(hwloc_topology_t topology, const void *addr, size_t len, hwloc_cpuset_t cpuset, hwloc_membind_policy_t * policy, int flags); /** \brief Allocate some memory * - * This is equivalent to malloc(), except it tries to allocated page-aligned - * memory from the OS. + * This is equivalent to malloc(), except that it tries to allocate + * page-aligned memory from the OS. * * \note The allocated memory should be freed with hwloc_free(). */ @@ -1202,7 +1548,8 @@ HWLOC_DECLSPEC void *hwloc_alloc_membind_nodeset(hwloc_topology_t topology, size */ HWLOC_DECLSPEC void *hwloc_alloc_membind(hwloc_topology_t topology, size_t len, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags) __hwloc_attribute_malloc; -/** \brief Free some memory allocated by hwloc_alloc() or hwloc_alloc_membind(). +/** \brief Free memory that was previously allocated by hwloc_alloc() + * or hwloc_alloc_membind(). */ HWLOC_DECLSPEC int hwloc_free(hwloc_topology_t topology, void *addr, size_t len); diff --git a/opal/mca/common/hwloc/hwloc/include/hwloc/bitmap.h b/opal/mca/common/hwloc/hwloc/include/hwloc/bitmap.h index 69827b575c..6610d1a7a2 100644 --- a/opal/mca/common/hwloc/hwloc/include/hwloc/bitmap.h +++ b/opal/mca/common/hwloc/hwloc/include/hwloc/bitmap.h @@ -24,11 +24,17 @@ extern "C" { /** \defgroup hwlocality_bitmap The bitmap API * - * For use in hwloc itself, a hwloc_bitmap_t usually represents a set of - * objects, typically logical processors or memory nodes, indexed by OS - * physical number. + * The ::hwloc_bitmap_t type represents a set of objects, typically OS + * processors -- which may actually be hardware threads (represented + * by ::hwloc_cpuset_t, which is a typedef for ::hwloc_bitmap_t) -- or + * memory nodes (represented by ::hwloc_nodeset_t, which is also a + * typedef for ::hwloc_bitmap_t). * - * A bitmap may be infinite. + * Both CPU and node sets are always indexed by OS physical number. + * + * \note CPU sets and nodesets are described in \ref hwlocality_sets. + * + * A bitmap may be of infinite size. * @{ */ @@ -37,6 +43,7 @@ extern "C" { * Set of bits represented as an opaque pointer to an internal bitmap. */ typedef struct hwloc_bitmap_s * hwloc_bitmap_t; +/** \brief a non-modifiable ::hwloc_bitmap_t */ typedef const struct hwloc_bitmap_s * hwloc_const_bitmap_t; @@ -73,21 +80,18 @@ HWLOC_DECLSPEC void hwloc_bitmap_copy(hwloc_bitmap_t dst, hwloc_const_bitmap_t s * * Up to \p buflen characters may be written in buffer \p buf. * + * If \p buflen is 0, \p buf may safely be \c NULL. + * * \return the number of character that were actually written if not truncating, - * or that would have been written (not including the ending \\0). + * or that would have been written (not including the ending \\0). */ HWLOC_DECLSPEC int hwloc_bitmap_snprintf(char * __hwloc_restrict buf, size_t buflen, hwloc_const_bitmap_t bitmap); /** \brief Stringify a bitmap into a newly allocated string. - * - * \return the number of character that were actually written - * (not including the ending \\0). */ HWLOC_DECLSPEC int hwloc_bitmap_asprintf(char ** strp, hwloc_const_bitmap_t bitmap); /** \brief Parse a bitmap string and stores it in bitmap \p bitmap. - * - * Must start and end with a digit. */ HWLOC_DECLSPEC int hwloc_bitmap_sscanf(hwloc_bitmap_t bitmap, const char * __hwloc_restrict string); @@ -95,6 +99,13 @@ HWLOC_DECLSPEC int hwloc_bitmap_sscanf(hwloc_bitmap_t bitmap, const char * __hwl * * The taskset command manipulates bitmap strings that contain a single * (possible very long) hexadecimal number starting with 0x. + * + * Up to \p buflen characters may be written in buffer \p buf. + * + * If \p buflen is 0, \p buf may safely be \c NULL. + * + * \return the number of character that were actually written if not truncating, + * or that would have been written (not including the ending \\0). */ HWLOC_DECLSPEC int hwloc_bitmap_taskset_snprintf(char * __hwloc_restrict buf, size_t buflen, hwloc_const_bitmap_t bitmap); diff --git a/opal/mca/common/hwloc/hwloc/include/hwloc/helper.h b/opal/mca/common/hwloc/hwloc/include/hwloc/helper.h index dcdf4df0ef..45672e018e 100644 --- a/opal/mca/common/hwloc/hwloc/include/hwloc/helper.h +++ b/opal/mca/common/hwloc/hwloc/include/hwloc/helper.h @@ -582,7 +582,7 @@ hwloc_get_obj_below_array_by_type (hwloc_topology_t topology, int nr, hwloc_obj_ * * Array \p cpuset will be filled with \p n cpusets recursively distributed * linearly over the topology under \p root, down to depth \p until (which can - * be MAX_INT to distribute down to the finest level). + * be INT_MAX to distribute down to the finest level). * * This is typically useful when an application wants to distribute \p n * threads over a machine, giving each of them as much private cache as @@ -680,7 +680,7 @@ hwloc_alloc_membind_policy(hwloc_topology_t topology, size_t len, hwloc_const_cp /** \defgroup hwlocality_helper_cpuset Cpuset Helpers * @{ */ -/* \brief Get complete CPU set +/** \brief Get complete CPU set * * \return the complete CPU set of logical processors of the system. If the * topology is the result of a combination of several systems, NULL is @@ -695,7 +695,7 @@ hwloc_topology_get_complete_cpuset(hwloc_topology_t topology) return hwloc_get_root_obj(topology)->complete_cpuset; } -/* \brief Get topology CPU set +/** \brief Get topology CPU set * * \return the CPU set of logical processors of the system for which hwloc * provides topology information. This is equivalent to the cpuset of the @@ -748,7 +748,7 @@ hwloc_topology_get_allowed_cpuset(hwloc_topology_t topology) /** \defgroup hwlocality_helper_nodeset Nodeset Helpers * @{ */ -/* \brief Get complete node set +/** \brief Get complete node set * * \return the complete node set of memory of the system. If the * topology is the result of a combination of several systems, NULL is @@ -763,7 +763,7 @@ hwloc_topology_get_complete_nodeset(hwloc_topology_t topology) return hwloc_get_root_obj(topology)->complete_nodeset; } -/* \brief Get topology node set +/** \brief Get topology node set * * \return the node set of memory of the system for which hwloc * provides topology information. This is equivalent to the nodeset of the diff --git a/opal/mca/common/hwloc/hwloc/include/hwloc/rename.h b/opal/mca/common/hwloc/hwloc/include/hwloc/rename.h index c27bd73a9e..120f55e55a 100644 --- a/opal/mca/common/hwloc/hwloc/include/hwloc/rename.h +++ b/opal/mca/common/hwloc/hwloc/include/hwloc/rename.h @@ -36,6 +36,8 @@ extern "C" { /* Names from hwloc.h */ +#define hwloc_get_api_version HWLOC_NAME(get_api_version) + #define hwloc_topology HWLOC_NAME(topology) #define hwloc_topology_t HWLOC_NAME(topology_t) @@ -181,6 +183,9 @@ extern "C" { #define hwloc_bitmap_snprintf HWLOC_NAME(bitmap_snprintf) #define hwloc_bitmap_asprintf HWLOC_NAME(bitmap_asprintf) #define hwloc_bitmap_sscanf HWLOC_NAME(bitmap_sscanf) +#define hwloc_bitmap_taskset_snprintf HWLOC_NAME(bitmap_taskset_snprintf) +#define hwloc_bitmap_taskset_asprintf HWLOC_NAME(bitmap_taskset_asprintf) +#define hwloc_bitmap_taskset_sscanf HWLOC_NAME(bitmap_taskset_sscanf) #define hwloc_bitmap_zero HWLOC_NAME(bitmap_zero) #define hwloc_bitmap_fill HWLOC_NAME(bitmap_fill) #define hwloc_bitmap_from_ulong HWLOC_NAME(bitmap_from_ulong) @@ -214,6 +219,52 @@ extern "C" { #define hwloc_bitmap_compare HWLOC_NAME(bitmap_compare) #define hwloc_bitmap_weight HWLOC_NAME(bitmap_weight) +/* hwloc/cpuset.h -- deprecated but still available */ + +#define hwloc_cpuset HWLOC_NAME(cpuset) +#define hwloc_cpuset_s HWLOC_NAME(cpuset_s) +#define hwloc_cpuset_t HWLOC_NAME(cpuset_t) +#define hwloc_const_cpuset_t HWLOC_NAME(const_cpuset_t) + +#define hwloc_cpuset_alloc HWLOC_NAME(cpuset_alloc) +#define hwloc_cpuset_free HWLOC_NAME(cpuset_free) +#define hwloc_cpuset_dup HWLOC_NAME(cpuset_dup) +#define hwloc_cpuset_copy HWLOC_NAME(cpuset_copy) +#define hwloc_cpuset_snprintf HWLOC_NAME(cpuset_snprintf) +#define hwloc_cpuset_asprintf HWLOC_NAME(cpuset_asprintf) +#define hwloc_cpuset_from_string HWLOC_NAME(cpuset_from_string) +#define hwloc_cpuset_zero HWLOC_NAME(cpuset_zero) +#define hwloc_cpuset_fill HWLOC_NAME(cpuset_fill) +#define hwloc_cpuset_from_ulong HWLOC_NAME(cpuset_from_ulong) + +#define hwloc_cpuset_from_ith_ulong HWLOC_NAME(cpuset_from_ith_ulong) +#define hwloc_cpuset_to_ulong HWLOC_NAME(cpuset_to_ulong) +#define hwloc_cpuset_to_ith_ulong HWLOC_NAME(cpuset_to_ith_ulong) +#define hwloc_cpuset_cpu HWLOC_NAME(cpuset_cpu) +#define hwloc_cpuset_all_but_cpu HWLOC_NAME(cpuset_all_but_cpu) +#define hwloc_cpuset_set HWLOC_NAME(cpuset_set) +#define hwloc_cpuset_set_range HWLOC_NAME(cpuset_set_range) +#define hwloc_cpuset_clr HWLOC_NAME(cpuset_clr) +#define hwloc_cpuset_clr_range HWLOC_NAME(cpuset_clr_range) +#define hwloc_cpuset_isset HWLOC_NAME(cpuset_isset) +#define hwloc_cpuset_iszero HWLOC_NAME(cpuset_iszero) +#define hwloc_cpuset_isfull HWLOC_NAME(cpuset_isfull) +#define hwloc_cpuset_isequal HWLOC_NAME(cpuset_isequal) +#define hwloc_cpuset_intersects HWLOC_NAME(cpuset_intersects) +#define hwloc_cpuset_isincluded HWLOC_NAME(cpuset_isincluded) +#define hwloc_cpuset_or HWLOC_NAME(cpuset_or) +#define hwloc_cpuset_and HWLOC_NAME(cpuset_and) +#define hwloc_cpuset_andnot HWLOC_NAME(cpuset_andnot) +#define hwloc_cpuset_xor HWLOC_NAME(cpuset_xor) +#define hwloc_cpuset_not HWLOC_NAME(cpuset_not) +#define hwloc_cpuset_first HWLOC_NAME(cpuset_first) +#define hwloc_cpuset_last HWLOC_NAME(cpuset_last) +#define hwloc_cpuset_next HWLOC_NAME(cpuset_next) +#define hwloc_cpuset_singlify HWLOC_NAME(cpuset_singlify) +#define hwloc_cpuset_compare_first HWLOC_NAME(cpuset_compare_first) +#define hwloc_cpuset_compare HWLOC_NAME(cpuset_compare) +#define hwloc_cpuset_weight HWLOC_NAME(cpuset_weight) + /* hwloc/helper.h */ #define hwloc_get_type_or_below_depth HWLOC_NAME(get_type_or_below_depth) diff --git a/opal/mca/common/hwloc/hwloc/src/cpuset.c b/opal/mca/common/hwloc/hwloc/src/cpuset.c index 9836d8c45a..5188c17f20 100644 --- a/opal/mca/common/hwloc/hwloc/src/cpuset.c +++ b/opal/mca/common/hwloc/hwloc/src/cpuset.c @@ -36,8 +36,8 @@ /* actual opaque type internals */ struct hwloc_bitmap_s { - unsigned ulongs_count; /* how many ulong bitmasks are valid */ - unsigned ulongs_allocated; /* how many ulong bitmasks are allocated */ + 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 @@ -47,7 +47,11 @@ struct hwloc_bitmap_s { /* overzealous check in debug-mode, not as powerful as valgrind but still useful */ #ifdef HWLOC_DEBUG -#define HWLOC__BITMAP_CHECK(set) assert((set)->magic == HWLOC_BITMAP_MAGIC) +#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 @@ -77,7 +81,7 @@ struct hwloc_bitmap_s * hwloc_bitmap_alloc(void) if (!set) return NULL; - set->ulongs_count = 0; + set->ulongs_count = 1; set->ulongs_allocated = 64/sizeof(unsigned long); set->ulongs = malloc(64); if (!set->ulongs) { @@ -85,6 +89,7 @@ struct hwloc_bitmap_s * hwloc_bitmap_alloc(void) return NULL; } + set->ulongs[0] = HWLOC_SUBBITMAP_ZERO; set->infinite = 0; #ifdef HWLOC_DEBUG set->magic = HWLOC_BITMAP_MAGIC; @@ -95,8 +100,10 @@ struct hwloc_bitmap_s * hwloc_bitmap_alloc(void) struct hwloc_bitmap_s * hwloc_bitmap_alloc_full(void) { struct hwloc_bitmap_s * set = hwloc_bitmap_alloc(); - if (set) + if (set) { set->infinite = 1; + set->ulongs[0] = HWLOC_SUBBITMAP_FULL; + } return set; } @@ -240,13 +247,9 @@ int hwloc_bitmap_snprintf(char * __hwloc_restrict buf, size_t buflen, const stru res = size>0 ? size - 1 : 0; tmp += res; size -= res; - } - - if (!set->infinite && !set->ulongs_count) { - res = hwloc_snprintf(tmp, size, "0x0"); - if (res < 0) - return -1; - return res; + /* optimize a common case: full bitmap should appear as 0xf...f instead of 0xf...f,0xffffffff */ + if (set->ulongs_count == 1 && set->ulongs[0] == HWLOC_SUBBITMAP_FULL) + return ret; } i=set->ulongs_count-1; @@ -318,9 +321,15 @@ int hwloc_bitmap_sscanf(struct hwloc_bitmap_s *set, const char * __hwloc_restric count++; current = string; - if (!strncmp("0xf...f,", current, 8)) { + if (!strncmp("0xf...f", current, 7)) { + current += 7; + if (*current != ',') { + /* special case for infinite/full cpuset */ + hwloc_bitmap_fill(set); + return 0; + } + current++; infinite = 1; - current += 8; count--; } @@ -384,6 +393,9 @@ int hwloc_bitmap_taskset_snprintf(char * __hwloc_restrict buf, size_t buflen, co res = size>0 ? size - 1 : 0; tmp += res; size -= res; + /* optimize a common case: full bitmap should appear as 0xf...f instead of 0xf...fffffffff */ + if (set->ulongs_count == 1 && set->ulongs[0] == HWLOC_SUBBITMAP_FULL) + return ret; } i=set->ulongs_count-1; @@ -391,8 +403,12 @@ int hwloc_bitmap_taskset_snprintf(char * __hwloc_restrict buf, size_t buflen, co 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); - } else if (val) { +#endif + } else if (val || i == -1) { res = hwloc_snprintf(tmp, size, "0x%lx", val); started = 1; } else { @@ -432,11 +448,25 @@ int hwloc_bitmap_taskset_sscanf(struct hwloc_bitmap_s *set, const char * __hwloc current = string; if (!strncmp("0xf...f", current, 7)) { + /* infinite bitmap */ infinite = 1; current += 7; - } else if (!strncmp("0x", current, 2)) { - current += 2; + 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; @@ -446,13 +476,13 @@ int hwloc_bitmap_taskset_sscanf(struct hwloc_bitmap_s *set, const char * __hwloc while (*current != '\0') { int tmpchars; - char ustr[9]; + char ustr[17]; unsigned long val; char *next; - tmpchars = chars % 8; + tmpchars = chars % (HWLOC_BITS_PER_LONG/4); if (!tmpchars) - tmpchars = 8; + tmpchars = (HWLOC_BITS_PER_LONG/4); memcpy(ustr, current, tmpchars); ustr[tmpchars] = '\0'; @@ -489,7 +519,7 @@ void hwloc_bitmap_zero(struct hwloc_bitmap_s * set) { HWLOC__BITMAP_CHECK(set); - hwloc_bitmap_reset_by_ulongs(set, 0); + hwloc_bitmap_reset_by_ulongs(set, 1); hwloc_bitmap__zero(set); } @@ -505,7 +535,7 @@ void hwloc_bitmap_fill(struct hwloc_bitmap_s * set) { HWLOC__BITMAP_CHECK(set); - hwloc_bitmap_reset_by_ulongs(set, 0); + hwloc_bitmap_reset_by_ulongs(set, 1); hwloc_bitmap__fill(set); } @@ -526,7 +556,7 @@ void hwloc_bitmap_from_ith_ulong(struct hwloc_bitmap_s *set, unsigned i, unsigne hwloc_bitmap_reset_by_ulongs(set, i+1); set->ulongs[i] = mask; - for(j=1; j<(unsigned) i; j++) + for(j=0; j<(unsigned) i; j++) set->ulongs[j] = HWLOC_SUBBITMAP_ZERO; set->infinite = 0; } diff --git a/opal/mca/common/hwloc/hwloc/src/topology-linux.c b/opal/mca/common/hwloc/hwloc/src/topology-linux.c index 7f05c29f1b..b2e4606253 100644 --- a/opal/mca/common/hwloc/hwloc/src/topology-linux.c +++ b/opal/mca/common/hwloc/hwloc/src/topology-linux.c @@ -896,18 +896,18 @@ hwloc_linux_membind_mask_from_nodeset(hwloc_topology_t topology __hwloc_attribut static void hwloc_linux_membind_mask_to_nodeset(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_nodeset_t nodeset, - unsigned _max_os_index, const unsigned long *linuxmask) + unsigned max_os_index, const unsigned long *linuxmask) { - unsigned max_os_index; unsigned i; - /* round up to the nearest multiple of BITS_PER_LONG */ - max_os_index = (_max_os_index + HWLOC_BITS_PER_LONG) & ~(HWLOC_BITS_PER_LONG - 1); +#ifdef HWLOC_DEBUG + /* max_os_index comes from hwloc_linux_find_kernel_max_numnodes() so it's a multiple of HWLOC_BITS_PER_LONG */ + assert(!(max_os_index%HWLOC_BITS_PER_LONG)); +#endif hwloc_bitmap_zero(nodeset); for(i=0; ilocal_memory, - &meminfo_hugepages_count, &meminfo_hugepages_size, + &meminfo_hugepages_count, NULL /* no hugepage size in node-specific meminfo */, memory->page_types == NULL); if (memory->page_types) { @@ -1744,12 +1745,14 @@ hwloc_sysfs_node_meminfo_info(struct hwloc_topology *topology, /* read from node%d/hugepages/hugepages-%skB/nr_hugepages */ hwloc_parse_hugepages_info(topology, 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 */ - /* hwloc_get_procfs_meminfo_info must have been called earlier */ if (meminfo_hugepages_size) { memory->page_types[1].count = meminfo_hugepages_count; - memory->page_types[1].size = topology->levels[0][0]->memory.page_types[1].size; - remaining_local_memory -= meminfo_hugepages_count * memory->page_types[1].size; + memory->page_types[1].size = meminfo_hugepages_size; + remaining_local_memory -= meminfo_hugepages_count * meminfo_hugepages_size; } else { memory->page_types_len = 1; } @@ -1771,8 +1774,10 @@ hwloc_parse_node_distance(const char *distancepath, unsigned nbnodes, unsigned * if (!fd) return; - if (!fgets(string, sizeof(string), fd)) + if (!fgets(string, sizeof(string), fd)) { + fclose(fd); return; + } tmp = string; while (tmp) { diff --git a/opal/mca/common/hwloc/hwloc/src/topology-synthetic.c b/opal/mca/common/hwloc/hwloc/src/topology-synthetic.c index 6f90c6235e..75103189a2 100644 --- a/opal/mca/common/hwloc/hwloc/src/topology-synthetic.c +++ b/opal/mca/common/hwloc/hwloc/src/topology-synthetic.c @@ -85,7 +85,6 @@ hwloc_backend_synthetic_init(struct hwloc_topology *topology, const char *descri topology->backend_params.synthetic.arity[count-1] = (unsigned)item; topology->backend_params.synthetic.type[count] = type; - topology->backend_params.synthetic.id[count] = 0; count++; } @@ -162,7 +161,6 @@ hwloc_backend_synthetic_init(struct hwloc_topology *topology, const char *descri topology->backend_params.synthetic.type[0] = HWLOC_OBJ_MACHINE; nb_machine_levels++; } - topology->backend_params.synthetic.id[0] = 0; if (cache_depth == 1) /* if there is a single cache level, make it L2 */ @@ -301,6 +299,12 @@ hwloc_look_synthetic(struct hwloc_topology *topology) topology->support.discovery->pu = 1; + /* start with id=0 for each level */ + for (i = 0; topology->backend_params.synthetic.arity[i] > 0; i++) + topology->backend_params.synthetic.id[i] = 0; + /* ... including the last one */ + topology->backend_params.synthetic.id[i] = 0; + /* update first level type according to the synthetic type array */ topology->levels[0][0]->type = topology->backend_params.synthetic.type[0]; diff --git a/opal/mca/common/hwloc/hwloc/src/topology-windows.c b/opal/mca/common/hwloc/hwloc/src/topology-windows.c index 2b8c8dc2c6..f8d7c2295b 100644 --- a/opal/mca/common/hwloc/hwloc/src/topology-windows.c +++ b/opal/mca/common/hwloc/hwloc/src/topology-windows.c @@ -309,7 +309,7 @@ static BOOL WINAPI (*QueryWorkingSetExProc)(HANDLE hProcess, PVOID pv, DWORD cb) static int hwloc_win_get_VirtualAllocExNumaProc(void) { if (VirtualAllocExNumaProc == NULL) { - FARPROC alloc_fun, free_fun; + FARPROC alloc_fun = NULL, free_fun = NULL; HMODULE kernel32; kernel32 = LoadLibrary("kernel32.dll"); @@ -318,7 +318,7 @@ static int hwloc_win_get_VirtualAllocExNumaProc(void) { free_fun = GetProcAddress(kernel32, "VirtualFreeEx"); } - if (!kernel32 || !alloc_fun || !free_fun) { + if (!alloc_fun || !free_fun) { VirtualAllocExNumaProc = (FARPROC) -1; errno = ENOSYS; return -1; @@ -378,7 +378,7 @@ hwloc_win_free_membind(hwloc_topology_t topology __hwloc_attribute_unused, void static int hwloc_win_get_QueryWorkingSetExProc(void) { if (QueryWorkingSetExProc == NULL) { - FARPROC fun; + FARPROC fun = NULL; HMODULE kernel32, psapi; kernel32 = LoadLibrary("kernel32.dll"); diff --git a/opal/mca/common/hwloc/hwloc/src/topology.c b/opal/mca/common/hwloc/hwloc/src/topology.c index 4ff4517e13..a473122d8e 100644 --- a/opal/mca/common/hwloc/hwloc/src/topology.c +++ b/opal/mca/common/hwloc/hwloc/src/topology.c @@ -43,6 +43,12 @@ #include #endif +unsigned hwloc_get_api_version(void) +{ + return HWLOC_API_VERSION; +} + + static void hwloc_topology_clear (struct hwloc_topology *topology); diff --git a/opal/mca/common/hwloc/hwloc/src/traversal.c b/opal/mca/common/hwloc/hwloc/src/traversal.c index cb2ce24f53..8d3de86400 100644 --- a/opal/mca/common/hwloc/hwloc/src/traversal.c +++ b/opal/mca/common/hwloc/hwloc/src/traversal.c @@ -193,7 +193,8 @@ hwloc_obj_type_snprintf(char * __hwloc_restrict string, size_t size, hwloc_obj_t /* TODO: more pretty presentation? */ return hwloc_snprintf(string, size, "%s%u", hwloc_obj_type_string(type), obj->attr->group.depth); default: - *string = '\0'; + if (size > 0) + *string = '\0'; return 0; } }