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