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 */