1
1
openmpi/ompi/mpi/f77/constants.h
Rainer Keller 9b91ac2fa3 Thanks to Daniel Spangberg for noticing this problem in the f77
interface:
 - Fix the handling of MPI_BOTTOM in various places
   Update of r15030
 - While being at it, handle MPI_IN_PLACE in the same way.
   Convert OMPI_ADDR -> OMPI_F2C_BOTTOM
   Convert OMPI_IN_PLACE -> OMPI_F2C_IN_PLACE
   and have them converted before the actual call.
 - Approved by George and tested with icc and simple f77 mpi-program and
   with program by Daniel.

This commit was SVN r15129.

The following SVN revision numbers were found above:
  r15030 --> open-mpi/ompi@15f9e58c68
2007-06-18 22:33:54 +00:00

222 строки
9.7 KiB
C

/*
* 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 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#ifndef OMPI_F77_CONSTANTS_H
#define OMPI_F77_CONSTANTS_H
/*
* Several variables are used to link against MPI F77 constants which
* correspond to addresses, e.g. MPI_BOTTOM, and are implemented via
* common blocks.
*
* We use common blocks so that in the C wrapper functions, we can
* compare the address that comes in against known addresses (e.g., if
* the "status" argument in MPI_RECV is the address of the common
* block for the fortran equivalent of MPI_STATUS_IGNORE, then we know
* to pass the C MPI_STATUS_IGNORE to the C MPI_Recv function). As
* such, we never look at the *value* of these variables (indeed,
* they're never actually initialized), but instead only ever look at
* the *address* of these variables.
*
* As such, it is not strictly necessary that the size and type of our
* C variables matches that of the common Fortran block variables.
* However, good programming form says that we should match, so we do.
*
* Note, however, that the alignments of the Fortran common block and
* the C variable may not match (e.g., Intel 9.0 compilers on 64 bit
* platforms will put the alignment of a double on 4 bytes, but put
* the alignment of all common blocks on 16 bytes). This only matters
* (to some compilers!), however, if you initialize the C variable in
* the global scope. If the C global instantiation is not
* initialized, the compiler/linker seems to "figure it all out" and
* make the alignments match.
*
* Since we made the fundamental decision to support all 4 common
* fortran compiler symbol conventions within the same library for
* those compilers who support weak symbols, we need to have 4 symbols
* for each of the fortran address constants. As described above, we
* have to have known *pointer* values for the fortran addresses
* (e.g., MPI_STATUS_IGNORE). So when the fortran wrapper for
* MPI_RECV gets (MPI_Fint *status), it can check (status ==
* some_sentinel_value) to know that it got the Fortran equivalent of
* MPI_STATUS_IGNORE and therefore pass the C MPI_STATUS_IGNORE to the
* C MPI_Recv.
*
* We do this by having a "common" block in mpif.h:
*
* INTEGER MPI_STATUS_IGNORE(MPI_STATUS_SIZE)
* common /mpi_fortran_status_ignore/ MPI_STATUS_IGNORE
*
* This makes the fortran variable MPI_STATUS_IGNORE effectively be an
* alias for the C variable "mpi_fortran_status_ignore" -- but the C
* symbol name is according to the fortran compiler's naming symbol
* convention bais. So it could be MPI_FORTRAN_STATUS_IGNORE,
* mpi_fortran_status_ignore, mpi_fortran_status_ignore_, or
* mpi_fortran_status_ignore__.
*
* Hence, we have to have *4* C symbols for this, and them compare for
* all of them in the fortran MPI_RECV wrapper. :-( I can't think of
* any better way to do this.
*
* I'm putting these 4 comparisons in macros (on systems where we
* don't support the 4 symbols -- e.g., OSX, where we don't have weak
* symbols -- it'll only be one comparison), so if anyone things of
* something better than this, you should only need to modify this
* file.
*/
#define DECL(type, upper_case, lower_case, single_u, double_u) \
OMPI_DECLSPEC extern type upper_case; \
OMPI_DECLSPEC extern type lower_case; \
OMPI_DECLSPEC extern type single_u; \
OMPI_DECLSPEC extern type double_u
/* Note that the rationale for the types of each of these variables is
discussed in ompi/include/mpif-common.h. Do not change the types
without also changing ompi/runtime/ompi_mpi_init.c and
ompi/include/mpif-common.h. */
DECL(int, MPI_FORTRAN_BOTTOM, mpi_fortran_bottom,
mpi_fortran_bottom_, mpi_fortran_bottom__);
DECL(int, MPI_FORTRAN_IN_PLACE, mpi_fortran_in_place,
mpi_fortran_in_place_, mpi_fortran_in_place__);
DECL(char *, MPI_FORTRAN_ARGV_NULL, mpi_fortran_argv_null,
mpi_fortran_argv_null_, mpi_fortran_argv_null__);
DECL(double, MPI_FORTRAN_ARGVS_NULL, mpi_fortran_argvs_null,
mpi_fortran_argvs_null_, mpi_fortran_argvs_null__);
DECL(int *, MPI_FORTRAN_ERRCODES_IGNORE, mpi_fortran_errcodes_ignore,
mpi_fortran_errcodes_ignore_, mpi_fortran_errcodes_ignore__);
DECL(int *, MPI_FORTRAN_STATUS_IGNORE, mpi_fortran_status_ignore,
mpi_fortran_status_ignore_, mpi_fortran_status_ignore__);
DECL(double, MPI_FORTRAN_STATUSES_IGNORE, mpi_fortran_statuses_ignore,
mpi_fortran_statuses_ignore_, mpi_fortran_statuses_ignore__);
/*
* Create macros to do the checking. Only check for all 4 if we have
* weak symbols. Otherwise, just check for the one relevant symbol.
*/
#if OMPI_HAVE_WEAK_SYMBOLS
#define OMPI_IS_FORTRAN_BOTTOM(addr) \
(addr == (void*) &MPI_FORTRAN_BOTTOM || \
addr == (void*) &mpi_fortran_bottom || \
addr == (void*) &mpi_fortran_bottom_ || \
addr == (void*) &mpi_fortran_bottom__)
#define OMPI_IS_FORTRAN_IN_PLACE(addr) \
(addr == (void*) &MPI_FORTRAN_IN_PLACE || \
addr == (void*) &mpi_fortran_in_place || \
addr == (void*) &mpi_fortran_in_place_ || \
addr == (void*) &mpi_fortran_in_place__)
#define OMPI_IS_FORTRAN_ARGV_NULL(addr) \
(addr == (void*) &MPI_FORTRAN_ARGV_NULL || \
addr == (void*) &mpi_fortran_argv_null || \
addr == (void*) &mpi_fortran_argv_null_ || \
addr == (void*) &mpi_fortran_argv_null__)
#define OMPI_IS_FORTRAN_ARGVS_NULL(addr) \
(addr == (void*) &MPI_FORTRAN_ARGVS_NULL || \
addr == (void*) &mpi_fortran_argvs_null || \
addr == (void*) &mpi_fortran_argvs_null_ || \
addr == (void*) &mpi_fortran_argvs_null__)
#define OMPI_IS_FORTRAN_ERRCODES_IGNORE(addr) \
(addr == (void*) &MPI_FORTRAN_ERRCODES_IGNORE || \
addr == (void*) &mpi_fortran_errcodes_ignore || \
addr == (void*) &mpi_fortran_errcodes_ignore_ || \
addr == (void*) &mpi_fortran_errcodes_ignore__)
#define OMPI_IS_FORTRAN_STATUS_IGNORE(addr) \
(addr == (void*) &MPI_FORTRAN_STATUS_IGNORE || \
addr == (void*) &mpi_fortran_status_ignore || \
addr == (void*) &mpi_fortran_status_ignore_ || \
addr == (void*) &mpi_fortran_status_ignore__)
#define OMPI_IS_FORTRAN_STATUSES_IGNORE(addr) \
(addr == (void*) &MPI_FORTRAN_STATUSES_IGNORE || \
addr == (void*) &mpi_fortran_statuses_ignore || \
addr == (void*) &mpi_fortran_statuses_ignore_ || \
addr == (void*) &mpi_fortran_statuses_ignore__)
#elif OMPI_F77_CAPS
#define OMPI_IS_FORTRAN_BOTTOM(addr) \
(addr == (void*) &MPI_FORTRAN_BOTTOM)
#define OMPI_IS_FORTRAN_IN_PLACE(addr) \
(addr == (void*) &MPI_FORTRAN_IN_PLACE)
#define OMPI_IS_FORTRAN_ARGV_NULL(addr) \
(addr == (void*) &MPI_FORTRAN_ARGV_NULL)
#define OMPI_IS_FORTRAN_ARGVS_NULL(addr) \
(addr == (void*) &MPI_FORTRAN_ARGVS_NULL)
#define OMPI_IS_FORTRAN_ERRCODES_IGNORE(addr) \
(addr == (void*) &MPI_FORTRAN_ERRCODES_IGNORE)
#define OMPI_IS_FORTRAN_STATUS_IGNORE(addr) \
(addr == (void*) &MPI_FORTRAN_STATUS_IGNORE)
#define OMPI_IS_FORTRAN_STATUSES_IGNORE(addr) \
(addr == (void*) &MPI_FORTRAN_STATUSES_IGNORE)
#elif OMPI_F77_PLAIN
#define OMPI_IS_FORTRAN_BOTTOM(addr) \
(addr == (void*) &mpi_fortran_bottom)
#define OMPI_IS_FORTRAN_IN_PLACE(addr) \
(addr == (void*) &mpi_fortran_in_place)
#define OMPI_IS_FORTRAN_ARGV_NULL(addr) \
(addr == (void*) &mpi_fortran_argv_null)
#define OMPI_IS_FORTRAN_ARGVS_NULL(addr) \
(addr == (void*) &mpi_fortran_argvs_null)
#define OMPI_IS_FORTRAN_ERRCODES_IGNORE(addr) \
(addr == (void*) &mpi_fortran_errcodes_ignore)
#define OMPI_IS_FORTRAN_STATUS_IGNORE(addr) \
(addr == (void*) &mpi_fortran_status_ignore)
#define OMPI_IS_FORTRAN_STATUSES_IGNORE(addr) \
(addr == (void*) &mpi_fortran_statuses_ignore)
#elif OMPI_F77_SINGLE_UNDERSCORE
#define OMPI_IS_FORTRAN_BOTTOM(addr) \
(addr == (void*) &mpi_fortran_bottom_)
#define OMPI_IS_FORTRAN_IN_PLACE(addr) \
(addr == (void*) &mpi_fortran_in_place_)
#define OMPI_IS_FORTRAN_ARGV_NULL(addr) \
(addr == (void*) &mpi_fortran_argv_null_)
#define OMPI_IS_FORTRAN_ARGVS_NULL(addr) \
(addr == (void*) &mpi_fortran_argvs_null_)
#define OMPI_IS_FORTRAN_ERRCODES_IGNORE(addr) \
(addr == (void*) &mpi_fortran_errcodes_ignore_)
#define OMPI_IS_FORTRAN_STATUS_IGNORE(addr) \
(addr == (void*) &mpi_fortran_status_ignore_)
#define OMPI_IS_FORTRAN_STATUSES_IGNORE(addr) \
(addr == (void*) &mpi_fortran_statuses_ignore_)
#else
#define OMPI_IS_FORTRAN_BOTTOM(addr) \
(addr == (void*) &mpi_fortran_bottom__)
#define OMPI_IS_FORTRAN_IN_PLACE(addr) \
(addr == (void*) &mpi_fortran_in_place__)
#define OMPI_IS_FORTRAN_ARGV_NULL(addr) \
(addr == (void*) &mpi_fortran_argv_null__)
#define OMPI_IS_FORTRAN_ARGVS_NULL(addr) \
(addr == (void*) &mpi_fortran_argvs_null__)
#define OMPI_IS_FORTRAN_ERRCODES_IGNORE(addr) \
(addr == (void*) &mpi_fortran_errcodes_ignore__)
#define OMPI_IS_FORTRAN_STATUS_IGNORE(addr) \
(addr == (void*) &mpi_fortran_status_ignore__)
#define OMPI_IS_FORTRAN_STATUSES_IGNORE(addr) \
(addr == (void*) &mpi_fortran_statuses_ignore__)
#endif /* weak / specific symbol type */
/* Convert between Fortran and C MPI_BOTTOM */
#define OMPI_F2C_BOTTOM(addr) (OMPI_IS_FORTRAN_BOTTOM(addr) ? MPI_BOTTOM : (addr))
#define OMPI_F2C_IN_PLACE(addr) (OMPI_IS_FORTRAN_IN_PLACE(addr) ? MPI_IN_PLACE : (addr))
#endif /* OMPI_F77_CONSTANTS_H */