Commit ec17b702 authored by Hisham Muhammad's avatar Hisham Muhammad
Browse files

Convert affinity control from the deprecated PLPA to HWLOC

parent d07b043e
# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
#
# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 6 ltsugar.m4
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
# lt_join(SEP, ARG1, [ARG2...])
# -----------------------------
# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
# associated separator.
# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
# versions in m4sugar had bugs.
m4_define([lt_join],
[m4_if([$#], [1], [],
[$#], [2], [[$2]],
[m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
m4_define([_lt_join],
[m4_if([$#$2], [2], [],
[m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
# lt_car(LIST)
# lt_cdr(LIST)
# ------------
# Manipulate m4 lists.
# These macros are necessary as long as will still need to support
# Autoconf-2.59 which quotes differently.
m4_define([lt_car], [[$1]])
m4_define([lt_cdr],
[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
[$#], 1, [],
[m4_dquote(m4_shift($@))])])
m4_define([lt_unquote], $1)
# lt_append(MACRO-NAME, STRING, [SEPARATOR])
# ------------------------------------------
# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'.
# Note that neither SEPARATOR nor STRING are expanded; they are appended
# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
# No SEPARATOR is output if MACRO-NAME was previously undefined (different
# than defined and empty).
#
# This macro is needed until we can rely on Autoconf 2.62, since earlier
# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
m4_define([lt_append],
[m4_define([$1],
m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
# ----------------------------------------------------------
# Produce a SEP delimited list of all paired combinations of elements of
# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
# has the form PREFIXmINFIXSUFFIXn.
# Needed until we can rely on m4_combine added in Autoconf 2.62.
m4_define([lt_combine],
[m4_if(m4_eval([$# > 3]), [1],
[m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
[[m4_foreach([_Lt_prefix], [$2],
[m4_foreach([_Lt_suffix],
]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
[_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
# -----------------------------------------------------------------------
# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
m4_define([lt_if_append_uniq],
[m4_ifdef([$1],
[m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
[lt_append([$1], [$2], [$3])$4],
[$5])],
[lt_append([$1], [$2], [$3])$4])])
# lt_dict_add(DICT, KEY, VALUE)
# -----------------------------
m4_define([lt_dict_add],
[m4_define([$1($2)], [$3])])
# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
# --------------------------------------------
m4_define([lt_dict_add_subkey],
[m4_define([$1($2:$3)], [$4])])
# lt_dict_fetch(DICT, KEY, [SUBKEY])
# ----------------------------------
m4_define([lt_dict_fetch],
[m4_ifval([$3],
m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
# -----------------------------------------------------------------
m4_define([lt_if_dict_fetch],
[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
[$5],
[$6])])
# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
# --------------------------------------------------------------
m4_define([lt_dict_filter],
[m4_if([$5], [], [],
[lt_join(m4_quote(m4_default([$4], [[, ]])),
lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
[lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
])
# ltversion.m4 -- version numbers -*- Autoconf -*-
#
# Copyright (C) 2004 Free Software Foundation, Inc.
# Written by Scott James Remnant, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# @configure_input@
# serial 3293 ltversion.m4
# This file is part of GNU Libtool
m4_define([LT_PACKAGE_VERSION], [2.4])
m4_define([LT_PACKAGE_REVISION], [1.3293])
AC_DEFUN([LTVERSION_VERSION],
[macro_version='2.4'
macro_revision='1.3293'
_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
_LT_DECL(, macro_revision, 0)
])
# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
#
# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
# Written by Scott James Remnant, 2004.
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 5 lt~obsolete.m4
# These exist entirely to fool aclocal when bootstrapping libtool.
#
# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
# which have later been changed to m4_define as they aren't part of the
# exported API, or moved to Autoconf or Automake where they belong.
#
# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
# using a macro with the same name in our local m4/libtool.m4 it'll
# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
# and doesn't know about Autoconf macros at all.)
#
# So we provide this file, which has a silly filename so it's always
# included after everything else. This provides aclocal with the
# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
# because those macros already exist, or will be overwritten later.
# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
#
# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
# Yes, that means every name once taken will need to remain here until
# we give up compatibility with versions before 1.7, at which point
# we need to keep only those names which we still refer to.
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])])
m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])])
m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])
#! /bin/sh
# Common stub for a few missing GNU programs while installing.
scriptversion=2009-04-28.21; # UTC
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
# 2008, 2009 Free Software Foundation, Inc.
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
if test $# -eq 0; then
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
fi
run=:
sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
# In the cases where this matters, `missing' is being run in the
# srcdir already.
if test -f configure.ac; then
configure_ac=configure.ac
else
configure_ac=configure.in
fi
msg="missing on your system"
case $1 in
--run)
# Try to run requested program, and just exit if it succeeds.
run=
shift
"$@" && exit 0
# Exit code 63 means version mismatch. This often happens
# when the user try to use an ancient version of a tool on
# a file that requires a minimum version. In this case we
# we should proceed has if the program had been absent, or
# if --run hadn't been passed.
if test $? = 63; then
run=:
msg="probably too old"
fi
;;
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
error status if there is no known handling for PROGRAM.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
--run try to run the given command, and emulate it if it fails
Supported PROGRAM values:
aclocal touch file \`aclocal.m4'
autoconf touch file \`configure'
autoheader touch file \`config.h.in'
autom4te touch the output file, or create a stub one
automake touch all \`Makefile.in' files
bison create \`y.tab.[ch]', if possible, from existing .[ch]
flex create \`lex.yy.c', if possible, from existing .c
help2man touch the output file
lex create \`lex.yy.c', if possible, from existing .c
makeinfo touch the output file
tar try tar, gnutar, gtar, then tar without non-portable flags
yacc create \`y.tab.[ch]', if possible, from existing .[ch]
Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
\`g' are ignored when checking the name.
Send bug reports to <bug-automake@gnu.org>."
exit $?
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing $scriptversion (GNU Automake)"
exit $?
;;
-*)
echo 1>&2 "$0: Unknown \`$1' option"
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
;;
esac
# normalize program name to check for.
program=`echo "$1" | sed '
s/^gnu-//; t
s/^gnu//; t
s/^g//; t'`
# Now exit if we have it, but it failed. Also exit now if we
# don't have it and --version was passed (most likely to detect
# the program). This is about non-GNU programs, so use $1 not
# $program.
case $1 in
lex*|yacc*)
# Not GNU programs, they don't have --version.
;;
tar*)
if test -n "$run"; then
echo 1>&2 "ERROR: \`tar' requires --run"
exit 1
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
exit 1
fi
;;
*)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
# Could not run --version or --help. This is probably someone
# running `$TOOL --version' or `$TOOL --help' to check whether
# $TOOL exists and not knowing $TOOL uses missing.
exit 1
fi
;;
esac
# If it does not exist, or fails to run (possibly an outdated version),
# try to emulate it.
case $program in
aclocal*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`acinclude.m4' or \`${configure_ac}'. You might want
to install the \`Automake' and \`Perl' packages. Grab them from
any GNU archive site."
touch aclocal.m4
;;
autoconf*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`${configure_ac}'. You might want to install the
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
archive site."
touch configure
;;
autoheader*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`acconfig.h' or \`${configure_ac}'. You might want
to install the \`Autoconf' and \`GNU m4' packages. Grab them
from any GNU archive site."
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
test -z "$files" && files="config.h"
touch_files=
for f in $files; do
case $f in
*:*) touch_files="$touch_files "`echo "$f" |
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
*) touch_files="$touch_files $f.in";;
esac
done
touch $touch_files
;;
automake*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
You might want to install the \`Automake' and \`Perl' packages.
Grab them from any GNU archive site."
find . -type f -name Makefile.am -print |
sed 's/\.am$/.in/' |
while read f; do touch "$f"; done
;;
autom4te*)
echo 1>&2 "\
WARNING: \`$1' is needed, but is $msg.
You might have modified some files without having the
proper tools for further handling them.
You can get \`$1' as part of \`Autoconf' from any GNU
archive site."
file=`echo "$*" | sed -n "$sed_output"`
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
if test -f "$file"; then
touch $file
else
test -z "$file" || exec >$file
echo "#! /bin/sh"
echo "# Created by GNU Automake missing as a replacement of"
echo "# $ $@"
echo "exit 0"
chmod +x $file
exit 1
fi
;;
bison*|yacc*)
echo 1>&2 "\
WARNING: \`$1' $msg. You should only need it if
you modified a \`.y' file. You may need the \`Bison' package
in order for those modifications to take effect. You can get
\`Bison' from any GNU archive site."
rm -f y.tab.c y.tab.h
if test $# -ne 1; then
eval LASTARG="\${$#}"
case $LASTARG in
*.y)
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
if test -f "$SRCFILE"; then
cp "$SRCFILE" y.tab.c
fi
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
if test -f "$SRCFILE"; then
cp "$SRCFILE" y.tab.h
fi
;;
esac
fi
if test ! -f y.tab.h; then
echo >y.tab.h
fi
if test ! -f y.tab.c; then
echo 'main() { return 0; }' >y.tab.c
fi
;;
lex*|flex*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified a \`.l' file. You may need the \`Flex' package
in order for those modifications to take effect. You can get
\`Flex' from any GNU archive site."
rm -f lex.yy.c
if test $# -ne 1; then
eval LASTARG="\${$#}"
case $LASTARG in
*.l)
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
if test -f "$SRCFILE"; then
cp "$SRCFILE" lex.yy.c
fi
;;
esac
fi
if test ! -f lex.yy.c; then
echo 'main() { return 0; }' >lex.yy.c
fi
;;
help2man*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified a dependency of a manual page. You may need the
\`Help2man' package in order for those modifications to take
effect. You can get \`Help2man' from any GNU archive site."
file=`echo "$*" | sed -n "$sed_output"`
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
if test -f "$file"; then
touch $file
else
test -z "$file" || exec >$file
echo ".ab help2man is required to generate this page"
exit $?
fi
;;
makeinfo*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified a \`.texi' or \`.texinfo' file, or any other file
indirectly affecting the aspect of the manual. The spurious
call might also be the consequence of using a buggy \`make' (AIX,
DU, IRIX). You might want to install the \`Texinfo' package or
the \`GNU make' package. Grab either from any GNU archive site."
# The file to touch is that specified with -o ...
file=`echo "$*" | sed -n "$sed_output"`
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
if test -z "$file"; then
# ... or it is the one specified with @setfilename ...
infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
file=`sed -n '
/^@setfilename/{
s/.* \([^ ]*\) *$/\1/
p
q
}' $infile`
# ... or it is derived from the source name (dir/f.texi becomes f.info)
test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
fi
# If the file does not exist, the user really needs makeinfo;
# let's fail without touching anything.
test -f $file || exit 1
touch $file
;;
tar*)
shift
# We have already tried tar in the generic part.
# Look for gnutar/gtar before invocation to avoid ugly error
# messages.
if (gnutar --version > /dev/null 2>&1); then
gnutar "$@" && exit 0
fi
if (gtar --version > /dev/null 2>&1); then
gtar "$@" && exit 0
fi
firstarg="$1"
if shift; then
case $firstarg in
*o*)
firstarg=`echo "$firstarg" | sed s/o//`
tar "$firstarg" "$@" && exit 0
;;
esac
case $firstarg in
*h*)
firstarg=`echo "$firstarg" | sed s/h//`
tar "$firstarg" "$@" && exit 0
;;
esac
fi
echo 1>&2 "\
WARNING: I can't seem to be able to run \`tar' with the given arguments.
You may want to install GNU tar or Free paxutils, or check the
command line arguments."
exit 1
;;
*)
echo 1>&2 "\
WARNING: \`$1' is needed, and is $msg.
You might have modified some files without having the
proper tools for further handling them. Check the \`README' file,
it often tells you about the needed prerequisites for installing
this package. You may also peek at any GNU archive site, in case
some other package would contain this missing \`$1' program."
exit 1
;;
esac
exit 0
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:
This source diff could not be displayed because it is too large. You can view the blob instead.
# -*- shell-script -*-
#
# Copyright © 2009 CNRS
# 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.
#
# Additional copyrights may follow
#
# $HEADER$
#
AC_INIT([hwloc],
[m4_normalize(esyscmd([config/hwloc_get_version.sh VERSION --base]))],
[http://www.open-mpi.org/community/help/], [hwloc])
AC_PREREQ(2.63)
AC_CONFIG_AUX_DIR(./config)
# Note that this directory must *exactly* match what was specified via
# -I in ACLOCAL_AMFLAGS in the top-level Makefile.am.
AC_CONFIG_MACRO_DIR(./config)
cat <<EOF
###
### Configuring hwloc distribution tarball
### Startup tests
###
EOF
# This must be before AM_INIT_AUTOMAKE
AC_CANONICAL_TARGET
# Init automake
AM_INIT_AUTOMAKE([1.10 dist-bzip2 subdir-objects foreign tar-ustar -Wall -Werror])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
# We want new Libtool. None of that old stuff. Pfft.
m4_ifdef([LT_PREREQ], [],
[m4_fatal([libtool version 2.2.6 or higher is required], [63])])
LT_PREREQ([2.2.6])
AC_LANG([C])
# Make configure depend on the VERSION file, since it's used in AC_INIT
AC_SUBST([CONFIGURE_DEPENDENCIES], ['$(top_srcdir)/VERSION'])
# Get the version of hwloc that we are installing
AC_MSG_CHECKING([for hwloc version])
HWLOC_VERSION="`$srcdir/config/hwloc_get_version.sh $srcdir/VERSION`"
HWLOC_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_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)
AC_SUBST(HWLOC_RELEASE_DATE)
AC_DEFINE_UNQUOTED([HWLOC_MAJOR_VERSION], [$HWLOC_MAJOR_VERSION],
[Major version of hwloc])
AC_DEFINE_UNQUOTED([HWLOC_MINOR_VERSION], [$HWLOC_MINOR_VERSION],
[Minor version of hwloc])
AC_DEFINE_UNQUOTED([HWLOC_RELEASE_VERSION], [$HWLOC_RELEASE_VERSION],
[Release version of hwloc])
AC_MSG_RESULT([$HWLOC_VERSION])
# Override/fixup the version numbers set by AC_INIT, since on
# developer builds, there's no good way to know what the version is
# before running configure :(. We only use the base version number
# (ie, no svn r numbers) for the version set in AC_INIT. This will
# always match reality because we add the VERSION file (the only way
# to change the major.minor.release{greek}) into the configure
# dependencies.
PACKAGE_VERSION="$HWLOC_VERSION"
PACKAGE_STRING="${PACKAGE_NAME} ${PACKAGE_VERSION}"
VERSION="${PACKAGE_VERSION}"
# For standalone configurations, we also include a .so version number.
. $srcdir/VERSION
AC_SUBST([libhwloc_so_version])
# Setup the header file
AH_TOP([/* -*- c -*-
*
* Copyright © 2009 CNRS, INRIA., Université Bordeaux 1 All rights reserved.
* Copyright © 2009 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*
* This file is automatically generated by configure. Edits will be lost
* the next time you run configure!
*/
#ifndef HWLOC_CONFIGURE_H
#define HWLOC_CONFIGURE_H
])
AH_BOTTOM([
#endif /* HWLOC_CONFIGURE_H */
])
# Setup C compiler
CFLAGS_save="$CFLAGS"
AC_PROG_CC
AM_PROG_CC_C_O
CFLAGS="$CFLAGS_save"
# Define hwloc's configure arguments
HWLOC_DEFINE_ARGS
# If debug mode, add -g
AS_IF([test "$hwloc_debug" = "1"],
[CFLAGS="$CFLAGS -g"])
# If the user didn't specifically ask for embedding mode, default to
# standalone mode
AS_IF([test "$enable_embedded_mode" != "yes"],
[AS_IF([test ! -d "$srcdir/doc"],
[AC_MSG_WARN([The hwloc source tree looks incomplete for a standalone])
AC_MSG_WARN([build. Perhaps this hwloc tree is intended for an embedded])
AC_MSG_WARN([build? Try using the --enable-embedded-mode switch.])
AC_MSG_ERROR([Cannot build standalone hwloc])],
[HWLOC_BUILD_STANDALONE])])
# Setup the hwloc core
HWLOC_SETUP_CORE([], [], [AC_MSG_ERROR([Cannot build hwloc core])], [1])
# Setup hwloc's docs, utils, and tests
AS_IF([test "$hwloc_mode" = "standalone"],
[HWLOC_SETUP_DOCS
HWLOC_SETUP_UTILS
HWLOC_SETUP_TESTS])
# Run the AM_CONDITIONALs
HWLOC_DO_AM_CONDITIONALS
# Set the final flags
CFLAGS="$HWLOC_EMBEDDED_CFLAGS $CFLAGS"
CPPFLAGS="$HWLOC_EMBEDDED_CPPFLAGS $CPPFLAGS"
LIBS="$HWLOC_EMBEDDED_LIBS $LIBS"
# Setup libtool, but disable C++, F77, Java and Windows Resource
# Compiler support -- we don't need that stuff.
AM_ENABLE_SHARED
AM_DISABLE_STATIC
AM_PROG_LIBTOOL([win32-dll])
LT_LANG([C])
# Party on
AC_OUTPUT
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: hwloc
Description: Hardware locality detection and management library
Version: @VERSION@
Requires.private: @HWLOC_REQUIRES@
Cflags: -I${includedir}
Libs: -L${libdir} -lhwloc
Libs.private: @LIBS@
# 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.
# Only install the headers if we're in standalone mode (meaning:
# *don't* install the headers if we're in embedded mode).
if HWLOC_BUILD_STANDALONE
include_HEADERS = hwloc.h
include_hwlocdir = $(includedir)/hwloc
include_hwloc_HEADERS = \
hwloc/bitmap.h \
hwloc/cpuset.h \
hwloc/helper.h \
hwloc/myriexpress.h \
hwloc/openfabrics-verbs.h \
hwloc/cuda.h \
hwloc/cudart.h \
hwloc/rename.h
include_hwloc_autogendir = $(includedir)/hwloc/autogen
nodist_include_hwloc_autogen_HEADERS = hwloc/autogen/config.h
noinst_HEADERS = \
private/private.h \
private/debug.h \
private/misc.h \
private/cpuid.h
if HWLOC_HAVE_LINUX
include_hwloc_HEADERS += \
hwloc/linux.h \
hwloc/linux-libnuma.h
endif HWLOC_HAVE_LINUX
if HWLOC_HAVE_SCHED_SETAFFINITY
include_hwloc_HEADERS += hwloc/glibc-sched.h
endif HWLOC_HAVE_SCHED_SETAFFINITY
endif HWLOC_BUILD_STANDALONE
# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
# Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# 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.
# Only install the headers if we're in standalone mode (meaning:
# *don't* install the headers if we're in embedded mode).
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
@HWLOC_BUILD_STANDALONE_TRUE@@HWLOC_HAVE_LINUX_TRUE@am__append_1 = \
@HWLOC_BUILD_STANDALONE_TRUE@@HWLOC_HAVE_LINUX_TRUE@ hwloc/linux.h \
@HWLOC_BUILD_STANDALONE_TRUE@@HWLOC_HAVE_LINUX_TRUE@ hwloc/linux-libnuma.h
@HWLOC_BUILD_STANDALONE_TRUE@@HWLOC_HAVE_SCHED_SETAFFINITY_TRUE@am__append_2 = hwloc/glibc-sched.h
subdir = hwloc-1.2.1/include
DIST_COMMON = $(am__include_HEADERS_DIST) \
$(am__include_hwloc_HEADERS_DIST) $(am__noinst_HEADERS_DIST) \
$(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = \
$(top_srcdir)/hwloc-1.2.1/config/hwloc_check_attributes.m4 \
$(top_srcdir)/hwloc-1.2.1/config/hwloc_check_visibility.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/hwloc-1.2.1/config/hwloc.m4 \
$(top_srcdir)/hwloc-1.2.1/config/hwloc_pkg.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h \
$(top_builddir)/hwloc-1.2.1/include/private/autogen/config.h \
$(top_builddir)/hwloc-1.2.1/include/hwloc/autogen/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
SOURCES =
DIST_SOURCES =
am__include_HEADERS_DIST = hwloc.h
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(includedir)" \
"$(DESTDIR)$(include_hwlocdir)" \
"$(DESTDIR)$(include_hwloc_autogendir)"
am__include_hwloc_HEADERS_DIST = hwloc/bitmap.h hwloc/cpuset.h \
hwloc/helper.h hwloc/myriexpress.h hwloc/openfabrics-verbs.h \
hwloc/cuda.h hwloc/cudart.h hwloc/rename.h hwloc/linux.h \
hwloc/linux-libnuma.h hwloc/glibc-sched.h
am__noinst_HEADERS_DIST = private/private.h private/debug.h \
private/misc.h private/cpuid.h
HEADERS = $(include_HEADERS) $(include_hwloc_HEADERS) \
$(nodist_include_hwloc_autogen_HEADERS) $(noinst_HEADERS)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BASH = @BASH@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
HWLOC_CFLAGS = @HWLOC_CFLAGS@
HWLOC_CPPFLAGS = @HWLOC_CPPFLAGS@
HWLOC_EMBEDDED_CFLAGS = @HWLOC_EMBEDDED_CFLAGS@
HWLOC_EMBEDDED_CPPFLAGS = @HWLOC_EMBEDDED_CPPFLAGS@
HWLOC_EMBEDDED_LDADD = @HWLOC_EMBEDDED_LDADD@
HWLOC_EMBEDDED_LIBS = @HWLOC_EMBEDDED_LIBS@
HWLOC_HAVE_XML = @HWLOC_HAVE_XML@
HWLOC_KERRIGHED_CFLAGS = @HWLOC_KERRIGHED_CFLAGS@
HWLOC_KERRIGHED_LIBS = @HWLOC_KERRIGHED_LIBS@
HWLOC_LDFLAGS = @HWLOC_LDFLAGS@
HWLOC_LIBS = @HWLOC_LIBS@
HWLOC_LINUX_LIBNUMA_LIBS = @HWLOC_LINUX_LIBNUMA_LIBS@
HWLOC_MS_LIB = @HWLOC_MS_LIB@
HWLOC_PKG_CONFIG = @HWLOC_PKG_CONFIG@
HWLOC_REQUIRES = @HWLOC_REQUIRES@
HWLOC_XML_CFLAGS = @HWLOC_XML_CFLAGS@
HWLOC_XML_LIBS = @HWLOC_XML_LIBS@
HWLOC_top_builddir = @HWLOC_top_builddir@
HWLOC_top_srcdir = @HWLOC_top_srcdir@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
@HWLOC_BUILD_STANDALONE_TRUE@include_HEADERS = hwloc.h
@HWLOC_BUILD_STANDALONE_TRUE@include_hwlocdir = $(includedir)/hwloc
@HWLOC_BUILD_STANDALONE_TRUE@include_hwloc_HEADERS = hwloc/bitmap.h \
@HWLOC_BUILD_STANDALONE_TRUE@ hwloc/cpuset.h hwloc/helper.h \
@HWLOC_BUILD_STANDALONE_TRUE@ hwloc/myriexpress.h \
@HWLOC_BUILD_STANDALONE_TRUE@ hwloc/openfabrics-verbs.h \
@HWLOC_BUILD_STANDALONE_TRUE@ hwloc/cuda.h hwloc/cudart.h \
@HWLOC_BUILD_STANDALONE_TRUE@ hwloc/rename.h $(am__append_1) \
@HWLOC_BUILD_STANDALONE_TRUE@ $(am__append_2)
@HWLOC_BUILD_STANDALONE_TRUE@include_hwloc_autogendir = $(includedir)/hwloc/autogen
@HWLOC_BUILD_STANDALONE_TRUE@nodist_include_hwloc_autogen_HEADERS = hwloc/autogen/config.h
@HWLOC_BUILD_STANDALONE_TRUE@noinst_HEADERS = \
@HWLOC_BUILD_STANDALONE_TRUE@ private/private.h \
@HWLOC_BUILD_STANDALONE_TRUE@ private/debug.h \
@HWLOC_BUILD_STANDALONE_TRUE@ private/misc.h \
@HWLOC_BUILD_STANDALONE_TRUE@ private/cpuid.h
all: all-am
.SUFFIXES:
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu hwloc-1.2.1/include/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu hwloc-1.2.1/include/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
install-includeHEADERS: $(include_HEADERS)
@$(NORMAL_INSTALL)
test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
@list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \
$(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \
done
uninstall-includeHEADERS:
@$(NORMAL_UNINSTALL)
@list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
test -n "$$files" || exit 0; \
echo " ( cd '$(DESTDIR)$(includedir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(includedir)" && rm -f $$files
install-include_hwlocHEADERS: $(include_hwloc_HEADERS)
@$(NORMAL_INSTALL)
test -z "$(include_hwlocdir)" || $(MKDIR_P) "$(DESTDIR)$(include_hwlocdir)"
@list='$(include_hwloc_HEADERS)'; test -n "$(include_hwlocdir)" || list=; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(include_hwlocdir)'"; \
$(INSTALL_HEADER) $$files "$(DESTDIR)$(include_hwlocdir)" || exit $$?; \
done
uninstall-include_hwlocHEADERS:
@$(NORMAL_UNINSTALL)
@list='$(include_hwloc_HEADERS)'; test -n "$(include_hwlocdir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
test -n "$$files" || exit 0; \
echo " ( cd '$(DESTDIR)$(include_hwlocdir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(include_hwlocdir)" && rm -f $$files
install-nodist_include_hwloc_autogenHEADERS: $(nodist_include_hwloc_autogen_HEADERS)
@$(NORMAL_INSTALL)
test -z "$(include_hwloc_autogendir)" || $(MKDIR_P) "$(DESTDIR)$(include_hwloc_autogendir)"
@list='$(nodist_include_hwloc_autogen_HEADERS)'; test -n "$(include_hwloc_autogendir)" || list=; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(include_hwloc_autogendir)'"; \
$(INSTALL_HEADER) $$files "$(DESTDIR)$(include_hwloc_autogendir)" || exit $$?; \
done
uninstall-nodist_include_hwloc_autogenHEADERS:
@$(NORMAL_UNINSTALL)
@list='$(nodist_include_hwloc_autogen_HEADERS)'; test -n "$(include_hwloc_autogendir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
test -n "$$files" || exit 0; \
echo " ( cd '$(DESTDIR)$(include_hwloc_autogendir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(include_hwloc_autogendir)" && rm -f $$files
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
set x; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(HEADERS)
installdirs:
for dir in "$(DESTDIR)$(includedir)" "$(DESTDIR)$(include_hwlocdir)" "$(DESTDIR)$(include_hwloc_autogendir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libtool mostlyclean-am
distclean: distclean-am
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am: install-includeHEADERS install-include_hwlocHEADERS \
install-nodist_include_hwloc_autogenHEADERS
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-includeHEADERS uninstall-include_hwlocHEADERS \
uninstall-nodist_include_hwloc_autogenHEADERS
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
clean-libtool ctags distclean distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am \
install-includeHEADERS install-include_hwlocHEADERS \
install-info install-info-am install-man \
install-nodist_include_hwloc_autogenHEADERS install-pdf \
install-pdf-am install-ps install-ps-am install-strip \
installcheck installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-generic \
mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
uninstall-am uninstall-includeHEADERS \
uninstall-include_hwlocHEADERS \
uninstall-nodist_include_hwloc_autogenHEADERS
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
/*
* Copyright © 2009 CNRS
* 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.
*/
/** \file
* \brief The hwloc API.
*
* See hwloc/bitmap.h for bitmap specific macros.
* See hwloc/helper.h for high-level topology traversal helpers.
*/
#ifndef HWLOC_H
#define HWLOC_H
#include <hwloc/autogen/config.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
/*
* Symbol transforms
*/
#include <hwloc/rename.h>
/*
* Bitmap definitions
*/
#include <hwloc/bitmap.h>
#include <hwloc/cpuset.h>
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup hwlocality_api_version API version
* @{
*/
/** \brief Indicate at build time which hwloc API version is being used. */
#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);
/** @} */
/** \defgroup hwlocality_topology Topology context
* @{
*/
struct hwloc_topology;
/** \brief Topology context
*
* To be initialized with hwloc_topology_init() and built with hwloc_topology_load().
*/
typedef struct hwloc_topology * hwloc_topology_t;
/** @} */
/** \defgroup hwlocality_sets Object sets (hwloc_cpuset_t and hwloc_nodeset_t)
*
* Hwloc uses bitmaps to represent two distinct kinds of object sets:
* CPU sets (::hwloc_cpuset_t) and NUMA node sets (::hwloc_nodeset_t).
* These types are both typedefs to a common back end type
* (::hwloc_bitmap_t), and therefore all the hwloc bitmap functions
* are applicable to both ::hwloc_cpuset_t and ::hwloc_nodeset_t (see
* \ref hwlocality_bitmap).
*
* The rationale for having two different types is that even though
* the actions one wants to perform on these types are the same (e.g.,
* enable and disable individual items in the set/mask), they're used
* in very different contexts: one for specifying which processors to
* use and one for specifying which NUMA nodes to use. Hence, the
* name difference is really just to reflect the intent of where the
* type is used.
*
* @{
*/
/** \brief A CPU set is a bitmap whose bits are set according to CPU
* physical OS indexes.
*
* It may be consulted and modified with the bitmap API as any
* ::hwloc_bitmap_t (see hwloc/bitmap.h).
*/
typedef hwloc_bitmap_t hwloc_cpuset_t;
/** \brief A non-modifiable ::hwloc_cpuset_t. */
typedef hwloc_const_bitmap_t hwloc_const_cpuset_t;
/** \brief A node set is a bitmap whose bits are set according to NUMA
* memory node physical OS indexes.
*
* It may be consulted and modified with the bitmap API as any
* ::hwloc_bitmap_t (see hwloc/bitmap.h).
*
* When binding memory on a system without any NUMA node
* (when the whole memory is considered as a single memory bank),
* the nodeset may be either empty (no memory selected)
* or full (whole system memory selected).
*
* See also \ref hwlocality_helper_nodeset_convert.
*/
typedef hwloc_bitmap_t hwloc_nodeset_t;
/** \brief A non-modifiable ::hwloc_nodeset_t.
*/
typedef hwloc_const_bitmap_t hwloc_const_nodeset_t;
/** @} */
/** \defgroup hwlocality_types Topology Object Types
* @{
*/
/** \brief Type of topology object.
*
* \note Do not rely on the ordering or completeness of the values as new ones
* may be defined in the future! If you need to compare types, use
* 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
* like Kerrighed.
*/
HWLOC_OBJ_MACHINE, /**< \brief Machine.
* The typical root object type.
* A set of processors and memory with cache
* coherency.
*/
HWLOC_OBJ_NODE, /**< \brief NUMA node.
* A set of processors around memory which the
* processors can directly access.
*/
HWLOC_OBJ_SOCKET, /**< \brief Socket, physical package, or chip.
* In the physical meaning, i.e. that you can add
* or remove physically.
*/
HWLOC_OBJ_CACHE, /**< \brief Data cache.
* Can be L1, L2, L3, ...
*/
HWLOC_OBJ_CORE, /**< \brief Core.
* A computation unit (may be shared by several
* logical processors).
*/
HWLOC_OBJ_PU, /**< \brief Processing Unit, or (Logical) Processor.
* An execution unit (may share a core with some
* other logical processors, e.g. in the case of
* an SMT core).
*
* Objects of this kind are always reported and can
* thus be used as fallback when others are not.
*/
HWLOC_OBJ_GROUP, /**< \brief Group objects.
* Objects which do not fit in the above but are
* detected by hwloc and are useful to take into
* account for affinity. For instance, some operating systems
* expose their arbitrary processors aggregation this
* way. And hwloc may insert such objects to group
* NUMA nodes according to their distances.
*
* These objects are ignored when they do not bring
* any structure.
*/
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
*
* Types shouldn't be compared as they are, since newer ones may be added in
* the future. This function returns less than, equal to, or greater than zero
* respectively if \p type1 objects usually include \p type2 objects, are the
* same as \p type2 objects, or are included in \p type2 objects. If the types
* can not be compared (because neither is usually contained in the other),
* HWLOC_TYPE_UNORDERED is returned. Object types containing CPUs can always
* be compared (usually, a system contains machines which contain nodes which
* contain sockets which contain caches, which contain cores, which contain
* processors).
*
* \note HWLOC_OBJ_PU will always be the deepest.
* \note This does not mean that the actual topology will respect that order:
* e.g. as of today cores may also contain caches, and sockets may also contain
* nodes. This is thus just to be seen as a fallback comparison method.
*/
HWLOC_DECLSPEC int hwloc_compare_types (hwloc_obj_type_t type1, hwloc_obj_type_t type2) __hwloc_attribute_const;
enum hwloc_compare_types_e {
HWLOC_TYPE_UNORDERED = INT_MAX /**< \brief Value returned by hwloc_compare_types when types can not be compared. \hideinitializer */
};
/** @} */
/** \defgroup hwlocality_objects Topology Objects
* @{
*/
union hwloc_obj_attr_u;
/** \brief Object memory */
struct hwloc_obj_memory_s {
hwloc_uint64_t total_memory; /**< \brief Total memory (in bytes) in this object and its children */
hwloc_uint64_t local_memory; /**< \brief Local memory (in bytes) */
unsigned page_types_len; /**< \brief Size of array \p page_types */
/** \brief Array of local memory page types, \c NULL if no local memory and \p page_types is 0.
*
* The array is sorted by increasing \p size fields.
* It contains \p page_types_len slots.
*/
struct hwloc_obj_memory_page_type_s {
hwloc_uint64_t size; /**< \brief Size of pages */
hwloc_uint64_t count; /**< \brief Number of pages of this size */
} * page_types;
};
/** \brief Structure of a topology object
*
* Applications must not modify any field except hwloc_obj.userdata.
*/
struct hwloc_obj {
/* physical information */
hwloc_obj_type_t type; /**< \brief Type of object */
unsigned os_index; /**< \brief OS-provided physical index number */
char *name; /**< \brief Object description if any */
struct hwloc_obj_memory_s memory; /**< \brief Memory attributes */
union hwloc_obj_attr_u *attr; /**< \brief Object type-specific Attributes,
* may be \c NULL if no attribute value was found */
/* global position */
unsigned depth; /**< \brief Vertical index in the hierarchy */
unsigned logical_index; /**< \brief Horizontal index in the whole list of similar objects,
* 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 */
/* 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 */
/* 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 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 */
struct hwloc_obj *last_child; /**< \brief Last child */
/* misc */
void *userdata; /**< \brief Application-given private data pointer, initialized to \c NULL, use it as you wish */
/* cpusets and nodesets */
hwloc_cpuset_t cpuset; /**< \brief CPUs covered by this object
*
* This is the set of CPUs for which there are PU objects in the topology
* under this object, i.e. which are known to be physically contained in this
* object and known how (the children path between this object and the PU
* objects).
*
* If the HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM configuration flag is set, some of
* these CPUs may be offline, or not allowed for binding, see online_cpuset
* and allowed_cpuset.
*
* \note Its value must not be changed, hwloc_bitmap_dup must be used instead.
*/
hwloc_cpuset_t complete_cpuset; /**< \brief The complete CPU set of logical processors of this object,
*
* This includes not only the same as the cpuset field, but also the CPUs for
* which topology information is unknown or incomplete, and the CPUs that are
* ignored when the HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM flag is not set.
* Thus no corresponding PU object may be found in the topology, because the
* precise position is undefined. It is however known that it would be somewhere
* under this object.
*
* \note Its value must not be changed, hwloc_bitmap_dup must be used instead.
*/
hwloc_cpuset_t online_cpuset; /**< \brief The CPU set of online logical processors
*
* This includes the CPUs contained in this object that are online, i.e. draw
* power and can execute threads. It may however not be allowed to bind to
* them due to administration rules, see allowed_cpuset.
*
* \note Its value must not be changed, hwloc_bitmap_dup must be used instead.
*/
hwloc_cpuset_t allowed_cpuset; /**< \brief The CPU set of allowed logical processors
*
* This includes the CPUs contained in this object which are allowed for
* binding, i.e. passing them to the hwloc binding functions should not return
* permission errors. This is usually restricted by administration rules.
* Some of them may however be offline so binding to them may still not be
* possible, see online_cpuset.
*
* \note Its value must not be changed, hwloc_bitmap_dup must be used instead.
*/
hwloc_nodeset_t nodeset; /**< \brief NUMA nodes covered by this object or containing this object
*
* This is the set of NUMA nodes for which there are NODE objects in the
* topology under or above this object, i.e. which are known to be physically
* contained in this object or containing it and known how (the children path
* between this object and the NODE objects).
*
* In the end, these nodes are those that are close to the current object.
*
* If the HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM configuration flag is set, some of
* these nodes may not be allowed for allocation, see allowed_nodeset.
*
* If there are no NUMA nodes in the machine, all the memory is close to this
* object, so \p nodeset is full.
*
* \note Its value must not be changed, hwloc_bitmap_dup must be used instead.
*/
hwloc_nodeset_t complete_nodeset; /**< \brief The complete NUMA node set of this object,
*
* This includes not only the same as the nodeset field, but also the NUMA
* nodes for which topology information is unknown or incomplete, and the nodes
* that are ignored when the HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM flag is not set.
* Thus no corresponding NODE object may be found in the topology, because the
* precise position is undefined. It is however known that it would be
* somewhere under this object.
*
* If there are no NUMA nodes in the machine, all the memory is close to this
* object, so \p complete_nodeset is full.
*
* \note Its value must not be changed, hwloc_bitmap_dup must be used instead.
*/
hwloc_nodeset_t allowed_nodeset; /**< \brief The set of allowed NUMA memory nodes
*
* This includes the NUMA memory nodes contained in this object which are
* allowed for memory allocation, i.e. passing them to NUMA node-directed
* memory allocation should not return permission errors. This is usually
* restricted by administration rules.
*
* If there are no NUMA nodes in the machine, all the memory is close to this
* object, so \p allowed_nodeset is full.
*
* \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. */
};
/**
* \brief Convenience typedef; a pointer to a struct hwloc_obj.
*/
typedef struct hwloc_obj * hwloc_obj_t;
/** \brief Object type-specific Attributes */
union hwloc_obj_attr_u {
/** \brief Cache-specific Object Attributes */
struct hwloc_cache_attr_s {
hwloc_uint64_t size; /**< \brief Size of cache in bytes */
unsigned depth; /**< \brief Depth of cache */
unsigned linesize; /**< \brief Cache-line size in bytes */
} cache;
/** \brief Group-specific Object Attributes */
struct hwloc_group_attr_s {
unsigned depth; /**< \brief Depth of group object */
} 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 */
char *value; /**< \brief Info value */
};
/** @} */
/** \defgroup hwlocality_creation Create and Destroy Topologies
* @{
*/
/** \brief Allocate a topology context.
*
* \param[out] topologyp is assigned a pointer to the new allocated context.
*
* \return 0 on success, -1 on error.
*/
HWLOC_DECLSPEC int hwloc_topology_init (hwloc_topology_t *topologyp);
/** \brief Build the actual topology
*
* Build the actual topology once initialized with hwloc_topology_init() and
* tuned with \ref hwlocality_configuration routines.
* No other routine may be called earlier using this topology context.
*
* \param topology is the topology to be loaded with objects.
*
* \return 0 on success, -1 on error.
*
* \sa hwlocality_configuration
*/
HWLOC_DECLSPEC int hwloc_topology_load(hwloc_topology_t topology);
/** \brief Terminate and free a topology context
*
* \param topology is the topology to be freed
*/
HWLOC_DECLSPEC void hwloc_topology_destroy (hwloc_topology_t topology);
/** \brief Run internal checks on a topology structure
*
* \param topology is the topology to be checked
*/
HWLOC_DECLSPEC void hwloc_topology_check(hwloc_topology_t topology);
/** @} */
/** \defgroup hwlocality_configuration Configure Topology Detection
*
* These functions can optionally be called between hwloc_topology_init() and
* hwloc_topology_load() to configure how the detection should be performed,
* e.g. to ignore some objects types, define a synthetic topology, etc.
*
* If none of them is called, the default is to detect all the objects of the
* machine that the caller is allowed to access.
*
* This default behavior may also be modified through environment variables
* if the application did not modify it already.
* Setting HWLOC_XMLFILE in the environment enforces the discovery from a XML
* file as if hwloc_topology_set_xml() had been called.
* HWLOC_FSROOT switches to reading the topology from the specified Linux
* filesystem root as if hwloc_topology_set_fsroot() had been called.
* Finally, HWLOC_THISSYSTEM enforces the return value of
* hwloc_topology_is_thissystem().
*
* @{
*/
/** \brief Ignore an object type.
*
* Ignore all objects from the given type.
* The bottom-level type HWLOC_OBJ_PU may not be ignored.
* The top-level object of the hierarchy will never be ignored, even if this function
* succeeds.
*/
HWLOC_DECLSPEC int hwloc_topology_ignore_type(hwloc_topology_t topology, hwloc_obj_type_t type);
/** \brief Ignore an object type if it does not bring any structure.
*
* Ignore all objects from the given type as long as they do not bring any structure:
* Each ignored object should have a single children or be the only child of its parent.
* The bottom-level type HWLOC_OBJ_PU may not be ignored.
*/
HWLOC_DECLSPEC int hwloc_topology_ignore_type_keep_structure(hwloc_topology_t topology, hwloc_obj_type_t type);
/** \brief Ignore all objects that do not bring any structure.
*
* Ignore all objects that do not bring any structure:
* Each ignored object should have a single children or be the only child of its parent.
*/
HWLOC_DECLSPEC int hwloc_topology_ignore_all_keep_structure(hwloc_topology_t topology);
/** \brief Flags to be set onto a topology context before load.
*
* Flags should be given to hwloc_topology_set_flags().
*/
enum hwloc_topology_flags_e {
HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM = (1<<0),
/**< \brief Detect the whole system, ignore reservations and offline settings.
* \hideinitializer
*
* Gather all resources, even if some were disabled by the administrator.
* For instance, ignore Linux Cpusets and gather all processors and memory nodes,
* and ignore the fact that some resources may be offline.
*/
HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM = (1<<1)
/**< \brief Assume that the selected backend provides the topology for the
* system on which we are running.
* \hideinitializer
*
* This forces hwloc_topology_is_thissystem to return 1, i.e. makes hwloc assume that
* the selected backend provides the topology for the system on which we are running,
* even if it is not the OS-specific backend but the XML backend for instance.
* This means making the binding functions actually call the OS-specific
* system calls and really do binding, while the XML backend would otherwise
* provide empty hooks just returning success.
*
* Setting the environment variable HWLOC_THISSYSTEM may also result in the
* same behavior.
*
* This can be used for efficiency reasons to first detect the topology once,
* save it to an XML file, and quickly reload it later through the XML
* backend, but still having binding functions actually do bind.
*/
};
/** \brief Set OR'ed flags to non-yet-loaded topology.
*
* Set a OR'ed set of ::hwloc_topology_flags_e onto a topology that was not yet loaded.
*/
HWLOC_DECLSPEC int hwloc_topology_set_flags (hwloc_topology_t topology, unsigned long flags);
/** \brief Change the file-system root path when building the topology from sysfs/procfs.
*
* On Linux system, use sysfs and procfs files as if they were mounted on the given
* \p fsroot_path instead of the main file-system root. Setting the environment
* variable HWLOC_FSROOT may also result in this behavior.
* Not using the main file-system root causes hwloc_topology_is_thissystem()
* to return 0.
*
* \note For conveniency, this backend provides empty binding hooks which just
* return success. To have hwloc still actually call OS-specific hooks, the
* HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM has to be set to assert that the loaded
* file is really the underlying system.
*/
HWLOC_DECLSPEC int hwloc_topology_set_fsroot(hwloc_topology_t __hwloc_restrict topology, const char * __hwloc_restrict fsroot_path);
/** \brief Change which pid the topology is viewed from
*
* On some systems, processes may have different views of the machine, for
* instance the set of allowed CPUs. By default, hwloc exposes the view from
* the current process. Calling hwloc_topology_set_pid() permits to make it
* expose the topology of the machine from the point of view of another
* process.
*
* \note hwloc_pid_t is pid_t on unix platforms, and HANDLE on native Windows
* platforms
* \note -1 is returned and errno is set to ENOSYS on platforms that do not
* support this feature.
*/
HWLOC_DECLSPEC int hwloc_topology_set_pid(hwloc_topology_t __hwloc_restrict topology, hwloc_pid_t pid);
/** \brief Enable synthetic topology.
*
* Gather topology information from the given \p description
* which should be a space-separated string of numbers describing
* the arity of each level.
* Each number may be prefixed with a type and a colon to enforce the type
* of a level. If only some level types are enforced, hwloc will try to
* choose the other types according to usual topologies, but it may fail
* and you may have to specify more level types manually.
*
* If \p description was properly parsed and describes a valid topology
* configuration, this function returns 0.
* Otherwise -1 is returned and errno is set to EINVAL.
*
* \note For conveniency, this backend provides empty binding hooks which just
* return success.
*/
HWLOC_DECLSPEC int hwloc_topology_set_synthetic(hwloc_topology_t __hwloc_restrict topology, const char * __hwloc_restrict description);
/** \brief Enable XML-file based topology.
*
* Gather topology information from the XML file given at \p xmlpath.
* Setting the environment variable HWLOC_XMLFILE may also result in this behavior.
* This file may have been generated earlier with lstopo file.xml.
*
* \note For conveniency, this backend provides empty binding hooks which just
* return success. To have hwloc still actually call OS-specific hooks, the
* HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM has to be set to assert that the loaded
* file is really the underlying system.
*/
HWLOC_DECLSPEC int hwloc_topology_set_xml(hwloc_topology_t __hwloc_restrict topology, const char * __hwloc_restrict xmlpath);
/** \brief Enable XML based topology using a memory buffer instead of a file.
*
* Gather topology information from the XML memory buffer given at \p buffer
* and of length \p length.
*/
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. */
unsigned char pu;
};
/** \brief Flags describing actual PU binding support for this topology. */
struct hwloc_topology_cpubind_support {
/** Binding the whole current process is supported. */
unsigned char set_thisproc_cpubind;
/** Getting the binding of the whole current process is supported. */
unsigned char get_thisproc_cpubind;
/** Binding a whole given process is supported. */
unsigned char set_proc_cpubind;
/** Getting the binding of a whole given process is supported. */
unsigned char get_proc_cpubind;
/** Binding the current thread only is supported. */
unsigned char set_thisthread_cpubind;
/** Getting the binding of the current thread only is supported. */
unsigned char get_thisthread_cpubind;
/** Binding a given thread only is supported. */
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. */
struct hwloc_topology_membind_support {
/** Binding the whole current process is supported. */
unsigned char set_thisproc_membind;
/** Getting the binding of the whole current process is supported. */
unsigned char get_thisproc_membind;
/** Binding a whole given process is supported. */
unsigned char set_proc_membind;
/** Getting the binding of a whole given process is supported. */
unsigned char get_proc_membind;
/** Binding the current thread only is supported. */
unsigned char set_thisthread_membind;
/** Getting the binding of the current thread only is supported. */
unsigned char get_thisthread_membind;
/** Binding a given memory area is supported. */
unsigned char set_area_membind;
/** Getting the binding of a given memory area is supported. */
unsigned char get_area_membind;
/** Allocating a bound memory area is supported. */
unsigned char alloc_membind;
/** First-touch policy is supported. */
unsigned char firsttouch_membind;
/** Bind policy is supported. */
unsigned char bind_membind;
/** Interleave policy is supported. */
unsigned char interleave_membind;
/** Replication policy is supported. */
unsigned char replicate_membind;
/** Next-touch migration policy is supported. */
unsigned char nexttouch_membind;
/** Migration flags is supported. */
unsigned char migrate_membind;
};
/** \brief Set of flags describing actual support for this topology.
*
* This is retrieved with hwloc_topology_get_support() and will be valid until
* the topology object is destroyed. Note: the values are correct only after
* discovery.
*/
struct hwloc_topology_support {
struct hwloc_topology_discovery_support *discovery;
struct hwloc_topology_cpubind_support *cpubind;
struct hwloc_topology_membind_support *membind;
};
/** \brief Retrieve the topology support. */
HWLOC_DECLSPEC const struct hwloc_topology_support *hwloc_topology_get_support(hwloc_topology_t __hwloc_restrict topology);
/** @} */
/** \defgroup hwlocality_tinker Tinker with topologies.
* @{
*/
/** \brief Export the topology into an XML file.
*
* This file may be loaded later through hwloc_topology_set_xml().
*/
HWLOC_DECLSPEC void hwloc_topology_export_xml(hwloc_topology_t topology, const char *xmlpath);
/** \brief Export the topology into a newly-allocated XML memory buffer.
*
* \p xmlbuffer is allocated by the callee and should be freed with xmlFree later in the caller.
*
* This memory buffer may be loaded later through hwloc_topology_set_xmlbuffer().
*/
HWLOC_DECLSPEC void hwloc_topology_export_xmlbuffer(hwloc_topology_t topology, char **xmlbuffer, int *buflen);
/** \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. This offers a way to add new
* intermediate levels to the topology hierarchy.
*
* \p cpuset and \p name will be copied to setup the new object attributes.
*
* \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 as a leaf of the topology
*
* A new MISC object will be created and inserted into the topology at the
* 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.
*
* \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);
/** @} */
/** \defgroup hwlocality_information Get some Topology Information
* @{
*/
/** \brief Get the depth of the hierachical tree of objects.
*
* This is the depth of HWLOC_OBJ_PU objects plus one.
*/
HWLOC_DECLSPEC unsigned hwloc_topology_get_depth(hwloc_topology_t __hwloc_restrict topology) __hwloc_attribute_pure;
/** \brief Returns the depth of objects of type \p type.
*
* If no object of this type is present on the underlying architecture, or if
* the OS doesn't provide this kind of information, the function returns
* HWLOC_TYPE_DEPTH_UNKNOWN.
*
* If type is absent but a similar type is acceptable, see also
* hwloc_get_type_or_below_depth() and hwloc_get_type_or_above_depth().
*
* If some objects of the given type exist in different levels, for instance
* L1 and L2 caches, the function returns HWLOC_TYPE_DEPTH_MULTIPLE.
*/
HWLOC_DECLSPEC int hwloc_get_type_depth (hwloc_topology_t topology, hwloc_obj_type_t type);
enum hwloc_get_type_depth_e {
HWLOC_TYPE_DEPTH_UNKNOWN = -1, /**< \brief No object of given type exists in the topology. \hideinitializer */
HWLOC_TYPE_DEPTH_MULTIPLE = -2 /**< \brief Objects of given type exist at different depth in the topology. \hideinitializer */
};
/** \brief Returns the type of objects at depth \p depth.
*
* \return -1 if depth \p depth does not exist.
*/
HWLOC_DECLSPEC hwloc_obj_type_t hwloc_get_depth_type (hwloc_topology_t topology, unsigned depth) __hwloc_attribute_pure;
/** \brief Returns the width of level at depth \p depth */
HWLOC_DECLSPEC unsigned hwloc_get_nbobjs_by_depth (hwloc_topology_t topology, unsigned depth) __hwloc_attribute_pure;
/** \brief Returns the width of level type \p type
*
* If no object for that type exists, 0 is returned.
* If there are several levels with objects of that type, -1 is returned.
*/
static __hwloc_inline int __hwloc_attribute_pure
hwloc_get_nbobjs_by_type (hwloc_topology_t topology, hwloc_obj_type_t type)
{
int depth = hwloc_get_type_depth(topology, type);
if (depth == HWLOC_TYPE_DEPTH_UNKNOWN)
return 0;
if (depth == HWLOC_TYPE_DEPTH_MULTIPLE)
return -1; /* FIXME: agregate nbobjs from different levels? */
return hwloc_get_nbobjs_by_depth(topology, depth);
}
/** \brief Does the topology context come from this system?
*
* \return 1 if this topology context was built using the system
* running this program.
* \return 0 instead (for instance if using another file-system root,
* a XML topology file, or a synthetic topology).
*/
HWLOC_DECLSPEC int hwloc_topology_is_thissystem(hwloc_topology_t __hwloc_restrict topology) __hwloc_attribute_pure;
/** @} */
/** \defgroup hwlocality_traversal Retrieve Objects
* @{
*/
/** \brief Returns the topology object at logical index \p idx from depth \p depth */
HWLOC_DECLSPEC hwloc_obj_t hwloc_get_obj_by_depth (hwloc_topology_t topology, unsigned depth, unsigned idx) __hwloc_attribute_pure;
/** \brief Returns the topology object at logical index \p idx with type \p type
*
* If no object for that type exists, \c NULL is returned.
* If there are several levels with objects of that type, \c NULL is returned
* and ther caller may fallback to hwloc_get_obj_by_depth().
*/
static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
hwloc_get_obj_by_type (hwloc_topology_t topology, hwloc_obj_type_t type, unsigned idx)
{
int depth = hwloc_get_type_depth(topology, type);
if (depth == HWLOC_TYPE_DEPTH_UNKNOWN)
return NULL;
if (depth == HWLOC_TYPE_DEPTH_MULTIPLE)
return NULL;
return hwloc_get_obj_by_depth(topology, depth, idx);
}
/** @} */
/** \defgroup hwlocality_conversion Object/String Conversion
* @{
*/
/** \brief Return a stringified topology object type */
HWLOC_DECLSPEC const char * hwloc_obj_type_string (hwloc_obj_type_t type) __hwloc_attribute_const;
/** \brief Return an object type from the string
*
* \return -1 if unrecognized.
*/
HWLOC_DECLSPEC hwloc_obj_type_t hwloc_obj_type_of_string (const char * string) __hwloc_attribute_pure;
/** \brief Stringify the type of a given topology object into a human-readable form.
*
* It differs from hwloc_obj_type_string() because it prints type attributes such
* as cache depth.
*
* If \p size is 0, \p string may safely be \c NULL.
*
* \return the number of character that were actually written if not truncating,
* or that would have been written (not including the ending \\0).
*/
HWLOC_DECLSPEC int hwloc_obj_type_snprintf(char * __hwloc_restrict string, size_t size, hwloc_obj_t obj,
int verbose);
/** \brief Stringify the attributes of a given topology object into a human-readable form.
*
* Attribute values are separated by \p separator.
*
* Only the major attributes are printed in non-verbose mode.
*
* If \p size is 0, \p string may safely be \c NULL.
*
* \return the number of character that were actually written if not truncating,
* or that would have been written (not including the ending \\0).
*/
HWLOC_DECLSPEC int hwloc_obj_attr_snprintf(char * __hwloc_restrict string, size_t size, hwloc_obj_t obj, const char * __hwloc_restrict separator,
int verbose);
/** \brief Stringify a given topology object into a human-readable form.
*
* \note This function is deprecated in favor of hwloc_obj_type_snprintf()
* and hwloc_obj_attr_snprintf() since it is not very flexible and
* only prints physical/OS indexes.
*
* Fill string \p string up to \p size characters with the description
* of topology object \p obj in topology \p topology.
*
* If \p verbose is set, a longer description is used. Otherwise a
* short description is used.
*
* \p indexprefix is used to prefix the \p os_index attribute number of
* the object in the description. If \c NULL, the \c # character is used.
*
* If \p size is 0, \p string may safely be \c NULL.
*
* \return the number of character that were actually written if not truncating,
* or that would have been written (not including the ending \\0).
*/
HWLOC_DECLSPEC int hwloc_obj_snprintf(char * __hwloc_restrict string, size_t size,
hwloc_topology_t topology, hwloc_obj_t obj,
const char * __hwloc_restrict indexprefix, int verbose);
/** \brief Stringify the cpuset containing a set of objects.
*
* If \p size is 0, \p string may safely be \c NULL.
*
* \return the number of character that were actually written if not truncating,
* or that would have been written (not including the ending \\0).
*/
HWLOC_DECLSPEC int hwloc_obj_cpuset_snprintf(char * __hwloc_restrict str, size_t size, size_t nobj, const hwloc_obj_t * __hwloc_restrict objs);
/** \brief Search the given key name in object infos and return the corresponding value.
*
* \return \c NULL if no such key exists.
*/
static __hwloc_inline char * __hwloc_attribute_pure
hwloc_obj_get_info_by_name(hwloc_obj_t obj, const char *name)
{
unsigned i;
for(i=0; i<obj->infos_count; i++)
if (!strcmp(obj->infos[i].name, name))
return obj->infos[i].value;
return NULL;
}
/** @} */
/** \defgroup hwlocality_cpubinding CPU binding
*
* It is often useful to call hwloc_bitmap_singlify() first so that a single CPU
* remains in the set. This way, the process will not even migrate between
* different CPUs. Some operating systems also only support that kind of binding.
*
* \note Some operating systems do not provide all hwloc-supported
* mechanisms to bind processes, threads, etc. and the corresponding
* binding functions may fail. -1 is returned and errno is set to
* ENOSYS when it is not possible to bind the requested kind of object
* processes/threads. errno is set to EXDEV when the requested cpuset
* can not be enforced (e.g. some systems only allow one CPU, and some
* other systems only allow one NUMA node).
*
* The most portable version that should be preferred over the others, whenever
* possible, is
*
* \code
* hwloc_set_cpubind(topology, set, 0),
* \endcode
*
* as it just binds the current program, assuming it is single-threaded, or
*
* \code
* hwloc_set_cpubind(topology, set, HWLOC_CPUBIND_THREAD),
* \endcode
*
* which binds the current thread of the current program (which may be
* multithreaded).
*
* \note To unbind, just call the binding function with either a full cpuset or
* a cpuset equal to the system cpuset.
*
* \note On some operating systems, CPU binding may have effects on memory binding, see
* ::HWLOC_CPUBIND_NOMEMBIND
*
* Running lstopo --top can be a very convenient tool to check how binding
* actually happened.
* @{
*/
/** \brief Process/Thread binding flags.
*
* These bit flags can be used to refine the binding policy.
*
* The default (0) is to bind the current process, assumed to be
* single-threaded, in a non-strict way. This is the most portable
* way to bind as all operating systems usually provide it.
*
* \note Not all systems support all kinds of binding. See the
* "Detailed Description" section of \ref hwlocality_cpubinding for a
* description of errors that can occur.
*/
typedef enum {
HWLOC_CPUBIND_PROCESS = (1<<0), /**< \brief Bind all threads of the current
* (possibly) multithreaded process.
* \hideinitializer */
HWLOC_CPUBIND_THREAD = (1<<1), /**< \brief Bind current thread of current process.
* \hideinitializer */
HWLOC_CPUBIND_STRICT = (1<<2), /**< \brief Request for strict binding from the OS.
* \hideinitializer
*
* By default, when the designated CPUs are
* all busy while other CPUs are idle, operating systems
* may execute the thread/process on those
* other CPUs instead of the designated CPUs,
* to let them progress anyway. Strict
* binding means that the thread/process will
* _never_ execute on other cpus than the
* designated CPUs, even when those are busy
* with other tasks and other CPUs are idle.
*
* \note Depending on the operating system,
* strict binding may not be
* possible (e.g., the OS does not implement it) or not
* allowed (e.g., for an administrative reasons), and the
* function will fail in that case.
*
* When retrieving the binding of a process,
* this flag checks whether all its threads
* actually have the same binding.
* If the flag is not given, the binding of
* each thread will be accumulated.
*
* \note This flag is meaningless when retrieving
* the binding of a thread.
*/
HWLOC_CPUBIND_NOMEMBIND = (1<<3)/**< \brief Avoid any effect on memory binding
* \hideinitializer
*
* On some operating systems, some CPU binding function
* would also bind the memory on the
* corresponding NUMA node. It is often not
* a problem for the application, but if it
* is, setting this flag will make hwloc
* avoid using OS functions that would also
* bind memory. This will however reduce the
* support of CPU bindings, i.e. potentially
* return -1 with errno set to ENOSYS in some
* cases.
*/
} hwloc_cpubind_flags_t;
/** \brief Bind current process or thread on cpus given in bitmap \p set
*
* \return -1 with errno set to ENOSYS if the action is not supported
* \return -1 with errno set to EXDEV if the binding cannot be enforced
*/
HWLOC_DECLSPEC int hwloc_set_cpubind(hwloc_topology_t topology, hwloc_const_cpuset_t set, int flags);
/** \brief Get current process or thread binding
*
* Writes into \p set the cpuset which the process or thread (according to \e
* flags) was last bound to.
*/
HWLOC_DECLSPEC int hwloc_get_cpubind(hwloc_topology_t topology, hwloc_cpuset_t set, int flags);
/** \brief Bind a process \p pid on cpus given in bitmap \p set
*
* \note hwloc_pid_t is pid_t on unix platforms, and HANDLE on native Windows
* platforms
*
* \note HWLOC_CPUBIND_THREAD can not be used in \p flags.
*/
HWLOC_DECLSPEC int hwloc_set_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_cpuset_t set, int flags);
/** \brief Get the current binding of process \p pid
*
* \note hwloc_pid_t is pid_t on unix platforms, and HANDLE on native Windows
* platforms
*
* \note HWLOC_CPUBIND_THREAD can not be used in \p flags.
*/
HWLOC_DECLSPEC int hwloc_get_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_cpuset_t set, int flags);
#ifdef hwloc_thread_t
/** \brief Bind a thread \p thread on cpus given in bitmap \p set
*
* \note hwloc_thread_t is pthread_t on unix platforms, and HANDLE on native
* Windows platforms
*
* \note HWLOC_CPUBIND_PROCESS can not be used in \p flags.
*/
HWLOC_DECLSPEC int hwloc_set_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t thread, hwloc_const_cpuset_t set, int flags);
#endif
#ifdef hwloc_thread_t
/** \brief Get the current binding of thread \p tid
*
* \note hwloc_thread_t is pthread_t on unix platforms, and HANDLE on native
* Windows platforms
*
* \note HWLOC_CPUBIND_PROCESS can not be used in \p flags.
*/
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);
/** @} */
/** \defgroup hwlocality_membinding Memory binding
*
* \note Not all operating systems support all ways to bind existing
* allocated memory (e.g., migration), future memory allocation,
* explicit memory allocation, etc. Using a binding flag or policy
* that is not supported by the underlying OS will cause hwloc's
* binding functions to fail and return -1. errno will be set to
* ENOSYS when the system does support the specified action or policy
* (e.g., some systems only allow binding memory on a per-thread
* basis, whereas other systems only allow binding memory for all
* threads in a process). errno will be set to EXDEV when the
* requested cpuset can not be enforced (e.g., some systems only allow
* binding memory to a single NUMA node).
*
* The most portable form that should be preferred over the others
* whenever possible is as follows:
*
* \code
* hwloc_alloc_membind_policy(topology, size, set,
* HWLOC_MEMBIND_DEFAULT, 0);
* \endcode
*
* This will allocate some memory hopefully bound to the specified set.
* To do so, hwloc will possibly have to change the current memory
* binding policy in order to actually get the memory bound, if the OS
* does not provide any other way to simply allocate bound memory
* without changing the policy for all allocations. That is the
* difference with hwloc_alloc_membind(), which will never change the
* current memory binding policy. Note that since HWLOC_MEMBIND_STRICT
* was not specified, failures to bind will not be reported --
* generally, only memory allocation failures will be reported (e.g.,
* even a plain malloc() would have failed with ENOMEM).
*
* Each hwloc memory binding function is available in two forms: one
* that takes a CPU set argument and another that takes a NUMA memory
* node set argument (see \ref hwlocality_sets and \ref
* hwlocality_bitmap for a discussion of CPU sets and NUMA memory node
* sets). The names of the latter form end with _nodeset. It is also
* possible to convert between CPU set and node set using
* hwloc_cpuset_to_nodeset() or hwloc_cpuset_from_nodeset().
*
* \note On some operating systems, memory binding affects the CPU
* binding; see ::HWLOC_MEMBIND_NOCPUBIND
* @{
*/
/** \brief Memory binding policy.
*
* These constants can be used to choose the binding policy. Only one policy can
* be used at a time (i.e., the values cannot be OR'ed together).
*
* \note Not all systems support all kinds of binding. See the
* "Detailed Description" section of \ref hwlocality_membinding for a
* description of errors that can occur.
*/
typedef enum {
HWLOC_MEMBIND_DEFAULT = 0, /**< \brief Reset the memory allocation policy to the system default.
* \hideinitializer */
HWLOC_MEMBIND_FIRSTTOUCH = 1, /**< \brief Allocate memory
* but do not immediately bind
* it to a specific locality.
* Instead, each page in the
* allocation is bound only
* when it is first touched.
* Pages are individually
* bound to the local NUMA
* node of the first thread
* that touches it.
* \hideinitializer */
HWLOC_MEMBIND_BIND = 2, /**< \brief Allocate memory on the specified nodes.
* \hideinitializer */
HWLOC_MEMBIND_INTERLEAVE = 3, /**< \brief Allocate memory on
* the given nodes in an
* interleaved / round-robin
* manner. The precise layout
* of the memory across
* multiple NUMA nodes is
* OS/system specific.
* Interleaving can be useful
* when threads distributed across
* the specified NUMA nodes
* will all be accessing the whole
* memory range concurrently, since
* the interleave will then balance
* the memory references.
* \hideinitializer */
HWLOC_MEMBIND_REPLICATE = 4, /**< \brief Replicate memory
* on the given nodes; reads
* from this memory will
* attempt to be serviced from
* the NUMA node local to the
* reading thread.
* Replicating can be useful
* when multiple threads from
* the specified NUMA nodes
* will be sharing the same
* read-only data.
*
* This policy can only be
* used with existing memory
* allocations (i.e., the
* hwloc_set_*membind*()
* functions); it cannot be
* used with functions that
* allocate new memory (i.e.,
* the hwloc_alloc*()
* functions).
* \hideinitializer */
HWLOC_MEMBIND_NEXTTOUCH = 5, /**< \brief For each page bound
* with this policy, by next time
* it is touched (and next time only),
* it is moved from
* its current location to the
* local NUMA node of the
* thread where the memory
* reference occurred (if it
* needs to be moved at all).
* \hideinitializer */
HWLOC_MEMBIND_MIXED = -1 /**< \brief Returned by hwloc_get_membind*()
* functions when multiple threads or
* parts of a memory area have
* differing memory binding policies.
* \hideinitializer */
} hwloc_membind_policy_t;
/** \brief Memory binding flags.
*
* These flags can be used to refine the binding policy. All flags
* can be logically OR'ed together with the exception of
* HWLOC_MEMBIND_PROCESS and HWLOC_MEMBIND_THREAD; these two flags are
* mutually exclusive.
*
* \note Not all systems support all kinds of binding. See the
* "Detailed Description" section of \ref hwlocality_membinding for a
* description of errors that can occur.
*/
typedef enum {
HWLOC_MEMBIND_PROCESS = (1<<0), /**< \brief Set policy for all
* threads of the specified
* (possibly multithreaded)
* process. This flag is
* mutually exclusive with
* HWLOC_MEMBIND_THREAD.
* \hideinitializer */
HWLOC_MEMBIND_THREAD = (1<<1), /**< \brief Set policy for a
* specific thread of the
* current process. This flag
* is mutually exclusive with
* HWLOC_MEMBIND_PROCESS.
* \hideinitializer */
HWLOC_MEMBIND_STRICT = (1<<2), /**< Request strict binding
* from the OS. The function
* will fail if the binding
* can not be guaranteed /
* completely enforced.
*
* This flag has slightly
* different meanings
* depending on which function
* it is used with.
* \hideinitializer */
HWLOC_MEMBIND_MIGRATE = (1<<3), /**< \brief Migrate existing
* allocated memory. If the
* memory cannot be migrated
* and the
* HWLOC_MEMBIND_STRICT flag
* is passed, an error will be
* returned.
* \hideinitializer */
HWLOC_MEMBIND_NOCPUBIND = (1<<4) /**< \brief Avoid any effect
* on CPU binding.
*
* On some operating systems,
* some underlying memory
* binding functions also bind
* the application to the
* corresponding CPU(s).
* Using this flag will cause
* hwloc to avoid using OS
* functions that could
* potentially affect CPU
* bindings. Note, however,
* that using NOCPUBIND may
* reduce hwloc's overall
* memory binding support.
* Specifically: some of
* hwloc's memory binding
* functions may fail with
* errno set to ENOSYS when
* used with NOCPUBIND.
* \hideinitializer
*/
} hwloc_membind_flags_t;
/** \brief Set the default memory binding policy of the current
* process or thread to prefer the NUMA node(s) specified by \p nodeset
*
* If neither HWLOC_MEMBIND_PROCESS nor HWLOC_MEMBIND_THREAD is
* specified, the current process is assumed to be single-threaded.
* This is the most portable form as it permits hwloc to use either
* process-based OS functions or thread-based OS functions, depending
* on which are available.
*
* \return -1 with errno set to ENOSYS if the action is not supported
* \return -1 with errno set to EXDEV if the binding cannot be enforced
*/
HWLOC_DECLSPEC int hwloc_set_membind_nodeset(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags);
/** \brief Set the default memory binding policy of the current
* process or thread to prefer the NUMA node(s) near the specified \p
* cpuset
*
* If neither HWLOC_MEMBIND_PROCESS nor HWLOC_MEMBIND_THREAD is
* specified, the current process is assumed to be single-threaded.
* This is the most portable form as it permits hwloc to use either
* process-based OS functions or thread-based OS functions, depending
* on which are available.
*
* \return -1 with errno set to ENOSYS if the action is not supported
* \return -1 with errno set to EXDEV if the binding cannot be enforced
*/
HWLOC_DECLSPEC int hwloc_set_membind(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags);
/** \brief Query the default memory binding policy and locality of the
* current process or thread.
*
* This function has two output parameters: \p nodeset and \p policy.
* The values returned in these parameters depend on both the \p flags
* passed in and the current memory binding policies and nodesets in
* the queried target.
*
* Passing the HWLOC_MEMBIND_PROCESS flag specifies that the query
* target is the current policies and nodesets for all the threads in
* the current process. Passing HWLOC_MEMBIND_THREAD specifies that
* the query target is the current policy and nodeset for only the
* thread invoking this function.
*
* If neither of these flags are passed (which is the most portable
* method), the process is assumed to be single threaded. This allows
* hwloc to use either process-based OS functions or thread-based OS
* functions, depending on which are available.
*
* HWLOC_MEMBIND_STRICT is only meaningful when HWLOC_MEMBIND_PROCESS
* is also specified. In this case, hwloc will check the default
* memory policies and nodesets for all threads in the process. If
* they are not identical, -1 is returned and errno is set to EXDEV.
* If they are identical, the values are returned in \p nodeset and \p
* policy.
*
* Otherwise, if HWLOC_MEMBIND_PROCESS is specified (and
* HWLOC_MEMBIND_STRICT is \em not specified), \p nodeset is set to
* the logical OR of all threads' default nodeset. If all threads'
* default policies are the same, \p policy is set to that policy. If
* they are different, \p policy is set to HWLOC_MEMBIND_MIXED.
*
* In the HWLOC_MEMBIND_THREAD case (or when neither
* HWLOC_MEMBIND_PROCESS or HWLOC_MEMBIND_THREAD is specified), there
* is only one nodeset and policy; they are returned in \p nodeset and
* \p policy, respectively.
*
* If any other flags are specified, -1 is returned and errno is set
* to EINVAL.
*/
HWLOC_DECLSPEC int hwloc_get_membind_nodeset(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags);
/** \brief Query the default memory binding policy and locality of the
* current process or thread (the locality is returned in \p cpuset as
* CPUs near the locality's actual NUMA node(s)).
*
* This function has two output parameters: \p cpuset and \p policy.
* The values returned in these parameters depend on both the \p flags
* passed in and the current memory binding policies and nodesets in
* the queried target.
*
* Passing the HWLOC_MEMBIND_PROCESS flag specifies that the query
* target is the current policies and nodesets for all the threads in
* the current process. Passing HWLOC_MEMBIND_THREAD specifies that
* the query target is the current policy and nodeset for only the
* thread invoking this function.
*
* If neither of these flags are passed (which is the most portable
* method), the process is assumed to be single threaded. This allows
* hwloc to use either process-based OS functions or thread-based OS
* functions, depending on which are available.
*
* HWLOC_MEMBIND_STRICT is only meaningful when HWLOC_MEMBIND_PROCESS
* is also specified. In this case, hwloc will check the default
* memory policies and nodesets for all threads in the process. If
* they are not identical, -1 is returned and errno is set to EXDEV.
* If they are identical, the policy is returned in \p policy. \p
* cpuset is set to the union of CPUs near the NUMA node(s) in the
* nodeset.
*
* Otherwise, if HWLOC_MEMBIND_PROCESS is specified (and
* HWLOC_MEMBIND_STRICT is \em not specified), the default nodeset
* from each thread is logically OR'ed together. \p cpuset is set to
* the union of CPUs near the NUMA node(s) in the resulting nodeset.
* If all threads' default policies are the same, \p policy is set to
* that policy. If they are different, \p policy is set to
* HWLOC_MEMBIND_MIXED.
*
* In the HWLOC_MEMBIND_THREAD case (or when neither
* HWLOC_MEMBIND_PROCESS or HWLOC_MEMBIND_THREAD is specified), there
* is only one nodeset and policy. The policy is returned in \p
* policy; \p cpuset is set to the union of CPUs near the NUMA node(s)
* in the \p nodeset.
*
* If any other flags are specified, -1 is returned and errno is set
* to EINVAL.
*/
HWLOC_DECLSPEC int hwloc_get_membind(hwloc_topology_t topology, hwloc_cpuset_t cpuset, hwloc_membind_policy_t * policy, int flags);
/** \brief Set the default memory binding policy of the specified
* process to prefer the NUMA node(s) specified by \p nodeset
*
* \return -1 with errno set to ENOSYS if the action is not supported
* \return -1 with errno set to EXDEV if the binding cannot be enforced
*/
HWLOC_DECLSPEC int hwloc_set_proc_membind_nodeset(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags);
/** \brief Set the default memory binding policy of the specified
* process to prefer the NUMA node(s) near the specified \p cpuset
*
* \return -1 with errno set to ENOSYS if the action is not supported
* \return -1 with errno set to EXDEV if the binding cannot be enforced
*/
HWLOC_DECLSPEC int hwloc_set_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags);
/** \brief Query the default memory binding policy and locality of the
* specified process.
*
* This function has two output parameters: \p nodeset and \p policy.
* The values returned in these parameters depend on both the \p flags
* passed in and the current memory binding policies and nodesets in
* the queried target.
*
* Passing the HWLOC_MEMBIND_PROCESS flag specifies that the query
* target is the current policies and nodesets for all the threads in
* the specified process. If HWLOC_MEMBIND_PROCESS is not specified
* (which is the most portable method), the process is assumed to be
* single threaded. This allows hwloc to use either process-based OS
* functions or thread-based OS functions, depending on which are
* available.
*
* Note that it does not make sense to pass HWLOC_MEMBIND_THREAD to
* this function.
*
* If HWLOC_MEMBIND_STRICT is specified, hwloc will check the default
* memory policies and nodesets for all threads in the specified
* process. If they are not identical, -1 is returned and errno is
* set to EXDEV. If they are identical, the values are returned in \p
* nodeset and \p policy.
*
* Otherwise, \p nodeset is set to the logical OR of all threads'
* default nodeset. If all threads' default policies are the same, \p
* policy is set to that policy. If they are different, \p policy is
* set to HWLOC_MEMBIND_MIXED.
*
* If any other flags are specified, -1 is returned and errno is set
* to EINVAL.
*/
HWLOC_DECLSPEC int hwloc_get_proc_membind_nodeset(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags);
/** \brief Query the default memory binding policy and locality of the
* specified process (the locality is returned in \p cpuset as CPUs
* near the locality's actual NUMA node(s)).
*
* This function has two output parameters: \p cpuset and \p policy.
* The values returned in these parameters depend on both the \p flags
* passed in and the current memory binding policies and nodesets in
* the queried target.
*
* Passing the HWLOC_MEMBIND_PROCESS flag specifies that the query
* target is the current policies and nodesets for all the threads in
* the specified process. If HWLOC_MEMBIND_PROCESS is not specified
* (which is the most portable method), the process is assumed to be
* single threaded. This allows hwloc to use either process-based OS
* functions or thread-based OS functions, depending on which are
* available.
*
* Note that it does not make sense to pass HWLOC_MEMBIND_THREAD to
* this function.
*
* If HWLOC_MEMBIND_STRICT is specified, hwloc will check the default
* memory policies and nodesets for all threads in the specified
* process. If they are not identical, -1 is returned and errno is
* set to EXDEV. If they are identical, the policy is returned in \p
* policy. \p cpuset is set to the union of CPUs near the NUMA
* node(s) in the nodeset.
*
* Otherwise, the default nodeset from each thread is logically OR'ed
* together. \p cpuset is set to the union of CPUs near the NUMA
* node(s) in the resulting nodeset. If all threads' default policies
* are the same, \p policy is set to that policy. If they are
* different, \p policy is set to HWLOC_MEMBIND_MIXED.
*
* If any other flags are specified, -1 is returned and errno is set
* to EINVAL.
*/
HWLOC_DECLSPEC int hwloc_get_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_cpuset_t cpuset, hwloc_membind_policy_t * policy, int flags);
/** \brief Bind the already-allocated memory identified by (addr, len)
* to the NUMA node(s) in \p nodeset.
*
* \return -1 with errno set to ENOSYS if the action is not supported
* \return -1 with errno set to EXDEV if the binding cannot be enforced
*/
HWLOC_DECLSPEC int hwloc_set_area_membind_nodeset(hwloc_topology_t topology, const void *addr, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags);
/** \brief Bind the already-allocated memory identified by (addr, len)
* to the NUMA node(s) near \p cpuset.
*
* \return -1 with errno set to ENOSYS if the action is not supported
* \return -1 with errno set to EXDEV if the binding cannot be enforced
*/
HWLOC_DECLSPEC int hwloc_set_area_membind(hwloc_topology_t topology, const void *addr, size_t len, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags);
/** \brief Query the NUMA node(s) and binding policy of the memory
* identified by (\p addr, \p len ).
*
* This function has two output parameters: \p nodeset and \p policy.
* The values returned in these parameters depend on both the \p flags
* passed in and the memory binding policies and nodesets of the pages
* in the address range.
*
* If HWLOC_MEMBIND_STRICT is specified, the target pages are first
* checked to see if they all have the same memory binding policy and
* nodeset. If they do not, -1 is returned and errno is set to EXDEV.
* If they are identical across all pages, the nodeset and policy are
* returned in \p nodeset and \p policy, respectively.
*
* If HWLOC_MEMBIND_STRICT is not specified, \p nodeset is set to the
* union of all NUMA node(s) containing pages in the address range.
* If all pages in the target have the same policy, it is returned in
* \p policy. Otherwise, \p policy is set to HWLOC_MEMBIND_MIXED.
*
* If any other flags are specified, -1 is returned and errno is set
* to EINVAL.
*/
HWLOC_DECLSPEC int hwloc_get_area_membind_nodeset(hwloc_topology_t topology, const void *addr, size_t len, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags);
/** \brief Query the CPUs near the NUMA node(s) and binding policy of
* the memory identified by (\p addr, \p len ).
*
* This function has two output parameters: \p cpuset and \p policy.
* The values returned in these parameters depend on both the \p flags
* passed in and the memory binding policies and nodesets of the pages
* in the address range.
*
* If HWLOC_MEMBIND_STRICT is specified, the target pages are first
* checked to see if they all have the same memory binding policy and
* nodeset. If they do not, -1 is returned and errno is set to EXDEV.
* If they are identical across all pages, the policy is returned in
* \p policy. \p cpuset is set to the union of CPUs near the NUMA
* node(s) in the nodeset.
*
* If HWLOC_MEMBIND_STRICT is not specified, the union of all NUMA
* node(s) containing pages in the address range is calculated. \p
* cpuset is then set to the CPUs near the NUMA node(s) in this union.
* If all pages in the target have the same policy, it is returned in
* \p policy. Otherwise, \p policy is set to HWLOC_MEMBIND_MIXED.
*
* If any other flags are specified, -1 is returned and errno is set
* to EINVAL.
*/
HWLOC_DECLSPEC int hwloc_get_area_membind(hwloc_topology_t topology, const void *addr, size_t len, hwloc_cpuset_t cpuset, hwloc_membind_policy_t * policy, int flags);
/** \brief Allocate some memory
*
* This is equivalent to malloc(), except that it tries to allocate
* page-aligned memory from the OS.
*
* \note The allocated memory should be freed with hwloc_free().
*/
HWLOC_DECLSPEC void *hwloc_alloc(hwloc_topology_t topology, size_t len);
/** \brief Allocate some memory on the given nodeset \p nodeset
*
* \return -1 with errno set to ENOSYS if the action is not supported
* and HWLOC_MEMBIND_STRICT is given
* \return -1 with errno set to EXDEV if the binding cannot be enforced
* and HWLOC_MEMBIND_STRICT is given
*
* \note The allocated memory should be freed with hwloc_free().
*/
HWLOC_DECLSPEC void *hwloc_alloc_membind_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) __hwloc_attribute_malloc;
/** \brief Allocate some memory on memory nodes near the given cpuset \p cpuset
*
* \return -1 with errno set to ENOSYS if the action is not supported
* and HWLOC_MEMBIND_STRICT is given
* \return -1 with errno set to EXDEV if the binding cannot be enforced
* and HWLOC_MEMBIND_STRICT is given
*
* \note The allocated memory should be freed with hwloc_free().
*/
HWLOC_DECLSPEC void *hwloc_alloc_membind(hwloc_topology_t topology, size_t len, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags) __hwloc_attribute_malloc;
/** \brief Free memory that was previously allocated by hwloc_alloc()
* or hwloc_alloc_membind().
*/
HWLOC_DECLSPEC int hwloc_free(hwloc_topology_t topology, void *addr, size_t len);
/** @} */
#ifdef __cplusplus
} /* extern "C" */
#endif
/* high-level helpers */
#include <hwloc/helper.h>
#endif /* HWLOC_H */
/* hwloc-1.2.1/include/hwloc/autogen/config.h. Generated from config.h.in by configure. */
/* -*- c -*-
* Copyright © 2009 CNRS
* 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.
*/
/* The configuration file */
#ifndef HWLOC_CONFIG_H
#define HWLOC_CONFIG_H
#if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95))
# define __hwloc_restrict __restrict
#else
# if __STDC_VERSION__ >= 199901L
# define __hwloc_restrict restrict
# else
# define __hwloc_restrict
# endif
#endif
#define __hwloc_inline __inline__
/*
* Note: this is public. We can not assume anything from the compiler used
* by the application and thus the HWLOC_HAVE_* macros below are not
* fetched from the autoconf result here. We only automatically use a few
* well-known easy cases.
*/
/* Maybe before gcc 2.95 too */
#if defined(HWLOC_HAVE_ATTRIBUTE_UNUSED) || (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95))
# if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)) || HWLOC_HAVE_ATTRIBUTE_UNUSED
# define __hwloc_attribute_unused __attribute__((__unused__))
# else
# define __hwloc_attribute_unused
# endif
#else
# define __hwloc_attribute_unused
#endif
#if defined(HWLOC_HAVE_ATTRIBUTE_MALLOC) || (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96))
# if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)) || HWLOC_HAVE_ATTRIBUTE_MALLOC
# define __hwloc_attribute_malloc __attribute__((__malloc__))
# else
# define __hwloc_attribute_malloc
# endif
#else
# define __hwloc_attribute_malloc
#endif
#if defined(HWLOC_HAVE_ATTRIBUTE_CONST) || (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95))
# if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)) || HWLOC_HAVE_ATTRIBUTE_CONST
# define __hwloc_attribute_const __attribute__((__const__))
# else
# define __hwloc_attribute_const
# endif
#else
# define __hwloc_attribute_const
#endif
#if defined(HWLOC_HAVE_ATTRIBUTE_PURE) || (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96))
# if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)) || HWLOC_HAVE_ATTRIBUTE_PURE
# define __hwloc_attribute_pure __attribute__((__pure__))
# else
# define __hwloc_attribute_pure
# endif
#else
# define __hwloc_attribute_pure
#endif
#if defined(HWLOC_HAVE_ATTRIBUTE_DEPRECATED) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3))
# if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) || HWLOC_HAVE_ATTRIBUTE_DEPRECATED
# define __hwloc_attribute_deprecated __attribute__((__deprecated__))
# else
# define __hwloc_attribute_deprecated
# endif
#else
# define __hwloc_attribute_deprecated
#endif
#ifdef HWLOC_C_HAVE_VISIBILITY
# if HWLOC_C_HAVE_VISIBILITY
# define HWLOC_DECLSPEC __attribute__((__visibility__("default")))
# else
# define HWLOC_DECLSPEC
# endif
#else
# define HWLOC_DECLSPEC
#endif
/* Defined to 1 on Linux */
#define HWLOC_LINUX_SYS 1
/* Defined to 1 if the CPU_SET macro works */
#define HWLOC_HAVE_CPU_SET 1
/* Defined to 1 if you have the `windows.h' header. */
/* #undef HWLOC_HAVE_WINDOWS_H */
#define hwloc_pid_t pid_t
#define hwloc_thread_t pthread_t
#ifdef HWLOC_HAVE_WINDOWS_H
# include <windows.h>
typedef DWORDLONG hwloc_uint64_t;
#else /* HWLOC_HAVE_WINDOWS_H */
# ifdef hwloc_thread_t
# include <pthread.h>
# endif /* hwloc_thread_t */
/* Defined to 1 if you have the <stdint.h> header file. */
# define HWLOC_HAVE_STDINT_H 1
# include <unistd.h>
# ifdef HWLOC_HAVE_STDINT_H
# include <stdint.h>
# endif
typedef uint64_t hwloc_uint64_t;
#endif /* HWLOC_HAVE_WINDOWS_H */
/* Whether we need to re-define all the hwloc public symbols or not */
#define HWLOC_SYM_TRANSFORM 0
/* The hwloc symbol prefix */
#define HWLOC_SYM_PREFIX hwloc_
/* The hwloc symbol prefix in all caps */
#define HWLOC_SYM_PREFIX_CAPS HWLOC_
#endif /* HWLOC_CONFIG_H */
/* -*- c -*-
* Copyright © 2009 CNRS
* 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.
*/
/* The configuration file */
#ifndef HWLOC_CONFIG_H
#define HWLOC_CONFIG_H
#if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95))
# define __hwloc_restrict __restrict
#else
# if __STDC_VERSION__ >= 199901L
# define __hwloc_restrict restrict
# else
# define __hwloc_restrict
# endif
#endif
#undef __hwloc_inline
/*
* Note: this is public. We can not assume anything from the compiler used
* by the application and thus the HWLOC_HAVE_* macros below are not
* fetched from the autoconf result here. We only automatically use a few
* well-known easy cases.
*/
/* Maybe before gcc 2.95 too */
#if defined(HWLOC_HAVE_ATTRIBUTE_UNUSED) || (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95))
# if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)) || HWLOC_HAVE_ATTRIBUTE_UNUSED
# define __hwloc_attribute_unused __attribute__((__unused__))
# else
# define __hwloc_attribute_unused
# endif
#else
# define __hwloc_attribute_unused
#endif
#if defined(HWLOC_HAVE_ATTRIBUTE_MALLOC) || (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96))
# if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)) || HWLOC_HAVE_ATTRIBUTE_MALLOC
# define __hwloc_attribute_malloc __attribute__((__malloc__))
# else
# define __hwloc_attribute_malloc
# endif
#else
# define __hwloc_attribute_malloc
#endif
#if defined(HWLOC_HAVE_ATTRIBUTE_CONST) || (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95))
# if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)) || HWLOC_HAVE_ATTRIBUTE_CONST
# define __hwloc_attribute_const __attribute__((__const__))
# else
# define __hwloc_attribute_const
# endif
#else
# define __hwloc_attribute_const
#endif
#if defined(HWLOC_HAVE_ATTRIBUTE_PURE) || (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96))
# if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)) || HWLOC_HAVE_ATTRIBUTE_PURE
# define __hwloc_attribute_pure __attribute__((__pure__))
# else
# define __hwloc_attribute_pure
# endif
#else
# define __hwloc_attribute_pure
#endif
#if defined(HWLOC_HAVE_ATTRIBUTE_DEPRECATED) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3))
# if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) || HWLOC_HAVE_ATTRIBUTE_DEPRECATED
# define __hwloc_attribute_deprecated __attribute__((__deprecated__))
# else
# define __hwloc_attribute_deprecated
# endif
#else
# define __hwloc_attribute_deprecated
#endif
#ifdef HWLOC_C_HAVE_VISIBILITY
# if HWLOC_C_HAVE_VISIBILITY
# define HWLOC_DECLSPEC __attribute__((__visibility__("default")))
# else
# define HWLOC_DECLSPEC
# endif
#else
# define HWLOC_DECLSPEC
#endif
/* Defined to 1 on Linux */
#undef HWLOC_LINUX_SYS
/* Defined to 1 if the CPU_SET macro works */
#undef HWLOC_HAVE_CPU_SET
/* Defined to 1 if you have the `windows.h' header. */
#undef HWLOC_HAVE_WINDOWS_H
#undef hwloc_pid_t
#undef hwloc_thread_t
#ifdef HWLOC_HAVE_WINDOWS_H
# include <windows.h>
typedef DWORDLONG hwloc_uint64_t;
#else /* HWLOC_HAVE_WINDOWS_H */
# ifdef hwloc_thread_t
# include <pthread.h>
# endif /* hwloc_thread_t */
/* Defined to 1 if you have the <stdint.h> header file. */
# undef HWLOC_HAVE_STDINT_H
# include <unistd.h>
# ifdef HWLOC_HAVE_STDINT_H
# include <stdint.h>
# endif
typedef uint64_t hwloc_uint64_t;
#endif /* HWLOC_HAVE_WINDOWS_H */
/* Whether we need to re-define all the hwloc public symbols or not */
#undef HWLOC_SYM_TRANSFORM
/* The hwloc symbol prefix */
#undef HWLOC_SYM_PREFIX
/* The hwloc symbol prefix in all caps */
#undef HWLOC_SYM_PREFIX_CAPS
#endif /* HWLOC_CONFIG_H */
timestamp for hwloc-1.2.1/include/hwloc/autogen/config.h
/*
* Copyright © 2009 CNRS
* 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.
*/
/** \file
* \brief The bitmap API, for use in hwloc itself.
*/
#ifndef HWLOC_BITMAP_H
#define HWLOC_BITMAP_H
#include <hwloc/autogen/config.h>
#include <assert.h>
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup hwlocality_bitmap The bitmap API
*
* The ::hwloc_bitmap_t type represents a set of objects, typically OS
* processors -- which may actually be hardware threads (represented
* by ::hwloc_cpuset_t, which is a typedef for ::hwloc_bitmap_t) -- or
* memory nodes (represented by ::hwloc_nodeset_t, which is also a
* typedef for ::hwloc_bitmap_t).
*
* <em>Both CPU and node sets are always indexed by OS physical number.</em>
*
* \note CPU sets and nodesets are described in \ref hwlocality_sets.
*
* A bitmap may be of infinite size.
* @{
*/
/** \brief
* Set of bits represented as an opaque pointer to an internal bitmap.
*/
typedef struct hwloc_bitmap_s * hwloc_bitmap_t;
/** \brief a non-modifiable ::hwloc_bitmap_t */
typedef const struct hwloc_bitmap_s * hwloc_const_bitmap_t;
/*
* Bitmap allocation, freeing and copying.
*/
/** \brief Allocate a new empty bitmap.
*
* \returns A valid bitmap or \c NULL.
*
* The bitmap should be freed by a corresponding call to
* hwloc_bitmap_free().
*/
HWLOC_DECLSPEC hwloc_bitmap_t hwloc_bitmap_alloc(void) __hwloc_attribute_malloc;
/** \brief Allocate a new full bitmap. */
HWLOC_DECLSPEC hwloc_bitmap_t hwloc_bitmap_alloc_full(void) __hwloc_attribute_malloc;
/** \brief Free bitmap \p bitmap.
*
* If \p bitmap is \c NULL, no operation is performed.
*/
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.
*
* 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 */
HWLOC_DECLSPEC void hwloc_bitmap_copy(hwloc_bitmap_t dst, hwloc_const_bitmap_t src);
/*
* Bitmap/String Conversion
*/
/** \brief Stringify a bitmap.
*
* 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_snprintf(char * __hwloc_restrict buf, size_t buflen, hwloc_const_bitmap_t bitmap);
/** \brief Stringify a bitmap into a newly allocated string.
*/
HWLOC_DECLSPEC int hwloc_bitmap_asprintf(char ** strp, hwloc_const_bitmap_t bitmap);
/** \brief Parse a bitmap string and stores it in bitmap \p bitmap.
*/
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
* (possible very long) hexadecimal number starting with 0x.
*
* Up to \p buflen characters may be written in buffer \p buf.
*
* If \p buflen is 0, \p buf may safely be \c NULL.
*
* \return the number of character that were actually written if not truncating,
* or that would have been written (not including the ending \\0).
*/
HWLOC_DECLSPEC int hwloc_bitmap_taskset_snprintf(char * __hwloc_restrict buf, size_t buflen, hwloc_const_bitmap_t bitmap);
/** \brief Stringify a bitmap into a newly allocated taskset-specific string.
*/
HWLOC_DECLSPEC int hwloc_bitmap_taskset_asprintf(char ** strp, hwloc_const_bitmap_t bitmap);
/** \brief Parse a taskset-specific bitmap string and stores it in bitmap \p bitmap.
*/
HWLOC_DECLSPEC int hwloc_bitmap_taskset_sscanf(hwloc_bitmap_t bitmap, const char * __hwloc_restrict string);
/*
* Building bitmaps.
*/
/** \brief Empty the bitmap \p bitmap */
HWLOC_DECLSPEC void hwloc_bitmap_zero(hwloc_bitmap_t bitmap);
/** \brief Fill bitmap \p bitmap with all possible indexes (even if those objects don't exist or are otherwise unavailable) */
HWLOC_DECLSPEC void hwloc_bitmap_fill(hwloc_bitmap_t bitmap);
/** \brief Empty the bitmap \p bitmap and add bit \p id */
HWLOC_DECLSPEC void hwloc_bitmap_only(hwloc_bitmap_t bitmap, unsigned id);
/** \brief Fill the bitmap \p and clear the index \p id */
HWLOC_DECLSPEC void hwloc_bitmap_allbut(hwloc_bitmap_t bitmap, unsigned id);
/** \brief Setup bitmap \p bitmap from unsigned long \p mask */
HWLOC_DECLSPEC void hwloc_bitmap_from_ulong(hwloc_bitmap_t bitmap, unsigned long mask);
/** \brief Setup bitmap \p bitmap from unsigned long \p mask used as \p i -th subset */
HWLOC_DECLSPEC void hwloc_bitmap_from_ith_ulong(hwloc_bitmap_t bitmap, unsigned i, unsigned long mask);
/*
* Modifying bitmaps.
*/
/** \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.
*
* 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);
/** \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.
*
* 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
*
* May be useful before binding so that the process does not
* have a chance of migrating between multiple logical CPUs
* in the original mask.
*/
HWLOC_DECLSPEC void hwloc_bitmap_singlify(hwloc_bitmap_t bitmap);
/*
* Consulting bitmaps.
*/
/** \brief Convert the beginning part of bitmap \p bitmap into unsigned long \p mask */
HWLOC_DECLSPEC unsigned long hwloc_bitmap_to_ulong(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
/** \brief Convert the \p i -th subset of bitmap \p bitmap into unsigned long mask */
HWLOC_DECLSPEC unsigned long hwloc_bitmap_to_ith_ulong(hwloc_const_bitmap_t bitmap, unsigned i) __hwloc_attribute_pure;
/** \brief Test whether index \p id is part of bitmap \p bitmap */
HWLOC_DECLSPEC int hwloc_bitmap_isset(hwloc_const_bitmap_t bitmap, unsigned id) __hwloc_attribute_pure;
/** \brief Test whether bitmap \p bitmap is empty */
HWLOC_DECLSPEC int hwloc_bitmap_iszero(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
/** \brief Test whether bitmap \p bitmap is completely full */
HWLOC_DECLSPEC int hwloc_bitmap_isfull(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
/** \brief Compute the first index (least significant bit) in bitmap \p bitmap
*
* \return -1 if no index is set.
*/
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, int prev) __hwloc_attribute_pure;
/** \brief Compute the last index (most significant bit) in bitmap \p bitmap
*
* \return -1 if no index is bitmap, or if the index bitmap is infinite.
*/
HWLOC_DECLSPEC int hwloc_bitmap_last(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
/** \brief Compute the "weight" of bitmap \p bitmap (i.e., number of
* indexes that are in the bitmap).
*
* \return the number of indexes that are in the bitmap.
*/
HWLOC_DECLSPEC int hwloc_bitmap_weight(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
/** \brief Loop macro iterating on bitmap \p bitmap
* \hideinitializer
*
* \p index is the loop variable; it should be an unsigned int. The
* first iteration will set \p index to the lowest index in the bitmap.
* Successive iterations will iterate through, in order, all remaining
* indexes that in the bitmap. To be specific: each iteration will return a
* value for \p index such that hwloc_bitmap_isset(bitmap, index) is true.
*
* The assert prevents the loop from being infinite if the bitmap is infinite.
*/
#define hwloc_bitmap_foreach_begin(id, bitmap) \
do { \
assert(hwloc_bitmap_weight(bitmap) != -1); \
for (id = hwloc_bitmap_first(bitmap); \
(unsigned) id != (unsigned) -1; \
id = hwloc_bitmap_next(bitmap, id)) { \
/** \brief End of loop. Needs a terminating ';'.
* \hideinitializer
*
* \sa hwloc_bitmap_foreach_begin */
#define hwloc_bitmap_foreach_end() \
} \
} while (0)
/*
* Combining bitmaps.
*/
/** \brief Or bitmaps \p bitmap1 and \p bitmap2 and store the result in bitmap \p res */
HWLOC_DECLSPEC void hwloc_bitmap_or (hwloc_bitmap_t res, hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2);
/** \brief And bitmaps \p bitmap1 and \p bitmap2 and store the result in bitmap \p res */
HWLOC_DECLSPEC void hwloc_bitmap_and (hwloc_bitmap_t res, hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2);
/** \brief And bitmap \p bitmap1 and the negation of \p bitmap2 and store the result in bitmap \p res */
HWLOC_DECLSPEC void hwloc_bitmap_andnot (hwloc_bitmap_t res, hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2);
/** \brief Xor bitmaps \p bitmap1 and \p bitmap2 and store the result in bitmap \p res */
HWLOC_DECLSPEC void hwloc_bitmap_xor (hwloc_bitmap_t res, hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2);
/** \brief Negate bitmap \p bitmap and store the result in bitmap \p res */
HWLOC_DECLSPEC void hwloc_bitmap_not (hwloc_bitmap_t res, hwloc_const_bitmap_t bitmap);
/*
* Comparing bitmaps.
*/
/** \brief Test whether bitmaps \p bitmap1 and \p bitmap2 intersects */
HWLOC_DECLSPEC int hwloc_bitmap_intersects (hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2) __hwloc_attribute_pure;
/** \brief Test whether bitmap \p sub_bitmap is part of bitmap \p super_bitmap */
HWLOC_DECLSPEC int hwloc_bitmap_isincluded (hwloc_const_bitmap_t sub_bitmap, hwloc_const_bitmap_t super_bitmap) __hwloc_attribute_pure;
/** \brief Test whether bitmap \p bitmap1 is equal to bitmap \p bitmap2 */
HWLOC_DECLSPEC int hwloc_bitmap_isequal (hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2) __hwloc_attribute_pure;
/** \brief Compare bitmaps \p bitmap1 and \p bitmap2 using their lowest index.
*
* Smaller least significant bit is smaller.
* The empty bitmap is considered higher than anything.
*/
HWLOC_DECLSPEC int hwloc_bitmap_compare_first(hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2) __hwloc_attribute_pure;
/** \brief Compare bitmaps \p bitmap1 and \p bitmap2 using their highest index.
*
* Higher most significant bit is higher.
* The empty bitmap is considered lower than anything.
*/
HWLOC_DECLSPEC int hwloc_bitmap_compare(hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2) __hwloc_attribute_pure;
/** @} */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* HWLOC_BITMAP_H */
/*
* Copyright © 2009 CNRS
* 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.
*/
/** \file
* \brief The old deprecated Cpuset API.
* This interface should not be used anymore, it will be dropped in a later release.
*
* hwloc/bitmap.h should be used instead. Most hwloc_cpuset_foo functions are
* replaced with hwloc_bitmap_foo. The only exceptions are:
* - hwloc_cpuset_from_string -> hwloc_bitmap_sscanf
* - hwloc_cpuset_cpu -> hwloc_bitmap_only
* - hwloc_cpuset_all_but_cpu -> hwloc_bitmap_allbut
*/
#ifndef HWLOC_CPUSET_H
#define HWLOC_CPUSET_H
#ifdef __cplusplus
extern "C" {
#endif
#include "hwloc/bitmap.h"
static __hwloc_inline hwloc_bitmap_t __hwloc_attribute_deprecated hwloc_cpuset_alloc(void) { return hwloc_bitmap_alloc(); }
static __hwloc_inline void __hwloc_attribute_deprecated hwloc_cpuset_free(hwloc_bitmap_t bitmap) { hwloc_bitmap_free(bitmap); }
static __hwloc_inline hwloc_bitmap_t __hwloc_attribute_deprecated hwloc_cpuset_dup(hwloc_const_bitmap_t bitmap) { return hwloc_bitmap_dup(bitmap); }
static __hwloc_inline void __hwloc_attribute_deprecated hwloc_cpuset_copy(hwloc_bitmap_t dst, hwloc_const_bitmap_t src) { hwloc_bitmap_copy(dst, src); }
static __hwloc_inline int __hwloc_attribute_deprecated hwloc_cpuset_snprintf(char * __hwloc_restrict buf, size_t buflen, hwloc_const_bitmap_t bitmap) { return hwloc_bitmap_snprintf(buf, buflen, bitmap); }
static __hwloc_inline int __hwloc_attribute_deprecated hwloc_cpuset_asprintf(char ** strp, hwloc_const_bitmap_t bitmap) { return hwloc_bitmap_asprintf(strp, bitmap); }
static __hwloc_inline int __hwloc_attribute_deprecated hwloc_cpuset_from_string(hwloc_bitmap_t bitmap, const char * __hwloc_restrict string) { return hwloc_bitmap_sscanf(bitmap, string); }
static __hwloc_inline void __hwloc_attribute_deprecated hwloc_cpuset_zero(hwloc_bitmap_t bitmap) { hwloc_bitmap_zero(bitmap); }
static __hwloc_inline void __hwloc_attribute_deprecated hwloc_cpuset_fill(hwloc_bitmap_t bitmap) { hwloc_bitmap_fill(bitmap); }
static __hwloc_inline void __hwloc_attribute_deprecated hwloc_cpuset_from_ulong(hwloc_bitmap_t bitmap, unsigned long mask) { hwloc_bitmap_from_ulong(bitmap, mask); }
static __hwloc_inline void __hwloc_attribute_deprecated hwloc_cpuset_from_ith_ulong(hwloc_bitmap_t bitmap, unsigned i, unsigned long mask) { hwloc_bitmap_from_ith_ulong(bitmap, i, mask); }
static __hwloc_inline unsigned __hwloc_attribute_deprecated long hwloc_cpuset_to_ulong(hwloc_const_bitmap_t bitmap) { return hwloc_bitmap_to_ulong(bitmap); }
static __hwloc_inline unsigned __hwloc_attribute_deprecated long hwloc_cpuset_to_ith_ulong(hwloc_const_bitmap_t bitmap, unsigned i) { return hwloc_bitmap_to_ith_ulong(bitmap, i); }
static __hwloc_inline void __hwloc_attribute_deprecated hwloc_cpuset_cpu(hwloc_bitmap_t bitmap, unsigned index_) { hwloc_bitmap_only(bitmap, index_); }
static __hwloc_inline void __hwloc_attribute_deprecated hwloc_cpuset_all_but_cpu(hwloc_bitmap_t bitmap, unsigned index_) { hwloc_bitmap_allbut(bitmap, index_); }
static __hwloc_inline void __hwloc_attribute_deprecated hwloc_cpuset_set(hwloc_bitmap_t bitmap, unsigned index_) { hwloc_bitmap_set(bitmap, index_); }
static __hwloc_inline void __hwloc_attribute_deprecated hwloc_cpuset_set_range(hwloc_bitmap_t bitmap, unsigned begin, unsigned end) { hwloc_bitmap_set_range(bitmap, begin, end); }
static __hwloc_inline void __hwloc_attribute_deprecated hwloc_cpuset_set_ith_ulong(hwloc_bitmap_t bitmap, unsigned i, unsigned long mask) { hwloc_bitmap_set_ith_ulong(bitmap, i, mask); }
static __hwloc_inline void __hwloc_attribute_deprecated hwloc_cpuset_clr(hwloc_bitmap_t bitmap, unsigned index_) { hwloc_bitmap_clr(bitmap, index_); }
static __hwloc_inline void __hwloc_attribute_deprecated hwloc_cpuset_clr_range(hwloc_bitmap_t bitmap, unsigned begin, unsigned end) { hwloc_bitmap_clr_range(bitmap, begin, end); }
static __hwloc_inline int __hwloc_attribute_deprecated hwloc_cpuset_isset(hwloc_const_bitmap_t bitmap, unsigned index_) { return hwloc_bitmap_isset(bitmap, index_); }
static __hwloc_inline int __hwloc_attribute_deprecated hwloc_cpuset_iszero(hwloc_const_bitmap_t bitmap) { return hwloc_bitmap_iszero(bitmap); }
static __hwloc_inline int __hwloc_attribute_deprecated hwloc_cpuset_isfull(hwloc_const_bitmap_t bitmap) { return hwloc_bitmap_isfull(bitmap); }
static __hwloc_inline int __hwloc_attribute_deprecated hwloc_cpuset_isequal(hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2) { return hwloc_bitmap_isequal(bitmap1, bitmap2); }
static __hwloc_inline int __hwloc_attribute_deprecated hwloc_cpuset_intersects(hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2) { return hwloc_bitmap_intersects(bitmap1, bitmap2); }
static __hwloc_inline int __hwloc_attribute_deprecated hwloc_cpuset_isincluded(hwloc_const_bitmap_t sub_bitmap, hwloc_const_bitmap_t super_bitmap) { return hwloc_bitmap_isincluded(sub_bitmap, super_bitmap); }
static __hwloc_inline void __hwloc_attribute_deprecated hwloc_cpuset_or(hwloc_bitmap_t res, hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2) { hwloc_bitmap_or(res, bitmap1, bitmap2); }
static __hwloc_inline void __hwloc_attribute_deprecated hwloc_cpuset_and(hwloc_bitmap_t res, hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2) { hwloc_bitmap_and(res, bitmap1, bitmap2); }
static __hwloc_inline void __hwloc_attribute_deprecated hwloc_cpuset_andnot(hwloc_bitmap_t res, hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2) { hwloc_bitmap_andnot(res, bitmap1, bitmap2); }
static __hwloc_inline void __hwloc_attribute_deprecated hwloc_cpuset_xor(hwloc_bitmap_t res, hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2) { hwloc_bitmap_xor(res, bitmap1, bitmap2); }
static __hwloc_inline void __hwloc_attribute_deprecated hwloc_cpuset_not(hwloc_bitmap_t res, hwloc_const_bitmap_t bitmap) { hwloc_bitmap_not(res, bitmap); }
static __hwloc_inline int __hwloc_attribute_deprecated hwloc_cpuset_first(hwloc_const_bitmap_t bitmap) { return hwloc_bitmap_first(bitmap); }
static __hwloc_inline int __hwloc_attribute_deprecated hwloc_cpuset_last(hwloc_const_bitmap_t bitmap) { return hwloc_bitmap_last(bitmap); }
static __hwloc_inline int __hwloc_attribute_deprecated hwloc_cpuset_next(hwloc_const_bitmap_t bitmap, unsigned prev) { return hwloc_bitmap_next(bitmap, prev); }
static __hwloc_inline void __hwloc_attribute_deprecated hwloc_cpuset_singlify(hwloc_bitmap_t bitmap) { hwloc_bitmap_singlify(bitmap); }
static __hwloc_inline int __hwloc_attribute_deprecated hwloc_cpuset_compare_first(hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2) { return hwloc_bitmap_compare_first(bitmap1, bitmap2); }
static __hwloc_inline int __hwloc_attribute_deprecated hwloc_cpuset_compare(hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2) { return hwloc_bitmap_compare(bitmap1, bitmap2); }
static __hwloc_inline int __hwloc_attribute_deprecated hwloc_cpuset_weight(hwloc_const_bitmap_t bitmap) { return hwloc_bitmap_weight(bitmap); }
#define hwloc_cpuset_foreach_begin hwloc_bitmap_foreach_begin
#define hwloc_cpuset_foreach_end hwloc_bitmap_foreach_end
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* HWLOC_CPUSET_H */
/*
* 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.
*/
/** \file
* \brief Macros to help interaction between hwloc and the CUDA Driver API.
*
* Applications that use both hwloc and the CUDA Driver API may want to
* include this file so as to get topology information for CUDA devices.
*
*/
#ifndef HWLOC_CUDA_H
#define HWLOC_CUDA_H
#include <hwloc.h>
#include <hwloc/autogen/config.h>
#include <hwloc/linux.h>
#include <cuda.h>
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup hwlocality_cuda CUDA Driver API Specific Functions
* @{
*/
/** \brief Get the CPU set of logical processors that are physically
* close to device \p cudevice.
*
* For the given CUDA Driver API device \p cudevice, read the corresponding
* kernel-provided cpumap file and return the corresponding CPU set.
* This function is currently only implemented in a meaningful way for
* Linux; other systems will simply get a full cpuset.
*/
static __hwloc_inline int
hwloc_cuda_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
CUdevice cudevice, hwloc_cpuset_t set)
{
#ifdef HWLOC_LINUX_SYS
/* If we're on Linux, use the sysfs mechanism to get the local cpus */
#define HWLOC_CUDA_DEVICE_SYSFS_PATH_MAX 128
CUresult cres;
int deviceid;
int busid;
char path[HWLOC_CUDA_DEVICE_SYSFS_PATH_MAX];
FILE *sysfile = NULL;
cres = cuDeviceGetAttribute(&busid, CU_DEVICE_ATTRIBUTE_PCI_BUS_ID, cudevice);
if (cres != CUDA_SUCCESS) {
errno = ENOSYS;
return -1;
}
cres = cuDeviceGetAttribute(&deviceid, CU_DEVICE_ATTRIBUTE_PCI_DEVICE_ID, cudevice);
if (cres != CUDA_SUCCESS) {
errno = ENOSYS;
return -1;
}
sprintf(path, "/sys/bus/pci/devices/0000:%02x:%02x.0/local_cpus", busid, deviceid);
sysfile = fopen(path, "r");
if (!sysfile)
return -1;
hwloc_linux_parse_cpumap_file(sysfile, set);
fclose(sysfile);
#else
/* Non-Linux systems simply get a full cpuset */
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
#endif
return 0;
}
/** @} */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* HWLOC_CUDA_H */
/*
* 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.
*/
/** \file
* \brief Macros to help interaction between hwloc and the CUDA Runtime API.
*
* Applications that use both hwloc and the CUDA Runtime API may want to
* include this file so as to get topology information for CUDA devices.
*
*/
#ifndef HWLOC_CUDART_H
#define HWLOC_CUDART_H
#include <hwloc.h>
#include <hwloc/autogen/config.h>
#include <hwloc/linux.h>
#include <cuda_runtime_api.h>
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup hwlocality_cudart CUDA Runtime API Specific Functions
* @{
*/
/** \brief Get the CPU set of logical processors that are physically
* close to device \p cudevice.
*
* For the given CUDA Runtime API device \p cudevice, read the corresponding
* kernel-provided cpumap file and return the corresponding CPU set.
* This function is currently only implemented in a meaningful way for
* Linux; other systems will simply get a full cpuset.
*/
static __hwloc_inline int
hwloc_cudart_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
int device, hwloc_cpuset_t set)
{
#ifdef HWLOC_LINUX_SYS
/* If we're on Linux, use the sysfs mechanism to get the local cpus */
#define HWLOC_CUDART_DEVICE_SYSFS_PATH_MAX 128
cudaError_t cerr;
struct cudaDeviceProp prop;
char path[HWLOC_CUDART_DEVICE_SYSFS_PATH_MAX];
FILE *sysfile = NULL;
cerr = cudaGetDeviceProperties(&prop, device);
if (cerr) {
errno = ENOSYS;
return -1;
}
sprintf(path, "/sys/bus/pci/devices/0000:%02x:%02x.0/local_cpus", prop.pciBusID, prop.pciDeviceID);
sysfile = fopen(path, "r");
if (!sysfile)
return -1;
hwloc_linux_parse_cpumap_file(sysfile, set);
fclose(sysfile);
#else
/* Non-Linux systems simply get a full cpuset */
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
#endif
return 0;
}
/** @} */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* HWLOC_CUDART_H */
/*
* Copyright © 2009 CNRS
* 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.
*/
/** \file
* \brief Macros to help interaction between hwloc and glibc scheduling routines.
*
* Applications that use both hwloc and glibc scheduling routines such as
* sched_getaffinity may want to include this file so as to ease conversion
* between their respective types.
*/
#ifndef HWLOC_GLIBC_SCHED_H
#define HWLOC_GLIBC_SCHED_H
#include <hwloc.h>
#include <hwloc/helper.h>
#include <assert.h>
#if !defined _GNU_SOURCE || !defined _SCHED_H || !defined CPU_SETSIZE
#error Please make sure to include sched.h before including glibc-sched.h, and define _GNU_SOURCE before any inclusion of sched.h
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef HWLOC_HAVE_CPU_SET
/** \defgroup hwlocality_glibc_sched Helpers for manipulating glibc sched affinity
* @{
*/
/** \brief Convert hwloc CPU set \p toposet into glibc sched affinity CPU set \p schedset
*
* This function may be used before calling sched_setaffinity or any other function
* that takes a cpu_set_t as input parameter.
*
* \p schedsetsize should be sizeof(cpu_set_t) unless \p schedset was dynamically allocated with CPU_ALLOC
*/
static __hwloc_inline int
hwloc_cpuset_to_glibc_sched_affinity(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_const_cpuset_t hwlocset,
cpu_set_t *schedset, size_t schedsetsize)
{
#ifdef CPU_ZERO_S
unsigned cpu;
CPU_ZERO_S(schedsetsize, schedset);
hwloc_bitmap_foreach_begin(cpu, hwlocset)
CPU_SET_S(cpu, schedsetsize, schedset);
hwloc_bitmap_foreach_end();
#else /* !CPU_ZERO_S */
unsigned cpu;
CPU_ZERO(schedset);
assert(schedsetsize == sizeof(cpu_set_t));
hwloc_bitmap_foreach_begin(cpu, hwlocset)
CPU_SET(cpu, schedset);
hwloc_bitmap_foreach_end();
#endif /* !CPU_ZERO_S */
return 0;
}
/** \brief Convert glibc sched affinity CPU set \p schedset into hwloc CPU set
*
* This function may be used before calling sched_setaffinity or any other function
* that takes a cpu_set_t as input parameter.
*
* \p schedsetsize should be sizeof(cpu_set_t) unless \p schedset was dynamically allocated with CPU_ALLOC
*/
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)
{
#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) {
if (CPU_ISSET_S(cpu, schedsetsize, schedset)) {
hwloc_bitmap_set(hwlocset, cpu);
count--;
}
cpu++;
}
#else /* !CPU_ZERO_S */
/* sched.h does not support dynamic cpu_set_t (introduced in glibc 2.7),
* assume we have a very old interface without CPU_COUNT (added in 2.6)
*/
int cpu;
assert(schedsetsize == sizeof(cpu_set_t));
for(cpu=0; cpu<CPU_SETSIZE; cpu++)
if (CPU_ISSET(cpu, schedset))
hwloc_bitmap_set(hwlocset, cpu);
#endif /* !CPU_ZERO_S */
return 0;
}
/** @} */
#endif /* CPU_SET */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* HWLOC_GLIBC_SCHED_H */
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2011 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.
*/
/** \file
* \brief High-level hwloc traversal helpers.
*/
#ifndef HWLOC_HELPER_H
#define HWLOC_HELPER_H
#ifndef HWLOC_H
#error Please include the main hwloc.h instead
#endif
#include <stdlib.h>
#include <errno.h>
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup hwlocality_helper_types Object Type Helpers
* @{
*/
/** \brief Returns the depth of objects of type \p type or below
*
* If no object of this type is present on the underlying architecture, the
* function returns the depth of the first "present" object typically found
* inside \p type.
*/
static __hwloc_inline int __hwloc_attribute_pure
hwloc_get_type_or_below_depth (hwloc_topology_t topology, hwloc_obj_type_t type)
{
int depth = hwloc_get_type_depth(topology, type);
if (depth != HWLOC_TYPE_DEPTH_UNKNOWN)
return depth;
/* find the highest existing level with type order >= */
for(depth = hwloc_get_type_depth(topology, HWLOC_OBJ_PU); ; depth--)
if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) < 0)
return depth+1;
/* Shouldn't ever happen, as there is always a SYSTEM level with lower order and known depth. */
/* abort(); */
}
/** \brief Returns the depth of objects of type \p type or above
*
* If no object of this type is present on the underlying architecture, the
* function returns the depth of the first "present" object typically
* containing \p type.
*/
static __hwloc_inline int __hwloc_attribute_pure
hwloc_get_type_or_above_depth (hwloc_topology_t topology, hwloc_obj_type_t type)
{
int depth = hwloc_get_type_depth(topology, type);
if (depth != HWLOC_TYPE_DEPTH_UNKNOWN)
return depth;
/* find the lowest existing level with type order <= */
for(depth = 0; ; depth++)
if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) > 0)
return depth-1;
/* Shouldn't ever happen, as there is always a PU level with higher order and known depth. */
/* abort(); */
}
/** @} */
/** \defgroup hwlocality_helper_traversal_basic Basic Traversal Helpers
* @{
*/
/** \brief Returns the top-object of the topology-tree.
*
* Its type is typically ::HWLOC_OBJ_MACHINE but it could be different
* for complex topologies. This function replaces the old deprecated
* hwloc_get_system_obj().
*/
static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
hwloc_get_root_obj (hwloc_topology_t topology)
{
return hwloc_get_obj_by_depth (topology, 0, 0);
}
/** \brief Returns the ancestor object of \p obj at depth \p depth. */
static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
hwloc_get_ancestor_obj_by_depth (hwloc_topology_t topology __hwloc_attribute_unused, unsigned depth, hwloc_obj_t obj)
{
hwloc_obj_t ancestor = obj;
if (obj->depth < depth)
return NULL;
while (ancestor && ancestor->depth > depth)
ancestor = ancestor->parent;
return ancestor;
}
/** \brief Returns the ancestor object of \p obj with type \p type. */
static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
hwloc_get_ancestor_obj_by_type (hwloc_topology_t topology __hwloc_attribute_unused, hwloc_obj_type_t type, hwloc_obj_t obj)
{
hwloc_obj_t ancestor = obj->parent;
while (ancestor && ancestor->type != type)
ancestor = ancestor->parent;
return ancestor;
}
/** \brief Returns the next object at depth \p depth.
*
* If \p prev is \c NULL, return the first object at depth \p depth.
*/
static __hwloc_inline hwloc_obj_t
hwloc_get_next_obj_by_depth (hwloc_topology_t topology, unsigned depth, hwloc_obj_t prev)
{
if (!prev)
return hwloc_get_obj_by_depth (topology, depth, 0);
if (prev->depth != depth)
return NULL;
return prev->next_cousin;
}
/** \brief Returns the next object of type \p type.
*
* If \p prev is \c NULL, return the first object at type \p type. If
* there are multiple or no depth for given type, return \c NULL and
* let the caller fallback to hwloc_get_next_obj_by_depth().
*/
static __hwloc_inline hwloc_obj_t
hwloc_get_next_obj_by_type (hwloc_topology_t topology, hwloc_obj_type_t type,
hwloc_obj_t prev)
{
int depth = hwloc_get_type_depth(topology, type);
if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
return NULL;
return hwloc_get_next_obj_by_depth (topology, depth, prev);
}
/** \brief Returns the object of type ::HWLOC_OBJ_PU with \p os_index.
*
* \note The \p os_index field of object should most of the times only be
* used for pretty-printing purpose. Type ::HWLOC_OBJ_PU is the only case
* where \p os_index could actually be useful, when manually binding to
* processors.
* However, using CPU sets to hide this complexity should often be preferred.
*/
static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
hwloc_get_pu_obj_by_os_index(hwloc_topology_t topology, unsigned os_index)
{
hwloc_obj_t obj = NULL;
while ((obj = hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_PU, obj)) != NULL)
if (obj->os_index == os_index)
return obj;
return NULL;
}
/** \brief Return the next child.
*
* If \p prev is \c NULL, return the first child.
*/
static __hwloc_inline hwloc_obj_t
hwloc_get_next_child (hwloc_topology_t topology __hwloc_attribute_unused, hwloc_obj_t parent, hwloc_obj_t prev)
{
if (!prev)
return parent->first_child;
if (prev->parent != parent)
return NULL;
return prev->next_sibling;
}
/** \brief Returns the common parent object to objects lvl1 and lvl2 */
static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
hwloc_get_common_ancestor_obj (hwloc_topology_t topology __hwloc_attribute_unused, hwloc_obj_t obj1, hwloc_obj_t obj2)
{
/* the loop isn't so easy since intermediate ancestors may have
* different depth, causing us to alternate between using obj1->parent
* and obj2->parent. Also, even if at some point we find ancestors of
* of the same depth, their ancestors may have different depth again.
*/
while (obj1 != obj2) {
while (obj1->depth > obj2->depth)
obj1 = obj1->parent;
while (obj2->depth > obj1->depth)
obj2 = obj2->parent;
if (obj1 != obj2 && obj1->depth == obj2->depth) {
obj1 = obj1->parent;
obj2 = obj2->parent;
}
}
return obj1;
}
/** \brief Returns true if \p obj is inside the subtree beginning with \p subtree_root.
*
* \note This function assumes that both \p obj and \p subtree_root have a \p cpuset.
*/
static __hwloc_inline int __hwloc_attribute_pure
hwloc_obj_is_in_subtree (hwloc_topology_t topology __hwloc_attribute_unused, hwloc_obj_t obj, hwloc_obj_t subtree_root)
{
return hwloc_bitmap_isincluded(obj->cpuset, subtree_root->cpuset);
}
/** @} */
/** \defgroup hwlocality_helper_find_inside Finding Objects Inside a CPU set
* @{
*/
/** \brief Get the first largest object included in the given cpuset \p set.
*
* \return the first object that is included in \p set and whose parent is not.
*
* This is convenient for iterating over all largest objects within a CPU set
* by doing a loop getting the first largest object and clearing its CPU set
* from the remaining CPU set.
*/
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 (child->cpuset && hwloc_bitmap_intersects(child->cpuset, set))
break;
}
if (!child)
/* no child intersects, return their father */
return obj;
/* found one intersecting child, look at its children */
obj = child;
}
/* obj is included, return it */
return obj;
}
/** \brief Get the set of largest objects covering exactly a given cpuset \p set
*
* \return the number of objects returned in \p objs.
*/
HWLOC_DECLSPEC int hwloc_get_largest_objs_inside_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set,
hwloc_obj_t * __hwloc_restrict objs, int max);
/** \brief Return the next object at depth \p depth included in CPU set \p set.
*
* If \p prev is \c NULL, return the first object at depth \p depth
* included in \p set. The next invokation should pass the previous
* return value in \p prev so as to obtain the next object in \p set.
*/
static __hwloc_inline hwloc_obj_t
hwloc_get_next_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
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;
}
/** \brief Return the next object of type \p type included in CPU set \p set.
*
* If there are multiple or no depth for given type, return \c NULL
* and let the caller fallback to
* hwloc_get_next_obj_inside_cpuset_by_depth().
*/
static __hwloc_inline hwloc_obj_t
hwloc_get_next_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
hwloc_obj_type_t type, hwloc_obj_t prev)
{
int depth = hwloc_get_type_depth(topology, type);
if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
return NULL;
return hwloc_get_next_obj_inside_cpuset_by_depth(topology, set, depth, prev);
}
/** \brief Return the (logically) \p idx -th object at depth \p depth included in CPU set \p set.
*/
static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
hwloc_get_obj_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
unsigned depth, unsigned idx)
{
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;
count++;
}
obj = obj->next_cousin;
}
return NULL;
}
/** \brief Return the \p idx -th object of type \p type included in CPU set \p set.
*
* If there are multiple or no depth for given type, return \c NULL
* and let the caller fallback to
* hwloc_get_obj_inside_cpuset_by_depth().
*/
static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
hwloc_get_obj_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
hwloc_obj_type_t type, unsigned idx)
{
int depth = hwloc_get_type_depth(topology, type);
if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
return NULL;
return hwloc_get_obj_inside_cpuset_by_depth(topology, set, depth, idx);
}
/** \brief Return the number of objects at depth \p depth included in CPU set \p set. */
static __hwloc_inline unsigned __hwloc_attribute_pure
hwloc_get_nbobjs_inside_cpuset_by_depth (hwloc_topology_t topology, hwloc_const_cpuset_t set,
unsigned depth)
{
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;
}
return count;
}
/** \brief Return the number of objects of type \p type included in CPU set \p set.
*
* If no object for that type exists inside CPU set \p set, 0 is
* returned. If there are several levels with objects of that type
* inside CPU set \p set, -1 is returned.
*/
static __hwloc_inline int __hwloc_attribute_pure
hwloc_get_nbobjs_inside_cpuset_by_type (hwloc_topology_t topology, hwloc_const_cpuset_t set,
hwloc_obj_type_t type)
{
int depth = hwloc_get_type_depth(topology, type);
if (depth == HWLOC_TYPE_DEPTH_UNKNOWN)
return 0;
if (depth == HWLOC_TYPE_DEPTH_MULTIPLE)
return -1; /* FIXME: agregate nbobjs from different levels? */
return hwloc_get_nbobjs_inside_cpuset_by_depth(topology, set, depth);
}
/** @} */
/** \defgroup hwlocality_helper_find_covering Finding a single Object covering at least CPU set
* @{
*/
/** \brief Get the child covering at least CPU set \p set.
*
* \return \c NULL if no child matches or if \p set is empty.
*/
static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
hwloc_get_child_covering_cpuset (hwloc_topology_t topology __hwloc_attribute_unused, hwloc_const_cpuset_t set,
hwloc_obj_t parent)
{
hwloc_obj_t child;
if (hwloc_bitmap_iszero(set))
return NULL;
child = parent->first_child;
while (child) {
if (child->cpuset && hwloc_bitmap_isincluded(set, child->cpuset))
return child;
child = child->next_sibling;
}
return NULL;
}
/** \brief Get the lowest object covering at least CPU set \p set
*
* \return \c NULL if no object matches or if \p set is empty.
*/
static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
hwloc_get_obj_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set)
{
struct hwloc_obj *current = hwloc_get_root_obj(topology);
if (hwloc_bitmap_iszero(set))
return NULL;
/* FIXME: what if !root->cpuset? */
if (!hwloc_bitmap_isincluded(set, current->cpuset))
return NULL;
while (1) {
hwloc_obj_t child = hwloc_get_child_covering_cpuset(topology, set, current);
if (!child)
return current;
current = child;
}
}
/** @} */
/** \defgroup hwlocality_helper_find_coverings Finding a set of similar Objects covering at least a CPU set
* @{
*/
/** \brief Iterate through same-depth objects covering at least CPU set \p set
*
* If object \p prev is \c NULL, return the first object at depth \p
* depth covering at least part of CPU set \p set. The next
* invokation should pass the previous return value in \p prev so as
* to obtain the next object covering at least another part of \p set.
*/
static __hwloc_inline hwloc_obj_t
hwloc_get_next_obj_covering_cpuset_by_depth(hwloc_topology_t topology, hwloc_const_cpuset_t set,
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;
}
/** \brief Iterate through same-type objects covering at least CPU set \p set
*
* If object \p prev is \c NULL, return the first object of type \p
* type covering at least part of CPU set \p set. The next invokation
* should pass the previous return value in \p prev so as to obtain
* the next object of type \p type covering at least another part of
* \p set.
*
* If there are no or multiple depths for type \p type, \c NULL is returned.
* The caller may fallback to hwloc_get_next_obj_covering_cpuset_by_depth()
* for each depth.
*/
static __hwloc_inline hwloc_obj_t
hwloc_get_next_obj_covering_cpuset_by_type(hwloc_topology_t topology, hwloc_const_cpuset_t set,
hwloc_obj_type_t type, hwloc_obj_t prev)
{
int depth = hwloc_get_type_depth(topology, type);
if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
return NULL;
return hwloc_get_next_obj_covering_cpuset_by_depth(topology, set, depth, prev);
}
/** @} */
/** \defgroup hwlocality_helper_find_cache Cache-specific Finding Helpers
* @{
*/
/** \brief Get the first cache covering a cpuset \p set
*
* \return \c NULL if no cache matches
*/
static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
hwloc_get_cache_covering_cpuset (hwloc_topology_t topology, hwloc_const_cpuset_t set)
{
hwloc_obj_t current = hwloc_get_obj_covering_cpuset(topology, set);
while (current) {
if (current->type == HWLOC_OBJ_CACHE)
return current;
current = current->parent;
}
return NULL;
}
/** \brief Get the first cache shared between an object and somebody else.
*
* \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;
if (!obj->cpuset)
return NULL;
while (current && current->cpuset) {
if (!hwloc_bitmap_isequal(current->cpuset, obj->cpuset)
&& current->type == HWLOC_OBJ_CACHE)
return current;
current = current->parent;
}
return NULL;
}
/** @} */
/** \defgroup hwlocality_helper_traversal Advanced Traversal Helpers
* @{
*/
/** \brief Do a depth-first traversal of the topology to find and sort
*
* all objects that are at the same depth than \p src.
* Report in \p objs up to \p max physically closest ones to \p src.
*
* \return the number of objects returned in \p objs.
*/
/* TODO: rather provide an iterator? Provide a way to know how much should be allocated? By returning the total number of objects instead? */
HWLOC_DECLSPEC unsigned hwloc_get_closest_objs (hwloc_topology_t topology, hwloc_obj_t src, hwloc_obj_t * __hwloc_restrict objs, unsigned max);
/** \brief Find an object below another object, both specified by types and indexes.
*
* Start from the top system object and find object of type \p type1
* and logical index \p idx1. Then look below this object and find another
* object of type \p type2 and logical index \p idx2. Indexes are specified
* within the parent, not withing the entire system.
*
* For instance, if type1 is SOCKET, idx1 is 2, type2 is CORE and idx2
* is 3, return the fourth core object below the third socket.
*/
static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
hwloc_get_obj_below_by_type (hwloc_topology_t topology,
hwloc_obj_type_t type1, unsigned idx1,
hwloc_obj_type_t type2, unsigned idx2)
{
hwloc_obj_t obj;
obj = hwloc_get_obj_by_type (topology, type1, idx1);
if (!obj)
return NULL;
return hwloc_get_obj_inside_cpuset_by_type(topology, obj->cpuset, type2, idx2);
}
/** \brief Find an object below a chain of objects specified by types and indexes.
*
* This is a generalized version of hwloc_get_obj_below_by_type().
*
* Arrays \p typev and \p idxv must contain \p nr types and indexes.
*
* Start from the top system object and walk the arrays \p typev and \p idxv.
* For each type and logical index couple in the arrays, look under the previously found
* object to find the index-th object of the given type.
* Indexes are specified within the parent, not withing the entire system.
*
* For instance, if nr is 3, typev contains NODE, SOCKET and CORE,
* and idxv contains 0, 1 and 2, return the third core object below
* the second socket below the first NUMA node.
*/
static __hwloc_inline hwloc_obj_t __hwloc_attribute_pure
hwloc_get_obj_below_array_by_type (hwloc_topology_t topology, int nr, hwloc_obj_type_t *typev, unsigned *idxv)
{
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)
return NULL;
}
return obj;
}
/** @} */
/** \defgroup hwlocality_helper_binding Binding Helpers
* @{
*/
/** \brief Distribute \p n items over the topology under \p root
*
* Array \p cpuset will be filled with \p n cpusets recursively distributed
* linearly over the topology under \p root, down to depth \p until (which can
* be INT_MAX to distribute down to the finest level).
*
* This is typically useful when an application wants to distribute \p n
* threads over a machine, giving each of them as much private cache as
* possible and keeping them locally in number order.
*
* The caller may typically want to also call hwloc_bitmap_singlify()
* before binding a thread so that it does not move at all.
*/
static __hwloc_inline void
hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *root, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until);
static __hwloc_inline void
hwloc_distribute(hwloc_topology_t topology, hwloc_obj_t root, hwloc_cpuset_t *cpuset, unsigned n, unsigned until)
{
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++)
cpuset[i] = hwloc_bitmap_dup(root->cpuset);
return;
}
hwloc_distributev(topology, root->children, root->arity, cpuset, n, until);
}
/** \brief Distribute \p n items over the topology under \p roots
*
* This is the same as hwloc_distribute, but takes an array of roots instead of
* just one root.
*/
static __hwloc_inline void
hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *roots, unsigned n_roots, hwloc_cpuset_t *cpuset, unsigned n, unsigned until)
{
unsigned i;
unsigned tot_weight;
hwloc_cpuset_t *cpusetp = cpuset;
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 && tot_weight; i++) {
/* Give to roots[i] a portion proportional to its weight */
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;
tot_weight -= weight;
n -= chunk;
}
}
/** \brief Allocate some memory on the given nodeset \p nodeset
*
* This is similar to hwloc_alloc_membind except that it is allowed to change
* the current memory binding policy, thus providing more binding support, at
* the expense of changing the current state.
*/
static __hwloc_inline void *
hwloc_alloc_membind_policy_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
{
void *p = hwloc_alloc_membind_nodeset(topology, len, nodeset, policy, flags);
if (p)
return p;
hwloc_set_membind_nodeset(topology, nodeset, policy, flags);
p = hwloc_alloc(topology, len);
if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH)
/* Enforce the binding by touching the data */
memset(p, 0, len);
return p;
}
/** \brief Allocate some memory on the memory nodes near given cpuset \p cpuset
*
* This is similar to hwloc_alloc_membind_policy_nodeset, but for a given cpuset.
*/
static __hwloc_inline void *
hwloc_alloc_membind_policy(hwloc_topology_t topology, size_t len, hwloc_const_cpuset_t cpuset, hwloc_membind_policy_t policy, int flags)
{
void *p = hwloc_alloc_membind(topology, len, cpuset, policy, flags);
if (p)
return p;
hwloc_set_membind(topology, cpuset, policy, flags);
p = hwloc_alloc(topology, len);
if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH)
/* Enforce the binding by touching the data */
memset(p, 0, len);
return p;
}
/** @} */
/** \defgroup hwlocality_helper_cpuset Cpuset Helpers
* @{
*/
/** \brief Get complete CPU set
*
* \return the complete CPU set of logical processors of the system. If the
* topology is the result of a combination of several systems, NULL is
* returned.
*
* \note The returned cpuset is not newly allocated and should thus not be
* changed or freed; hwloc_cpuset_dup must be used to obtain a local copy.
*/
static __hwloc_inline hwloc_const_cpuset_t __hwloc_attribute_pure
hwloc_topology_get_complete_cpuset(hwloc_topology_t topology)
{
return hwloc_get_root_obj(topology)->complete_cpuset;
}
/** \brief Get topology CPU set
*
* \return the CPU set of logical processors of the system for which hwloc
* provides topology information. This is equivalent to the cpuset of the
* system object. If the topology is the result of a combination of several
* systems, NULL is returned.
*
* \note The returned cpuset is not newly allocated and should thus not be
* changed or freed; hwloc_cpuset_dup must be used to obtain a local copy.
*/
static __hwloc_inline hwloc_const_cpuset_t __hwloc_attribute_pure
hwloc_topology_get_topology_cpuset(hwloc_topology_t topology)
{
return hwloc_get_root_obj(topology)->cpuset;
}
/** \brief Get online CPU set
*
* \return the CPU set of online logical processors of the system. If the
* topology is the result of a combination of several systems, NULL is
* returned.
*
* \note The returned cpuset is not newly allocated and should thus not be
* changed or freed; hwloc_cpuset_dup must be used to obtain a local copy.
*/
static __hwloc_inline hwloc_const_cpuset_t __hwloc_attribute_pure
hwloc_topology_get_online_cpuset(hwloc_topology_t topology)
{
return hwloc_get_root_obj(topology)->online_cpuset;
}
/** \brief Get allowed CPU set
*
* \return the CPU set of allowed logical processors of the system. If the
* topology is the result of a combination of several systems, NULL is
* returned.
*
* \note The returned cpuset is not newly allocated and should thus not be
* changed or freed, hwloc_cpuset_dup must be used to obtain a local copy.
*/
static __hwloc_inline hwloc_const_cpuset_t __hwloc_attribute_pure
hwloc_topology_get_allowed_cpuset(hwloc_topology_t topology)
{
return hwloc_get_root_obj(topology)->allowed_cpuset;
}
/** @} */
/** \defgroup hwlocality_helper_nodeset Nodeset Helpers
* @{
*/
/** \brief Get complete node set
*
* \return the complete node set of memory of the system. If the
* topology is the result of a combination of several systems, NULL is
* returned.
*
* \note The returned nodeset is not newly allocated and should thus not be
* changed or freed; hwloc_nodeset_dup must be used to obtain a local copy.
*/
static __hwloc_inline hwloc_const_nodeset_t __hwloc_attribute_pure
hwloc_topology_get_complete_nodeset(hwloc_topology_t topology)
{
return hwloc_get_root_obj(topology)->complete_nodeset;
}
/** \brief Get topology node set
*
* \return the node set of memory of the system for which hwloc
* provides topology information. This is equivalent to the nodeset of the
* system object. If the topology is the result of a combination of several
* systems, NULL is returned.
*
* \note The returned nodeset is not newly allocated and should thus not be
* changed or freed; hwloc_nodeset_dup must be used to obtain a local copy.
*/
static __hwloc_inline hwloc_const_nodeset_t __hwloc_attribute_pure
hwloc_topology_get_topology_nodeset(hwloc_topology_t topology)
{
return hwloc_get_root_obj(topology)->nodeset;
}
/** \brief Get allowed node set
*
* \return the node set of allowed memory of the system. If the
* topology is the result of a combination of several systems, NULL is
* returned.
*
* \note The returned nodeset is not newly allocated and should thus not be
* changed or freed, hwloc_nodeset_dup must be used to obtain a local copy.
*/
static __hwloc_inline hwloc_const_nodeset_t __hwloc_attribute_pure
hwloc_topology_get_allowed_nodeset(hwloc_topology_t topology)
{
return hwloc_get_root_obj(topology)->allowed_nodeset;
}
/** @} */
/** \defgroup hwlocality_helper_nodeset_convert Conversion between cpuset and nodeset
*
* There are two semantics for converting cpusets to nodesets depending on how
* non-NUMA machines are handled.
*
* When manipulating nodesets for memory binding, non-NUMA machines should be
* considered as having a single NUMA node. The standard conversion routines
* below should be used so that marking the first bit of the nodeset means
* that memory should be bound to a non-NUMA whole machine.
*
* When manipulating nodesets as an actual list of NUMA nodes without any
* need to handle memory binding on non-NUMA machines, the strict conversion
* routines may be used instead.
* @{
*/
/** \brief Convert a CPU set into a NUMA node set and handle non-NUMA cases
*
* If some NUMA nodes have no CPUs at all, this function never sets their
* indexes in the output node set, even if a full CPU set is given in input.
*
* If the topology contains no NUMA nodes, the machine is considered
* as a single memory node, and the following behavior is used:
* If \p cpuset is empty, \p nodeset will be emptied as well.
* Otherwise \p nodeset will be entirely filled.
*/
static __hwloc_inline void
hwloc_cpuset_to_nodeset(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset)
{
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
hwloc_obj_t obj;
if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) {
if (hwloc_bitmap_iszero(cpuset))
hwloc_bitmap_zero(nodeset);
else
/* Assume the whole system */
hwloc_bitmap_fill(nodeset);
return;
}
hwloc_bitmap_zero(nodeset);
obj = NULL;
while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL)
hwloc_bitmap_set(nodeset, obj->os_index);
}
/** \brief Convert a CPU set into a NUMA node set without handling non-NUMA cases
*
* This is the strict variant of ::hwloc_cpuset_to_nodeset. It does not fix
* non-NUMA cases. If the topology contains some NUMA nodes, behave exactly
* the same. However, if the topology contains no NUMA nodes, return an empty
* nodeset.
*/
static __hwloc_inline void
hwloc_cpuset_to_nodeset_strict(struct hwloc_topology *topology, hwloc_const_cpuset_t cpuset, hwloc_nodeset_t nodeset)
{
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
hwloc_obj_t obj;
if (depth == HWLOC_TYPE_DEPTH_UNKNOWN )
return;
hwloc_bitmap_zero(nodeset);
obj = NULL;
while ((obj = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, obj)) != NULL)
hwloc_bitmap_set(nodeset, obj->os_index);
}
/** \brief Convert a NUMA node set into a CPU set and handle non-NUMA cases
*
* If the topology contains no NUMA nodes, the machine is considered
* as a single memory node, and the following behavior is used:
* If \p nodeset is empty, \p cpuset will be emptied as well.
* Otherwise \p cpuset will be entirely filled.
* This is useful for manipulating memory binding sets.
*/
static __hwloc_inline void
hwloc_cpuset_from_nodeset(hwloc_topology_t topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset)
{
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
hwloc_obj_t obj;
if (depth == HWLOC_TYPE_DEPTH_UNKNOWN ) {
if (hwloc_bitmap_iszero(nodeset))
hwloc_bitmap_zero(cpuset);
else
/* Assume the whole system */
hwloc_bitmap_fill(cpuset);
return;
}
hwloc_bitmap_zero(cpuset);
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);
}
}
/** \brief Convert a NUMA node set into a CPU set without handling non-NUMA cases
*
* This is the strict variant of ::hwloc_cpuset_from_nodeset. It does not fix
* non-NUMA cases. If the topology contains some NUMA nodes, behave exactly
* the same. However, if the topology contains no NUMA nodes, return an empty
* cpuset.
*/
static __hwloc_inline void
hwloc_cpuset_from_nodeset_strict(struct hwloc_topology *topology, hwloc_cpuset_t cpuset, hwloc_const_nodeset_t nodeset)
{
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
hwloc_obj_t obj;
if (depth == HWLOC_TYPE_DEPTH_UNKNOWN )
return;
hwloc_bitmap_zero(cpuset);
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);
}
/** @} */
/** \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
#endif /* HWLOC_HELPER_H */
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2010 INRIA. All rights reserved.
* Copyright © 2009-2010 Université Bordeaux 1
* See COPYING in top-level directory.
*/
/** \file
* \brief Macros to help interaction between hwloc and Linux libnuma.
*
* Applications that use both Linux libnuma and hwloc may want to
* include this file so as to ease conversion between their respective types.
*/
#ifndef HWLOC_LINUX_LIBNUMA_H
#define HWLOC_LINUX_LIBNUMA_H
#include <hwloc.h>
#include <numa.h>
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup hwlocality_linux_libnuma_ulongs Helpers for manipulating Linux libnuma unsigned long masks
* @{
*/
/** \brief Convert hwloc CPU set \p cpuset into the array of unsigned long \p mask
*
* \p mask is the array of unsigned long that will be filled.
* \p maxnode contains the maximal node number that may be stored in \p mask.
* \p maxnode will be set to the maximal node number that was found, plus one.
*
* This function may be used before calling set_mempolicy, mbind, migrate_pages
* or any other function that takes an array of unsigned long and a maximal
* node number as input parameter.
*/
static __hwloc_inline int
hwloc_cpuset_to_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset,
unsigned long *mask, unsigned long *maxnode)
{
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
unsigned long outmaxnode = -1;
/* round-up to the next ulong and clear all bytes */
*maxnode = (*maxnode + 8*sizeof(*mask) - 1) & ~(8*sizeof(*mask) - 1);
memset(mask, 0, *maxnode/8);
if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
hwloc_obj_t node = NULL;
while ((node = hwloc_get_next_obj_covering_cpuset_by_type(topology, cpuset, HWLOC_OBJ_NODE, node)) != NULL) {
if (node->os_index >= *maxnode)
continue;
mask[node->os_index/sizeof(*mask)/8] |= 1UL << (node->os_index % (sizeof(*mask)*8));
if (outmaxnode == (unsigned long) -1 || outmaxnode < node->os_index)
outmaxnode = node->os_index;
}
} else {
/* if no numa, libnuma assumes we have a single node */
if (!hwloc_bitmap_iszero(cpuset)) {
mask[0] = 1;
outmaxnode = 0;
}
}
*maxnode = outmaxnode+1;
return 0;
}
/** \brief Convert hwloc NUMA node set \p nodeset into the array of unsigned long \p mask
*
* \p mask is the array of unsigned long that will be filled.
* \p maxnode contains the maximal node number that may be stored in \p mask.
* \p maxnode will be set to the maximal node number that was found, plus one.
*
* This function may be used before calling set_mempolicy, mbind, migrate_pages
* or any other function that takes an array of unsigned long and a maximal
* node number as input parameter.
*/
static __hwloc_inline int
hwloc_nodeset_to_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset,
unsigned long *mask, unsigned long *maxnode)
{
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
unsigned long outmaxnode = -1;
/* round-up to the next ulong and clear all bytes */
*maxnode = (*maxnode + 8*sizeof(*mask) - 1) & ~(8*sizeof(*mask) - 1);
memset(mask, 0, *maxnode/8);
if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
hwloc_obj_t node = NULL;
while ((node = hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_NODE, node)) != NULL) {
if (node->os_index >= *maxnode)
continue;
if (!hwloc_bitmap_isset(nodeset, node->os_index))
continue;
mask[node->os_index/sizeof(*mask)/8] |= 1UL << (node->os_index % (sizeof(*mask)*8));
if (outmaxnode == (unsigned long) -1 || outmaxnode < node->os_index)
outmaxnode = node->os_index;
}
} else {
/* if no numa, libnuma assumes we have a single node */
if (!hwloc_bitmap_iszero(nodeset)) {
mask[0] = 1;
outmaxnode = 0;
}
}
*maxnode = outmaxnode+1;
return 0;
}
/** \brief Convert the array of unsigned long \p mask into hwloc CPU set
*
* \p mask is a array of unsigned long that will be read.
* \p maxnode contains the maximal node number that may be read in \p mask.
*
* This function may be used after calling get_mempolicy or any other function
* that takes an array of unsigned long as output parameter (and possibly
* a maximal node number as input parameter).
*/
static __hwloc_inline int
hwloc_cpuset_from_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_cpuset_t cpuset,
const unsigned long *mask, unsigned long maxnode)
{
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
hwloc_obj_t node;
unsigned i;
hwloc_bitmap_zero(cpuset);
for(i=0; i<maxnode; i++)
if (mask[i/sizeof(*mask)/8] & (1UL << (i% (sizeof(*mask)*8)))) {
node = hwloc_get_obj_by_depth(topology, depth, i);
if (node)
hwloc_bitmap_or(cpuset, cpuset, node->cpuset);
}
} else {
/* if no numa, libnuma assumes we have a single node */
if (mask[0] & 1)
hwloc_bitmap_copy(cpuset, hwloc_topology_get_complete_cpuset(topology));
else
hwloc_bitmap_zero(cpuset);
}
return 0;
}
/** \brief Convert the array of unsigned long \p mask into hwloc NUMA node set
*
* \p mask is a array of unsigned long that will be read.
* \p maxnode contains the maximal node number that may be read in \p mask.
*
* This function may be used after calling get_mempolicy or any other function
* that takes an array of unsigned long as output parameter (and possibly
* a maximal node number as input parameter).
*/
static __hwloc_inline int
hwloc_nodeset_from_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_nodeset_t nodeset,
const unsigned long *mask, unsigned long maxnode)
{
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
hwloc_obj_t node;
unsigned i;
hwloc_bitmap_zero(nodeset);
for(i=0; i<maxnode; i++)
if (mask[i/sizeof(*mask)/8] & (1UL << (i% (sizeof(*mask)*8)))) {
node = hwloc_get_obj_by_depth(topology, depth, i);
if (node)
hwloc_bitmap_set(nodeset, node->os_index);
}
} else {
/* if no numa, libnuma assumes we have a single node */
if (mask[0] & 1)
hwloc_bitmap_fill(nodeset);
else
hwloc_bitmap_zero(nodeset);
}
return 0;
}
/** @} */
/** \defgroup hwlocality_linux_libnuma_bitmask Helpers for manipulating Linux libnuma bitmask
* @{
*/
/** \brief Convert hwloc CPU set \p cpuset into the returned libnuma bitmask
*
* The returned bitmask should later be freed with numa_bitmask_free.
*
* This function may be used before calling many numa_ functions
* that use a struct bitmask as an input parameter.
*
* \return newly allocated struct bitmask.
*/
static __hwloc_inline struct bitmask * __hwloc_attribute_malloc
hwloc_cpuset_to_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset)
{
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
struct bitmask *bitmask = numa_allocate_cpumask();
if (!bitmask)
return NULL;
if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
hwloc_obj_t node = NULL;
while ((node = hwloc_get_next_obj_covering_cpuset_by_type(topology, cpuset, HWLOC_OBJ_NODE, node)) != NULL)
numa_bitmask_setbit(bitmask, node->os_index);
} else {
/* if no numa, libnuma assumes we have a single node */
if (!hwloc_bitmap_iszero(cpuset))
numa_bitmask_setbit(bitmask, 0);
}
return bitmask;
}
/** \brief Convert hwloc NUMA node set \p nodeset into the returned libnuma bitmask
*
* The returned bitmask should later be freed with numa_bitmask_free.
*
* This function may be used before calling many numa_ functions
* that use a struct bitmask as an input parameter.
*
* \return newly allocated struct bitmask.
*/
static __hwloc_inline struct bitmask * __hwloc_attribute_malloc
hwloc_nodeset_to_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset)
{
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
struct bitmask *bitmask = numa_allocate_cpumask();
if (!bitmask)
return NULL;
if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
hwloc_obj_t node = NULL;
while ((node = hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_NODE, node)) != NULL)
if (hwloc_bitmap_isset(nodeset, node->os_index))
numa_bitmask_setbit(bitmask, node->os_index);
} else {
/* if no numa, libnuma assumes we have a single node */
if (!hwloc_bitmap_iszero(nodeset))
numa_bitmask_setbit(bitmask, 0);
}
return bitmask;
}
/** \brief Convert libnuma bitmask \p bitmask into hwloc CPU set \p cpuset
*
* This function may be used after calling many numa_ functions
* that use a struct bitmask as an output parameter.
*/
static __hwloc_inline int
hwloc_cpuset_from_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_cpuset_t cpuset,
const struct bitmask *bitmask)
{
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
hwloc_obj_t node;
int i;
hwloc_bitmap_zero(cpuset);
for(i=0; i<NUMA_NUM_NODES; i++)
if (numa_bitmask_isbitset(bitmask, i)) {
node = hwloc_get_obj_by_depth(topology, depth, i);
if (node)
hwloc_bitmap_or(cpuset, cpuset, node->cpuset);
}
} else {
/* if no numa, libnuma assumes we have a single node */
if (numa_bitmask_isbitset(bitmask, 0))
hwloc_bitmap_copy(cpuset, hwloc_topology_get_complete_cpuset(topology));
else
hwloc_bitmap_zero(cpuset);
}
return 0;
}
/** \brief Convert libnuma bitmask \p bitmask into hwloc NUMA node set \p nodeset
*
* This function may be used after calling many numa_ functions
* that use a struct bitmask as an output parameter.
*/
static __hwloc_inline int
hwloc_nodeset_from_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_nodeset_t nodeset,
const struct bitmask *bitmask)
{
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
hwloc_obj_t node;
int i;
hwloc_bitmap_zero(nodeset);
for(i=0; i<NUMA_NUM_NODES; i++)
if (numa_bitmask_isbitset(bitmask, i)) {
node = hwloc_get_obj_by_depth(topology, depth, i);
if (node)
hwloc_bitmap_set(nodeset, node->os_index);
}
} else {
/* if no numa, libnuma assumes we have a single node */
if (numa_bitmask_isbitset(bitmask, 0))
hwloc_bitmap_fill(nodeset);
else
hwloc_bitmap_zero(nodeset);
}
return 0;
}
/** @} */
#ifdef NUMA_VERSION1_COMPATIBILITY
/** \defgroup hwlocality_linux_libnuma_nodemask Helpers for manipulating Linux libnuma nodemask_t
* @{
*/
/** \brief Convert hwloc CPU set \p cpuset into libnuma nodemask \p nodemask
*
* This function may be used before calling some old libnuma functions
* that use a nodemask_t as an input parameter.
*/
static __hwloc_inline int
hwloc_cpuset_to_linux_libnuma_nodemask(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset,
nodemask_t *nodemask)
{
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
nodemask_zero(nodemask);
if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
hwloc_obj_t node = NULL;
while ((node = hwloc_get_next_obj_covering_cpuset_by_type(topology, cpuset, HWLOC_OBJ_NODE, node)) != NULL)
nodemask_set(nodemask, node->os_index);
} else {
/* if no numa, libnuma assumes we have a single node */
if (!hwloc_bitmap_iszero(cpuset))
nodemask_set(nodemask, 0);
}
return 0;
}
/** \brief Convert hwloc NUMA node set \p nodeset into libnuma nodemask \p nodemask
*
* This function may be used before calling some old libnuma functions
* that use a nodemask_t as an input parameter.
*/
static __hwloc_inline int
hwloc_nodeset_to_linux_libnuma_nodemask(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset,
nodemask_t *nodemask)
{
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
nodemask_zero(nodemask);
if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
hwloc_obj_t node = NULL;
while ((node = hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_NODE, node)) != NULL)
if (hwloc_bitmap_isset(nodeset, node->os_index))
nodemask_set(nodemask, node->os_index);
} else {
/* if no numa, libnuma assumes we have a single node */
if (!hwloc_bitmap_iszero(nodeset))
nodemask_set(nodemask, 0);
}
return 0;
}
/** \brief Convert libnuma nodemask \p nodemask into hwloc CPU set \p cpuset
*
* This function may be used before calling some old libnuma functions
* that use a nodemask_t as an output parameter.
*/
static __hwloc_inline int
hwloc_cpuset_from_linux_libnuma_nodemask(hwloc_topology_t topology, hwloc_cpuset_t cpuset,
const nodemask_t *nodemask)
{
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
hwloc_obj_t node;
int i;
hwloc_bitmap_zero(cpuset);
for(i=0; i<NUMA_NUM_NODES; i++)
if (nodemask_isset(nodemask, i)) {
node = hwloc_get_obj_by_depth(topology, depth, i);
if (node)
hwloc_bitmap_or(cpuset, cpuset, node->cpuset);
}
} else {
/* if no numa, libnuma assumes we have a single node */
if (nodemask_isset(nodemask, 0))
hwloc_bitmap_copy(cpuset, hwloc_topology_get_complete_cpuset(topology));
else
hwloc_bitmap_zero(cpuset);
}
return 0;
}
/** \brief Convert libnuma nodemask \p nodemask into hwloc NUMA node set \p nodeset
*
* This function may be used before calling some old libnuma functions
* that use a nodemask_t as an output parameter.
*/
static __hwloc_inline int
hwloc_nodeset_from_linux_libnuma_nodemask(hwloc_topology_t topology, hwloc_nodeset_t nodeset,
const nodemask_t *nodemask)
{
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
hwloc_obj_t node;
int i;
hwloc_bitmap_zero(nodeset);
for(i=0; i<NUMA_NUM_NODES; i++)
if (nodemask_isset(nodemask, i)) {
node = hwloc_get_obj_by_depth(topology, depth, i);
if (node)
hwloc_bitmap_set(nodeset, node->os_index);
}
} else {
/* if no numa, libnuma assumes we have a single node */
if (nodemask_isset(nodemask, 0))
hwloc_bitmap_fill(nodeset);
else
hwloc_bitmap_zero(nodeset);
}
return 0;
}
/** @} */
#endif /* NUMA_VERSION1_COMPATIBILITY */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* HWLOC_LINUX_NUMA_H */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment