1
1
Upgrade to hwloc 1.2 (from hwloc 1.1.2).  This should fix the problems
Nathan's seeing in #2778.

Let's let this soak on the trunk for a little while and see how LANL's
MTT's work out.  If that works, then we can CMR this to v1.5.

This commit was SVN r24635.

The following Trac tickets were found above:
  Ticket 2778 --> https://svn.open-mpi.org/trac/ompi/ticket/2778
Этот коммит содержится в:
Jeff Squyres 2011-04-25 19:31:49 +00:00
родитель b8af3b7c4a
Коммит 926af377fe
52 изменённых файлов: 2636 добавлений и 719 удалений

Просмотреть файл

@ -1,7 +1,8 @@
Copyright © 2009 CNRS
Copyright © 2009 INRIA
Copyright © 2009 INRIA. All rights reserved.
Copyright © 2009 Université Bordeaux 1
Copyright © 2009 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

Просмотреть файл

@ -1,6 +1,7 @@
# Copyright © 2009 INRIA
# Copyright © 2009 INRIA. All rights reserved.
# Copyright © 2009 Université Bordeaux 1
# Copyright © 2009-2010 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.

Просмотреть файл

@ -1,5 +1,5 @@
Copyright © 2009 CNRS
Copyright © 2009-2011 INRIA
Copyright © 2009-2011 INRIA. All rights reserved.
Copyright © 2009-2011 Université Bordeaux 1
Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
@ -17,6 +17,52 @@ bug fixes (and other actions) for each version of hwloc since version
in v0.9.1).
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

Просмотреть файл

@ -14,11 +14,11 @@ 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 is 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. More
new features and more PLPA-like features will be added to hwloc over time. See
Switching from PLPA to hwloc for more details about converting your application
from PLPA to 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:
@ -424,9 +424,10 @@ core of the machine.
/* Example hwloc API program.
*
* Copyright ? 2009-2010 INRIA
* Copyright ? 2009-2010 INRIA. All rights reserved.
* Copyright ? 2009-2011 Universit? Bordeaux 1
* Copyright ? 2009-2010 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
*
* hwloc-hello.c
*/
@ -677,12 +678,11 @@ The documentation chapters include
* Interoperability With Other Software
* Thread Safety
* Embedding hwloc in Other Software
* Switching from PLPA to hwloc
* Frequently Asked Questions
Make sure to have had a look at those too!
-------------------------------------------------------------------------------
Generated on Wed Apr 6 2011 17:31:39 for Hardware Locality (hwloc) by doxygen
Generated on Thu Apr 14 2011 22:34:49 for Hardware Locality (hwloc) by doxygen
1.7.3

Просмотреть файл

@ -6,8 +6,8 @@
# <major>.<minor>.<release>. If release is zero, then it is omitted.
major=1
minor=1
release=2
minor=2
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
@ -18,26 +18,34 @@ release=2
greek=
# If want_svn=1, then the SVN r number will be included in the overall
# If want_repo_rev=1, then the SVN r number will be included in the overall
# hwloc version number in some form.
want_svn=0
want_repo_rev=0
# If svn_r=-1, then the SVN r numbere will be obtained dynamically at
# run time, either 1) via the "svnversion" command (if this is a
# Subversion checkout) in the form "r<svn_r>", or b) with the date (if
# this is not a Subversion checkout, and the svnversion command cannot
# be used) in the form of "svn<date>". Alternatively, if svn_r is not
# -1, the value of svn_r will be directly appended to the version
# string. This happens during "make dist", for example: if the
# distribution tarball is being made from an SVN checkout, the value
# of svn_r in this file is replaced with the output of "svnversion".
# If repo_rev=-1, then the repository version number will be obtained
# dynamically at run time, either:
#
# 1) via the "svnversion" command (if this is a Subversion checkout)
# in the form "r<svn_r>", or
# 2) via the "hg -v -R tip" command (if this is a Mercurial clone)
# in the form of "hg<hash>", using the hash tag at the tip
# 3) via the "git log -1" command (if this is a Git clone) in the form
# of "git<hash>", using the hash tag at the HEAD
# 4) with the date (if none of the above work) in the form of
# "date<date>".
#
# Alternatively, if repo_rev is not -1, the value of repo_rev_r will
# be directly appended to the version string. This happens during
# "make dist", for example: if the distribution tarball is being made
# from an SVN checkout, if repo_rev=-1, then its value is replaced
# with the output of "svnversion".
svn_r=r3393
repo_rev=r3454
# The date when this release was created
date="avril 06, 2011"
date="Apr 14, 2011"
# The shared library version of hwloc's public library. This version
# is maintained in accordance with the "Library Interface Versions"
@ -50,4 +58,4 @@ date="avril 06, 2011"
# 2. Version numbers are described in the Libtool current:revision:age
# format.
libhwloc_so_version=2:1:2
libhwloc_so_version=3:0:3

Просмотреть файл

@ -10,8 +10,8 @@
# University of Stuttgart. All rights reserved.
# Copyright (c) 2004-2005 The Regents of the University of California.
# All rights reserved.
# Copyright © 2010 INRIA
# Copyright © 2009-2010 Cisco Systems, Inc. All rights reserved.
# Copyright © 2010 INRIA. All rights reserved.
# Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
@ -28,7 +28,7 @@ cd "$builddir"
set distdir="$builddir/$2"
set HWLOC_VERSION="$3"
set HWLOC_SVN_VERSION="$4"
set HWLOC_REPO_REV="$4"
if ("$distdir" == "") then
echo "Must supply relative distdir as argv[2] -- aborting"
@ -52,9 +52,9 @@ endif
# our tree's revision number, but only if we are in the source tree.
# Otherwise, use what configure told us, at the cost of allowing one
# or two corner cases in (but otherwise VPATH builds won't work).
set svn_r=$HWLOC_SVN_VERSION
set repo_rev=$HWLOC_REPO_REV
if (-d .svn) then
set svn_r="r`svnversion .`"
set repo_rev="r`svnversion .`"
endif
set start=`date`
@ -79,21 +79,21 @@ if (! -d "$distdir") then
endif
#
# See if we need to update the version file with the current SVN
# See if we need to update the version file with the current repo
# revision number. Do this *before* entering the distribution tree to
# solve a whole host of problems with VPATH (since srcdir may be
# relative or absolute)
#
set cur_svn_r="`grep '^svn_r' ${distdir}/VERSION | cut -d= -f2`"
if ("$cur_svn_r" == "-1") then
sed -e 's/^svn_r=.*/svn_r='$svn_r'/' "${distdir}/VERSION" > "${distdir}/version.new"
set cur_repo_rev="`grep '^repo_rev' ${distdir}/VERSION | cut -d= -f2`"
if ("$cur_repo_rev" == "-1") then
sed -e 's/^repo_rev=.*/repo_rev='$repo_rev'/' "${distdir}/VERSION" > "${distdir}/version.new"
cp "${distdir}/version.new" "${distdir}/VERSION"
rm -f "${distdir}/version.new"
# need to reset the timestamp to not annoy AM dependencies
touch -r "${srcdir}/VERSION" "${distdir}/VERSION"
echo "*** Updated VERSION file with SVN r number"
echo "*** Updated VERSION file with repo rev number: $repo_rev"
else
echo "*** Did NOT update VERSION file with SVN r number"
echo "*** Did NOT update VERSION file with repo rev number"
endif
#

Просмотреть файл

@ -1,6 +1,6 @@
dnl -*- Autoconf -*-
dnl
dnl Copyright (c) 2009-2010 INRIA
dnl Copyright (c) 2009-2010 INRIA. All rights reserved.
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
@ -106,7 +106,7 @@ EOF])
AC_MSG_RESULT(m4_ifval([$1], hwloc_config_prefix, [(none)]))
# Note that private/config.h *MUST* be listed first so that it
# becomes the "main" config header file. Any AC_CONFIG_HEADERs
# becomes the "main" config header file. Any AC-CONFIG-HEADERS
# after that (hwloc/config.h) will only have selective #defines
# replaced, not the entire file.
AC_CONFIG_HEADERS(hwloc_config_prefix[include/private/autogen/config.h])
@ -134,27 +134,6 @@ EOF])
[AC_DEFINE([HWLOC_SYM_TRANSFORM], [0])],
[AC_DEFINE([HWLOC_SYM_TRANSFORM], [1])])
#
# Define C flags
#
# hwloc uses C99 style, so ensure that we can figure out which
# compiler flags will drive this.
hwloc_CC_save=$CC
hwloc_CFLAGS_save=$CFLAGS
AC_PROG_CC_C99
AS_IF([test x"$ac_cv_prog_cc_c99" = xno],
[AC_WARN([C99 support is required by hwloc])
$3],
[HWLOC_SETUP_CORE_AFTER_C99($1, $2, $3, $4)])
])
dnl Same order of parameters form HWLOC-SETUP-CORE
AC_DEFUN([HWLOC_SETUP_CORE_AFTER_C99],[
hwloc_CC_c99_flags=`echo $CC | sed -e "s;^$hwloc_CC_save;;"`
CC=$hwloc_CC_save
CFLAGS=$hwloc_CFLAGS_save
# GCC specifics.
if test "x$GCC" = "xyes"; then
HWLOC_GCC_CFLAGS="-Wall -Wmissing-prototypes -Wundef"
@ -559,7 +538,6 @@ AC_DEFUN([HWLOC_SETUP_CORE_AFTER_C99],[
# Setup HWLOC's C, CPP, and LD flags, and LIBS
AC_SUBST(HWLOC_REQUIRES)
HWLOC_CFLAGS="$hwloc_CC_c99_flags $HWLOC_CFLAGS"
AC_SUBST(HWLOC_CFLAGS)
HWLOC_CPPFLAGS='-I$(HWLOC_top_srcdir)/include -I$(HWLOC_top_builddir)/include'
AC_SUBST(HWLOC_CPPFLAGS)

Просмотреть файл

@ -10,9 +10,10 @@
# Copyright (c) 2004-2005 The Regents of the University of California.
# All rights reserved.
# and renamed for hwloc:
# Copyright (c) 2009 INRIA
# 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

Просмотреть файл

@ -11,9 +11,10 @@
# All rights reserved.
# Copyright (c) 2006-2007 Cisco Systems, Inc. All rights reserved.
# and renamed for hwloc:
# Copyright (c) 2009 INRIA
# Copyright (c) 2009 Université Bordeaux 1
# Copyright (c) 2009 INRIA. All rights reserved.
# Copyright (c) 2009-2010 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

Просмотреть файл

@ -12,7 +12,7 @@
# University of Stuttgart. All rights reserved.
# Copyright (c) 2004-2005 The Regents of the University of California.
# All rights reserved.
# Copyright © 2008-2009 Cisco Systems, Inc. All rights reserved.
# Copyright © 2008-2010 Cisco Systems, Inc. All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
@ -36,8 +36,8 @@
# prefix_MINOR_VERSION
# prefix_RELEASE_VERSION
# prefix_GREEK_VERSION
# prefix_WANT_SVN
# prefix_SVN_R
# prefix_WANT_REPO_REV
# prefix_REPO_REV
# prefix_RELEASE_DATE
@ -48,10 +48,10 @@ option="$2"
case "$option" in
# svnversion can take a while to run. If we don't need it, don't run it.
--major|--minor|--release|--greek|--base|--help)
ompi_ver_need_svn=0
ompi_ver_need_repo_rev=0
;;
*)
ompi_ver_need_svn=1
ompi_ver_need_repo_rev=1
esac
@ -59,7 +59,7 @@ if test -z "$srcfile"; then
option="--help"
else
: ${ompi_ver_need_svn=1}
: ${ompi_ver_need_repo_rev=1}
: ${srcdir=.}
: ${svnversion_result=-1}
@ -71,8 +71,8 @@ else
s/^minor/HWLOC_MINOR_VERSION/
s/^release/HWLOC_RELEASE_VERSION/
s/^greek/HWLOC_GREEK_VERSION/
s/^want_svn/HWLOC_WANT_SVN/
s/^svn_r/HWLOC_SVN_R/
s/^want_repo_rev/HWLOC_WANT_REPO_REV/
s/^repo_rev/HWLOC_REPO_REV/
s/^date/HWLOC_RELEASE_DATE/
t print
b
@ -89,23 +89,25 @@ else
HWLOC_VERSION="${HWLOC_VERSION}${HWLOC_GREEK_VERSION}"
HWLOC_BASE_VERSION=$HWLOC_VERSION
if test $HWLOC_WANT_SVN -eq 1 && test $ompi_ver_need_svn -eq 1 ; then
if test $HWLOC_WANT_REPO_REV -eq 1 && test $ompi_ver_need_repo_rev -eq 1 ; then
if test "$svnversion_result" != "-1" ; then
HWLOC_SVN_R=$svnversion_result
HWLOC_REPO_REV=$svnversion_result
fi
if test "$HWLOC_SVN_R" = "-1" ; then
if test "$HWLOC_REPO_REV" = "-1" ; then
if test -d "$srcdir/.svn" ; then
HWLOC_SVN_R=r`svnversion "$srcdir"`
HWLOC_REPO_REV=r`svnversion "$srcdir"`
elif test -d "$srcdir/.hg" ; then
HWLOC_SVN_R=hg`hg -v -R "$srcdir" tip | grep changeset | cut -d: -f3`
HWLOC_REPO_REV=hg`hg -v -R "$srcdir" tip | grep changeset | cut -d: -f3`
elif test -d "$srcdir/.git" ; then
HWLOC_REPO_REV=git`git log -1 "$srcdir" | grep commit | awk '{ print $2 }'`
fi
if test "HWLOC_SVN_R" = ""; then
HWLOC_SVN_R=svn`date '+%m%d%Y'`
if test "HWLOC_REPO_REV" = ""; then
HWLOC_REPO_REV=date`date '+%m%d%Y'`
fi
fi
HWLOC_VERSION="${HWLOC_VERSION}${HWLOC_SVN_R}"
HWLOC_VERSION="${HWLOC_VERSION}${HWLOC_REPO_REV}"
fi
fi
@ -131,8 +133,8 @@ case "$option" in
--greek)
echo $HWLOC_GREEK_VERSION
;;
--svn)
echo $HWLOC_SVN_R
--repo-rev)
echo $HWLOC_REPO_REV
;;
--base)
echo $HWLOC_BASE_VERSION
@ -141,7 +143,7 @@ case "$option" in
echo $HWLOC_RELEASE_DATE
;;
--all)
echo ${HWLOC_VERSION} ${HWLOC_MAJOR_VERSION} ${HWLOC_MINOR_VERSION} ${HWLOC_RELEASE_VERSION} ${HWLOC_GREEK_VERSION} ${HWLOC_SVN_R}
echo ${HWLOC_VERSION} ${HWLOC_MAJOR_VERSION} ${HWLOC_MINOR_VERSION} ${HWLOC_RELEASE_VERSION} ${HWLOC_GREEK_VERSION} ${HWLOC_REPO_REV}
;;
-h|--help)
cat <<EOF
@ -154,9 +156,9 @@ $0 <srcfile> <option>
--minor - Minor version number
--release - Release version number
--greek - Greek (alpha, beta, etc) version number
--svn - Subversion repository number
--repo-rev - Repository version number
--all - Show all version numbers, separated by :
--base - Show base version number (no svn number)
--base - Show base version number (no repo version number)
--release-date - Show the release date
--help - This message
EOF

Просмотреть файл

