vgdb: Handle EAGAIN in read_buf
[valgrind.git] / mpi / libmpiwrap.c
blobb277617854006ae094ec6f46d1d0eebd4249ab32
2 /*---------------------------------------------------------------*/
3 /*--- ---*/
4 /*--- A library of wrappers for MPI 2 functions. ---*/
5 /*--- ---*/
6 /*---------------------------------------------------------------*/
8 /* ----------------------------------------------------------------
10 Notice that the following BSD-style license applies to this one
11 file (mpiwrap.c) only. The rest of Valgrind is licensed under the
12 terms of the GNU General Public License, version 2, unless
13 otherwise indicated. See the COPYING file in the source
14 distribution for details.
16 ----------------------------------------------------------------
18 This file is part of Valgrind, a dynamic binary instrumentation
19 framework.
21 Copyright (C) 2006-2017 OpenWorks LLP. All rights reserved.
23 Redistribution and use in source and binary forms, with or without
24 modification, are permitted provided that the following conditions
25 are met:
27 1. Redistributions of source code must retain the above copyright
28 notice, this list of conditions and the following disclaimer.
30 2. The origin of this software must not be misrepresented; you must
31 not claim that you wrote the original software. If you use this
32 software in a product, an acknowledgment in the product
33 documentation would be appreciated but is not required.
35 3. Altered source versions must be plainly marked as such, and must
36 not be misrepresented as being the original software.
38 4. The name of the author may not be used to endorse or promote
39 products derived from this software without specific prior written
40 permission.
42 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
43 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
44 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
46 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
48 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
49 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
50 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
51 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
52 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 Neither the names of the U.S. Department of Energy nor the
55 University of California nor the names of its contributors may be
56 used to endorse or promote products derived from this software
57 without prior written permission.
60 /* Handling of MPI_STATUS{ES}_IGNORE for MPI_Status* arguments.
62 The MPI-2 spec allows many functions which have MPI_Status* purely
63 as an out parameter, to accept the constants MPI_STATUS_IGNORE or
64 MPI_STATUSES_IGNORE there instead, if the caller does not care
65 about the status. See the MPI-2 spec sec 4.5.1 ("Passing
66 MPI_STATUS_IGNORE for Status"). (mpi2-report.pdf, 1615898 bytes,
67 md5=694a5efe2fd291eecf7e8c9875b5f43f).
69 This library handles such cases by allocating a fake MPI_Status
70 object (on the stack) or an array thereof (on the heap), and
71 passing that onwards instead. From the outside the caller sees no
72 difference. Unfortunately the simpler approach of merely detecting
73 and handling these special cases at a lower level does not work,
74 because we need to use information returned in MPI_Status*
75 arguments to paint result buffers, even if the caller doesn't
76 supply a real MPI_Status object.
78 Eg, MPI_Recv. We can't paint the result buffer without knowing how
79 many items arrived; but we can't find that out without passing a
80 real MPI_Status object to the (real) MPI_Recv call. Hence, if the
81 caller did not supply one, we have no option but to use a temporary
82 stack allocated one for the inner call. Ditto, more indirectly
83 (via maybe_complete) for nonblocking receives and the various
84 associated wait/test calls. */
87 /*------------------------------------------------------------*/
88 /*--- includes ---*/
89 /*------------------------------------------------------------*/
91 #include <stdio.h>
92 #include <assert.h>
93 #include <unistd.h> /* getpid */
94 #include <stdlib.h> /* exit */
95 #include <string.h> /* strstr */
96 #include <pthread.h> /* pthread_mutex_{lock,unlock} */
98 /* Include Valgrind magic macros for writing wrappers. */
99 #include "../memcheck/memcheck.h"
101 /* Include macros for VALGRIND_{DIS,EN}ABLE_ERROR_REPORTING.
102 This is somewhat experimental and hence disable-able, by
103 setting cONFIG_DER to zero. */
104 #include "../include/valgrind.h"
106 #define cONFIG_DER 1 /* set to 0 to disable */
109 /*------------------------------------------------------------*/
110 /*--- Connect to MPI library ---*/
111 /*------------------------------------------------------------*/
113 /* Include headers for whatever MPI implementation the wrappers are to
114 be used with. The configure system will tell us what the path to
115 the chosen MPI implementation is, via -I.. to the compiler. */
116 #include "mpi.h"
118 /* Where are API symbols?
119 Open MPI lib/libmpi.so, soname = libmpi.so.0
120 Quadrics MPI lib/libmpi.so, soname = libmpi.so.0
121 MPICH libmpich.so.1.0, soname = libmpich.so.1.0
123 A suitable soname to match with is therefore "libmpi*.so*".
125 #define I_WRAP_FNNAME_U(_name) \
126 I_WRAP_SONAME_FNNAME_ZU(libmpiZaZdsoZa,_name)
129 /* Define HAVE_MPI_STATUS_IGNORE iff we have to deal with
130 MPI_STATUS{ES}_IGNORE. */
131 #if MPI_VERSION >= 2 \
132 || (defined(MPI_STATUS_IGNORE) && defined(MPI_STATUSES_IGNORE))
133 # undef HAVE_MPI_STATUS_IGNORE
134 # define HAVE_MPI_STATUS_IGNORE 1
135 #else
136 # undef HAVE_MPI_STATUS_IGNORE
137 #endif
140 /*------------------------------------------------------------*/
141 /*--- Decls ---*/
142 /*------------------------------------------------------------*/
144 typedef unsigned char Bool;
145 #define False ((Bool)0)
146 #define True ((Bool)1)
148 /* Word, UWord are machine words - same size as a pointer. This is
149 checked at startup. The wrappers below use 'long' to mean a
150 machine word - this too is tested at startup. */
151 typedef signed long Word;
152 typedef unsigned long UWord;
154 #if !defined(offsetof)
155 # define offsetof(type,memb) ((UWord)&((type*)0)->memb)
156 #endif
158 /* Find the size of long double image (not 'sizeof(long double)').
159 See comments in sizeofOneNamedTy. */
160 static long sizeof_long_double_image ( void );
163 /*------------------------------------------------------------*/
164 /*--- Simple helpers ---*/
165 /*------------------------------------------------------------*/
167 /* ------ Helpers for debug printing ------ */
169 /* constant */
170 static const char* preamble = "valgrind MPI wrappers";
172 /* established at startup */
173 static pid_t my_pid = -1;
174 static char* options_str = NULL;
175 static int opt_verbosity = 1;
176 static Bool opt_missing = 0; /* 0:silent; 1:warn; 2:abort */
177 static Bool opt_help = False;
178 static Bool opt_initkludge = False;
180 static void before ( char* fnname )
182 /* This isn't thread-safe wrt 'done' (no locking). It's not
183 critical. */
184 static int done = 0;
185 if (done == 0) {
186 done = 1;
187 my_pid = getpid();
188 options_str = getenv("MPIWRAP_DEBUG");
189 if (options_str) {
190 if (NULL != strstr(options_str, "warn"))
191 opt_missing = 1;
192 if (NULL != strstr(options_str, "strict"))
193 opt_missing = 2;
194 if (NULL != strstr(options_str, "verbose"))
195 opt_verbosity++;
196 if (NULL != strstr(options_str, "quiet"))
197 opt_verbosity--;
198 if (NULL != strstr(options_str, "help"))
199 opt_help = True;
200 if (NULL != strstr(options_str, "initkludge"))
201 opt_initkludge = True;
203 if (opt_verbosity > 0)
204 fprintf(stderr, "%s %5d: Active for pid %d\n",
205 preamble, my_pid, my_pid);
206 /* Sanity check - that Word/UWord really are machine words. */
207 assert(sizeof(Word) == sizeof(void*));
208 assert(sizeof(UWord) == sizeof(void*));
209 /* Sanity check - char is byte-sized (else address calculations
210 in walk_type don't work. */
211 assert(sizeof(char) == 1);
212 if (opt_help) {
213 fprintf(stderr, "\n");
214 fprintf(stderr, "Valid options for the MPIWRAP_DEBUG environment"
215 " variable are:\n");
216 fprintf(stderr, "\n");
217 fprintf(stderr, " quiet be silent except for errors\n");
218 fprintf(stderr, " verbose show wrapper entries/exits\n");
219 fprintf(stderr, " strict abort the program if a function"
220 " with no wrapper is used\n");
221 fprintf(stderr, " warn give a warning if a function"
222 " with no wrapper is used\n");
223 fprintf(stderr, " help display this message, then exit\n");
224 fprintf(stderr, " initkludge debugging hack; do not use\n");
225 fprintf(stderr, "\n");
226 fprintf(stderr, "Multiple options are allowed, eg"
227 " MPIWRAP_DEBUG=strict,verbose\n");
228 fprintf(stderr, "Note: 'warn' generates output even if 'quiet'"
229 " is also specified\n");
230 fprintf(stderr, "\n");
231 fprintf(stderr, "%s %5d: exiting now\n", preamble, my_pid );
232 exit(1);
234 if (opt_verbosity > 0)
235 fprintf(stderr,
236 "%s %5d: Try MPIWRAP_DEBUG=help for possible options\n",
237 preamble, my_pid);
240 if (opt_verbosity > 1)
241 fprintf(stderr, "%s %5d: enter PMPI_%s\n", preamble, my_pid, fnname );
244 static __inline__ void after ( char* fnname, int err )
246 if (opt_verbosity > 1)
247 fprintf(stderr, "%s %5d: exit PMPI_%s (err = %d)\n",
248 preamble, my_pid, fnname, err );
251 static void barf ( char* msg )
253 fprintf(stderr, "%s %5d: fatal: %s\n", preamble, my_pid, msg);
254 fprintf(stderr, "%s %5d: exiting now\n", preamble, my_pid );
255 exit(1);
258 /* Half-hearted type-showing function (for debugging). */
259 static void showTy ( FILE* f, MPI_Datatype ty )
261 if (ty == MPI_DATATYPE_NULL) fprintf(f,"DATATYPE_NULL");
262 else if (ty == MPI_BYTE) fprintf(f,"BYTE");
263 else if (ty == MPI_PACKED) fprintf(f,"PACKED");
264 else if (ty == MPI_CHAR) fprintf(f,"CHAR");
265 else if (ty == MPI_SHORT) fprintf(f,"SHORT");
266 else if (ty == MPI_INT) fprintf(f,"INT");
267 else if (ty == MPI_LONG) fprintf(f,"LONG");
268 else if (ty == MPI_FLOAT) fprintf(f,"FLOAT");
269 else if (ty == MPI_DOUBLE) fprintf(f,"DOUBLE");
270 else if (ty == MPI_LONG_DOUBLE) fprintf(f,"LONG_DOUBLE");
271 else if (ty == MPI_UNSIGNED_CHAR) fprintf(f,"UNSIGNED_CHAR");
272 else if (ty == MPI_UNSIGNED_SHORT) fprintf(f,"UNSIGNED_SHORT");
273 else if (ty == MPI_UNSIGNED_LONG) fprintf(f,"UNSIGNED_LONG");
274 else if (ty == MPI_UNSIGNED) fprintf(f,"UNSIGNED");
275 else if (ty == MPI_FLOAT_INT) fprintf(f,"FLOAT_INT");
276 else if (ty == MPI_DOUBLE_INT) fprintf(f,"DOUBLE_INT");
277 else if (ty == MPI_LONG_DOUBLE_INT) fprintf(f,"LONG_DOUBLE_INT");
278 else if (ty == MPI_LONG_INT) fprintf(f,"LONG_INT");
279 else if (ty == MPI_SHORT_INT) fprintf(f,"SHORT_INT");
280 else if (ty == MPI_2INT) fprintf(f,"2INT");
281 # if defined(MPI_UB) && \
282 (!defined(OMPI_MAJOR_VERSION) || OMPI_MAJOR_VERSION < 3)
283 else if (ty == MPI_UB) fprintf(f,"UB");
284 # endif
285 # if defined(MPI_LB) && \
286 (!defined(OMPI_MAJOR_VERSION) || OMPI_MAJOR_VERSION < 3)
287 else if (ty == MPI_LB) fprintf(f,"LB");
288 # endif
289 # if defined(MPI_WCHAR)
290 else if (ty == MPI_WCHAR) fprintf(f,"WCHAR");
291 # endif
292 else if (ty == MPI_LONG_LONG_INT) fprintf(f,"LONG_LONG_INT");
293 # if defined(MPI_LONG_LONG)
294 else if (ty == MPI_LONG_LONG) fprintf(f,"LONG_LONG");
295 # endif
296 # if defined(MPI_UNSIGNED_LONG_LONG)
297 else if (ty == MPI_UNSIGNED_LONG_LONG) fprintf(f,"UNSIGNED_LONG_LONG");
298 # endif
299 # if defined(MPI_REAL8)
300 else if (ty == MPI_REAL8) fprintf(f, "REAL8");
301 # endif
302 # if defined(MPI_REAL4)
303 else if (ty == MPI_REAL4) fprintf(f, "REAL4");
304 # endif
305 # if defined(MPI_REAL)
306 else if (ty == MPI_REAL) fprintf(f, "REAL");
307 # endif
308 # if defined(MPI_INTEGER8)
309 else if (ty == MPI_INTEGER8) fprintf(f, "INTEGER8");
310 # endif
311 # if defined(MPI_INTEGER4)
312 else if (ty == MPI_INTEGER4) fprintf(f, "INTEGER4");
313 # endif
314 # if defined(MPI_INTEGER)
315 else if (ty == MPI_INTEGER) fprintf(f, "INTEGER");
316 # endif
317 # if defined(MPI_DOUBLE_PRECISION)
318 else if (ty == MPI_DOUBLE_PRECISION) fprintf(f, "DOUBLE_PRECISION");
319 # endif
320 # if defined(MPI_COMPLEX)
321 else if (ty == MPI_COMPLEX) fprintf(f, "COMPLEX");
322 # endif
323 # if defined(MPI_DOUBLE_COMPLEX)
324 else if (ty == MPI_DOUBLE_COMPLEX) fprintf(f, "DOUBLE_COMPLEX");
325 # endif
326 # if defined(MPI_LOGICAL)
327 else if (ty == MPI_LOGICAL) fprintf(f, "LOGICAL");
328 # endif
329 # if defined(MPI_2INTEGER)
330 else if (ty == MPI_2INTEGER) fprintf(f, "2INTEGER");
331 # endif
332 # if defined(MPI_2COMPLEX)
333 else if (ty == MPI_2COMPLEX) fprintf(f, "2COMPLEX");
334 # endif
335 # if defined(MPI_2DOUBLE_COMPLEX)
336 else if (ty == MPI_2DOUBLE_COMPLEX) fprintf(f, "2DOUBLE_COMPLEX");
337 # endif
338 # if defined(MPI_2REAL)
339 else if (ty == MPI_2REAL) fprintf(f, "2REAL");
340 # endif
341 # if defined(MPI_2DOUBLE_PRECISION)
342 else if (ty == MPI_2DOUBLE_PRECISION) fprintf(f, "2DOUBLE_PRECISION");
343 # endif
344 # if defined(MPI_CHARACTER)
345 else if (ty == MPI_CHARACTER) fprintf(f, "CHARACTER");
346 # endif
347 else fprintf(f,"showTy:???");
350 static void showCombiner ( FILE* f, int combiner )
352 switch (combiner) {
353 case MPI_COMBINER_NAMED: fprintf(f, "NAMED"); break;
354 # if defined(MPI_COMBINER_DUP)
355 case MPI_COMBINER_DUP: fprintf(f, "DUP"); break;
356 # endif
357 case MPI_COMBINER_CONTIGUOUS: fprintf(f, "CONTIGUOUS"); break;
358 case MPI_COMBINER_VECTOR: fprintf(f, "VECTOR"); break;
359 # if defined(MPI_COMBINER_HVECTOR_INTEGER) && \
360 (!defined(OMPI_MAJOR_VERSION) || OMPI_MAJOR_VERSION < 3)
361 case MPI_COMBINER_HVECTOR_INTEGER: fprintf(f, "HVECTOR_INTEGER"); break;
362 # endif
363 case MPI_COMBINER_HVECTOR: fprintf(f, "HVECTOR"); break;
364 case MPI_COMBINER_INDEXED: fprintf(f, "INDEXED"); break;
365 # if defined(MPI_COMBINER_HINDEXED_INTEGER) && \
366 (!defined(OMPI_MAJOR_VERSION) || OMPI_MAJOR_VERSION < 3)
367 case MPI_COMBINER_HINDEXED_INTEGER: fprintf(f, "HINDEXED_INTEGER"); break;
368 # endif
369 case MPI_COMBINER_HINDEXED: fprintf(f, "HINDEXED"); break;
370 # if defined(MPI_COMBINER_INDEXED_BLOCK)
371 case MPI_COMBINER_INDEXED_BLOCK: fprintf(f, "INDEXED_BLOCK"); break;
372 # endif
373 # if defined(MPI_COMBINER_STRUCT_INTEGER) && \
374 (!defined(OMPI_MAJOR_VERSION) || OMPI_MAJOR_VERSION < 3)
375 case MPI_COMBINER_STRUCT_INTEGER: fprintf(f, "STRUCT_INTEGER"); break;
376 # endif
377 case MPI_COMBINER_STRUCT: fprintf(f, "STRUCT"); break;
378 # if defined(MPI_COMBINER_SUBARRAY)
379 case MPI_COMBINER_SUBARRAY: fprintf(f, "SUBARRAY"); break;
380 # endif
381 # if defined(MPI_COMBINER_DARRAY)
382 case MPI_COMBINER_DARRAY: fprintf(f, "DARRAY"); break;
383 # endif
384 # if defined(MPI_COMBINER_F90_REAL)
385 case MPI_COMBINER_F90_REAL: fprintf(f, "F90_REAL"); break;
386 # endif
387 # if defined(MPI_COMBINER_F90_COMPLEX)
388 case MPI_COMBINER_F90_COMPLEX: fprintf(f, "F90_COMPLEX"); break;
389 # endif
390 # if defined(MPI_COMBINER_F90_INTEGER)
391 case MPI_COMBINER_F90_INTEGER: fprintf(f, "F90_INTEGER"); break;
392 # endif
393 # if defined(MPI_COMBINER_RESIZED)
394 case MPI_COMBINER_RESIZED: fprintf(f, "RESIZED"); break;
395 # endif
396 default: fprintf(f, "showCombiner:??"); break;
401 /* ------ Get useful bits of info ------ */
403 /* Note, PMPI_Comm_rank/size are themselves wrapped. Should work
404 fine. */
406 static __inline__ int comm_rank ( MPI_Comm comm )
408 int err, r;
409 err = PMPI_Comm_rank(comm, &r);
410 return err ? 0/*arbitrary*/ : r;
413 static __inline__ int comm_size ( MPI_Comm comm )
415 int err, r;
416 err = PMPI_Comm_size(comm, &r);
417 return err ? 0/*arbitrary*/ : r;
420 static __inline__ Bool count_from_Status( /*OUT*/int* recv_count,
421 MPI_Datatype datatype,
422 MPI_Status* status)
424 int n;
425 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
426 int err = PMPI_Get_count(status, datatype, &n);
427 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
428 if (err == MPI_SUCCESS) {
429 VALGRIND_MAKE_MEM_DEFINED(&n, sizeof(n));
430 *recv_count = n;
431 return True;
432 } else {
433 return False;
437 /* It's critical that we can do equality on MPI_Requests.
438 Unfortunately these are opaque objects to us (handles, in the
439 parlance of the MPI 1.1 spec). Fortunately Sec 2.4.1 ("Opaque
440 Objects") specifies that "In C, [...] These [handles] should be
441 types that support assignment and equality operations." Hence the
442 following function should compile for any compliant definition of
443 MPI_Request. */
444 static __inline__
445 Bool eq_MPI_Request ( MPI_Request r1, MPI_Request r2 )
447 return r1 == r2;
450 /* Return True if status is MPI_STATUS_IGNORE or MPI_STATUSES_IGNORE.
451 On MPI-1.x platforms which don't have these symbols (and they would
452 only have them if they've been backported from 2.x) always return
453 False. */
454 static __inline__
455 Bool isMSI ( MPI_Status* status )
457 # if defined(HAVE_MPI_STATUS_IGNORE)
458 return status == MPI_STATUSES_IGNORE || status == MPI_STATUS_IGNORE;
459 # else
460 return False;
461 # endif
464 /* Get the 'extent' of a type. Note, as per the MPI spec this
465 includes whatever padding would be required when using 'ty' in an
466 array. */
467 static long extentOfTy ( MPI_Datatype ty )
469 int r;
470 MPI_Aint n;
471 # if defined(MPI_TYPE_EXTENT)
472 r = PMPI_Type_extent(ty, &n);
473 # else
474 MPI_Aint lb;
475 r = MPI_Type_get_extent(ty, &lb, &n);
476 # endif
477 assert(r == MPI_SUCCESS);
478 return (long)n;
481 /* Free up *ty, if it is safe to do so */
482 static void maybeFreeTy ( MPI_Datatype* ty )
484 int r, n_ints, n_addrs, n_dtys, tycon;
486 r = PMPI_Type_get_envelope( *ty, &n_ints, &n_addrs, &n_dtys, &tycon );
487 assert(r == MPI_SUCCESS);
489 /* can't free named types */
490 if (tycon == MPI_COMBINER_NAMED)
491 return;
493 /* some kinds of structs are predefined so we can't free them
494 either. */
495 if (*ty == MPI_FLOAT_INT || *ty == MPI_DOUBLE_INT
496 || *ty == MPI_LONG_INT || *ty == MPI_2INT
497 || *ty == MPI_SHORT_INT || *ty == MPI_LONG_DOUBLE_INT)
498 return;
500 /* Looks OK - free it. */
501 if (0) {
502 /* show me what you're about to free .. */
503 fprintf(stderr, "freeing combiner ");
504 showCombiner(stderr,tycon);
505 fprintf(stderr, " ty= ");
506 showTy(stderr,*ty);
507 fprintf(stderr,"\n");
509 r = PMPI_Type_free(ty);
510 assert(r == MPI_SUCCESS);
513 /* How big is a "named" (base) type? Returns 0 if not known. Note.
514 There is a subtlety, which is that this is required to return the
515 exact size of one item of the type, NOT the size of it when padded
516 suitably to make an array of them. In particular that's why the
517 size of LONG_DOUBLE is computed by looking at the result of doing a
518 long double store, rather than just asking what is the sizeof(long
519 double).
521 For LONG_DOUBLE on x86-linux and amd64-linux my impression is that
522 the right answer is 10 even though sizeof(long double) says 12 and
523 16 respectively. On ppc32-linux it appears to be 16.
525 Ref: MPI 1.1 doc p18 */
526 static long sizeofOneNamedTy ( MPI_Datatype ty )
528 if (ty == MPI_CHAR) return sizeof(signed char);
529 if (ty == MPI_SHORT) return sizeof(signed short int);
530 if (ty == MPI_INT) return sizeof(signed int);
531 if (ty == MPI_LONG) return sizeof(signed long int);
532 if (ty == MPI_UNSIGNED_CHAR) return sizeof(unsigned char);
533 if (ty == MPI_UNSIGNED_SHORT) return sizeof(unsigned short int);
534 if (ty == MPI_UNSIGNED) return sizeof(unsigned int);
535 if (ty == MPI_UNSIGNED_LONG) return sizeof(unsigned long int);
536 if (ty == MPI_FLOAT) return sizeof(float);
537 if (ty == MPI_DOUBLE) return sizeof(double);
538 if (ty == MPI_BYTE) return 1;
539 if (ty == MPI_LONG_DOUBLE) return sizeof_long_double_image();
540 if (ty == MPI_PACKED) return 1;
541 if (ty == MPI_LONG_LONG_INT) return sizeof(signed long long int);
543 # if defined(MPI_REAL8)
544 if (ty == MPI_REAL8) return 8; /* MPI2 spec */;
545 # endif
546 # if defined(MPI_REAL4)
547 if (ty == MPI_REAL4) return 4; /* MPI2 spec */;
548 # endif
549 # if defined(MPI_REAL)
550 if (ty == MPI_REAL) return 4; /* MPI2 spec */;
551 # endif
552 # if defined(MPI_INTEGER8)
553 if (ty == MPI_INTEGER8) return 8; /* MPI2 spec */;
554 # endif
555 # if defined(MPI_INTEGER4)
556 if (ty == MPI_INTEGER4) return 4; /* MPI2 spec */;
557 # endif
558 # if defined(MPI_INTEGER)
559 if (ty == MPI_INTEGER) return 4; /* MPI2 spec */;
560 # endif
561 # if defined(MPI_DOUBLE_PRECISION)
562 if (ty == MPI_DOUBLE_PRECISION) return 8; /* MPI2 spec */;
563 # endif
565 /* new in MPI2: */
566 # if defined(MPI_WCHAR)
567 if (ty == MPI_WCHAR) return 2; /* MPI2 spec */;
568 # endif
569 # if defined(MPI_SIGNED_CHAR)
570 if (ty == MPI_SIGNED_CHAR) return 1; /* MPI2 spec */;
571 # endif
572 # if defined(MPI_UNSIGNED_LONG_LONG)
573 if (ty == MPI_UNSIGNED_LONG_LONG) return 8; /* MPI2 spec */;
574 # endif
575 # if defined(MPI_COMPLEX)
576 if (ty == MPI_COMPLEX) return 2 * 4; /* MPI2 spec */
577 # endif
578 # if defined(MPI_DOUBLE_COMPLEX)
579 if (ty == MPI_DOUBLE_COMPLEX) return 2 * 8; /* MPI2 spec */
580 # endif
581 # if defined(MPI_LOGICAL)
582 if (ty == MPI_LOGICAL) return 4; /* MPI2 spec */
583 # endif
584 # if defined(MPI_2INTEGER)
585 if (ty == MPI_2INTEGER) return 2 * 4; /* undocumented in MPI2 */
586 # endif
587 # if defined(MPI_2COMPLEX)
588 if (ty == MPI_2COMPLEX) return 2 * 8; /* undocumented in MPI2 */
589 # endif
590 # if defined(MPI_2DOUBLE_COMPLEX)
591 /* 32: this is how openmpi-1.2.2 behaves on x86-linux, but I have
592 really no idea if this is right. */
593 if (ty == MPI_2DOUBLE_COMPLEX) return 32; /* undocumented in MPI2 */
594 # endif
595 # if defined(MPI_2REAL)
596 if (ty == MPI_2REAL) return 2 * 4; /* undocumented in MPI2 */
597 # endif
598 # if defined(MPI_2DOUBLE_PRECISION)
599 if (ty == MPI_2DOUBLE_PRECISION) return 2 * 8; /* undocumented in MPI2 */
600 # endif
601 # if defined(MPI_CHARACTER)
602 if (ty == MPI_CHARACTER) return 1; /* MPI2 spec */
603 # endif
605 /* Note: the following are named structs, not named basic types,
606 and so are not handled here:
607 FLOAT_INT DOUBLE_INT LONG_INT 2INT SHORT_INT LONG_DOUBLE_INT
608 My guess is they are probably for doing max-w-index style
609 reductions, the INT carrying the index of the max/min and the
610 other type its actual value.
612 return 0;
616 /* Find the size of long double image (not 'sizeof(long double)').
617 See comments in sizeofOneNamedTy.
619 static long sizeof_long_double_image ( void )
621 long i;
622 unsigned char* p;
623 static long cached_result = 0;
625 /* Hopefully we have it already. */
626 if (cached_result != 0) {
627 assert(cached_result == 10 || cached_result == 16 || cached_result == 8);
628 return cached_result;
631 /* No? Then we'll have to compute it. This isn't thread-safe but
632 it doesn't really matter since all races to compute it should
633 produce the same answer. */
634 p = malloc(64);
635 assert(p);
636 for (i = 0; i < 64; i++)
637 p[i] = 0x55;
639 /* Write a value which isn't known at compile time and therefore
640 must come out of a register. If we just store a constant here,
641 some compilers write more data than a store from a machine
642 register would. Therefore we have to force a store from a
643 machine register by storing a value which isn't known at compile
644 time. Since getpid() will return a value < 1 million, turn it
645 into a zero by dividing by 1e+30. */
646 *(long double*)(&p[16]) = (long double)(1.0e-30 * (double)getpid());
648 for (i = 0; i < 16; i++) {
649 assert(p[i] == 0x55);
650 assert(p[i+48] == 0x55);
652 for (i = 16; i <= 48; i++) {
653 if (p[i] == 0x55)
654 break;
657 assert(i < 48);
658 assert(i > 16);
659 free(p);
660 cached_result = i - 16;
662 if (0)
663 printf("sizeof_long_double_image: computed %d\n", (int)cached_result);
665 assert(cached_result == 10 || cached_result == 16 || cached_result == 8);
666 return cached_result;
670 /*------------------------------------------------------------*/
671 /*--- Unpicking datatypes ---*/
672 /*------------------------------------------------------------*/
674 static __inline__
675 void walk_type_array ( void(*f)(void*,long), char* base,
676 MPI_Datatype ty, long count );
679 /* Walk over all fragments of the object of type 'ty' with base
680 address 'base', and apply 'f' to the start/length of each
681 contiguous fragment. */
682 static
683 void walk_type ( void(*f)(void*,long), char* base, MPI_Datatype ty )
685 int r, n_ints, n_addrs, n_dtys, tycon;
686 long ex, i;
687 int* ints = NULL;
688 MPI_Aint* addrs = NULL;
689 MPI_Datatype* dtys = NULL;
691 /* Stuff for limiting how much complaining text it spews out */
692 static int complaints = 3;
693 static int last_complained_about_tycon = -987654321; /* presumably bogus */
695 if (0)
696 printf("walk_type %p\n", (void*)(unsigned long)ty);
698 r = PMPI_Type_get_envelope( ty, &n_ints, &n_addrs, &n_dtys, &tycon );
699 assert(r == MPI_SUCCESS);
701 /* Handle the base cases fast(er/ish). */
702 if (tycon == MPI_COMBINER_NAMED) {
703 long sz = sizeofOneNamedTy(ty);
704 if (sz > 0) {
705 f(base, sz);
706 return;
708 /* Hmm. Perhaps it's a named struct? Unfortunately we can't
709 take them to bits so we have to do a really ugly hack, which
710 makes assumptions about how the MPI implementation has laid
711 out these types. At least Open MPI 1.0.1 appears to put
712 the 'val' field first. MPICH2 agrees.
714 if (ty == MPI_2INT) {
715 typedef struct { int val; int loc; } Ty;
716 f(base + offsetof(Ty,val), sizeof(int));
717 f(base + offsetof(Ty,loc), sizeof(int));
718 return;
720 if (ty == MPI_LONG_INT) {
721 typedef struct { long val; int loc; } Ty;
722 f(base + offsetof(Ty,val), sizeof(long));
723 f(base + offsetof(Ty,loc), sizeof(int));
724 return;
726 if (ty == MPI_DOUBLE_INT) {
727 typedef struct { double val; int loc; } Ty;
728 f(base + offsetof(Ty,val), sizeof(double));
729 f(base + offsetof(Ty,loc), sizeof(int));
730 return;
732 if (ty == MPI_SHORT_INT) {
733 typedef struct { short val; int loc; } Ty;
734 f(base + offsetof(Ty,val), sizeof(short));
735 f(base + offsetof(Ty,loc), sizeof(int));
736 return;
738 if (ty == MPI_FLOAT_INT) {
739 typedef struct { float val; int loc; } Ty;
740 f(base + offsetof(Ty,val), sizeof(float));
741 f(base + offsetof(Ty,loc), sizeof(int));
742 return;
744 if (ty == MPI_LONG_DOUBLE_INT) {
745 typedef struct { long double val; int loc; } Ty;
746 f(base + offsetof(Ty,val), sizeof_long_double_image());
747 f(base + offsetof(Ty,loc), sizeof(int));
748 return;
750 # if defined(MPI_LB) && defined(MPI_UB) && \
751 (!defined(OMPI_MAJOR_VERSION) || OMPI_MAJOR_VERSION < 3)
752 if (ty == MPI_LB || ty == MPI_UB)
753 return; /* have zero size, so nothing needs to be done */
754 # endif
755 goto unhandled;
756 /*NOTREACHED*/
759 if (0) {
760 ex = extentOfTy(ty);
761 printf("tycon 0x%llx %d %d %d (ext %d)\n",
762 (unsigned long long int)tycon,
763 n_ints, n_addrs, n_dtys, (int)ex );
766 /* Now safe to do MPI_Type_get_contents */
767 assert(n_ints >= 0);
768 assert(n_addrs >= 0);
769 assert(n_dtys >= 0);
771 if (n_ints > 0) {
772 ints = malloc(n_ints * sizeof(int));
773 assert(ints);
775 if (n_addrs > 0) {
776 addrs = malloc(n_addrs * sizeof(MPI_Aint));
777 assert(addrs);
779 if (n_dtys > 0) {
780 dtys = malloc(n_dtys * sizeof(MPI_Datatype));
781 assert(dtys);
784 r = PMPI_Type_get_contents( ty, n_ints, n_addrs, n_dtys,
785 ints, addrs, dtys );
786 assert(r == MPI_SUCCESS);
788 switch (tycon) {
790 case MPI_COMBINER_CONTIGUOUS:
791 assert(n_ints == 1 && n_addrs == 0 && n_dtys == 1);
792 walk_type_array( f, base, dtys[0], ints[0] );
793 maybeFreeTy( &dtys[0] );
794 break;
796 case MPI_COMBINER_VECTOR:
797 assert(n_ints == 3 && n_addrs == 0 && n_dtys == 1);
798 ex = extentOfTy(dtys[0]);
799 if (0)
800 printf("vector count %d x (bl %d stride %d)\n",
801 (int)ints[0], (int)ints[1], (int)ints[2]);
802 for (i = 0; i < ints[0]; i++) {
803 walk_type_array( f, base + i * ints[2]/*stride*/ * ex,
804 dtys[0], ints[1]/*blocklength*/ );
806 maybeFreeTy( &dtys[0] );
807 break;
809 case MPI_COMBINER_HVECTOR:
810 assert(n_ints == 2 && n_addrs == 1 && n_dtys == 1);
811 ex = extentOfTy(dtys[0]);
812 if (0)
813 printf("hvector count %d x (bl %d hstride %d)\n",
814 (int)ints[0], (int)ints[1], (int)addrs[0]);
815 for (i = 0; i < ints[0]; i++) {
816 walk_type_array( f, base + i * addrs[0]/*hstride*/,
817 dtys[0], ints[1]/*blocklength*/ );
819 maybeFreeTy( &dtys[0] );
820 break;
822 case MPI_COMBINER_INDEXED:
823 assert(n_addrs == 0 && n_dtys == 1);
824 assert(n_ints > 0);
825 assert(n_ints == 2 * ints[0] + 1);
826 ex = extentOfTy(dtys[0]);
827 for (i = 0; i < ints[0]; i++) {
828 if (0)
829 printf("indexed (elem %d) off %d copies %d\n",
830 (int)i, ints[i+1+ints[0]], ints[i+1] );
831 walk_type_array( f, base + ex * ints[i+1+ints[0]],
832 dtys[0], ints[i+1] );
834 maybeFreeTy( &dtys[0] );
835 break;
837 case MPI_COMBINER_HINDEXED:
838 assert(n_ints > 0);
839 assert(n_ints == ints[0] + 1);
840 assert(n_addrs == ints[0] && n_dtys == 1);
841 ex = extentOfTy(dtys[0]);
842 for (i = 0; i < ints[0]; i++) {
843 if (0)
844 printf("hindexed (elem %d) hoff %d copies %d\n",
845 (int)i, (int)addrs[i], ints[i+1] );
846 walk_type_array( f, base + addrs[i],
847 dtys[0], ints[i+1] );
849 maybeFreeTy( &dtys[0] );
850 break;
852 case MPI_COMBINER_STRUCT:
853 assert(n_addrs == n_ints-1);
854 assert(n_dtys == n_ints-1);
855 assert(n_ints > 0);
856 assert(n_ints == ints[0] + 1);
857 for (i = 0; i < ints[0]; i++) {
858 if (0)
859 printf("struct (elem %d limit %d) hoff %d copies %d\n",
860 (int)i, (int)ints[0], (int)addrs[i], (int)ints[i+1]);
861 walk_type_array( f, base + addrs[i], dtys[i], (long)ints[i+1] );
862 maybeFreeTy( &dtys[i] );
864 break;
866 default:
867 goto unhandled;
871 /* normal exit */
872 if (ints) free(ints);
873 if (addrs) free(addrs);
874 if (dtys) free(dtys);
875 return;
877 unhandled:
878 /* Complain, but limit the amount of complaining that can happen to
879 the first 3 different unhandled tycons that show up, so as to
880 avoid swamping users with thousands of duplicate messages. */
881 if (complaints > 0 && tycon != last_complained_about_tycon) {
882 complaints--;
883 last_complained_about_tycon = tycon;
884 if (tycon == MPI_COMBINER_NAMED) {
885 fprintf(stderr, "%s %5d: walk_type: unhandled base type 0x%lx ",
886 preamble, my_pid, (long)ty);
887 showTy(stderr, ty);
888 fprintf(stderr, "\n");
889 } else {
890 fprintf(stderr, "%s %5d: walk_type: unhandled combiner 0x%lx\n",
891 preamble, my_pid, (long)tycon);
894 if (ints) free(ints);
895 if (addrs) free(addrs);
896 if (dtys) free(dtys);
897 if (opt_missing >= 2)
898 barf("walk_type: unhandled combiner, strict checking selected");
902 /* Same as walk_type but apply 'f' to every element in an array of
903 'count' items starting at 'base'. The only purpose of pushing this
904 into a different routine is so it can attempt to optimise the case
905 where the array elements are contiguous and packed together without
906 holes. */
907 static __inline__
908 void walk_type_array ( void(*f)(void*,long), char* base,
909 MPI_Datatype elemTy, long count )
911 long i, ex;
913 assert(sizeof(unsigned long) == sizeof(char*));
915 /* First see if we can do this the fast way. */
916 ex = sizeofOneNamedTy(elemTy);
918 if ( /* ty is a primitive type with power-of-2 size */
919 (ex == 8 || ex == 4 || ex == 2 || ex == 1)
920 && /* base is suitably aligned for ty */
921 ( ((unsigned long)base) & (ex-1)) == 0) {
923 /* We're sure it's contiguous, so just paint/check it in one
924 go. */
925 if (0) printf("walk_type_array fast %ld of size %ld\n", count, ex );
926 f ( base, count * ex );
928 } else {
930 /* Bad news. We have to futz with each element individually.
931 This could be very expensive.
933 Note: subtle. If ty is LONG_DOUBLE then the extent will be
934 12, so the following loop will jump along in steps of 12, but
935 the size painted by walk_type will be 10 since it uses
936 sizeofOneNamedTy to establish the size of base types. Which
937 is what we need to happen. */
938 ex = extentOfTy(elemTy);
939 if (0) printf("walk_type_array SLOW %ld of size %ld\n", count, ex );
940 for (i = 0; i < count; i++)
941 walk_type( f, base + i * ex, elemTy );
947 /* Hook so it's visible from outside (can be handy to dlopen/dlsym
948 it) */
949 void mpiwrap_walk_type_EXTERNALLY_VISIBLE
950 ( void(*f)(void*,long), char* base, MPI_Datatype ty )
952 walk_type(f, base, ty);
956 /*------------------------------------------------------------*/
957 /*--- Address-range helpers ---*/
958 /*------------------------------------------------------------*/
960 /* ----------------
961 Do corresponding checks on memory areas defined using a
962 straightforward (start, length) description.
963 ----------------
966 static __inline__
967 void check_mem_is_defined_untyped ( void* buffer, long nbytes )
969 if (nbytes > 0) {
970 VALGRIND_CHECK_MEM_IS_DEFINED(buffer, nbytes);
974 static __inline__
975 void check_mem_is_addressable_untyped ( void* buffer, long nbytes )
977 if (nbytes > 0) {
978 VALGRIND_CHECK_MEM_IS_ADDRESSABLE(buffer, nbytes);
982 static __inline__
983 void make_mem_defined_if_addressable_untyped ( void* buffer, long nbytes )
985 if (nbytes > 0) {
986 VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(buffer, nbytes);
990 static __inline__
991 void make_mem_defined_if_addressable_if_success_untyped ( int err,
992 void* buffer, long nbytes )
994 if (err == MPI_SUCCESS && nbytes > 0) {
995 VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(buffer, nbytes);
1000 /* ----------------
1001 Do checks on memory areas defined using the MPI (buffer, count,
1002 type) convention.
1003 ----------------
1006 /* Check that the specified area is both addressible and contains
1007 initialised data, and cause V to complain if not. */
1009 static __inline__
1010 void check_mem_is_defined ( char* buffer, long count, MPI_Datatype datatype )
1012 walk_type_array( check_mem_is_defined_untyped, buffer, datatype, count );
1016 /* Check that the specified area is addressible, and cause V to
1017 complain if not. Doesn't matter whether the data there is
1018 initialised or not. */
1020 static __inline__
1021 void check_mem_is_addressable ( void *buffer, long count, MPI_Datatype datatype )
1023 walk_type_array( check_mem_is_addressable_untyped, buffer, datatype, count );
1027 /* Set the specified area to 'defined for each byte which is
1028 addressible' state. */
1030 static __inline__
1031 void make_mem_defined_if_addressable ( void *buffer, int count, MPI_Datatype datatype )
1033 walk_type_array( make_mem_defined_if_addressable_untyped,
1034 buffer, datatype, count );
1037 static __inline__
1038 void
1039 make_mem_defined_if_addressable_if_success ( int err, void *buffer, int count,
1040 MPI_Datatype datatype )
1042 if (err == MPI_SUCCESS)
1043 make_mem_defined_if_addressable(buffer, count, datatype);
1047 /*------------------------------------------------------------*/
1048 /*--- ---*/
1049 /*--- The wrappers proper. They are listed in the order ---*/
1050 /*--- in which they appear in "MPI: A Message-Passing ---*/
1051 /*--- Interface Standard, MPIF, Nov 15 2003" (the MPI 1.1 ---*/
1052 /*--- spec. All unimplemented wrappers are listed at the ---*/
1053 /*--- end of the file. The list of function names is ---*/
1054 /*--- taken from the headers of Open MPI svn r9191. ---*/
1055 /*--- Hopefully it is a complete list of all the MPI 2 ---*/
1056 /*--- functions. ---*/
1057 /*--- ---*/
1058 /*------------------------------------------------------------*/
1060 /* Handy abbreviation */
1061 #define WRAPPER_FOR(name) I_WRAP_FNNAME_U(name)
1063 /* Generates (conceptually) a wrapper which does nothing. In
1064 fact just generate no wrapper at all. */
1065 #define HAS_NO_WRAPPER(basename) /* */
1068 /*------------------------------------------------------------*/
1069 /*--- ---*/
1070 /*--- Sec 3.2, Blocking Send and Receive Operations ---*/
1071 /*--- ---*/
1072 /*------------------------------------------------------------*/
1074 /* --- {,B,S,R}Send --- */
1075 /* pre: rd: (buf,count,datatype) */
1076 static
1077 int generic_Send(void *buf, int count, MPI_Datatype datatype,
1078 int dest, int tag, MPI_Comm comm)
1080 OrigFn fn;
1081 int err;
1082 VALGRIND_GET_ORIG_FN(fn);
1083 before("{,B,S,R}Send");
1084 check_mem_is_defined(buf, count, datatype);
1085 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1086 CALL_FN_W_6W(err, fn, buf,count,datatype,dest,tag,comm);
1087 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1088 after("{,B,S,R}Send", err);
1089 return err;
1091 int WRAPPER_FOR(PMPI_Send)(void *buf, int count, MPI_Datatype datatype,
1092 int dest, int tag, MPI_Comm comm) {
1093 return generic_Send(buf,count,datatype, dest,tag,comm);
1095 int WRAPPER_FOR(PMPI_Bsend)(void *buf, int count, MPI_Datatype datatype,
1096 int dest, int tag, MPI_Comm comm) {
1097 return generic_Send(buf,count,datatype, dest,tag,comm);
1099 int WRAPPER_FOR(PMPI_Ssend)(void *buf, int count, MPI_Datatype datatype,
1100 int dest, int tag, MPI_Comm comm) {
1101 return generic_Send(buf,count,datatype, dest,tag,comm);
1103 int WRAPPER_FOR(PMPI_Rsend)(void *buf, int count, MPI_Datatype datatype,
1104 int dest, int tag, MPI_Comm comm) {
1105 return generic_Send(buf,count,datatype, dest,tag,comm);
1108 /* --- Recv --- */
1109 /* pre: must be writable: (buf,count,datatype)
1110 must be writable: status
1111 post: make readable: (buf,recv_count,datatype)
1112 where recv_count is determined from *status
1114 int WRAPPER_FOR(PMPI_Recv)(void *buf, int count, MPI_Datatype datatype,
1115 int source, int tag,
1116 MPI_Comm comm, MPI_Status *status)
1118 OrigFn fn;
1119 int err, recv_count = 0;
1120 MPI_Status fake_status;
1121 VALGRIND_GET_ORIG_FN(fn);
1122 before("Recv");
1123 if (isMSI(status))
1124 status = &fake_status;
1125 check_mem_is_addressable(buf, count, datatype);
1126 check_mem_is_addressable_untyped(status, sizeof(*status));
1127 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1128 CALL_FN_W_7W(err, fn, buf,count,datatype,source,tag,comm,status);
1129 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1130 make_mem_defined_if_addressable_if_success_untyped(err, status, sizeof(*status));
1131 if (err == MPI_SUCCESS && count_from_Status(&recv_count,datatype,status)) {
1132 make_mem_defined_if_addressable(buf, recv_count, datatype);
1134 after("Recv", err);
1135 return err;
1138 /* --- Get_count --- */
1139 /* pre: must be readable: *status
1140 post: make defined: *count -- don't bother, libmpi will surely do this
1142 int WRAPPER_FOR(PMPI_Get_count)(MPI_Status* status,
1143 MPI_Datatype ty, int* count )
1145 OrigFn fn;
1146 int err;
1147 VALGRIND_GET_ORIG_FN(fn);
1148 before("Get_count");
1149 check_mem_is_defined_untyped(status, sizeof(*status));
1150 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1151 CALL_FN_W_WWW(err, fn, status,ty,count);
1152 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1153 after("Get_count", err);
1154 return err;
1158 /*------------------------------------------------------------*/
1159 /*--- ---*/
1160 /*--- Sec 3.7, Nonblocking communication ---*/
1161 /*--- ---*/
1162 /*------------------------------------------------------------*/
1164 /* Maintain a table that makes it possible for the wrappers to
1165 complete MPI_Irecv successfully.
1167 The issue is that MPI_Irecv states the recv buffer and returns
1168 immediately, giving a handle (MPI_Request) for the transaction.
1169 Later the user will have to poll for completion with MPI_Wait etc,
1170 and at that point these wrappers have to paint the recv buffer.
1171 But the recv buffer details are not presented to MPI_Wait - only
1172 the handle is. We therefore have to use a shadow table
1173 (sReqs{,_size,_used,_lock}) which associates uncompleted
1174 MPI_Requests with the corresponding buffer address/count/type.
1176 Only read requests are placed in the table, since there is no need
1177 to do any buffer painting following completion of an Isend - all
1178 the checks for that are done at the time Isend is called.
1180 Care has to be take to remove completed requests from the table.
1182 Access to the table is guarded by sReqs_lock so as to make it
1183 thread-safe.
1186 typedef
1187 struct {
1188 Bool inUse;
1189 MPI_Request key;
1190 void* buf;
1191 int count;
1192 MPI_Datatype datatype;
1194 ShadowRequest;
1196 static ShadowRequest* sReqs = NULL;
1197 static int sReqs_size = 0;
1198 static int sReqs_used = 0;
1199 static pthread_mutex_t sReqs_lock = PTHREAD_MUTEX_INITIALIZER;
1201 #define LOCK_SREQS \
1202 do { int pr = pthread_mutex_lock(&sReqs_lock); \
1203 assert(pr == 0); \
1204 } while (0)
1206 #define UNLOCK_SREQS \
1207 do { int pr = pthread_mutex_unlock(&sReqs_lock); \
1208 assert(pr == 0); \
1209 } while (0)
1212 /* Ensure the sReqs expandable array has at least one free slot, by
1213 copying it into a larger one if necessary. NOTE: sReqs_lock is
1214 held throughout this procedure.*/
1215 static void ensure_sReq_space ( void )
1217 int i;
1218 ShadowRequest* sReqs2;
1219 if (sReqs_used == sReqs_size) {
1220 sReqs_size = sReqs_size==0 ? 2 : 2*sReqs_size;
1221 sReqs2 = malloc( sReqs_size * sizeof(ShadowRequest) );
1222 if (sReqs2 == NULL) {
1223 UNLOCK_SREQS;
1224 barf("add_shadow_Request: malloc failed.\n");
1226 for (i = 0; i < sReqs_used; i++)
1227 sReqs2[i] = sReqs[i];
1228 if (sReqs)
1229 free(sReqs);
1230 sReqs = sReqs2;
1232 assert(sReqs_used < sReqs_size);
1236 /* Find shadow info for 'request', or NULL if none. */
1238 static
1239 ShadowRequest* find_shadow_Request ( MPI_Request request )
1241 ShadowRequest* ret = NULL;
1242 int i;
1243 LOCK_SREQS;
1244 for (i = 0; i < sReqs_used; i++) {
1245 if (sReqs[i].inUse && eq_MPI_Request(sReqs[i].key,request)) {
1246 ret = &sReqs[i];
1247 break;
1250 UNLOCK_SREQS;
1251 return ret;
1255 /* Delete shadow info for 'request', if any. */
1257 static void delete_shadow_Request ( MPI_Request request )
1259 int i;
1260 LOCK_SREQS;
1261 for (i = 0; i < sReqs_used; i++) {
1262 if (sReqs[i].inUse && eq_MPI_Request(sReqs[i].key,request)) {
1263 sReqs[i].inUse = False;
1264 break;
1267 UNLOCK_SREQS;
1271 /* Add a shadow for 'request', overwriting any old binding for it. */
1273 static
1274 void add_shadow_Request( MPI_Request request,
1275 void* buf, int count,
1276 MPI_Datatype datatype )
1278 int i, ix = -1;
1279 LOCK_SREQS;
1280 assert(sReqs_used >= 0);
1281 assert(sReqs_size >= 0);
1282 assert(sReqs_used <= sReqs_size);
1283 if (sReqs == NULL) assert(sReqs_size == 0);
1285 /* First of all see if we already have a binding for this key; if
1286 so just replace it, and have done. */
1287 for (i = 0; i < sReqs_used; i++) {
1288 if (sReqs[i].inUse && eq_MPI_Request(sReqs[i].key,request)) {
1289 ix = i;
1290 break;
1294 if (ix < 0) {
1295 /* Ok, we don't have it, so will have to add it. First search
1296 to see if there is an existing empty slot. */
1297 for (i = 0; i < sReqs_used; i++) {
1298 if (!sReqs[i].inUse) {
1299 ix = i;
1300 break;
1305 /* No empty slots. Allocate a new one. */
1306 if (ix < 0) {
1307 ensure_sReq_space();
1308 assert(sReqs_used < sReqs_size);
1309 ix = sReqs_used;
1310 sReqs_used++;
1313 assert(ix >= 0 && ix < sReqs_used);
1314 assert(sReqs_used <= sReqs_size);
1316 sReqs[ix].inUse = True;
1317 sReqs[ix].key = request;
1318 sReqs[ix].buf = buf;
1319 sReqs[ix].count = count;
1320 sReqs[ix].datatype = datatype;
1322 UNLOCK_SREQS;
1323 if (opt_verbosity > 1)
1324 fprintf(stderr, "%s %5d: sReq+ 0x%lx -> b/c/d %p/%d/0x%lx [slot %d]\n",
1325 preamble, my_pid, (unsigned long)request,
1326 buf, count, (long)datatype, ix);
1329 static
1330 MPI_Request* clone_Request_array ( int count, MPI_Request* orig )
1332 MPI_Request* copy;
1333 int i;
1334 LOCK_SREQS;
1335 if (count < 0)
1336 count = 0; /* Hmm. Call Mulder and Scully. */
1337 copy = malloc( count * sizeof(MPI_Request) );
1338 if (copy == NULL && count > 0) {
1339 UNLOCK_SREQS;
1340 barf("clone_Request_array: malloc failed");
1342 for (i = 0; i < count; i++)
1343 copy[i] = orig[i];
1344 UNLOCK_SREQS;
1345 return copy;
1348 #undef LOCK_SREQS
1349 #undef UNLOCK_SREQS
1352 static void maybe_complete ( Bool error_in_status,
1353 MPI_Request request_before,
1354 MPI_Request request_after,
1355 MPI_Status* status )
1357 int recv_count = 0;
1358 ShadowRequest* shadow;
1359 /* How do we know if this is an Irecv request that has now
1360 finished successfully?
1362 request_before isn't MPI_REQUEST_NULL
1363 and request_before is found in the shadow table
1364 and request_after *is* MPI_REQUEST_NULL
1365 and (if error_in_status then status.MPI_ERROR is MPI_SUCCESS)
1367 (when error_in_status == False, then we expect not to get
1368 called at all if there was an error.)
1370 if (request_before != MPI_REQUEST_NULL
1371 && request_after == MPI_REQUEST_NULL
1372 && (error_in_status ? status->MPI_ERROR == MPI_SUCCESS : True)
1373 && ( (shadow=find_shadow_Request(request_before)) != NULL) ) {
1374 /* The Irecv detailed in 'shadow' completed. Paint the result
1375 buffer, and delete the entry. */
1376 if (count_from_Status(&recv_count, shadow->datatype, status)) {
1377 make_mem_defined_if_addressable(shadow->buf, recv_count, shadow->datatype);
1378 if (opt_verbosity > 1)
1379 fprintf(stderr, "%s %5d: sReq- 0x%lx (completed)\n",
1380 preamble, my_pid, (unsigned long) request_before);
1382 delete_shadow_Request(request_before);
1387 /* --- Isend --- */
1388 /* rd: (buf,count,datatype) */
1389 /* wr: *request */
1390 static __inline__
1391 int generic_Isend(void *buf, int count, MPI_Datatype datatype,
1392 int dest, int tag, MPI_Comm comm,
1393 MPI_Request* request)
1395 OrigFn fn;
1396 int err;
1397 VALGRIND_GET_ORIG_FN(fn);
1398 before("{,B,S,R}Isend");
1399 check_mem_is_defined(buf, count, datatype);
1400 check_mem_is_addressable_untyped(request, sizeof(*request));
1401 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1402 CALL_FN_W_7W(err, fn, buf,count,datatype,dest,tag,comm,request);
1403 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1404 make_mem_defined_if_addressable_if_success_untyped(err, request, sizeof(*request));
1405 after("{,B,S,R}Isend", err);
1406 return err;
1408 int WRAPPER_FOR(PMPI_Isend)(void *buf, int count, MPI_Datatype datatype,
1409 int dest, int tag, MPI_Comm comm,
1410 MPI_Request* request) {
1411 return generic_Isend(buf,count,datatype, dest,tag,comm, request);
1413 int WRAPPER_FOR(PMPI_Ibsend)(void *buf, int count, MPI_Datatype datatype,
1414 int dest, int tag, MPI_Comm comm,
1415 MPI_Request* request) {
1416 return generic_Isend(buf,count,datatype, dest,tag,comm, request);
1418 int WRAPPER_FOR(PMPI_Issend)(void *buf, int count, MPI_Datatype datatype,
1419 int dest, int tag, MPI_Comm comm,
1420 MPI_Request* request) {
1421 return generic_Isend(buf,count,datatype, dest,tag,comm, request);
1423 int WRAPPER_FOR(PMPI_Irsend)(void *buf, int count, MPI_Datatype datatype,
1424 int dest, int tag, MPI_Comm comm,
1425 MPI_Request* request) {
1426 return generic_Isend(buf,count,datatype, dest,tag,comm, request);
1430 /* --- Irecv --- */
1431 /* pre: must be writable: (buf,count,datatype), *request
1432 post: make readable *request
1433 add a request->(buf,count,ty) binding to the
1434 shadow request table.
1436 int WRAPPER_FOR(PMPI_Irecv)( void* buf, int count, MPI_Datatype datatype,
1437 int source, int tag, MPI_Comm comm,
1438 MPI_Request* request )
1440 OrigFn fn;
1441 int err;
1442 VALGRIND_GET_ORIG_FN(fn);
1443 before("Irecv");
1444 check_mem_is_addressable(buf, count, datatype);
1445 check_mem_is_addressable_untyped(request, sizeof(*request));
1446 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1447 CALL_FN_W_7W(err, fn, buf,count,datatype,source,tag,comm,request);
1448 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1449 if (err == MPI_SUCCESS) {
1450 make_mem_defined_if_addressable_untyped(request, sizeof(*request));
1451 add_shadow_Request( *request, buf,count,datatype );
1453 after("Irecv", err);
1454 return err;
1457 /* --- Wait --- */
1458 /* The MPI1 spec (imprecisely) defines 3 request states:
1459 - "null" if the request is MPI_REQUEST_NULL
1460 - "inactive" if not "null" and not associated with ongoing comms
1461 - "active" if not "null" and is associated with ongoing comms
1463 int WRAPPER_FOR(PMPI_Wait)( MPI_Request* request,
1464 MPI_Status* status )
1466 MPI_Request request_before;
1467 MPI_Status fake_status;
1468 OrigFn fn;
1469 int err;
1470 VALGRIND_GET_ORIG_FN(fn);
1471 before("Wait");
1472 if (isMSI(status))
1473 status = &fake_status;
1474 check_mem_is_addressable_untyped(status, sizeof(MPI_Status));
1475 check_mem_is_defined_untyped(request, sizeof(MPI_Request));
1476 request_before = *request;
1477 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1478 CALL_FN_W_WW(err, fn, request,status);
1479 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1480 if (err == MPI_SUCCESS) {
1481 maybe_complete(False/*err in status?*/,
1482 request_before, *request, status);
1483 make_mem_defined_if_addressable_untyped(status, sizeof(MPI_Status));
1485 after("Wait", err);
1486 return err;
1489 /* --- Waitany --- */
1490 int WRAPPER_FOR(PMPI_Waitany)( int count,
1491 MPI_Request* requests,
1492 int* index,
1493 MPI_Status* status )
1495 MPI_Request* requests_before = NULL;
1496 MPI_Status fake_status;
1497 OrigFn fn;
1498 int err, i;
1499 VALGRIND_GET_ORIG_FN(fn);
1500 before("Waitany");
1501 if (isMSI(status))
1502 status = &fake_status;
1503 if (0) fprintf(stderr, "Waitany: %d\n", count);
1504 check_mem_is_addressable_untyped(index, sizeof(int));
1505 check_mem_is_addressable_untyped(status, sizeof(MPI_Status));
1506 for (i = 0; i < count; i++) {
1507 check_mem_is_defined_untyped(&requests[i], sizeof(MPI_Request));
1509 requests_before = clone_Request_array( count, requests );
1510 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1511 CALL_FN_W_WWWW(err, fn, count,requests,index,status);
1512 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1513 if (err == MPI_SUCCESS && *index >= 0 && *index < count) {
1514 maybe_complete(False/*err in status?*/,
1515 requests_before[*index], requests[*index], status);
1516 make_mem_defined_if_addressable_untyped(status, sizeof(MPI_Status));
1518 if (requests_before)
1519 free(requests_before);
1520 after("Waitany", err);
1521 return err;
1524 /* --- Waitall --- */
1525 int WRAPPER_FOR(PMPI_Waitall)( int count,
1526 MPI_Request* requests,
1527 MPI_Status* statuses )
1529 MPI_Request* requests_before = NULL;
1530 OrigFn fn;
1531 int err, i;
1532 Bool free_sta = False;
1533 VALGRIND_GET_ORIG_FN(fn);
1534 before("Waitall");
1535 if (0) fprintf(stderr, "Waitall: %d\n", count);
1536 if (isMSI(statuses)) {
1537 free_sta = True;
1538 statuses = malloc( (count < 0 ? 0 : count) * sizeof(MPI_Status) );
1540 for (i = 0; i < count; i++) {
1541 check_mem_is_addressable_untyped(&statuses[i], sizeof(MPI_Status));
1542 check_mem_is_defined_untyped(&requests[i], sizeof(MPI_Request));
1544 requests_before = clone_Request_array( count, requests );
1545 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1546 CALL_FN_W_WWW(err, fn, count,requests,statuses);
1547 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1548 if (err == MPI_SUCCESS /*complete success*/
1549 || err == MPI_ERR_IN_STATUS /* partial success */) {
1550 Bool e_i_s = err == MPI_ERR_IN_STATUS;
1551 for (i = 0; i < count; i++) {
1552 maybe_complete(e_i_s, requests_before[i], requests[i],
1553 &statuses[i]);
1554 make_mem_defined_if_addressable_untyped(&statuses[i],
1555 sizeof(MPI_Status));
1558 if (requests_before)
1559 free(requests_before);
1560 if (free_sta)
1561 free(statuses);
1562 after("Waitall", err);
1563 return err;
1566 /* --- Test --- */
1567 /* nonblocking version of Wait */
1568 int WRAPPER_FOR(PMPI_Test)( MPI_Request* request, int* flag,
1569 MPI_Status* status )
1571 MPI_Request request_before;
1572 MPI_Status fake_status;
1573 OrigFn fn;
1574 int err;
1575 VALGRIND_GET_ORIG_FN(fn);
1576 before("Test");
1577 if (isMSI(status))
1578 status = &fake_status;
1579 check_mem_is_addressable_untyped(status, sizeof(MPI_Status));
1580 check_mem_is_addressable_untyped(flag, sizeof(int));
1581 check_mem_is_defined_untyped(request, sizeof(MPI_Request));
1582 request_before = *request;
1583 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1584 CALL_FN_W_WWW(err, fn, request,flag,status);
1585 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1586 if (err == MPI_SUCCESS && *flag) {
1587 maybe_complete(False/*err in status?*/,
1588 request_before, *request, status);
1589 make_mem_defined_if_addressable_untyped(status, sizeof(MPI_Status));
1591 after("Test", err);
1592 return err;
1595 /* --- Testall --- */
1596 /* nonblocking version of Waitall */
1597 int WRAPPER_FOR(PMPI_Testall)( int count, MPI_Request* requests,
1598 int* flag, MPI_Status* statuses )
1600 MPI_Request* requests_before = NULL;
1601 OrigFn fn;
1602 int err, i;
1603 Bool free_sta = False;
1604 VALGRIND_GET_ORIG_FN(fn);
1605 before("Testall");
1606 if (0) fprintf(stderr, "Testall: %d\n", count);
1607 if (isMSI(statuses)) {
1608 free_sta = True;
1609 statuses = malloc( (count < 0 ? 0 : count) * sizeof(MPI_Status) );
1611 check_mem_is_addressable_untyped(flag, sizeof(int));
1612 for (i = 0; i < count; i++) {
1613 check_mem_is_addressable_untyped(&statuses[i], sizeof(MPI_Status));
1614 check_mem_is_defined_untyped(&requests[i], sizeof(MPI_Request));
1616 requests_before = clone_Request_array( count, requests );
1617 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1618 CALL_FN_W_WWWW(err, fn, count,requests,flag,statuses);
1619 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1620 /* Urk. Is the following "if (...)" really right? I don't know. */
1621 if (*flag
1622 && (err == MPI_SUCCESS /*complete success*/
1623 || err == MPI_ERR_IN_STATUS /* partial success */)) {
1624 Bool e_i_s = err == MPI_ERR_IN_STATUS;
1625 for (i = 0; i < count; i++) {
1626 maybe_complete(e_i_s, requests_before[i], requests[i],
1627 &statuses[i]);
1628 make_mem_defined_if_addressable_untyped(&statuses[i],
1629 sizeof(MPI_Status));
1632 if (requests_before)
1633 free(requests_before);
1634 if (free_sta)
1635 free(statuses);
1636 after("Testall", err);
1637 return err;
1640 /* --- Iprobe --- */
1641 /* pre: must-be-writable: *flag, *status */
1642 /* post: make-readable *flag
1643 if *flag==True make-defined *status */
1644 int WRAPPER_FOR(PMPI_Iprobe)(int source, int tag,
1645 MPI_Comm comm,
1646 int* flag, MPI_Status* status)
1648 MPI_Status fake_status;
1649 OrigFn fn;
1650 int err;
1651 VALGRIND_GET_ORIG_FN(fn);
1652 before("Iprobe");
1653 if (isMSI(status))
1654 status = &fake_status;
1655 check_mem_is_addressable_untyped(flag, sizeof(*flag));
1656 check_mem_is_addressable_untyped(status, sizeof(*status));
1657 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1658 CALL_FN_W_5W(err, fn, source,tag,comm,flag,status);
1659 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1660 if (err == MPI_SUCCESS) {
1661 make_mem_defined_if_addressable_untyped(flag, sizeof(*flag));
1662 if (*flag)
1663 make_mem_defined_if_addressable_untyped(status, sizeof(*status));
1665 after("Iprobe", err);
1666 return err;
1669 /* --- Probe --- */
1670 /* pre: must-be-writable *status */
1671 /* post: make-defined *status */
1672 int WRAPPER_FOR(PMPI_Probe)(int source, int tag,
1673 MPI_Comm comm, MPI_Status* status)
1675 MPI_Status fake_status;
1676 OrigFn fn;
1677 int err;
1678 VALGRIND_GET_ORIG_FN(fn);
1679 before("Probe");
1680 if (isMSI(status))
1681 status = &fake_status;
1682 check_mem_is_addressable_untyped(status, sizeof(*status));
1683 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1684 CALL_FN_W_WWWW(err, fn, source,tag,comm,status);
1685 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1686 make_mem_defined_if_addressable_if_success_untyped(err, status, sizeof(*status));
1687 after("Probe", err);
1688 return err;
1691 /* --- Cancel --- */
1692 /* Wrapping PMPI_Cancel is interesting only to the extent that we need
1693 to be able to detect when a request should be removed from our
1694 shadow table due to cancellation. */
1695 int WRAPPER_FOR(PMPI_Cancel)(MPI_Request* request)
1697 OrigFn fn;
1698 int err;
1699 MPI_Request tmp;
1700 VALGRIND_GET_ORIG_FN(fn);
1701 before("Cancel");
1702 check_mem_is_addressable_untyped(request, sizeof(*request));
1703 tmp = *request;
1704 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1705 CALL_FN_W_W(err, fn, request);
1706 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1707 if (err == MPI_SUCCESS)
1708 delete_shadow_Request(tmp);
1709 after("Cancel", err);
1710 return err;
1714 /*------------------------------------------------------------*/
1715 /*--- ---*/
1716 /*--- Sec 3.10, Send-receive ---*/
1717 /*--- ---*/
1718 /*------------------------------------------------------------*/
1720 /* --- Sendrecv --- */
1721 /* pre: must be readable: (sendbuf,sendcount,sendtype)
1722 must be writable: (recvbuf,recvcount,recvtype)
1723 post: make readable: (recvbuf,recvcount_actual,datatype)
1724 where recvcount_actual is determined from *status
1726 int WRAPPER_FOR(PMPI_Sendrecv)(
1727 void *sendbuf, int sendcount, MPI_Datatype sendtype,
1728 int dest, int sendtag,
1729 void *recvbuf, int recvcount, MPI_Datatype recvtype,
1730 int source, int recvtag,
1731 MPI_Comm comm, MPI_Status *status)
1733 MPI_Status fake_status;
1734 OrigFn fn;
1735 int err, recvcount_actual = 0;
1736 VALGRIND_GET_ORIG_FN(fn);
1737 before("Sendrecv");
1738 if (isMSI(status))
1739 status = &fake_status;
1740 check_mem_is_defined(sendbuf, sendcount, sendtype);
1741 check_mem_is_addressable(recvbuf, recvcount, recvtype);
1742 check_mem_is_addressable_untyped(status, sizeof(*status));
1743 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1744 CALL_FN_W_12W(err, fn, sendbuf,sendcount,sendtype,dest,sendtag,
1745 recvbuf,recvcount,recvtype,source,recvtag,
1746 comm,status);
1747 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1748 make_mem_defined_if_addressable_if_success_untyped(err, status, sizeof(*status));
1749 if (err == MPI_SUCCESS
1750 && count_from_Status(&recvcount_actual,recvtype,status)) {
1751 make_mem_defined_if_addressable(recvbuf, recvcount_actual, recvtype);
1753 after("Sendrecv", err);
1754 return err;
1758 /*------------------------------------------------------------*/
1759 /*--- ---*/
1760 /*--- Sec 3.12, Derived datatypes ---*/
1761 /*--- ---*/
1762 /*------------------------------------------------------------*/
1764 /* --- Address --- */
1765 /* Does this have anything worth checking? */
1766 HAS_NO_WRAPPER(Address)
1768 /* --- MPI 2 stuff --- */
1769 /* Type_extent, Type_get_contents and Type_get_envelope sometimes get
1770 used intensively by the type walker (walk_type). There's no reason
1771 why they couldn't be properly wrapped if needed, but doing so slows
1772 everything down, so don't bother until needed. */
1773 HAS_NO_WRAPPER(Type_extent)
1774 HAS_NO_WRAPPER(Type_get_contents)
1775 HAS_NO_WRAPPER(Type_get_envelope)
1777 /* --- Type_commit --- */
1778 int WRAPPER_FOR(PMPI_Type_commit)( MPI_Datatype* ty )
1780 OrigFn fn;
1781 int err;
1782 VALGRIND_GET_ORIG_FN(fn);
1783 before("Type_commit");
1784 check_mem_is_defined_untyped(ty, sizeof(*ty));
1785 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1786 CALL_FN_W_W(err, fn, ty);
1787 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1788 after("Type_commit", err);
1789 return err;
1792 /* --- Type_free --- */
1793 int WRAPPER_FOR(PMPI_Type_free)( MPI_Datatype* ty )
1795 OrigFn fn;
1796 int err;
1797 VALGRIND_GET_ORIG_FN(fn);
1798 before("Type_free");
1799 check_mem_is_defined_untyped(ty, sizeof(*ty));
1800 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1801 CALL_FN_W_W(err, fn, ty);
1802 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1803 after("Type_free", err);
1804 return err;
1808 /*------------------------------------------------------------*/
1809 /*--- ---*/
1810 /*--- Sec 3.13, Pack and unpack ---*/
1811 /*--- ---*/
1812 /*------------------------------------------------------------*/
1814 /* --- Pack --- */
1815 /* pre: must be readable: position
1816 must be readable: (inbuf,incount,datatype)
1817 must be writable: outbuf[0 .. outsize-1]
1818 must be writable: outbuf[*position ..
1819 *position - 1
1820 + however much space PMPI_Pack_size
1821 says we will need]
1822 post: make readable: outbuf[old *position .. new *position]
1824 int WRAPPER_FOR(PMPI_Pack)( void* inbuf, int incount, MPI_Datatype datatype,
1825 void* outbuf, int outsize,
1826 int* position, MPI_Comm comm )
1828 OrigFn fn;
1829 int err, szB = 0;
1830 int position_ORIG = *position;
1831 VALGRIND_GET_ORIG_FN(fn);
1832 before("Pack");
1833 /* stay sane */
1834 check_mem_is_defined_untyped(position, sizeof(*position));
1835 /* check input */
1836 check_mem_is_defined(inbuf, incount, datatype);
1837 /* check output area's stated bounds make sense */
1838 check_mem_is_addressable_untyped(outbuf, outsize);
1839 /* check output area's actual used size properly */
1840 err = PMPI_Pack_size( incount, datatype, comm, &szB );
1841 if (err == MPI_SUCCESS && szB > 0) {
1842 check_mem_is_addressable_untyped(
1843 ((char*)outbuf) + position_ORIG, szB
1847 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1848 CALL_FN_W_7W(err, fn, inbuf,incount,datatype, outbuf,outsize,position, comm);
1849 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1851 if (err == MPI_SUCCESS && (*position) > position_ORIG) {
1852 /* paint output */
1853 make_mem_defined_if_addressable_untyped(
1854 ((char*)outbuf) + position_ORIG, *position - position_ORIG
1857 after("Pack", err);
1858 return err;
1861 /* --- Unpack --- */
1862 /* pre: must be readable: position
1863 must be writable: (outbuf,outcount,datatype)
1864 must be writable: outbuf[0 .. outsize-1]
1865 must be writable: outbuf[*position ..
1866 *position - 1
1867 + however much space PMPI_Pack_size
1868 says we will need]
1869 post: make readable: (outbuf,outcount,datatype)
1870 and also do a readability check of
1871 inbuf[old *position .. new *position]
1873 int WRAPPER_FOR(PMPI_Unpack)( void* inbuf, int insize, int* position,
1874 void* outbuf, int outcount, MPI_Datatype datatype,
1875 MPI_Comm comm )
1877 OrigFn fn;
1878 int err, szB = 0;
1879 int position_ORIG = *position;
1880 VALGRIND_GET_ORIG_FN(fn);
1881 before("Unpack");
1882 /* stay sane */
1883 check_mem_is_defined_untyped(position, sizeof(*position));
1884 /* check output area is accessible */
1885 check_mem_is_addressable(outbuf, outcount, datatype);
1886 /* check input area's stated bounds make sense */
1887 check_mem_is_addressable_untyped(inbuf, insize);
1888 /* check input area's actual used size properly */
1889 err = PMPI_Pack_size( outcount, datatype, comm, &szB );
1890 if (err == MPI_SUCCESS && szB > 0) {
1891 check_mem_is_addressable_untyped(
1892 ((char*)inbuf) + position_ORIG, szB
1896 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1897 CALL_FN_W_7W(err, fn, inbuf,insize,position, outbuf,outcount,datatype, comm);
1898 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1900 if (err == MPI_SUCCESS && (*position) > position_ORIG) {
1901 /* recheck input more carefully */
1902 check_mem_is_defined_untyped(
1903 ((char*)inbuf) + position_ORIG, *position - position_ORIG
1905 /* paint output */
1906 make_mem_defined_if_addressable( outbuf, outcount, datatype );
1908 after("Unpack", err);
1909 return err;
1913 /*------------------------------------------------------------*/
1914 /*--- ---*/
1915 /*--- Sec 4.4, Broadcast ---*/
1916 /*--- ---*/
1917 /*------------------------------------------------------------*/
1919 /* --- Bcast --- */
1920 /* pre: must-be-readable (buffer,count,datatype) for rank==root
1921 must-be-writable (buffer,count,datatype) for rank!=root
1922 post: make-readable (buffer,count,datatype) for all
1924 Resulting behaviour is: if root sends uninitialised stuff, then
1925 V complains, but then all ranks, including itself, see the buffer
1926 as initialised after that.
1928 int WRAPPER_FOR(PMPI_Bcast)(void *buffer, int count,
1929 MPI_Datatype datatype,
1930 int root, MPI_Comm comm)
1932 OrigFn fn;
1933 int err;
1934 Bool i_am_sender;
1935 VALGRIND_GET_ORIG_FN(fn);
1936 before("Bcast");
1937 i_am_sender = root == comm_rank(comm);
1938 if (i_am_sender) {
1939 check_mem_is_defined(buffer, count, datatype);
1940 } else {
1941 check_mem_is_addressable(buffer, count, datatype);
1943 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1944 CALL_FN_W_5W(err, fn, buffer,count,datatype,root,comm);
1945 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1946 make_mem_defined_if_addressable_if_success(err, buffer, count, datatype);
1947 after("Bcast", err);
1948 return err;
1952 /*------------------------------------------------------------*/
1953 /*--- ---*/
1954 /*--- Sec 4.5, Gather ---*/
1955 /*--- ---*/
1956 /*------------------------------------------------------------*/
1958 /* --- Gather --- */
1959 /* JRS 20060217: I don't really understand this. Each process is
1960 going to send sendcount items of type sendtype to the root. So
1961 the root is going to receive comm_size*sendcount items of type
1962 sendtype (right?) So why specify recvcount and recvtype?
1964 Anyway, assuming the MPI Spec is correct (seems likely :-) we have:
1966 pre: (all) must be readable: (sendbuf,sendcount,sendtype)
1967 (root only): must be writable: (recvbuf,recvcount * comm_size,recvtype)
1968 post: (root only): make readable: (recvbuf,recvcount * comm_size,recvtype)
1970 int WRAPPER_FOR(PMPI_Gather)(
1971 void *sendbuf, int sendcount, MPI_Datatype sendtype,
1972 void *recvbuf, int recvcount, MPI_Datatype recvtype,
1973 int root, MPI_Comm comm)
1975 OrigFn fn;
1976 int err, me, sz;
1977 VALGRIND_GET_ORIG_FN(fn);
1978 before("Gather");
1979 me = comm_rank(comm);
1980 sz = comm_size(comm);
1981 check_mem_is_defined(sendbuf, sendcount, sendtype);
1982 if (me == root)
1983 check_mem_is_addressable(recvbuf, recvcount * sz, recvtype);
1984 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1985 CALL_FN_W_8W(err, fn, sendbuf,sendcount,sendtype,
1986 recvbuf,recvcount,recvtype,
1987 root,comm);
1988 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1989 if (me == root)
1990 make_mem_defined_if_addressable_if_success(err, recvbuf, recvcount * sz, recvtype);
1991 after("Gather", err);
1992 return err;
1996 /*------------------------------------------------------------*/
1997 /*--- ---*/
1998 /*--- Sec 4.6, Scatter ---*/
1999 /*--- ---*/
2000 /*------------------------------------------------------------*/
2002 /* pre: (root only): must be readable: (sendbuf,sendcount * comm_size,sendtype)
2003 (all): must be writable: (recvbuf,recvbuf,recvtype)
2004 post: (all): make defined: (recvbuf,recvbuf,recvtype)
2006 int WRAPPER_FOR(PMPI_Scatter)(
2007 void* sendbuf, int sendcount, MPI_Datatype sendtype,
2008 void* recvbuf, int recvcount, MPI_Datatype recvtype,
2009 int root, MPI_Comm comm)
2011 OrigFn fn;
2012 int err, me, sz;
2013 VALGRIND_GET_ORIG_FN(fn);
2014 before("Scatter");
2015 me = comm_rank(comm);
2016 sz = comm_size(comm);
2017 check_mem_is_addressable(recvbuf, recvcount, recvtype);
2018 if (me == root)
2019 check_mem_is_defined(sendbuf, sendcount * sz, sendtype);
2020 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2021 CALL_FN_W_8W(err, fn, sendbuf,sendcount,sendtype,
2022 recvbuf,recvcount,recvtype,
2023 root,comm);
2024 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2025 make_mem_defined_if_addressable_if_success(err, recvbuf, recvcount, recvtype);
2026 after("Scatter", err);
2027 return err;
2031 /*------------------------------------------------------------*/
2032 /*--- ---*/
2033 /*--- Sec 4.8, All-to-All Scatter/Gather ---*/
2034 /*--- ---*/
2035 /*------------------------------------------------------------*/
2037 /* pre: (all) must be readable: (sendbuf,sendcount * comm_size,sendtype)
2038 (all) must be writable: (recvbuf,recvcount * comm_size,recvtype)
2039 post: (all) make defined: (recvbuf,recvcount * comm_size,recvtype)
2041 int WRAPPER_FOR(PMPI_Alltoall)(
2042 void* sendbuf, int sendcount, MPI_Datatype sendtype,
2043 void* recvbuf, int recvcount, MPI_Datatype recvtype,
2044 MPI_Comm comm)
2046 OrigFn fn;
2047 int err, sz;
2048 VALGRIND_GET_ORIG_FN(fn);
2049 before("Alltoall");
2050 sz = comm_size(comm);
2051 check_mem_is_defined(sendbuf, sendcount * sz, sendtype);
2052 check_mem_is_addressable(recvbuf, recvcount * sz, recvtype);
2053 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2054 CALL_FN_W_7W(err, fn, sendbuf,sendcount,sendtype,
2055 recvbuf,recvcount,recvtype,
2056 comm);
2057 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2058 make_mem_defined_if_addressable_if_success(err, recvbuf, recvcount * sz, recvtype);
2059 after("Alltoall", err);
2060 return err;
2064 /*------------------------------------------------------------*/
2065 /*--- ---*/
2066 /*--- Sec 4.9, Global Reduction Operations ---*/
2067 /*--- ---*/
2068 /*------------------------------------------------------------*/
2070 /* --- Reduce --- */
2071 /* rd: (sendbuf,count,datatype) for all
2072 wr: (recvbuf,count,datatype) but only for rank == root
2074 int WRAPPER_FOR(PMPI_Reduce)(void *sendbuf, void *recvbuf,
2075 int count,
2076 MPI_Datatype datatype, MPI_Op op,
2077 int root, MPI_Comm comm)
2079 OrigFn fn;
2080 int err;
2081 Bool i_am_root;
2082 VALGRIND_GET_ORIG_FN(fn);
2083 before("Reduce");
2084 i_am_root = root == comm_rank(comm);
2085 check_mem_is_defined(sendbuf, count, datatype);
2086 if (i_am_root)
2087 check_mem_is_addressable(recvbuf, count, datatype);
2088 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2089 CALL_FN_W_7W(err, fn, sendbuf,recvbuf,count,datatype,op,root,comm);
2090 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2091 if (i_am_root)
2092 make_mem_defined_if_addressable_if_success(err, recvbuf, count, datatype);
2093 after("Reduce", err);
2094 return err;
2098 /* --- Allreduce --- */
2099 /* rd: (sendbuf,count,datatype) for all
2100 wr: (recvbuf,count,datatype) for all
2102 int WRAPPER_FOR(PMPI_Allreduce)(void *sendbuf, void *recvbuf,
2103 int count,
2104 MPI_Datatype datatype, MPI_Op op,
2105 MPI_Comm comm)
2107 OrigFn fn;
2108 int err;
2109 VALGRIND_GET_ORIG_FN(fn);
2110 before("Allreduce");
2111 check_mem_is_defined(sendbuf, count, datatype);
2112 check_mem_is_addressable(recvbuf, count, datatype);
2113 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2114 CALL_FN_W_6W(err, fn, sendbuf,recvbuf,count,datatype,op,comm);
2115 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2116 make_mem_defined_if_addressable_if_success(err, recvbuf, count, datatype);
2117 after("Allreduce", err);
2118 return err;
2122 /* --- Op_create --- */
2123 /* This is a bit dubious. I suppose it takes 'function' and
2124 writes something at *op, but who knows what an MPI_Op is?
2125 Can we safely do 'sizeof' on it? */
2126 int WRAPPER_FOR(PMPI_Op_create)( MPI_User_function* function,
2127 int commute,
2128 MPI_Op* op )
2130 OrigFn fn;
2131 int err;
2132 VALGRIND_GET_ORIG_FN(fn);
2133 before("Op_create");
2134 check_mem_is_addressable_untyped(op, sizeof(*op));
2135 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2136 CALL_FN_W_WWW(err, fn, function,commute,op);
2137 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2138 make_mem_defined_if_addressable_if_success_untyped(err, op, sizeof(*op));
2139 after("Op_create", err);
2140 return err;
2144 /*------------------------------------------------------------*/
2145 /*--- ---*/
2146 /*--- Sec 5.4, Communicator management ---*/
2147 /*--- ---*/
2148 /*------------------------------------------------------------*/
2150 /* Hardly seems worth wrapping Comm_rank and Comm_size, but
2151 since it's done now .. */
2153 /* --- Comm_create --- */
2154 /* Let normal memcheck tracking handle this. */
2155 int WRAPPER_FOR(PMPI_Comm_create)(MPI_Comm comm, MPI_Group group,
2156 MPI_Comm* newcomm)
2158 OrigFn fn;
2159 int err;
2160 VALGRIND_GET_ORIG_FN(fn);
2161 before("Comm_create");
2162 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2163 CALL_FN_W_WWW(err, fn, comm,group,newcomm);
2164 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2165 after("Comm_create", err);
2166 return err;
2169 /* --- Comm_dup --- */
2170 /* Let normal memcheck tracking handle this. */
2171 int WRAPPER_FOR(PMPI_Comm_dup)(MPI_Comm comm, MPI_Comm* newcomm)
2173 OrigFn fn;
2174 int err;
2175 VALGRIND_GET_ORIG_FN(fn);
2176 before("Comm_dup");
2177 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2178 CALL_FN_W_WW(err, fn, comm,newcomm);
2179 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2180 after("Comm_dup", err);
2181 return err;
2184 /* --- Comm_free --- */
2185 /* Let normal memcheck tracking handle this. */
2186 int WRAPPER_FOR(PMPI_Comm_free)(MPI_Comm* comm)
2188 OrigFn fn;
2189 int err;
2190 VALGRIND_GET_ORIG_FN(fn);
2191 before("Comm_free");
2192 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2193 CALL_FN_W_W(err, fn, comm);
2194 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2195 after("Comm_free", err);
2196 return err;
2199 /* --- Comm_rank --- */
2200 /* wr: (rank, sizeof(*rank)) */
2201 int WRAPPER_FOR(PMPI_Comm_rank)(MPI_Comm comm, int *rank)
2203 OrigFn fn;
2204 int err;
2205 VALGRIND_GET_ORIG_FN(fn);
2206 before("Comm_rank");
2207 check_mem_is_addressable_untyped(rank, sizeof(*rank));
2208 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2209 CALL_FN_W_WW(err, fn, comm,rank);
2210 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2211 make_mem_defined_if_addressable_if_success_untyped(err, rank, sizeof(*rank));
2212 after("Comm_rank", err);
2213 return err;
2216 /* --- Comm_size --- */
2217 /* wr: (size, sizeof(*size)) */
2218 int WRAPPER_FOR(PMPI_Comm_size)(MPI_Comm comm, int *size)
2220 OrigFn fn;
2221 int err;
2222 VALGRIND_GET_ORIG_FN(fn);
2223 before("Comm_size");
2224 check_mem_is_addressable_untyped(size, sizeof(*size));
2225 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2226 CALL_FN_W_WW(err, fn, comm,size);
2227 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2228 make_mem_defined_if_addressable_if_success_untyped(err, size, sizeof(*size));
2229 after("Comm_size", err);
2230 return err;
2234 /*------------------------------------------------------------*/
2235 /*--- ---*/
2236 /*--- Sec 5.7, Caching ---*/
2237 /*--- ---*/
2238 /*------------------------------------------------------------*/
2241 /*------------------------------------------------------------*/
2242 /*--- ---*/
2243 /*--- Sec 7.3, Error codes and classes ---*/
2244 /*--- ---*/
2245 /*------------------------------------------------------------*/
2247 /* --- Error_string --- */
2248 int WRAPPER_FOR(PMPI_Error_string)( int errorcode, char* string,
2249 int* resultlen )
2251 OrigFn fn;
2252 int err;
2253 VALGRIND_GET_ORIG_FN(fn);
2254 before("Error_string");
2255 check_mem_is_addressable_untyped(resultlen, sizeof(int));
2256 check_mem_is_addressable_untyped(string, MPI_MAX_ERROR_STRING);
2257 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2258 CALL_FN_W_WWW(err, fn, errorcode,string,resultlen);
2259 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2260 /* Don't bother to paint the result; we assume the real function
2261 will have filled it with defined characters :-) */
2262 after("Error_string", err);
2263 return err;
2267 /*------------------------------------------------------------*/
2268 /*--- ---*/
2269 /*--- Sec 7.5, Startup ---*/
2270 /*--- ---*/
2271 /*------------------------------------------------------------*/
2273 /* --- Init --- */
2274 /* rd: *argc, *argv[0 .. *argc-1] */
2275 long WRAPPER_FOR(PMPI_Init)(int *argc, char ***argv)
2277 OrigFn fn;
2278 int err;
2279 VALGRIND_GET_ORIG_FN(fn);
2280 before("Init");
2281 if (argc) {
2282 check_mem_is_defined_untyped(argc, sizeof(int));
2284 if (argc && argv) {
2285 check_mem_is_defined_untyped(*argv, *argc * sizeof(char**));
2287 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2288 CALL_FN_W_WW(err, fn, argc,argv);
2289 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2290 after("Init", err);
2291 if (opt_initkludge)
2292 return (long)(void*)&mpiwrap_walk_type_EXTERNALLY_VISIBLE;
2293 else
2294 return (long)err;
2297 /* --- Initialized --- */
2298 int WRAPPER_FOR(PMPI_Initialized)(int* flag)
2300 OrigFn fn;
2301 int err;
2302 VALGRIND_GET_ORIG_FN(fn);
2303 before("Initialized");
2304 check_mem_is_addressable_untyped(flag, sizeof(int));
2305 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2306 CALL_FN_W_W(err, fn, flag);
2307 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2308 make_mem_defined_if_addressable_if_success_untyped(err, flag, sizeof(int));
2309 after("Initialized", err);
2310 return err;
2313 /* --- Finalize --- */
2314 int WRAPPER_FOR(PMPI_Finalize)(void)
2316 OrigFn fn;
2317 int err;
2318 VALGRIND_GET_ORIG_FN(fn);
2319 before("Finalize");
2320 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2321 CALL_FN_W_v(err, fn);
2322 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2323 after("Finalize", err);
2324 return err;
2328 /*------------------------------------------------------------*/
2329 /*--- ---*/
2330 /*--- Default wrappers for all remaining functions ---*/
2331 /*--- ---*/
2332 /*------------------------------------------------------------*/
2334 /* Boilerplate for default wrappers. */
2335 #define DEFAULT_WRAPPER_PREAMBLE(basename) \
2336 OrigFn fn; \
2337 UWord res; \
2338 static int complaints = 1; \
2339 VALGRIND_GET_ORIG_FN(fn); \
2340 before(#basename); \
2341 if (opt_missing >= 2) { \
2342 barf("no wrapper for PMPI_" #basename \
2343 ",\n\t\t\t and you have " \
2344 "requested strict checking"); \
2346 if (opt_missing == 1 && complaints > 0) { \
2347 fprintf(stderr, "%s %5d: warning: no wrapper " \
2348 "for PMPI_" #basename "\n", \
2349 preamble, my_pid); \
2350 complaints--; \
2353 #define DEFAULT_WRAPPER_W_0W(basename) \
2354 UWord WRAPPER_FOR(PMPI_##basename)( void ) \
2356 DEFAULT_WRAPPER_PREAMBLE(basename) \
2357 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2358 CALL_FN_W_v(res, fn); \
2359 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2360 return res; \
2363 #define DEFAULT_WRAPPER_W_1W(basename) \
2364 UWord WRAPPER_FOR(PMPI_##basename)( UWord a1 ) \
2366 DEFAULT_WRAPPER_PREAMBLE(basename) \
2367 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2368 CALL_FN_W_W(res, fn, a1); \
2369 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2370 return res; \
2373 #define DEFAULT_WRAPPER_W_2W(basename) \
2374 UWord WRAPPER_FOR(PMPI_##basename)( UWord a1, UWord a2 ) \
2376 DEFAULT_WRAPPER_PREAMBLE(basename) \
2377 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2378 CALL_FN_W_WW(res, fn, a1,a2); \
2379 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2380 return res; \
2383 #define DEFAULT_WRAPPER_W_3W(basename) \
2384 UWord WRAPPER_FOR(PMPI_##basename) \
2385 ( UWord a1, UWord a2, UWord a3 ) \
2387 DEFAULT_WRAPPER_PREAMBLE(basename) \
2388 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2389 CALL_FN_W_WWW(res, fn, a1,a2,a3); \
2390 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2391 return res; \
2394 #define DEFAULT_WRAPPER_W_4W(basename) \
2395 UWord WRAPPER_FOR(PMPI_##basename) \
2396 ( UWord a1, UWord a2, UWord a3, UWord a4 ) \
2398 DEFAULT_WRAPPER_PREAMBLE(basename) \
2399 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2400 CALL_FN_W_WWWW(res, fn, a1,a2,a3,a4); \
2401 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2402 return res; \
2405 #define DEFAULT_WRAPPER_W_5W(basename) \
2406 UWord WRAPPER_FOR(PMPI_##basename) \
2407 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5 ) \
2409 DEFAULT_WRAPPER_PREAMBLE(basename) \
2410 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2411 CALL_FN_W_5W(res, fn, a1,a2,a3,a4,a5); \
2412 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2413 return res; \
2416 #define DEFAULT_WRAPPER_W_6W(basename) \
2417 UWord WRAPPER_FOR(PMPI_##basename) \
2418 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2419 UWord a6 ) \
2421 DEFAULT_WRAPPER_PREAMBLE(basename) \
2422 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2423 CALL_FN_W_6W(res, fn, a1,a2,a3,a4,a5,a6); \
2424 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2425 return res; \
2428 #define DEFAULT_WRAPPER_W_7W(basename) \
2429 UWord WRAPPER_FOR(PMPI_##basename) \
2430 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2431 UWord a6, UWord a7 ) \
2433 DEFAULT_WRAPPER_PREAMBLE(basename) \
2434 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2435 CALL_FN_W_7W(res, fn, a1,a2,a3,a4,a5,a6,a7); \
2436 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2437 return res; \
2440 #define DEFAULT_WRAPPER_W_8W(basename) \
2441 UWord WRAPPER_FOR(PMPI_##basename) \
2442 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2443 UWord a6, UWord a7, UWord a8 ) \
2445 DEFAULT_WRAPPER_PREAMBLE(basename) \
2446 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2447 CALL_FN_W_8W(res, fn, a1,a2,a3,a4,a5,a6,a7,a8); \
2448 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2449 return res; \
2452 #define DEFAULT_WRAPPER_W_9W(basename) \
2453 UWord WRAPPER_FOR(PMPI_##basename) \
2454 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2455 UWord a6, UWord a7, UWord a8, UWord a9 ) \
2457 DEFAULT_WRAPPER_PREAMBLE(basename) \
2458 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2459 CALL_FN_W_9W(res, fn, a1,a2,a3,a4,a5,a6,a7,a8,a9); \
2460 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2461 return res; \
2464 #define DEFAULT_WRAPPER_W_10W(basename) \
2465 UWord WRAPPER_FOR(PMPI_##basename) \
2466 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2467 UWord a6, UWord a7, UWord a8, UWord a9, UWord a10 ) \
2469 DEFAULT_WRAPPER_PREAMBLE(basename) \
2470 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2471 CALL_FN_W_10W(res, fn, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10); \
2472 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2473 return res; \
2476 #define DEFAULT_WRAPPER_W_12W(basename) \
2477 UWord WRAPPER_FOR(PMPI_##basename) \
2478 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2479 UWord a6, UWord a7, UWord a8, UWord a9, UWord a10, \
2480 UWord a11, UWord a12 ) \
2482 DEFAULT_WRAPPER_PREAMBLE(basename) \
2483 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2484 CALL_FN_W_12W(res, fn, a1,a2,a3,a4,a5,a6, \
2485 a7,a8,a9,a10,a11,a12); \
2486 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2487 return res; \
2491 /* Canned summary of MPI-1.1/MPI-2 entry points, as derived from mpi.h
2492 from Open MPI svn rev 9191 (somewhere between Open MPI versions
2493 1.0.1 and 1.1.0). */
2495 /* If a function is commented out in this list, it's because it has a
2496 proper wrapper written elsewhere (above here). */
2498 DEFAULT_WRAPPER_W_2W(Abort)
2499 DEFAULT_WRAPPER_W_9W(Accumulate)
2500 DEFAULT_WRAPPER_W_1W(Add_error_class)
2501 DEFAULT_WRAPPER_W_2W(Add_error_code)
2502 DEFAULT_WRAPPER_W_2W(Add_error_string)
2503 /* DEFAULT_WRAPPER_W_2W(Address) */
2504 DEFAULT_WRAPPER_W_7W(Allgather)
2505 DEFAULT_WRAPPER_W_8W(Allgatherv)
2506 DEFAULT_WRAPPER_W_3W(Alloc_mem)
2507 /* DEFAULT_WRAPPER_W_6W(Allreduce) */
2508 /* DEFAULT_WRAPPER_W_7W(Alltoall) */
2509 DEFAULT_WRAPPER_W_9W(Alltoallv)
2510 DEFAULT_WRAPPER_W_9W(Alltoallw)
2511 DEFAULT_WRAPPER_W_2W(Attr_delete)
2512 DEFAULT_WRAPPER_W_4W(Attr_get)
2513 DEFAULT_WRAPPER_W_3W(Attr_put)
2514 DEFAULT_WRAPPER_W_1W(Barrier)
2515 /* DEFAULT_WRAPPER_W_5W(Bcast) */
2516 /* DEFAULT_WRAPPER_W_6W(Bsend) */
2517 DEFAULT_WRAPPER_W_7W(Bsend_init)
2518 DEFAULT_WRAPPER_W_2W(Buffer_attach)
2519 DEFAULT_WRAPPER_W_2W(Buffer_detach)
2520 /* DEFAULT_WRAPPER_W_1W(Cancel) */
2521 DEFAULT_WRAPPER_W_4W(Cart_coords)
2522 DEFAULT_WRAPPER_W_6W(Cart_create)
2523 DEFAULT_WRAPPER_W_5W(Cart_get)
2524 DEFAULT_WRAPPER_W_5W(Cart_map)
2525 DEFAULT_WRAPPER_W_3W(Cart_rank)
2526 DEFAULT_WRAPPER_W_5W(Cart_shift)
2527 DEFAULT_WRAPPER_W_3W(Cart_sub)
2528 DEFAULT_WRAPPER_W_2W(Cartdim_get)
2529 DEFAULT_WRAPPER_W_1W(Close_port)
2530 DEFAULT_WRAPPER_W_5W(Comm_accept)
2531 DEFAULT_WRAPPER_W_1W(Comm_c2f)
2532 DEFAULT_WRAPPER_W_2W(Comm_call_errhandler)
2533 DEFAULT_WRAPPER_W_3W(Comm_compare)
2534 DEFAULT_WRAPPER_W_5W(Comm_connect)
2535 DEFAULT_WRAPPER_W_2W(Comm_create_errhandler)
2536 DEFAULT_WRAPPER_W_4W(Comm_create_keyval)
2537 /* DEFAULT_WRAPPER_W_3W(Comm_create) */
2538 DEFAULT_WRAPPER_W_2W(Comm_delete_attr)
2539 DEFAULT_WRAPPER_W_1W(Comm_disconnect)
2540 /* DEFAULT_WRAPPER_W_2W(Comm_dup) */
2541 DEFAULT_WRAPPER_W_1W(Comm_f2c)
2542 DEFAULT_WRAPPER_W_1W(Comm_free_keyval)
2543 /* DEFAULT_WRAPPER_W_1W(Comm_free) */
2544 DEFAULT_WRAPPER_W_4W(Comm_get_attr)
2545 DEFAULT_WRAPPER_W_2W(Comm_get_errhandler)
2546 DEFAULT_WRAPPER_W_3W(Comm_get_name)
2547 DEFAULT_WRAPPER_W_1W(Comm_get_parent)
2548 DEFAULT_WRAPPER_W_2W(Comm_group)
2549 DEFAULT_WRAPPER_W_2W(Comm_join)
2550 /* DEFAULT_WRAPPER_W_2W(Comm_rank) */
2551 DEFAULT_WRAPPER_W_2W(Comm_remote_group)
2552 DEFAULT_WRAPPER_W_2W(Comm_remote_size)
2553 DEFAULT_WRAPPER_W_3W(Comm_set_attr)
2554 DEFAULT_WRAPPER_W_2W(Comm_set_errhandler)
2555 DEFAULT_WRAPPER_W_2W(Comm_set_name)
2556 /* DEFAULT_WRAPPER_W_2W(Comm_size) */
2557 DEFAULT_WRAPPER_W_8W(Comm_spawn)
2558 DEFAULT_WRAPPER_W_9W(Comm_spawn_multiple)
2559 DEFAULT_WRAPPER_W_4W(Comm_split)
2560 DEFAULT_WRAPPER_W_2W(Comm_test_inter)
2561 DEFAULT_WRAPPER_W_3W(Dims_create)
2562 DEFAULT_WRAPPER_W_1W(Errhandler_c2f)
2563 DEFAULT_WRAPPER_W_2W(Errhandler_create)
2564 DEFAULT_WRAPPER_W_1W(Errhandler_f2c)
2565 DEFAULT_WRAPPER_W_1W(Errhandler_free)
2566 DEFAULT_WRAPPER_W_2W(Errhandler_get)
2567 DEFAULT_WRAPPER_W_2W(Errhandler_set)
2568 DEFAULT_WRAPPER_W_2W(Error_class)
2569 /* DEFAULT_WRAPPER_W_3W(Error_string) */
2570 DEFAULT_WRAPPER_W_6W(Exscan)
2571 DEFAULT_WRAPPER_W_1W(File_c2f)
2572 DEFAULT_WRAPPER_W_1W(File_f2c)
2573 DEFAULT_WRAPPER_W_2W(File_call_errhandler)
2574 DEFAULT_WRAPPER_W_2W(File_create_errhandler)
2575 DEFAULT_WRAPPER_W_2W(File_set_errhandler)
2576 DEFAULT_WRAPPER_W_2W(File_get_errhandler)
2577 DEFAULT_WRAPPER_W_5W(File_open)
2578 DEFAULT_WRAPPER_W_1W(File_close)
2579 DEFAULT_WRAPPER_W_2W(File_delete)
2580 DEFAULT_WRAPPER_W_2W(File_set_size)
2581 DEFAULT_WRAPPER_W_2W(File_preallocate)
2582 DEFAULT_WRAPPER_W_2W(File_get_size)
2583 DEFAULT_WRAPPER_W_2W(File_get_group)
2584 DEFAULT_WRAPPER_W_2W(File_get_amode)
2585 DEFAULT_WRAPPER_W_2W(File_set_info)
2586 DEFAULT_WRAPPER_W_2W(File_get_info)
2587 DEFAULT_WRAPPER_W_6W(File_set_view)
2588 DEFAULT_WRAPPER_W_5W(File_get_view)
2589 DEFAULT_WRAPPER_W_6W(File_read_at)
2590 DEFAULT_WRAPPER_W_6W(File_read_at_all)
2591 DEFAULT_WRAPPER_W_6W(File_write_at)
2592 DEFAULT_WRAPPER_W_6W(File_write_at_all)
2593 DEFAULT_WRAPPER_W_6W(File_iread_at)
2594 DEFAULT_WRAPPER_W_6W(File_iwrite_at)
2595 DEFAULT_WRAPPER_W_5W(File_read)
2596 DEFAULT_WRAPPER_W_5W(File_read_all)
2597 DEFAULT_WRAPPER_W_5W(File_write)
2598 DEFAULT_WRAPPER_W_5W(File_write_all)
2599 DEFAULT_WRAPPER_W_5W(File_iread)
2600 DEFAULT_WRAPPER_W_5W(File_iwrite)
2601 DEFAULT_WRAPPER_W_3W(File_seek)
2602 DEFAULT_WRAPPER_W_2W(File_get_position)
2603 DEFAULT_WRAPPER_W_3W(File_get_byte_offset)
2604 DEFAULT_WRAPPER_W_5W(File_read_shared)
2605 DEFAULT_WRAPPER_W_5W(File_write_shared)
2606 DEFAULT_WRAPPER_W_5W(File_iread_shared)
2607 DEFAULT_WRAPPER_W_5W(File_iwrite_shared)
2608 DEFAULT_WRAPPER_W_5W(File_read_ordered)
2609 DEFAULT_WRAPPER_W_5W(File_write_ordered)
2610 DEFAULT_WRAPPER_W_3W(File_seek_shared)
2611 DEFAULT_WRAPPER_W_2W(File_get_position_shared)
2612 DEFAULT_WRAPPER_W_5W(File_read_at_all_begin)
2613 DEFAULT_WRAPPER_W_3W(File_read_at_all_end)
2614 DEFAULT_WRAPPER_W_5W(File_write_at_all_begin)
2615 DEFAULT_WRAPPER_W_3W(File_write_at_all_end)
2616 DEFAULT_WRAPPER_W_4W(File_read_all_begin)
2617 DEFAULT_WRAPPER_W_3W(File_read_all_end)
2618 DEFAULT_WRAPPER_W_4W(File_write_all_begin)
2619 DEFAULT_WRAPPER_W_3W(File_write_all_end)
2620 DEFAULT_WRAPPER_W_4W(File_read_ordered_begin)
2621 DEFAULT_WRAPPER_W_3W(File_read_ordered_end)
2622 DEFAULT_WRAPPER_W_4W(File_write_ordered_begin)
2623 DEFAULT_WRAPPER_W_3W(File_write_ordered_end)
2624 DEFAULT_WRAPPER_W_3W(File_get_type_extent)
2625 DEFAULT_WRAPPER_W_2W(File_set_atomicity)
2626 DEFAULT_WRAPPER_W_2W(File_get_atomicity)
2627 DEFAULT_WRAPPER_W_1W(File_sync)
2628 /* DEFAULT_WRAPPER_W_0W(Finalize) */
2629 DEFAULT_WRAPPER_W_1W(Finalized)
2630 DEFAULT_WRAPPER_W_1W(Free_mem)
2631 /* DEFAULT_WRAPPER_W_8W(Gather) */
2632 DEFAULT_WRAPPER_W_9W(Gatherv)
2633 DEFAULT_WRAPPER_W_2W(Get_address)
2634 /* DEFAULT_WRAPPER_W_3W(Get_count) */
2635 DEFAULT_WRAPPER_W_3W(Get_elements)
2636 DEFAULT_WRAPPER_W_8W(Get)
2637 DEFAULT_WRAPPER_W_2W(Get_processor_name)
2638 DEFAULT_WRAPPER_W_2W(Get_version)
2639 DEFAULT_WRAPPER_W_6W(Graph_create)
2640 DEFAULT_WRAPPER_W_5W(Graph_get)
2641 DEFAULT_WRAPPER_W_5W(Graph_map)
2642 DEFAULT_WRAPPER_W_3W(Graph_neighbors_count)
2643 DEFAULT_WRAPPER_W_4W(Graph_neighbors)
2644 DEFAULT_WRAPPER_W_3W(Graphdims_get)
2645 DEFAULT_WRAPPER_W_1W(Grequest_complete)
2646 DEFAULT_WRAPPER_W_5W(Grequest_start)
2647 DEFAULT_WRAPPER_W_1W(Group_c2f)
2648 DEFAULT_WRAPPER_W_3W(Group_compare)
2649 DEFAULT_WRAPPER_W_3W(Group_difference)
2650 DEFAULT_WRAPPER_W_4W(Group_excl)
2651 DEFAULT_WRAPPER_W_1W(Group_f2c)
2652 DEFAULT_WRAPPER_W_1W(Group_free)
2653 DEFAULT_WRAPPER_W_4W(Group_incl)
2654 DEFAULT_WRAPPER_W_3W(Group_intersection)
2655 DEFAULT_WRAPPER_W_4W(Group_range_excl)
2656 DEFAULT_WRAPPER_W_4W(Group_range_incl)
2657 DEFAULT_WRAPPER_W_2W(Group_rank)
2658 DEFAULT_WRAPPER_W_2W(Group_size)
2659 DEFAULT_WRAPPER_W_5W(Group_translate_ranks)
2660 DEFAULT_WRAPPER_W_3W(Group_union)
2661 /* DEFAULT_WRAPPER_W_7W(Ibsend) */
2662 DEFAULT_WRAPPER_W_1W(Info_c2f)
2663 DEFAULT_WRAPPER_W_1W(Info_create)
2664 DEFAULT_WRAPPER_W_2W(Info_delete)
2665 DEFAULT_WRAPPER_W_2W(Info_dup)
2666 DEFAULT_WRAPPER_W_1W(Info_f2c)
2667 DEFAULT_WRAPPER_W_1W(Info_free)
2668 DEFAULT_WRAPPER_W_5W(Info_get)
2669 DEFAULT_WRAPPER_W_2W(Info_get_nkeys)
2670 DEFAULT_WRAPPER_W_3W(Info_get_nthkey)
2671 DEFAULT_WRAPPER_W_4W(Info_get_valuelen)
2672 DEFAULT_WRAPPER_W_3W(Info_set)
2673 /* DEFAULT_WRAPPER_W_2W(Init) */
2674 /* DEFAULT_WRAPPER_W_1W(Initialized) */
2675 DEFAULT_WRAPPER_W_4W(Init_thread)
2676 DEFAULT_WRAPPER_W_6W(Intercomm_create)
2677 DEFAULT_WRAPPER_W_3W(Intercomm_merge)
2678 /* DEFAULT_WRAPPER_W_5W(Iprobe) */
2679 /* DEFAULT_WRAPPER_W_7W(Irecv) */
2680 /* DEFAULT_WRAPPER_W_7W(Irsend) */
2681 /* DEFAULT_WRAPPER_W_7W(Isend) */
2682 /* DEFAULT_WRAPPER_W_7W(Issend) */
2683 DEFAULT_WRAPPER_W_1W(Is_thread_main)
2684 DEFAULT_WRAPPER_W_4W(Keyval_create)
2685 DEFAULT_WRAPPER_W_1W(Keyval_free)
2686 DEFAULT_WRAPPER_W_3W(Lookup_name)
2687 DEFAULT_WRAPPER_W_1W(Op_c2f)
2688 /* DEFAULT_WRAPPER_W_3W(Op_create) */
2689 DEFAULT_WRAPPER_W_2W(Open_port)
2690 DEFAULT_WRAPPER_W_1W(Op_f2c)
2691 DEFAULT_WRAPPER_W_1W(Op_free)
2692 DEFAULT_WRAPPER_W_7W(Pack_external)
2693 DEFAULT_WRAPPER_W_4W(Pack_external_size)
2694 /* DEFAULT_WRAPPER_W_7W(Pack) */
2695 DEFAULT_WRAPPER_W_4W(Pack_size)
2696 /* int MPI_Pcontrol(const int level, ...) */
2697 /* DEFAULT_WRAPPER_W_4W(Probe) */
2698 DEFAULT_WRAPPER_W_3W(Publish_name)
2699 DEFAULT_WRAPPER_W_8W(Put)
2700 DEFAULT_WRAPPER_W_1W(Query_thread)
2701 DEFAULT_WRAPPER_W_7W(Recv_init)
2702 /* DEFAULT_WRAPPER_W_7W(Recv) */
2703 /* DEFAULT_WRAPPER_W_7W(Reduce) */
2704 DEFAULT_WRAPPER_W_6W(Reduce_scatter)
2705 DEFAULT_WRAPPER_W_5W(Register_datarep)
2706 DEFAULT_WRAPPER_W_1W(Request_c2f)
2707 DEFAULT_WRAPPER_W_1W(Request_f2c)
2708 DEFAULT_WRAPPER_W_1W(Request_free)
2709 DEFAULT_WRAPPER_W_3W(Request_get_status)
2710 /* DEFAULT_WRAPPER_W_6W(Rsend) */
2711 DEFAULT_WRAPPER_W_7W(Rsend_init)
2712 DEFAULT_WRAPPER_W_6W(Scan)
2713 /* DEFAULT_WRAPPER_W_8W(Scatter) */
2714 DEFAULT_WRAPPER_W_9W(Scatterv)
2715 DEFAULT_WRAPPER_W_7W(Send_init)
2716 /* DEFAULT_WRAPPER_W_6W(Send) */
2717 /* DEFAULT_WRAPPER_W_12W(Sendrecv) */
2718 DEFAULT_WRAPPER_W_9W(Sendrecv_replace)
2719 DEFAULT_WRAPPER_W_7W(Ssend_init)
2720 /* DEFAULT_WRAPPER_W_6W(Ssend) */
2721 DEFAULT_WRAPPER_W_1W(Start)
2722 DEFAULT_WRAPPER_W_2W(Startall)
2723 DEFAULT_WRAPPER_W_2W(Status_c2f)
2724 DEFAULT_WRAPPER_W_2W(Status_f2c)
2725 DEFAULT_WRAPPER_W_2W(Status_set_cancelled)
2726 DEFAULT_WRAPPER_W_3W(Status_set_elements)
2727 /* DEFAULT_WRAPPER_W_4W(Testall) */
2728 DEFAULT_WRAPPER_W_5W(Testany)
2729 /* DEFAULT_WRAPPER_W_3W(Test) */
2730 DEFAULT_WRAPPER_W_2W(Test_cancelled)
2731 DEFAULT_WRAPPER_W_5W(Testsome)
2732 DEFAULT_WRAPPER_W_2W(Topo_test)
2733 DEFAULT_WRAPPER_W_1W(Type_c2f)
2734 /* DEFAULT_WRAPPER_W_1W(Type_commit) */
2735 DEFAULT_WRAPPER_W_3W(Type_contiguous)
2736 DEFAULT_WRAPPER_W_10W(Type_create_darray)
2737 DEFAULT_WRAPPER_W_3W(Type_create_f90_complex)
2738 DEFAULT_WRAPPER_W_2W(Type_create_f90_integer)
2739 DEFAULT_WRAPPER_W_3W(Type_create_f90_real)
2740 DEFAULT_WRAPPER_W_5W(Type_create_hindexed)
2741 DEFAULT_WRAPPER_W_5W(Type_create_hvector)
2742 DEFAULT_WRAPPER_W_4W(Type_create_keyval)
2743 DEFAULT_WRAPPER_W_5W(Type_create_indexed_block)
2744 DEFAULT_WRAPPER_W_5W(Type_create_struct)
2745 DEFAULT_WRAPPER_W_7W(Type_create_subarray)
2746 DEFAULT_WRAPPER_W_4W(Type_create_resized)
2747 DEFAULT_WRAPPER_W_2W(Type_delete_attr)
2748 DEFAULT_WRAPPER_W_2W(Type_dup)
2749 /* DEFAULT_WRAPPER_W_2W(Type_extent) */
2750 /* DEFAULT_WRAPPER_W_1W(Type_free) */
2751 DEFAULT_WRAPPER_W_1W(Type_free_keyval)
2752 DEFAULT_WRAPPER_W_1W(Type_f2c)
2753 DEFAULT_WRAPPER_W_4W(Type_get_attr)
2754 /* DEFAULT_WRAPPER_W_7W(Type_get_contents) */
2755 /* DEFAULT_WRAPPER_W_5W(Type_get_envelope) */
2756 DEFAULT_WRAPPER_W_3W(Type_get_extent)
2757 DEFAULT_WRAPPER_W_3W(Type_get_name)
2758 DEFAULT_WRAPPER_W_3W(Type_get_true_extent)
2759 DEFAULT_WRAPPER_W_5W(Type_hindexed)
2760 DEFAULT_WRAPPER_W_5W(Type_hvector)
2761 DEFAULT_WRAPPER_W_5W(Type_indexed)
2762 DEFAULT_WRAPPER_W_2W(Type_lb)
2763 DEFAULT_WRAPPER_W_3W(Type_match_size)
2764 DEFAULT_WRAPPER_W_3W(Type_set_attr)
2765 DEFAULT_WRAPPER_W_2W(Type_set_name)
2766 DEFAULT_WRAPPER_W_2W(Type_size)
2767 DEFAULT_WRAPPER_W_5W(Type_struct)
2768 DEFAULT_WRAPPER_W_2W(Type_ub)
2769 DEFAULT_WRAPPER_W_5W(Type_vector)
2770 /* DEFAULT_WRAPPER_W_7W(Unpack) */
2771 DEFAULT_WRAPPER_W_3W(Unpublish_name)
2772 DEFAULT_WRAPPER_W_7W(Unpack_external)
2773 /* DEFAULT_WRAPPER_W_3W(Waitall) */
2774 /* DEFAULT_WRAPPER_W_4W(Waitany) */
2775 /* DEFAULT_WRAPPER_W_2W(Wait) */
2776 DEFAULT_WRAPPER_W_5W(Waitsome)
2777 DEFAULT_WRAPPER_W_1W(Win_c2f)
2778 DEFAULT_WRAPPER_W_2W(Win_call_errhandler)
2779 DEFAULT_WRAPPER_W_1W(Win_complete)
2780 DEFAULT_WRAPPER_W_6W(Win_create)
2781 DEFAULT_WRAPPER_W_2W(Win_create_errhandler)
2782 DEFAULT_WRAPPER_W_4W(Win_create_keyval)
2783 DEFAULT_WRAPPER_W_2W(Win_delete_attr)
2784 DEFAULT_WRAPPER_W_1W(Win_f2c)
2785 DEFAULT_WRAPPER_W_2W(Win_fence)
2786 DEFAULT_WRAPPER_W_1W(Win_free)
2787 DEFAULT_WRAPPER_W_1W(Win_free_keyval)
2788 DEFAULT_WRAPPER_W_4W(Win_get_attr)
2789 DEFAULT_WRAPPER_W_2W(Win_get_errhandler)
2790 DEFAULT_WRAPPER_W_2W(Win_get_group)
2791 DEFAULT_WRAPPER_W_3W(Win_get_name)
2792 DEFAULT_WRAPPER_W_4W(Win_lock)
2793 DEFAULT_WRAPPER_W_3W(Win_post)
2794 DEFAULT_WRAPPER_W_3W(Win_set_attr)
2795 DEFAULT_WRAPPER_W_2W(Win_set_errhandler)
2796 DEFAULT_WRAPPER_W_2W(Win_set_name)
2797 DEFAULT_WRAPPER_W_3W(Win_start)
2798 DEFAULT_WRAPPER_W_2W(Win_test)
2799 DEFAULT_WRAPPER_W_2W(Win_unlock)
2800 DEFAULT_WRAPPER_W_1W(Win_wait)
2801 /* double MPI_Wtick(void) */
2802 /* double MPI_Wtime(void) */
2805 /*------------------------------------------------------------*/
2806 /*--- ---*/
2807 /*--- ---*/
2808 /*--- ---*/
2809 /*------------------------------------------------------------*/
2811 /*---------------------------------------------------------------*/
2812 /*--- end mpiwrap.c ---*/
2813 /*---------------------------------------------------------------*/