Commit ed089ed8 authored by David Goodell's avatar David Goodell
Browse files

[svn-r10558] use MPI_Count in MPI_Status

This commit actually does a few things to the status object:

(1) `int count` becomes `MPI_Count count`;
(2) `count` & `cancelled` have been reordered after the "public"
fields (e.g., MPI_TAG) to ensure that direct access from Fortran is
not somehow broken by the (potentially) non-INTEGER count field;
(3) and a new future-proofing field, `abi_slush_fund`, has been added to
attempt to allow us to add fields to the status object in the future
without having to break ABI compatibility.

There's still too much duplication of the status object's contents/layout
in multiple pieces of the code, but I don't see a reasonable way to fix
this in the near term.

Warning: large count breaks the experimental Fortran binding code
generated for handling the "sizeof(int)!=sizeof(MPI_Fint)" case.

Reviewed by balaji@.
parent 088c4106
......@@ -3748,61 +3748,6 @@ dnl len_doublecplx=$hexlen
fi
fi
#
# Set size of MPI_Status. We may need sizeof_int here as well
#
#
# The size of MPI_Status is needed for the Fortran interface.
# This is not quite right unless the device setup script, executed above,
# sets the EXTRA_STATUS_DECL that will be used in defining a status.
# The default size assumes that there are 5 ints
AC_CACHE_CHECK([for size of MPI_Status],pac_cv_sizeof_mpi_status,[
rm -f pac_mpi_status.h
cat > pac_mpi_status.h <<_EOF
typedef struct {
int count;
int cancelled;
int MPI_SOURCE;
int MPI_TAG;
int MPI_ERROR;
$EXTRA_STATUS_DECL
} MPI_Status;
_EOF
dnl another alternative is to use AC_CHECK_SIZEOF as follows:
dnl AC_CHECK_SIZEOF([MPI_Status],[], [#include "pac_status.h"])
dnl But AC_CHECK_SIZEOF has its own AC_MSG_CHECKING, so can't use
dnl AC_CACHE_CHECK, so use AC_COMPUTE_INT here.
default_status_size=`expr 5 \* $ac_cv_sizeof_int`
AC_COMPUTE_INT([pac_cv_sizeof_mpi_status],
[sizeof(MPI_Status)],
[#include "pac_mpi_status.h"],
[pac_cv_sizeof_mpi_status=$default_status_size])
rm -f pac_mpi_status.h
])
SIZEOF_MPI_STATUS=$pac_cv_sizeof_mpi_status
export SIZEOF_MPI_STATUS
AC_SUBST(SIZEOF_MPI_STATUS)
if test -z "$MPI_STATUS_SIZE" ; then
if test -n "$SIZEOF_MPI_STATUS" ; then
# compute from the C sizeof
MPI_STATUS_SIZE=`expr $SIZEOF_MPI_STATUS / $ac_cv_sizeof_int`
if test "$MPI_STATUS_SIZE" = "0" ; then
AC_MSG_WARN([Could not compute the size of MPI_Status])
MPI_STATUS_SIZE=5
fi
else
AC_MSG_WARN([MPI_STATUS_SIZE was not defined!])
# The default size is 5. See mpi.h.in
MPI_STATUS_SIZE=5
fi
fi
AC_SUBST(MPI_STATUS_SIZE)
MPIF_STATUS_SIZE=$MPI_STATUS_SIZE
AC_DEFINE_UNQUOTED(MPIF_STATUS_SIZE,$MPIF_STATUS_SIZE,[Size of an MPI_STATUS, in Fortran, in Fortran integers])
# We must convert all hex values to decimal (!).
# This is for the C types so they are also available in Fortran
for var in CHAR SIGNED_CHAR UNSIGNED_CHAR WCHAR SHORT \
......@@ -5563,6 +5508,76 @@ AC_DEFINE_UNQUOTED([MPIR_COUNT_MAX],[$MPIR_COUNT_MAX],[limits.h _MAX constant fo
# ----------------------------------------------------------------------------
#
# Set size of MPI_Status. Must come after MPI_Count determination.
#
#
# The size of MPI_Status is needed for the Fortran interface.
# This is not quite right unless the device prereq macro, expanded above,
# sets the EXTRA_STATUS_DECL that will be used in defining a status.
#
# WARNING!!! this is a spot where we duplicate code from mpi.h.in and it *must*
# be kept in sync in order to make a proper computation
AC_CACHE_CHECK([for size of MPI_Status],[pac_cv_sizeof_mpi_status],[
dnl "double-quote" (in m4), otherwise you end up with a heinous bug because of
dnl the array subscripting below
[
rm -f pac_mpi_status.h
cat > pac_mpi_status.h <<_EOF
typedef struct {
int MPI_SOURCE;
int MPI_TAG;
int MPI_ERROR;
$MPI_COUNT count;
int cancelled;
int abi_slush_fund[2];
$EXTRA_STATUS_DECL
} MPI_Status;
_EOF
]
dnl just compute it, since a 1s-complement or sign-and-magnitude machine is
dnl *highly* unlikely. Users will report the error if it is ever dnl
dnl encountered, which will be safer than attempting some never-tested
dnl default fallback.
AC_COMPUTE_INT([pac_cv_sizeof_mpi_status],
[sizeof(MPI_Status)],
[#include "pac_mpi_status.h"],
[AC_MSG_ERROR([unable to compute status size, are you compiling on a non-2s-complement host?])])
rm -f pac_mpi_status.h
])
SIZEOF_MPI_STATUS=$pac_cv_sizeof_mpi_status
export SIZEOF_MPI_STATUS
AC_SUBST([SIZEOF_MPI_STATUS])
if test -z "$MPI_STATUS_SIZE" ; then
if test -n "$SIZEOF_MPI_STATUS" ; then
# compute from the C sizeof
# FIXME shouldn't these calculations be based on the size of a Fortran
# 'INTEGER' rather than a C 'int'?
AS_VAR_ARITH([MPI_STATUS_SIZE],[$SIZEOF_MPI_STATUS / $ac_cv_sizeof_int])
if test "$MPI_STATUS_SIZE" = "0" ; then
AC_MSG_ERROR([Could not compute the size of MPI_Status])
fi
# sanity: otherwise we have a problem in Fortran where we must implement
# MPI_STATUS as an array of INTEGERs with MPI_STATUS_SIZE elements
AS_VAR_ARITH([status_int_rem],[$SIZEOF_MPI_STATUS '%' $ac_cv_sizeof_int])
AS_IF([test "$status_int_rem" -gt 0],
[AC_MSG_ERROR([status size does not divide evenly by the integer size])])
AS_UNSET([status_int_rem])
else
AC_MSG_ERROR([MPI_STATUS_SIZE was not defined!])
fi
fi
AC_SUBST([MPI_STATUS_SIZE])
MPIF_STATUS_SIZE=$MPI_STATUS_SIZE
AC_DEFINE_UNQUOTED([MPIF_STATUS_SIZE],[$MPIF_STATUS_SIZE],[Size of an MPI_STATUS, in Fortran, in Fortran integers])
# ----------------------------------------------------------------------------
dnl Extra status information, from device subsystem, to be included in the
dnl declaration of MPI_Status in mpi.h.in
AC_SUBST(EXTRA_STATUS_DECL)
......
......@@ -3591,7 +3591,7 @@ if ($write_mpif) {
# FIXME: The offsets for the status elements are hardwired. If they
# change in mpi.h.in, they need to change here as well.
print MPIFFD " INTEGER MPI_SOURCE, MPI_TAG, MPI_ERROR\n";
print MPIFFD " PARAMETER (MPI_SOURCE=3,MPI_TAG=4,MPI_ERROR=5)\n";
print MPIFFD " PARAMETER (MPI_SOURCE=1,MPI_TAG=2,MPI_ERROR=3)\n";
print MPIFFD " INTEGER MPI_STATUS_SIZE\n";
print MPIFFD " PARAMETER (MPI_STATUS_SIZE=\@MPI_STATUS_SIZE\@)\n";
# Temporary until configure handles these. Define as arrays to keep
......@@ -4378,11 +4378,13 @@ print $OUTFD "\
#ifdef HAVE_FINT_IS_INT
*c_status = *(MPI_Status *) f_status;
#else
c_status->count = f_status\[0\];
c_status->cancelled = f_status\[1\];
c_status->MPI_SOURCE = f_status\[2\];
c_status->MPI_TAG = f_status\[3\];
c_status->MPI_ERROR = f_status\[4\];
#error this code is broken because of the new MPI_Count type
c_status->MPI_SOURCE = f_status\[0\];
c_status->MPI_TAG = f_status\[1\];
c_status->MPI_ERROR = f_status\[2\];
c_status->count = f_status\[3\];
c_status->cancelled = f_status\[4\];
/* no need to copy abi_slush_fund field */
#endif\n";
}
else {
......@@ -4451,13 +4453,13 @@ int MPI_Status_c2f( const MPI_Status *c_status, MPI_Fint *f_status )
#ifdef HAVE_FINT_IS_INT
*(MPI_Status *)f_status = *c_status;
#else
f_status\[0\] = c_status->count;
f_status\[1\] = c_status->cancelled;
f_status\[2\] = c_status->MPI_SOURCE;
f_status\[3\] = c_status->MPI_TAG;
f_status\[4\] = c_status->MPI_ERROR;
#error this code is broken because of the new MPI_Count type
f_status\[0\] = c_status->MPI_SOURCE;
f_status\[1\] = c_status->MPI_TAG;
f_status\[2\] = c_status->MPI_ERROR;
f_status\[3\] = c_status->count;
f_status\[4\] = c_status->cancelled;
#endif\n";
# printf( \"c_status = %d, %d, %d\\n\", c_status->MPI_SOURCE, c_status->MPI_TAG, c_status->MPI_ERROR );
}
else {
print $OUTFD " *(MPI_Status *)f_status = *c_status;\n";
......
......@@ -642,11 +642,15 @@ $PRIVATEVAR = "";
#
#$BINDACCESS = ", BIND(C)";
#$BINDDEF ="";
print MPIFD " TYPE$BINDACCESS :: MPI_Status
print MPIFD <<EOT;
TYPE$BINDACCESS :: MPI_Status
$BINDDEF
INTEGER$PRIVATEVAR :: count, cancelled
INTEGER$PUBLICVAR :: MPI_SOURCE, MPI_TAG, MPI_ERROR
END TYPE MPI_Status\n";
INTEGER$PRIVATEVAR(KIND=MPI_COUNT_KIND) :: count
INTEGER$PRIVATEVAR :: cancelled
INTEGER$PRIVATEVAR(2) :: abi_slush_fund
END TYPE MPI_Status
EOT
%handles = ( 'comm' => 'Comm', 'datatype' => 'Datatype',
'group' => 'Group', 'win' => 'Win',
......
......@@ -523,11 +523,12 @@ static const MPI_Datatype mpich_mpi_offset MPICH_ATTR_TYPE_TAG(MPI_Offset) = MPI
/* The order of these elements must match that in mpif.h */
typedef struct MPI_Status {
int count;
int cancelled;
int MPI_SOURCE;
int MPI_TAG;
int MPI_ERROR;
MPI_Count count;
int cancelled;
int abi_slush_fund[2];
@EXTRA_STATUS_DECL@
} MPI_Status;
......
......@@ -429,6 +429,9 @@ int MPIR_Init_thread(int * argc, char ***argv, int required, int * provided)
/* Assert: tag_ub is at least the minimum asked for in the MPI spec */
MPIU_Assert( MPIR_Process.attrs.tag_ub >= 32767 );
/* very nasty bugs will occur if this does not hold */
MPIU_Assert(sizeof(MPI_Status) == MPIF_STATUS_SIZE*sizeof(MPI_Fint));
/* Capture the level of thread support provided */
MPIR_ThreadInfo.thread_provided = thread_provided;
if (provided) *provided = thread_provided;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment