Bring Portable Linux Processor Affinity into trunk.
Changes paffinity interface to use a cpu mask for available/preferred cpus rather than the current coarse grained paffinity that lets the OS choose which processor. Macros for setting and clearing masks are provided. Solaris and windows changes have not been made. Solaris subdirectory has some suggested changes - however the relevant man pages for the Solaris 10 APIs have some ambiguity regarding order in which one create and sets a processor set. As we did not have access to a solaris 10 machine we could not test to see the correct way to do the work under solaris. This commit was SVN r14887.
Этот коммит содержится в:
родитель
a5a7ccd7ec
Коммит
9b5f73976d
@ -73,6 +73,8 @@ OMPI_SAVE_VERSION([ORTE], [Open Run-Time Environment], [$srcdir/VERSION],
|
||||
OMPI_SAVE_VERSION([OPAL], [Open Portable Access Layer], [$srcdir/VERSION],
|
||||
[opal/include/opal/version.h])
|
||||
|
||||
AM_CONFIG_HEADER([opal/include/opal_config.h orte/include/orte_config.h ompi/include/ompi_config.h ompi/include/mpi.h])
|
||||
|
||||
# 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
|
||||
@ -1147,7 +1149,6 @@ OMPI_SETUP_WRAPPER_FINAL
|
||||
|
||||
ompi_show_subtitle "Final output"
|
||||
|
||||
AM_CONFIG_HEADER([opal/include/opal_config.h orte/include/orte_config.h ompi/include/ompi_config.h ompi/include/mpi.h])
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
|
||||
|
@ -302,8 +302,12 @@ int ompi_mpi_init(int argc, char **argv, int requested, int *provided)
|
||||
if (param >= 0) {
|
||||
if (OMPI_SUCCESS == mca_base_param_lookup_int(param, &value)) {
|
||||
if (value >= 0) {
|
||||
if (OPAL_SUCCESS == opal_paffinity_base_set(value)) {
|
||||
set = true;
|
||||
|
||||
opal_paffinity_base_cpu_set_t mpi_cpumask;
|
||||
OPAL_PAFFINITY_CPU_ZERO(mpi_cpumask);
|
||||
OPAL_PAFFINITY_CPU_SET(value,mpi_cpumask);
|
||||
if (OPAL_SUCCESS == opal_paffinity_base_set(mpi_cpumask)) {
|
||||
set = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
* University of Stuttgart. All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
@ -87,59 +88,40 @@ extern "C" {
|
||||
*/
|
||||
OPAL_DECLSPEC int opal_paffinity_base_select(void);
|
||||
|
||||
/**
|
||||
* Get the available number of processors
|
||||
*
|
||||
* @param num_procs Pointer to int where the number of processors
|
||||
* is returned
|
||||
*
|
||||
* @retval OPAL_SUCCESS upon success.
|
||||
* @retval OPAL_NOT_FOUND if no paffinity components are available.
|
||||
* @retval OPAL_ERROR upon other error.
|
||||
*
|
||||
* This function queries the selected paffinity component to find
|
||||
* out how many physical processors exist.
|
||||
*
|
||||
* If no paffinity components were available, or if the
|
||||
* opal_paffinity_base_select() was never invoked, OPAL_NOT_FOUND
|
||||
* is returned and num_procs is set to -1.
|
||||
*/
|
||||
OPAL_DECLSPEC int opal_paffinity_base_get_num_processors(int *num_procs);
|
||||
|
||||
/**
|
||||
* Set this process' affinity.
|
||||
*
|
||||
* @param id Virtual processor ID number
|
||||
* @param cpumask Virtual processor bitmask
|
||||
*
|
||||
* @retval OPAL_SUCCESS upon success
|
||||
* @retval OPAL_NOT_FOUND if no paffinity components are available.
|
||||
* @retval OPAL_ERROR upon other error.
|
||||
*
|
||||
* Set this process' affinity to the CPU ID \em id.
|
||||
* Set this process' affinity to the CPU's specified in \em cpumask
|
||||
*
|
||||
* If no paffinity components were available, or if the
|
||||
* opal_paffinity_base_select() was never invoked, OPAL_NOT_FOUND
|
||||
* is returned.
|
||||
*/
|
||||
OPAL_DECLSPEC int opal_paffinity_base_set(int id);
|
||||
OPAL_DECLSPEC int opal_paffinity_base_set(opal_paffinity_base_cpu_set_t cpumask);
|
||||
|
||||
/**
|
||||
* Get this process' affinity.
|
||||
*
|
||||
* @param id Pointer to virtual processor ID number
|
||||
* @param cpumask Pointer to virtual processor bitmask
|
||||
*
|
||||
* @retval OPAL_SUCCESS upon success
|
||||
* @retval OPAL_NOT_FOUND if no paffinity components are available.
|
||||
* @retval OPAL_ERROR upon other error.
|
||||
*
|
||||
* Get this process' CPU affinitity virtual ID number and assign
|
||||
* it to \em id.
|
||||
* Get this process' CPU affinity virtual bitmask and assign
|
||||
* it to \em cpumask.
|
||||
*
|
||||
* If no paffinity components were available, or if the
|
||||
* opal_paffinity_base_select() was never invoked, OPAL_NOT_FOUND
|
||||
* is returned and id is set to -1.
|
||||
* is returned and cpumask is zeroed out.
|
||||
*/
|
||||
OPAL_DECLSPEC int opal_paffinity_base_get(int *id);
|
||||
OPAL_DECLSPEC int opal_paffinity_base_get(opal_paffinity_base_cpu_set_t *cpumask);
|
||||
|
||||
/**
|
||||
* Shut down the paffinity MCA framework.
|
||||
@ -163,12 +145,12 @@ extern "C" {
|
||||
/**
|
||||
* Global component struct for the selected component
|
||||
*/
|
||||
OPAL_DECLSPEC extern const opal_paffinity_base_component_1_0_0_t
|
||||
OPAL_DECLSPEC extern const opal_paffinity_base_component_1_1_0_t
|
||||
*opal_paffinity_base_component;
|
||||
/**
|
||||
* Global module struct for the selected module
|
||||
*/
|
||||
OPAL_DECLSPEC extern const opal_paffinity_base_module_1_0_0_t
|
||||
OPAL_DECLSPEC extern const opal_paffinity_base_module_1_1_0_t
|
||||
*opal_paffinity_base_module;
|
||||
|
||||
/**
|
||||
|
@ -9,6 +9,7 @@
|
||||
* University of Stuttgart. All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2007 Cisco, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
@ -31,8 +32,8 @@
|
||||
* Globals
|
||||
*/
|
||||
bool opal_paffinity_base_selected = false;
|
||||
const opal_paffinity_base_component_1_0_0_t *opal_paffinity_base_component = NULL;
|
||||
const opal_paffinity_base_module_1_0_0_t *opal_paffinity_base_module = NULL;
|
||||
const opal_paffinity_base_component_1_1_0_t *opal_paffinity_base_component = NULL;
|
||||
const opal_paffinity_base_module_1_1_0_t *opal_paffinity_base_module = NULL;
|
||||
|
||||
|
||||
int opal_paffinity_base_select(void)
|
||||
@ -40,9 +41,9 @@ int opal_paffinity_base_select(void)
|
||||
int priority = 0, best_priority = 0;
|
||||
opal_list_item_t *item = NULL;
|
||||
mca_base_component_list_item_t *cli = NULL;
|
||||
opal_paffinity_base_component_1_0_0_t *component = NULL,
|
||||
opal_paffinity_base_component_1_1_0_t *component = NULL,
|
||||
*best_component = NULL;
|
||||
const opal_paffinity_base_module_1_0_0_t *module = NULL,
|
||||
const opal_paffinity_base_module_1_1_0_t *module = NULL,
|
||||
*best_module = NULL;
|
||||
char *value;
|
||||
|
||||
@ -71,7 +72,7 @@ int opal_paffinity_base_select(void)
|
||||
opal_list_get_end(&opal_paffinity_base_components_opened) != item;
|
||||
item = opal_list_get_next(item) ) {
|
||||
cli = (mca_base_component_list_item_t *) item;
|
||||
component = (opal_paffinity_base_component_1_0_0_t *) cli->cli_component;
|
||||
component = (opal_paffinity_base_component_1_1_0_t *) cli->cli_component;
|
||||
|
||||
/* if there is an include list - item must be in the list to
|
||||
be included */
|
||||
|
@ -9,6 +9,8 @@
|
||||
* University of Stuttgart. All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
|
||||
*
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
@ -22,31 +24,25 @@
|
||||
#include "opal/constants.h"
|
||||
#include "opal/mca/paffinity/paffinity.h"
|
||||
#include "opal/mca/paffinity/base/base.h"
|
||||
#include "opal/util/num_procs.h"
|
||||
|
||||
int opal_paffinity_base_get_num_processors(int *num_procs)
|
||||
{
|
||||
if (!opal_paffinity_base_selected) {
|
||||
return opal_get_num_processors(num_procs);
|
||||
}
|
||||
return opal_paffinity_base_module->paff_module_get_num_processors(num_procs);
|
||||
}
|
||||
|
||||
|
||||
int opal_paffinity_base_set(int id)
|
||||
int opal_paffinity_base_set(opal_paffinity_base_cpu_set_t cpumask)
|
||||
{
|
||||
if (!opal_paffinity_base_selected) {
|
||||
return OPAL_ERR_NOT_FOUND;
|
||||
}
|
||||
return opal_paffinity_base_module->paff_module_set(id);
|
||||
return opal_paffinity_base_module->paff_module_set(cpumask);
|
||||
}
|
||||
|
||||
|
||||
int opal_paffinity_base_get(int *id)
|
||||
int opal_paffinity_base_get(opal_paffinity_base_cpu_set_t *cpumask)
|
||||
{
|
||||
if (!opal_paffinity_base_selected) {
|
||||
*id = -1;
|
||||
if(NULL != cpumask) {
|
||||
OPAL_PAFFINITY_CPU_ZERO(*cpumask);
|
||||
}
|
||||
return OPAL_ERR_NOT_FOUND;
|
||||
}
|
||||
return opal_paffinity_base_module->paff_module_get(id);
|
||||
if(NULL == cpumask) {
|
||||
return OPAL_ERR_BAD_PARAM;
|
||||
}
|
||||
return opal_paffinity_base_module->paff_module_get(cpumask);
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
# University of Stuttgart. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
@ -16,6 +17,8 @@
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
SUBDIRS = plpa
|
||||
|
||||
sources = \
|
||||
paffinity_linux.h \
|
||||
paffinity_linux_component.c \
|
||||
@ -38,6 +41,7 @@ mcacomponent_LTLIBRARIES = $(component_install)
|
||||
mca_paffinity_linux_la_SOURCES = $(sources)
|
||||
mca_paffinity_linux_la_LDFLAGS = -module -avoid-version
|
||||
mca_paffinity_linux_la_LIBADD = \
|
||||
$(top_ompi_builddir)/opal/mca/paffinity/linux/plpa/src/libplpa/libplpa_included.la \
|
||||
$(top_ompi_builddir)/opal/libopen-pal.la
|
||||
|
||||
noinst_LTLIBRARIES = $(component_noinst)
|
||||
|
@ -10,6 +10,8 @@
|
||||
# University of Stuttgart. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
|
||||
#
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
@ -19,53 +21,12 @@
|
||||
|
||||
# MCA_paffinity_linux_CONFIG([action-if-found], [action-if-not-found])
|
||||
# -----------------------------------------------------------
|
||||
m4_include(opal/mca/paffinity/linux/plpa/config/plpa.m4)
|
||||
|
||||
AC_DEFUN([MCA_paffinity_linux_CONFIG],[
|
||||
# check for sched_setaffinity(), which originated in Linux kernel
|
||||
# 2.5.8, but was back-ported in several distro's 2.4 kernels.
|
||||
AC_CHECK_FUNC([sched_setaffinity],
|
||||
[$1],
|
||||
[$2])
|
||||
|
||||
#####################################################################
|
||||
# See lengthy comment in paffinity_linux.h for an explanation of
|
||||
# these tests.
|
||||
#####################################################################
|
||||
|
||||
AH_TEMPLATE([HAVE_cpu_set_t], [Whether we have the cpu_set_t type or not])
|
||||
AC_CHECK_TYPES([cpu_set_t],
|
||||
[AC_DEFINE([HAVE_cpu_set_t], [1])
|
||||
opal_paffinity_linux_have_cpu_set_t=1],
|
||||
[opal_paffinity_linux_have_cpu_set_t=0],
|
||||
[#include <sched.h>])
|
||||
|
||||
if test "$opal_paffinity_linux_have_cpu_set_t" = "1"; then
|
||||
|
||||
# Check to see if CPU_ZERO is functional (see comment in
|
||||
# paffinity_linux.h)
|
||||
|
||||
AC_MSG_CHECKING([whether CPU_ZERO is broken])
|
||||
AH_TEMPLATE([HAVE_CPU_ZERO], [Whether we have a functional CPU_ZERO macro or not])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <sched.h>],
|
||||
[cpu_set_t foo; CPU_ZERO(&foo);])],
|
||||
[AC_DEFINE(HAVE_CPU_ZERO, 1)
|
||||
AC_MSG_RESULT([no])], [AC_MSG_RESULT([yes])])
|
||||
|
||||
# Now check whether sched_setaffinity() takes 2 or 3
|
||||
# arguments (see comment in paffinity_linux.h)
|
||||
|
||||
AC_MSG_CHECKING([how many parameters sched_setaffinity() takes])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <sched.h>],
|
||||
[cpu_set_t foo; sched_setaffinity(0, sizeof(foo), &foo);])],
|
||||
[opal_paffinity_linux_ssnp=3],
|
||||
[opal_paffinity_linux_ssnp=2])
|
||||
AC_DEFINE_UNQUOTED(OPAL_PAFFINITY_LINUX_SCHED_SETAFF_NUM_PARAMS,
|
||||
$opal_paffinity_linux_ssnp,
|
||||
[How many parameters sched_setaffinity() takes (!)])
|
||||
AC_MSG_RESULT([$opal_paffinity_linux_ssnp])
|
||||
fi
|
||||
|
||||
# Clean up (not entirely necessary; just being social)
|
||||
|
||||
unset opal_paffinity_linux_have_cpu_set_t
|
||||
unset opal_paffinity_linux_ssnp
|
||||
paffinity_linux_CPPFLAGS="-Iopal/mca/paffinity/linux/plpa/src/libplpa"
|
||||
AC_SUBST([paffinity_linux_CPPFLAGS])
|
||||
PLPA_SET_SYMBOL_PREFIX([opal_paffinity_linux_plpa_])
|
||||
PLPA_INCLUDED([opal/mca/paffinity/linux/plpa])
|
||||
PLPA_INIT([$1],[$2])
|
||||
])dnl
|
||||
|
@ -9,6 +9,8 @@
|
||||
* University of Stuttgart. All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2006-2007 Cisco Systems, Inc. All rights reserved.
|
||||
*
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
@ -22,46 +24,15 @@
|
||||
* Processor affinity for Linux.
|
||||
*
|
||||
* Linux sucks. There are at least 3 different ways that
|
||||
* sched_setaffinity is implemented (only one of which -- the most
|
||||
* outdated -- is documented in the sched_setaffinity(2) man page):
|
||||
* sched_setaffinity is implemented.
|
||||
*
|
||||
*-----------------------------------------------------------------
|
||||
* 1. int sched_setaffinity(pid_t pid, unsigned int len, unsigned
|
||||
* long *mask);
|
||||
* Fortunately we have an independent project called Portable Linux
|
||||
* Processor Affinity (PLPA) which allows us to do processor affinity
|
||||
* without knowing which flavor of afffinity is installed on the
|
||||
* system a priori - PLPA does a few probes behind the scenes and
|
||||
* utilizes the correct syntax to the correct system call to set
|
||||
* or get processor affinity for us.
|
||||
*
|
||||
* This originated in 2.5 kernels (which we won't worry about) and
|
||||
* some distros back-ported it to their 2.4 kernels. It's unknown if
|
||||
* this appears in any 2.6 kernels.
|
||||
*
|
||||
* 2. int sched_setaffinity (pid_t __pid, size_t __cpusetsize,
|
||||
* const cpu_set_t *__cpuset);
|
||||
*
|
||||
* This appears to be in recent 2.6 kernels (confirmed in Gentoo
|
||||
* 2.6.11). I don't know when #1 changed into #2. However, this
|
||||
* prototype is nice -- the cpu_set_t type is accompanied by
|
||||
* fdset-like CPU_ZERO(), CPU_SET(), CPU_ISSET(), etc. macros.
|
||||
*
|
||||
* 3. int sched_setaffinity (pid_t __pid, const cpu_set_t *__mask);
|
||||
*
|
||||
* (note the missing len parameter) This is in at least some Linux
|
||||
* distros (e.g., MDK 10.0 with a 2.6.3 kernel, and SGI Altix, even
|
||||
* though the Altix uses a 2.4-based kernel and therefore likely
|
||||
* back-ported the 2.5 work but modified it for their needs). Similar
|
||||
* to #2, the cpu_set_t type is accompanied by fdset-like CPU_ZERO(),
|
||||
* CPU_SET(), CPU_ISSET(), etc. macros.
|
||||
*-----------------------------------------------------------------
|
||||
*
|
||||
* This component has to figure out which one to use. :-\
|
||||
*
|
||||
* Also note that at least some distros of Linux have a broken
|
||||
* CPU_ZERO macro (a pair of typos in /usr/include/bits/sched.h).
|
||||
* MDK 9.2 is the screaming example, but it's pretty old and
|
||||
* probably only matters because one of the developers uses that as
|
||||
* a compilation machine :-) (it also appears to have been fixed in
|
||||
* MDK 10.0, but they also changed from #2 to #3 -- arrgh!).
|
||||
* However, there's no way of knowing where these typos came from
|
||||
* and if they exist elsewhere. So it seems safest to extend this
|
||||
* configure script to check for a bad CPU_ZERO macro. #$%#@%$@!!!
|
||||
*/
|
||||
|
||||
|
||||
@ -72,18 +43,7 @@
|
||||
|
||||
#include "opal/mca/mca.h"
|
||||
#include "opal/mca/paffinity/paffinity.h"
|
||||
|
||||
|
||||
/**
|
||||
* Determine whether we have a working CPU_ZERO() macro or not. If
|
||||
* not, use memset().
|
||||
*/
|
||||
#ifdef HAVE_CPU_ZERO
|
||||
#define OMPI_CPU_ZERO(foo) CPU_ZERO(foo)
|
||||
#else
|
||||
#include <string.h>
|
||||
#define OMPI_CPU_ZERO(foo) memset(foo, 0, sizeof(*foo))
|
||||
#endif
|
||||
#include "opal/mca/paffinity/linux/plpa/src/libplpa/plpa.h"
|
||||
|
||||
|
||||
#if defined(c_plusplus) || defined(__cplusplus)
|
||||
@ -93,14 +53,14 @@ extern "C" {
|
||||
/**
|
||||
* Globally exported variable
|
||||
*/
|
||||
OPAL_DECLSPEC extern const opal_paffinity_base_component_1_0_0_t
|
||||
OPAL_DECLSPEC extern const opal_paffinity_base_component_1_1_0_t
|
||||
mca_paffinity_linux_component;
|
||||
|
||||
|
||||
/**
|
||||
* paffinity query API function
|
||||
*/
|
||||
const opal_paffinity_base_module_1_0_0_t *
|
||||
const opal_paffinity_base_module_1_1_0_t *
|
||||
opal_paffinity_linux_component_query(int *query);
|
||||
|
||||
#if defined(c_plusplus) || defined(__cplusplus)
|
||||
|
@ -9,6 +9,7 @@
|
||||
* University of Stuttgart. All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2007 Cisco, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
@ -44,16 +45,16 @@ static int linux_open(void);
|
||||
* and pointers to our public functions in it
|
||||
*/
|
||||
|
||||
const opal_paffinity_base_component_1_0_0_t mca_paffinity_linux_component = {
|
||||
const opal_paffinity_base_component_1_1_0_t mca_paffinity_linux_component = {
|
||||
|
||||
/* First, the mca_component_t struct containing meta information
|
||||
about the component itself */
|
||||
|
||||
{
|
||||
/* Indicate that we are a paffinity v1.0.0 component (which also
|
||||
/* Indicate that we are a paffinity v1.1.0 component (which also
|
||||
implies a specific MCA version) */
|
||||
|
||||
OPAL_PAFFINITY_BASE_VERSION_1_0_0,
|
||||
OPAL_PAFFINITY_BASE_VERSION_1_1_0,
|
||||
|
||||
/* Component name and version */
|
||||
|
||||
@ -67,10 +68,8 @@ const opal_paffinity_base_component_1_0_0_t mca_paffinity_linux_component = {
|
||||
linux_open,
|
||||
NULL
|
||||
},
|
||||
|
||||
/* Next the MCA v1.0.0 component meta data */
|
||||
|
||||
{
|
||||
|
||||
/* The component is checkpoint ready */
|
||||
MCA_BASE_METADATA_PARAM_CHECKPOINT
|
||||
},
|
||||
@ -88,44 +87,5 @@ static int linux_open(void)
|
||||
"Priority of the linux paffinity component",
|
||||
false, false, 10, NULL);
|
||||
|
||||
mca_base_param_reg_int(&mca_paffinity_linux_component.paffinityc_version,
|
||||
"have_cpu_set_t",
|
||||
"Whether this component was compiled on a system with the type cpu_set_t or not (1 = yes, 0 = no)",
|
||||
false, true,
|
||||
#ifdef HAVE_cpu_set_t
|
||||
HAVE_cpu_set_t,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
NULL);
|
||||
mca_base_param_reg_int(&mca_paffinity_linux_component.paffinityc_version,
|
||||
"CPU_ZERO_ok",
|
||||
"Whether this component was compiled on a system where CPU_ZERO() is functional or broken (1 = functional, 0 = broken/not available)",
|
||||
false, true,
|
||||
#ifdef HAVE_CPU_ZERO
|
||||
HAVE_CPU_ZERO,
|
||||
#else
|
||||
/* If we don't have cpu_set_t, then the
|
||||
macro CPU_ZERO does not exist */
|
||||
0,
|
||||
#endif
|
||||
NULL);
|
||||
mca_base_param_reg_int(&mca_paffinity_linux_component.paffinityc_version,
|
||||
"sched_setaffinity_num_params",
|
||||
"The number of parameters that sched_set_affinity() takes on the machine where this component was compiled",
|
||||
false, true,
|
||||
#ifdef OPAL_PAFFINITY_LINUX_SCHED_SETAFF_NUM_PARAMS
|
||||
OPAL_PAFFINITY_LINUX_SCHED_SETAFF_NUM_PARAMS,
|
||||
#else
|
||||
/* If we do not have cpu_set_t, we don't
|
||||
check for the number of params (and
|
||||
therefore OPAL_..._SETAFF_NUM_PARAMS is
|
||||
undefined), because the only variant
|
||||
that does not have the type cpu_set_t
|
||||
has 3 params for sched_set_affinity() */
|
||||
3,
|
||||
#endif
|
||||
NULL);
|
||||
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
@ -9,6 +9,8 @@
|
||||
* University of Stuttgart. All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2006-2007 Cisco Systems, Inc. All rights reserved.
|
||||
*
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
@ -22,14 +24,6 @@
|
||||
guaranteed to have <unistd.h> and friends */
|
||||
#include <stdio.h>
|
||||
|
||||
/* the affinity macros are only exposed if __USE_GNU is set (at least,
|
||||
on Suse Linux for PPC). However, __USE_GNU causes problems for
|
||||
some compilers (IBM XL) with stdio.h. So include stdio.h, then
|
||||
set __USE_GNU. */
|
||||
#ifndef __USE_GNU
|
||||
#define __USE_GNU 1
|
||||
#endif
|
||||
#include <sched.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -40,20 +34,20 @@
|
||||
#include "opal/mca/paffinity/paffinity.h"
|
||||
#include "opal/mca/paffinity/base/base.h"
|
||||
#include "paffinity_linux.h"
|
||||
#include "plpa/src/libplpa/plpa.h"
|
||||
|
||||
|
||||
/*
|
||||
* Local functions
|
||||
*/
|
||||
static int linux_module_init(void);
|
||||
static int linux_module_get_num_procs(int *num_procs);
|
||||
static int linux_module_set(int id);
|
||||
static int linux_module_get(int *id);
|
||||
static int linux_module_set(opal_paffinity_base_cpu_set_t cpumask);
|
||||
static int linux_module_get(opal_paffinity_base_cpu_set_t *cpumask);
|
||||
|
||||
/*
|
||||
* Linux paffinity module
|
||||
*/
|
||||
static const opal_paffinity_base_module_1_0_0_t module = {
|
||||
static const opal_paffinity_base_module_1_1_0_t module = {
|
||||
|
||||
/* Initialization function */
|
||||
|
||||
@ -61,13 +55,12 @@ static const opal_paffinity_base_module_1_0_0_t module = {
|
||||
|
||||
/* Module function pointers */
|
||||
|
||||
linux_module_get_num_procs,
|
||||
linux_module_set,
|
||||
linux_module_get
|
||||
};
|
||||
|
||||
|
||||
const opal_paffinity_base_module_1_0_0_t *
|
||||
const opal_paffinity_base_module_1_1_0_t *
|
||||
opal_paffinity_linux_component_query(int *query)
|
||||
{
|
||||
int param;
|
||||
@ -87,196 +80,70 @@ static int linux_module_init(void)
|
||||
}
|
||||
|
||||
|
||||
static int linux_module_get_num_procs(int *num_procs)
|
||||
{
|
||||
*num_procs = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
See the note in paffinity_linux.h -- there are at least 3 different
|
||||
ways that Linux's sched_setaffinity()/sched_getaffinity() are
|
||||
implemented. Hence, rather than trying to pepper #if's all
|
||||
throughout the code, just have multiple implementations of these
|
||||
module functions.
|
||||
implemented. Thankfully there is the Portable Linux Processor
|
||||
Affinity project which determines the flavor of affinity at runtime
|
||||
and takes care of of the problem.
|
||||
|
||||
Using get/set affinity functions from plpa - configured with an
|
||||
opal prefix.
|
||||
|
||||
User needs to set a mask with the bit number of the cpu set. We provide
|
||||
macros to do this.
|
||||
|
||||
************************************************************************/
|
||||
|
||||
#if !defined(HAVE_CPU_SET_T)
|
||||
|
||||
/************************************************************************
|
||||
If we don't have cpu_set_t, then we have the "old style" Linux
|
||||
sched_setaffinity():
|
||||
|
||||
int sched_setaffinity(pid_t pid, unsigned int len, unsigned long
|
||||
*mask);
|
||||
int sched_getaffinity(pid_t pid, unsigned int len, unsigned long
|
||||
*mask);
|
||||
|
||||
We do not have the CPU_ZERO(), CPU_SET(), CPU_ISSET(), etc. macros.
|
||||
************************************************************************/
|
||||
|
||||
static int make_mask(unsigned int *len, unsigned long **mask)
|
||||
static int linux_module_set(opal_paffinity_base_cpu_set_t mask)
|
||||
{
|
||||
int num_procs;
|
||||
|
||||
linux_module_get_num_procs(&num_procs);
|
||||
*len = num_procs / 8;
|
||||
if (*len != (unsigned int)(num_procs * 8)) {
|
||||
++*len;
|
||||
}
|
||||
|
||||
/* Ensure *len is a multiple of sizeof(long) */
|
||||
|
||||
if (*len != (*len / sizeof(long)) * sizeof(long)) {
|
||||
*len += sizeof(long) - (*len % sizeof(long));
|
||||
}
|
||||
|
||||
/* Malloc */
|
||||
|
||||
*mask = malloc(*len);
|
||||
if (NULL == *mask) {
|
||||
return OPAL_ERR_OUT_OF_RESOURCE;
|
||||
}
|
||||
memset(*mask, 0, *len);
|
||||
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int linux_module_set(int id)
|
||||
{
|
||||
int ret, num_procs, byte, bit;
|
||||
unsigned int len;
|
||||
unsigned long *mask;
|
||||
|
||||
linux_module_get_num_procs(&num_procs);
|
||||
if (id >= num_procs || id < 0) {
|
||||
return OPAL_ERR_BAD_PARAM;
|
||||
}
|
||||
|
||||
if (OPAL_SUCCESS != (ret = make_mask(&len, &mask))) {
|
||||
return ret;
|
||||
}
|
||||
byte = id / 8;
|
||||
bit = id % 8;
|
||||
((char *) mask)[byte] = 1 << bit;
|
||||
|
||||
ret = sched_setaffinity(0, len, mask);
|
||||
|
||||
bit = errno;
|
||||
free(mask);
|
||||
errno = bit;
|
||||
return (0 == ret) ? OPAL_SUCCESS : OPAL_ERR_IN_ERRNO;
|
||||
}
|
||||
|
||||
|
||||
static int linux_module_get(int *id)
|
||||
{
|
||||
int ret, save, byte, bit;
|
||||
unsigned int i, len;
|
||||
unsigned long *mask;
|
||||
|
||||
if (OPAL_SUCCESS != (ret = make_mask(&len, &mask))) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (0 != sched_getaffinity(0, len, mask)) {
|
||||
save = errno;
|
||||
free(mask);
|
||||
errno = save;
|
||||
return OPAL_ERR_IN_ERRNO;
|
||||
}
|
||||
*id = -1;
|
||||
for (i = 0; i < sizeof(mask); ++i) {
|
||||
byte = i / 8;
|
||||
bit = i % 8;
|
||||
if (0 != (mask[byte] & (1 << bit))) {
|
||||
*id = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(mask);
|
||||
if (-1 == *id) {
|
||||
return OPAL_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/************************************************************************
|
||||
In this case, we're using the following prototypes for the affinity
|
||||
functions (case 2)
|
||||
|
||||
int sched_setaffinity (pid_t __pid, size_t __cpusetsize, const
|
||||
cpu_set_t *__cpuset);
|
||||
int sched_getaffinity (pid_t __pid, size_t __cpusetsize, const
|
||||
cpu_set_t *__cpuset);
|
||||
|
||||
or
|
||||
|
||||
int sched_setaffinity (pid_t __pid, const cpu_set_t *__cpuset);
|
||||
int sched_getaffinity (pid_t __pid, const cpu_set_t *__cpuset);
|
||||
|
||||
The only difference is the missing size_t parameter, which is easy
|
||||
to determine inline, below.
|
||||
|
||||
We also have the CPU_ZERO(), CPU_SET(), CPU_ISSET(), etc. macros
|
||||
(but CPU_ZERO() may not work, so use the indirection
|
||||
OMPI_CPU_ZERO()).
|
||||
************************************************************************/
|
||||
|
||||
static int linux_module_set(int id)
|
||||
{
|
||||
int num_procs;
|
||||
cpu_set_t mask;
|
||||
|
||||
linux_module_get_num_procs(&num_procs);
|
||||
if (id >= num_procs || id < 0) {
|
||||
return OPAL_ERR_BAD_PARAM;
|
||||
}
|
||||
|
||||
OMPI_CPU_ZERO(&mask);
|
||||
CPU_SET(id, &mask);
|
||||
|
||||
if (0 != sched_setaffinity(0,
|
||||
#if OPAL_PAFFINITY_LINUX_SCHED_SETAFF_NUM_PARAMS == 3
|
||||
sizeof(mask),
|
||||
#endif
|
||||
&mask)) {
|
||||
return OPAL_ERR_IN_ERRNO;
|
||||
}
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int linux_module_get(int *id)
|
||||
{
|
||||
opal_paffinity_linux_plpa_cpu_set_t plpa_mask;
|
||||
unsigned int i;
|
||||
cpu_set_t mask;
|
||||
|
||||
OMPI_CPU_ZERO(&mask);
|
||||
if (0 != sched_getaffinity(0,
|
||||
#if OPAL_PAFFINITY_LINUX_SCHED_SETAFF_NUM_PARAMS == 3
|
||||
sizeof(mask),
|
||||
#endif
|
||||
&mask)) {
|
||||
if (sizeof(mask) > sizeof(plpa_mask)) {
|
||||
return OPAL_ERR_BAD_PARAM;
|
||||
} else {
|
||||
PLPA_CPU_ZERO(&plpa_mask);
|
||||
for (i = 0; i < sizeof(plpa_mask) ; i++) {
|
||||
if (PLPA_CPU_ISSET(i,&mask)) {
|
||||
PLPA_CPU_SET(i,&plpa_mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != opal_paffinity_linux_plpa_sched_setaffinity(getpid(),
|
||||
sizeof(plpa_mask),
|
||||
&plpa_mask)) {
|
||||
return OPAL_ERR_IN_ERRNO;
|
||||
}
|
||||
*id = -1;
|
||||
for (i = 0; i < sizeof(mask); ++i) {
|
||||
if (CPU_ISSET(i, &mask)) {
|
||||
*id = i;
|
||||
break;
|
||||
}
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int linux_module_get(opal_paffinity_base_cpu_set_t *mask)
|
||||
{
|
||||
opal_paffinity_linux_plpa_cpu_set_t plpa_mask;
|
||||
unsigned int i;
|
||||
|
||||
if (NULL == mask) {
|
||||
return OPAL_ERR_BAD_PARAM;
|
||||
}
|
||||
if (-1 == *id) {
|
||||
return OPAL_ERR_NOT_FOUND;
|
||||
|
||||
if (sizeof(*mask) > sizeof(plpa_mask)) {
|
||||
return OPAL_ERR_BAD_PARAM; /* look up in header file */
|
||||
}
|
||||
|
||||
if (0 != opal_paffinity_linux_plpa_sched_getaffinity(getpid(), sizeof(plpa_mask), &plpa_mask)) {
|
||||
return OPAL_ERR_IN_ERRNO;
|
||||
}
|
||||
for (i = 0; i < sizeof(mask); i++) {
|
||||
if (PLPA_CPU_ISSET(i,&plpa_mask)) {
|
||||
PLPA_CPU_SET(i,mask);
|
||||
}
|
||||
}
|
||||
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
13
opal/mca/paffinity/linux/plpa/AUTHORS
Обычный файл
13
opal/mca/paffinity/linux/plpa/AUTHORS
Обычный файл
@ -0,0 +1,13 @@
|
||||
PLPA Authors
|
||||
============
|
||||
|
||||
The IDs in parenthesis are those used in Subversion commit notices.
|
||||
|
||||
Current Authors
|
||||
---------------
|
||||
|
||||
Indiana University:
|
||||
- Jeff Squyres (jsquyres)
|
||||
|
||||
Lawrence Berkeley National Lab:
|
||||
- Paul Hargrove (phargrov)
|
57
opal/mca/paffinity/linux/plpa/LICENSE
Обычный файл
57
opal/mca/paffinity/linux/plpa/LICENSE
Обычный файл
@ -0,0 +1,57 @@
|
||||
Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana
|
||||
University Research and Technology
|
||||
Corporation. All rights reserved.
|
||||
Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
All rights reserved.
|
||||
Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
|
||||
|
||||
Portions copyright:
|
||||
|
||||
Copyright (c) 2004-2005 The University of Tennessee and The University
|
||||
of Tennessee Research Foundation. All rights
|
||||
reserved.
|
||||
Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
||||
University of Stuttgart. All rights reserved.
|
||||
Copyright (c) 2006, 2007 Advanced Micro Devices, Inc.
|
||||
All rights reserved.
|
||||
|
||||
$COPYRIGHT$
|
||||
|
||||
Additional copyrights may follow
|
||||
|
||||
$HEADER$
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer listed
|
||||
in this license in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
- Neither the name of the copyright holders nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
The copyright holders provide no reassurances that the source code
|
||||
provided does not infringe any patent, copyright, or any other
|
||||
intellectual property rights of third parties. The copyright holders
|
||||
disclaim any liability to any recipient for claims brought against
|
||||
recipient by any third party for infringement of that parties
|
||||
intellectual property rights.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
19
opal/mca/paffinity/linux/plpa/Makefile.am
Обычный файл
19
opal/mca/paffinity/linux/plpa/Makefile.am
Обычный файл
@ -0,0 +1,19 @@
|
||||
#
|
||||
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
# University Research and Technology
|
||||
# Corporation. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
SUBDIRS = src
|
||||
DIST_SUBDIRS = config $(SUBDIRS)
|
||||
EXTRA_DIST = README VERSION LICENSE AUTHORS
|
||||
|
||||
dist-hook:
|
||||
csh "$(top_srcdir)/config/distscript.csh" "$(top_srcdir)" "$(distdir)" "$(PLPA_VERSION)" "$(PLPA_SVN_R)"
|
95
opal/mca/paffinity/linux/plpa/NEWS
Обычный файл
95
opal/mca/paffinity/linux/plpa/NEWS
Обычный файл
@ -0,0 +1,95 @@
|
||||
Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana
|
||||
University Research and Technology
|
||||
Corporation. All rights reserved.
|
||||
Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
All rights reserved.
|
||||
Copyright (c) 2006-2007 Cisco Systems, Inc. All rights reserved.
|
||||
$COPYRIGHT$
|
||||
|
||||
Additional copyrights may follow
|
||||
|
||||
$HEADER$
|
||||
|
||||
===========================================================================
|
||||
|
||||
This file contains the main features as well as overviews of specific
|
||||
bug fixes (and other actions) for each version of PLPA since
|
||||
version 1.0.
|
||||
|
||||
1.1
|
||||
---
|
||||
|
||||
- New command: plpa-taskset. It is intended as a drop-in replacement
|
||||
for the "taskset" command, except it also understands sockets and
|
||||
cores. See the man page for more details.
|
||||
- Renamed "plpa_info" to "plpa-info".
|
||||
- Added PLPA_{MAJOR|MINOR|RELEASE}_VERSION integer macros in plpa.h.
|
||||
This release, they have the values of 1, 1, and 0, respectively.
|
||||
- Add new API functions to map from (socket,core) back and forth from
|
||||
the Linux virtual processor ID. Thanks to AMD for the initial code
|
||||
contribution that made this possible. See the man page for
|
||||
plpa_map_to_processor_id(3) as a starting point for more
|
||||
information.
|
||||
- Added man pages for executables and API functions.
|
||||
- Various fixes to "included" mode.
|
||||
|
||||
|
||||
1.0.5
|
||||
-----
|
||||
|
||||
- Fix an issue where the PLPA get/set affinity functions would only
|
||||
operate on the current process; the PID argument to these functions
|
||||
was effectively ignored.
|
||||
|
||||
|
||||
1.0.4
|
||||
-----
|
||||
|
||||
- Fix some 64 bit issues. Thanks to David Creasy for reporting the
|
||||
problems.
|
||||
- Fix plpa.h to be C++-friendly. Thanks to Emmanuel Paris for
|
||||
pointing out this problem.
|
||||
|
||||
|
||||
1.0.3
|
||||
-----
|
||||
|
||||
- Resolve some sizing / units ambiguities that mistakenly did not make
|
||||
it into 1.0.1. Thanks to Bert Wesarg for pointing these problems out.
|
||||
|
||||
|
||||
1.0.2
|
||||
-----
|
||||
|
||||
- Ensure that plpa_sched_[set|get]affinity() returns 0 upon success.
|
||||
Thanks to David Creasy for bringing this to our attention.
|
||||
|
||||
|
||||
1.0.1
|
||||
-----
|
||||
|
||||
- Specify that cpusetsize should be in units of bytes and add some
|
||||
missing "* 8"'s in plpa_dispatch.c.
|
||||
|
||||
|
||||
1.0
|
||||
---
|
||||
|
||||
- Initial release.
|
||||
|
||||
|
||||
0.9a2
|
||||
-----
|
||||
|
||||
- Change the back-end type of the plpa_bitmask_t to unsigned long
|
||||
instead of unsigned char to avoid an endian problem.
|
||||
- No longer attempt to set the affinity in plpa_api_probe() to avoid a
|
||||
possible race condition (setting it after getting it).
|
||||
- Fix PLPA_CPU_ZERO macro. Thanks to Bogdan Costescu for pointing
|
||||
this out.
|
||||
|
||||
|
||||
0.9a1
|
||||
-----
|
||||
|
||||
Initial public release.
|
484
opal/mca/paffinity/linux/plpa/README
Обычный файл
484
opal/mca/paffinity/linux/plpa/README
Обычный файл
@ -0,0 +1,484 @@
|
||||
Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana
|
||||
University Research and Technology
|
||||
Corporation. All rights reserved.
|
||||
Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
All rights reserved.
|
||||
Copyright (c) 2006-2007 Cisco Systems, Inc. All rights reserved.
|
||||
$COPYRIGHT$
|
||||
|
||||
See LICENSE file for a rollup of all copyright notices.
|
||||
|
||||
$HEADER$
|
||||
|
||||
===========================================================================
|
||||
|
||||
This is the Portable Linux Processor Affinity (PLPA) package
|
||||
(pronounced "pli-pa"). It is intended for developers who wish to use
|
||||
Linux processor affinity via the sched_setaffinity() and
|
||||
sched_getaffinity() library calls, but don't want to wade through the
|
||||
morass of 3 different APIs that have been offered through the life of
|
||||
these calls in various Linux distributions and glibc versions.
|
||||
|
||||
Specifically, to compile for any given Linux system, you need some
|
||||
complex compile-time tests to figure out which of the 3 APIs to use.
|
||||
And if you want your application to be binary portable across
|
||||
different Linux distributions, more complex run-time tests (and horrid
|
||||
compile-time trickery) are required to figure out which API the system
|
||||
you are running on uses.
|
||||
|
||||
These problems all stem from the fact that the same 2 symbols have had
|
||||
three different APIs (with different numbers and types of
|
||||
parameters) throughout their life in Linux. Ick.
|
||||
|
||||
The PLPA is an attempt to solve this problem by providing a single API
|
||||
that developers can write to. It provides three things:
|
||||
|
||||
1. A single API that developers can write to, regardless of what
|
||||
back-end API the system you are compiling on has.
|
||||
2. A run-time test and dispatch that will invoke the Right back-end
|
||||
API depending on what back-end API the system you are running on
|
||||
has.
|
||||
3. Mapping information between (socket, core) tuples and Linux virtual
|
||||
processor IDs.
|
||||
|
||||
This package is actually pretty small. It does not attempt to have
|
||||
many extra bells and whistles. Anyone could write it and package it.
|
||||
We did it simply because it appears that no one else has yet done
|
||||
this. In a world where larger scale SMPs are [again] becoming more
|
||||
common, particularly where at least some of them are NUMA-based
|
||||
architectures, processor affinity is going to become more and more
|
||||
important. Just because developers have not yet realized that they
|
||||
have this problem does not mean that they won't evenutally figure it
|
||||
out. :-)
|
||||
|
||||
Note that if you're looking into processor affinity, if you're on a
|
||||
NUMA machine, you probably also want to look into libnuma:
|
||||
|
||||
ftp://ftp.suse.com/pub/people/ak/numa/
|
||||
|
||||
We hope that PLPA helps you.
|
||||
|
||||
===========================================================================
|
||||
|
||||
What, exactly, is the problem?
|
||||
------------------------------
|
||||
|
||||
There are at least 3 different ways that sched_setaffinity is
|
||||
implemented in glibc (only one of which is documented in the
|
||||
sched_setaffinity(2) man page), and some corresponding changes
|
||||
to what the kernel considers to be valid arguments:
|
||||
|
||||
1. int sched_setaffinity(pid_t pid, unsigned int len, unsigned
|
||||
long *mask);
|
||||
|
||||
This originated in the time period of 2.5 kernels and some distros
|
||||
back-ported it to their 2.4 kernels and libraries. It's unknown if
|
||||
this version was ever packaged with any 2.6 kernels.
|
||||
|
||||
2. int sched_setaffinity (pid_t __pid, size_t __cpusetsize,
|
||||
const cpu_set_t *__cpuset);
|
||||
|
||||
This appears to be in recent distros using 2.6 kernels. We don't
|
||||
know exactly when #1 changed into #2. However, this prototype is nice
|
||||
because the cpu_set_t type is accompanied by fdset-like CPU_ZERO(),
|
||||
CPU_SET(), CPU_ISSET(), etc. macros.
|
||||
|
||||
3. int sched_setaffinity (pid_t __pid, const cpu_set_t *__mask);
|
||||
|
||||
(note the missing len parameter) This is in at least some Linux
|
||||
distros (e.g., MDK 10.0 with a 2.6.3 kernel, and SGI Altix, even
|
||||
though the Altix uses a 2.4-based kernel and therefore likely
|
||||
back-ported the 2.5 work or originated it in the first place).
|
||||
Similar to #2, the cpu_set_t type is accompanied by fdset-like
|
||||
CPU_ZERO(), CPU_SET(), CPU_ISSET(), etc. macros.
|
||||
|
||||
But wait, it gets worse.
|
||||
|
||||
Remember that getting/setting processor affinity has to involve the
|
||||
kernel. The sched_[sg]etaffinity() glibc functions typically do a
|
||||
little error checking and then make a syscall down into the kernel to
|
||||
actually do the work. There are multiple possibilities for problems
|
||||
here as the amount of checking has changed:
|
||||
|
||||
1. The glibc may support the affinity functions, but the kernel may
|
||||
not (and vice versa).
|
||||
|
||||
This is typically only an issue with slightly older Linux distributions.
|
||||
Mandrake 9.2 is an example of this. PLPA can detect this at run-time
|
||||
and turn its internal functions into no-ops and return appropriate error
|
||||
codes (ENOSYS).
|
||||
|
||||
2. The glibc affinity functions may be buggy (i.e., they pass bad data
|
||||
down to the syscall).
|
||||
|
||||
This is fortunately restricted to some older versions of glibc, and
|
||||
is relatively easy to check for at run-time. PLPA reliably detects
|
||||
this situation at run-time and returns appropriate error codes
|
||||
(ENOSYS).
|
||||
|
||||
The original SuSE 9.1 version seems to have this problem, but it was
|
||||
fixed it somewhere in the SuSE patching history (it is unknown exactly
|
||||
when). Specifically, updating to the latest SuSE 9.1 patch level
|
||||
(as of Dec 2005) seems to fix the problem.
|
||||
|
||||
3. The CPU_* macros for manipulating cpu_set_t bitmasks may not
|
||||
compile because of typo bugs in system header files.
|
||||
|
||||
PLPA avoids this problem by providing its own PLPA_CPU_* macros for
|
||||
manipulating CPU bitmasks. See "How do I use PLPA?", below, for
|
||||
more details.
|
||||
|
||||
The PLPA avoids all the glibc issues by using syscall() to directly
|
||||
access the kernel set and get affinity functions. This is described
|
||||
below.
|
||||
|
||||
===========================================================================
|
||||
|
||||
How does PLPA work?
|
||||
-------------------
|
||||
|
||||
Jeff Squyres initially sent a mail to the Open MPI developer's mailing
|
||||
list explaining the Linux processor affinity problems and asking for
|
||||
help coming up with a solution (particularly for binary
|
||||
compatibility):
|
||||
|
||||
http://www.open-mpi.org/community/lists/devel/2005/11/0558.php
|
||||
|
||||
Discussion on that thread and others eventually resulted in the
|
||||
run-time tests that form the heart of the PLPA. Many thanks to Paul
|
||||
Hargrove and Bogdan Costescu for their time and effort to get these
|
||||
tests right.
|
||||
|
||||
PLPA was written so that other developers who want to use processor
|
||||
affinity in Linux don't have to go through this mess. The PLPA
|
||||
provides a single interface that can be used on any platform,
|
||||
regardless of which back-end API variant it has. This includes both
|
||||
the sched_setaffinity() and sched_getaffinity() calls as well as the
|
||||
CPU_*() macros.
|
||||
|
||||
The PLPA avoids glibc altogether -- although tests were developed that
|
||||
could *usually* figure out which glibc variant to use at run time,
|
||||
there were still some cases where it was either impossible to
|
||||
determine or the glibc interface itself was buggy. Hence, it was
|
||||
decided that a simpler approach was simply to use syscall() to invoke
|
||||
the back-end kernel functions directly.
|
||||
|
||||
The kernel functions have gone through a few changes as well, so the
|
||||
PLPA does a few run-time tests to determine which variant to use
|
||||
before actually invoking the back-end functions with the
|
||||
user-specified arguments.
|
||||
|
||||
NOTE: The run-time tests that the PLPA performs involve getting the
|
||||
current affinity for the process in question and then attempting to
|
||||
set them back to the same value. By definition, this introduces a
|
||||
race condition (there is no atomic get-and-set functionality for
|
||||
processor affinity). The PLPA cannot guarantee consistent results if
|
||||
multiple entities (such as multiple threads or multiple processes) are
|
||||
setting the affinity for a process at the same time. In a worst case
|
||||
scenario, the PLPA may actually determine that it cannot determine the
|
||||
kernel variant at run time if another entity modifies a process'
|
||||
affinity while PLPA is executing its run-time tests.
|
||||
|
||||
===========================================================================
|
||||
|
||||
Does PLPA make truly portable binaries?
|
||||
---------------------------------------
|
||||
|
||||
As much as Linux binaries are portable, yes. That is, if you have
|
||||
within your power to make a binary that is runnable on several
|
||||
different Linux distributions/versions/etc., then you may run into
|
||||
problems with the Linux processor affinity functions. PLPA attempts
|
||||
to solve this problem for you by *also* making the Linux processor
|
||||
affinity calls be binary portable.
|
||||
|
||||
Hence, you need to start with something that is already binary
|
||||
portable (perhaps linking everything statically) -- then PLPA will be
|
||||
of help to you. Do not fall into the misconception that PLPA will
|
||||
magically make your executable be binary portable between different
|
||||
Linux variants.
|
||||
|
||||
===========================================================================
|
||||
|
||||
How do I use PLPA?
|
||||
------------------
|
||||
|
||||
There are two main uses of the PLPA:
|
||||
|
||||
1. Using the plpa_info executable to check if your system supports
|
||||
processor affinity and the PLPA can determine which to use at run-time.
|
||||
2. Developers using the PLPA library to enable source and binary Linux
|
||||
processor affinity portability.
|
||||
|
||||
In more detail:
|
||||
|
||||
1. The plpa_info executable is a simple call into the PLPA library
|
||||
that checks which API variant the system it is running on has. If
|
||||
the kernel supports processor affinity and the PLPA is able to
|
||||
figure out which API variant to use, it prints "PLPA_PROBE_OK".
|
||||
Other responses indicate an error.
|
||||
|
||||
Since the PLPA library abstracts this kind of problem away, this is
|
||||
more a diagnostic tool than anything else. Note that plpa_info is
|
||||
*only* compiled and installed if PLPA is installed as a standalone
|
||||
package (see below).
|
||||
|
||||
2. Developers can use this package by including the <plpa.h> header
|
||||
file and using the following prototypes:
|
||||
|
||||
int plpa_sched_setaffinity(pid_t pid, size_t cpusetsize,
|
||||
const plpa_cpu_set_t *cpuset);
|
||||
|
||||
int plpa_sched_getaffinity(pid_t pid, size_t cpusetsize,
|
||||
const plpa_cpu_set_t *cpuset)
|
||||
|
||||
These functions perform run-time tests to determine which back-end
|
||||
API variant exists on the system and then dispatch to it correctly.
|
||||
The units of cpusetsize is number of bytes. This should normally
|
||||
just be sizeof(*cpuset), but is made available as a parameter to
|
||||
allow for future expansion of the PLPA (stay tuned).
|
||||
|
||||
The observant reader will notice that this is remarkably similar to
|
||||
the one of the Linux API's (the function names are different and
|
||||
the CPU set type is different). PLPA also provides several macros
|
||||
for manipulating the plpa_cpu_set_t bitmask, quite similar to FDSET
|
||||
macros (see "What, Exactly, Is the Problem?" above for a
|
||||
description of problems with the native CPU_* macros):
|
||||
|
||||
- PLPA_CPU_ZERO(&cpuset): Sets all bits in a plpa_cpu_set_t to
|
||||
zero.
|
||||
- PLPA_CPU_SET(num, &cpuset): Sets bit <num> of <cpuset> to one.
|
||||
- PLPA_CPU_CLR(num, &cpuset): Sets bit <num> of <cpuset> to zero.
|
||||
- PLPA_CPU_ISSET(num, &cpuset): Returns one if bit <num> of
|
||||
<cpuset> is one; returns zero otherwise.
|
||||
|
||||
Note that all four macros take a *pointer* to a plpa_cpu_set_t, as
|
||||
denoted by "&cpuset" in the descriptions above.
|
||||
|
||||
The following API functions are also available on kernels that
|
||||
support topology information (e.g., 2.6.16 or later):
|
||||
|
||||
- plpa_map_to_processor_id()
|
||||
- plpa_map_to_socket_core()
|
||||
- plpa_max_processor_id()
|
||||
- plpa_max_socket()
|
||||
- plpa_max_core()
|
||||
|
||||
On unsupported kernels, a negative value is returned to indicate
|
||||
graceful failure. Additionally, the function
|
||||
plpa_have_topology_information() can be called to determine whether
|
||||
a kernel supports the topology information or not. It returns 1 if
|
||||
the information is available (and therefore the above plpa_*()
|
||||
functions return meaningful values) or 0 if the information is
|
||||
unavailable (and therefore the above plpa_*() functions return a
|
||||
negative value indicating failure).
|
||||
|
||||
Note that invoking any of the topology functions (including
|
||||
plpa_have_topology_information()) will allocate memory from the
|
||||
heap. To release this memory, call plpa_finalize().
|
||||
|
||||
Note that the special case of invoking any of the topology
|
||||
functions on an unsupported kernel will not allocate any memory;
|
||||
invoking plpa_finalize() is therefore unnecessary, but harmless.
|
||||
|
||||
===========================================================================
|
||||
|
||||
How do I compile / install the PLPA as a standalone package?
|
||||
------------------------------------------------------------
|
||||
|
||||
The PLPA uses the standard GNU Autoconf/Automake/Libtool toolset to
|
||||
build and install itself. This means that generally, the following
|
||||
works:
|
||||
|
||||
shell$ ./configure --prefix=/where/you/want/to/install
|
||||
[...lots of output...]
|
||||
shell$ make all
|
||||
[...lots of output...]
|
||||
shell$ make install
|
||||
|
||||
Depending on your --prefix, you may need to run the "make install"
|
||||
step as root or some other privileged user.
|
||||
|
||||
"make install" will install the following:
|
||||
|
||||
- <plpa.h> in $includedir (typically $prefix/include)
|
||||
- libplpa.la and libplpa.a and/or libplpa.so in $libdir (typically
|
||||
$prefix/lib)
|
||||
- plpa_info executable in $bindir (typically $prefix/bin)
|
||||
|
||||
Note that since PLPA builds itself with GNU Libtool, it can be built
|
||||
as a static or shared library (or both). The default is to build a
|
||||
shared library. You can enable building a static library by supplying
|
||||
the "--enable-static" argument to configure; you can disable building
|
||||
the shared library by supplying the "--disable-shared" argument to
|
||||
configure. "make install" will install whichever library was built
|
||||
(or both).
|
||||
|
||||
"make uninstall" will fully uninstall PLPA from the prefix directory
|
||||
(again, depending in filesystem permissions, you may need to run this
|
||||
as root or some privileged user).
|
||||
|
||||
===========================================================================
|
||||
|
||||
How do I include PLPA in my software package?
|
||||
---------------------------------------------
|
||||
|
||||
It can be desirable to include PLPA in a larger software package
|
||||
(be sure to check out the LICENSE file) so that users don't have to
|
||||
separately download and install it before installing your software
|
||||
(after all, PLPA is a tiny little project -- why make users bother
|
||||
with it?).
|
||||
|
||||
When used in "included" mode, PLPA will:
|
||||
|
||||
- not install any header files
|
||||
- not build or install plpa_info
|
||||
- not build libplpa.* -- instead, it will build libplpa_included.*
|
||||
|
||||
There are two ways to put PLPA into "included" mode. From the
|
||||
configure command line:
|
||||
|
||||
shell$ ./configure --enable-included-mode ...
|
||||
|
||||
Or by directly integrating PLPA's m4 configure macro in your configure
|
||||
script and invoking a specific macro to enable the included mode.
|
||||
|
||||
Every project is different, and there are many different ways of
|
||||
integrating PLPA into yours. What follows is *one* example of how to
|
||||
do it.
|
||||
|
||||
Copy the PLPA directory in your source tree and include the plpa.m4
|
||||
file in your configure script -- perhaps with the following line in
|
||||
acinclude.m4 (assuming the use of Automake):
|
||||
|
||||
m4_include(path/to/plpa.m4)
|
||||
|
||||
The following macros can then be used from your configure script:
|
||||
|
||||
- PLPA_INIT(action-upon-success, action-upon-failure)
|
||||
Invoke the PLPA tests and setup the PLPA to build. A traversal of
|
||||
"make" into the PLPA directory should build everything (it is safe
|
||||
to list the PLPA directory in the SUBDIRS of a higher-level
|
||||
Makefile.am, for example).
|
||||
|
||||
- PLPA_STANDALONE
|
||||
Force the building of PLPA in standalone mode. Overrides the
|
||||
--enable-included-mode command line switch.
|
||||
|
||||
- PLPA_INCLUDED
|
||||
Force the building of PLPA in included mode.
|
||||
|
||||
- PLPA_SET_SYMBOL_PREFIX(foo)
|
||||
Tells the PLPA to prefix all types and public symbols with "foo"
|
||||
instead of "plpa_". This is recommended behavior if you are
|
||||
including PLPA in a larger project -- it is possible that your
|
||||
software will be combined with other software that also includes
|
||||
PLPA. If you both use different symbol prefixes, there will be no
|
||||
type/symbol clashes, and everything will compile and link
|
||||
successfully. If you both include PLPA and do not change the symbol
|
||||
prefix, it is likely that you will get multiple symbol definitions
|
||||
when linking.
|
||||
|
||||
Here's an example of integrating with a larger project named sandbox:
|
||||
|
||||
shell$ cd sandbox
|
||||
shell$ cp -r /somewhere/else/plpa-<version> .
|
||||
shell$ edit acinclude.m4
|
||||
...add the line "m4_include(plpa-<version>/config/plpa.m4)"...
|
||||
shell$ edit Makefile.am
|
||||
...add "plpa-<version>" to SUBDIRS...
|
||||
...add "$(top_builddir)/plpa-<version>/src/libplpa/libplpa_included.la" to
|
||||
my executable's LDADD line...
|
||||
shell$ edit configure.ac
|
||||
...add "PLPA_INCLUDED" line...
|
||||
...add "PLPA_SET_SYMBOL_PREFIX(sandbox_plpa_)" line...
|
||||
...add "PLPA_INIT(plpa_happy=yes, plpa_happy=no)" line...
|
||||
...add error checking for plpa_happy=no case...
|
||||
shell$ edit src/my_program.c
|
||||
...add #include <plpa.h>...
|
||||
...add calls to plpa_sched_setaffinity()...
|
||||
shell$ aclocal
|
||||
shell$ autoconf
|
||||
shell$ libtoolize --automake
|
||||
shell$ automake -a
|
||||
shell$ ./configure
|
||||
...lots of output...
|
||||
shell$ make
|
||||
...lots of output...
|
||||
|
||||
===========================================================================
|
||||
|
||||
How can I tell if PLPA is working?
|
||||
----------------------------------
|
||||
|
||||
Run plpa_info; if it says "PLPA_PROBE_OK", then PLPA is working
|
||||
properly.
|
||||
|
||||
If you want to compile your own test program to verify it, try
|
||||
compiling and running the following:
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
#include <stdio.h>
|
||||
#include <plpa.h>
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (PLPA_PROBE_OK == plpa_api_probe()) {
|
||||
printf("All is good!\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
You may need to supply appropriate -I and -L arguments to the
|
||||
compiler/linker, respectively, to tell it where to find the PLPA
|
||||
header and library files. Also don't forget to supply -lplpa to link
|
||||
in the PLPA library itself. For example, if you configured PLPA with:
|
||||
|
||||
shell$ ./configure --prefix=$HOME/my-plpa-install
|
||||
|
||||
Then you would compile the above program with:
|
||||
|
||||
shell$ gcc my-plpa-test.c \
|
||||
-I$HOME/my-plpa-install/include \
|
||||
-L$HOME/my-plpa-install/lib -lplpa \
|
||||
-o my-plpa-test
|
||||
shell$ ./my-plpa-test
|
||||
|
||||
If it compiles, links, runs, and prints "All is good!", then all
|
||||
should be well.
|
||||
|
||||
===========================================================================
|
||||
|
||||
What license does PLPA use?
|
||||
---------------------------
|
||||
|
||||
This package is distributed under the BSD license (see the LICENSE
|
||||
file in the top-level directory of a PLPA distribution). The
|
||||
copyrights of several institutions appear throughout the code base
|
||||
because some of the code was directly derived from the Open MPI
|
||||
project (http://www.open-mpi.org/), which is also distributed under
|
||||
the BSD license.
|
||||
|
||||
===========================================================================
|
||||
|
||||
How do I get involved in PLPA?
|
||||
------------------------------
|
||||
|
||||
Hopefully, PLPA is so simple that it won't need to be modified much
|
||||
after its first few releases. However, it is possible that we'll need
|
||||
to modify the run-time test if new variants of the Linux processor
|
||||
affinity API emerge.
|
||||
|
||||
The best way to report bugs, send comments, or ask questions is to
|
||||
sign up on the user's mailing list:
|
||||
|
||||
plpa-users@open-mpi.org
|
||||
|
||||
Because of spam, only subscribers are allowed to post to this list
|
||||
(ensure that you subscribe with and post from exactly the same e-mail
|
||||
address -- joe@example.com is considered different than
|
||||
joe@mycomputer.example.com!). Visit this page to subscribe to the
|
||||
list:
|
||||
|
||||
http://www.open-mpi.org/mailman/listinfo.cgi/plpa-users
|
||||
|
||||
Thanks for your time.
|
63
opal/mca/paffinity/linux/plpa/README.from-amd.txt
Обычный файл
63
opal/mca/paffinity/linux/plpa/README.from-amd.txt
Обычный файл
@ -0,0 +1,63 @@
|
||||
(from helpful AMD engineers...)
|
||||
|
||||
Jeff,
|
||||
|
||||
Bill asked me to expand on what I previously wrote by documenting the
|
||||
/sys interface. Without further ado:
|
||||
|
||||
All the information you need for determining the topology of a given
|
||||
core is located in the /sys/devices/system/cpu/cpuX/topology/
|
||||
directory, where X is a core number from 0 to N - 1, given N total
|
||||
cores present on the system. On an AMD64 system, this directory will
|
||||
contain the following entries, readable in ASCII form:
|
||||
|
||||
physical_package_id - which socket am I in?
|
||||
core_id - in my socket, which core am
|
||||
I? (0 or 1
|
||||
for dual-core CPUs)
|
||||
core_siblings - who are my sibling cores in this
|
||||
socket? (see below)
|
||||
thread_siblings - who are my sibling threads
|
||||
in this
|
||||
socket? (not really useful for AMD64)
|
||||
|
||||
The sibling fields are given as bit masks of core IDs, represented as
|
||||
hexdecimal numbers delimited by commas into groups of eight for easier
|
||||
readability. So for example, given a kernel that supports a maximum
|
||||
of 128 cores:
|
||||
|
||||
cparrott@compute-2:~> cat
|
||||
/sys/devices/system/cpu/cpu0/topology/core_siblings
|
||||
00000000,00000000,00000000,00000003
|
||||
|
||||
would tell us that cores 0 and 1 are the sibling cores of core 0.
|
||||
Each core is included in its own sibling core mask, so you would still
|
||||
get a meaningful result if you happened to be running on a single-core
|
||||
system.
|
||||
|
||||
Given that these are NUMA systems, you may assume that each socket may
|
||||
or may not have a region of memory associated with it. Most systems
|
||||
do, but I have seen a few that had sockets without associated memory.
|
||||
My dual-Opteron Linux workstation system at my desk is a prime example
|
||||
of this -- all of its memory appears to the kernel as being directly
|
||||
connected to socket 0.
|
||||
|
||||
Unfortunately, I am not aware of an easy mechanism for determining the
|
||||
memory associated with a given socket, although this information does
|
||||
show up in the kernel messages buffer during boot. (i.e. run dmesg)
|
||||
Perhaps Ray might know.
|
||||
|
||||
------
|
||||
|
||||
Followup to this:
|
||||
|
||||
The /sys/devices/system/node/ directory tree contains the memory node
|
||||
topology. Of particular interest here is numastat entry: this will
|
||||
give stats on which of this node's pages are physically located here
|
||||
versus foreign nodes, for example.
|
||||
|
||||
Unfortunately, memory mappings for specific address ranges to nodes
|
||||
are not available. I suspect that this is probably due to the fact
|
||||
that Linux uses virtual addressing everywhere in userland, so any
|
||||
physical address ranges corresponding to a particular memory node are
|
||||
meaningless in userland.
|
36
opal/mca/paffinity/linux/plpa/VERSION
Обычный файл
36
opal/mca/paffinity/linux/plpa/VERSION
Обычный файл
@ -0,0 +1,36 @@
|
||||
# This is the VERSION file for PLPA, describing the precise version of
|
||||
# PLPA in this distribution. The various components of the version
|
||||
# number below are combined to form a single version number string.
|
||||
|
||||
# major, minor, and release are generally combined in the form
|
||||
# <major>.<minor>.<release>. If release is zero, then it is omitted.
|
||||
|
||||
major=1
|
||||
minor=1
|
||||
release=0
|
||||
|
||||
# greek is used for alpha or beta release tags. If it is non-empty,
|
||||
# it will be appended to the version number. It does not have to be
|
||||
# numeric. Common examples include a1 (alpha release 1), b1 (beta
|
||||
# release 1), sc2005 (Super Computing 2005 release). The only
|
||||
# requirement is that it must be entirely printable ASCII characters
|
||||
# and have no white space.
|
||||
|
||||
greek=a1
|
||||
|
||||
# If want_svn=1, then the SVN r number will be included in the overall
|
||||
# PLPA version number in some form.
|
||||
|
||||
want_svn=1
|
||||
|
||||
# If svn_r=-1, then the SVN r numbere will be obtained dynamically at
|
||||
# run time, either 1) via the "svnversion" command (if this is a
|
||||
# Subversion checkout) in the form "r<svn_r>", or b) with the date (if
|
||||
# this is not a Subversion checkout, and the svnversion command cannot
|
||||
# be used) in the form of "svn<date>". Alternatively, if svn_r is not
|
||||
# -1, the value of svn_r will be directly appended to the version
|
||||
# string. This happens during "make dist", for example: if the
|
||||
# distribution tarball is being made from an SVN checkout, the value
|
||||
# of svn_r in this file is replaced with the output of "svnversion".
|
||||
|
||||
svn_r=-1
|
19
opal/mca/paffinity/linux/plpa/acinclude.m4
Обычный файл
19
opal/mca/paffinity/linux/plpa/acinclude.m4
Обычный файл
@ -0,0 +1,19 @@
|
||||
dnl -*- shell-script -*-
|
||||
dnl
|
||||
dnl Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
dnl University Research and Technology
|
||||
dnl Corporation. All rights reserved.
|
||||
dnl Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
dnl All rights reserved.
|
||||
dnl $COPYRIGHT$
|
||||
dnl
|
||||
dnl Additional copyrights may follow
|
||||
dnl
|
||||
dnl $HEADER$
|
||||
dnl
|
||||
|
||||
#
|
||||
# PLPA tests
|
||||
#
|
||||
|
||||
m4_include(config/plpa.m4)
|
386
opal/mca/paffinity/linux/plpa/autogen.sh
Исполняемый файл
386
opal/mca/paffinity/linux/plpa/autogen.sh
Исполняемый файл
@ -0,0 +1,386 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
# University Research and Technology
|
||||
# Corporation. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The University of Tennessee and The University
|
||||
# of Tennessee Research Foundation. All rights
|
||||
# reserved.
|
||||
# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
||||
# University of Stuttgart. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright (c) 2007 Cisco, Inc. All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
# This script is run on developer copies of PLPA -- *not* distribution
|
||||
# tarballs.
|
||||
|
||||
#set -x
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# User-definable parameters (search path and minimum supported versions)
|
||||
#
|
||||
# Note: use ';' to separate parameters
|
||||
##############################################################################
|
||||
|
||||
ompi_aclocal_search="aclocal"
|
||||
if test ! -z "$ACLOCAL"; then
|
||||
ompi_aclocal_search="$ACLOCAL"
|
||||
fi
|
||||
ompi_autoheader_search="autoheader"
|
||||
if test ! -z "$AUTOHEADER"; then
|
||||
ompi_autoheader_search="$AUTOHEADER"
|
||||
fi
|
||||
ompi_autoconf_search="autoconf"
|
||||
if test ! -z "$AUTOCONF"; then
|
||||
ompi_autoconf_search="$AUTOCONF"
|
||||
fi
|
||||
ompi_libtoolize_search="libtoolize;glibtoolize"
|
||||
if test ! -z "$LIBTOOLIZE"; then
|
||||
ompi_libtoolize_search="$LIBTOOLIZE"
|
||||
fi
|
||||
ompi_automake_search="automake"
|
||||
if test ! -z "$AUTOMAKE"; then
|
||||
ompi_automake_search="$AUTOMAKE"
|
||||
fi
|
||||
|
||||
ompi_automake_version="1.9.6"
|
||||
ompi_autoconf_version="2.59"
|
||||
ompi_libtool_version="1.5.22"
|
||||
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Global variables - should not need to modify defaults
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
ompi_aclocal_version="$ompi_automake_version"
|
||||
ompi_autoheader_version="$ompi_autoconf_version"
|
||||
ompi_libtoolize_version="$ompi_libtool_version"
|
||||
|
||||
# program names to execute
|
||||
ompi_aclocal=""
|
||||
ompi_autoheader=""
|
||||
ompi_autoconf=""
|
||||
ompi_libtoolize=""
|
||||
ompi_automake=""
|
||||
|
||||
mca_no_configure_components_file="config/mca_no_configure_components.m4"
|
||||
mca_no_config_list_file="mca_no_config_list"
|
||||
mca_no_config_env_file="mca_no_config_env"
|
||||
mca_m4_include_file="mca_m4_config_include.m4"
|
||||
mca_m4_config_env_file="mca_m4_config_env"
|
||||
autogen_subdir_file="autogen.subdirs"
|
||||
|
||||
############################################################################
|
||||
#
|
||||
# Version check - does major,minor,release check (hopefully ignoring
|
||||
# beta et al)
|
||||
#
|
||||
# INPUT:
|
||||
# - minimum version allowable
|
||||
# - version we found
|
||||
#
|
||||
# OUTPUT:
|
||||
# - 0 version is ok
|
||||
# - 1 version is not ok
|
||||
#
|
||||
# SIDE EFFECTS:
|
||||
# none
|
||||
#
|
||||
##############################################################################
|
||||
check_version() {
|
||||
local min_version="$1"
|
||||
local version="$2"
|
||||
|
||||
local min_major_version="`echo $min_version | cut -f1 -d.`"
|
||||
local min_minor_version="`echo $min_version | cut -f2 -d.`"
|
||||
local min_release_version="`echo $min_version | cut -f3 -d.`"
|
||||
if test "$min_release_version" = "" ; then
|
||||
min_release_version=0
|
||||
fi
|
||||
|
||||
local major_version="`echo $version | cut -f1 -d.`"
|
||||
local minor_version="`echo $version | cut -f2 -d.`"
|
||||
local release_version="`echo $version | cut -f3 -d.`"
|
||||
if test "$release_version" = "" ; then
|
||||
release_version=0
|
||||
fi
|
||||
|
||||
if test $min_major_version -lt $major_version ; then
|
||||
return 0
|
||||
elif test $min_major_version -gt $major_version ; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if test $min_minor_version -lt $minor_version ; then
|
||||
return 0
|
||||
elif test $min_minor_version -gt $minor_version ; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if test $min_release_version -gt $release_version ; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# find app - find a version of the given application that is new
|
||||
# enough for use
|
||||
#
|
||||
# INPUT:
|
||||
# - name of application (eg aclocal)
|
||||
#
|
||||
# OUTPUT:
|
||||
# none
|
||||
#
|
||||
# SIDE EFFECTS:
|
||||
# - sets application_name variable to working executable name
|
||||
# - aborts on error finding application
|
||||
#
|
||||
##############################################################################
|
||||
find_app() {
|
||||
local app_name="$1"
|
||||
|
||||
local version="0.0.0"
|
||||
local min_version="99.99.99"
|
||||
local found=0
|
||||
local tmpIFS=$IFS
|
||||
|
||||
eval "min_version=\"\$ompi_${app_name}_version\""
|
||||
eval "search_path=\"\$ompi_${app_name}_search\""
|
||||
IFS=";"
|
||||
for i in $search_path ; do
|
||||
IFS="$tmpIFS"
|
||||
version="`${i} --version 2>&1`"
|
||||
if test "$?" != 0 ; then
|
||||
IFS=";"
|
||||
continue
|
||||
fi
|
||||
|
||||
version="`echo $version | cut -f2 -d')'`"
|
||||
version="`echo $version | cut -f1 -d' '`"
|
||||
|
||||
if check_version $min_version $version ; then
|
||||
eval "ompi_${app_name}=\"${i}\""
|
||||
found=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
IFS="$tmpIFS"
|
||||
|
||||
if test "$found" = "0" ; then
|
||||
cat <<EOF
|
||||
I could not find a recent enough copy of ${app_name}.
|
||||
I am gonna abort. :-(
|
||||
|
||||
Please make sure you are using at least the following versions of the
|
||||
GNU tools:
|
||||
|
||||
GNU Autoconf $ompi_autoconf_version
|
||||
GNU Automake $ompi_automake_version
|
||||
NOTE: You may need Automake 1.8.5 (or higher) in order to run
|
||||
"make dist" successfully
|
||||
GNU Libtool $ompi_libtool_version
|
||||
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# run_and_check - run the right GNU tool, printing warning on failure
|
||||
#
|
||||
# INPUT:
|
||||
# - name of application (eg aclocal)
|
||||
# - program arguments
|
||||
#
|
||||
# OUTPUT:
|
||||
# none
|
||||
#
|
||||
# SIDE EFFECTS:
|
||||
# - aborts on error running application
|
||||
#
|
||||
##############################################################################
|
||||
run_and_check() {
|
||||
local rac_progs="$*"
|
||||
echo "[Running] $rac_progs"
|
||||
eval $rac_progs
|
||||
if test "$?" != 0; then
|
||||
cat <<EOF
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
It seems that the execution of "$rac_progs" has failed. See above for
|
||||
the specific error message that caused it to abort.
|
||||
|
||||
This *MAY* be caused by an older version of one of the required
|
||||
packages. Please make sure you are using at least the following
|
||||
versions:
|
||||
|
||||
GNU Autoconf $ompi_autoconf_version
|
||||
GNU Automake $ompi_automake_version
|
||||
GNU Libtool $ompi_libtool_version
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# find_and_delete - look for standard files in a number of common places
|
||||
# (e.g., ./config.guess, config/config.guess, dist/config.guess), and
|
||||
# delete it. If it's not found there, look for AC_CONFIG_AUX_DIR in
|
||||
# the configure.in script and try there. If it's not there, oh well.
|
||||
#
|
||||
# INPUT:
|
||||
# - file to delete
|
||||
#
|
||||
# OUTPUT:
|
||||
# none
|
||||
#
|
||||
# SIDE EFFECTS:
|
||||
# - files may disappear
|
||||
#
|
||||
##############################################################################
|
||||
find_and_delete() {
|
||||
local fad_file="$1"
|
||||
|
||||
local fad_cfile
|
||||
local auxdir
|
||||
|
||||
# Look for the file in "standard" places
|
||||
|
||||
if test -f $fad_file; then
|
||||
rm -f $fad_file
|
||||
elif test -d config/$fad_file; then
|
||||
rm -f config/$fad_file
|
||||
elif test -d dist/$fad_file; then
|
||||
rm -f dist/$fad_file
|
||||
else
|
||||
|
||||
# Didn't find it -- look for an AC_CONFIG_AUX_DIR line in
|
||||
# configure.[in|ac]
|
||||
|
||||
if test -f configure.in; then
|
||||
fad_cfile=configure.in
|
||||
elif test -f configure.ac; then
|
||||
fad_cfile=configure.ac
|
||||
else
|
||||
echo "--> Errr... there's no configure.in or configure.ac file!"
|
||||
fi
|
||||
if test -n "$fad_cfile"; then
|
||||
auxdir="`grep AC_CONFIG_AUX_DIR $fad_cfile | cut -d\( -f 2 | cut -d\) -f 1`"
|
||||
fi
|
||||
if test -f "$auxdir/$fad_file"; then
|
||||
rm -f "$auxdir/$fad_file"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# run_gnu_tools - run the GNU tools in a given directory
|
||||
#
|
||||
# INPUT:
|
||||
# none
|
||||
#
|
||||
# OUTPUT:
|
||||
# none
|
||||
#
|
||||
# SIDE EFFECTS:
|
||||
# - assumes that the directory is ready to have the GNU tools run
|
||||
# in it (i.e., there's some form of configure.*)
|
||||
# - may preprocess the directory before running the GNU tools
|
||||
# (e.g., generale Makefile.am's from configure.params, etc.)
|
||||
#
|
||||
##############################################################################
|
||||
run_gnu_tools() {
|
||||
|
||||
# Find and delete the GNU helper script files
|
||||
|
||||
find_and_delete config.guess
|
||||
find_and_delete config.sub
|
||||
find_and_delete depcomp
|
||||
find_and_delete compile
|
||||
find_and_delete install-sh
|
||||
find_and_delete ltconfig
|
||||
find_and_delete ltmain.sh
|
||||
find_and_delete missing
|
||||
find_and_delete mkinstalldirs
|
||||
find_and_delete libtool
|
||||
|
||||
# Run the GNU tools
|
||||
|
||||
echo "*** Running GNU tools"
|
||||
|
||||
run_and_check $ompi_aclocal
|
||||
run_and_check $ompi_autoheader
|
||||
run_and_check $ompi_autoconf
|
||||
run_and_check $ompi_libtoolize --automake --copy
|
||||
run_and_check $ompi_automake --foreign -a --copy --include-deps
|
||||
}
|
||||
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# main - do the real work...
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# announce
|
||||
echo "[Checking] prerequisites"
|
||||
|
||||
# sanity check to make sure user isn't being stupid
|
||||
if test ! -d .svn ; then
|
||||
cat <<EOF
|
||||
|
||||
This doesn't look like a developer copy of PLPA. You probably do not
|
||||
want to run autogen.sh - it is normally not needed for a release
|
||||
source tree. Giving you 5 seconds to reconsider and kill me.
|
||||
|
||||
EOF
|
||||
sleep 5
|
||||
fi
|
||||
|
||||
|
||||
if test -f VERSION -a -f configure.ac -a -f src/libplpa/plpa_bottom.h ; then
|
||||
# Top level of PLPA tree
|
||||
uptime > /dev/null
|
||||
else
|
||||
cat <<EOF
|
||||
|
||||
You must run this script from either the top level of the OMPI
|
||||
directory tree or the top-level of an MCA component directory tree.
|
||||
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# find all the apps we are going to run
|
||||
find_app "aclocal"
|
||||
find_app "autoheader"
|
||||
find_app "autoconf"
|
||||
find_app "libtoolize"
|
||||
find_app "automake"
|
||||
|
||||
run_gnu_tools
|
||||
|
||||
# All done
|
||||
exit 0
|
17
opal/mca/paffinity/linux/plpa/config/Makefile.am
Обычный файл
17
opal/mca/paffinity/linux/plpa/config/Makefile.am
Обычный файл
@ -0,0 +1,17 @@
|
||||
#
|
||||
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
# University Research and Technology
|
||||
# Corporation. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
EXTRA_DIST = \
|
||||
distscript.csh \
|
||||
plpa.m4 \
|
||||
plpa_get_version.sh
|
134
opal/mca/paffinity/linux/plpa/config/distscript.csh
Исполняемый файл
134
opal/mca/paffinity/linux/plpa/config/distscript.csh
Исполняемый файл
@ -0,0 +1,134 @@
|
||||
#! /bin/csh -f
|
||||
#
|
||||
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
# University Research and Technology
|
||||
# Corporation. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The University of Tennessee and The University
|
||||
# of Tennessee Research Foundation. All rights
|
||||
# reserved.
|
||||
# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
||||
# University of Stuttgart. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
set srcdir="$1"
|
||||
set builddir="`pwd`"
|
||||
set distdir="$builddir/$2"
|
||||
set PLPA_VERSION="$3"
|
||||
set PLPA_SVN_VERSION="$4"
|
||||
|
||||
if ("$distdir" == "") then
|
||||
echo "Must supply relative distdir as argv[2] -- aborting"
|
||||
exit 1
|
||||
elif ("$PLPA_VERSION" == "") then
|
||||
echo "Must supply version as argv[1] -- aborting"
|
||||
exit 1
|
||||
endif
|
||||
|
||||
# we can catch some hard (but possible) to do mistakes by looking at
|
||||
# our tree's revision number, but only if we are in the source tree.
|
||||
# Otherwise, use what configure told us, at the cost of allowing one
|
||||
# or two corner cases in (but otherwise VPATH builds won't work)
|
||||
set svn_r=$PLPA_SVN_VERSION
|
||||
if (-d .svn) then
|
||||
set svn_r="r`svnversion .`"
|
||||
endif
|
||||
|
||||
set start=`date`
|
||||
cat <<EOF
|
||||
|
||||
Creating PLPA distribution
|
||||
In directory: `pwd`
|
||||
Version: $PLPA_VERSION
|
||||
Started: $start
|
||||
|
||||
EOF
|
||||
|
||||
umask 022
|
||||
|
||||
if (! -d "$distdir") then
|
||||
echo "*** ERROR: dist dir does not exist"
|
||||
echo "*** ERROR: $distdir"
|
||||
exit 1
|
||||
endif
|
||||
|
||||
#
|
||||
# See if we need to update the version file with the current SVN
|
||||
# revision number. Do this *before* entering the distribution tree to
|
||||
# solve a whole host of problems with VPATH (since srcdir may be
|
||||
# relative or absolute)
|
||||
#
|
||||
set cur_svn_r="`grep '^svn_r' ${distdir}/VERSION | cut -d= -f2`"
|
||||
if ("$cur_svn_r" == "-1") then
|
||||
sed -e 's/^svn_r=.*/svn_r='$svn_r'/' "${distdir}/VERSION" > "${distdir}/version.new"
|
||||
cp "${distdir}/version.new" "${distdir}/VERSION"
|
||||
rm -f "${distdir}/version.new"
|
||||
# need to reset the timestamp to not annoy AM dependencies
|
||||
touch -r "${srcdir}/VERSION" "${distdir}/VERSION"
|
||||
echo "*** Updated VERSION file with SVN r number"
|
||||
else
|
||||
echo "*** Did NOT updated VERSION file with SVN r number"
|
||||
endif
|
||||
|
||||
#########################################################
|
||||
# VERY IMPORTANT: Now go into the new distribution tree #
|
||||
#########################################################
|
||||
cd "$distdir"
|
||||
echo "*** Now in distdir: $distdir"
|
||||
|
||||
#
|
||||
# Get the latest config.guess and config.sub from ftp.gnu.org
|
||||
#
|
||||
|
||||
echo "*** Downloading latest config.sub/config.guess from ftp.gnu.org..."
|
||||
cd config
|
||||
set configdir="`pwd`"
|
||||
mkdir tmp.$$
|
||||
cd tmp.$$
|
||||
# "Temporary" instructions at ftp.gnu.org/gnu/config advise using the
|
||||
# following URLs:
|
||||
wget -t 1 -T 10 'http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess'
|
||||
wget -t 1 -T 10 'http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub'
|
||||
chmod +x config.guess config.sub
|
||||
|
||||
# Recently, ftp.gnu.org has had zero-legnth config.guess / config.sub
|
||||
# files, which causes the automated nightly SVN snapshot tarball to
|
||||
# fail to be made correctly. This is a primitive attempt to fix that.
|
||||
# If we got zero-length files from wget, use a config.guess /
|
||||
# config.sub from a known location that is more recent than what ships
|
||||
# in the current generation of auto* tools.
|
||||
|
||||
if (! -f config.guess || ! -s config.guess) then
|
||||
echo " - WARNING: Got BAD config.guess from ftp.gnu.org"
|
||||
echo " - WARNING: using included version"
|
||||
else
|
||||
cp config.guess ..
|
||||
endif
|
||||
if (! -f config.sub || ! -s config.sub) then
|
||||
echo " - WARNING: Got BAD config.sub from ftp.gnu.org"
|
||||
echo " - WARNING: using known version"
|
||||
else
|
||||
cp config.sub ..
|
||||
endif
|
||||
cd ..
|
||||
rm -rf tmp.$$
|
||||
cd ..
|
||||
|
||||
#
|
||||
# All done
|
||||
#
|
||||
|
||||
cat <<EOF
|
||||
*** PLPA version $PLPA_VERSION distribution created
|
||||
|
||||
Started: $start
|
||||
Ended: `date`
|
||||
|
||||
EOF
|
||||
|
274
opal/mca/paffinity/linux/plpa/config/plpa.m4
Обычный файл
274
opal/mca/paffinity/linux/plpa/config/plpa.m4
Обычный файл
@ -0,0 +1,274 @@
|
||||
# -*- shell-script -*-
|
||||
#
|
||||
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
# University Research and Technology
|
||||
# Corporation. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright (c) 2006-2007 Cisco Systems, Inc. All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
# Main PLPA m4 macro, to be invoked by the user
|
||||
#
|
||||
# Expects two paramters:
|
||||
# 1. What to do upon success
|
||||
# 2. What to do upon failure
|
||||
#
|
||||
AC_DEFUN([PLPA_INIT],[
|
||||
AC_REQUIRE([_PLPA_INTERNAL_SETUP])
|
||||
AC_REQUIRE([AC_PROG_CC])
|
||||
|
||||
# Check for syscall()
|
||||
AC_CHECK_FUNC([syscall], [happy=1], [happy=0])
|
||||
|
||||
# Look for syscall.h
|
||||
if test "$happy" = 1; then
|
||||
AC_CHECK_HEADER([sys/syscall.h], [happy=1], [happy=0])
|
||||
fi
|
||||
|
||||
# Look for unistd.h
|
||||
if test "$happy" = 1; then
|
||||
AC_CHECK_HEADER([unistd.h], [happy=1], [happy=0])
|
||||
fi
|
||||
|
||||
# Check for __NR_sched_setaffinity
|
||||
if test "$happy" = 1; then
|
||||
AC_MSG_CHECKING([for __NR_sched_setaffinity])
|
||||
if test "$plpa_emulate" = "yes"; then
|
||||
AC_MSG_RESULT([emulated])
|
||||
AC_DEFINE([__NR_sched_setaffinity], [0], [Emulated value])
|
||||
else
|
||||
AC_TRY_COMPILE([#include <syscall.h>
|
||||
#include <unistd.h>], [#ifndef __NR_sched_setaffinity
|
||||
#error __NR_sched_setaffinity_not found!
|
||||
#endif
|
||||
int i = 1;],
|
||||
[AC_MSG_RESULT([yes])
|
||||
happy=1],
|
||||
[AC_MSG_RESULT([no])
|
||||
happy=0])
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check for __NR_sched_getaffinity (probably overkill, but what
|
||||
# the heck?)
|
||||
if test "$happy" = 1; then
|
||||
AC_MSG_CHECKING([for __NR_sched_getaffinity])
|
||||
if test "$plpa_emulate" = "yes"; then
|
||||
AC_MSG_RESULT([emulated])
|
||||
AC_DEFINE([__NR_sched_getaffinity], [0], [Emulated value])
|
||||
else
|
||||
AC_TRY_COMPILE([#include <syscall.h>
|
||||
#include <unistd.h>], [#ifndef __NR_sched_getaffinity
|
||||
#error __NR_sched_getaffinity_not found!
|
||||
#endif
|
||||
int i = 1;],
|
||||
[AC_MSG_RESULT([yes])
|
||||
happy=1],
|
||||
[AC_MSG_RESULT([no])
|
||||
happy=0])
|
||||
fi
|
||||
fi
|
||||
|
||||
# If all was good, do the real init
|
||||
AS_IF([test "$happy" = "1"],
|
||||
[_PLPA_INIT($1, $2)],
|
||||
[$2])
|
||||
AM_CONDITIONAL([PLPA_BUILD_STANDALONE], [test "$plpa_mode" = "standalone"])
|
||||
|
||||
# Cleanup
|
||||
unset happy
|
||||
])dnl
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Build PLPA as a standalone package
|
||||
AC_DEFUN([PLPA_STANDALONE],[
|
||||
m4_define([plpa_config_prefix],[.])
|
||||
AC_REQUIRE([_PLPA_INTERNAL_SETUP])
|
||||
plpa_mode=standalone
|
||||
])dnl
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Build PLPA as an included package
|
||||
AC_DEFUN([PLPA_INCLUDED],[
|
||||
m4_define([plpa_config_prefix],[$1])
|
||||
AC_REQUIRE([_PLPA_INTERNAL_SETUP])
|
||||
plpa_mode=included
|
||||
plpa_executables=no
|
||||
])dnl
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Set whether the fortran bindings will be built or not
|
||||
AC_DEFUN([PLPA_FORTRAN],[
|
||||
AC_REQUIRE([_PLPA_INTERNAL_SETUP])
|
||||
|
||||
# Need [] around entire following line to escape m4 properly
|
||||
[plpa_tmp=`echo $1 | tr '[:upper:]' '[:lower:]'`]
|
||||
if test "$1" = "0" -o "$1" = "n"; then
|
||||
plpa_fortran=no
|
||||
elif test "$1" = "1" -o "$1" = "y"; then
|
||||
plpa_fortran=yes
|
||||
else
|
||||
AC_MSG_WARN([Did not understand PLPA_FORTRAN argument ($1) -- ignored])
|
||||
fi
|
||||
])dnl
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Set whether to build and install the executables or not
|
||||
AC_DEFUN([PLPA_EXECUTABLES],[
|
||||
AC_REQUIRE([_PLPA_INTERNAL_SETUP])
|
||||
|
||||
# Need [] around entire following line to escape m4 properly
|
||||
[plpa_tmp=`echo $1 | tr '[:upper:]' '[:lower:]'`]
|
||||
if test "$1" = "0" -o "$1" = "n"; then
|
||||
plpa_executables=no
|
||||
elif test "$1" = "1" -o "$1" = "y"; then
|
||||
plpa_executables=yes
|
||||
else
|
||||
AC_MSG_WARN([Did not understand PLPA_EXECUTABLES argument ($1) -- ignored])
|
||||
fi
|
||||
|
||||
#
|
||||
# need to check for plpa_mode = included and plpa_executables=yes
|
||||
# and print a big AC_MSG_WARN if both are true
|
||||
|
||||
if test "$plpa_mode" = "included" -a "$plpa_executables" = "yes" ; then
|
||||
AC_MSG_WARN([ Attempting to build executables in included mode ])
|
||||
AC_MSG_WARN([ This will fail - libplpa_included will be built ])
|
||||
AC_MSG_WARN([ Executables expect libplpa ])
|
||||
fi
|
||||
|
||||
])dnl
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Specify the symbol prefix
|
||||
AC_DEFUN([PLPA_SET_SYMBOL_PREFIX],[
|
||||
AC_REQUIRE([_PLPA_INTERNAL_SETUP])
|
||||
plpa_symbol_prefix_value=$1
|
||||
])dnl
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Internals
|
||||
AC_DEFUN([_PLPA_INTERNAL_SETUP],[
|
||||
|
||||
AC_ARG_ENABLE([emulate],
|
||||
AC_HELP_STRING([--enable-emulate],
|
||||
[Emulate __NR_sched_setaffinity and __NR_sched_getaffinity, to allow building on non-Linux systems (for testing)]))
|
||||
if test "$enable_emulate" = "yes"; then
|
||||
plpa_emulate=yes
|
||||
else
|
||||
plpa_emulate=no
|
||||
fi
|
||||
|
||||
# Included mode, or standalone?
|
||||
AC_ARG_ENABLE([included-mode],
|
||||
AC_HELP_STRING([--enable-included-mode],
|
||||
[Using --enable-included-mode puts the PLPA into "included" mode. The default is --disable-included-mode, meaning that the PLPA is in "standalone" mode.]))
|
||||
if test "$enable_included_mode" = "yes"; then
|
||||
plpa_mode=included
|
||||
else
|
||||
plpa_mode=standalone
|
||||
fi
|
||||
|
||||
# Fortran bindings, or no?
|
||||
AC_ARG_ENABLE([fortran],
|
||||
AC_HELP_STRING([--disable-fortran],
|
||||
[Using --disable-fortran disables building the Fortran PLPA API bindings]))
|
||||
if test "$enable_fortran" = "yes" -o "$enable_fortran" = ""; then
|
||||
plpa_fortran=yes
|
||||
else
|
||||
plpa_fortran=no
|
||||
fi
|
||||
|
||||
# Build and install the executables or no?
|
||||
AC_ARG_ENABLE([executables],
|
||||
AC_HELP_STRING([--disable-executables],
|
||||
[Using --disable-executables disables building and installing the PLPA executables]))
|
||||
if test "$enable_executables" = "yes" -o "$enable_executables" = ""; then
|
||||
plpa_executables=yes
|
||||
else
|
||||
plpa_executables=no
|
||||
fi
|
||||
|
||||
# Change the symbol prefix?
|
||||
AC_ARG_WITH([plpa-symbol-prefix],
|
||||
AC_HELP_STRING([--with-plpa-symbol-prefix=STRING],
|
||||
[STRING can be any valid C symbol name. It will be prefixed to all public PLPA symbols. Default: "plpa_"]))
|
||||
if test "$with_plpa_symbol_prefix" = ""; then
|
||||
plpa_symbol_prefix_value=plpa_
|
||||
else
|
||||
plpa_symbol_prefix_value=$with_plpa_symbol_prefix
|
||||
fi
|
||||
])dnl
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Internals for PLPA_INIT
|
||||
AC_DEFUN([_PLPA_INIT],[
|
||||
AC_REQUIRE([_PLPA_INTERNAL_SETUP])
|
||||
|
||||
# Are we building as standalone or included?
|
||||
AC_MSG_CHECKING([for PLPA building mode])
|
||||
AC_MSG_RESULT([$plpa_mode])
|
||||
|
||||
# We need to set a path for header, etc files depending on whether
|
||||
# we're standalone or included. this is taken care of by PLPA_INCLUDED.
|
||||
# Move AC_CONFIG_HEADER and AC_CONFIG_FILES to here, using the
|
||||
# path prefix from PLPA_INCLUDED
|
||||
|
||||
AC_MSG_CHECKING([for PLPA config prefix])
|
||||
AC_MSG_RESULT(plpa_config_prefix)
|
||||
|
||||
AM_CONFIG_HEADER(plpa_config_prefix[/src/libplpa/plpa.h])
|
||||
AC_CONFIG_FILES(
|
||||
plpa_config_prefix[/Makefile]
|
||||
plpa_config_prefix[/config/Makefile]
|
||||
plpa_config_prefix[/src/Makefile]
|
||||
plpa_config_prefix[/src/libplpa/Makefile]
|
||||
plpa_config_prefix[/src/plpa-info/Makefile]
|
||||
plpa_config_prefix[/src/plpa-taskset/Makefile]
|
||||
)
|
||||
|
||||
# What prefix are we using?
|
||||
AC_MSG_CHECKING([for PLPA symbol prefix])
|
||||
AC_DEFINE_UNQUOTED(PLPA_SYM_PREFIX, [$plpa_symbol_prefix_value],
|
||||
[The PLPA symbol prefix])
|
||||
# Ensure to [] escape the whole next line so that we can get the
|
||||
# proper tr tokens
|
||||
[plpa_symbol_prefix_value_caps="`echo $plpa_symbol_prefix_value | tr '[:lower:]' '[:upper:]'`"]
|
||||
AC_DEFINE_UNQUOTED(PLPA_SYM_PREFIX_CAPS, [$plpa_symbol_prefix_value_caps],
|
||||
[The PLPA symbol prefix in all caps])
|
||||
AC_MSG_RESULT([$plpa_symbol_prefix_value])
|
||||
|
||||
# Check for fortran
|
||||
AC_MSG_CHECKING([whether to build PLPA Fortran API])
|
||||
AM_CONDITIONAL(PLPA_BUILD_FORTRAN, [test "$plpa_fortran" = "yes"])
|
||||
AC_MSG_RESULT([$plpa_fortran])
|
||||
|
||||
# Check whether to build the exectuables or not
|
||||
AC_MSG_CHECKING([whether to build PLPA executables])
|
||||
AM_CONDITIONAL(PLPA_BUILD_EXECUTABLES, [test "$plpa_executables" = "yes"])
|
||||
AC_MSG_RESULT([$plpa_executables])
|
||||
|
||||
# If we're building executables, we need some things for plpa-taskset
|
||||
if test "$plpa_executables" = "yes"; then
|
||||
AC_C_INLINE
|
||||
AM_PROG_LEX
|
||||
AC_PROG_YACC
|
||||
fi
|
||||
|
||||
# Success
|
||||
$1
|
||||
])dnl
|
||||
|
126
opal/mca/paffinity/linux/plpa/config/plpa_get_version.sh
Исполняемый файл
126
opal/mca/paffinity/linux/plpa/config/plpa_get_version.sh
Исполняемый файл
@ -0,0 +1,126 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
# University Research and Technology
|
||||
# Corporation. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The University of Tennessee and The University
|
||||
# of Tennessee Research Foundation. All rights
|
||||
# reserved.
|
||||
# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
||||
# University of Stuttgart. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
#
|
||||
# This file is almost identical in functionality to
|
||||
# ompi_get_version.m4. It is unfortunate that we have to duplicate
|
||||
# code, but it is really the only what that I can think to do it. :-(
|
||||
# Hence, if you change the logic here for determining version numbers,
|
||||
# YOU MUST ALSO CHANGE IT IN ompi_get_version.m4!!
|
||||
#
|
||||
|
||||
srcfile="$1"
|
||||
option="$2"
|
||||
|
||||
case "$option" in
|
||||
# svnversion can take a while to run. If we don't need it, don't run it.
|
||||
--major|--minor|--release|--greek|--base|--help)
|
||||
OMPI_NEED_SVN=0
|
||||
;;
|
||||
*)
|
||||
OMPI_NEED_SVN=1
|
||||
esac
|
||||
|
||||
|
||||
if test "$srcfile" = ""; then
|
||||
option="--help"
|
||||
else
|
||||
OMPI_MAJOR_VERSION="`cat $srcfile | egrep '^major=' | cut -d= -f2`"
|
||||
OMPI_MINOR_VERSION="`cat $srcfile | egrep '^minor=' | cut -d= -f2`"
|
||||
OMPI_RELEASE_VERSION="`cat $srcfile | egrep '^release=' | cut -d= -f2`"
|
||||
OMPI_GREEK_VERSION="`cat $srcfile | egrep '^greek=' | cut -d= -f2`"
|
||||
OMPI_WANT_SVN="`cat $srcfile | egrep '^want_svn=' | cut -d= -f2`"
|
||||
OMPI_SVN_R="`cat $srcfile | egrep '^svn_r=' | cut -d= -f2`"
|
||||
if test "$OMPI_RELEASE_VERSION" != "0" -a "$OMPI_RELEASE_VERSION" != ""; then
|
||||
OMPI_VERSION="$OMPI_MAJOR_VERSION.$OMPI_MINOR_VERSION.$OMPI_RELEASE_VERSION"
|
||||
else
|
||||
OMPI_VERSION="$OMPI_MAJOR_VERSION.$OMPI_MINOR_VERSION"
|
||||
fi
|
||||
|
||||
OMPI_VERSION="${OMPI_VERSION}${OMPI_GREEK_VERSION}"
|
||||
|
||||
OMPI_BASE_VERSION="$OMPI_VERSION"
|
||||
|
||||
if test "$OMPI_WANT_SVN" = "1" -a "$OMPI_NEED_SVN" = "1" ; then
|
||||
if test "$OMPI_SVN_R" = "-1"; then
|
||||
if test -d .svn; then
|
||||
ver="r`svnversion .`"
|
||||
else
|
||||
ver="svn`date '+%m%d%Y'`"
|
||||
fi
|
||||
OMPI_SVN_R="$ver"
|
||||
fi
|
||||
OMPI_VERSION="${OMPI_VERSION}$OMPI_SVN_R"
|
||||
fi
|
||||
|
||||
if test "$option" = ""; then
|
||||
option="--full"
|
||||
fi
|
||||
fi
|
||||
|
||||
case "$option" in
|
||||
--full|-v|--version)
|
||||
echo $OMPI_VERSION
|
||||
;;
|
||||
--major)
|
||||
echo $OMPI_MAJOR_VERSION
|
||||
;;
|
||||
--minor)
|
||||
echo $OMPI_MINOR_VERSION
|
||||
;;
|
||||
--release)
|
||||
echo $OMPI_RELEASE_VERSION
|
||||
;;
|
||||
--greek)
|
||||
echo $OMPI_GREEK_VERSION
|
||||
;;
|
||||
--svn)
|
||||
echo $OMPI_SVN_R
|
||||
;;
|
||||
--base)
|
||||
echo $OMPI_BASE_VERSION
|
||||
;;
|
||||
--all)
|
||||
echo ${OMPI_VERSION} ${OMPI_MAJOR_VERSION} ${OMPI_MINOR_VERSION} ${OMPI_RELEASE_VERSION} ${OMPI_GREEK_VERSION} ${OMPI_SVN_R}
|
||||
;;
|
||||
-h|--help)
|
||||
cat <<EOF
|
||||
$0 <srcfile> [<option>]
|
||||
|
||||
<srcfile> - Text version file
|
||||
<option> - One of:
|
||||
--full - Full version number
|
||||
--major - Major version number
|
||||
--minor - Minor version number
|
||||
--release - Release version number
|
||||
--greek - Greek (alpha, beta, etc) version number
|
||||
--svn - Subversion repository number
|
||||
--all - Show all version numbers, separated by :
|
||||
--base - Show base version number (no svn number)
|
||||
--help - This message
|
||||
EOF
|
||||
;;
|
||||
*)
|
||||
echo "Unrecognized option $option. Run $0 --help for options"
|
||||
;;
|
||||
esac
|
||||
|
||||
# All done
|
||||
|
||||
exit 0
|
176
opal/mca/paffinity/linux/plpa/configure.ac
Обычный файл
176
opal/mca/paffinity/linux/plpa/configure.ac
Обычный файл
@ -0,0 +1,176 @@
|
||||
# -*- shell-script -*-
|
||||
#
|
||||
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
# University Research and Technology
|
||||
# Corporation. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The University of Tennessee and The University
|
||||
# of Tennessee Research Foundation. All rights
|
||||
# reserved.
|
||||
# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
||||
# University of Stuttgart. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright (c) 2006-2007 Cisco Systems, Inc. All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
AC_INIT([plpa],
|
||||
[m4_normalize(esyscmd([config/plpa_get_version.sh VERSION --base]))],
|
||||
[http://www.open-mpi.org/community/help/], [plpa])
|
||||
AC_PREREQ(2.59)
|
||||
AC_CONFIG_AUX_DIR(./config)
|
||||
AC_CONFIG_MACRO_DIR(./config)
|
||||
|
||||
# Init automake
|
||||
AM_INIT_AUTOMAKE([foreign dist-bzip2 subdir-objects no-define])
|
||||
|
||||
# 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 OMPI that we are installing
|
||||
AC_MSG_CHECKING([for PLPA version])
|
||||
PLPA_VERSION="`$srcdir/config/plpa_get_version.sh $srcdir/VERSION`"
|
||||
PLPA_MAJOR_VERSION="`$srcdir/config/plpa_get_version.sh $srcdir/VERSION --major`"
|
||||
PLPA_MINOR_VERSION="`$srcdir/config/plpa_get_version.sh $srcdir/VERSION --minor`"
|
||||
PLPA_RELEASE_VERSION="`$srcdir/config/plpa_get_version.sh $srcdir/VERSION --release`"
|
||||
PLPA_SVN_R="`$srcdir/config/plpa_get_version.sh $srcdir/VERSION --svn`"
|
||||
AC_SUBST(PLPA_VERSION)
|
||||
AC_SUBST(PLPA_SVN_R)
|
||||
AC_DEFINE_UNQUOTED([PLPA_MAJOR_VERSION], [$PLPA_MAJOR_VERSION],
|
||||
[Major version of PLPA])
|
||||
AC_DEFINE_UNQUOTED([PLPA_MINOR_VERSION], [$PLPA_MINOR_VERSION],
|
||||
[Minor version of PLPA])
|
||||
AC_DEFINE_UNQUOTED([PLPA_RELEASE_VERSION], [$PLPA_RELEASE_VERSION],
|
||||
[Release version of PLPA])
|
||||
AC_MSG_RESULT([$PLPA_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="$PLPA_VERSION"
|
||||
PACKAGE_STRING="${PACKAGE_NAME} ${PACKAGE_VERSION}"
|
||||
VERSION="${PACKAGE_VERSION}"
|
||||
|
||||
# Setup the header file
|
||||
AH_TOP([/* -*- c -*-
|
||||
*
|
||||
* Copyright (c) 2004-2005 The Trustees of Indiana University.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2006 Cisco Systems, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#ifndef PLPA_H
|
||||
#define PLPA_H
|
||||
])
|
||||
AH_BOTTOM([
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "plpa_bottom.h"
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
#endif /* PLPA_H */
|
||||
])
|
||||
|
||||
# Compiler stuff
|
||||
AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
|
||||
# For the common developer case, if we're in a Subversion checkout and
|
||||
# using the GNU compilers, turn on maximum warnings unless
|
||||
# specifically disabled by the user.
|
||||
AC_MSG_CHECKING([whether to enable "picky" compiler mode])
|
||||
want_picky=0
|
||||
if test -d "$srcdir/.svn" -a "$GCC" = "yes"; then
|
||||
want_picky=1
|
||||
fi
|
||||
AC_ARG_ENABLE(picky,
|
||||
AC_HELP_STRING([--disable-picky],
|
||||
[When in Subversion checkouts of PLPA and compiling with gcc, the default is to enable maximum compiler pickyness. Using --disable-picky or --enable-picky overrides any default setting]))
|
||||
if test "$enable_picky" = "yes"; then
|
||||
if test "$GCC" = "yes"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
want_picky=1
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_WARN([Warning: --enable-picky used, but is currently only defined for the GCC compiler set -- automatically disabled])
|
||||
want_picky=0
|
||||
fi
|
||||
elif test "$enable_picky" = "no"; then
|
||||
AC_MSG_RESULT([no])
|
||||
want_picky=0
|
||||
else
|
||||
if test "$want_picky" = 1; then
|
||||
AC_MSG_RESULT([yes (default)])
|
||||
else
|
||||
AC_MSG_RESULT([no (default)])
|
||||
fi
|
||||
fi
|
||||
if test "$want_picky" = 1; then
|
||||
add="-Wall -Wundef -Wno-long-long -Wsign-compare"
|
||||
add="$add -Wmissing-prototypes -Wstrict-prototypes"
|
||||
add="$add -Wcomment -pedantic"
|
||||
|
||||
CFLAGS="$CFLAGS $add"
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether to enable debug mode])
|
||||
AC_ARG_ENABLE(debug,
|
||||
AC_HELP_STRING([--disable-debug],
|
||||
[When in Subversion checkouts of PLPA and compiling with gcc, the default is to debugging. Use --disable-debug or --enable-debug overrides any default setting]))
|
||||
|
||||
# Slightly different tests for whether we're in a svn checkout or not
|
||||
want_debug=no
|
||||
if test -d "$srcdir/.svn"; then
|
||||
if test "$enable_debug" = "no"; then
|
||||
value=0
|
||||
msg="no"
|
||||
else
|
||||
value=1
|
||||
msg="yes (default)"
|
||||
fi
|
||||
else
|
||||
if test "$enable_debug" = "yes"; then
|
||||
value=1
|
||||
msg="yes"
|
||||
else
|
||||
value=0
|
||||
msg="no (default)"
|
||||
fi
|
||||
fi
|
||||
if test "$value" = "1"; then
|
||||
CFLAGS="$CFLAGS -g"
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED([PLPA_DEBUG], [$value], [Whether we're in debugging mode or not])
|
||||
# Stupid emacs mode: '
|
||||
AC_MSG_RESULT([$msg])
|
||||
|
||||
# Setup the PLPA (taking all defaults)
|
||||
PLPA_STANDALONE
|
||||
PLPA_INIT([plpa_setup=happy], [plpa_setup=unhappy])
|
||||
AS_IF([test "$plpa_setup" = "unhappy"],
|
||||
[AC_MSG_ERROR([Cannot continue])])
|
||||
|
||||
# Setup libtool
|
||||
AM_ENABLE_SHARED
|
||||
AM_DISABLE_STATIC
|
||||
AM_PROG_LIBTOOL
|
||||
|
||||
# Party on
|
||||
AC_OUTPUT
|
199
opal/mca/paffinity/linux/plpa/contrib/dist/make_dist_tarball
поставляемый
Исполняемый файл
199
opal/mca/paffinity/linux/plpa/contrib/dist/make_dist_tarball
поставляемый
Исполняемый файл
@ -0,0 +1,199 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
# University Research and Technology
|
||||
# Corporation. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The University of Tennessee and The University
|
||||
# of Tennessee Research Foundation. All rights
|
||||
# reserved.
|
||||
# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
||||
# University of Stuttgart. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
#
|
||||
# Version of auto tools that we want
|
||||
#
|
||||
|
||||
AM_TARGET_VERSION=1.9.6
|
||||
AC_TARGET_VERSION=2.59
|
||||
LT_TARGET_VERSION=1.5.22
|
||||
|
||||
#
|
||||
# First things first -- check that the auto versions that we have are
|
||||
# the ones that we want.
|
||||
#
|
||||
|
||||
check_gnu_version() {
|
||||
prog="$1"
|
||||
target="$2"
|
||||
|
||||
ver="`$prog --version | head -n 1 | cut -d\ -f 4`"
|
||||
if test "$ver" != "$target"; then
|
||||
cat <<EOF
|
||||
ERROR: Program "$prog" does not have the correct/expected version:
|
||||
Found: $ver
|
||||
|
||||
Expected versions:
|
||||
Automake: $AM_TARGET_VERSION
|
||||
Autoconf: $AC_TARGET_VERSION
|
||||
Libtool: $LT_TARGET_VERSION
|
||||
|
||||
Either change this script to match the found version, or install
|
||||
the correct version of the tools.
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Subroutine to actually make a tarball
|
||||
#
|
||||
|
||||
make_tarball() {
|
||||
#
|
||||
# Autogen
|
||||
#
|
||||
echo "*** Removing old configure..."
|
||||
# Ensure that configure is re-generated -- sometimes it won't be
|
||||
# (if it hasn't changed), and therefore VERSION could be newer
|
||||
# than configure, and that leads to all kinds of problems
|
||||
rm -f configure
|
||||
echo "*** Running autogen.sh..."
|
||||
./autogen.sh 2>&1 | tee auto.out
|
||||
if test ! "$?" = "0"; then
|
||||
echo "Autogen failed. Aborting"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#
|
||||
# Configure
|
||||
#
|
||||
echo "*** Running configure..."
|
||||
./configure --enable-dist 2>&1 | tee config.out
|
||||
if test ! "$?" = "0"; then
|
||||
echo "Configure failed. Aborting"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#
|
||||
# Remove autogen.sh (just to ensure users don't try to run it)
|
||||
#
|
||||
echo "*** Removing autogen.sh from the tarball before make dist"
|
||||
rm -rf autogen.sh
|
||||
|
||||
#
|
||||
# make tarball
|
||||
#
|
||||
echo "*** Running make distcheck..."
|
||||
save_LD=$LD_LIBRARY_PATH
|
||||
LD_LIBRARY_PATH=
|
||||
make distcheck 2>&1 | tee dist.out
|
||||
if test ! "$?" = "0"; then
|
||||
echo "Make dist failed. Aborting"
|
||||
exit 1
|
||||
fi
|
||||
LD_LIBRARY_PATH=$save_LD
|
||||
|
||||
#
|
||||
# move
|
||||
#
|
||||
echo "*** Moving tarballs..."
|
||||
mv plpa-* ..
|
||||
|
||||
echo "*** All done"
|
||||
|
||||
#
|
||||
# bring back autogen.sh
|
||||
#
|
||||
svn up autogen.sh
|
||||
}
|
||||
|
||||
#########################################################################
|
||||
# main
|
||||
#########################################################################
|
||||
|
||||
echo "*** Checking GNU tools versions..."
|
||||
check_gnu_version automake $AM_TARGET_VERSION
|
||||
check_gnu_version autoconf $AC_TARGET_VERSION
|
||||
check_gnu_version libtool $LT_TARGET_VERSION
|
||||
|
||||
#
|
||||
# Verify that we're in a top PLPA dir
|
||||
#
|
||||
echo "*** Checking to ensure in top-level PLPA directory..."
|
||||
if test -f VERSION -a -f configure.ac -a -f config/plpa.m4; then
|
||||
happy=1
|
||||
else
|
||||
echo "Do not appear to be in a PLPA top directory. Abort!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#
|
||||
# Do svn up and all that
|
||||
#
|
||||
echo "*** Removing old VERSION files..."
|
||||
find . -name VERSION -exec rm -f {} \; -print
|
||||
|
||||
echo "*** Running svn up..."
|
||||
svn up
|
||||
if test ! "$?" = "0"; then
|
||||
echo "SVN update failed. Aborting"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#
|
||||
# Ditch "svn" from all version numbers
|
||||
#
|
||||
echo "*** Removing svn version numbers..."
|
||||
svn_r="r`svnversion .`"
|
||||
version_files="`find . -name VERSION`"
|
||||
for file in $version_files; do
|
||||
echo " - $file"
|
||||
sed -e 's/^want_svn=.*/want_svn=0/' \
|
||||
-e 's/^svn_r=.*/'svn_r=$svn_r/ $file > $file.new
|
||||
cp -f $file.new $file
|
||||
rm $file.new
|
||||
done
|
||||
|
||||
#
|
||||
# Make 2 tarballs:
|
||||
#
|
||||
# - one with the greek
|
||||
# - one without the greek
|
||||
#
|
||||
# unless the user specifically said --greekonly, then only make the
|
||||
# greek tarball. Making both tarballs at once allows us to guarantee
|
||||
# to have two tarballs -- one greek and one not -- that have exactly
|
||||
# the same SVN r number (as opposed to, for example, running this
|
||||
# script to make a greek tarball, then running it again to make a
|
||||
# non-greek tarball -- there is a race condition that someone could
|
||||
# commit in the meantime and change the SVN r number in the 2nd
|
||||
# tarball)
|
||||
#
|
||||
|
||||
# First, make greek tarball
|
||||
|
||||
echo "*** Making greek tarball"
|
||||
make_tarball
|
||||
|
||||
# Now if ! --greekonly, make the non-greek tarball
|
||||
|
||||
if test "$1" != "-greekonly" -a "$1" != "--greekonly"; then
|
||||
echo "*** REMOVING ALL GREEK FROM VERSION NUMBERS!!"
|
||||
for file in $version_files; do
|
||||
echo " - $file"
|
||||
sed -e 's/^greek=.*/greek=/' $file > $file.new
|
||||
cp -f $file.new $file
|
||||
rm $file.new
|
||||
done
|
||||
echo "Making non-greek tarball"
|
||||
make_tarball
|
||||
fi
|
||||
|
15
opal/mca/paffinity/linux/plpa/src/Makefile.am
Обычный файл
15
opal/mca/paffinity/linux/plpa/src/Makefile.am
Обычный файл
@ -0,0 +1,15 @@
|
||||
#
|
||||
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
# University Research and Technology
|
||||
# Corporation. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
SUBDIRS = libplpa plpa-info plpa-taskset
|
70
opal/mca/paffinity/linux/plpa/src/libplpa/Makefile.am
Обычный файл
70
opal/mca/paffinity/linux/plpa/src/libplpa/Makefile.am
Обычный файл
@ -0,0 +1,70 @@
|
||||
#
|
||||
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
# University Research and Technology
|
||||
# Corporation. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The University of Tennessee and The University
|
||||
# of Tennessee Research Foundation. All rights
|
||||
# reserved.
|
||||
# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
||||
# University of Stuttgart. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright (c) 2006-2007 Cisco Systems, Inc. All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
# Defaults
|
||||
lib_LTLIBRARIES =
|
||||
noinst_LTLIBRARIES =
|
||||
include_HEADERS =
|
||||
nodist_include_HEADERS =
|
||||
noinst_HEADERS = plpa_internal.h
|
||||
nodist_noinst_HEADERS =
|
||||
|
||||
nodist_public_headers = \
|
||||
plpa.h
|
||||
|
||||
public_headers = \
|
||||
plpa_bottom.h
|
||||
|
||||
# See which mode we're building in
|
||||
if PLPA_BUILD_STANDALONE
|
||||
lib_LTLIBRARIES += libplpa.la
|
||||
include_HEADERS += $(public_headers)
|
||||
nodist_include_HEADERS += $(nodist_public_headers)
|
||||
else
|
||||
noinst_LTLIBRARIES += libplpa_included.la
|
||||
noinst_HEADERS += $(public_headers)
|
||||
nodist_noinst_HEADERS += $(nodist_public_headers)
|
||||
endif
|
||||
|
||||
# The sources
|
||||
plpa_sources = \
|
||||
plpa_api_probe.c \
|
||||
plpa_dispatch.c \
|
||||
plpa_runtime.c \
|
||||
plpa_map.c
|
||||
|
||||
libplpa_la_SOURCES = $(plpa_sources)
|
||||
libplpa_included_la_SOURCES = $(plpa_sources)
|
||||
|
||||
# Add a hook to run *after* the header file has been installed out to
|
||||
# the target location. It changes the pesky PACKAGE_* macros that
|
||||
# autoconf automatically generates (and there is no way of turning
|
||||
# off) into PLPA_PACKAGE_* in order to make <plpa.h> safe to include
|
||||
# with other files.
|
||||
|
||||
if PLPA_BUILD_STANDALONE
|
||||
install-data-hook:
|
||||
sed -e 's/define PACKAGE/define PLPA_PACKAGE/' \
|
||||
$(DESTDIR)$(includedir)/plpa.h \
|
||||
> $(DESTDIR)$(includedir)/plpa.h.install
|
||||
cp $(DESTDIR)$(includedir)/plpa.h.install \
|
||||
$(DESTDIR)$(includedir)/plpa.h
|
||||
rm -f $(DESTDIR)$(includedir)/plpa.h.install
|
||||
chmod 0644 $(DESTDIR)$(includedir)/plpa.h
|
||||
endif
|
89
opal/mca/paffinity/linux/plpa/src/libplpa/plpa_api_probe.c
Обычный файл
89
opal/mca/paffinity/linux/plpa/src/libplpa/plpa_api_probe.c
Обычный файл
@ -0,0 +1,89 @@
|
||||
/* -*- c -*-
|
||||
*
|
||||
* Copyright (c) 2004-2005 The Trustees of Indiana University.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2007 Cisco, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include "plpa.h"
|
||||
#include "plpa_internal.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Cache, just to make things a little more efficient */
|
||||
static PLPA_NAME(api_type_t) cache = PLPA_NAME_CAPS(PROBE_UNSET);
|
||||
|
||||
/* The len value we find - not in public header, but used by the lib */
|
||||
size_t PLPA_NAME(len) = 0;
|
||||
|
||||
int PLPA_NAME(api_probe_init)(void)
|
||||
{
|
||||
PLPA_NAME(cpu_set_t) mask;
|
||||
int rc;
|
||||
size_t len;
|
||||
|
||||
for (len = sizeof(mask); len != 0; len >>= 1) {
|
||||
rc = syscall(__NR_sched_getaffinity, 0, len, &mask);
|
||||
if (rc >= 0) {
|
||||
/* OK, kernel is happy with a get(). Validate w/ a set(). */
|
||||
/* Note that kernel may have told us the "proper" size */
|
||||
size_t tmp = (0 != rc) ? ((size_t) rc) : len;
|
||||
/* Pass mask=NULL, expect errno==EFAULT if tmp was OK
|
||||
as a length */
|
||||
rc = syscall(__NR_sched_setaffinity, 0, tmp, NULL);
|
||||
if ((rc < 0) && (errno == EFAULT)) {
|
||||
cache = PLPA_NAME_CAPS(PROBE_OK);
|
||||
PLPA_NAME(len) = tmp;
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (errno == ENOSYS) {
|
||||
break; /* No point in looping */
|
||||
}
|
||||
}
|
||||
|
||||
if (rc >= 0) {
|
||||
/* OK */
|
||||
} else if (errno == ENOSYS) {
|
||||
/* Kernel returns ENOSYS because there is no support for
|
||||
processor affinity */
|
||||
cache = PLPA_NAME_CAPS(PROBE_NOT_SUPPORTED);
|
||||
} else {
|
||||
/* Unknown! */
|
||||
cache = PLPA_NAME_CAPS(PROBE_UNKNOWN);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int PLPA_NAME(api_probe)(PLPA_NAME(api_type_t) *api_type)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Check to see that we're initialized */
|
||||
if (!PLPA_NAME(initialized)) {
|
||||
if (0 != (ret = PLPA_NAME(init)())) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for bozo arguments */
|
||||
if (NULL == api_type) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* All done */
|
||||
*api_type = cache;
|
||||
return 0;
|
||||
}
|
134
opal/mca/paffinity/linux/plpa/src/libplpa/plpa_bottom.h
Обычный файл
134
opal/mca/paffinity/linux/plpa/src/libplpa/plpa_bottom.h
Обычный файл
@ -0,0 +1,134 @@
|
||||
/* -*- c -*-
|
||||
*
|
||||
* Copyright (c) 2004-2005 The Trustees of Indiana University.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#ifndef PLPA_BOTTOM_H
|
||||
#define PLPA_BOTTOM_H
|
||||
|
||||
/* Absolutely must not include <sched.h> here or it will generate
|
||||
conflicts. */
|
||||
|
||||
/* For memset() */
|
||||
#include <string.h>
|
||||
/* For pid_t and size_t */
|
||||
#include <sys/types.h>
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/* Internal macro to munge names */
|
||||
|
||||
/* Preprocessors are fun -- the double indirection is necessary.
|
||||
Extra bonus points if you can figure out why! :p */
|
||||
#define PLPA_MUNGE_NAME(a, b) PLPA_MUNGE_NAME2(a, b)
|
||||
#define PLPA_MUNGE_NAME2(a, b) a ## b
|
||||
#define PLPA_NAME(name) PLPA_MUNGE_NAME(PLPA_SYM_PREFIX, name)
|
||||
#define PLPA_NAME_CAPS(name) PLPA_MUNGE_NAME(PLPA_SYM_PREFIX_CAPS, name)
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/* Values that can be returned from plpa_api_probe() */
|
||||
typedef enum {
|
||||
/* Sentinel value */
|
||||
PLPA_NAME_CAPS(PROBE_UNSET),
|
||||
/* sched_setaffinity syscall available */
|
||||
PLPA_NAME_CAPS(PROBE_OK),
|
||||
/* syscall unavailable/unimplemented */
|
||||
PLPA_NAME_CAPS(PROBE_NOT_SUPPORTED),
|
||||
/* we experienced some strange failure that the user should report */
|
||||
PLPA_NAME_CAPS(PROBE_UNKNOWN)
|
||||
} PLPA_NAME(api_type_t);
|
||||
|
||||
/* Values that can be used in plpa_max_id() */
|
||||
typedef enum {
|
||||
/* Linux virtual processor */
|
||||
PLPA_NAME_CAPS(ID_TYPE_PROCESSOR),
|
||||
/* CPU sockets */
|
||||
PLPA_NAME_CAPS(ID_TYPE_SOCKET),
|
||||
/* CPU cores */
|
||||
PLPA_NAME_CAPS(ID_TYPE_CORE),
|
||||
/* Sentinel value */
|
||||
PLPA_NAME_CAPS(ID_TYPE_MAX)
|
||||
} PLPA_NAME(plpa_id_type_t);
|
||||
|
||||
/* PLPA bitmask type */
|
||||
typedef unsigned long int PLPA_NAME(bitmask_t);
|
||||
#define PLPA_BITMASK_T_NUM_BITS (sizeof(PLPA_NAME(bitmask_t)) * 8)
|
||||
#define PLPA_BITMASK_CPU_MAX 1024
|
||||
#define PLPA_BITMASK_NUM_ELEMENTS (PLPA_BITMASK_CPU_MAX / PLPA_BITMASK_T_NUM_BITS)
|
||||
typedef struct { PLPA_NAME(bitmask_t) bitmask[PLPA_BITMASK_NUM_ELEMENTS]; } PLPA_NAME(cpu_set_t);
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/* Internal macro for identifying the byte in a bitmask array */
|
||||
#define PLPA_CPU_BYTE(num) ((num) / PLPA_BITMASK_T_NUM_BITS)
|
||||
|
||||
/* Internal macro for identifying the bit in a bitmask array */
|
||||
#define PLPA_CPU_BIT(num) ((num) % PLPA_BITMASK_T_NUM_BITS)
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/* Public macro to zero out a PLPA cpu set */
|
||||
#define PLPA_CPU_ZERO(cpuset) \
|
||||
memset((cpuset), 0, sizeof(PLPA_NAME(cpu_set_t)))
|
||||
|
||||
/* Public macro to set a bit in a PLPA cpu set */
|
||||
#define PLPA_CPU_SET(num, cpuset) \
|
||||
(cpuset)->bitmask[PLPA_CPU_BYTE(num)] |= ((PLPA_NAME(bitmask_t))1 << PLPA_CPU_BIT(num))
|
||||
|
||||
/* Public macro to clear a bit in a PLPA cpu set */
|
||||
#define PLPA_CPU_CLR(num, cpuset) \
|
||||
(cpuset)->bitmask[PLPA_CPU_BYTE(num)] &= ~((PLPA_NAME(bitmask_t))1 << PLPA_CPU_BIT(num))
|
||||
|
||||
/* Public macro to test if a bit is set in a PLPA cpu set */
|
||||
#define PLPA_CPU_ISSET(num, cpuset) \
|
||||
(0 != (((cpuset)->bitmask[PLPA_CPU_BYTE(num)]) & ((PLPA_NAME(bitmask_t))1 << PLPA_CPU_BIT(num))))
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/* Setup PLPA internals */
|
||||
int PLPA_NAME(init)(void);
|
||||
|
||||
/* Check what API is on this machine */
|
||||
int PLPA_NAME(api_probe)(PLPA_NAME(api_type_t) *api_type);
|
||||
|
||||
/* Set processor affinity */
|
||||
int PLPA_NAME(sched_setaffinity)(pid_t pid, size_t cpusetsize,
|
||||
const PLPA_NAME(cpu_set_t) *cpuset);
|
||||
|
||||
/* Get processor affinity */
|
||||
int PLPA_NAME(sched_getaffinity)(pid_t pid, size_t cpusetsize,
|
||||
PLPA_NAME(cpu_set_t) *cpuset);
|
||||
|
||||
/* Return whether topology information is available (i.e.,
|
||||
plpa_map_to_*, plpa_max_*) */
|
||||
int PLPA_NAME(have_topology_information)(int *supported);
|
||||
|
||||
/* Map (socket,core) tuple to virtual processor ID */
|
||||
int PLPA_NAME(map_to_processor_id)(int socket, int core, int *processor_id);
|
||||
|
||||
/* Map processor_id to (socket,core) tuple */
|
||||
int PLPA_NAME(map_to_socket_core)(int processor_id, int *socket, int *core);
|
||||
|
||||
/* Return the max processor ID */
|
||||
int PLPA_NAME(max_processor_id)(int *max_processor_id);
|
||||
|
||||
/* Return the max socket number */
|
||||
int PLPA_NAME(max_socket)(int *max_socket);
|
||||
|
||||
/* Return the max core number for a given socket */
|
||||
int PLPA_NAME(max_core)(int socket, int *max_core);
|
||||
|
||||
/* Shut down PLPA */
|
||||
int PLPA_NAME(finalize)(void);
|
||||
|
||||
#endif /* PLPA_BOTTOM_H */
|
||||
|
206
opal/mca/paffinity/linux/plpa/src/libplpa/plpa_dispatch.c
Обычный файл
206
opal/mca/paffinity/linux/plpa/src/libplpa/plpa_dispatch.c
Обычный файл
@ -0,0 +1,206 @@
|
||||
/* -*- c -*-
|
||||
*
|
||||
* Copyright (c) 2004-2006 The Trustees of Indiana University.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include "plpa.h"
|
||||
#include "plpa_internal.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* Call the kernel's setaffinity, massaging the user's input
|
||||
* parameters as necessary
|
||||
*/
|
||||
int PLPA_NAME(sched_setaffinity)(pid_t pid, size_t cpusetsize,
|
||||
const PLPA_NAME(cpu_set_t) *cpuset)
|
||||
{
|
||||
int ret;
|
||||
size_t i;
|
||||
PLPA_NAME(cpu_set_t) tmp;
|
||||
PLPA_NAME(api_type_t) api;
|
||||
|
||||
/* Check to see that we're initialized */
|
||||
if (!PLPA_NAME(initialized)) {
|
||||
if (0 != (ret = PLPA_NAME(init)())) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for bozo arguments */
|
||||
if (NULL == cpuset) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* Probe the API type */
|
||||
if (0 != (ret = PLPA_NAME(api_probe)(&api))) {
|
||||
return ret;
|
||||
}
|
||||
switch (api) {
|
||||
case PLPA_NAME_CAPS(PROBE_OK):
|
||||
/* This shouldn't happen, but check anyway */
|
||||
if (cpusetsize > sizeof(*cpuset)) {
|
||||
return EINVAL;
|
||||
}
|
||||
if (NULL == cpuset) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* If the user-supplied bitmask is smaller than what the
|
||||
kernel wants, zero out a temporary buffer of the size that
|
||||
the kernel wants and copy the user-supplied bitmask to the
|
||||
lower part of the temporary buffer. This could be done
|
||||
more efficiently, but we're looking for clarity/simplicity
|
||||
of code here -- this is not intended to be
|
||||
performance-critical. */
|
||||
if (cpusetsize < PLPA_NAME(len)) {
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
for (i = 0; i < cpusetsize * 8; ++i) {
|
||||
if (PLPA_CPU_ISSET(i, cpuset)) {
|
||||
PLPA_CPU_SET(i, &tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If the user-supplied bitmask is larger than what the kernel
|
||||
will accept, scan it and see if there are any set bits in
|
||||
the part larger than what the kernel will accept. If so,
|
||||
return EINVAL. Otherwise, copy the part that the kernel
|
||||
will accept into a temporary and use that. Again,
|
||||
efficinency is not the issue of this code -- clarity is. */
|
||||
else if (cpusetsize > PLPA_NAME(len)) {
|
||||
for (i = PLPA_NAME(len) * 8; i < cpusetsize * 8; ++i) {
|
||||
if (PLPA_CPU_ISSET(i, cpuset)) {
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
/* No upper-level bits are set, so now copy over the bits
|
||||
that the kernel will look at */
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
for (i = 0; i < PLPA_NAME(len) * 8; ++i) {
|
||||
if (PLPA_CPU_ISSET(i, cpuset)) {
|
||||
PLPA_CPU_SET(i, &tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, the user supplied a buffer that is exactly the
|
||||
right size. Just for clarity of code, copy the user's
|
||||
buffer into the temporary and use that. */
|
||||
else {
|
||||
memcpy(&tmp, cpuset, cpusetsize);
|
||||
}
|
||||
|
||||
/* Now do the syscall */
|
||||
ret = syscall(__NR_sched_setaffinity, pid, PLPA_NAME(len), &tmp);
|
||||
|
||||
/* Return 0 upon success. According to
|
||||
http://www.open-mpi.org/community/lists/plpa-users/2006/02/0016.php,
|
||||
all the kernel implementations return >= 0 upon success. */
|
||||
if (ret >= 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case PLPA_NAME_CAPS(PROBE_NOT_SUPPORTED):
|
||||
/* Process affinity not supported here */
|
||||
return ENOSYS;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Something went wrong */
|
||||
/* JMS: would be good to have something other than EINVAL here
|
||||
-- suggestions? */
|
||||
return EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Call the kernel's getaffinity, massaging the user's input
|
||||
* parameters as necessary
|
||||
*/
|
||||
int PLPA_NAME(sched_getaffinity)(pid_t pid, size_t cpusetsize,
|
||||
PLPA_NAME(cpu_set_t) *cpuset)
|
||||
{
|
||||
int ret;
|
||||
PLPA_NAME(api_type_t) api;
|
||||
|
||||
/* Check to see that we're initialized */
|
||||
if (!PLPA_NAME(initialized)) {
|
||||
if (0 != (ret = PLPA_NAME(init)())) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for bozo arguments */
|
||||
if (NULL == cpuset) {
|
||||
return EINVAL;
|
||||
}
|
||||
/* Probe the API type */
|
||||
if (0 != (ret = PLPA_NAME(api_probe)(&api))) {
|
||||
return ret;
|
||||
}
|
||||
switch (api) {
|
||||
case PLPA_NAME_CAPS(PROBE_OK):
|
||||
/* This shouldn't happen, but check anyway */
|
||||
if (PLPA_NAME(len) > sizeof(*cpuset)) {
|
||||
return EINVAL;
|
||||
}
|
||||
if (NULL == cpuset) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* If the user supplied a buffer that is too small, then don't
|
||||
even bother */
|
||||
if (cpusetsize < PLPA_NAME(len)) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* Now we know that the user's buffer is >= the size required
|
||||
by the kernel. If it's >, then zero it out so that the
|
||||
bits at the top are cleared (since they won't be set by the
|
||||
kernel) */
|
||||
if (cpusetsize > PLPA_NAME(len)) {
|
||||
memset(cpuset, 0, cpusetsize);
|
||||
}
|
||||
|
||||
/* Now do the syscall */
|
||||
ret = syscall(__NR_sched_getaffinity, pid, PLPA_NAME(len), cpuset);
|
||||
|
||||
/* Return 0 upon success. According to
|
||||
http://www.open-mpi.org/community/lists/plpa-users/2006/02/0016.php,
|
||||
all the kernel implementations return >= 0 upon success. */
|
||||
if (ret >= 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case PLPA_NAME_CAPS(PROBE_NOT_SUPPORTED):
|
||||
/* Process affinity not supported here */
|
||||
return ENOSYS;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Something went wrong */
|
||||
return EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
36
opal/mca/paffinity/linux/plpa/src/libplpa/plpa_internal.h
Обычный файл
36
opal/mca/paffinity/linux/plpa/src/libplpa/plpa_internal.h
Обычный файл
@ -0,0 +1,36 @@
|
||||
/* -*- c -*-
|
||||
*
|
||||
* Copyright (c) 2004-2005 The Trustees of Indiana University.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#ifndef PLPA_INTERNAL_H
|
||||
#define PLPA_INTERNAL_H
|
||||
|
||||
#include <plpa.h>
|
||||
|
||||
/* Have we initialized yet? */
|
||||
extern int PLPA_NAME(initialized);
|
||||
|
||||
/* Cached size of the affinity buffers that the kernel expects */
|
||||
extern size_t PLPA_NAME(len);
|
||||
|
||||
/* Setup topology information */
|
||||
int PLPA_NAME(map_init)(void);
|
||||
|
||||
/* Setup API type */
|
||||
int PLPA_NAME(api_probe_init)(void);
|
||||
|
||||
/* Free all mapping memory */
|
||||
void PLPA_NAME(map_finalize)(void);
|
||||
|
||||
#endif /* PLPA_INTERNAL_H */
|
||||
|
501
opal/mca/paffinity/linux/plpa/src/libplpa/plpa_map.c
Обычный файл
501
opal/mca/paffinity/linux/plpa/src/libplpa/plpa_map.c
Обычный файл
@ -0,0 +1,501 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
|
||||
*
|
||||
* Portions of this file originally contributed by Advanced Micro
|
||||
* Devices, Inc. See notice below.
|
||||
*/
|
||||
/* ============================================================
|
||||
License Agreement
|
||||
|
||||
Copyright (c) 2006, 2007 Advanced Micro Devices, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in any form of this material and any product
|
||||
thereof including software in source or binary forms, along with any
|
||||
related documentation, with or without modification ("this material"),
|
||||
is permitted provided that the following conditions are met:
|
||||
|
||||
+ Redistributions of source code of any software must retain the above
|
||||
copyright notice and all terms of this license as part of the code.
|
||||
|
||||
+ Redistributions in binary form of any software must reproduce the
|
||||
above copyright notice and all terms of this license in any related
|
||||
documentation and/or other materials.
|
||||
|
||||
+ Neither the names nor trademarks of Advanced Micro Devices, Inc. or
|
||||
any copyright holders or contributors may be used to endorse or
|
||||
promote products derived from this material without specific prior
|
||||
written permission.
|
||||
|
||||
+ Notice about U.S. Government restricted rights: This material is
|
||||
provided with "RESTRICTED RIGHTS." Use, duplication or disclosure by
|
||||
the U.S. Government is subject to the full extent of restrictions set
|
||||
forth in FAR52.227 and DFARS252.227 et seq., or any successor or
|
||||
applicable regulations. Use of this material by the U.S. Government
|
||||
constitutes acknowledgment of the proprietary rights of Advanced Micro
|
||||
Devices, Inc.
|
||||
and any copyright holders and contributors.
|
||||
|
||||
+ In no event shall anyone redistributing or accessing or using this
|
||||
material commence or participate in any arbitration or legal action
|
||||
relating to this material against Advanced Micro Devices, Inc. or any
|
||||
copyright holders or contributors. The foregoing shall survive any
|
||||
expiration or termination of this license or any agreement or access
|
||||
or use related to this material.
|
||||
|
||||
+ ANY BREACH OF ANY TERM OF THIS LICENSE SHALL RESULT IN THE IMMEDIATE
|
||||
REVOCATION OF ALL RIGHTS TO REDISTRIBUTE, ACCESS OR USE THIS MATERIAL.
|
||||
|
||||
THIS MATERIAL IS PROVIDED BY ADVANCED MICRO DEVICES, INC. AND ANY
|
||||
COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" IN ITS CURRENT CONDITION
|
||||
AND WITHOUT ANY REPRESENTATIONS, GUARANTEE, OR WARRANTY OF ANY KIND OR
|
||||
IN ANY WAY RELATED TO SUPPORT, INDEMNITY, ERROR FREE OR UNINTERRUPTED
|
||||
OPERATION, OR THAT IT IS FREE FROM DEFECTS OR VIRUSES. ALL
|
||||
OBLIGATIONS ARE HEREBY DISCLAIMED - WHETHER EXPRESS, IMPLIED, OR
|
||||
STATUTORY - INCLUDING, BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF
|
||||
TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, ACCURACY,
|
||||
COMPLETENESS, OPERABILITY, QUALITY OF SERVICE, OR NON-INFRINGEMENT. IN
|
||||
NO EVENT SHALL ADVANCED MICRO DEVICES, INC. OR ANY COPYRIGHT HOLDERS
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, PUNITIVE, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
USE, REVENUE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED OR BASED ON ANY THEORY OF LIABILITY ARISING IN ANY WAY RELATED
|
||||
TO THIS MATERIAL, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
THE ENTIRE AND AGGREGATE LIABILITY OF ADVANCED MICRO DEVICES, INC. AND
|
||||
ANY COPYRIGHT HOLDERS AND CONTRIBUTORS SHALL NOT EXCEED TEN DOLLARS
|
||||
(US $10.00). ANYONE REDISTRIBUTING OR ACCESSING OR USING THIS MATERIAL
|
||||
ACCEPTS THIS ALLOCATION OF RISK AND AGREES TO RELEASE ADVANCED MICRO
|
||||
DEVICES, INC. AND ANY COPYRIGHT HOLDERS AND CONTRIBUTORS FROM ANY AND
|
||||
ALL LIABILITIES, OBLIGATIONS, CLAIMS, OR DEMANDS IN EXCESS OF TEN
|
||||
DOLLARS (US $10.00). THE FOREGOING ARE ESSENTIAL TERMS OF THIS LICENSE
|
||||
AND, IF ANY OF THESE TERMS ARE CONSTRUED AS UNENFORCEABLE, FAIL IN
|
||||
ESSENTIAL PURPOSE, OR BECOME VOID OR DETRIMENTAL TO ADVANCED MICRO
|
||||
DEVICES, INC. OR ANY COPYRIGHT HOLDERS OR CONTRIBUTORS FOR ANY REASON,
|
||||
THEN ALL RIGHTS TO REDISTRIBUTE, ACCESS OR USE THIS MATERIAL SHALL
|
||||
TERMINATE IMMEDIATELY. MOREOVER, THE FOREGOING SHALL SURVIVE ANY
|
||||
EXPIRATION OR TERMINATION OF THIS LICENSE OR ANY AGREEMENT OR ACCESS
|
||||
OR USE RELATED TO THIS MATERIAL.
|
||||
|
||||
NOTICE IS HEREBY PROVIDED, AND BY REDISTRIBUTING OR ACCESSING OR USING
|
||||
THIS MATERIAL SUCH NOTICE IS ACKNOWLEDGED, THAT THIS MATERIAL MAY BE
|
||||
SUBJECT TO RESTRICTIONS UNDER THE LAWS AND REGULATIONS OF THE UNITED
|
||||
STATES OR OTHER COUNTRIES, WHICH INCLUDE BUT ARE NOT LIMITED TO, U.S.
|
||||
EXPORT CONTROL LAWS SUCH AS THE EXPORT ADMINISTRATION REGULATIONS AND
|
||||
NATIONAL SECURITY CONTROLS AS DEFINED THEREUNDER, AS WELL AS STATE
|
||||
DEPARTMENT CONTROLS UNDER THE U.S. MUNITIONS LIST. THIS MATERIAL MAY
|
||||
NOT BE USED, RELEASED, TRANSFERRED, IMPORTED, EXPORTED AND/OR RE-
|
||||
EXPORTED IN ANY MANNER PROHIBITED UNDER ANY APPLICABLE LAWS, INCLUDING
|
||||
U.S. EXPORT CONTROL LAWS REGARDING SPECIFICALLY DESIGNATED PERSONS,
|
||||
COUNTRIES AND NATIONALS OF COUNTRIES SUBJECT TO NATIONAL SECURITY
|
||||
CONTROLS.
|
||||
MOREOVER,
|
||||
THE FOREGOING SHALL SURVIVE ANY EXPIRATION OR TERMINATION OF ANY
|
||||
LICENSE OR AGREEMENT OR ACCESS OR USE RELATED TO THIS MATERIAL.
|
||||
|
||||
This license forms the entire agreement regarding the subject matter
|
||||
hereof and supersedes all proposals and prior discussions and writings
|
||||
between the parties with respect thereto. This license does not affect
|
||||
any ownership, rights, title, or interest in, or relating to, this
|
||||
material. No terms of this license can be modified or waived, and no
|
||||
breach of this license can be excused, unless done so in a writing
|
||||
signed by all affected parties. Each term of this license is
|
||||
separately enforceable. If any term of this license is determined to
|
||||
be or becomes unenforceable or illegal, such term shall be reformed to
|
||||
the minimum extent necessary in order for this license to remain in
|
||||
effect in accordance with its terms as modified by such reformation.
|
||||
This license shall be governed by and construed in accordance with the
|
||||
laws of the State of Texas without regard to rules on conflicts of law
|
||||
of any state or jurisdiction or the United Nations Convention on the
|
||||
International Sale of Goods. All disputes arising out of this license
|
||||
shall be subject to the jurisdiction of the federal and state courts
|
||||
in Austin, Texas, and all defenses are hereby waived concerning
|
||||
personal jurisdiction and venue of these courts.
|
||||
============================================================ */
|
||||
|
||||
#include "plpa.h"
|
||||
#include "plpa_internal.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct tuple_t_ {
|
||||
int processor_id, socket, core;
|
||||
} tuple_t;
|
||||
|
||||
static int supported = 0;
|
||||
static int max_processor = -1;
|
||||
static int max_socket = -1;
|
||||
static int *max_core = NULL;
|
||||
static int max_core_overall = -1;
|
||||
static tuple_t *map_processor_id_to_tuple = NULL;
|
||||
static tuple_t ***map_tuple_to_processor_id = NULL;
|
||||
|
||||
static void clear_cache(void)
|
||||
{
|
||||
if (NULL != max_core) {
|
||||
free(max_core);
|
||||
max_core = NULL;
|
||||
}
|
||||
if (NULL != map_processor_id_to_tuple) {
|
||||
free(map_processor_id_to_tuple);
|
||||
map_processor_id_to_tuple = NULL;
|
||||
}
|
||||
if (NULL != map_tuple_to_processor_id) {
|
||||
if (NULL != map_tuple_to_processor_id[0]) {
|
||||
free(map_tuple_to_processor_id[0]);
|
||||
map_tuple_to_processor_id = NULL;
|
||||
}
|
||||
free(map_tuple_to_processor_id);
|
||||
map_tuple_to_processor_id = NULL;
|
||||
}
|
||||
|
||||
max_processor = -1;
|
||||
max_socket = -1;
|
||||
max_core_overall = -1;
|
||||
}
|
||||
|
||||
static void load_cache(const char *sysfs_mount)
|
||||
{
|
||||
int i, j, k, invalid_entry, fd;
|
||||
char path[PATH_MAX], buf[8];
|
||||
|
||||
/* Check for the parent directory */
|
||||
sprintf(path, "%s/devices/system/cpu", sysfs_mount);
|
||||
if (access(path, R_OK|X_OK)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Go through and find the max processor ID */
|
||||
for (max_processor = 0; max_processor < PLPA_BITMASK_CPU_MAX;
|
||||
++max_processor) {
|
||||
sprintf(path, "%s/devices/system/cpu/cpu%d", sysfs_mount,
|
||||
max_processor);
|
||||
if ( access(path, R_OK|X_OK) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
--max_processor;
|
||||
|
||||
/* Malloc space for the first map (processor ID -> tuple).
|
||||
Include enough space for one invalid entry. */
|
||||
map_processor_id_to_tuple = malloc(sizeof(tuple_t) * (max_processor + 2));
|
||||
if (NULL == map_processor_id_to_tuple) {
|
||||
return;
|
||||
}
|
||||
for (i = 0; i <= max_processor; ++i) {
|
||||
map_processor_id_to_tuple[i].processor_id = i;
|
||||
map_processor_id_to_tuple[i].socket = -1;
|
||||
map_processor_id_to_tuple[i].core = -1;
|
||||
}
|
||||
/* Set the invalid entry */
|
||||
invalid_entry = i;
|
||||
map_processor_id_to_tuple[invalid_entry].processor_id = -1;
|
||||
map_processor_id_to_tuple[invalid_entry].socket = -1;
|
||||
map_processor_id_to_tuple[invalid_entry].core = -1;
|
||||
|
||||
/* Malloc space for the max number of cores on each socket */
|
||||
max_core = malloc(sizeof(int) * (max_processor + 1));
|
||||
if (NULL == max_core) {
|
||||
clear_cache();
|
||||
return;
|
||||
}
|
||||
for (i = 0; i <= max_processor; ++i) {
|
||||
max_core[i] = -1;
|
||||
}
|
||||
|
||||
/* Build a cached map of (socket,core) tuples */
|
||||
for ( i = 0; i <= max_processor; i++ ) {
|
||||
sprintf(path, "%s/devices/system/cpu/cpu%d/topology/core_id",
|
||||
sysfs_mount, i);
|
||||
fd = open(path, O_RDONLY);
|
||||
if ( fd < 0 ) {
|
||||
clear_cache();
|
||||
return;
|
||||
}
|
||||
if ( read(fd, buf, 7) <= 0 ) {
|
||||
clear_cache();
|
||||
return;
|
||||
}
|
||||
sscanf(buf, "%d", &(map_processor_id_to_tuple[i].core));
|
||||
close(fd);
|
||||
|
||||
sprintf(path, "%s/devices/system/cpu/cpu%d/topology/physical_package_id",
|
||||
sysfs_mount, i);
|
||||
fd = open(path, O_RDONLY);
|
||||
if ( fd < 0 ) {
|
||||
clear_cache();
|
||||
return;
|
||||
}
|
||||
if ( read(fd, buf, 7) <= 0 ) {
|
||||
clear_cache();
|
||||
return;
|
||||
}
|
||||
sscanf(buf, "%d", &(map_processor_id_to_tuple[i].socket));
|
||||
close(fd);
|
||||
|
||||
/* Compute some globals */
|
||||
if (map_processor_id_to_tuple[i].socket > max_socket) {
|
||||
max_socket = map_processor_id_to_tuple[i].socket;
|
||||
}
|
||||
if (map_processor_id_to_tuple[i].core >
|
||||
max_core[map_processor_id_to_tuple[i].socket]) {
|
||||
max_core[map_processor_id_to_tuple[i].socket] =
|
||||
map_processor_id_to_tuple[i].core;
|
||||
}
|
||||
if (max_core[map_processor_id_to_tuple[i].socket] > max_core_overall) {
|
||||
max_core_overall = max_core[map_processor_id_to_tuple[i].socket];
|
||||
}
|
||||
}
|
||||
|
||||
/* Now go through and build the map in the other direction:
|
||||
(socket,core) => processor_id. This map simply points to
|
||||
entries in the other map (i.e., it's by reference instead of by
|
||||
value). */
|
||||
map_tuple_to_processor_id = malloc(sizeof(tuple_t **) * (max_socket + 1));
|
||||
if (NULL == map_tuple_to_processor_id) {
|
||||
clear_cache();
|
||||
return;
|
||||
}
|
||||
map_tuple_to_processor_id[0] = malloc(sizeof(tuple_t *) *
|
||||
((max_socket + 1) *
|
||||
(max_core_overall + 1)));
|
||||
if (NULL == map_tuple_to_processor_id[0]) {
|
||||
clear_cache();
|
||||
return;
|
||||
}
|
||||
/* Set pointers for 2nd dimension */
|
||||
for (i = 1; i <= max_socket; ++i) {
|
||||
map_tuple_to_processor_id[i] =
|
||||
map_tuple_to_processor_id[i - 1] + max_core_overall;
|
||||
}
|
||||
/* Compute map */
|
||||
for (i = 0; i <= max_socket; ++i) {
|
||||
for (j = 0; j <= max_core_overall; ++j) {
|
||||
/* Default to the invalid entry in the other map, meaning
|
||||
that this (socket,core) combination doesn't exist
|
||||
(e.g., the core number does not exist in this socket,
|
||||
although it does exist in other sockets). */
|
||||
map_tuple_to_processor_id[i][j] =
|
||||
&map_processor_id_to_tuple[invalid_entry];
|
||||
|
||||
/* See if this (socket,core) tuple exists in the other
|
||||
map. If so, set this entry to point to it (overriding
|
||||
the invalid entry default). */
|
||||
for (k = 0; k <= max_processor; ++k) {
|
||||
if (map_processor_id_to_tuple[k].socket == i &&
|
||||
map_processor_id_to_tuple[k].core == j) {
|
||||
map_tuple_to_processor_id[i][j] =
|
||||
&map_processor_id_to_tuple[k];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
supported = 1;
|
||||
}
|
||||
|
||||
/* Internal function to setup the mapping data. Guaranteed to be
|
||||
calling during PLPA_NAME(init), so we don't have to worry about
|
||||
thread safety here. */
|
||||
int PLPA_NAME(map_init)(void)
|
||||
{
|
||||
const char *sysfs_mount = "/sys";
|
||||
char *temp;
|
||||
|
||||
temp = getenv("PLPA_SYSFS_MOUNT");
|
||||
if (temp) {
|
||||
sysfs_mount = temp;
|
||||
}
|
||||
|
||||
load_cache(sysfs_mount);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Internal function to cleanup allocated memory. Only called by one
|
||||
thread (during PLPA_NAME(finalize), so don't need to worry about
|
||||
thread safety here. */
|
||||
void PLPA_NAME(map_finalize)(void)
|
||||
{
|
||||
clear_cache();
|
||||
}
|
||||
|
||||
/* Return whether this kernel supports topology information or not */
|
||||
int PLPA_NAME(have_topology_information)(int *supported_arg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Initialize if not already done so */
|
||||
if (!PLPA_NAME(initialized)) {
|
||||
if (0 != (ret = PLPA_NAME(init)())) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for bozo arguments */
|
||||
if (NULL == supported_arg) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
*supported_arg = supported;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PLPA_NAME(map_to_processor_id)(int socket, int core, int *processor_id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Initialize if not already done so */
|
||||
if (!PLPA_NAME(initialized)) {
|
||||
if (0 != (ret = PLPA_NAME(init)())) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for bozo arguments */
|
||||
if (NULL == processor_id) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* If this system doesn't support mapping, sorry Charlie */
|
||||
if (!supported) {
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
/* Check for some invalid entries */
|
||||
if (socket < 0 || socket > max_socket ||
|
||||
core < 0 || core > max_core_overall ||
|
||||
NULL == processor_id) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* Ok, all should be good -- return the mapping */
|
||||
*processor_id = map_tuple_to_processor_id[socket][core]->processor_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PLPA_NAME(map_to_socket_core)(int processor_id, int *socket, int *core)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Initialize if not already done so */
|
||||
if (!PLPA_NAME(initialized)) {
|
||||
if (0 != (ret = PLPA_NAME(init)())) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for bozo arguments */
|
||||
if (NULL == socket || NULL == core) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* If this system doesn't support mapping, sorry Charlie */
|
||||
if (!supported) {
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
/* Check for some invalid entries */
|
||||
if (processor_id < 0 || processor_id > max_processor ||
|
||||
NULL == socket ||
|
||||
NULL == core) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* Ok, all should be good -- return the mapping */
|
||||
*socket = map_processor_id_to_tuple[processor_id].socket;
|
||||
*core = map_processor_id_to_tuple[processor_id].core;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PLPA_NAME(max_processor_id)(int *max_processor_id_arg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Initialize if not already done so */
|
||||
if (!PLPA_NAME(initialized)) {
|
||||
if (0 != (ret = PLPA_NAME(init)())) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for bozo arguments */
|
||||
if (NULL == max_processor_id_arg) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* If this system doesn't support mapping, sorry Charlie */
|
||||
if (!supported) {
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
/* All done */
|
||||
*max_processor_id_arg = max_processor;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the max socket number */
|
||||
int PLPA_NAME(max_socket)(int *max_socket_arg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Initialize if not already done so */
|
||||
if (!PLPA_NAME(initialized)) {
|
||||
if (0 != (ret = PLPA_NAME(init)())) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for bozo arguments */
|
||||
if (NULL == max_socket_arg) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* If this system doesn't support mapping, sorry Charlie */
|
||||
if (!supported) {
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
/* All done */
|
||||
*max_socket_arg = max_socket;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the max core number for a given socket */
|
||||
int PLPA_NAME(max_core)(int socket, int *max_core_arg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Initialize if not already done so */
|
||||
if (!PLPA_NAME(initialized)) {
|
||||
if (0 != (ret = PLPA_NAME(init)())) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for bozo arguments */
|
||||
if (NULL == max_core_arg) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* If this system doesn't support mapping, sorry Charlie */
|
||||
if (!supported) {
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
/* Check for some invalid entries */
|
||||
if (socket < 0 || socket > max_socket) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* All done */
|
||||
*max_core_arg = max_core[socket];
|
||||
return 0;
|
||||
}
|
72
opal/mca/paffinity/linux/plpa/src/libplpa/plpa_runtime.c
Обычный файл
72
opal/mca/paffinity/linux/plpa/src/libplpa/plpa_runtime.c
Обычный файл
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "plpa.h"
|
||||
#include "plpa_internal.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
/* Global variables */
|
||||
int PLPA_NAME(initialized) = 0;
|
||||
|
||||
/* Local variables */
|
||||
static int refcount = 0;
|
||||
static pthread_mutex_t mutex;
|
||||
|
||||
|
||||
/* Central clearing point for all parts of PLPA that need to be
|
||||
initialized. It is erroneous to call this function by more than
|
||||
one thread simultaneously. */
|
||||
int PLPA_NAME(init)(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* If we're already initialized, simply increase the refcount */
|
||||
if (PLPA_NAME(initialized)) {
|
||||
pthread_mutex_lock(&mutex);
|
||||
++refcount;
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Otherwise, initialize all the sybsystems */
|
||||
if (0 != (ret = pthread_mutex_init(&mutex, NULL)) ||
|
||||
0 != (ret = PLPA_NAME(api_probe_init)()) ||
|
||||
0 != (ret = PLPA_NAME(map_init)())) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
PLPA_NAME(initialized) = 1;
|
||||
refcount = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Central clearing point for all parts of PLPA that need to be
|
||||
shutdown. */
|
||||
int PLPA_NAME(finalize)(void)
|
||||
{
|
||||
int val;
|
||||
|
||||
/* If we're not initialized, return an error */
|
||||
if (!PLPA_NAME(initialized)) {
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
/* Decrement and check the refcount. If it's nonzero, then simply
|
||||
return success. */
|
||||
pthread_mutex_lock(&mutex);
|
||||
val = --refcount;
|
||||
pthread_mutex_unlock(&mutex);
|
||||
if (0 != val) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Ok, we're the last one. Cleanup. */
|
||||
PLPA_NAME(map_finalize)();
|
||||
pthread_mutex_destroy(&mutex);
|
||||
PLPA_NAME(initialized) = 0;
|
||||
return 0;
|
||||
}
|
26
opal/mca/paffinity/linux/plpa/src/plpa-info/Makefile.am
Обычный файл
26
opal/mca/paffinity/linux/plpa/src/plpa-info/Makefile.am
Обычный файл
@ -0,0 +1,26 @@
|
||||
#
|
||||
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
# University Research and Technology
|
||||
# Corporation. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
# Default to empty
|
||||
bin_PROGRAMS=
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/src/libplpa
|
||||
|
||||
# See which mode we're building in
|
||||
if PLPA_BUILD_EXECUTABLES
|
||||
bin_PROGRAMS += plpa-info
|
||||
endif
|
||||
|
||||
plpa_info_SOURCES = plpa-info.c
|
||||
plpa_info_LDADD = $(top_builddir)/src/libplpa/libplpa.la
|
103
opal/mca/paffinity/linux/plpa/src/plpa-info/plpa-info.c
Обычный файл
103
opal/mca/paffinity/linux/plpa/src/plpa-info/plpa-info.c
Обычный файл
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2005 The Trustees of Indiana University.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <plpa.h>
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
int ret = 0;
|
||||
int need_help = 0;
|
||||
int show_topo = 0;
|
||||
int have_topo, max_socket, max_core;
|
||||
PLPA_NAME(api_type_t) api_probe;
|
||||
|
||||
for (i = 1; i < argc; ++i) {
|
||||
if (0 == strcmp("--version", argv[i])) {
|
||||
printf("PLPA version %s\n", PACKAGE_VERSION);
|
||||
exit(0);
|
||||
} else if (0 == strcmp("--help", argv[i])) {
|
||||
need_help = 1;
|
||||
ret = 0;
|
||||
break;
|
||||
} else if (0 == strcmp("--topo", argv[i])) {
|
||||
show_topo = 1;
|
||||
} else {
|
||||
printf("%s: unrecognized option: %s\n",
|
||||
argv[0], argv[i]);
|
||||
need_help = 1;
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (need_help) {
|
||||
printf("usage: %s [--version | --topo] [--help]\n", argv[0]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Is affinity supported at all? */
|
||||
|
||||
if (0 != PLPA_NAME(api_probe)(&api_probe)) {
|
||||
api_probe = PLPA_NAME_CAPS(PROBE_NOT_SUPPORTED);
|
||||
}
|
||||
printf("Kernel affinity support: ");
|
||||
switch (api_probe) {
|
||||
case PLPA_NAME_CAPS(PROBE_OK):
|
||||
printf("yes\n");
|
||||
break;
|
||||
case PLPA_NAME_CAPS(PROBE_NOT_SUPPORTED):
|
||||
printf("no\n");
|
||||
break;
|
||||
default:
|
||||
printf("unknonwn (no)\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* What about topology? */
|
||||
|
||||
if (0 != PLPA_NAME(have_topology_information)(&have_topo)) {
|
||||
have_topo = 0;
|
||||
}
|
||||
printf("Kernel topology support: %s\n", have_topo ? "yes" : "no");
|
||||
if (0 != PLPA_NAME(max_socket)(&max_socket)) {
|
||||
max_socket = -1;
|
||||
}
|
||||
printf("Number of processor sockets: %d\n", have_topo ? max_socket : -1);
|
||||
|
||||
/* If asked, print the map */
|
||||
|
||||
if (show_topo) {
|
||||
if (have_topo) {
|
||||
/* Remember that max_socket and max_core values are
|
||||
0-indexed */
|
||||
for (i = 0; i <= max_socket; ++i) {
|
||||
ret = PLPA_NAME(max_core)(i, &max_core);
|
||||
if (0 == ret) {
|
||||
printf("Socket %d: %d core%s\n", i, max_core + 1,
|
||||
(0 == max_core) ? "" : "s");
|
||||
} else {
|
||||
printf("Socket %d: unknown cores\n", i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("Kernel topology not supported -- cannot show topology information\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
38
opal/mca/paffinity/linux/plpa/src/plpa-taskset/Makefile.am
Обычный файл
38
opal/mca/paffinity/linux/plpa/src/plpa-taskset/Makefile.am
Обычный файл
@ -0,0 +1,38 @@
|
||||
#
|
||||
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
# University Research and Technology
|
||||
# Corporation. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
# Default to empty
|
||||
bin_PROGRAMS=
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/src/libplpa
|
||||
AM_YFLAGS = -d
|
||||
|
||||
if PLPA_BUILD_EXECUTABLES
|
||||
bin_PROGRAMS += plpa-taskset
|
||||
endif
|
||||
|
||||
# Force recognition that tokens.h is generated via tokens.c; there's a
|
||||
# rule to create tokens.c from tokens.y.
|
||||
tokens.c: tokens.y
|
||||
tokens.h: tokens.c
|
||||
|
||||
# Force parser.c to be re-compiled when tokens.h is re-generated
|
||||
parser.c: tokens.h
|
||||
|
||||
plpa_taskset_SOURCES = \
|
||||
plpa-taskset.c \
|
||||
plpa-taskset.h \
|
||||
parser.l \
|
||||
tokens.y
|
||||
plpa_taskset_LDADD = $(top_builddir)/src/libplpa/libplpa.la
|
53
opal/mca/paffinity/linux/plpa/src/plpa-taskset/info.txt
Обычный файл
53
opal/mca/paffinity/linux/plpa/src/plpa-taskset/info.txt
Обычный файл
@ -0,0 +1,53 @@
|
||||
The requirements are:
|
||||
|
||||
1. devise a relatively simple command line syntax to bind a single
|
||||
process to a set of (socket,core) tuples
|
||||
|
||||
2. be compatible with the "taskset" precedent, meaning:
|
||||
- specify the sets of tuples in a single command line token (e.g.,
|
||||
comma delimited?)
|
||||
- be able to clearly differentiate this notation from the
|
||||
"taskset" processor mask and list specifications (so that it's
|
||||
clear when to treat a command line token as a processor mask, a
|
||||
processor list, and a set of (socket,core) tuples)
|
||||
|
||||
3. be able to specify a single tuple with a some kind of "stride" for
|
||||
repeating simple patterns (analogous to taskset's "x-y:step" range
|
||||
notation)
|
||||
|
||||
4. include ability to wildcard sockets or cores. For example:
|
||||
- bind to all cores on sockets x, y, z
|
||||
- bind to cores x, y, z on all sockets
|
||||
|
||||
5. not force the user to use escapes in common shells (e.g., avoid the
|
||||
use of *, !, and other shell-special characters)
|
||||
|
||||
Here's what I have figured out so far:
|
||||
|
||||
- use the general notation "<core>@<socket>"
|
||||
- wildcard values:
|
||||
- "all" -- all sockets/cores (depending on context)
|
||||
- "even" -- even numbered sockets/cores
|
||||
- "odd" -- odd numbered sockets/cores
|
||||
- "not" -- negate the specified sockets and/or cores
|
||||
- ...easy enough to add others
|
||||
- sockets and cores are numbered starting with 0 (just like processor
|
||||
IDs)
|
||||
- multiple tuples can be specified as a comma delimited list
|
||||
- core/socket ranges can be specified as "x-y", where x<=y
|
||||
- {} can be used to specify lists of cores or sockets, and can be used
|
||||
to make complex tuples
|
||||
- examples:
|
||||
- binding to core 3 on socket 1 is "3@1"
|
||||
- binding to core 1 on all sockets is "1@all"
|
||||
- binding to all cores on socket 2 is "all@2"
|
||||
- binding to all cores on sockets 2 and 3 is "all@2,all@3" OR
|
||||
"all@{2,3}"
|
||||
- binding to cores 1 and 2 on sockets 0, 1, and 3 is
|
||||
"{1,2}@{0,1,3}"
|
||||
- binding to cores 0, 1, and 2 on sockets 0, 1, 2, and 5 is
|
||||
"{0-2}@{0-2,5}"
|
||||
- binding to all cores on all sockets (effectively disables PA) is
|
||||
"all@all"
|
||||
- binding to all cores on all sockets *except* all cores on socket
|
||||
0 is "all@not0"
|
78
opal/mca/paffinity/linux/plpa/src/plpa-taskset/parser.l
Обычный файл
78
opal/mca/paffinity/linux/plpa/src/plpa-taskset/parser.l
Обычный файл
@ -0,0 +1,78 @@
|
||||
%{ /* -*- C -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include "plpa.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "plpa-taskset.h"
|
||||
#include "tokens.h"
|
||||
|
||||
/*
|
||||
* local functions
|
||||
*/
|
||||
static int finish_parsing(void);
|
||||
|
||||
#define yyterminate() \
|
||||
return finish_parsing()
|
||||
|
||||
/*
|
||||
* Make lex-generated files not issue compiler warnings
|
||||
*/
|
||||
#define YY_STACK_USED 0
|
||||
#define YY_ALWAYS_INTERACTIVE 0
|
||||
#define YY_NEVER_INTERACTIVE 0
|
||||
#define YY_MAIN 0
|
||||
#define YY_NO_UNPUT 1
|
||||
|
||||
%}
|
||||
|
||||
%option noyywrap
|
||||
|
||||
%%
|
||||
|
||||
[0-9]* { yylval.number = atoi(yytext); return TOKENS_NUMBER; }
|
||||
|
||||
"all" { return TOKENS_STRING_ALL; }
|
||||
|
||||
"even" { return TOKENS_STRING_EVEN; }
|
||||
|
||||
"odd" { return TOKENS_STRING_ODD; }
|
||||
|
||||
"not" { return TOKENS_STRING_NOT; }
|
||||
|
||||
. { return *yytext; }
|
||||
|
||||
%%
|
||||
|
||||
|
||||
/*
|
||||
* This cleans up at the end of the parse (since, in this case, we
|
||||
* always parse the entire file) and prevents a memory leak.
|
||||
*/
|
||||
static int finish_parsing(void)
|
||||
{
|
||||
if (NULL != YY_CURRENT_BUFFER) {
|
||||
yy_delete_buffer(YY_CURRENT_BUFFER);
|
||||
#if defined(YY_CURRENT_BUFFER_LVALUE)
|
||||
YY_CURRENT_BUFFER_LVALUE = NULL;
|
||||
#else
|
||||
YY_CURRENT_BUFFER = NULL;
|
||||
#endif /* YY_CURRENT_BUFFER_LVALUE */
|
||||
}
|
||||
return YY_NULL;
|
||||
}
|
||||
|
||||
void parser_setup_string(char *str)
|
||||
{
|
||||
yy_scan_string(str);
|
||||
}
|
438
opal/mca/paffinity/linux/plpa/src/plpa-taskset/plpa-taskset.c
Обычный файл
438
opal/mca/paffinity/linux/plpa/src/plpa-taskset/plpa-taskset.c
Обычный файл
@ -0,0 +1,438 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Cisco, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*
|
||||
* And before you ask: no, none of this code is lifted from the GPL'ed
|
||||
* taskset source. I looked at that source code just enough to read
|
||||
* the header and realize that it was GPL. This is entirely new
|
||||
* source code unencumbered by the GPL. I read the man page to make
|
||||
* this functionality similar to that of the taskset command. The
|
||||
* goal here is to make an executable that behaves like the venerable
|
||||
* taskset command but has some more options, such as for socket and
|
||||
* core mapping.
|
||||
*/
|
||||
|
||||
/* Needed for getopt_long() */
|
||||
#define GNU_SOURCE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <plpa.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "plpa-taskset.h"
|
||||
|
||||
static void show_help(char *argv0, int ret)
|
||||
{
|
||||
printf("plpa_taskset version %s\n", PACKAGE_VERSION);
|
||||
printf("usage: %s [options] [mask | cpu-list] [pid | cmd [args...]]\n",
|
||||
argv0);
|
||||
printf("set or get the affinity of a process\n\n");
|
||||
printf(" -p, --pid operating on existing given pid\n");
|
||||
printf(" pid can also be \"self\" or \"parent\"\n");
|
||||
printf(" -c, --cpu-list display and specify cpus in list format\n");
|
||||
printf(" -h, --help display this help\n");
|
||||
printf(" -v, --version output version information\n");
|
||||
printf("\n");
|
||||
printf("The default behavior is to run a new command:\n");
|
||||
printf(" %s 03 sshd -b 1024\n", argv0);
|
||||
printf("You can retrieve the mask of an existing task:\n");
|
||||
printf(" %s -p 700\n", argv0);
|
||||
printf("Or set it:\n");
|
||||
printf(" %s -p 03 700\n", argv0);
|
||||
printf("List format uses a comma-separated list instead of a mask:\n");
|
||||
printf(" %s -pc 0,3,7-11 700\n", argv0);
|
||||
printf("Ranges in list format can take a stride argument:\n");
|
||||
printf(" e.g. 0-31:2 is equivalent to mask 0x55555555\n");
|
||||
printf("\n");
|
||||
printf("Core/socket tuples can be specified with <core>@<socket> syntax:\n");
|
||||
printf(" %s -pc 1@3,0@2 700\n", argv0);
|
||||
printf("\"all\", \"even\", and \"odd\" are valid in the socket/core syntax:\n");
|
||||
printf(" %s -pc all@3,2@even 700\n", argv0);
|
||||
printf("\"all\" can be used to disable affinity:\n");
|
||||
printf(" %s -pc all@all 700\n", argv0);
|
||||
printf("Complex core/socket tuples can be specified with {}:\n");
|
||||
printf(" %s -pc {0-2}@{0-2,5} 700\n", argv0);
|
||||
printf("\"parent\" can be used as the PID:\n");
|
||||
printf(" %s -pc even@all parent\n", argv0);
|
||||
printf("\n");
|
||||
|
||||
exit(ret);
|
||||
}
|
||||
|
||||
static void show_version(void)
|
||||
{
|
||||
printf("plpa_taskset version %s\n", PACKAGE_VERSION);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void append(char *str, int val)
|
||||
{
|
||||
char temp[8];
|
||||
|
||||
if ('\0' != str[0]) {
|
||||
strcat(str, ",");
|
||||
}
|
||||
snprintf(temp, sizeof(temp) - 1, "%d", val);
|
||||
strcat(str, temp);
|
||||
}
|
||||
|
||||
static char *cpu_set_to_list(const PLPA_NAME(cpu_set_t) *cpu_set)
|
||||
{
|
||||
size_t i, j, last_bit, size = PLPA_BITMASK_NUM_ELEMENTS;
|
||||
unsigned long long mask_value = 0;
|
||||
/* Upper bound on string length: 4 digits per
|
||||
PLPA_BITMASK_NUM_ELEMENTS + 1 comma for each */
|
||||
static char str[PLPA_BITMASK_NUM_ELEMENTS * 5];
|
||||
char temp[8];
|
||||
|
||||
if (sizeof(mask_value) * 8 < size) {
|
||||
size = sizeof(mask_value) * 8;
|
||||
}
|
||||
/* Only print ranges for 3 or more consecutive bits, otherwise
|
||||
print individual numbers. */
|
||||
str[0] = '\0';
|
||||
for (i = 0; i < size; ++i) {
|
||||
if (PLPA_CPU_ISSET(i, cpu_set)) {
|
||||
/* This bit is set -- is it part of a longer series? */
|
||||
/* Simple answer: if this is the last or next-to-last bit,
|
||||
just print it */
|
||||
if (i == size - 1 || i == size - 2) {
|
||||
append(str, i);
|
||||
continue;
|
||||
}
|
||||
/* Simple answer: if next bit is not set, then just print
|
||||
it */
|
||||
else if (!PLPA_CPU_ISSET(i + 1, cpu_set)) {
|
||||
append(str, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Look for the next unset bit */
|
||||
last_bit = i;
|
||||
for (j = i + 1; j < size; ++j) {
|
||||
if (!PLPA_CPU_ISSET(j, cpu_set)) {
|
||||
last_bit = j - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* If we fell off the end of the array without finding an
|
||||
unset bit, then they're all set. */
|
||||
if (j >= size) {
|
||||
last_bit = size - 1;
|
||||
}
|
||||
|
||||
if (i != last_bit) {
|
||||
/* last_bit is now the last bit set after i (and it
|
||||
might actually be i). So if last_bit > i+2, print
|
||||
the range. */
|
||||
if (last_bit >= i + 2) {
|
||||
append(str, i);
|
||||
strcat(str, "-");
|
||||
snprintf(temp, sizeof(temp) - 1, "%d", (int) last_bit);
|
||||
strcat(str, temp);
|
||||
} else {
|
||||
/* It wasn't worth printing a range, so print
|
||||
i, and possibly print last_bit */
|
||||
append(str, i);
|
||||
if (last_bit != i) {
|
||||
append(str, last_bit);
|
||||
}
|
||||
}
|
||||
i = last_bit + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
static unsigned long long cpu_set_to_ll(const PLPA_NAME(cpu_set_t) *cpu_set)
|
||||
{
|
||||
size_t i, size = PLPA_BITMASK_NUM_ELEMENTS;
|
||||
unsigned long long mask_value = 0;
|
||||
|
||||
if (sizeof(mask_value) * 8 < size) {
|
||||
size = sizeof(mask_value) * 8;
|
||||
}
|
||||
for (i = 0; i < size; ++i) {
|
||||
if (PLPA_CPU_ISSET(i, cpu_set)) {
|
||||
mask_value += 1 << i;
|
||||
}
|
||||
}
|
||||
return mask_value;
|
||||
}
|
||||
|
||||
static int cpu_list_to_cpu_set(char *str, PLPA_NAME(cpu_set_t) *cpu_set)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (NULL == str) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
parser_setup_string(str);
|
||||
ret = token_parse(cpu_set);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mask_to_cpu_set(char *mask_string, PLPA_NAME(cpu_set_t) *cpu_set)
|
||||
{
|
||||
size_t i;
|
||||
unsigned int mask_value;
|
||||
|
||||
PLPA_CPU_ZERO(cpu_set);
|
||||
sscanf(mask_string, "%x", &mask_value);
|
||||
for (i = 0; i < sizeof(mask_value) * 8; ++i) {
|
||||
if (0 != (mask_value & (1 << i))) {
|
||||
PLPA_CPU_SET(i, cpu_set);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void run_test(int use_cpu_list, char *str)
|
||||
{
|
||||
int ret = 0;
|
||||
PLPA_NAME(cpu_set_t) cpu_set;
|
||||
|
||||
PLPA_CPU_ZERO(&cpu_set);
|
||||
if (use_cpu_list) {
|
||||
if (0 == cpu_list_to_cpu_set(str, &cpu_set)) {
|
||||
printf("in:%s\nout:%s\n", str, cpu_set_to_list(&cpu_set));
|
||||
} else {
|
||||
ret = 1;
|
||||
}
|
||||
} else {
|
||||
if (0 == mask_to_cpu_set(str, &cpu_set)) {
|
||||
printf("%s\n%llx\n", str, cpu_set_to_ll(&cpu_set));
|
||||
} else {
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
exit(ret);
|
||||
}
|
||||
|
||||
static int get_pid_affinity(int use_cpu_list, char *pid_string)
|
||||
{
|
||||
int ret, pid = atoi(pid_string);
|
||||
PLPA_NAME(cpu_set_t) cpu_set;
|
||||
|
||||
/* Check for the special pid_strings of "self" and "parent" */
|
||||
if (0 == strcmp(pid_string, "self")) {
|
||||
pid = getpid();
|
||||
} else if (0 == strcmp(pid_string, "parent")) {
|
||||
pid = getppid();
|
||||
}
|
||||
|
||||
/* Report the affinity */
|
||||
ret = PLPA_NAME(sched_getaffinity)((pid_t) pid, sizeof(cpu_set), &cpu_set);
|
||||
switch (ret) {
|
||||
case 0:
|
||||
if (use_cpu_list) {
|
||||
printf("pid %d's current affinity list: %s\n", pid,
|
||||
cpu_set_to_list(&cpu_set));
|
||||
} else {
|
||||
printf("pid %d's current affinity mask: %llx\n", pid,
|
||||
cpu_set_to_ll(&cpu_set));
|
||||
}
|
||||
break;
|
||||
|
||||
case ENOSYS:
|
||||
printf("sched_getaffinity: processor affinity is not supported on this kernel\n");
|
||||
printf("failed to get pid %d's affinity.\n", pid);
|
||||
break;
|
||||
|
||||
default:
|
||||
perror("sched_getaffinity");
|
||||
printf("failed to get pid %d's affinity.\n", pid);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_pid_affinity(int use_cpu_list, char *mask_string,
|
||||
char *pid_string)
|
||||
{
|
||||
int ret, pid;
|
||||
PLPA_NAME(cpu_set_t) cpu_set;
|
||||
|
||||
/* Print the original affinity */
|
||||
ret = get_pid_affinity(use_cpu_list, pid_string);
|
||||
if (0 != ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Convert the argv token mask string to a PLPA cpu set */
|
||||
PLPA_CPU_ZERO(&cpu_set);
|
||||
if (use_cpu_list) {
|
||||
if (0 != (ret = cpu_list_to_cpu_set(mask_string, &cpu_set))) {
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
if (0 != (ret = mask_to_cpu_set(mask_string, &cpu_set))) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the affinity */
|
||||
|
||||
/* Check for the special pid_strings of "self" and "parent" */
|
||||
if (0 == strcmp(pid_string, "self")) {
|
||||
pid = getpid();
|
||||
} else if (0 == strcmp(pid_string, "parent")) {
|
||||
pid = getppid();
|
||||
} else {
|
||||
pid = atoi(pid_string);
|
||||
}
|
||||
ret = PLPA_NAME(sched_setaffinity)((pid_t) pid, sizeof(cpu_set), &cpu_set);
|
||||
switch (ret) {
|
||||
case 0:
|
||||
if (use_cpu_list) {
|
||||
printf("pid %d's new affinity list: %s\n",
|
||||
pid, cpu_set_to_list(&cpu_set));
|
||||
} else {
|
||||
printf("pid %d's new affinity mask: %llx\n",
|
||||
pid, cpu_set_to_ll(&cpu_set));
|
||||
}
|
||||
break;
|
||||
|
||||
case ENOSYS:
|
||||
printf("sched_setaffinity: processor affinity is not supported on this kernel\n");
|
||||
printf("failed to set pid %d's affinity.\n", pid);
|
||||
break;
|
||||
|
||||
default:
|
||||
perror("sched_setaffinity");
|
||||
printf("failed to set pid %d's affinity.\n", pid);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int launch_task(int use_cpu_list, char **argv)
|
||||
{
|
||||
int ret, cmd_begins;
|
||||
PLPA_NAME(cpu_set_t) cpu_set;
|
||||
|
||||
/* The next argument is the list/mask, optionally followed by
|
||||
"--", then the argv to launch */
|
||||
|
||||
PLPA_CPU_ZERO(&cpu_set);
|
||||
if (use_cpu_list) {
|
||||
if (0 != (ret = cpu_list_to_cpu_set(argv[0], &cpu_set))) {
|
||||
exit(ret);
|
||||
}
|
||||
} else {
|
||||
if (0 != (ret = mask_to_cpu_set(argv[0], &cpu_set))) {
|
||||
exit(ret);
|
||||
}
|
||||
}
|
||||
if (0 != PLPA_NAME(sched_setaffinity)(getpid(), sizeof(cpu_set), &cpu_set)) {
|
||||
perror("sched_setaffinity");
|
||||
fprintf(stderr, "failed to set pid %d's affinity.\n", getpid());
|
||||
}
|
||||
|
||||
/* The next argument may be "--". If so, ignore it */
|
||||
|
||||
if (0 == strcmp(argv[1], "--")) {
|
||||
cmd_begins = 2;
|
||||
} else {
|
||||
cmd_begins = 1;
|
||||
}
|
||||
execvp(argv[cmd_begins], &argv[cmd_begins]);
|
||||
|
||||
/* If we get here, Something Bad Happened(tm) */
|
||||
perror("execvp");
|
||||
fprintf(stderr, "failed to execute %s\n", argv[cmd_begins]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int option;
|
||||
int getting_pid = 0;
|
||||
int use_cpu_list = 0;
|
||||
int testing = 0;
|
||||
struct option options[] = {
|
||||
{ "pid", 0, NULL, 'p' },
|
||||
{ "cpu-list", 0, NULL, 'c' },
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ "version", 0, NULL, 'V' },
|
||||
{ "testing", 0, NULL, 't' },
|
||||
/* Undocumented testing function */
|
||||
{ "testing", 0, NULL, 't' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
while (-1 != (option = getopt_long(argc, argv, "+pchVt", options, NULL))) {
|
||||
switch (option) {
|
||||
case 'p':
|
||||
getting_pid = 1;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
use_cpu_list = 1;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
show_help(argv[0], 0);
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
show_version();
|
||||
break;
|
||||
|
||||
case 't':
|
||||
testing = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
show_help(argv[0], 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* No argv? Show the help. */
|
||||
if (1 == argc) {
|
||||
show_help(argv[0], 1);
|
||||
}
|
||||
|
||||
/* Undocumented testing function */
|
||||
if (testing) {
|
||||
run_test(use_cpu_list, argv[optind]);
|
||||
}
|
||||
|
||||
/* If we're getting_pid:
|
||||
- If there's 1 argument, it's the PID to *get*
|
||||
- If there's 2 arguments, it's the mask/list and the PID to *set*
|
||||
- Otherwise, it's an error -- show the help message */
|
||||
if (getting_pid) {
|
||||
if (optind + 1 == argc) {
|
||||
return get_pid_affinity(use_cpu_list, argv[optind]);
|
||||
} else if (optind + 2 == argc) {
|
||||
return set_pid_affinity(use_cpu_list,
|
||||
argv[optind], argv[optind + 1]);
|
||||
} else {
|
||||
show_help(argv[0], 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, it looks like we're launching a command */
|
||||
launch_task(use_cpu_list, argv + optind);
|
||||
|
||||
/* We should never get here */
|
||||
return 1;
|
||||
}
|
32
opal/mca/paffinity/linux/plpa/src/plpa-taskset/plpa-taskset.h
Обычный файл
32
opal/mca/paffinity/linux/plpa/src/plpa-taskset/plpa-taskset.h
Обычный файл
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#ifndef PLPA_TASKSET_H
|
||||
#define PLPA_TASKSET_H
|
||||
|
||||
#include <plpa.h>
|
||||
|
||||
/*
|
||||
* Function in flexer to set up the parser to read from a string
|
||||
* (vs. reading from a file)
|
||||
*/
|
||||
void parser_setup_string(char* str);
|
||||
|
||||
/*
|
||||
* Main bison parser.
|
||||
*/
|
||||
int token_parse(PLPA_NAME(cpu_set_t) *cpu_set);
|
||||
|
||||
/*
|
||||
* Main flex parser
|
||||
*/
|
||||
int yylex(void);
|
||||
|
||||
|
||||
#endif
|
26
opal/mca/paffinity/linux/plpa/src/plpa-taskset/run_tests.pl
Исполняемый файл
26
opal/mca/paffinity/linux/plpa/src/plpa-taskset/run_tests.pl
Исполняемый файл
@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
|
||||
open(FILE, "test_cases.txt") or die "Can't open test_cases.txt file";
|
||||
my $test_num = 1;
|
||||
while (<FILE>) {
|
||||
chomp;
|
||||
/(\S+)\s+(\S+)/m;
|
||||
my $in = $1;
|
||||
my $expected_out = $2;
|
||||
if ($in ne "") {
|
||||
my $stdout = `./plpa_taskset -tc $in`;
|
||||
chomp $stdout;
|
||||
$stdout =~ /(.+?)\n(.+)/;
|
||||
my $real_out = $2;
|
||||
print "Test $test_num: ";
|
||||
if ($real_out ne $expected_out) {
|
||||
print "FAILED\n In: $in\n Out: $real_out\n Expected: $expected_out\n";
|
||||
} else {
|
||||
print "PASSED\n";
|
||||
}
|
||||
++$test_num;
|
||||
}
|
||||
}
|
||||
close(FILE);
|
14
opal/mca/paffinity/linux/plpa/src/plpa-taskset/socket_tests
Обычный файл
14
opal/mca/paffinity/linux/plpa/src/plpa-taskset/socket_tests
Обычный файл
@ -0,0 +1,14 @@
|
||||
3@1
|
||||
1@all
|
||||
all@1
|
||||
all@2,all@3
|
||||
all@{2,3}
|
||||
{1,2}@{3,4,5}
|
||||
{0-2}@{0-2,5}
|
||||
all@all
|
||||
## not{0@0}
|
||||
not0@0
|
||||
0@not0
|
||||
{0-2}@not{1,2}
|
||||
##not{0@even,1@odd}
|
||||
not0@even,not1@odd
|
39
opal/mca/paffinity/linux/plpa/src/plpa-taskset/test_cases.txt
Обычный файл
39
opal/mca/paffinity/linux/plpa/src/plpa-taskset/test_cases.txt
Обычный файл
@ -0,0 +1,39 @@
|
||||
0 0
|
||||
2 2
|
||||
0-2 0-2
|
||||
0,2 0,2
|
||||
0-2,4 0-2,4
|
||||
0,2-4 0,2-4
|
||||
0,2,4 0,2,4
|
||||
0-2,4,6 0-2,4,6
|
||||
0-2,4-6 0-2,4-6
|
||||
0,2-4,6 0,2-4,6
|
||||
0,2,4-6 0,2,4-6
|
||||
0,2,4,6,8 0,2,4,6,8
|
||||
0-2,4,6,8 0-2,4,6,8
|
||||
0-2,4-6,8 0-2,4-6,8
|
||||
0-2,4,6-8 0-2,4,6-8
|
||||
0,2-4,6,8 0,2-4,6,8
|
||||
0,2-4,6-8 0,2-4,6-8
|
||||
0,2,4-6,8 0,2,4-6,8
|
||||
0,2,4,6-8 0,2,4,6-8
|
||||
0,1,2 0-2
|
||||
0-2,3 0-3
|
||||
0-2,3,4-5 0-5
|
||||
0-2,3,4-6 0-6
|
||||
0-4:1 0-4
|
||||
0-4:2 0,2,4
|
||||
0-4:3 0,3
|
||||
0-4:2,6 0,2,4,6
|
||||
0-4:1,5 0-5
|
||||
0-4:1,5,6 0-6
|
||||
0-4:2,6,8 0,2,4,6,8
|
||||
0-4:2,6,7,8 0,2,4,6-8
|
||||
0-4:2,6-8 0,2,4,6-8
|
||||
0-4:2,6-8:2 0,2,4,6,8
|
||||
0-4:2,6-10:2 0,2,4,6,8,10
|
||||
0-4:2,6-10:2,8 0,2,4,6,8,10
|
||||
0-4:2,6-10:2,9 0,2,4,6,8-10
|
||||
0-4:2,6-10:2,13 0,2,4,6,8,10,13
|
||||
0-4:2,6-10:2,13,15 0,2,4,6,8,10,13,15
|
||||
0-31 0-31
|
286
opal/mca/paffinity/linux/plpa/src/plpa-taskset/tokens.y
Обычный файл
286
opal/mca/paffinity/linux/plpa/src/plpa-taskset/tokens.y
Обычный файл
@ -0,0 +1,286 @@
|
||||
%{
|
||||
|
||||
#include "plpa.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "plpa-taskset.h"
|
||||
|
||||
|
||||
/*
|
||||
* Could this be done more efficiently? Absolutely.
|
||||
*
|
||||
* But this is neat, elegant, and easy to understand / maintain.
|
||||
* Performance is not an issue here.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Global functions
|
||||
*/
|
||||
int token_parse(PLPA_NAME(cpu_set_t) *cpu_set);
|
||||
void yyerror(char const *s);
|
||||
|
||||
/*
|
||||
* Local functions
|
||||
*/
|
||||
static void set_merge(PLPA_NAME(cpu_set_t) *out, PLPA_NAME(cpu_set_t) *a,
|
||||
PLPA_NAME(cpu_set_t) *b);
|
||||
static void set_copy(PLPA_NAME(cpu_set_t) *out, PLPA_NAME(cpu_set_t) *in);
|
||||
static void cpu_set(PLPA_NAME(cpu_set_t) *out, int pos);
|
||||
static void cpu_set_all(PLPA_NAME(cpu_set_t) *out);
|
||||
static void cpu_set_even(PLPA_NAME(cpu_set_t) *out);
|
||||
static void cpu_set_odd(PLPA_NAME(cpu_set_t) *out);
|
||||
static void cpu_set_range(PLPA_NAME(cpu_set_t) *out, int min, int max);
|
||||
static void cpu_compliment(PLPA_NAME(cpu_set_t) *out, PLPA_NAME(cpu_set_t) *in);
|
||||
static void sc_merge(PLPA_NAME(cpu_set_t) *out, PLPA_NAME(cpu_set_t) *cores,
|
||||
PLPA_NAME(cpu_set_t) *sockets);
|
||||
|
||||
/*
|
||||
* Local variables
|
||||
*/
|
||||
static int socket_list[PLPA_BITMASK_CPU_MAX];
|
||||
static PLPA_NAME(cpu_set_t) *return_value;
|
||||
%}
|
||||
|
||||
%union {
|
||||
PLPA_NAME(cpu_set_t) cpu_set;
|
||||
int number;
|
||||
}
|
||||
|
||||
%token <cpu_set> TOKENS_STRING_ALL
|
||||
%token <cpu_set> TOKENS_STRING_EVEN
|
||||
%token <cpu_set> TOKENS_STRING_ODD
|
||||
%token <cpu_set> TOKENS_STRING_NOT
|
||||
%token <number> TOKENS_NUMBER
|
||||
|
||||
%type <cpu_set> start
|
||||
%type <cpu_set> cpu_list
|
||||
%type <cpu_set> cpu_numbers
|
||||
%type <cpu_set> cpu_strings
|
||||
%type <cpu_set> sc_list
|
||||
%type <cpu_set> sc_expr
|
||||
%type <cpu_set> sc_item
|
||||
%type <cpu_set> sc_item_list
|
||||
%type <cpu_set> sc_strings
|
||||
|
||||
%% /* Grammar rules and actions follow. */
|
||||
|
||||
start: cpu_list
|
||||
{ set_copy(return_value, &$1); }
|
||||
| sc_list
|
||||
{ set_copy(return_value, &$1); }
|
||||
|
||||
cpu_list: cpu_strings
|
||||
{ set_copy(&$$, &$1); }
|
||||
| cpu_numbers
|
||||
{ set_copy(&$$, &$1); }
|
||||
|
||||
cpu_numbers: TOKENS_NUMBER
|
||||
{ cpu_set(&$$, $1); }
|
||||
| TOKENS_NUMBER '-' TOKENS_NUMBER
|
||||
{ cpu_set_range(&$$, $1, $3); }
|
||||
| cpu_list ',' TOKENS_NUMBER
|
||||
{ PLPA_NAME(cpu_set_t) temp; cpu_set(&temp, $3); set_merge(&$$, &$1, &temp); }
|
||||
| cpu_list ',' TOKENS_NUMBER '-' TOKENS_NUMBER
|
||||
{ PLPA_NAME(cpu_set_t) temp; cpu_set_range(&temp, $3, $5); set_merge(&$$, &$1, &temp); }
|
||||
|
||||
cpu_strings: TOKENS_STRING_ALL
|
||||
{ cpu_set_all(&$$); }
|
||||
| TOKENS_STRING_EVEN
|
||||
{ cpu_set_even(&$$); }
|
||||
| TOKENS_STRING_ODD
|
||||
{ cpu_set_odd(&$$); }
|
||||
|
||||
sc_list: sc_expr
|
||||
{ set_copy(&$$, &$1); }
|
||||
| sc_list ',' sc_expr
|
||||
{ set_merge(&$$, &$1, &$3); }
|
||||
|
||||
sc_expr: sc_item '@' sc_item
|
||||
{ sc_merge(&$$, &$1, &$3); }
|
||||
|
||||
sc_item: sc_strings
|
||||
{ set_copy(&$$, &$1); }
|
||||
| TOKENS_NUMBER
|
||||
{ cpu_set(&$$, $1); }
|
||||
| TOKENS_STRING_NOT TOKENS_NUMBER
|
||||
{ PLPA_NAME(cpu_set_t) temp; cpu_set(&temp, $2); cpu_compliment(&$$, &temp); }
|
||||
| TOKENS_STRING_NOT '{' sc_item_list '}'
|
||||
{ cpu_compliment(&$$, &$3); }
|
||||
| '{' sc_item_list '}'
|
||||
{ set_copy(&$$, &$2); }
|
||||
| '{' sc_strings '}'
|
||||
{ set_copy(&$$, &$2); }
|
||||
|
||||
sc_item_list: TOKENS_NUMBER
|
||||
{ cpu_set(&$$, $1); }
|
||||
| TOKENS_NUMBER '-' TOKENS_NUMBER
|
||||
{ cpu_set_range(&$$, $1, $3); }
|
||||
| sc_item_list ',' TOKENS_NUMBER
|
||||
{ PLPA_NAME(cpu_set_t) temp; cpu_set(&temp, $3); set_merge(&$$, &$1, &temp); }
|
||||
| sc_item_list ',' TOKENS_NUMBER '-' TOKENS_NUMBER
|
||||
{ PLPA_NAME(cpu_set_t) temp; cpu_set_range(&temp, $3, $5); set_merge(&$$, &$1, &temp); }
|
||||
|
||||
sc_strings: TOKENS_STRING_ALL
|
||||
{ cpu_set_all(&$$); }
|
||||
| TOKENS_STRING_EVEN
|
||||
{ cpu_set_even(&$$); }
|
||||
| TOKENS_STRING_ODD
|
||||
{ cpu_set_odd(&$$); }
|
||||
|
||||
%%
|
||||
|
||||
int token_parse(PLPA_NAME(cpu_set_t) *cpu_set)
|
||||
{
|
||||
int ret;
|
||||
|
||||
PLPA_CPU_ZERO(cpu_set);
|
||||
return_value = cpu_set;
|
||||
ret = yyparse();
|
||||
if (0 != ret) {
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void yyerror (char const *s)
|
||||
{
|
||||
fprintf(stderr, "ERROR: %s\n", s);
|
||||
}
|
||||
|
||||
static void set_merge(PLPA_NAME(cpu_set_t) *out, PLPA_NAME(cpu_set_t) *a,
|
||||
PLPA_NAME(cpu_set_t) *b)
|
||||
{
|
||||
int i;
|
||||
PLPA_CPU_ZERO(out);
|
||||
for (i = 0; i < PLPA_BITMASK_CPU_MAX; ++i) {
|
||||
if (PLPA_CPU_ISSET(i, a) || PLPA_CPU_ISSET(i, b)) {
|
||||
PLPA_CPU_SET(i, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void set_copy(PLPA_NAME(cpu_set_t) *out, PLPA_NAME(cpu_set_t) *in)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < PLPA_BITMASK_CPU_MAX; ++i) {
|
||||
if (PLPA_CPU_ISSET(i, in)) {
|
||||
PLPA_CPU_SET(i, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cpu_set(PLPA_NAME(cpu_set_t) *out, int pos)
|
||||
{
|
||||
PLPA_CPU_ZERO(out);
|
||||
if (pos < PLPA_BITMASK_CPU_MAX) {
|
||||
PLPA_CPU_SET(pos, out);
|
||||
}
|
||||
}
|
||||
|
||||
static void cpu_set_all(PLPA_NAME(cpu_set_t) *out)
|
||||
{
|
||||
int i;
|
||||
PLPA_CPU_ZERO(out);
|
||||
for (i = 0; i < PLPA_BITMASK_CPU_MAX; ++i) {
|
||||
PLPA_CPU_SET(i, out);
|
||||
}
|
||||
}
|
||||
|
||||
static void cpu_set_even(PLPA_NAME(cpu_set_t) *out)
|
||||
{
|
||||
int i;
|
||||
PLPA_CPU_ZERO(out);
|
||||
for (i = 0; i < PLPA_BITMASK_CPU_MAX; i += 2) {
|
||||
PLPA_CPU_SET(i, out);
|
||||
}
|
||||
}
|
||||
|
||||
static void cpu_set_odd(PLPA_NAME(cpu_set_t) *out)
|
||||
{
|
||||
int i;
|
||||
PLPA_CPU_ZERO(out);
|
||||
for (i = 1; i < PLPA_BITMASK_CPU_MAX; i += 2) {
|
||||
PLPA_CPU_SET(i, out);
|
||||
}
|
||||
}
|
||||
|
||||
static void cpu_set_range(PLPA_NAME(cpu_set_t) *out, int min, int max)
|
||||
{
|
||||
int i;
|
||||
PLPA_CPU_ZERO(out);
|
||||
for (i = min; i < max && i < PLPA_BITMASK_CPU_MAX; ++i) {
|
||||
PLPA_CPU_SET(i, out);
|
||||
}
|
||||
}
|
||||
|
||||
static void cpu_compliment(PLPA_NAME(cpu_set_t) *out, PLPA_NAME(cpu_set_t) *in)
|
||||
{
|
||||
int i;
|
||||
PLPA_CPU_ZERO(out);
|
||||
for (i = 0; i < PLPA_BITMASK_CPU_MAX; ++i) {
|
||||
if (!PLPA_CPU_ISSET(i, in)) {
|
||||
PLPA_CPU_SET(i, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void sc_merge(PLPA_NAME(cpu_set_t) *out, PLPA_NAME(cpu_set_t) *cores,
|
||||
PLPA_NAME(cpu_set_t) *sockets)
|
||||
{
|
||||
int i, core, socket, id, have_topo;
|
||||
|
||||
/* This is just about the only function that's tricky. Take a
|
||||
bitmask representing all the cores and a bitmask representing
|
||||
all the sockets and merge them into a single cpu_set_t
|
||||
representing real CPU id's using the plpa_map_to_processor_id()
|
||||
function. But error out if this system doesn't support the
|
||||
topology information (because we won't be able to do the
|
||||
mapping).
|
||||
*/
|
||||
|
||||
PLPA_CPU_ZERO(out);
|
||||
if (0 != PLPA_NAME(have_topology_information)(&have_topo) ||
|
||||
0 == have_topo) {
|
||||
fprintf(stderr, "ERROR: This system does not support topology information\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Even though I officially don't care about performance here,
|
||||
intentionally putting in a loop that is
|
||||
O(PLPA_BITMASK_CPU_MAX^2) gives me pause. :-) So scan through
|
||||
the sockets array once and generate a list of the set bits in a
|
||||
much shorter array. */
|
||||
|
||||
for (i = socket = 0; socket < PLPA_BITMASK_CPU_MAX; ++socket) {
|
||||
if (PLPA_CPU_ISSET(socket, sockets)) {
|
||||
socket_list[i++] = socket;
|
||||
}
|
||||
}
|
||||
|
||||
/* Bozo case: if there were no sockets set, we're done */
|
||||
|
||||
if (0 == i) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise, do the loop to create the mapping of sockets and
|
||||
cores, seting the final bitmask. Yes, this is a double loop,
|
||||
but hopefully it's much smaller than
|
||||
PLPA_BITMASK_CPU_MAX^2. */
|
||||
|
||||
for (core = 0; core < PLPA_BITMASK_CPU_MAX; ++core) {
|
||||
if (PLPA_CPU_ISSET(core, cores)) {
|
||||
for (socket = 0; socket < i; ++socket) {
|
||||
if (0 != PLPA_NAME(map_to_processor_id)(socket_list[socket],
|
||||
core, &id)) {
|
||||
fprintf(stderr, "ERROR: Failed to map %d@%d to processor ID\n",
|
||||
core, socket);
|
||||
exit(1);
|
||||
}
|
||||
printf("Setting id: %d\n", id);
|
||||
PLPA_CPU_SET(id, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@
|
||||
* University of Stuttgart. All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
@ -26,7 +27,7 @@
|
||||
* This is an extremely simple framework that is used to support the
|
||||
* OS-specific API for placement of processes on processors. It does
|
||||
* *not* decide scheduling issues -- it is simply for assigning the
|
||||
* current process it to a specific processor. As such, the
|
||||
* current process it to a specific processor set. As such, the
|
||||
* components are likely to be extremely short/simple -- there will
|
||||
* likely be one component for each OS/API that we support (e.g.,
|
||||
* Linux, IRIX, etc.). As a direct consequence, there will likely
|
||||
@ -46,14 +47,11 @@
|
||||
* priority (for the unlikely event where there are multiple
|
||||
* components available on a given platform).
|
||||
*
|
||||
* The module has four functions:
|
||||
* The module has three functions:
|
||||
*
|
||||
* - module_init: initialze the module
|
||||
* - get_num_processors: return the maximum number N that can be used
|
||||
* in the set() module function (i.e., the number of available
|
||||
* processors)
|
||||
* - set: set this process's affinity to a specific processor
|
||||
* - get: get this process's processor affinity
|
||||
* - set: set this process's affinity to a specific processor set
|
||||
* - get: get this process's processor affinity set
|
||||
*/
|
||||
|
||||
#ifndef OPAL_PAFFINITY_H
|
||||
@ -64,6 +62,81 @@
|
||||
#include "opal/mca/mca.h"
|
||||
#include "opal/mca/base/base.h"
|
||||
|
||||
/**
|
||||
* Buffer type for paffinity processor masks.
|
||||
* Copied almost directly from PLPA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \internal
|
||||
* Internal type used for the underlying bitmask unit
|
||||
*/
|
||||
typedef unsigned long int opal_paffinity_base_bitmask_t;
|
||||
|
||||
/**
|
||||
* \internal
|
||||
* Number of bits in opal_paffinity_base_bitmask_t
|
||||
*/
|
||||
#define OPAL_PAFFINITY_BITMASK_T_NUM_BITS (sizeof(opal_paffinity_base_bitmask_t) * 8)
|
||||
/**
|
||||
* \internal
|
||||
* How many bits we want
|
||||
*/
|
||||
#define OPAL_PAFFINITY_BITMASK_CPU_MAX 1024
|
||||
/**
|
||||
* \internal
|
||||
* How many opal_paffinity_base_bitmask_t's we need
|
||||
*/
|
||||
#define OPAL_PAFFINITY_BITMASK_NUM_ELEMENTS (OPAL_PAFFINITY_BITMASK_CPU_MAX / OPAL_PAFFINITY_BITMASK_T_NUM_BITS)
|
||||
|
||||
/**
|
||||
* Public processor bitmask type
|
||||
*/
|
||||
typedef struct opal_paffinity_base_cpu_set_t {
|
||||
opal_paffinity_base_bitmask_t bitmask[OPAL_PAFFINITY_BITMASK_NUM_ELEMENTS];
|
||||
} opal_paffinity_base_cpu_set_t;
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/**
|
||||
* \internal
|
||||
* Internal macro for identifying the byte in a bitmask array
|
||||
*/
|
||||
#define OPAL_PAFFINITY_CPU_BYTE(num) ((num) / OPAL_PAFFINITY_BITMASK_T_NUM_BITS)
|
||||
|
||||
/**
|
||||
* \internal
|
||||
* Internal macro for identifying the bit in a bitmask array
|
||||
*/
|
||||
#define OPAL_PAFFINITY_CPU_BIT(num) ((num) % OPAL_PAFFINITY_BITMASK_T_NUM_BITS)
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/**
|
||||
* Public macro to zero out a OPAL_PAFFINITY cpu set
|
||||
*/
|
||||
#define OPAL_PAFFINITY_CPU_ZERO(cpuset) \
|
||||
memset(&(cpuset), 0, sizeof(opal_paffinity_base_cpu_set_t))
|
||||
|
||||
/**
|
||||
* Public macro to set a bit in a OPAL_PAFFINITY cpu set
|
||||
*/
|
||||
#define OPAL_PAFFINITY_CPU_SET(num, cpuset) \
|
||||
(cpuset).bitmask[OPAL_PAFFINITY_CPU_BYTE(num)] |= ((opal_paffinity_base_bitmask_t) 1 << OPAL_PAFFINITY_CPU_BIT(num))
|
||||
|
||||
/**
|
||||
* Public macro to clear a bit in a OPAL_PAFFINITY cpu set
|
||||
*/
|
||||
#define OPAL_PAFFINITY_CPU_CLR(num, cpuset) \
|
||||
(cpuset).bitmask[OPAL_PAFFINITY_CPU_BYTE(num)] &= ~((opal_paffinity_base_bitmask_t) 1 << OPAL_PAFFINITY_CPU_BIT(num))
|
||||
|
||||
/**
|
||||
* Public macro to test if a bit is set in a OPAL_PAFFINITY cpu set
|
||||
*/
|
||||
#define OPAL_PAFFINITY_CPU_ISSET(num, cpuset) \
|
||||
(0 != (((cpuset).bitmask[OPAL_PAFFINITY_CPU_BYTE(num)]) & ((opal_paffinity_base_bitmask_t) 1 << OPAL_PAFFINITY_CPU_BIT(num))))
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/**
|
||||
* Query function for paffinity components. Simply returns a priority
|
||||
@ -71,70 +144,58 @@
|
||||
* only one component will be available per platform, but it's
|
||||
* possible that there could be more than one available).
|
||||
*/
|
||||
typedef const struct opal_paffinity_base_module_1_0_0_t *
|
||||
(*opal_paffinity_base_component_query_1_0_0_fn_t)
|
||||
typedef const struct opal_paffinity_base_module_1_1_0_t *
|
||||
(*opal_paffinity_base_component_query_1_1_0_fn_t)
|
||||
(int *priority);
|
||||
|
||||
|
||||
/**
|
||||
* Module initialization function. Should return OPAL_SUCCESS.
|
||||
*/
|
||||
typedef int (*opal_paffinity_base_module_init_1_0_0_fn_t)(void);
|
||||
|
||||
typedef int (*opal_paffinity_base_module_init_1_1_0_fn_t)(void);
|
||||
|
||||
/**
|
||||
* Module function to query the physical number of processors (which
|
||||
* may be different than what schedulers have allocated to us).
|
||||
* Module function to set this process' affinity to a specific set of
|
||||
* [virtual] CPUs.
|
||||
*/
|
||||
typedef int (*opal_paffinity_base_module_get_num_processors_t)(int *nprocs);
|
||||
typedef int (*opal_paffinity_base_module_set_fn_t)(opal_paffinity_base_cpu_set_t cpumask);
|
||||
|
||||
|
||||
/**
|
||||
* Module function to set this process' affinity to a specific
|
||||
* [virtual] CPU.
|
||||
*/
|
||||
typedef int (*opal_paffinity_base_module_set_fn_t)(int cpuid);
|
||||
|
||||
|
||||
/**
|
||||
* Module function to get this process' affinity to a specific
|
||||
* [virtual] CPU. Returns OPAL_ERR_NOT_FOUND if
|
||||
* Module function to get this process' affinity to a specific set of
|
||||
* [virtual] CPUs. Returns OPAL_ERR_NOT_FOUND if
|
||||
* opal_paffinity_base_module_set_fn_t() was not previously invoked in
|
||||
* this process.
|
||||
*/
|
||||
typedef int (*opal_paffinity_base_module_get_fn_t)(int *cpuid);
|
||||
typedef int (*opal_paffinity_base_module_get_fn_t)(opal_paffinity_base_cpu_set_t *cpumask);
|
||||
|
||||
|
||||
/**
|
||||
* Structure for paffinity v1.0.0 components.
|
||||
* Chained to MCA v1.0.0
|
||||
* Structure for paffinity v1.1.0 components.
|
||||
* Chained to MCA v1.1.0
|
||||
*/
|
||||
struct opal_paffinity_base_component_1_0_0_t {
|
||||
struct opal_paffinity_base_component_1_1_0_t {
|
||||
/** MCA base component */
|
||||
mca_base_component_t paffinityc_version;
|
||||
/** MCA base data */
|
||||
mca_base_component_data_1_0_0_t paffinityc_data;
|
||||
|
||||
/** Component query function */
|
||||
opal_paffinity_base_component_query_1_0_0_fn_t paffinityc_query;
|
||||
opal_paffinity_base_component_query_1_1_0_fn_t paffinityc_query;
|
||||
};
|
||||
/**
|
||||
* Convenience typedef
|
||||
*/
|
||||
typedef struct opal_paffinity_base_component_1_0_0_t opal_paffinity_base_component_1_0_0_t;
|
||||
typedef struct opal_paffinity_base_component_1_1_0_t opal_paffinity_base_component_1_1_0_t;
|
||||
|
||||
|
||||
/**
|
||||
* Structure for paffinity v1.0.0 modules
|
||||
*/
|
||||
struct opal_paffinity_base_module_1_0_0_t {
|
||||
struct opal_paffinity_base_module_1_1_0_t {
|
||||
|
||||
/** Module initialization function */
|
||||
opal_paffinity_base_module_init_1_0_0_fn_t paff_module_init;
|
||||
|
||||
/** Query the number of physical processors */
|
||||
opal_paffinity_base_module_get_num_processors_t
|
||||
paff_module_get_num_processors;
|
||||
opal_paffinity_base_module_init_1_1_0_fn_t paff_module_init;
|
||||
|
||||
/** Set this process' affinity */
|
||||
opal_paffinity_base_module_set_fn_t paff_module_set;
|
||||
@ -145,14 +206,14 @@ struct opal_paffinity_base_module_1_0_0_t {
|
||||
/**
|
||||
* Convenience typedef
|
||||
*/
|
||||
typedef struct opal_paffinity_base_module_1_0_0_t opal_paffinity_base_module_1_0_0_t;
|
||||
typedef struct opal_paffinity_base_module_1_1_0_t opal_paffinity_base_module_1_1_0_t;
|
||||
|
||||
|
||||
/*
|
||||
* Macro for use in components that are of type paffinity v1.0.0
|
||||
* Macro for use in components that are of type paffinity v1.1.0
|
||||
*/
|
||||
#define OPAL_PAFFINITY_BASE_VERSION_1_0_0 \
|
||||
/* paffinity v1.0 is chained to MCA v1.0 */ \
|
||||
#define OPAL_PAFFINITY_BASE_VERSION_1_1_0 \
|
||||
/* paffinity v1.1 is chained to MCA v1.0 */ \
|
||||
MCA_BASE_VERSION_1_0_0, \
|
||||
/* paffinity v1.0 */ \
|
||||
"paffinity", 1, 0, 0
|
||||
|
@ -10,6 +10,7 @@
|
||||
# University of Stuttgart. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright (c) 2007 Cisco, Inc. All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
@ -20,8 +21,26 @@
|
||||
# MCA_paffinity_solaris_CONFIG([action-if-found], [action-if-not-found])
|
||||
# -----------------------------------------------------------
|
||||
AC_DEFUN([MCA_paffinity_solaris_CONFIG],[
|
||||
# check for processor_bind()
|
||||
AC_CHECK_FUNC([processor_bind],
|
||||
[$1],
|
||||
[$2])
|
||||
#check to see if we have <sys/pset.h>
|
||||
AC_CHECK_HEADER([sys/pset.h], [happy=yes], [happy=no])
|
||||
|
||||
if test "$happy" = "yes"; then
|
||||
# check for pset_bind()
|
||||
AC_CHECK_FUNC([pset_bind],[happy=yes],[happy=no])
|
||||
fi
|
||||
|
||||
if test "$happy" = "yes"; then
|
||||
# check for whether header has PS_MYID defined
|
||||
AC_MSG_CHECKING([if PS_MYID is defined])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/pset.h>]], [[int i = PS_MYID;]])],
|
||||
[happy=yes],[happy=no])
|
||||
AC_MSG_RESULT([$happy ])
|
||||
fi
|
||||
|
||||
if test "$happy" = "yes"; then
|
||||
$1
|
||||
else
|
||||
$2
|
||||
fi
|
||||
])dnl
|
||||
|
||||
|
@ -9,6 +9,8 @@
|
||||
* University of Stuttgart. All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
|
||||
*
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
@ -24,6 +26,7 @@
|
||||
#include <sys/processor.h>
|
||||
#include <sys/procset.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/pset.h>
|
||||
|
||||
#include "opal/constants.h"
|
||||
#include "opal/mca/base/mca_base_param.h"
|
||||
@ -31,15 +34,13 @@
|
||||
#include "opal/mca/paffinity/base/base.h"
|
||||
#include "paffinity_solaris.h"
|
||||
|
||||
|
||||
/*
|
||||
* Local functions
|
||||
*/
|
||||
static int solaris_module_init(void);
|
||||
static int solaris_module_get_num_procs(int *num_procs);
|
||||
static int solaris_module_set(int id);
|
||||
static int solaris_module_get(int *id);
|
||||
|
||||
static int solaris_module_set(opal_paffinity_base_cpu_set_t cpuset);
|
||||
static int solaris_module_get(opal_paffinity_base_cpu_set_t *cpuset);
|
||||
static int solaris_module_finalize(void);
|
||||
/*
|
||||
* Solaris paffinity module
|
||||
*/
|
||||
@ -51,9 +52,9 @@ static const opal_paffinity_base_module_1_0_0_t module = {
|
||||
|
||||
/* Module function pointers */
|
||||
|
||||
solaris_module_get_num_procs,
|
||||
solaris_module_set,
|
||||
solaris_module_get
|
||||
solaris_module_get,
|
||||
solaris_module_finalize
|
||||
};
|
||||
|
||||
|
||||
@ -68,37 +69,111 @@ opal_paffinity_solaris_component_query(int *query)
|
||||
return &module;
|
||||
}
|
||||
|
||||
/*
|
||||
we are commenting out code in the solaris section - it is not clear
|
||||
from man pages exactly what we want. In particular the following global
|
||||
is not good programming practice, but it seems like it may be needed to
|
||||
be able to have a persistent pset under solaris
|
||||
|
||||
static psetid_t opal_pset;
|
||||
*/
|
||||
|
||||
static int solaris_module_init(void)
|
||||
{
|
||||
/* Nothing to do */
|
||||
int ierr;
|
||||
|
||||
/* We need to set up a processor set
|
||||
* Actual setting/getting of processors will use pset_assign calls
|
||||
* A failure here will return an error ( one likely reason for failure
|
||||
* is insufficient privilege to create a pset) */
|
||||
|
||||
/* ierr = pset_create(&opal_pset);
|
||||
if(0 == ierr) {
|
||||
return OPAL_SUCCESS;
|
||||
} else {
|
||||
return OPAL_ERR_IN_ERRNO;
|
||||
} */
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
Solaris_module_set will need to assign processors in the mask to a pset. This
|
||||
pset needs to be created (and persist until solaris_module_finalize
|
||||
is called - hence the global variable above).
|
||||
|
||||
static int solaris_module_get_num_procs(int *num_procs)
|
||||
there is some ambiguity in the available documentation as to
|
||||
the order in which pset_bind and pset_assign calls must be made.
|
||||
|
||||
My reading is that the LWP must be bound to a pset (even an empty
|
||||
pset) before processors can be assigned. This doesn't make a lot of
|
||||
sense though, and it may be that the pset_assign calls need to be done
|
||||
prior to the pset_bind call.
|
||||
|
||||
Documentation is located at http://docs.sun.com/app/docs/doc/819-2241/6n4huc7m7?a=view
|
||||
*/
|
||||
|
||||
static int solaris_module_set(opal_paffinity_base_cpu_set_t mask)
|
||||
{
|
||||
*num_procs = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int solaris_module_set(int id)
|
||||
{
|
||||
if (0 != processor_bind(P_PID, P_MYID, (processorid_t) id, NULL)) {
|
||||
/*
|
||||
int loopindex;
|
||||
psetid_t temp_pset;
|
||||
*/
|
||||
/* Bind process to opal_pset - have to bind to a pset before
|
||||
* assigning processors */
|
||||
/*
|
||||
if (0 != pset_bind(PS_QUERY, P_PID, P_MYID, &temp_pset)) {
|
||||
return OPAL_ERR_IN_ERRNO;
|
||||
}
|
||||
*/
|
||||
/* Assign all processors in mask to opal_pset */
|
||||
/*
|
||||
for(loopindex=0;loopindex< sizeof(mask); loopindex++) {
|
||||
if(OPAL_PAFFINITY_CPU_ISSET(loopindex,mask)) {
|
||||
pset_assign(PS_MYID,(processor_t) loopindex, NULL);
|
||||
|
||||
}
|
||||
} */
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
Solaris_module_get is a bit easier - we do a pset_info call and then loop through
|
||||
the array of processor ids and set them in the mask structure
|
||||
|
||||
static int solaris_module_get(int *id)
|
||||
*/
|
||||
|
||||
static int solaris_module_get(opal_paffinity_base_cpu_set_t *mask)
|
||||
{
|
||||
processorid_t obind;
|
||||
if (0 != processor_bind(P_PID, P_MYID, PBIND_QUERY, &obind)) {
|
||||
/*
|
||||
processorid_t solar_cpulist;
|
||||
uint_t solar_numcpus;
|
||||
int loopindex, type; */
|
||||
/*
|
||||
* pset_info returns an array of processor_t elements for the
|
||||
* processors that are in this pset. There are solar_numcpus in the
|
||||
* array
|
||||
*/
|
||||
/* if (0 != pset_info(temp_pset, &type, &solar_numcpus, &solar_cpulist)) {
|
||||
return OPAL_ERR_IN_ERRNO;
|
||||
}
|
||||
*id = (int) obind;
|
||||
if (PS_NONE == type) { */
|
||||
/* do the right thing */
|
||||
/* }
|
||||
for (loopindex = 0; loopindex < solar_numcpus; loopindex++) {
|
||||
OPAL_PAFFINITY_CPU_SET((int) solar_cpulist[loopindex],*mask);
|
||||
} */
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
static int solaris_module_finalize(void)
|
||||
{
|
||||
/*
|
||||
int ierr;
|
||||
ierr = pset_destroy(opal_pset);
|
||||
if(0 == ierr) {
|
||||
return OPAL_SUCCESS;
|
||||
} else {
|
||||
return OPAL_ERR_IN_ERRNO;
|
||||
} */
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user