1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
/*
* Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#ifndef OMPI_FORTRAN_STATUS_CONVERSION_H
#define OMPI_FORTRAN_STATUS_CONVERSION_H
#include "ompi_config.h"
#include "mpi.h"
/*
* A Fortran MPI_STATUS argument and a C MPI_Status argument can differ.
* Therefore, the Fortran layer converts between Fortran and C statuses
* using the MPI_Status_[f2c|c2f] functions:
*
* void Fortran_api(... MPI_Fint *status ...)
* {
* int c_ierr;
* MPI_Status c_status;
* MPI_Status_f2c(status, &c_status);
* c_ierr = C_api(... &c_status ...);
* MPI_Status_c2f(&c_status, status);
* }
*
* The macros we define below support a different approach that avoids
* the overhead of conversion in cases where we can detect that the
* Fortran status can be used directly:
*
* void Fortran_api(... MPI_Fint *status ...)
* {
* int c_ierr;
* OMPI_FORTRAN_STATUS_DECLARATION(c_status,c_status2)
* OMPI_FORTRAN_STATUS_SET_POINTER(c_status,c_status2,status)
* c_ierr = C_api(... c_status ...);
* OMPI_FORTRAN_STATUS_RETURN(c_status,c_status2,status,c_ierr)
* }
*
* Issues around whether a Fortran status can be used directly by
* OMPI C internals are discussed in trac tickets 2526 and 3218 as
* well as ompi/mpi/c/status_c2f.c. The issues include:
*
* - A Fortran status must be large enough to hold a C status.
* This requirement is always satisfied by the configure-time
* determination of the Fortran parameter MPI_STATUS_SIZE.
*
* - A Fortran INTEGER should be the same size as a C int so
* that components indicated by MPI_SOURCE, MPI_TAG, and
* MPI_ERROR can be addressed properly from either language.
*
* - A Fortran status must be aligned such that all C status
* struct components have proper alignment. The Fortran
* status alignment is only guaranteed to be suitable for
* Fortran INTEGERs. The C status requires alignment for a
* size_t component. We utilize two tests:
*
* - Check if Fortran INTEGER alignment matches size_t alignment.
* This check is not necessary, but it is sufficient and can be
* assessed at compile time.
*
* - Check if the particular Fortran status pointer provided by
* the user has suitable alignment. This check is both necessary
* and sufficient, but must be conducted at run time.
*
* These alignment issues are taken into consideration only
* for 64-bit SPARC runs, which is where these issues have
* been visible.
*/
/*
* First, we have two preliminary checks:
* - OMPI_FORTRAN_STATUS_NEED_CONVERSION_1
* is sufficient, but not necessary
* can be evaluated at compile time
* - OMPI_FORTRAN_STATUS_NEED_CONVERSION_2(status)
* is sufficient and necessary
* must be evaluated at run time
* If check #1 is false at compile time, then check #2 will always be false at run time.
* The compile-time check is used to conditionalize compilation of references to c_status2.
*/
#if defined(__sparc) && SIZEOF_SIZE_T == 8
#define OMPI_FORTRAN_STATUS_NEED_CONVERSION_1 \
((OMPI_SIZEOF_FORTRAN_INTEGER!=SIZEOF_INT) || \
(OMPI_ALIGNMENT_FORTRAN_INTEGER!=OPAL_ALIGNMENT_SIZE_T))
#else
#define OMPI_FORTRAN_STATUS_NEED_CONVERSION_1 \
(OMPI_SIZEOF_FORTRAN_INTEGER!=SIZEOF_INT)
#endif
#if defined(__sparc) && SIZEOF_SIZE_T == 8
#define OMPI_FORTRAN_STATUS_NEED_CONVERSION_2(status) \
( \
(OMPI_SIZEOF_FORTRAN_INTEGER!=SIZEOF_INT) \
|| \
( \
(OMPI_ALIGNMENT_FORTRAN_INTEGER!=OPAL_ALIGNMENT_SIZE_T) \
&& \
(((ulong) (status)) & (OPAL_ALIGNMENT_SIZE_T-1)) \
) \
)
#else
#define OMPI_FORTRAN_STATUS_NEED_CONVERSION_2(status) \
(OMPI_SIZEOF_FORTRAN_INTEGER!=SIZEOF_INT)
#endif
/*
* Now, the macros:
* - OMPI_FORTRAN_STATUS_DECLARATION(c_status,c_status2)
* - OMPI_FORTRAN_STATUS_SET_POINTER(c_status,c_status2,status)
* - OMPI_FORTRAN_STATUS_RETURN(c_status,c_status2,status,c_ierr)
*/
#if OMPI_FORTRAN_STATUS_NEED_CONVERSION_1
#define OMPI_FORTRAN_STATUS_DECLARATION(c_status,c_status2) MPI_Status *c_status, c_status2;
#else
#define OMPI_FORTRAN_STATUS_DECLARATION(c_status,c_status2) MPI_Status *c_status;
#endif
#if OMPI_FORTRAN_STATUS_NEED_CONVERSION_1
#define OMPI_FORTRAN_STATUS_SET_POINTER(c_status,c_status2,status) \
do { \
if (OMPI_IS_FORTRAN_STATUS_IGNORE(status)) { \
c_status = MPI_STATUS_IGNORE; \
} else { \
if ( OMPI_FORTRAN_STATUS_NEED_CONVERSION_2(status) ) { \
c_status = &c_status2; \
} else { \
c_status = (MPI_Status *) status; \
} \
} \
} while (0);
#else
#define OMPI_FORTRAN_STATUS_SET_POINTER(c_status,c_status2,status) \
do { \
if (OMPI_IS_FORTRAN_STATUS_IGNORE(status)) { \
c_status = MPI_STATUS_IGNORE; \
} else { \
c_status = (MPI_Status *) status; \
} \
} while (0);
#endif
#if OMPI_FORTRAN_STATUS_NEED_CONVERSION_1
#define OMPI_FORTRAN_STATUS_RETURN(c_status,c_status2,status,c_ierr) \
do { \
if ( \
OMPI_FORTRAN_STATUS_NEED_CONVERSION_2(status) && \
MPI_SUCCESS == c_ierr && \
MPI_STATUS_IGNORE != c_status ) \
{ \
MPI_Status_c2f(c_status, status); \
} \
} while (0);
#else
#define OMPI_FORTRAN_STATUS_RETURN(c_status,c_status2,status,c_ierr)
#endif
#endif /* OMPI_FORTRAN_STATUS_CONVERSION_H */
|