@ -1,6 +1,6 @@
dnl -*- Autoconf -*-
dnl
dnl Copyright (c) 2009 INRIA
dnl Copyright (c) 2009 INRIA. All rights reserved.
dnl Copyright (c) 2009 Université Bordeaux 1
dnl Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
dnl University Research and Technology
@ -9,8 +9,10 @@ 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 © 2006-2010 Cisco Systems, Inc. All rights reserved.
dnl Copyright © 2010 INRIA. All rights reserved.
dnl Copyright © 2006-2011 Cisco Systems, Inc. All rights reserved.
dnl
dnl See COPYING in top-level directory.
#-----------------------------------------------------------------------
@ -160,7 +162,7 @@ EOF
AC_MSG_CHECKING([whether to enable "picky" compiler mode])
hwloc_want_picky=0
AS_IF([test "$GCC" = "yes"],
[AS_IF([test -d "$srcdir/.svn" -o -d "$srcdir/.hg"],
[AS_IF([test -d "$srcdir/.svn" -o -d "$srcdir/.hg" -o -d "$srcdir/.git"],
[hwloc_want_picky=1])])
if test "$enable_picky" = "yes"; then
if test "$GCC" = "yes"; then
@ -351,13 +353,13 @@ EOF
hwloc_config_prefix[tests/linux/gather/Makefile]
hwloc_config_prefix[tests/xml/Makefile]
hwloc_config_prefix[tests/ports/Makefile]
hwloc_config_prefix[tests/linux/hwloc-gather-topology.sh]
hwloc_config_prefix[tests/linux/hwloc-gather-topology]
hwloc_config_prefix[tests/linux/gather/test-gather-topology.sh]
hwloc_config_prefix[tests/linux/test-topology.sh]
hwloc_config_prefix[tests/xml/test-topology.sh]
hwloc_config_prefix[utils/test-hwloc-distrib.sh])
AC_CONFIG_COMMANDS([chmoding-scripts], [chmod +x ]hwloc_config_prefix[tests/linux/test-topology.sh ]hwloc_config_prefix[tests/xml/test-topology.sh ]hwloc_config_prefix[tests/linux/hwloc-gather-topology.sh ]hwloc_config_prefix[tests/linux/gather/test-gather-topology.sh ]hwloc_config_prefix[utils/test-hwloc-distrib.sh])
AC_CONFIG_COMMANDS([chmoding-scripts], [chmod +x ]hwloc_config_prefix[tests/linux/test-topology.sh ]hwloc_config_prefix[tests/xml/test-topology.sh ]hwloc_config_prefix[tests/linux/hwloc-gather-topology ]hwloc_config_prefix[tests/linux/gather/test-gather-topology.sh ]hwloc_config_prefix[utils/test-hwloc-distrib.sh])
# These links are only needed in standalone mode. It would
# be nice to m4 foreach this somehow, but whenever I tried

Просмотреть файл

@ -1,4 +1,5 @@
# Copyright (c) 2010 Cisco Systems, Inc. All rights reserved.
# See COPYING in top-level directory.
#
# hwloc modification to the following PKG_* macros -- add HWLOC_
# prefix to make it "safe" to embed these macros in other packages.

Просмотреть файл

@ -1,7 +1,7 @@
# -*- shell-script -*-
#
# Copyright © 2009 CNRS
# Copyright © 2009-2010 INRIA
# Copyright © 2009-2010 INRIA. All rights reserved.
# Copyright © 2009, 2011 Université Bordeaux 1
# Copyright © 2009-2010 Cisco Systems, Inc. All rights reserved.
#
@ -52,7 +52,7 @@ HWLOC_VERSION="`$srcdir/config/hwloc_get_version.sh $srcdir/VERSION`"
HWLOC_MAJOR_VERSION="`$srcdir/config/hwloc_get_version.sh $srcdir/VERSION --major`"
HWLOC_MINOR_VERSION="`$srcdir/config/hwloc_get_version.sh $srcdir/VERSION --minor`"
HWLOC_RELEASE_VERSION="`$srcdir/config/hwloc_get_version.sh $srcdir/VERSION --release`"
HWLOC_SVN_R="`$srcdir/config/hwloc_get_version.sh $srcdir/VERSION --svn`"
HWLOC_REPO_REV="`$srcdir/config/hwloc_get_version.sh $srcdir/VERSION --repo-rev`"
HWLOC_RELEASE_DATE="`$srcdir/config/hwloc_get_version.sh $srcdir/VERSION --release-date`"
AC_SUBST(HWLOC_VERSION)
AC_SUBST(HWLOC_SVN_R)
@ -85,7 +85,7 @@ AC_SUBST([libhwloc_so_version])
# Setup the header file
AH_TOP([/* -*- c -*-
*
* Copyright © 2009 CNRS, INRIA, Université Bordeaux 1
* Copyright © 2009 CNRS, INRIA., Université Bordeaux 1 All rights reserved.
* Copyright © 2009 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*

Просмотреть файл

@ -1,4 +1,4 @@
# Copyright © 2009-2011 INRIA. All rights reserved.
# Copyright © 2009-2010 INRIA. All rights reserved.
# Copyright © 2009-2010 Université Bordeaux 1
# Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
# See COPYING in top-level directory.

Просмотреть файл

@ -45,7 +45,7 @@ extern "C" {
*/
/** \brief Indicate at build time which hwloc API version is being used. */
#define HWLOC_API_VERSION 0x00010100
#define HWLOC_API_VERSION 0x00010200
/** \brief Indicate at runtime which hwloc API version was used at build time. */
HWLOC_DECLSPEC unsigned hwloc_get_api_version(void);
@ -132,6 +132,15 @@ typedef hwloc_const_bitmap_t hwloc_const_nodeset_t;
* hwloc_compare_types() instead.
*/
typedef enum {
/* ***************************************************************
WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
If new enum values are added here, you MUST also go update the
obj_type_order[] and obj_order_type[] arrays in src/topology.c.
WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
*************************************************************** */
HWLOC_OBJ_SYSTEM, /**< \brief Whole system (may be a cluster of machines).
* The whole system that is accessible to hwloc.
* That may comprise several machines in SSI systems
@ -178,10 +187,21 @@ typedef enum {
* any structure.
*/
HWLOC_OBJ_MISC /**< \brief Miscellaneous objects.
HWLOC_OBJ_MISC, /**< \brief Miscellaneous objects.
* Objects without particular meaning, that can e.g. be
* added by the application for its own use.
*/
HWLOC_OBJ_TYPE_MAX /**< \private Sentinel value */
/* ***************************************************************
WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
If new enum values are added here, you MUST also go update the
obj_type_order[] and obj_order_type[] arrays in src/topology.c.
WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
*************************************************************** */
} hwloc_obj_type_t;
/** \brief Compare the depth of two object types
@ -255,16 +275,17 @@ struct hwloc_obj {
* could be a "cousin_rank" since it's the rank within the "cousin" list below */
signed os_level; /**< \brief OS-provided physical level, -1 if unknown or meaningless */
struct hwloc_obj *next_cousin; /**< \brief Next object of same type */
struct hwloc_obj *prev_cousin; /**< \brief Previous object of same type */
/* cousins are all objects of the same type (and depth) across the entire topology */
struct hwloc_obj *next_cousin; /**< \brief Next object of same type and depth */
struct hwloc_obj *prev_cousin; /**< \brief Previous object of same type and depth */
/* parent */
/* children of the same parent are siblings, even if they may have different type and depth */
struct hwloc_obj *parent; /**< \brief Parent, \c NULL if root (system object) */
unsigned sibling_rank; /**< \brief Index in parent's \c children[] array */
struct hwloc_obj *next_sibling; /**< \brief Next object below the same parent */
struct hwloc_obj *prev_sibling; /**< \brief Previous object below the same parent */
/* children */
/* children array below this object */
unsigned arity; /**< \brief Number of children */
struct hwloc_obj **children; /**< \brief Children, \c children[0 .. arity -1] */
struct hwloc_obj *first_child; /**< \brief First child */
@ -361,6 +382,9 @@ struct hwloc_obj {
* \note Its value must not be changed, hwloc_bitmap_dup must be used instead.
*/
struct hwloc_distances_s **distances; /**< \brief Distances between all objects at same depth below this object */
unsigned distances_count;
struct hwloc_obj_info_s *infos; /**< \brief Array of stringified info type=name. */
unsigned infos_count; /**< \brief Size of infos array. */
};
@ -383,6 +407,40 @@ union hwloc_obj_attr_u {
} group;
};
/** \brief Distances between objects
*
* One object may contain a distance structure describing distances
* between all its descendants at a given relative depth. If the
* containing object is the root object of the topology, then the
* distances are available for all objects in the machine.
*
* The distance may be a memory latency, as defined by the ACPI SLIT
* specification. If so, the \p latency pointer will not be \c NULL
* and the pointed array will contain non-zero values.
*
* In the future, some other types of distances may be considered.
* In these cases, \p latency will be \c NULL.
*/
struct hwloc_distances_s {
unsigned relative_depth; /**< \brief Relative depth of the considered objects
* below the object containing this distance information. */
unsigned nbobjs; /**< \brief Number of objects considered in the matrix.
* It is the number of descendant objects at \p relative_depth
* below the containing object.
* It corresponds to the result of hwloc_get_nbobjs_inside_cpuset_by_depth. */
float *latency; /**< \brief Matrix of latencies between objects, stored as a one-dimension array.
* May be \c NULL if the distances considered here are not latencies.
* Values are normalized to get 1.0 as the minimal value in the matrix.
* Latency from i-th to j-th object is stored in slot i*nbobjs+j.
*/
float latency_max; /**< \brief The maximal value in the latency matrix. */
float latency_base; /**< \brief The multiplier that should be applied to latency matrix
* to retrieve the original OS-provided latencies.
* Usually 10 on Linux since ACPI SLIT uses 10 for local latency.
*/
};
/** \brief Object info */
struct hwloc_obj_info_s {
char *name; /**< \brief Info name */
@ -590,6 +648,18 @@ HWLOC_DECLSPEC int hwloc_topology_set_xml(hwloc_topology_t __hwloc_restrict topo
*/
HWLOC_DECLSPEC int hwloc_topology_set_xmlbuffer(hwloc_topology_t __hwloc_restrict topology, const char * __hwloc_restrict buffer, int size);
/** \brief Provide a distance matrix.
*
* Provide the matrix of distances between a set of objects of the given type.
* The set may or may not contain all the existing objects of this type.
* The objects are specified by their OS/physical index in the \p os_index
* array. The \p distances matrix follows the same order.
* The distance from object i to object j in the i*nbobjs+j.
*/
HWLOC_DECLSPEC int hwloc_topology_set_distance_matrix(hwloc_topology_t __hwloc_restrict topology,
hwloc_obj_type_t type, unsigned nbobjs,
unsigned *os_index, float *distances);
/** \brief Flags describing actual discovery support for this topology. */
struct hwloc_topology_discovery_support {
/** \brief Detecting the number of PU objects is supported. */
@ -614,6 +684,12 @@ struct hwloc_topology_cpubind_support {
unsigned char set_thread_cpubind;
/** Getting the binding of a given thread only is supported. */
unsigned char get_thread_cpubind;
/** Getting the last processors where the whole current process ran is supported */
unsigned char get_thisproc_last_cpu_location;
/** Getting the last processors where a whole process ran is supported */
unsigned char get_proc_last_cpu_location;
/** Getting the last processors where the current thread ran is supported */
unsigned char get_thisthread_last_cpu_location;
};
/** \brief Flags describing actual memory binding support for this topology. */
@ -691,25 +767,58 @@ HWLOC_DECLSPEC void hwloc_topology_export_xmlbuffer(hwloc_topology_t topology, c
/** \brief Add a MISC object to the topology
*
* A new MISC object will be created and inserted into the topology at the
* position given by bitmap \p cpuset.
* position given by bitmap \p cpuset. This offers a way to add new
* intermediate levels to the topology hierarchy.
*
* cpuset and name will be copied.
* \p cpuset and \p name will be copied to setup the new object attributes.
*
* \return the newly-created object
* \return the newly-created object.
* \return \c NULL if the insertion conflicts with the existing topology tree.
*/
HWLOC_DECLSPEC hwloc_obj_t hwloc_topology_insert_misc_object_by_cpuset(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset, const char *name);
/** \brief Add a MISC object to the topology
/** \brief Add a MISC object as a leaf of the topology
*
* A new MISC object will be created and inserted into the topology at the
* position given by parent.
* position given by parent. It is appended to the list of existing children,
* without ever adding any intermediate hierarchy level. This is useful for
* annotating the topology without actually changing the hierarchy.
*
* name will be copied.
* \p name will be copied to the setup the new object attributes.
* However, the new leaf object will not have any \p cpuset.
*
* \return the newly-created object
*/
HWLOC_DECLSPEC hwloc_obj_t hwloc_topology_insert_misc_object_by_parent(hwloc_topology_t topology, hwloc_obj_t parent, const char *name);
/** \brief Flags to be given to hwloc_topology_restrict(). */
enum hwloc_restrict_flags_e {
HWLOC_RESTRICT_FLAG_ADAPT_DISTANCES = (1<<0),
/**< \brief Adapt distance matrices according to objects being removed during restriction.
* If this flag is not set, distance matrices are removed.
* \hideinitializer
*/
HWLOC_RESTRICT_FLAG_ADAPT_MISC = (1<<1)
/**< \brief Move Misc objects to ancestors if their parents are removed during restriction.
* If this flag is not set, Misc objects are removed when their parents are removed.
* \hideinitializer
*/
};
/** \brief Restrict the topology to the given CPU set.
*
* Topology \p topology is modified so as to remove all objects that
* are not included (or partially included) in the CPU set \p cpuset.
* All objects CPU and node sets are restricted accordingly.
*
* \p flags is a OR'ed set of ::hwloc_restrict_flags_e.
*
* \note This call may not be reverted by restricting back to a larger
* cpuset. Once dropped during restriction, objects may not be brought
* back, except by reloading the entire topology with hwloc_topology_load().
*/
HWLOC_DECLSPEC int hwloc_topology_restrict(hwloc_topology_t __hwloc_restrict topology, hwloc_const_cpuset_t cpuset, unsigned long flags);
/** @} */
@ -1051,6 +1160,26 @@ HWLOC_DECLSPEC int hwloc_set_thread_cpubind(hwloc_topology_t topology, hwloc_thr
HWLOC_DECLSPEC int hwloc_get_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t tid, hwloc_cpuset_t set, int flags);
#endif
/** \brief Get the last CPU where the current process or thread ran.
*
* The operating system may move some tasks from one processor
* to another at any time according to their binding,
* so this function may return something that is already
* outdated.
*/
HWLOC_DECLSPEC int hwloc_get_last_cpu_location(hwloc_topology_t topology, hwloc_cpuset_t set, int flags);
/** \brief Get the last CPU where a process ran.
*
* The operating system may move some tasks from one processor
* to another at any time according to their binding,
* so this function may return something that is already
* outdated.
*
* \note HWLOC_CPUBIND_THREAD can not be used in \p flags.
*/
HWLOC_DECLSPEC int hwloc_get_proc_last_cpu_location(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_cpuset_t set, int flags);
/** @} */

Просмотреть файл

@ -1,6 +1,6 @@
/* -*- c -*-
* Copyright © 2009 CNRS
* Copyright © 2009-2010 INRIA
* Copyright © 2009-2010 INRIA. All rights reserved.
* Copyright © 2009-2011 Université Bordeaux 1
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.

Просмотреть файл

@ -1,7 +1,7 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2011 INRIA. All rights reserved.
* Copyright © 2009-2010 Université Bordeaux 1
* Copyright © 2009-2011 Université Bordeaux 1
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
*/
@ -69,7 +69,10 @@ HWLOC_DECLSPEC hwloc_bitmap_t hwloc_bitmap_alloc_full(void) __hwloc_attribute_ma
*/
HWLOC_DECLSPEC void hwloc_bitmap_free(hwloc_bitmap_t bitmap);
/** \brief Duplicate bitmap \p bitmap by allocating a new bitmap and copying \p bitmap contents */
/** \brief Duplicate bitmap \p bitmap by allocating a new bitmap and copying \p bitmap contents.
*
* If \p bitmap is \c NULL, \c NULL is returned.
*/
HWLOC_DECLSPEC hwloc_bitmap_t hwloc_bitmap_dup(hwloc_const_bitmap_t bitmap) __hwloc_attribute_malloc;
/** \brief Copy the contents of bitmap \p src into the already allocated bitmap \p dst */
@ -99,6 +102,29 @@ HWLOC_DECLSPEC int hwloc_bitmap_asprintf(char ** strp, hwloc_const_bitmap_t bitm
*/
HWLOC_DECLSPEC int hwloc_bitmap_sscanf(hwloc_bitmap_t bitmap, const char * __hwloc_restrict string);
/** \brief Stringify a bitmap in the list format.
*
* Lists are comma-separated indexes or ranges.
* Ranges are dash separated indexes.
* The last range may not have a ending indexes if the bitmap is infinite.
*
* 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_list_snprintf(char * __hwloc_restrict buf, size_t buflen, hwloc_const_bitmap_t bitmap);
/** \brief Stringify a bitmap into a newly allocated list string.
*/
HWLOC_DECLSPEC int hwloc_bitmap_list_asprintf(char ** strp, hwloc_const_bitmap_t bitmap);
/** \brief Parse a list string and stores it in bitmap \p bitmap.
*/
HWLOC_DECLSPEC int hwloc_bitmap_list_sscanf(hwloc_bitmap_t bitmap, const char * __hwloc_restrict string);
/** \brief Stringify a bitmap in the taskset-specific format.
*
* The taskset command manipulates bitmap strings that contain a single
@ -152,8 +178,11 @@ HWLOC_DECLSPEC void hwloc_bitmap_from_ith_ulong(hwloc_bitmap_t bitmap, unsigned
/** \brief Add index \p id in bitmap \p bitmap */
HWLOC_DECLSPEC void hwloc_bitmap_set(hwloc_bitmap_t bitmap, unsigned id);
/** \brief Add indexes from \p begin to \p end in bitmap \p bitmap. */
HWLOC_DECLSPEC void hwloc_bitmap_set_range(hwloc_bitmap_t bitmap, unsigned begin, unsigned end);
/** \brief Add indexes from \p begin to \p end in bitmap \p bitmap.
*
* If \p end is \c -1, the range is infinite.
*/
HWLOC_DECLSPEC void hwloc_bitmap_set_range(hwloc_bitmap_t bitmap, unsigned begin, int end);
/** \brief Replace \p i -th subset of bitmap \p bitmap with unsigned long \p mask */
HWLOC_DECLSPEC void hwloc_bitmap_set_ith_ulong(hwloc_bitmap_t bitmap, unsigned i, unsigned long mask);
@ -161,8 +190,11 @@ HWLOC_DECLSPEC void hwloc_bitmap_set_ith_ulong(hwloc_bitmap_t bitmap, unsigned i
/** \brief Remove index \p id from bitmap \p bitmap */
HWLOC_DECLSPEC void hwloc_bitmap_clr(hwloc_bitmap_t bitmap, unsigned id);
/** \brief Remove indexes from \p begin to \p end in bitmap \p bitmap. */
HWLOC_DECLSPEC void hwloc_bitmap_clr_range(hwloc_bitmap_t bitmap, unsigned begin, unsigned end);
/** \brief Remove indexes from \p begin to \p end in bitmap \p bitmap.
*
* If \p end is \c -1, the range is infinite.
*/
HWLOC_DECLSPEC void hwloc_bitmap_clr_range(hwloc_bitmap_t bitmap, unsigned begin, int end);
/** \brief Keep a single index among those set in bitmap \p bitmap
*
@ -199,10 +231,12 @@ HWLOC_DECLSPEC int hwloc_bitmap_isfull(hwloc_const_bitmap_t bitmap) __hwloc_attr
HWLOC_DECLSPEC int hwloc_bitmap_first(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
/** \brief Compute the next index in bitmap \p bitmap which is after index \p prev
*
* If \p prev is -1, the first index is returned.
*
* \return -1 if no index with higher index is bitmap.
*/
HWLOC_DECLSPEC int hwloc_bitmap_next(hwloc_const_bitmap_t bitmap, unsigned prev) __hwloc_attribute_pure;
HWLOC_DECLSPEC int hwloc_bitmap_next(hwloc_const_bitmap_t bitmap, int prev) __hwloc_attribute_pure;
/** \brief Compute the last index (most significant bit) in bitmap \p bitmap
*

Просмотреть файл

@ -1,6 +1,6 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2010 INRIA
* Copyright © 2009-2010 INRIA. All rights reserved.
* Copyright © 2009-2010 Université Bordeaux 1
* Copyright © 2009-2010 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.

Просмотреть файл

@ -1,5 +1,5 @@
/*
* Copyright © 2010 INRIA
* Copyright © 2010 INRIA. All rights reserved.
* Copyright © 2010 Université Bordeaux 1
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.

Просмотреть файл

@ -1,5 +1,5 @@
/*
* Copyright © 2010 INRIA
* Copyright © 2010 INRIA. All rights reserved.
* Copyright © 2010 Université Bordeaux 1
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.

Просмотреть файл

@ -1,7 +1,8 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2011 INRIA. All rights reserved.
* Copyright © 2009-2010 INRIA. All rights reserved.
* Copyright © 2009-2011 Université Bordeaux 1
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
*/
@ -77,9 +78,11 @@ static __hwloc_inline int
hwloc_cpuset_from_glibc_sched_affinity(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_cpuset_t hwlocset,
const cpu_set_t *schedset, size_t schedsetsize)
{
hwloc_bitmap_zero(hwlocset);
#ifdef CPU_ZERO_S
int cpu, count;
#endif
hwloc_bitmap_zero(hwlocset);
#ifdef CPU_ZERO_S
count = CPU_COUNT_S(schedsetsize, schedset);
cpu = 0;
while (count) {

Просмотреть файл

@ -232,13 +232,14 @@ static __hwloc_inline hwloc_obj_t
hwloc_get_first_largest_obj_inside_cpuset(hwloc_topology_t topology, hwloc_const_cpuset_t set)
{
hwloc_obj_t obj = hwloc_get_root_obj(topology);
/* FIXME: what if !root->cpuset? */
if (!hwloc_bitmap_intersects(obj->cpuset, set))
return NULL;
while (!hwloc_bitmap_isincluded(obj->cpuset, set)) {
/* while the object intersects without being included, look at its children */
hwloc_obj_t child = NULL;
while ((child = hwloc_get_next_child(topology, obj, child)) != NULL) {
if (hwloc_bitmap_intersects(child->cpuset, set))
if (child->cpuset && hwloc_bitmap_intersects(child->cpuset, set))
break;
}
if (!child)
@ -269,6 +270,7 @@ hwloc_get_next_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_cons
unsigned depth, hwloc_obj_t prev)
{
hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev);
/* no need to check next->cpuset because objects in levels always have a cpuset */
while (next && !hwloc_bitmap_isincluded(next->cpuset, set))
next = next->next_cousin;
return next;
@ -299,6 +301,7 @@ hwloc_get_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpu
unsigned count = 0;
hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0);
while (obj) {
/* no need to check obj->cpuset because objects in levels always have a cpuset */
if (hwloc_bitmap_isincluded(obj->cpuset, set)) {
if (count == idx)
return obj;
@ -333,6 +336,7 @@ hwloc_get_nbobjs_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_
hwloc_obj_t obj = hwloc_get_obj_by_depth (topology, depth, 0);
int count = 0;
while (obj) {
/* no need to check obj->cpuset because objects in levels always have a cpuset */
if (hwloc_bitmap_isincluded(obj->cpuset, set))
count++;
obj = obj->next_cousin;
@ -381,7 +385,7 @@ hwloc_get_child_covering_cpuset (hwloc_topology_t topology __hwloc_attribute_unu
child = parent->first_child;
while (child) {
if (hwloc_bitmap_isincluded(set, child->cpuset))
if (child->cpuset && hwloc_bitmap_isincluded(set, child->cpuset))
return child;
child = child->next_sibling;
}
@ -400,6 +404,7 @@ hwloc_get_obj_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t s
if (hwloc_bitmap_iszero(set))
return NULL;
/* FIXME: what if !root->cpuset? */
if (!hwloc_bitmap_isincluded(set, current->cpuset))
return NULL;
@ -432,6 +437,7 @@ hwloc_get_next_obj_covering_cpuset_by_depth(hwloc_topology_t topology, hwloc_con
unsigned depth, hwloc_obj_t prev)
{
hwloc_obj_t next = hwloc_get_next_obj_by_depth(topology, depth, prev);
/* no need to check next->cpuset because objects in levels always have a cpuset */
while (next && !hwloc_bitmap_intersects(set, next->cpuset))
next = next->next_cousin;
return next;
@ -483,15 +489,17 @@ hwloc_get_cache_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t
return NULL;
}
/** \brief Get the first cache shared between an object and somebody else
/** \brief Get the first cache shared between an object and somebody else.
*
* \return \c NULL if no cache matches
* \return \c NULL if no cache matches or if an invalid object is given.
*/
static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
hwloc_get_shared_cache_covering_obj (hwloc_topology_t topology __hwloc_attribute_unused, hwloc_obj_t obj)
{
hwloc_obj_t current = obj->parent;
while (current) {
if (!obj->cpuset)
return NULL;
while (current && current->cpuset) {
if (!hwloc_bitmap_isequal(current->cpuset, obj->cpuset)
&& current->type == HWLOC_OBJ_CACHE)
return current;
@ -563,6 +571,7 @@ hwloc_get_obj_below_array_by_type (hwloc_topology_t topology, int nr, hwloc_obj_
hwloc_obj_t obj = hwloc_get_root_obj(topology);
int i;
/* FIXME: what if !root->cpuset? */
for(i=0; i<nr; i++) {
obj = hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, typev[i], idxv[i]);
if (!obj)
@ -600,6 +609,7 @@ hwloc_distribute(hwloc_topology_t topology, hwloc_obj_t root, hwloc_cpuset_t *cp
{
unsigned i;
/* FIXME: what if !root->cpuset? */
if (!root->arity || n == 1 || root->depth >= until) {
/* Got to the bottom, we can't split any more, put everything there. */
for (i=0; i<n; i++)
@ -624,11 +634,12 @@ hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *roots, unsigned n_root
tot_weight = 0;
for (i = 0; i < n_roots; i++)
if (roots[i]->cpuset)
tot_weight += hwloc_bitmap_weight(roots[i]->cpuset);
for (i = 0; i < n_roots; i++) {
for (i = 0; i < n_roots && tot_weight; i++) {
/* Give to roots[i] a portion proportional to its weight */
unsigned weight = hwloc_bitmap_weight(roots[i]->cpuset);
unsigned weight = roots[i]->cpuset ? hwloc_bitmap_weight(roots[i]->cpuset) : 0;
unsigned chunk = (n * weight + tot_weight-1) / tot_weight;
hwloc_distribute(topology, roots[i], cpusetp, chunk, until);
cpusetp += chunk;
@ -894,6 +905,7 @@ hwloc_cpuset_from_nodeset(hwloc_topology_t topology, hwloc_cpuset_t cpuset, hwlo
obj = NULL;
while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL) {
if (hwloc_bitmap_isset(nodeset, obj->os_index))
/* no need to check obj->cpuset because objects in levels always have a cpuset */
hwloc_bitmap_or(cpuset, cpuset, obj->cpuset);
}
}
@ -916,6 +928,7 @@ hwloc_cpuset_from_nodeset_strict(struct hwloc_topology *topology, hwloc_cpuset_t
obj = NULL;
while ((obj = hwloc_get_next_obj_by_depth(topology, depth, obj)) != NULL)
if (hwloc_bitmap_isset(nodeset, obj->os_index))
/* no need to check obj->cpuset because objects in levels always have a cpuset */
hwloc_bitmap_or(cpuset, cpuset, obj->cpuset);
}
@ -923,6 +936,145 @@ hwloc_cpuset_from_nodeset_strict(struct hwloc_topology *topology, hwloc_cpuset_t
/** \defgroup hwlocality_distances Distances
* @{
*/
/** \brief Get the distances between all objects at the given depth.
*
* \return a distances structure containing a matrix with all distances
* between all objects at the given depth.
*
* Slot i+nbobjs*j contains the distance from the object of logical index i
* the object of logical index j.
*
* \note This function only returns matrices covering the whole topology,
* without any unknown distance value. Those matrices are available in
* top-level object of the hierarchy. Matrices of lower objects are not
* reported here since they cover only part of the machine.
*
* The returned structure belongs to the hwloc library. The caller should
* not modify or free it.
*
* \return \c NULL if no such distance matrix exists.
*/
static __hwloc_inline const struct hwloc_distances_s *
hwloc_get_whole_distance_matrix_by_depth(hwloc_topology_t topology, unsigned depth)
{
hwloc_obj_t root = hwloc_get_root_obj(topology);
unsigned i;
for(i=0; i<root->distances_count; i++)
if (root->distances[i]->relative_depth == depth)
return root->distances[i];
return NULL;
}
/** \brief Get the distances between all objects of a given type.
*
* \return a distances structure containing a matrix with all distances
* between all objects of the given type.
*
* Slot i+nbobjs*j contains the distance from the object of logical index i
* the object of logical index j.
*
* \note This function only returns matrices covering the whole topology,
* without any unknown distance value. Those matrices are available in
* top-level object of the hierarchy. Matrices of lower objects are not
* reported here since they cover only part of the machine.
*
* The returned structure belongs to the hwloc library. The caller should
* not modify or free it.
*
* \return \c NULL if no such distance matrix exists.
*/
static __hwloc_inline const struct hwloc_distances_s *
hwloc_get_whole_distance_matrix_by_type(hwloc_topology_t topology, hwloc_obj_type_t type)
{
int depth = hwloc_get_type_depth(topology, type);
if (depth < 0)
return NULL;
return hwloc_get_whole_distance_matrix_by_depth(topology, depth);
}
/** \brief Get distances for the given depth and covering some objects
*
* Return a distance matrix that describes depth \p depth and covers at
* least object \p obj and all its ancestors.
*
* When looking for the distance between some objects, a common ancestor should
* be passed in \p obj.
*
* \p firstp is set to logical index of the first object described by the matrix.
*
* The returned structure belongs to the hwloc library. The caller should
* not modify or free it.
*/
static __hwloc_inline const struct hwloc_distances_s *
hwloc_get_distance_matrix_covering_obj_by_depth(hwloc_topology_t topology,
hwloc_obj_t obj, unsigned depth,
unsigned *firstp)
{
while (obj && obj->cpuset) {
unsigned i;
for(i=0; i<obj->distances_count; i++)
if (obj->distances[i]->relative_depth == depth - obj->depth) {
if (!obj->distances[i]->nbobjs)
continue;
*firstp = hwloc_get_next_obj_inside_cpuset_by_depth(topology, obj->cpuset, depth, NULL)->logical_index;
return obj->distances[i];
}
obj = obj->parent;
}
return NULL;
}
/** \brief Get the latency in both directions between two objects.
*
* Look at ancestor objects from the bottom to the top until one of them
* contains a distance matrix that matches the objects exactly.
*
* \p latency gets the value from object \p obj1 to \p obj2, while
* \p reverse_latency gets the reverse-direction value, which
* may be different on some architectures.
*
* \return -1 if no ancestor contains a matching latency matrix.
*/
static __hwloc_inline int
hwloc_get_latency(hwloc_topology_t topology,
hwloc_obj_t obj1, hwloc_obj_t obj2,
float *latency, float *reverse_latency)
{
hwloc_obj_t ancestor;
const struct hwloc_distances_s * distances;
unsigned first_logical ;
if (obj1->depth != obj2->depth) {
errno = EINVAL;
return -1;
}
ancestor = hwloc_get_common_ancestor_obj(topology, obj1, obj2);
distances = hwloc_get_distance_matrix_covering_obj_by_depth(topology, ancestor, obj1->depth, &first_logical);
if (distances && distances->latency) {
const float * latency_matrix = distances->latency;
unsigned nbobjs = distances->nbobjs;
unsigned l1 = obj1->logical_index - first_logical;
unsigned l2 = obj2->logical_index - first_logical;
*latency = latency_matrix[l1*nbobjs+l2];
*reverse_latency = latency_matrix[l2*nbobjs+l1];
return 0;
}
errno = ENOSYS;
return -1;
}
/** @} */
#ifdef __cplusplus
} /* extern "C" */
#endif

Просмотреть файл

@ -1,6 +1,6 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2010 INRIA
* Copyright © 2009-2010 INRIA. All rights reserved.
* Copyright © 2009-2010 Université Bordeaux 1
* See COPYING in top-level directory.
*/

Просмотреть файл

@ -1,6 +1,6 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2010 INRIA
* Copyright © 2009-2010 INRIA. All rights reserved.
* Copyright © 2009-2010 Université Bordeaux 1
* See COPYING in top-level directory.
*/

Просмотреть файл

@ -1,5 +1,5 @@
/*
* Copyright © 2010 INRIA
* Copyright © 2010 INRIA. All rights reserved.
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
*/

Просмотреть файл

@ -1,6 +1,6 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2010 INRIA
* Copyright © 2009-2010 INRIA. All rights reserved.
* Copyright © 2009-2010 Université Bordeaux 1
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.

Просмотреть файл

@ -1,5 +1,6 @@
/*
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
* Copyright © 2010-2011 INRIA. All rights reserved.
* See COPYING in top-level directory.
*/
@ -55,21 +56,24 @@ extern "C" {
#define HWLOC_OBJ_PU HWLOC_NAME_CAPS(OBJ_PU)
#define HWLOC_OBJ_MISC HWLOC_NAME_CAPS(OBJ_MISC)
#define HWLOC_OBJ_GROUP HWLOC_NAME_CAPS(OBJ_GROUP)
#define HWLOC_OBJ_TYPE_MAX HWLOC_NAME_CAPS(OBJ_TYPE_MAX)
#define hwloc_obj_type_t HWLOC_NAME(obj_type_t)
#define hwloc_compare_types_e HWLOC_NAME(compare_types_e)
#define hwloc_compare_types HWLOC_NAME(compare_types)
#define hwloc_compare_types_e HWLOC_NAME(compare_types_e)
#define HWLOC_TYPE_UNORDERED HWLOC_NAME_CAPS(TYPE_UNORDERED)
#define hwloc_obj_memory_s HWLOC_NAME(obj_memory_s)
#define hwloc_obj_memory_page_type_s HWLOC_NAME(obj_memory_page_type_s)
#define hwloc_obj_info_s HWLOC_NAME(hwloc_obj_info_s)
#define hwloc_obj HWLOC_NAME(obj)
#define hwloc_obj_t HWLOC_NAME(obj_t)
#define hwloc_distances_s HWLOC_NAME(distances_s)
#define hwloc_obj_info_s HWLOC_NAME(obj_info_s)
#define hwloc_obj_attr_u HWLOC_NAME(obj_attr_u)
#define hwloc_cache_attr_s HWLOC_NAME(cache_attr_s)
#define hwloc_group_attr_s HWLOC_NAME(group_attr_s)
@ -93,6 +97,7 @@ extern "C" {
#define hwloc_topology_set_synthetic HWLOC_NAME(topology_set_synthetic)
#define hwloc_topology_set_xml HWLOC_NAME(topology_set_xml)
#define hwloc_topology_set_xmlbuffer HWLOC_NAME(topology_set_xmlbuffer)
#define hwloc_topology_set_distance_matrix HWLOC_NAME(topology_set_distance_matrix)
#define hwloc_topology_discovery_support HWLOC_NAME(topology_discovery_support)
#define hwloc_topology_cpubind_support HWLOC_NAME(topology_cpubind_support)
@ -105,6 +110,11 @@ extern "C" {
#define hwloc_topology_insert_misc_object_by_cpuset HWLOC_NAME(topology_insert_misc_object_by_cpuset)
#define hwloc_topology_insert_misc_object_by_parent HWLOC_NAME(topology_insert_misc_object_by_parent)
#define hwloc_restrict_flags_e HWLOC_NAME(restrict_flags_e)
#define HWLOC_RESTRICT_FLAG_ADAPT_DISTANCES HWLOC_NAME_CAPS(RESTRICT_FLAG_ADAPT_DISTANCES)
#define HWLOC_RESTRICT_FLAG_ADAPT_MISC HWLOC_NAME_CAPS(RESTRICT_FLAG_ADAPT_MISC)
#define hwloc_topology_restrict HWLOC_NAME(topology_restrict)
#define hwloc_topology_get_depth HWLOC_NAME(topology_get_depth)
#define hwloc_get_type_depth HWLOC_NAME(get_type_depth)
@ -143,6 +153,9 @@ extern "C" {
#define hwloc_set_thread_cpubind HWLOC_NAME(set_thread_cpubind)
#define hwloc_get_thread_cpubind HWLOC_NAME(get_thread_cpubind)
#define hwloc_get_last_cpu_location HWLOC_NAME(get_last_cpu_location)
#define hwloc_get_proc_last_cpu_location HWLOC_NAME(get_proc_last_cpu_location)
#define HWLOC_MEMBIND_DEFAULT HWLOC_NAME_CAPS(MEMBIND_DEFAULT)
#define HWLOC_MEMBIND_FIRSTTOUCH HWLOC_NAME_CAPS(MEMBIND_FIRSTTOUCH)
#define HWLOC_MEMBIND_BIND HWLOC_NAME_CAPS(MEMBIND_BIND)
@ -193,6 +206,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_list_snprintf HWLOC_NAME(bitmap_list_snprintf)
#define hwloc_bitmap_list_asprintf HWLOC_NAME(bitmap_list_asprintf)
#define hwloc_bitmap_list_sscanf HWLOC_NAME(bitmap_list_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)
@ -307,8 +323,10 @@ extern "C" {
#define hwloc_get_closest_objs HWLOC_NAME(get_closest_objs)
#define hwloc_get_obj_below_by_type HWLOC_NAME(get_obj_below_by_type)
#define hwloc_get_obj_below_array_by_type HWLOC_NAME(get_obj_below_array_by_type)
#define hwloc_distribute HWLOC_NAME(distribute)
#define hwloc_distributev HWLOC_NAME(distributev)
#define hwloc_distribute HWLOC_NAME(distribute)
#define hwloc_alloc_membind_policy HWLOC_NAME(alloc_membind_policy)
#define hwloc_alloc_membind_policy_nodeset HWLOC_NAME(alloc_membind_policy_nodeset)
#define hwloc_topology_get_complete_cpuset HWLOC_NAME(topology_get_complete_cpuset)
#define hwloc_topology_get_topology_cpuset HWLOC_NAME(topology_get_topology_cpuset)
#define hwloc_topology_get_online_cpuset HWLOC_NAME(topology_get_online_cpuset)
@ -320,8 +338,10 @@ extern "C" {
#define hwloc_cpuset_to_nodeset_strict HWLOC_NAME(cpuset_to_nodeset_strict)
#define hwloc_cpuset_from_nodeset HWLOC_NAME(cpuset_from_nodeset)
#define hwloc_cpuset_from_nodeset_strict HWLOC_NAME(cpuset_from_nodeset_strict)
#define hwloc_alloc_membind_policy HWLOC_NAME(alloc_membind_policy)
#define hwloc_alloc_membind_policy_nodeset HWLOC_NAME(alloc_membind_policy_nodeset)
#define hwloc_get_whole_distance_matrix_by_depth HWLOC_NAME(get_whole_distance_matrix_by_depth)
#define hwloc_get_whole_distance_matrix_by_type HWLOC_NAME(get_whole_distance_matrix_by_type)
#define hwloc_get_distance_matrix_covering_obj_by_depth HWLOC_NAME(get_distance_matrix_covering_obj_by_depth)
#define hwloc_get_latency HWLOC_NAME(get_latency)
/* glibc-sched.h */
@ -366,6 +386,10 @@ extern "C" {
#define hwloc_cudart_get_device_cpuset HWLOC_NAME(cudart_get_device_cpuset)
/* private/debug.h */
#define hwloc_debug HWLOC_NAME(debug)
/* private/misc.h */
#define hwloc_snprintf HWLOC_NAME(snprintf)
@ -389,6 +413,7 @@ extern "C" {
#define HWLOC_IGNORE_TYPE_KEEP_STRUCTURE HWLOC_NAME_CAPS(IGNORE_TYPE_KEEP_STRUCTURE)
#define HWLOC_IGNORE_TYPE_ALWAYS HWLOC_NAME_CAPS(IGNORE_TYPE_ALWAYS)
#define hwloc_os_distances_s HWLOC_NAME(os_distances_s)
#define hwloc_backend_e HWLOC_NAME(backend_e)
#define hwloc_backend_t HWLOC_NAME(backend_t)
@ -416,6 +441,7 @@ extern "C" {
#define hwloc_backend_sysfs_exit HWLOC_NAME(backend_sysfs_exit)
#define hwloc_backend_xml_init HWLOC_NAME(backend_xml_init)
#define hwloc_xml_check_distances HWLOC_NAME(xml_check_distances)
#define hwloc_look_xml HWLOC_NAME(look_xml)
#define hwloc_backend_xml_exit HWLOC_NAME(backend_xml_exit)
@ -447,12 +473,16 @@ extern "C" {
#define hwloc_look_synthetic HWLOC_NAME(look_synthetic )
#define hwloc_insert_object_by_cpuset HWLOC_NAME(insert_object_by_cpuset)
#define hwloc_report_error_t HWLOC_NAME(report_error_t)
#define hwloc_report_os_error HWLOC_NAME(report_os_error)
#define hwloc__insert_object_by_cpuset HWLOC_NAME(_insert_object_by_cpuset)
#define hwloc_insert_object_by_parent HWLOC_NAME(insert_object_by_parent)
#define hwloc_add_object_info HWLOC_NAME(add_object_info)
#define hwloc_add_uname_info HWLOC_NAME(add_uname_info)
#define hwloc_free_object HWLOC_NAME(free_object)
#define hwloc_bitmap_printf_value HWLOC_NAME(bitmap_printf_value)
#define hwloc_alloc_setup_object HWLOC_NAME(alloc_setup_object)
#define hwloc_free_unlinked_object HWLOC_NAME(free_unlinked_object)
#define hwloc_setup_level HWLOC_NAME(setup_level)
#define hwloc_alloc_heap HWLOC_NAME(alloc_heap)
@ -461,6 +491,17 @@ extern "C" {
#define hwloc_free_mmap HWLOC_NAME(free_mmap)
#define hwloc_alloc_or_fail HWLOC_NAME(alloc_or_fail)
#define hwloc_topology_distances_init HWLOC_NAME(topology_distances_init)
#define hwloc_topology_distances_clear HWLOC_NAME(topology_distances_clear)
#define hwloc_topology_distances_destroy HWLOC_NAME(topology_distances_destroy)
#define hwloc_topology__set_distance_matrix HWLOC_NAME(topology__set_distance_matrix)
#define hwloc_store_distances_from_env HWLOC_NAME(store_distances_from_env)
#define hwloc_convert_distances_indexes_into_objects HWLOC_NAME(convert_distances_indexes_into_objects)
#define hwloc_finalize_logical_distances HWLOC_NAME(finalize_logical_distances)
#define hwloc_restrict_distances HWLOC_NAME(restrict_distances)
#define hwloc_free_logical_distances HWLOC_NAME(free_logical_distances)
#define hwloc_group_by_distances HWLOC_NAME(group_by_distances)
#endif /* HWLOC_SYM_TRANSFORM */

Просмотреть файл

@ -2,7 +2,7 @@
/* -*- c -*-
*
* Copyright © 2009 CNRS, INRIA, Université Bordeaux 1
* Copyright © 2009 CNRS, INRIA., Université Bordeaux 1 All rights reserved.
* Copyright © 2009 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*

Просмотреть файл

@ -1,5 +1,5 @@
/*
* Copyright © 2010 Université Bordeaux 1
* Copyright © 2010-2011 Université Bordeaux 1
* Copyright © 2010 Cisco Systems, Inc. All rights reserved.
*
* See COPYING in top-level directory.
@ -11,7 +11,7 @@
#define HWLOC_PRIVATE_CPUID_H
#ifdef HWLOC_X86_32_ARCH
static inline int hwloc_have_cpuid(void)
static __hwloc_inline int hwloc_have_cpuid(void)
{
int ret;
unsigned tmp, tmp2;
@ -46,10 +46,10 @@ static inline int hwloc_have_cpuid(void)
}
#endif /* HWLOC_X86_32_ARCH */
#ifdef HWLOC_X86_64_ARCH
static inline int hwloc_have_cpuid(void) { return 1; }
static __hwloc_inline int hwloc_have_cpuid(void) { return 1; }
#endif /* HWLOC_X86_64_ARCH */
static inline void hwloc_cpuid(unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx)
static __hwloc_inline void hwloc_cpuid(unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx)
{
asm(
#ifdef HWLOC_X86_32_ARCH

Просмотреть файл

@ -1,7 +1,7 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2010 INRIA
* Copyright © 2009 Université Bordeaux 1
* Copyright © 2009-2010 INRIA. All rights reserved.
* Copyright © 2009, 2011 Université Bordeaux 1
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
*/
@ -14,7 +14,22 @@
#include <private/autogen/config.h>
#ifdef HWLOC_DEBUG
#define hwloc_debug(s, ...) fprintf(stderr, s, ##__VA_ARGS__)
#include <stdarg.h>
#include <stdio.h>
#endif
static __hwloc_inline void hwloc_debug(const char *s __hwloc_attribute_unused, ...)
{
#ifdef HWLOC_DEBUG
va_list ap;
va_start(ap, s);
vfprintf(stderr, s, ap);
va_end(ap);
#endif
}
#ifdef HWLOC_DEBUG
#define hwloc_debug_bitmap(fmt, bitmap) do { \
char *s= hwloc_bitmap_printf_value(bitmap); \
fprintf(stderr, fmt, s); \
@ -31,7 +46,6 @@
free(s); \
} while (0)
#else
#define hwloc_debug(s, ...) do { } while(0)
#define hwloc_debug_bitmap(s, bitmap) do { } while(0)
#define hwloc_debug_1arg_bitmap(s, arg1, bitmap) do { } while(0)
#define hwloc_debug_2args_bitmap(s, arg1, arg2, bitmap) do { } while(0)

Просмотреть файл

@ -1,7 +1,7 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2010 INRIA
* Copyright © 2009-2010 Université Bordeaux 1
* Copyright © 2009-2010 INRIA. All rights reserved.
* Copyright © 2009-2011 Université Bordeaux 1
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
*/
@ -75,7 +75,7 @@ extern int ffs(int) __hwloc_attribute_const;
#else /* no ffs implementation */
static inline int __hwloc_attribute_const
static __hwloc_inline int __hwloc_attribute_const
hwloc_ffsl(unsigned long x)
{
int i;
@ -121,7 +121,7 @@ hwloc_ffsl(unsigned long x)
/* We only have an int ffs(int) implementation, build a long one. */
/* First make it 32 bits if it was only 16. */
static inline int __hwloc_attribute_const
static __hwloc_inline int __hwloc_attribute_const
hwloc_ffs32(unsigned long x)
{
#if HWLOC_BITS_PER_INT == 16
@ -142,7 +142,7 @@ hwloc_ffs32(unsigned long x)
}
/* Then make it 64 bit if longs are. */
static inline int __hwloc_attribute_const
static __hwloc_inline int __hwloc_attribute_const
hwloc_ffsl(unsigned long x)
{
#if HWLOC_BITS_PER_LONG == 64
@ -211,7 +211,7 @@ extern int clz(int) __hwloc_attribute_const;
#else /* no fls implementation */
static inline int __hwloc_attribute_const
static __hwloc_inline int __hwloc_attribute_const
hwloc_flsl(unsigned long x)
{
int i = 0;
@ -257,7 +257,7 @@ hwloc_flsl(unsigned long x)
/* We only have an int fls(int) implementation, build a long one. */
/* First make it 32 bits if it was only 16. */
static inline int __hwloc_attribute_const
static __hwloc_inline int __hwloc_attribute_const
hwloc_fls32(unsigned long x)
{
#if HWLOC_BITS_PER_INT == 16
@ -278,7 +278,7 @@ hwloc_fls32(unsigned long x)
}
/* Then make it 64 bit if longs are. */
static inline int __hwloc_attribute_const
static __hwloc_inline int __hwloc_attribute_const
hwloc_flsl(unsigned long x)
{
#if HWLOC_BITS_PER_LONG == 64
@ -299,7 +299,7 @@ hwloc_flsl(unsigned long x)
}
#endif
static inline int __hwloc_attribute_const
static __hwloc_inline int __hwloc_attribute_const
hwloc_weight_long(unsigned long w)
{
#if HWLOC_BITS_PER_LONG == 32

Просмотреть файл

@ -1,7 +1,7 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2010 INRIA
* Copyright © 2009-2010 Université Bordeaux 1
* Copyright © 2009-2011 INRIA. All rights reserved.
* Copyright © 2009-2011 Université Bordeaux 1
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
*
* See COPYING in top-level directory.
@ -39,8 +39,6 @@ enum hwloc_ignore_type_e {
HWLOC_IGNORE_TYPE_ALWAYS
};
/* Maximal value of an object type */
#define HWLOC_OBJ_TYPE_MAX (HWLOC_OBJ_MISC+1)
#define HWLOC_DEPTH_MAX 128
typedef enum hwloc_backend_e {
@ -59,6 +57,7 @@ typedef enum hwloc_backend_e {
struct hwloc_topology {
unsigned nb_levels; /* Number of horizontal levels */
unsigned next_group_depth; /* Depth of the next Group object that we may create */
unsigned level_nbobjects[HWLOC_DEPTH_MAX]; /* Number of objects on each horizontal level */
struct hwloc_obj **levels[HWLOC_DEPTH_MAX]; /* Direct access to levels, levels[l = 0 .. nblevels-1][0..level_nbobjects[l]] */
unsigned long flags;
@ -79,6 +78,10 @@ struct hwloc_topology {
int (*get_thread_cpubind)(hwloc_topology_t topology, hwloc_thread_t tid, hwloc_cpuset_t set, int flags);
#endif
int (*get_thisproc_last_cpu_location)(hwloc_topology_t topology, hwloc_cpuset_t set, int flags);
int (*get_thisthread_last_cpu_location)(hwloc_topology_t topology, hwloc_cpuset_t set, int flags);
int (*get_proc_last_cpu_location)(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_cpuset_t set, int flags);
int (*set_thisproc_membind)(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags);
int (*get_thisproc_membind)(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags);
int (*set_thisthread_membind)(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags);
@ -96,6 +99,20 @@ struct hwloc_topology {
struct hwloc_topology_support support;
struct hwloc_os_distances_s {
int nbobjs;
unsigned *indexes; /* array of OS indexes before we can convert them into objs. always available.
*/
struct hwloc_obj **objs; /* array of objects, in the same order as above.
* either given (by a backend) together with the indexes array above.
* or build from the above indexes array when not given (by the user).
*/
float *distances; /* distance matrices, ordered according to the above indexes/objs array.
* distance from i to j is stored in slot i*nbnodes+j.
* will be copied into the main logical-index-ordered distance at the end of the discovery.
*/
} os_distances[HWLOC_OBJ_TYPE_MAX];
hwloc_backend_t backend_type;
union hwloc_backend_params_u {
#ifdef HWLOC_LINUX_SYS
@ -129,7 +146,6 @@ struct hwloc_topology {
extern void hwloc_setup_pu_level(struct hwloc_topology *topology, unsigned nb_pus);
extern void hwloc_setup_misc_level_from_distances(struct hwloc_topology *topology, unsigned nbobjs, struct hwloc_obj **objs, unsigned *_distances/*[nbnobjs][nbobjs]*/, unsigned *distance_indexes /*[nbobjs]*/);
extern int hwloc_get_sysctlbyname(const char *name, int64_t *n);
extern int hwloc_get_sysctl(int name[], unsigned namelen, int *n);
extern unsigned hwloc_fallback_nbprocessors(struct hwloc_topology *topology);
@ -143,6 +159,7 @@ extern void hwloc_backend_sysfs_exit(struct hwloc_topology *topology);
#ifdef HWLOC_HAVE_XML
extern int hwloc_backend_xml_init(struct hwloc_topology *topology, const char *xmlpath, const char *xmlbuffer, int buflen);
extern void hwloc_xml_check_distances(struct hwloc_topology *topology);
extern void hwloc_look_xml(struct hwloc_topology *topology);
extern void hwloc_backend_xml_exit(struct hwloc_topology *topology);
#endif /* HWLOC_HAVE_XML */
@ -201,9 +218,18 @@ extern void hwloc_look_synthetic (struct hwloc_topology *topology);
* The given object should not have children.
*
* This shall only be called before levels are built.
*
* In case of error, hwloc_report_os_error() is called.
*/
extern void hwloc_insert_object_by_cpuset(struct hwloc_topology *topology, hwloc_obj_t obj);
/*
* Add an object to the topology and specify which error callback to use
*/
typedef void (*hwloc_report_error_t)(const char * msg, int line);
extern void hwloc_report_os_error(const char * msg, int line);
extern int hwloc__insert_object_by_cpuset(struct hwloc_topology *topology, hwloc_obj_t obj, hwloc_report_error_t report_error);
/*
* Insert an object somewhere in the topology.
*
@ -224,7 +250,7 @@ extern void hwloc_add_object_info(hwloc_obj_t obj, const char *name, const char
extern void hwloc_add_uname_info(struct hwloc_topology *topology);
/** \brief Return a locally-allocated stringified bitmap for printf-like calls. */
static inline char *
static __hwloc_inline char *
hwloc_bitmap_printf_value(hwloc_const_bitmap_t bitmap)
{
char *buf;
@ -232,7 +258,7 @@ hwloc_bitmap_printf_value(hwloc_const_bitmap_t bitmap)
return buf;
}
static inline struct hwloc_obj *
static __hwloc_inline struct hwloc_obj *
hwloc_alloc_setup_object(hwloc_obj_type_t type, signed idx)
{
struct hwloc_obj *obj = malloc(sizeof(*obj));
@ -246,7 +272,7 @@ hwloc_alloc_setup_object(hwloc_obj_type_t type, signed idx)
return obj;
}
extern void hwloc_free_object(hwloc_obj_t obj);
extern void hwloc_free_unlinked_object(hwloc_obj_t obj);
#define hwloc_object_cpuset_from_array(l, _value, _array, _max) do { \
struct hwloc_obj *__l = (l); \
@ -261,7 +287,7 @@ extern void hwloc_free_object(hwloc_obj_t obj);
/* Configures an array of NUM objects of type TYPE with physical IDs OSPHYSIDS
* and for which processors have ID PROC_PHYSIDS, and add them to the topology.
* */
static inline void
static __hwloc_inline void
hwloc_setup_level(int procid_max, unsigned num, unsigned *osphysids, unsigned *proc_physids, struct hwloc_topology *topology, hwloc_obj_type_t type)
{
struct hwloc_obj *obj;
@ -295,7 +321,7 @@ int hwloc_free_mmap(hwloc_topology_t topology, void *addr, size_t len);
/* Allocates unbound memory or fail, depending on whether STRICT is requested
* or not */
static inline void *
static __hwloc_inline void *
hwloc_alloc_or_fail(hwloc_topology_t topology, size_t len, int flags)
{
if (flags & HWLOC_MEMBIND_STRICT)
@ -303,4 +329,15 @@ hwloc_alloc_or_fail(hwloc_topology_t topology, size_t len, int flags)
return hwloc_alloc(topology, len);
}
extern void hwloc_topology_distances_init(struct hwloc_topology *topology);
extern void hwloc_topology_distances_clear(struct hwloc_topology *topology);
extern void hwloc_topology_distances_destroy(struct hwloc_topology *topology);
extern void hwloc_topology__set_distance_matrix(struct hwloc_topology *topology, hwloc_obj_type_t type, unsigned nbobjs, unsigned *indexes, hwloc_obj_t *objs, float *distances);
extern void hwloc_store_distances_from_env(struct hwloc_topology *topology);
extern void hwloc_convert_distances_indexes_into_objects(struct hwloc_topology *topology);
extern void hwloc_finalize_logical_distances(struct hwloc_topology *topology);
extern void hwloc_restrict_distances(struct hwloc_topology *topology, unsigned long flags);
extern void hwloc_free_logical_distances(struct hwloc_distances_s *dist);
extern void hwloc_group_by_distances(struct hwloc_topology *topology);
#endif /* HWLOC_PRIVATE_H */

Просмотреть файл

@ -1,6 +1,7 @@
# Copyright © 2009-2010 INRIA
# Copyright © 2009-2010 INRIA. All rights reserved.
# Copyright © 2009-2010 Université Bordeaux 1
# Copyright © 2009-2010 Cisco Systems, Inc. All rights reserved.
# See COPYING in top-level directory.
AM_CFLAGS = $(HWLOC_CFLAGS)
AM_CPPFLAGS = $(HWLOC_CPPFLAGS)
@ -22,6 +23,7 @@ endif
sources = \
topology.c \
traversal.c \
distances.c \
topology-synthetic.c \
bind.c \
cpuset.c \

Просмотреть файл

@ -1,6 +1,6 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2010 INRIA
* Copyright © 2009-2011 INRIA. All rights reserved.
* Copyright © 2009-2010 Université Bordeaux 1
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
@ -152,6 +152,36 @@ hwloc_get_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t tid, hwloc_bi
}
#endif
int
hwloc_get_last_cpu_location(hwloc_topology_t topology, hwloc_bitmap_t set, int flags)
{
if (flags & HWLOC_CPUBIND_PROCESS) {
if (topology->get_thisproc_last_cpu_location)
return topology->get_thisproc_last_cpu_location(topology, set, flags);
} else if (flags & HWLOC_CPUBIND_THREAD) {
if (topology->get_thisthread_last_cpu_location)
return topology->get_thisthread_last_cpu_location(topology, set, flags);
} else {
if (topology->get_thisproc_last_cpu_location)
return topology->get_thisproc_last_cpu_location(topology, set, flags);
else if (topology->get_thisthread_last_cpu_location)
return topology->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->get_proc_last_cpu_location)
return topology->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)
{
@ -461,8 +491,8 @@ hwloc_alloc(hwloc_topology_t topology, size_t 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)
{
nodeset = hwloc_fix_membind(topology, nodeset);
void *p;
nodeset = hwloc_fix_membind(topology, nodeset);
if (!nodeset)
goto fallback;
if (flags & HWLOC_MEMBIND_MIGRATE) {

Просмотреть файл

@ -1,7 +1,7 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2010 INRIA
* Copyright © 2009-2010 Université Bordeaux 1
* Copyright © 2009-2011 INRIA. All rights reserved.
* Copyright © 2009-2011 Université Bordeaux 1
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
*/
@ -178,6 +178,9 @@ 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));
@ -369,6 +372,129 @@ int hwloc_bitmap_sscanf(struct hwloc_bitmap_s *set, const char * __hwloc_restric
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;
@ -556,7 +682,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=0; j<(unsigned) i; j++)
for(j=0; j<i; j++)
set->ulongs[j] = HWLOC_SUBBITMAP_ZERO;
set->infinite = 0;
}
@ -611,13 +737,19 @@ void hwloc_bitmap_set(struct hwloc_bitmap_s * set, unsigned cpu)
set->ulongs[index_] |= HWLOC_SUBBITMAP_CPU(cpu);
}
void hwloc_bitmap_set_range(struct hwloc_bitmap_s * set, unsigned begincpu, unsigned endcpu)
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)
@ -663,13 +795,19 @@ void hwloc_bitmap_clr(struct hwloc_bitmap_s * set, unsigned cpu)
set->ulongs[index_] &= ~HWLOC_SUBBITMAP_CPU(cpu);
}
void hwloc_bitmap_clr_range(struct hwloc_bitmap_s * set, unsigned begincpu, unsigned endcpu)
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)
@ -902,7 +1040,7 @@ int hwloc_bitmap_last(const struct hwloc_bitmap_s * set)
return -1;
}
int hwloc_bitmap_next(const struct hwloc_bitmap_s * set, unsigned prev_cpu)
int hwloc_bitmap_next(const struct hwloc_bitmap_s * set, int prev_cpu)
{
unsigned i = HWLOC_SUBBITMAP_INDEX(prev_cpu + 1);
@ -921,7 +1059,7 @@ int hwloc_bitmap_next(const struct hwloc_bitmap_s * set, unsigned prev_cpu)
/* if the prev cpu is in the same word as the possible next one,
we need to mask out previous cpus */
if (HWLOC_SUBBITMAP_INDEX(prev_cpu) == i)
if (prev_cpu >= 0 && HWLOC_SUBBITMAP_INDEX((unsigned) prev_cpu) == i)
w &= ~HWLOC_SUBBITMAP_ULBIT_TO(HWLOC_SUBBITMAP_CPU_ULBIT(prev_cpu));
if (w)

717
opal/mca/common/hwloc/hwloc/src/distances.c Обычный файл
Просмотреть файл

@ -0,0 +1,717 @@
/*
* Copyright © 2010-2011 INRIA. All rights reserved.
* Copyright © 2011 Université Bordeaux 1
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
*/
#include <private/autogen/config.h>
#include <hwloc.h>
#include <private/private.h>
#include <private/debug.h>
#include <float.h>
/* called during topology init */
void hwloc_topology_distances_init(struct hwloc_topology *topology)
{
unsigned i;
for (i=0; i < HWLOC_OBJ_TYPE_MAX; i++) {
/* no distances yet */
topology->os_distances[i].nbobjs = 0;
topology->os_distances[i].objs = NULL;
topology->os_distances[i].indexes = NULL;
topology->os_distances[i].distances = NULL;
}
}
/* called when reloading a topology.
* keep initial parameters (from set_distances and environment),
* but drop what was generated during previous load().
*/
void hwloc_topology_distances_clear(struct hwloc_topology *topology)
{
unsigned i;
for (i=0; i < HWLOC_OBJ_TYPE_MAX; i++) {
/* remove final distance matrices, but keep physically-ordered ones */
free(topology->os_distances[i].objs);
topology->os_distances[i].objs = NULL;
}
}
/* called during topology destroy */
void hwloc_topology_distances_destroy(struct hwloc_topology *topology)
{
unsigned i;
for (i=0; i < HWLOC_OBJ_TYPE_MAX; i++) {
/* remove final distance matrics AND physically-ordered ones */
free(topology->os_distances[i].indexes);
topology->os_distances[i].indexes = NULL;
free(topology->os_distances[i].objs);
topology->os_distances[i].objs = NULL;
free(topology->os_distances[i].distances);
topology->os_distances[i].distances = NULL;
}
}
/* 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_topology__set_distance_matrix(hwloc_topology_t __hwloc_restrict topology, hwloc_obj_type_t type,
unsigned nbobjs, unsigned *indexes, hwloc_obj_t *objs, float *distances)
{
free(topology->os_distances[type].indexes);
free(topology->os_distances[type].objs);
free(topology->os_distances[type].distances);
topology->os_distances[type].nbobjs = nbobjs;
topology->os_distances[type].indexes = indexes;
topology->os_distances[type].objs = objs;
topology->os_distances[type].distances = distances;
}
/* make sure a user-given distance matrix is sane */
static int hwloc_topology__check_distance_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<nbobjs; i++)
for(j=i+1; j<nbobjs; j++)
if (indexes[i] == indexes[j]) {
errno = EINVAL;
return -1;
}
return 0;
}
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;
}
static void hwloc_get_type_distances_from_string(struct hwloc_topology *topology,
hwloc_obj_type_t type, char *string)
{
/* the string format is: "index[0],...,index[N-1]:distance[0],...,distance[N*N-1]"
* or "index[0],...,index[N-1]:X*Y" or "index[0],...,index[N-1]:X*Y*Z"
*/
char *tmp = string, *next;
unsigned *indexes;
float *distances;
unsigned nbobjs = 0, i, j, x, y, z;
/* count indexes */
while (1) {
size_t size = strspn(tmp, "0123456789");
if (tmp[size] != ',') {
/* last element */
tmp += size;
nbobjs++;
break;
}
/* another index */
tmp += size+1;
nbobjs++;
}
if (*tmp != ':') {
fprintf(stderr, "Ignoring %s distances from environment variable, missing colon\n",
hwloc_obj_type_string(type));
return;
}
indexes = calloc(nbobjs, sizeof(unsigned));
distances = calloc(nbobjs*nbobjs, sizeof(float));
tmp = string;
/* parse indexes */
for(i=0; i<nbobjs; i++) {
indexes[i] = strtoul(tmp, &next, 0);
tmp = next+1;
}
/* parse distances */
z=1; /* default if sscanf finds only 2 values below */
if (sscanf(tmp, "%u*%u*%u", &x, &y, &z) >= 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; i<nbobjs; i++)
for(j=0; j<nbobjs; j++)
if (i==j)
distances[i*nbobjs+j] = 1;
else if (i/z == j/z)
distances[i*nbobjs+j] = 2;
else if (i/z/y == j/z/y)
distances[i*nbobjs+j] = 4;
else
distances[i*nbobjs+j] = 8;
} else {
/* parse a comma separated list of distances */
for(i=0; i<nbobjs*nbobjs; i++) {
distances[i] = strtof(tmp, &next);
tmp = next+1;
if (!*next && i!=nbobjs*nbobjs-1) {
fprintf(stderr, "Ignoring %s distances from environment variable, not enough values (%u out of %u)\n",
hwloc_obj_type_string(type), i+1, nbobjs*nbobjs);
free(indexes);
free(distances);
return;
}
}
}
if (hwloc_topology__check_distance_matrix(topology, type, nbobjs, indexes, NULL, distances) < 0) {
fprintf(stderr, "Ignoring invalid %s distances from environment variable\n", hwloc_obj_type_string(type));
free(indexes);
free(distances);
return;
}
hwloc_topology__set_distance_matrix(topology, type, nbobjs, indexes, NULL, distances);
}
/* take distances in the environment, store them as is in the topology.
* we'll convert them into object later once the tree is filled
*/
void hwloc_store_distances_from_env(struct hwloc_topology *topology)
{
hwloc_obj_type_t type;
for(type = HWLOC_OBJ_SYSTEM; type < HWLOC_OBJ_TYPE_MAX; type++) {
char *env, envname[64];
snprintf(envname, sizeof(envname), "HWLOC_%s_DISTANCES", hwloc_obj_type_string(type));
env = getenv(envname);
if (env)
hwloc_get_type_distances_from_string(topology, type, env);
}
}
/* take the given distance, store them as is in the topology.
* we'll convert them into object later once the tree is filled.
*/
int hwloc_topology_set_distance_matrix(hwloc_topology_t __hwloc_restrict topology, hwloc_obj_type_t type,
unsigned nbobjs, unsigned *indexes, float *distances)
{
unsigned *_indexes;
float *_distances;
if (hwloc_topology__check_distance_matrix(topology, type, nbobjs, indexes, NULL, distances) < 0)
return -1;
/* copy the input arrays and give them to the topology */
_indexes = malloc(nbobjs*sizeof(unsigned));
memcpy(_indexes, indexes, nbobjs*sizeof(unsigned));
_distances = malloc(nbobjs*nbobjs*sizeof(float));
memcpy(_distances, distances, nbobjs*nbobjs*sizeof(float));
hwloc_topology__set_distance_matrix(topology, type, nbobjs, _indexes, NULL, _distances);
return 0;
}
/* cleanup everything we created from distances so that we may rebuild them
* at the end of restrict()
*/
void hwloc_restrict_distances(struct hwloc_topology *topology, unsigned long flags)
{
hwloc_obj_type_t type;
for(type = HWLOC_OBJ_SYSTEM; type < HWLOC_OBJ_TYPE_MAX; type++) {
/* remove the objs array, we'll rebuild it from the indexes
* depending on remaining objects */
free(topology->os_distances[type].objs);
topology->os_distances[type].objs = NULL;
/* if not adapting distances, drop everything */
if (!(flags & HWLOC_RESTRICT_FLAG_ADAPT_DISTANCES)) {
free(topology->os_distances[type].indexes);
topology->os_distances[type].indexes = NULL;
free(topology->os_distances[type].distances);
topology->os_distances[type].distances = NULL;
topology->os_distances[type].nbobjs = 0;
}
}
}
/* 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.
* it's not done when distances come from the user.
*/
void hwloc_convert_distances_indexes_into_objects(struct hwloc_topology *topology)
{
hwloc_obj_type_t type;
for(type = HWLOC_OBJ_SYSTEM; type < HWLOC_OBJ_TYPE_MAX; type++) {
unsigned nbobjs = topology->os_distances[type].nbobjs;
unsigned *indexes = topology->os_distances[type].indexes;
float *distances = topology->os_distances[type].distances;
unsigned i, j;
if (!topology->os_distances[type].objs) {
hwloc_obj_t *objs = calloc(nbobjs, sizeof(hwloc_obj_t));
/* traverse the topology and look for the relevant objects */
for(i=0; i<nbobjs; i++) {
hwloc_obj_t obj = hwloc_find_obj_by_type_and_os_index(topology->levels[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; j<i-1; j++)
/** move end of jth line + beginning of (j+1)th line */
memmove(NEWPOS(j,i), OLDPOS(j,i+1), (nbobjs-1)*sizeof(*distances));
/** move end of (i-1)th line */
memmove(NEWPOS(i-1,i), OLDPOS(i-1,i+1), (nbobjs-i-1)*sizeof(*distances));
}
if (i<nbobjs-1) {
/** move beginning of (i+1)th line */
memmove(NEWPOS(i,0), OLDPOS(i+1,0), i*sizeof(*distances));
/** move end of jth line + beginning of (j+1)th line */
for(j=i; j<nbobjs-1; j++)
memmove(NEWPOS(j,i), OLDPOS(j+1,i+1), (nbobjs-1)*sizeof(*distances));
/** move end of (nbobjs-2)th line */
memmove(NEWPOS(nbobjs-2,i), OLDPOS(nbobjs-1,i+1), (nbobjs-i-1)*sizeof(*distances));
}
/* shift the indexes array */
memmove(indexes+i, indexes+i+1, (nbobjs-i-1)*sizeof(*indexes));
/* update counters */
nbobjs--;
i--;
continue;
}
objs[i] = obj;
}
topology->os_distances[type].nbobjs = nbobjs;
if (!nbobjs) {
/* the whole matrix was invalid */
free(objs);
free(topology->os_distances[type].indexes);
topology->os_distances[type].indexes = NULL;
free(topology->os_distances[type].distances);
topology->os_distances[type].distances = NULL;
} else {
/* setup the objs array */
topology->os_distances[type].objs = objs;
}
}
}
}
static void
hwloc_setup_distances_from_os_matrix(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 set;
unsigned relative_depth;
int idx;
/* find the root */
set = hwloc_bitmap_alloc();
for(i=0; i<nbobjs; i++)
hwloc_bitmap_or(set, set, objs[i]->cpuset);
root = hwloc_get_obj_covering_cpuset(topology, set);
assert(root);
if (!hwloc_bitmap_isequal(set, root->cpuset)) {
/* partial distance matrix not including all the children of a single object */
/* TODO insert an intermediate object (group?) covering only these children ? */
hwloc_bitmap_free(set);
return;
}
hwloc_bitmap_free(set);
relative_depth = objs[0]->depth - root->depth; /* this assume that we have distances between objects of the same level */
/* get the logical index offset, it's the min of all logical indexes */
minl = UINT_MAX;
for(i=0; i<nbobjs; i++)
if (minl > objs[i]->logical_index)
minl = objs[i]->logical_index;
/* compute/check min/max values */
for(i=0; i<nbobjs; i++)
for(j=0; j<nbobjs; j++) {
float val = osmatrix[i*nbobjs+j];
if (val < min)
min = val;
if (val > 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; i<nbobjs; i++) {
li = objs[i]->logical_index - minl;
matrix[li*nbobjs+li] = NORMALIZE_LATENCY(osmatrix[i*nbobjs+i]);
for(j=i+1; j<nbobjs; j++) {
lj = objs[j]->logical_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_finalize_logical_distances(struct hwloc_topology *topology)
{
unsigned nbobjs;
hwloc_obj_type_t type;
int depth;
for (type = HWLOC_OBJ_SYSTEM; type < HWLOC_OBJ_TYPE_MAX; type++) {
nbobjs = topology->os_distances[type].nbobjs;
if (!nbobjs)
continue;
depth = hwloc_get_type_depth(topology, type);
if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
continue;
if (topology->os_distances[type].objs) {
assert(topology->os_distances[type].distances);
hwloc_setup_distances_from_os_matrix(topology, nbobjs,
topology->os_distances[type].objs,
topology->os_distances[type].distances);
}
}
}
/* destroy a object distances structure */
void
hwloc_free_logical_distances(struct hwloc_distances_s * dist)
{
free(dist->latency);
free(dist);
}
static void hwloc_report_user_distance_error(const char *msg, int line)
{
static int reported = 0;
if (!reported) {
fprintf(stderr, "****************************************************************************\n");
fprintf(stderr, "* Hwloc has encountered what looks like an error from user-given distances.\n");
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;
}
}
/*
* 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_setup_group_from_min_distance(unsigned nbobjs,
float *_distances,
unsigned *groupids)
{
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; i<nbobjs; i++)
for(j=i+1; j<nbobjs; j++)
if (DISTANCE(i, j) < min_distance)
min_distance = DISTANCE(i, j);
hwloc_debug("found minimal distance %f between objects\n", min_distance);
if (min_distance == FLT_MAX)
return 0;
/* build groups of objects connected with this distance */
for(i=0; i<nbobjs; i++) {
unsigned size;
int firstfound;
/* if already grouped, skip */
if (groupids[i])
continue;
/* start a new group */
groupids[i] = groupid;
size = 1;
firstfound = i;
while (firstfound != -1) {
/* we added new objects to the group, the first one was firstfound.
* rescan all connections from these new objects (starting at first found) to any other objects,
* so as to find new objects minimally-connected by transivity.
*/
int newfirstfound = -1;
for(j=firstfound; j<nbobjs; j++)
if (groupids[j] == groupid)
for(k=0; k<nbobjs; k++)
if (!groupids[k] && DISTANCE(j, k) == min_distance) {
groupids[k] = groupid;
size++;
if (newfirstfound == -1)
newfirstfound = k;
if (i == j)
hwloc_debug("object %u is minimally connected to %u\n", k, i);
else
hwloc_debug("object %u is minimally connected to %u through %u\n", k, i, j);
}
firstfound = newfirstfound;
}
if (size == 1) {
/* cancel this useless group, ignore this object and try from the next one */
groupids[i] = 0;
skipped++;
continue;
}
/* valid this group */
groupid++;
hwloc_debug("found transitive graph with %u objects with minimal distance %f\n",
size, min_distance);
}
if (groupid == 2 && !skipped)
/* we created a single group containing all objects, ignore it */
return 0;
/* return the last id, since it's also the number of used group ids */
return groupid-1;
}
/*
* Look at object physical distances to group them,
* after having done some basic sanity checks.
*/
static void
hwloc__setup_groups_from_distances(struct hwloc_topology *topology,
unsigned nbobjs,
struct hwloc_obj **objs,
float *_distances,
int fromuser)
{
unsigned *groupids = NULL;
unsigned nbgroups;
unsigned i,j;
hwloc_debug("trying to group %s objects into Group objects according to physical distances\n",
hwloc_obj_type_string(objs[0]->type));
if (nbobjs <= 2) {
return;
}
groupids = malloc(sizeof(unsigned) * nbobjs);
if (NULL == groupids) {
return;
}
nbgroups = hwloc_setup_group_from_min_distance(nbobjs, _distances, groupids);
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;
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; i<nbgroups; i++) {
/* create the Group object */
hwloc_obj_t group_obj;
group_obj = hwloc_alloc_setup_object(HWLOC_OBJ_GROUP, -1);
group_obj->cpuset = hwloc_bitmap_alloc();
group_obj->attr->group.depth = topology->next_group_depth;
for (j=0; j<nbobjs; j++)
if (groupids[j] == i+1) {
hwloc_bitmap_or(group_obj->cpuset, group_obj->cpuset, objs[j]->cpuset);
groupsizes[i]++;
}
hwloc_debug_1arg_bitmap("adding Group object with %u objects and cpuset %s\n",
groupsizes[i], group_obj->cpuset);
hwloc__insert_object_by_cpuset(topology, group_obj,
fromuser ? hwloc_report_user_distance_error : hwloc_report_os_error);
groupobjs[i] = group_obj;
}
/* 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; i<nbobjs; i++)
if (groupids[i])
for(j=0; j<nbobjs; j++)
if (groupids[j])
GROUP_DISTANCE(groupids[i]-1, groupids[j]-1) += DISTANCE(i, j);
for(i=0; i<nbgroups; i++)
for(j=0; j<nbgroups; j++)
GROUP_DISTANCE(i, j) /= groupsizes[i]*groupsizes[j];
#ifdef HWLOC_DEBUG
hwloc_debug("%s", "generated new distance matrix between groups:\n");
hwloc_debug("%s", " index");
for(j=0; j<nbgroups; j++)
hwloc_debug(" % 5d", (int) j); /* print index because os_index is -1 fro Groups */
hwloc_debug("%s", "\n");
for(i=0; i<nbgroups; i++) {
hwloc_debug(" % 5d", (int) i);
for(j=0; j<nbgroups; j++)
hwloc_debug(" %2.3f", GROUP_DISTANCE(i, j));
hwloc_debug("%s", "\n");
}
#endif
topology->next_group_depth++;
hwloc__setup_groups_from_distances(topology, nbgroups, groupobjs, (float*) groupdistances, fromuser);
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);
}
}
/*
* Look at object physical distances to group them.
*/
static void
hwloc_setup_groups_from_distances(struct hwloc_topology *topology,
unsigned nbobjs,
struct hwloc_obj **objs,
float *_distances,
int fromuser)
{
unsigned i,j;
if (getenv("HWLOC_IGNORE_DISTANCES"))
return;
#ifdef HWLOC_DEBUG
hwloc_debug("%s", "trying to group objects using distance matrix:\n");
hwloc_debug("%s", " index");
for(j=0; j<nbobjs; j++)
hwloc_debug(" % 5d", (int) objs[j]->os_index);
hwloc_debug("%s", "\n");
for(i=0; i<nbobjs; i++) {
hwloc_debug(" % 5d", (int) objs[i]->os_index);
for(j=0; j<nbobjs; j++)
hwloc_debug(" %2.3f", DISTANCE(i, j));
hwloc_debug("%s", "\n");
}
#endif
/* check that the matrix is ok */
for(i=0; i<nbobjs; i++) {
for(j=i+1; j<nbobjs; j++) {
/* should be symmetric */
if (DISTANCE(i, j) != DISTANCE(j, i)) {
hwloc_debug("distance matrix asymmetric ([%u,%u]=%f != [%u,%u]=%f), aborting\n",
i, j, DISTANCE(i, j), j, i, DISTANCE(j, i));
return;
}
/* diagonal is smaller than everything else */
if (DISTANCE(i, j) <= DISTANCE(i, i)) {
hwloc_debug("distance to self not strictly minimal ([%u,%u]=%f <= [%u,%u]=%f), aborting\n",
i, j, DISTANCE(i, j), i, i, DISTANCE(i, i));
return;
}
}
}
hwloc__setup_groups_from_distances(topology, nbobjs, objs, _distances, fromuser);
}
void
hwloc_group_by_distances(struct hwloc_topology *topology)
{
unsigned nbobjs;
hwloc_obj_type_t type;
for (type = HWLOC_OBJ_SYSTEM; type < HWLOC_OBJ_TYPE_MAX; type++) {
nbobjs = topology->os_distances[type].nbobjs;
if (!nbobjs)
continue;
if (topology->os_distances[type].objs) {
/* if we have objs, we must have distances as well,
* thanks to hwloc_convert_distances_indexes_into_objects()
*/
assert(topology->os_distances[type].distances);
hwloc_setup_groups_from_distances(topology, nbobjs,
topology->os_distances[type].objs,
topology->os_distances[type].distances,
topology->os_distances[type].indexes != NULL);
}
}
}

Просмотреть файл

@ -1,6 +1,6 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009 INRIA
* Copyright © 2009 INRIA. All rights reserved.
* Copyright © 2009 Université Bordeaux 1
* See COPYING in top-level directory.
*/

Просмотреть файл

@ -1,7 +1,7 @@
<!ELEMENT topology (object)+>
<!ELEMENT root (object)+>
<!ELEMENT object (page_type*,info*,object*)>
<!ELEMENT object (page_type*,info*,distances*,object*)>
<!ATTLIST object type (System | Machine | Misc | Group | NUMANode | Socket| Cache | Core | PU) #REQUIRED>
<!ATTLIST object os_level CDATA "-1" >
<!ATTLIST object os_index CDATA "-1" >
@ -27,3 +27,11 @@
<!ELEMENT info EMPTY>
<!ATTLIST info name CDATA #REQUIRED>
<!ATTLIST info value CDATA #REQUIRED>
<!ELEMENT distances (latency*)>
<!ATTLIST distances nbobjs CDATA #REQUIRED>
<!ATTLIST distances relative_depth CDATA #REQUIRED>
<!ATTLIST distances latency_base CDATA #REQUIRED>
<!ELEMENT latency EMPTY>
<!ATTLIST latency value CDATA #REQUIRED>

Просмотреть файл

@ -1,6 +1,6 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2010 INRIA
* Copyright © 2009-2010 INRIA. All rights reserved.
* Copyright © 2009-2010 Université Bordeaux 1
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.

Просмотреть файл

@ -1,7 +1,7 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2010 INRIA
* Copyright © 2009-2010 Université Bordeaux 1
* Copyright © 2009-2010 INRIA. All rights reserved.
* Copyright © 2009-2011 Université Bordeaux 1
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
*/
@ -27,6 +27,7 @@
#include <sys/processor.h>
#include <sys/thread.h>
#include <sys/mman.h>
#include <sys/systemcfg.h>
static int
hwloc_aix_set_sth_cpubind(hwloc_topology_t topology, rstype_t what, rsid_t who, hwloc_const_bitmap_t hwloc_set, int flags __hwloc_attribute_unused)
@ -87,42 +88,48 @@ out:
static int
hwloc_aix_set_thisproc_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags)
{
rsid_t who = { .at_pid = getpid() };
rsid_t who;
who.at_pid = getpid();
return hwloc_aix_set_sth_cpubind(topology, R_PROCESS, who, hwloc_set, flags);
}
static int
hwloc_aix_get_thisproc_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_set, int flags)
{
rsid_t who = { .at_pid = getpid() };
rsid_t who;
who.at_pid = getpid();
return hwloc_aix_get_sth_cpubind(topology, R_PROCESS, who, hwloc_set, flags);
}
static int
hwloc_aix_set_thisthread_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags)
{
rsid_t who = { .at_tid = thread_self() };
rsid_t who;
who.at_tid = thread_self();
return hwloc_aix_set_sth_cpubind(topology, R_THREAD, who, hwloc_set, flags);
}
static int
hwloc_aix_get_thisthread_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_set, int flags)
{
rsid_t who = { .at_tid = thread_self() };
rsid_t who;
who.at_tid = thread_self();
return hwloc_aix_get_sth_cpubind(topology, R_THREAD, who, hwloc_set, flags);
}
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 = { .at_pid = pid };
rsid_t who;
who.at_pid = pid;
return hwloc_aix_set_sth_cpubind(topology, R_PROCESS, who, 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)
{
rsid_t who = { .at_pid = pid };
rsid_t who;
who.at_pid = pid;
return hwloc_aix_get_sth_cpubind(topology, R_PROCESS, who, hwloc_set, flags);
}
@ -148,7 +155,8 @@ hwloc_aix_get_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t pthread,
if (pthread_getthrds_np(&pthread, PTHRDSINFO_QUERY_TID, &info, sizeof(info), NULL, &size))
return -1;
{
rsid_t who = { .at_tid = info.__pi_tid };
rsid_t who;
who.at_tid = info.__pi_tid;
return hwloc_aix_get_sth_cpubind(topology, R_THREAD, who, hwloc_set, flags);
}
}
@ -278,42 +286,48 @@ out:
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 = { .at_pid = getpid() };
rsid_t who;
who.at_pid = getpid();
return hwloc_aix_set_sth_membind(topology, R_PROCESS, who, 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 = { .at_pid = getpid() };
rsid_t who;
who.at_pid = getpid();
return hwloc_aix_get_sth_membind(topology, R_PROCESS, who, hwloc_set, policy, flags);
}
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 = { .at_tid = thread_self() };
rsid_t who;
who.at_tid = thread_self();
return hwloc_aix_set_sth_membind(topology, R_THREAD, who, 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 = { .at_tid = thread_self() };
rsid_t who;
who.at_tid = thread_self();
return hwloc_aix_get_sth_membind(topology, R_THREAD, who, hwloc_set, policy, flags);
}
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 = { .at_pid = pid };
rsid_t who;
who.at_pid = pid;
return hwloc_aix_set_sth_membind(topology, R_PROCESS, who, 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 = { .at_pid = pid };
rsid_t who;
who.at_pid = pid;
return hwloc_aix_get_sth_membind(topology, R_PROCESS, who, hwloc_set, policy, flags);
}
@ -326,7 +340,8 @@ hwloc_aix_set_thread_membind(hwloc_topology_t topology, hwloc_thread_t pthread,
if ((errno = pthread_getthrds_np(&pthread, PTHRDSINFO_QUERY_TID, &info, sizeof(info), NULL, &size)))
return -1;
{
rsid_t who = { .at_tid = info.__pi_tid };
rsid_t who;
who.at_tid = info.__pi_tid;
return hwloc_aix_set_sth_membind(topology, R_THREAD, who, hwloc_set, policy, flags);
}
}
@ -339,7 +354,8 @@ hwloc_aix_get_thread_membind(hwloc_topology_t topology, hwloc_thread_t pthread,
if (pthread_getthrds_np(&pthread, PTHRDSINFO_QUERY_TID, &info, sizeof(info), NULL, &size))
return -1;
{
rsid_t who = { .at_tid = info.__pi_tid };
rsid_t who;
who.at_tid = info.__pi_tid;
return hwloc_aix_get_sth_membind(topology, R_THREAD, who, hwloc_set, policy, flags);
}
}
@ -433,6 +449,11 @@ look_rset(int sdl, hwloc_obj_type_t type, struct hwloc_topology *topology, int l
obj = hwloc_alloc_setup_object(type, i - (type == HWLOC_OBJ_PU));
obj->cpuset = hwloc_bitmap_alloc();
obj->os_level = sdl;
maxcpus = rs_getinfo(rad, R_MAXPROCS, 0);
for (j = 0; j < maxcpus; j++) {
if (rs_op(RS_TESTRESOURCE, rad, NULL, R_PROCS, j))
hwloc_bitmap_set(obj->cpuset, j);
}
switch(type) {
case HWLOC_OBJ_NODE:
obj->nodeset = hwloc_bitmap_alloc();
@ -448,19 +469,25 @@ look_rset(int sdl, hwloc_obj_type_t type, struct hwloc_topology *topology, int l
/* TODO: obj->memory.page_types[1].count = rs_getinfo(rset, R_LGPGFREE, 0) / hugepagesize */
break;
case HWLOC_OBJ_CACHE:
obj->attr->cache.size = 0; /* TODO: ? */
obj->attr->cache.size = _system_configuration.L2_cache_size;
obj->attr->cache.linesize = 0; /* TODO: ? */
obj->attr->cache.depth = 2;
break;
case HWLOC_OBJ_GROUP:
obj->attr->group.depth = level;
default:
case HWLOC_OBJ_CORE:
{
hwloc_obj_t 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.linesize = _system_configuration.dcache_line;
obj2->attr->cache.depth = 1;
hwloc_debug("Adding an L1 cache for core %d\n", i);
hwloc_insert_object_by_cpuset(topology, obj2);
break;
}
maxcpus = rs_getinfo(rad, R_MAXPROCS, 0);
for (j = 0; j < maxcpus; j++) {
if (rs_op(RS_TESTRESOURCE, rad, NULL, R_PROCS, j))
hwloc_bitmap_set(obj->cpuset, j);
default:
break;
}
hwloc_debug_2args_bitmap("%s %d has cpuset %s\n",
hwloc_obj_type_string(type),
@ -547,6 +574,7 @@ hwloc_set_aix_hooks(struct hwloc_topology *topology)
topology->get_thisproc_cpubind = hwloc_aix_get_thisproc_cpubind;
topology->set_thisthread_cpubind = hwloc_aix_set_thisthread_cpubind;
topology->get_thisthread_cpubind = hwloc_aix_get_thisthread_cpubind;
/* TODO: get_last_cpu_location: use mycpu() */
#ifdef P_DEFAULT
topology->set_proc_membind = hwloc_aix_set_proc_membind;
topology->get_proc_membind = hwloc_aix_get_proc_membind;
@ -559,7 +587,7 @@ hwloc_set_aix_hooks(struct hwloc_topology *topology)
topology->get_thisproc_membind = hwloc_aix_get_thisproc_membind;
topology->set_thisthread_membind = hwloc_aix_set_thisthread_membind;
topology->get_thisthread_membind = hwloc_aix_get_thisthread_membind;
//topology->set_area_membind = hwloc_aix_set_area_membind;
/* topology->set_area_membind = hwloc_aix_set_area_membind; */
/* get_area_membind is not available */
topology->alloc_membind = hwloc_aix_alloc_membind;
topology->alloc = hwloc_alloc_mmap;

Просмотреть файл

@ -1,6 +1,6 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2010 INRIA
* Copyright © 2009-2010 INRIA. All rights reserved.
* Copyright © 2009-2010 Université Bordeaux 1
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
@ -106,9 +106,22 @@ hwloc_look_darwin(struct hwloc_topology *topology)
if (!sysctlbyname("hw.cacheconfig", NULL, &size, NULL, 0)) {
unsigned n = size / sizeof(uint32_t);
uint64_t cacheconfig[n];
uint32_t cacheconfig32[n];
uint64_t cachesize[n];
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
@ -178,7 +191,18 @@ hwloc_look_darwin(struct hwloc_topology *topology)
}
}
}
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);

Просмотреть файл

@ -1,6 +1,6 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2010 INRIA
* Copyright © 2009-2010 INRIA. All rights reserved.
* Copyright © 2009-2010 Université Bordeaux 1
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
@ -197,4 +197,5 @@ hwloc_set_freebsd_hooks(struct hwloc_topology *topology)
#endif
#endif
#endif
/* TODO: get_last_cpu_location: find out ki_lastcpu */
}

Просмотреть файл

@ -1,6 +1,6 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2010 INRIA
* Copyright © 2009-2010 INRIA. All rights reserved.
* Copyright © 2009-2010 Université Bordeaux 1
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.

Просмотреть файл

@ -1,7 +1,7 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2010 INRIA
* Copyright © 2009-2010 Université Bordeaux 1
* Copyright © 2009-2011 INRIA. All rights reserved.
* Copyright © 2009-2011 Université Bordeaux 1
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
* Copyright © 2010 IBM
* See COPYING in top-level directory.
@ -199,7 +199,7 @@ hwloc_opendirat(const char *path, int fsroot_fd)
/* Static inline version of fopen so that we can use openat if we have
it, but still preserve compiler parameter checking */
static inline int
static __hwloc_inline int
hwloc_open(const char *p, int d __hwloc_attribute_unused)
{
#ifdef HAVE_OPENAT
@ -209,7 +209,7 @@ hwloc_open(const char *p, int d __hwloc_attribute_unused)
#endif
}
static inline FILE *
static __hwloc_inline FILE *
hwloc_fopen(const char *p, const char *m, int d __hwloc_attribute_unused)
{
#ifdef HAVE_OPENAT
@ -221,7 +221,7 @@ hwloc_fopen(const char *p, const char *m, int d __hwloc_attribute_unused)
/* Static inline version of access so that we can use openat if we have
it, but still preserve compiler parameter checking */
static inline int
static __hwloc_inline int
hwloc_access(const char *p, int m, int d __hwloc_attribute_unused)
{
#ifdef HAVE_OPENAT
@ -231,7 +231,7 @@ hwloc_access(const char *p, int m, int d __hwloc_attribute_unused)
#endif
}
static inline int
static __hwloc_inline int
hwloc_stat(const char *p, struct stat *st, int d __hwloc_attribute_unused)
{
#ifdef HAVE_OPENAT
@ -243,7 +243,7 @@ hwloc_stat(const char *p, struct stat *st, int d __hwloc_attribute_unused)
/* Static inline version of opendir so that we can use openat if we have
it, but still preserve compiler parameter checking */
static inline DIR *
static __hwloc_inline DIR *
hwloc_opendir(const char *p, int d __hwloc_attribute_unused)
{
#ifdef HAVE_OPENAT
@ -573,8 +573,11 @@ static int
hwloc_linux_get_pid_cpubind(hwloc_topology_t topology, pid_t pid, hwloc_bitmap_t hwloc_set, int flags)
{
hwloc_bitmap_t tidset = hwloc_bitmap_alloc();
hwloc_bitmap_t cpusets[2] = { hwloc_set, tidset };
hwloc_bitmap_t cpusets[2];
int ret;
cpusets[0] = hwloc_set;
cpusets[1] = tidset;
ret = hwloc_linux_foreach_proc_tid(topology, pid,
hwloc_linux_foreach_proc_tid_get_cpubind_cb,
(void*) cpusets, flags);
@ -828,6 +831,119 @@ hwloc_linux_get_thread_cpubind(hwloc_topology_t topology, pthread_t tid, hwloc_b
}
#endif /* HAVE_DECL_PTHREAD_GETAFFINITY_NP */
static int
hwloc_linux_get_tid_last_cpu_location(hwloc_topology_t topology __hwloc_attribute_unused, pid_t tid, hwloc_bitmap_t set)
{
/* read /proc/pid/stat.
* its second field contains the command name between parentheses,
* and the command itself may contain parentheses,
* so read the whole line and find the last closing parenthesis to find the third field.
*/
char buf[1024] = "";
char name[64];
char *tmp;
FILE *file;
int i;
if (!tid)
strcpy(name, "/proc/self/stat");
else
snprintf(name, sizeof(name), "/proc/%lu/stat", (unsigned long) tid);
file = fopen(name, "r");
if (!file) {
errno = ENOSYS;
return -1;
}
fgets(buf, sizeof(buf), file);
fclose(file);
tmp = strrchr(buf, ')');
if (!tmp) {
errno = ENOSYS;
return -1;
}
/* skip ') ' to find the actual third argument */
tmp += 2;
/* skip 35 fields */
for(i=0; i<36; i++) {
tmp = strchr(tmp, ' ');
if (!tmp) {
errno = ENOSYS;
return -1;
}
/* skip the ' ' itself */
tmp++;
}
/* read the last cpu in the 38th field now */
if (sscanf(tmp, "%d ", &i) != 1) {
errno = ENOSYS;
return -1;
}
hwloc_bitmap_only(set, i);
return 0;
}
static int
hwloc_linux_foreach_proc_tid_get_last_cpu_location_cb(hwloc_topology_t topology, pid_t tid, void *data, int idx, int flags __hwloc_attribute_unused)
{
hwloc_bitmap_t *cpusets = data;
hwloc_bitmap_t cpuset = cpusets[0];
hwloc_bitmap_t tidset = cpusets[1];
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_bitmap_t tidset = hwloc_bitmap_alloc();
hwloc_bitmap_t cpusets[2];
int ret;
cpusets[0] = hwloc_set;
cpusets[1] = tidset;
ret = hwloc_linux_foreach_proc_tid(topology, pid,
hwloc_linux_foreach_proc_tid_get_last_cpu_location_cb,
(void*) cpusets, flags);
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)
{
return hwloc_linux_get_tid_last_cpu_location(topology, topology->pid, hwloc_set);
}
#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)
@ -873,8 +989,9 @@ hwloc_linux_membind_mask_from_nodeset(hwloc_topology_t topology __hwloc_attribut
max_os_index = hwloc_bitmap_last(nodeset);
if (max_os_index == (unsigned) -1)
max_os_index = 0;
/* 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);
/* 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) {
@ -1764,7 +1881,7 @@ hwloc_sysfs_node_meminfo_info(struct hwloc_topology *topology,
}
static void
hwloc_parse_node_distance(const char *distancepath, unsigned nbnodes, unsigned *distances, int fsroot_fd)
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;
@ -1784,7 +1901,7 @@ hwloc_parse_node_distance(const char *distancepath, unsigned nbnodes, unsigned *
unsigned distance = strtoul(tmp, &next, 0);
if (next == tmp)
break;
*distances = distance;
*distances = (float) distance;
distances++;
nbnodes--;
if (!nbnodes)
@ -1828,21 +1945,27 @@ look_sysfsnode(struct hwloc_topology *topology, const char *path, unsigned *foun
return;
}
/* For convenience, put these declarations inside a block. Saves us
from a bunch of mallocs, particularly with the 2D array. */
/* For convenience, put these declarations inside a block. */
{
hwloc_obj_t nodes[nbnodes];
unsigned distances[nbnodes][nbnodes];
unsigned distance_indexes[nbnodes];
hwloc_obj_t * nodes = calloc(nbnodes, sizeof(hwloc_obj_t));
float * distances = calloc(nbnodes*nbnodes, sizeof(float));
unsigned *indexes = calloc(nbnodes, sizeof(unsigned));
unsigned index_;
if (NULL == indexes || NULL == distances || NULL == nodes) {
free(nodes);
free(indexes);
free(distances);
goto out;
}
/* Get node indexes now. We need them in order since Linux groups
* sparse distances but keep them in order in the sysfs distance files.
*/
index_ = 0;
hwloc_bitmap_foreach_begin (osnode, nodeset) {
distance_indexes[index_] = osnode;
indexes[index_] = osnode;
index_++;
} hwloc_bitmap_foreach_end();
hwloc_bitmap_free(nodeset);
@ -1850,7 +1973,7 @@ look_sysfsnode(struct hwloc_topology *topology, const char *path, unsigned *foun
#ifdef HWLOC_DEBUG
hwloc_debug("%s", "numa distance indexes: ");
for (index_ = 0; index_ < nbnodes; index_++) {
hwloc_debug(" %u", distance_indexes[index_]);
hwloc_debug(" %u", indexes[index_]);
}
hwloc_debug("%s", "\n");
#endif
@ -1859,7 +1982,7 @@ look_sysfsnode(struct hwloc_topology *topology, const char *path, unsigned *foun
for (index_ = 0; index_ < nbnodes; index_++) {
char nodepath[SYSFS_NUMA_NODE_PATH_LEN];
hwloc_bitmap_t cpuset;
osnode = distance_indexes[index_];
osnode = indexes[index_];
sprintf(nodepath, "%s/node%u/cpumap", path, osnode);
cpuset = hwloc_parse_cpumap(nodepath, topology->backend_params.sysfs.root_fd);
@ -1878,13 +2001,16 @@ look_sysfsnode(struct hwloc_topology *topology, const char *path, unsigned *foun
hwloc_insert_object_by_cpuset(topology, node);
nodes[index_] = node;
/* 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_], topology->backend_params.sysfs.root_fd);
hwloc_parse_node_distance(nodepath, nbnodes, distances+index_*nbnodes, topology->backend_params.sysfs.root_fd);
}
hwloc_setup_misc_level_from_distances(topology, nbnodes, nodes, (unsigned *) distances, (unsigned *) distance_indexes);
hwloc_topology__set_distance_matrix(topology, HWLOC_OBJ_NODE, nbnodes, indexes, nodes, distances);
}
out:
*found = nbnodes;
}
@ -1893,18 +2019,25 @@ look_sysfsnode(struct hwloc_topology *topology, const char *path, unsigned *foun
static void *
hwloc_read_raw(const char *p, const char *p1, size_t *bytes_read, int root_fd)
{
char fname[strlen(p) + 1 + strlen(p1) + 1];
char *fname = NULL;
char *ret = NULL;
struct stat fs;
int file = -1;
unsigned len;
snprintf(fname, sizeof(fname), "%s/%s", p, p1);
int file = hwloc_open(fname, root_fd);
if (-1 == file)
len = strlen(p) + 1 + strlen(p1) + 1;
fname = malloc(len);
if (NULL == fname) {
return NULL;
}
snprintf(fname, len, "%s/%s", p, p1);
file = hwloc_open(fname, root_fd);
if (-1 == file) {
goto out;
}
if (fstat(file, &fs)) {
close(file);
return NULL;
goto out;
}
ret = (char *) malloc(fs.st_size);
@ -1918,7 +2051,12 @@ hwloc_read_raw(const char *p, const char *p1, size_t *bytes_read, int root_fd)
*bytes_read = cb;
}
}
out:
close(file);
if (NULL != fname) {
free(fname);
}
return ret;
}
@ -1937,7 +2075,7 @@ hwloc_read_str(const char *p, const char *p1, int root_fd)
}
/* Reads first 32bit bigendian value */
static size_t
static ssize_t
hwloc_read_unit32be(const char *p, const char *p1, uint32_t *buf, int root_fd)
{
size_t cb = 0;
@ -1955,7 +2093,7 @@ typedef struct {
unsigned int n, allocated;
struct {
hwloc_bitmap_t cpuset;
uint32_t ibm_phandle;
uint32_t phandle;
uint32_t l2_cache;
char *name;
} *p;
@ -1963,7 +2101,7 @@ typedef struct {
static void
add_device_tree_cpus_node(device_tree_cpus_t *cpus, hwloc_bitmap_t cpuset,
uint32_t l2_cache, uint32_t ibm_phandle, const char *name)
uint32_t l2_cache, uint32_t phandle, const char *name)
{
if (cpus->n == cpus->allocated) {
if (!cpus->allocated)
@ -1972,7 +2110,7 @@ add_device_tree_cpus_node(device_tree_cpus_t *cpus, hwloc_bitmap_t cpuset,
cpus->allocated *= 2;
cpus->p = realloc(cpus->p, cpus->allocated * sizeof(cpus->p[0]));
}
cpus->p[cpus->n].ibm_phandle = ibm_phandle;
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);
@ -1982,14 +2120,14 @@ add_device_tree_cpus_node(device_tree_cpus_t *cpus, hwloc_bitmap_t cpuset,
/* 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 ibm_phandle, unsigned int *level, hwloc_bitmap_t cpuset)
uint32_t phandle, unsigned int *level, hwloc_bitmap_t cpuset)
{
unsigned int i;
int ret = -1;
if ((NULL == level) || (NULL == cpuset))
if ((NULL == level) || (NULL == cpuset) || phandle == (uint32_t) -1)
return ret;
for (i = 0; i < cpus->n; ++i) {
if (ibm_phandle != cpus->p[i].l2_cache)
if (phandle != cpus->p[i].l2_cache)
continue;
if (NULL != cpus->p[i].cpuset) {
hwloc_bitmap_or(cpuset, cpuset, cpus->p[i].cpuset);
@ -1997,7 +2135,7 @@ look_powerpc_device_tree_discover_cache(device_tree_cpus_t *cpus,
} else {
++(*level);
if (0 == look_powerpc_device_tree_discover_cache(cpus,
cpus->p[i].ibm_phandle, level, cpuset))
cpus->p[i].phandle, level, cpuset))
ret = 0;
}
}
@ -2017,6 +2155,7 @@ try_add_cache_from_device_tree_cpu(struct hwloc_topology *topology,
/* d-tlb-size - ignore, always 0 on power6 */
/* i-cache-* and i-tlb-* represent instruction cache, ignore */
uint32_t d_cache_line_size = 0, d_cache_size = 0;
struct hwloc_obj *c = NULL;
hwloc_read_unit32be(cpu, "d-cache-line-size", &d_cache_line_size,
topology->backend_params.sysfs.root_fd);
@ -2026,7 +2165,7 @@ try_add_cache_from_device_tree_cpu(struct hwloc_topology *topology,
if ( (0 == d_cache_line_size) && (0 == d_cache_size) )
return;
struct hwloc_obj *c = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -1);
c = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -1);
c->attr->cache.depth = level;
c->attr->cache.linesize = d_cache_line_size;
c->attr->cache.size = d_cache_size;
@ -2042,41 +2181,55 @@ try_add_cache_from_device_tree_cpu(struct hwloc_topology *topology,
static void
look_powerpc_device_tree(struct hwloc_topology *topology)
{
device_tree_cpus_t cpus = { .n = 0, .p = NULL, .allocated = 0 };
device_tree_cpus_t cpus;
const char ofroot[] = "/proc/device-tree/cpus";
unsigned int i;
int root_fd = topology->backend_params.sysfs.root_fd;
DIR *dt = hwloc_opendir(ofroot, root_fd);
struct dirent *dirent;
cpus.n = 0;
cpus.p = NULL;
cpus.allocated = 0;
if (NULL == dt)
return;
struct dirent *dirent;
while (NULL != (dirent = readdir(dt))) {
struct stat statbuf;
int err;
char *cpu;
char *device_type;
uint32_t reg = -1, l2_cache = -1, phandle = -1;
unsigned len;
if ('.' == dirent->d_name[0])
continue;
char cpu[sizeof(ofroot) + 1 + strlen(dirent->d_name) + 1];
snprintf(cpu, sizeof(cpu), "%s/%s", ofroot, dirent->d_name);
struct stat statbuf;
int err;
len = sizeof(ofroot) + 1 + strlen(dirent->d_name) + 1;
cpu = malloc(len);
if (NULL == cpu) {
continue;
}
snprintf(cpu, len, "%s/%s", ofroot, dirent->d_name);
err = hwloc_stat(cpu, &statbuf, root_fd);
if (err < 0 || !S_ISDIR(statbuf.st_mode))
continue;
goto cont;
char *device_type = hwloc_read_str(cpu, "device_type", root_fd);
device_type = hwloc_read_str(cpu, "device_type", root_fd);
if (NULL == device_type)
continue;
goto cont;
uint32_t reg = -1, l2_cache = -1, ibm_phandle = -1;
hwloc_read_unit32be(cpu, "reg", &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);
hwloc_read_unit32be(cpu, "ibm,phandle", &ibm_phandle, 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, ibm_phandle, dirent->d_name);
add_device_tree_cpus_node(&cpus, NULL, l2_cache, phandle, dirent->d_name);
}
else if (0 == strcmp(device_type, "cpu")) {
/* Found CPU */
@ -2101,10 +2254,11 @@ look_powerpc_device_tree(struct hwloc_topology *topology)
if (NULL == cpuset) {
hwloc_debug("%s has no \"reg\" property, skipping\n", cpu);
} else {
add_device_tree_cpus_node(&cpus, cpuset, l2_cache, ibm_phandle, dirent->d_name);
struct hwloc_obj *core = NULL;
add_device_tree_cpus_node(&cpus, cpuset, l2_cache, phandle, dirent->d_name);
/* Add core */
struct hwloc_obj *core = hwloc_alloc_setup_object(HWLOC_OBJ_CORE, reg);
core = hwloc_alloc_setup_object(HWLOC_OBJ_CORE, reg);
core->cpuset = hwloc_bitmap_dup(cpuset);
hwloc_insert_object_by_cpuset(topology, core);
@ -2115,6 +2269,8 @@ look_powerpc_device_tree(struct hwloc_topology *topology)
}
free(device_type);
}
cont:
free(cpu);
}
closedir(dt);
@ -2127,7 +2283,7 @@ look_powerpc_device_tree(struct hwloc_topology *topology)
#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].ibm_phandle, cpus.p[i].l2_cache);
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 {
@ -2138,20 +2294,28 @@ look_powerpc_device_tree(struct hwloc_topology *topology)
/* 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 */
unsigned int level = 2;
hwloc_bitmap_t cpuset = hwloc_bitmap_alloc();
cpuset = hwloc_bitmap_alloc();
if (0 == look_powerpc_device_tree_discover_cache(&cpus,
cpus.p[i].ibm_phandle, &level, cpuset)) {
cpus.p[i].phandle, &level, cpuset)) {
char *cpu;
unsigned len;
char cpu[sizeof(ofroot) + 1 + strlen(cpus.p[i].name) + 1];
snprintf(cpu, sizeof(cpu), "%s/%s", ofroot, cpus.p[i].name);
len = sizeof(ofroot) + 1 + strlen(cpus.p[i].name) + 1;
cpu = malloc(len);
if (NULL == cpu) {
return;
}
snprintf(cpu, len, "%s/%s", ofroot, cpus.p[i].name);
try_add_cache_from_device_tree_cpu(topology, cpu, level, cpuset);
free(cpu);
}
hwloc_bitmap_free(cpuset);
}
@ -2174,6 +2338,7 @@ look_sysfscpu(struct hwloc_topology *topology, const char *path)
DIR *dir;
int i,j;
FILE *fd;
unsigned caches_added;
cpuset = hwloc_bitmap_alloc();
@ -2226,7 +2391,7 @@ look_sysfscpu(struct hwloc_topology *topology, const char *path)
hwloc_debug_1arg_bitmap("found %d cpu topologies, cpuset %s\n",
hwloc_bitmap_weight(cpuset), cpuset);
unsigned caches_added = 0;
caches_added = 0;
hwloc_bitmap_foreach_begin(i, cpuset)
{
struct hwloc_obj *sock, *core, *thread;
@ -2385,8 +2550,9 @@ look_cpuinfo(struct hwloc_topology *topology, const char *path,
hwloc_bitmap_t online_cpuset)
{
FILE *fd;
char str[strlen(PHYSID)+1+9+1+1];
char *str = NULL;
char *endptr;
unsigned len;
unsigned proc_physids[HWLOC_NBMAXCPUS];
unsigned osphysids[HWLOC_NBMAXCPUS];
unsigned proc_coreids[HWLOC_NBMAXCPUS];
@ -2424,8 +2590,10 @@ look_cpuinfo(struct hwloc_topology *topology, const char *path,
cpuset = hwloc_bitmap_alloc();
/* Just record information and count number of sockets and cores */
len = strlen(PHYSID) + 1 + 9 + 1 + 1;
str = malloc(len);
hwloc_debug("%s", "\n\n * Topology extraction from /proc/cpuinfo *\n\n");
while (fgets(str,sizeof(str),fd)!=NULL)
while (fgets(str,len,fd)!=NULL)
{
# define getprocnb_begin(field, var) \
if ( !strncmp(field,str,strlen(field))) \
@ -2436,12 +2604,14 @@ look_cpuinfo(struct hwloc_topology *topology, const char *path,
{ \
hwloc_debug("%s", "no number in "field" field of /proc/cpuinfo\n"); \
hwloc_bitmap_free(cpuset); \
free(str); \
return -1; \
} \
else if (var==ULONG_MAX) \
{ \
hwloc_debug("%s", "too big "field" number in /proc/cpuinfo\n"); \
hwloc_bitmap_free(cpuset); \
free(str); \
return -1; \
} \
hwloc_debug(field " %lu\n", var)
@ -2491,6 +2661,7 @@ look_cpuinfo(struct hwloc_topology *topology, const char *path,
}
}
fclose(fd);
free(str);
if (processor == (unsigned long) -1) {
hwloc_bitmap_free(cpuset);
@ -2709,6 +2880,9 @@ hwloc_set_linux_hooks(struct hwloc_topology *topology)
#if HAVE_DECL_PTHREAD_GETAFFINITY_NP
topology->get_thread_cpubind = hwloc_linux_get_thread_cpubind;
#endif /* HAVE_DECL_PTHREAD_GETAFFINITY_NP */
topology->get_thisthread_last_cpu_location = hwloc_linux_get_thisthread_last_cpu_location;
topology->get_thisproc_last_cpu_location = hwloc_linux_get_thisproc_last_cpu_location;
topology->get_proc_last_cpu_location = hwloc_linux_get_proc_last_cpu_location;
#ifdef HWLOC_HAVE_SET_MEMPOLICY
topology->set_thisthread_membind = hwloc_linux_set_thisthread_membind;
topology->get_thisthread_membind = hwloc_linux_get_thisthread_membind;

Просмотреть файл

@ -1,7 +1,7 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2010 INRIA
* Copyright © 2009-2010 Université Bordeaux 1
* Copyright © 2009-2011 INRIA. All rights reserved.
* Copyright © 2009-2011 Université Bordeaux 1
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
*/
@ -250,15 +250,15 @@ hwloc_look_osf(struct hwloc_topology *topology)
radsetcreate(&radset);
radsetcreate(&radset2);
{
hwloc_obj_t nodes[nbnodes];
unsigned distances[nbnodes][nbnodes];
unsigned distance_indexes[nbnodes];
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 = {
.nattr_type = R_RAD,
.nattr_descr = { .rd_radset = radset },
.nattr_flags = 0,
};
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);
@ -269,6 +269,7 @@ hwloc_look_osf(struct hwloc_topology *topology)
continue;
}
indexes[radid] = radid;
nodes[radid] = obj = hwloc_alloc_setup_object(HWLOC_OBJ_NODE, radid);
obj->cpuset = hwloc_bitmap_alloc();
obj->memory.local_memory = rad_get_physmem(radid) * getpagesize();
@ -289,11 +290,9 @@ hwloc_look_osf(struct hwloc_topology *topology)
hwloc_insert_object_by_cpuset(topology, obj);
distance_indexes[radid] = radid;
nfound = 0;
for (radid2 = 0; radid2 < (radid_t) nbnodes; radid2++)
distances[radid][radid2] = RAD_DIST_REMOTE;
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 */
@ -303,8 +302,8 @@ hwloc_look_osf(struct hwloc_topology *topology)
}
cursor = SET_CURSOR_INIT;
while ((radid2 = rad_foreach(radset2, 0, &cursor)) != RAD_NONE) {
if (distances[radid][radid2] == RAD_DIST_REMOTE) {
distances[radid][radid2] = distance;
if (distances[radid*nbnodes+radid2] == RAD_DIST_REMOTE) {
distances[radid*nbnodes+radid2] = (float) distance;
nfound++;
}
}
@ -313,7 +312,8 @@ hwloc_look_osf(struct hwloc_topology *topology)
break;
}
}
hwloc_setup_misc_level_from_distances(topology, nbnodes, nodes, (unsigned*) distances, (unsigned*) distance_indexes);
hwloc_topology__set_distance_matrix(topology, HWLOC_OBJ_NODE, nbnodes, indexes, nodes, distances);
}
radsetdestroy(&radset2);
radsetdestroy(&radset);

Просмотреть файл

@ -1,6 +1,6 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2010 INRIA
* Copyright © 2009-2011 INRIA. All rights reserved.
* Copyright © 2009-2011 Université Bordeaux 1
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
@ -26,6 +26,9 @@
#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
@ -341,7 +344,9 @@ browse(struct hwloc_topology *topology, lgrp_cookie_t cookie, lgrp_id_t lgrp, hw
if ((mem_size = lgrp_mem_size(cookie, lgrp, LGRP_MEM_SZ_INSTALLED, LGRP_CONTENT_DIRECT)) > 0)
{
int i;
processorid_t cpuids[n];
processorid_t *cpuids;
cpuids = malloc(sizeof(processorid_t) * n);
assert(cpuids != NULL);
obj = hwloc_alloc_setup_object(HWLOC_OBJ_NODE, lgrp);
obj->nodeset = hwloc_bitmap_alloc();
@ -368,13 +373,16 @@ browse(struct hwloc_topology *topology, lgrp_cookie_t cookie, lgrp_id_t lgrp, hw
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[n];
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++)
@ -382,6 +390,7 @@ browse(struct hwloc_topology *topology, lgrp_cookie_t cookie, lgrp_id_t lgrp, hw
browse(topology, cookie, lgrps[i], glob_lgrps, curlgrp);
}
hwloc_debug("lgrp %ld's children done\n", lgrp);
free(lgrps);
}
}
@ -405,19 +414,19 @@ hwloc_look_lgrp(struct hwloc_topology *topology)
nlgrps = lgrp_nlgrps(cookie);
root = lgrp_root(cookie);
{
hwloc_obj_t glob_lgrps[nlgrps];
hwloc_obj_t *glob_lgrps = calloc(nlgrps, sizeof(hwloc_obj_t));
browse(topology, cookie, root, glob_lgrps, &curlgrp);
#ifdef HAVE_LGRP_LATENCY_COOKIE
{
unsigned distances[curlgrp][curlgrp];
unsigned indexes[curlgrp];
float *distances = calloc(curlgrp*curlgrp, sizeof(float));
unsigned *indexes;
unsigned i, j;
for (i = 0; i < curlgrp; i++) {
indexes[i] = glob_lgrps[i]->os_index;
for (j = 0; j < curlgrp; j++)
distances[i][j] = lgrp_latency_cookie(cookie, glob_lgrps[i]->os_index, glob_lgrps[j]->os_index, LGRP_LAT_CPU_TO_MEM);
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_setup_misc_level_from_distances(topology, curlgrp, glob_lgrps, (unsigned*) distances, (unsigned*) indexes);
hwloc_topology__set_distance_matrix(topology, HWLOC_OBJ_NODE, curlgrp, indexes, glob_lgrps, distances);
}
#endif /* HAVE_LGRP_LATENCY_COOKIE */
}

Просмотреть файл

@ -237,6 +237,10 @@ hwloc__look_synthetic(struct hwloc_topology *topology,
break;
case HWLOC_OBJ_PU:
break;
case HWLOC_OBJ_TYPE_MAX:
/* Should never happen */
assert(0);
break;
}
obj = hwloc_alloc_setup_object(type, topology->backend_params.synthetic.id[level]++);
@ -293,6 +297,10 @@ hwloc__look_synthetic(struct hwloc_topology *topology,
break;
case HWLOC_OBJ_PU:
break;
case HWLOC_OBJ_TYPE_MAX:
/* Should never happen */
assert(0);
break;
}
hwloc_insert_object_by_cpuset(topology, obj);

Просмотреть файл

@ -1,7 +1,7 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2010 INRIA
* Copyright © 2009-2010 Université Bordeaux 1
* Copyright © 2009-2010 INRIA. All rights reserved.
* Copyright © 2009-2011 Université Bordeaux 1
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
*/
@ -154,13 +154,13 @@ typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX {
typedef union _PSAPI_WORKING_SET_EX_BLOCK {
ULONG_PTR Flags;
struct {
ULONG_PTR Valid :1;
ULONG_PTR ShareCount :3;
ULONG_PTR Win32Protection :11;
ULONG_PTR Shared :1;
ULONG_PTR Node :6;
ULONG_PTR Locked :1;
ULONG_PTR LargePage :1;
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
@ -686,6 +686,7 @@ hwloc_set_windows_hooks(struct hwloc_topology *topology)
topology->set_thisproc_cpubind = hwloc_win_set_thisproc_cpubind;
topology->get_thisproc_cpubind = hwloc_win_get_thisproc_cpubind;
topology->set_thisthread_cpubind = hwloc_win_set_thisthread_cpubind;
/* TODO: get_last_cpu_location: use GetCurrentProcessorNumber */
topology->set_proc_membind = hwloc_win_set_proc_membind;
topology->get_proc_membind = hwloc_win_get_proc_membind;

Просмотреть файл

@ -43,6 +43,8 @@ struct procinfo {
unsigned logprocid;
unsigned threadid;
unsigned coreid;
unsigned *otherids;
unsigned levels;
unsigned numcaches;
struct cacheinfo *cache;
};
@ -155,7 +157,7 @@ static void look_proc(struct procinfo *infos, unsigned highest_cpuid, unsigned h
fill_amd_cache(infos, 3, edx);
}
/* AMD doesn't actually provide 0x80000008 information */
/* AMD doesn't actually provide 0x04 information */
if (cpuid_type != amd && highest_cpuid >= 0x04) {
cachenum = 0;
for (cachenum = 0; ; cachenum++) {
@ -215,17 +217,66 @@ static void look_proc(struct procinfo *infos, unsigned highest_cpuid, unsigned h
cache++;
}
}
if (cpuid_type == intel && highest_cpuid >= 0x0b) {
unsigned level, apic_nextshift, apic_number, apic_type, apic_id, apic_shift = 0, id;
for (level = 0; ; level++) {
ecx = level;
eax = 0x0b;
hwloc_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_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->socketid = apic_id >> apic_shift;
hwloc_debug("x2APIC remainder: %d\n", infos->socketid);
} else
infos->otherids = NULL;
} else
infos->otherids = NULL;
}
/* Analyse information stored in infos, and build topology levels accordingly */
static void summarize(hwloc_topology_t topology, struct procinfo *infos, unsigned nbprocs)
{
hwloc_bitmap_t complete_cpuset = hwloc_bitmap_alloc();
unsigned i, j;
unsigned i, j, l, one, level;
for (i = 0; i < nbprocs; i++)
if (infos[i].present)
if (infos[i].present) {
hwloc_bitmap_set(complete_cpuset, i);
one = i;
}
/* Look for sockets */
{
@ -252,6 +303,36 @@ static void summarize(hwloc_topology_t topology, struct procinfo *infos, unsigne
hwloc_bitmap_free(sockets_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;
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 = hwloc_alloc_setup_object(HWLOC_OBJ_MISC, unknownid);
unknown->cpuset = unknown_cpuset;
unknown->os_level = level;
hwloc_debug_2args_bitmap("os unknown%d %u has cpuset %s\n",
level, unknownid, unknown_cpuset);
hwloc_insert_object_by_cpuset(topology, unknown);
}
hwloc_bitmap_free(unknowns_cpuset);
}
}
}
/* Look for cores */
{
hwloc_bitmap_t cores_cpuset = hwloc_bitmap_dup(complete_cpuset);
@ -290,7 +371,7 @@ static void summarize(hwloc_topology_t topology, struct procinfo *infos, unsigne
/* Look for caches */
/* First find max level */
unsigned level = 0, l;
level = 0;
for (i = 0; i < nbprocs; i++)
for (j = 0; j < infos[i].numcaches; j++)
if (infos[i].cache[j].level > level)
@ -351,8 +432,11 @@ static void summarize(hwloc_topology_t topology, struct procinfo *infos, unsigne
level--;
}
for (i = 0; i < nbprocs; i++)
for (i = 0; i < nbprocs; i++) {
free(infos[i].cache);
if (infos[i].otherids)
free(infos[i].otherids);
}
}
#define INTEL_EBX ('G' | ('e'<<8) | ('n'<<16) | ('u'<<24))
@ -372,12 +456,17 @@ void hwloc_look_x86(struct hwloc_topology *topology, unsigned nbprocs)
unsigned i;
unsigned highest_cpuid;
unsigned highest_ext_cpuid;
struct procinfo infos[nbprocs];
struct procinfo *infos = NULL;
enum cpuid_type cpuid_type = unknown;
if (!hwloc_have_cpuid())
return;
infos = malloc(sizeof(struct procinfo) * nbprocs);
if (NULL == infos) {
return;
}
eax = 0x00;
hwloc_cpuid(&eax, &ebx, &ecx, &edx);
highest_cpuid = eax;
@ -387,8 +476,9 @@ void hwloc_look_x86(struct hwloc_topology *topology, unsigned nbprocs)
cpuid_type = amd;
hwloc_debug("highest cpuid %x, cpuid type %u\n", highest_cpuid, cpuid_type);
if (highest_cpuid < 0x01)
return;
if (highest_cpuid < 0x01) {
goto free;
}
eax = 0x80000000;
hwloc_cpuid(&eax, &ebx, &ecx, &edx);
@ -411,7 +501,7 @@ void hwloc_look_x86(struct hwloc_topology *topology, unsigned nbprocs)
topology->set_thisthread_cpubind(topology, orig_cpuset, 0);
hwloc_bitmap_free(orig_cpuset);
summarize(topology, infos, nbprocs);
return;
goto free;
}
}
if (topology->get_thisproc_cpubind && topology->set_thisproc_cpubind) {
@ -427,10 +517,15 @@ void hwloc_look_x86(struct hwloc_topology *topology, unsigned nbprocs)
topology->set_thisproc_cpubind(topology, orig_cpuset, 0);
hwloc_bitmap_free(orig_cpuset);
summarize(topology, infos, nbprocs);
return;
goto free;
}
}
#endif
hwloc_add_object_info(topology->levels[0][0], "Backend", "x86");
free:
if (NULL != infos) {
free(infos);
}
}

Просмотреть файл

@ -1,7 +1,7 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2010 INRIA
* Copyright © 2009-2010 Université Bordeaux 1
* Copyright © 2009-2011 INRIA. All rights reserved.
* Copyright © 2009-2011 Université Bordeaux 1
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
*/
@ -301,6 +301,84 @@ hwloc__xml_import_pagetype_node(struct hwloc_topology *topology __hwloc_attribut
fprintf(stderr, "ignoring pagetype attribute without size\n");
}
static void
hwloc__xml_import_distances_node(struct hwloc_topology *topology __hwloc_attribute_unused, struct hwloc_obj *obj, xmlNode *node)
{
unsigned long reldepth = 0, nbobjs = 0;
float latbase = 0;
xmlAttr *attr = NULL;
xmlNode *subnode;
for (attr = node->properties; attr; attr = attr->next) {
if (attr->type == XML_ATTRIBUTE_NODE) {
const xmlChar *value = hwloc__xml_import_attr_value(attr);
if (value) {
if (!strcmp((char *) attr->name, "nbobjs"))
nbobjs = strtoul((char *) value, NULL, 10);
else if (!strcmp((char *) attr->name, "relative_depth"))
reldepth = strtoul((char *) value, NULL, 10);
else if (!strcmp((char *) attr->name, "latency_base"))
latbase = (float) atof((char *) value);
else
fprintf(stderr, "ignoring unknown distances attribute %s\n", (char *) attr->name);
} else
fprintf(stderr, "ignoring unexpected xml distances attr name `%s' with no value\n", (const char*) attr->name);
} else {
fprintf(stderr, "ignoring unexpected xml distances attr type %u\n", attr->type);
}
}
if (nbobjs && reldepth && latbase) {
int idx = obj->distances_count;
unsigned nbcells, i;
float *matrix, latmax = 0;
nbcells = 0;
if (node->children)
for(subnode = node->children; subnode; subnode = subnode->next)
if (subnode->type == XML_ELEMENT_NODE)
nbcells++;
if (nbcells != nbobjs*nbobjs) {
fprintf(stderr, "ignoring distances with %u cells instead of %lu\n", nbcells, nbobjs*nbobjs);
return;
}
obj->distances = realloc(obj->distances, (idx+1)*sizeof(*obj->distances));
obj->distances_count = idx+1;
obj->distances[idx] = malloc(sizeof(**obj->distances));
obj->distances[idx]->relative_depth = reldepth;
obj->distances[idx]->nbobjs = nbobjs;
obj->distances[idx]->latency = matrix = malloc(nbcells*sizeof(float));
obj->distances[idx]->latency_base = latbase;
i = 0;
for(subnode = node->children; subnode; subnode = subnode->next)
if (subnode->type == XML_ELEMENT_NODE) {
/* read one cell */
for (attr = subnode->properties; attr; attr = attr->next)
if (attr->type == XML_ATTRIBUTE_NODE) {
const xmlChar *value = hwloc__xml_import_attr_value(attr);
if (value) {
if (!strcmp((char *) attr->name, "value")) {
float val = (float) atof((char *) value);
matrix[i] = val;
if (val > latmax)
latmax = val;
} else
fprintf(stderr, "ignoring unknown distance attribute %s\n", (char *) attr->name);
} else
fprintf(stderr, "ignoring unexpected xml distance attr name `%s' with no value\n", (const char*) attr->name);
} else {
fprintf(stderr, "ignoring unexpected xml distance attr type %u\n", attr->type);
}
/* next matrix cell */
i++;
}
obj->distances[idx]->latency_max = latmax;
}
}
static void
hwloc__xml_import_info_node(struct hwloc_topology *topology __hwloc_attribute_unused, struct hwloc_obj *obj, xmlNode *node)
{
@ -351,6 +429,9 @@ hwloc__xml_import_node(struct hwloc_topology *topology, struct hwloc_obj *parent
} else if (!strcmp((const char*) node->name, "info")) {
hwloc__xml_import_info_node(topology, parent, node);
} else if (!strcmp((const char*) node->name, "distances")) {
hwloc__xml_import_distances_node(topology, parent, node);
} else {
/* unknown class */
fprintf(stderr, "ignoring unexpected node class `%s'\n", (const char*) node->name);
@ -419,6 +500,39 @@ hwloc_look_xml(struct hwloc_topology *topology)
/* we could add "BackendSource=XML" to notify that XML was used between the actual backend and here */
}
static void
hwloc_xml__check_distances(struct hwloc_topology *topology, hwloc_obj_t obj)
{
hwloc_obj_t child;
unsigned i=0;
while (i<obj->distances_count) {
unsigned depth = obj->depth + obj->distances[i]->relative_depth;
unsigned nbobjs = hwloc_get_nbobjs_inside_cpuset_by_depth(topology, obj->cpuset, depth);
if (nbobjs != obj->distances[i]->nbobjs) {
fprintf(stderr, "ignoring invalid distance matrix with %u objs instead of %u\n",
obj->distances[i]->nbobjs, nbobjs);
hwloc_free_logical_distances(obj->distances[i]);
memmove(&obj->distances[i], &obj->distances[i+1], (obj->distances_count-i-1)*sizeof(*obj->distances));
obj->distances_count--;
} else
i++;
}
child = obj->first_child;
while (child != NULL) {
hwloc_xml__check_distances(topology, child);
child = child->next_sibling;
}
}
void
hwloc_xml_check_distances(struct hwloc_topology *topology)
{
/* now that the topology tree has been properly setup,
* check that our distance matrice sizes make sense */
hwloc_xml__check_distances(topology, topology->levels[0][0]);
}
/******************************
********* XML export *********
******************************/
@ -426,7 +540,7 @@ hwloc_look_xml(struct hwloc_topology *topology)
static void
hwloc__xml_export_object (hwloc_topology_t topology, hwloc_obj_t obj, xmlNodePtr root_node)
{
xmlNodePtr node = NULL, ptnode = NULL;
xmlNodePtr node = NULL, ptnode = NULL, dnode = NULL, dcnode = NULL;
char *cpuset = NULL;
char tmp[255];
unsigned i;
@ -515,6 +629,23 @@ hwloc__xml_export_object (hwloc_topology_t topology, hwloc_obj_t obj, xmlNodePtr
xmlNewProp(ptnode, BAD_CAST "value", BAD_CAST obj->infos[i].value);
}
for(i=0; i<obj->distances_count; i++) {
unsigned nbobjs = obj->distances[i]->nbobjs;
unsigned j;
dnode = xmlNewChild(node, NULL, BAD_CAST "distances", NULL);
sprintf(tmp, "%u", nbobjs);
xmlNewProp(dnode, BAD_CAST "nbobjs", BAD_CAST tmp);
sprintf(tmp, "%u", obj->distances[i]->relative_depth);
xmlNewProp(dnode, BAD_CAST "relative_depth", BAD_CAST tmp);
sprintf(tmp, "%f", obj->distances[i]->latency_base);
xmlNewProp(dnode, BAD_CAST "latency_base", BAD_CAST tmp);
for(j=0; j<nbobjs*nbobjs; j++) {
dcnode = xmlNewChild(dnode, NULL, BAD_CAST "latency", NULL);
sprintf(tmp, "%f", obj->distances[i]->latency[j]);
xmlNewProp(dcnode, BAD_CAST "value", BAD_CAST tmp);
}
}
if (obj->arity) {
unsigned x;
for (x=0; x<obj->arity; x++)

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -50,6 +50,9 @@ unsigned hwloc_get_closest_objs (struct hwloc_topology *topology, struct hwloc_o
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];
@ -59,11 +62,14 @@ unsigned hwloc_get_closest_objs (struct hwloc_topology *topology, struct hwloc_o
nextparent = parent->parent;
if (!nextparent)
goto out;
if (!hwloc_bitmap_isequal(parent->cpuset, nextparent->cpuset))
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; i<src_nbobjects; i++) {
if (hwloc_bitmap_isincluded(src_objs[i]->cpuset, nextparent->cpuset)
@ -103,11 +109,13 @@ hwloc__get_largest_objs_inside_cpuset (struct hwloc_obj *current, hwloc_const_bi
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;
@ -127,7 +135,7 @@ hwloc_get_largest_objs_inside_cpuset (struct hwloc_topology *topology, hwloc_con
{
struct hwloc_obj *current = topology->levels[0][0];
if (!hwloc_bitmap_isincluded(set, current->cpuset))
if (!current->cpuset || !hwloc_bitmap_isincluded(set, current->cpuset))
return -1;
if (max <= 0)
@ -333,6 +341,7 @@ int hwloc_obj_cpuset_snprintf(char *str, size_t size, size_t nobj, struct hwloc_
hwloc_bitmap_zero(set);
for(i=0; i<nobj; i++)
if (objs[i]->cpuset)
hwloc_bitmap_or(set, set, objs[i]->cpuset);
res = hwloc_bitmap_snprintf(str, size, set);