1 #ifndef PyMPI_COMPAT_OPENMPI_H
2 #define PyMPI_COMPAT_OPENMPI_H
3
4 /* ------------------------------------------------------------------------- */
5 /* ------------------------------------------------------------------------- */
6
7 /*
8 * The hackery below redefines the actuall calls to 'MPI_Init()' and
9 * 'MPI_Init_thread()' in order to preload the main MPI dynamic
10 * library with appropriate flags to 'dlopen()' ensuring global
11 * availability of library symbols.
12 */
13
14 #ifndef OPENMPI_DLOPEN_LIBMPI
15 #define OPENMPI_DLOPEN_LIBMPI 1
16 #endif
17
18 #if OPENMPI_DLOPEN_LIBMPI
19 #if HAVE_DLOPEN
20
21 #include "../dynload.h"
22
23 /*
24 static void * my_dlopen(const char *name, int mode) {
25 void *handle;
26 static int called = 0;
27 if (!called) {
28 called = 1;
29 #if HAVE_DLFCN_H
30 printf("HAVE_DLFCN_H: yes\n");
31 #else
32 printf("HAVE_DLFCN_H: no\n");
33 #endif
34 printf("\n");
35 printf("RTLD_LAZY: 0x%X\n", RTLD_LAZY );
36 printf("RTLD_NOW: 0x%X\n", RTLD_NOW );
37 printf("RTLD_LOCAL: 0x%X\n", RTLD_LOCAL );
38 printf("RTLD_GLOBAL: 0x%X\n", RTLD_GLOBAL );
39 #ifdef RTLD_NOLOAD
40 printf("RTLD_NOLOAD: 0x%X\n", RTLD_NOLOAD );
41 #endif
42 printf("\n");
43 }
44 handle = dlopen(name, mode);
45 printf("dlopen(\"%s\",0x%X) -> %p\n", name, mode, handle);
46 printf("dlerror() -> %s\n\n", dlerror());
47 return handle;
48 }
49 #define dlopen my_dlopen
50 */
51
OPENMPI_dlopen_libmpi(void)52 static void OPENMPI_dlopen_libmpi(void)
53 {
54 void *handle = 0;
55 int mode = RTLD_NOW | RTLD_GLOBAL;
56 #ifdef RTLD_NOLOAD
57 mode |= RTLD_NOLOAD;
58 #endif
59 #if defined(__CYGWIN__)
60 if (!handle) handle = dlopen("cygmpi.dll", mode);
61 if (!handle) handle = dlopen("mpi.dll", mode);
62 #elif defined(__APPLE__)
63 /* Mac OS X */
64 if (!handle) handle = dlopen("libmpi.3.dylib", mode);
65 if (!handle) handle = dlopen("libmpi.2.dylib", mode);
66 if (!handle) handle = dlopen("libmpi.1.dylib", mode);
67 if (!handle) handle = dlopen("libmpi.0.dylib", mode);
68 if (!handle) handle = dlopen("libmpi.dylib", mode);
69 #else
70 /* GNU/Linux and others*/
71 if (!handle) handle = dlopen("libmpi.so.3", mode);
72 if (!handle) handle = dlopen("libmpi.so.2", mode);
73 if (!handle) handle = dlopen("libmpi.so.1", mode);
74 if (!handle) handle = dlopen("libmpi.so.0", mode);
75 if (!handle) handle = dlopen("libmpi.so", mode);
76 #endif
77 }
78
PyMPI_OPENMPI_MPI_Init(int * argc,char *** argv)79 static int PyMPI_OPENMPI_MPI_Init(int *argc, char ***argv)
80 {
81 OPENMPI_dlopen_libmpi();
82 return MPI_Init(argc, argv);
83 }
84 #undef MPI_Init
85 #define MPI_Init PyMPI_OPENMPI_MPI_Init
86
PyMPI_OPENMPI_MPI_Init_thread(int * argc,char *** argv,int required,int * provided)87 static int PyMPI_OPENMPI_MPI_Init_thread(int *argc, char ***argv,
88 int required, int *provided)
89 {
90 OPENMPI_dlopen_libmpi();
91 return MPI_Init_thread(argc, argv, required, provided);
92 }
93 #undef MPI_Init_thread
94 #define MPI_Init_thread PyMPI_OPENMPI_MPI_Init_thread
95
96 #endif /* !HAVE_DLOPEN */
97 #endif /* !OPENMPI_DLOPEN_LIBMPI */
98
99 /* ------------------------------------------------------------------------- */
100 /* ------------------------------------------------------------------------- */
101
102
103 /* ------------------------------------------------------------------------- */
104
105 #if (defined(OMPI_MAJOR_VERSION) && \
106 defined(OMPI_MINOR_VERSION) && \
107 defined(OMPI_RELEASE_VERSION))
108 #define PyMPI_OPENMPI_VERSION ((OMPI_MAJOR_VERSION * 10000) + \
109 (OMPI_MINOR_VERSION * 100) + \
110 (OMPI_RELEASE_VERSION * 1))
111 #else
112 #define PyMPI_OPENMPI_VERSION 10000
113 #endif
114
115 /* ------------------------------------------------------------------------- */
116
117 /*
118 * Open MPI < 1.1.3 generates an error when MPI_File_get_errhandler()
119 * is called with the predefined error handlers MPI_ERRORS_RETURN and
120 * MPI_ERRORS_ARE_FATAL.
121 */
122
123 #if PyMPI_OPENMPI_VERSION < 10103
124
PyMPI_OPENMPI_Errhandler_free(MPI_Errhandler * errhandler)125 static int PyMPI_OPENMPI_Errhandler_free(MPI_Errhandler *errhandler)
126 {
127 if (errhandler && ((*errhandler == MPI_ERRORS_RETURN) ||
128 (*errhandler == MPI_ERRORS_ARE_FATAL))) {
129 *errhandler = MPI_ERRHANDLER_NULL;
130 return MPI_SUCCESS;
131 }
132 return MPI_Errhandler_free(errhandler);
133 }
134 #undef MPI_Errhandler_free
135 #define MPI_Errhandler_free PyMPI_OPENMPI_Errhandler_free
136
137 #endif /* !(PyMPI_OPENMPI_VERSION < 10103) */
138
139 /* ------------------------------------------------------------------------- */
140
141 /*
142 * Open MPI 1.1 generates an error when MPI_File_get_errhandler() is
143 * called with the MPI_FILE_NULL handle. The code below try to fix
144 * this bug by intercepting the calls to the functions setting and
145 * getting the error handlers for MPI_File's.
146 */
147
148 #if PyMPI_OPENMPI_VERSION < 10200
149
150 static MPI_Errhandler PyMPI_OPENMPI_FILE_NULL_ERRHANDLER = (MPI_Errhandler)0;
151
PyMPI_OPENMPI_File_get_errhandler(MPI_File file,MPI_Errhandler * errhandler)152 static int PyMPI_OPENMPI_File_get_errhandler(MPI_File file,
153 MPI_Errhandler *errhandler)
154 {
155 if (file == MPI_FILE_NULL) {
156 if (PyMPI_OPENMPI_FILE_NULL_ERRHANDLER == (MPI_Errhandler)0) {
157 PyMPI_OPENMPI_FILE_NULL_ERRHANDLER = MPI_ERRORS_RETURN;
158 }
159 *errhandler = PyMPI_OPENMPI_FILE_NULL_ERRHANDLER;
160 return MPI_SUCCESS;
161 }
162 return MPI_File_get_errhandler(file, errhandler);
163 }
164 #undef MPI_File_get_errhandler
165 #define MPI_File_get_errhandler PyMPI_OPENMPI_File_get_errhandler
166
PyMPI_OPENMPI_File_set_errhandler(MPI_File file,MPI_Errhandler errhandler)167 static int PyMPI_OPENMPI_File_set_errhandler(MPI_File file,
168 MPI_Errhandler errhandler)
169 {
170 int ierr = MPI_File_set_errhandler(file, errhandler);
171 if (ierr != MPI_SUCCESS) return ierr;
172 if (file == MPI_FILE_NULL) {
173 PyMPI_OPENMPI_FILE_NULL_ERRHANDLER = errhandler;
174 }
175 return ierr;
176 }
177 #undef MPI_File_set_errhandler
178 #define MPI_File_set_errhandler PyMPI_OPENMPI_File_set_errhandler
179
180 #endif /* !(PyMPI_OPENMPI_VERSION < 10200) */
181
182 /* ---------------------------------------------------------------- */
183
184 #if PyMPI_OPENMPI_VERSION < 10301
185
PyMPI_OPENMPI_File_c2f(MPI_File file)186 static MPI_Fint PyMPI_OPENMPI_File_c2f(MPI_File file)
187 {
188 if (file == MPI_FILE_NULL) return (MPI_Fint)0;
189 return MPI_File_c2f(file);
190 }
191 #define MPI_File_c2f PyMPI_OPENMPI_File_c2f
192
193 #endif /* !(PyMPI_OPENMPI_VERSION < 10301) */
194
195 /* ------------------------------------------------------------------------- */
196
197 #if PyMPI_OPENMPI_VERSION < 10402
198
PyMPI_OPENMPI_MPI_Cancel(MPI_Request * request)199 static int PyMPI_OPENMPI_MPI_Cancel(MPI_Request *request)
200 {
201 if (request && *request == MPI_REQUEST_NULL) {
202 MPI_Comm_call_errhandler(MPI_COMM_WORLD, MPI_ERR_REQUEST);
203 return MPI_ERR_REQUEST;
204 }
205 return MPI_Cancel(request);
206 }
207 #undef MPI_Cancel
208 #define MPI_Cancel PyMPI_OPENMPI_MPI_Cancel
209
PyMPI_OPENMPI_MPI_Request_free(MPI_Request * request)210 static int PyMPI_OPENMPI_MPI_Request_free(MPI_Request *request)
211 {
212 if (request && *request == MPI_REQUEST_NULL) {
213 MPI_Comm_call_errhandler(MPI_COMM_WORLD, MPI_ERR_REQUEST);
214 return MPI_ERR_REQUEST;
215 }
216 return MPI_Request_free(request);
217 }
218 #undef MPI_Request_free
219 #define MPI_Request_free PyMPI_OPENMPI_MPI_Request_free
220
PyMPI_OPENMPI_MPI_Win_get_errhandler(MPI_Win win,MPI_Errhandler * errhandler)221 static int PyMPI_OPENMPI_MPI_Win_get_errhandler(MPI_Win win,
222 MPI_Errhandler *errhandler)
223 {
224 if (win == MPI_WIN_NULL) {
225 MPI_Comm_call_errhandler(MPI_COMM_WORLD, MPI_ERR_WIN);
226 return MPI_ERR_WIN;
227 }
228 return MPI_Win_get_errhandler(win, errhandler);
229 }
230 #undef MPI_Win_get_errhandler
231 #define MPI_Win_get_errhandler PyMPI_OPENMPI_MPI_Win_get_errhandler
232
PyMPI_OPENMPI_MPI_Win_set_errhandler(MPI_Win win,MPI_Errhandler errhandler)233 static int PyMPI_OPENMPI_MPI_Win_set_errhandler(MPI_Win win,
234 MPI_Errhandler errhandler)
235 {
236 if (win == MPI_WIN_NULL) {
237 MPI_Comm_call_errhandler(MPI_COMM_WORLD, MPI_ERR_WIN);
238 return MPI_ERR_WIN;
239 }
240 return MPI_Win_set_errhandler(win, errhandler);
241 }
242 #undef MPI_Win_set_errhandler
243 #define MPI_Win_set_errhandler PyMPI_OPENMPI_MPI_Win_set_errhandler
244
245 #endif /* !(PyMPI_OPENMPI_VERSION < 10402) */
246
247 /* ------------------------------------------------------------------------- */
248
249 #endif /* !PyMPI_COMPAT_OPENMPI_H */
250
251 /*
252 Local Variables:
253 c-basic-offset: 2
254 indent-tabs-mode: nil
255 End:
256 */
257