Add bug 494246 to NEWS
[valgrind.git] / mpi / libmpiwrap.c
blob2fa1cb8fe0b0daf469376747b59d3c7d4bf3b4fa
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 // platform dependant? MPI_LONG_LONG and MPI_UNSIGNED_LONG_LONG can be the same
295 // coverity[DEADCODE:FALSE]
296 else if (ty == MPI_LONG_LONG) fprintf(f,"LONG_LONG");
297 # endif
298 # if defined(MPI_UNSIGNED_LONG_LONG)
299 else if (ty == MPI_UNSIGNED_LONG_LONG) fprintf(f,"UNSIGNED_LONG_LONG");
300 # endif
301 # if defined(MPI_REAL8)
302 else if (ty == MPI_REAL8) fprintf(f, "REAL8");
303 # endif
304 # if defined(MPI_REAL4)
305 else if (ty == MPI_REAL4) fprintf(f, "REAL4");
306 # endif
307 # if defined(MPI_REAL)
308 else if (ty == MPI_REAL) fprintf(f, "REAL");
309 # endif
310 # if defined(MPI_INTEGER8)
311 else if (ty == MPI_INTEGER8) fprintf(f, "INTEGER8");
312 # endif
313 # if defined(MPI_INTEGER4)
314 else if (ty == MPI_INTEGER4) fprintf(f, "INTEGER4");
315 # endif
316 # if defined(MPI_INTEGER)
317 else if (ty == MPI_INTEGER) fprintf(f, "INTEGER");
318 # endif
319 # if defined(MPI_DOUBLE_PRECISION)
320 else if (ty == MPI_DOUBLE_PRECISION) fprintf(f, "DOUBLE_PRECISION");
321 # endif
322 # if defined(MPI_COMPLEX)
323 else if (ty == MPI_COMPLEX) fprintf(f, "COMPLEX");
324 # endif
325 # if defined(MPI_DOUBLE_COMPLEX)
326 else if (ty == MPI_DOUBLE_COMPLEX) fprintf(f, "DOUBLE_COMPLEX");
327 # endif
328 # if defined(MPI_LOGICAL)
329 else if (ty == MPI_LOGICAL) fprintf(f, "LOGICAL");
330 # endif
331 # if defined(MPI_2INTEGER)
332 else if (ty == MPI_2INTEGER) fprintf(f, "2INTEGER");
333 # endif
334 # if defined(MPI_2COMPLEX)
335 else if (ty == MPI_2COMPLEX) fprintf(f, "2COMPLEX");
336 # endif
337 # if defined(MPI_2DOUBLE_COMPLEX)
338 else if (ty == MPI_2DOUBLE_COMPLEX) fprintf(f, "2DOUBLE_COMPLEX");
339 # endif
340 # if defined(MPI_2REAL)
341 else if (ty == MPI_2REAL) fprintf(f, "2REAL");
342 # endif
343 # if defined(MPI_2DOUBLE_PRECISION)
344 else if (ty == MPI_2DOUBLE_PRECISION) fprintf(f, "2DOUBLE_PRECISION");
345 # endif
346 # if defined(MPI_CHARACTER)
347 else if (ty == MPI_CHARACTER) fprintf(f, "CHARACTER");
348 # endif
349 else fprintf(f,"showTy:???");
352 static void showCombiner ( FILE* f, int combiner )
354 switch (combiner) {
355 case MPI_COMBINER_NAMED: fprintf(f, "NAMED"); break;
356 # if defined(MPI_COMBINER_DUP)
357 case MPI_COMBINER_DUP: fprintf(f, "DUP"); break;
358 # endif
359 case MPI_COMBINER_CONTIGUOUS: fprintf(f, "CONTIGUOUS"); break;
360 case MPI_COMBINER_VECTOR: fprintf(f, "VECTOR"); break;
361 # if defined(MPI_COMBINER_HVECTOR_INTEGER) && \
362 (!defined(OMPI_MAJOR_VERSION) || OMPI_MAJOR_VERSION < 3)
363 case MPI_COMBINER_HVECTOR_INTEGER: fprintf(f, "HVECTOR_INTEGER"); break;
364 # endif
365 case MPI_COMBINER_HVECTOR: fprintf(f, "HVECTOR"); break;
366 case MPI_COMBINER_INDEXED: fprintf(f, "INDEXED"); break;
367 # if defined(MPI_COMBINER_HINDEXED_INTEGER) && \
368 (!defined(OMPI_MAJOR_VERSION) || OMPI_MAJOR_VERSION < 3)
369 case MPI_COMBINER_HINDEXED_INTEGER: fprintf(f, "HINDEXED_INTEGER"); break;
370 # endif
371 case MPI_COMBINER_HINDEXED: fprintf(f, "HINDEXED"); break;
372 # if defined(MPI_COMBINER_INDEXED_BLOCK)
373 case MPI_COMBINER_INDEXED_BLOCK: fprintf(f, "INDEXED_BLOCK"); break;
374 # endif
375 # if defined(MPI_COMBINER_STRUCT_INTEGER) && \
376 (!defined(OMPI_MAJOR_VERSION) || OMPI_MAJOR_VERSION < 3)
377 case MPI_COMBINER_STRUCT_INTEGER: fprintf(f, "STRUCT_INTEGER"); break;
378 # endif
379 case MPI_COMBINER_STRUCT: fprintf(f, "STRUCT"); break;
380 # if defined(MPI_COMBINER_SUBARRAY)
381 case MPI_COMBINER_SUBARRAY: fprintf(f, "SUBARRAY"); break;
382 # endif
383 # if defined(MPI_COMBINER_DARRAY)
384 case MPI_COMBINER_DARRAY: fprintf(f, "DARRAY"); break;
385 # endif
386 # if defined(MPI_COMBINER_F90_REAL)
387 case MPI_COMBINER_F90_REAL: fprintf(f, "F90_REAL"); break;
388 # endif
389 # if defined(MPI_COMBINER_F90_COMPLEX)
390 case MPI_COMBINER_F90_COMPLEX: fprintf(f, "F90_COMPLEX"); break;
391 # endif
392 # if defined(MPI_COMBINER_F90_INTEGER)
393 case MPI_COMBINER_F90_INTEGER: fprintf(f, "F90_INTEGER"); break;
394 # endif
395 # if defined(MPI_COMBINER_RESIZED)
396 case MPI_COMBINER_RESIZED: fprintf(f, "RESIZED"); break;
397 # endif
398 default: fprintf(f, "showCombiner:??"); break;
403 /* ------ Get useful bits of info ------ */
405 /* Note, PMPI_Comm_rank/size are themselves wrapped. Should work
406 fine. */
408 static __inline__ int comm_rank ( MPI_Comm comm )
410 int err, r;
411 err = PMPI_Comm_rank(comm, &r);
412 return err ? 0/*arbitrary*/ : r;
415 static __inline__ int comm_size ( MPI_Comm comm )
417 int err, r;
418 err = PMPI_Comm_size(comm, &r);
419 return err ? 0/*arbitrary*/ : r;
422 static __inline__ Bool count_from_Status( /*OUT*/int* recv_count,
423 MPI_Datatype datatype,
424 MPI_Status* status)
426 int n;
427 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
428 int err = PMPI_Get_count(status, datatype, &n);
429 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
430 if (err == MPI_SUCCESS) {
431 VALGRIND_MAKE_MEM_DEFINED(&n, sizeof(n));
432 *recv_count = n;
433 return True;
434 } else {
435 return False;
439 /* It's critical that we can do equality on MPI_Requests.
440 Unfortunately these are opaque objects to us (handles, in the
441 parlance of the MPI 1.1 spec). Fortunately Sec 2.4.1 ("Opaque
442 Objects") specifies that "In C, [...] These [handles] should be
443 types that support assignment and equality operations." Hence the
444 following function should compile for any compliant definition of
445 MPI_Request. */
446 static __inline__
447 Bool eq_MPI_Request ( MPI_Request r1, MPI_Request r2 )
449 return r1 == r2;
452 /* Return True if status is MPI_STATUS_IGNORE or MPI_STATUSES_IGNORE.
453 On MPI-1.x platforms which don't have these symbols (and they would
454 only have them if they've been backported from 2.x) always return
455 False. */
456 static __inline__
457 Bool isMSI ( MPI_Status* status )
459 # if defined(HAVE_MPI_STATUS_IGNORE)
460 return status == MPI_STATUSES_IGNORE || status == MPI_STATUS_IGNORE;
461 # else
462 return False;
463 # endif
466 /* Get the 'extent' of a type. Note, as per the MPI spec this
467 includes whatever padding would be required when using 'ty' in an
468 array. */
469 static long extentOfTy ( MPI_Datatype ty )
471 int r;
472 MPI_Aint n;
473 # if defined(MPI_TYPE_EXTENT)
474 r = PMPI_Type_extent(ty, &n);
475 # else
476 MPI_Aint lb;
477 r = MPI_Type_get_extent(ty, &lb, &n);
478 # endif
479 assert(r == MPI_SUCCESS);
480 return (long)n;
483 /* Free up *ty, if it is safe to do so */
484 static void maybeFreeTy ( MPI_Datatype* ty )
486 int r, n_ints, n_addrs, n_dtys, tycon;
488 r = PMPI_Type_get_envelope( *ty, &n_ints, &n_addrs, &n_dtys, &tycon );
489 assert(r == MPI_SUCCESS);
491 /* can't free named types */
492 if (tycon == MPI_COMBINER_NAMED)
493 return;
495 /* some kinds of structs are predefined so we can't free them
496 either. */
497 if (*ty == MPI_FLOAT_INT || *ty == MPI_DOUBLE_INT
498 || *ty == MPI_LONG_INT || *ty == MPI_2INT
499 || *ty == MPI_SHORT_INT || *ty == MPI_LONG_DOUBLE_INT)
500 return;
502 /* Looks OK - free it. */
503 if (0) {
504 /* show me what you're about to free .. */
505 fprintf(stderr, "freeing combiner ");
506 showCombiner(stderr,tycon);
507 fprintf(stderr, " ty= ");
508 showTy(stderr,*ty);
509 fprintf(stderr,"\n");
511 r = PMPI_Type_free(ty);
512 assert(r == MPI_SUCCESS);
515 /* How big is a "named" (base) type? Returns 0 if not known. Note.
516 There is a subtlety, which is that this is required to return the
517 exact size of one item of the type, NOT the size of it when padded
518 suitably to make an array of them. In particular that's why the
519 size of LONG_DOUBLE is computed by looking at the result of doing a
520 long double store, rather than just asking what is the sizeof(long
521 double).
523 For LONG_DOUBLE on x86-linux and amd64-linux my impression is that
524 the right answer is 10 even though sizeof(long double) says 12 and
525 16 respectively. On ppc32-linux it appears to be 16.
527 Ref: MPI 1.1 doc p18 */
528 static long sizeofOneNamedTy ( MPI_Datatype ty )
530 if (ty == MPI_CHAR) return sizeof(signed char);
531 if (ty == MPI_SHORT) return sizeof(signed short int);
532 if (ty == MPI_INT) return sizeof(signed int);
533 if (ty == MPI_LONG) return sizeof(signed long int);
534 if (ty == MPI_UNSIGNED_CHAR) return sizeof(unsigned char);
535 if (ty == MPI_UNSIGNED_SHORT) return sizeof(unsigned short int);
536 if (ty == MPI_UNSIGNED) return sizeof(unsigned int);
537 if (ty == MPI_UNSIGNED_LONG) return sizeof(unsigned long int);
538 if (ty == MPI_FLOAT) return sizeof(float);
539 if (ty == MPI_DOUBLE) return sizeof(double);
540 if (ty == MPI_BYTE) return 1;
541 if (ty == MPI_LONG_DOUBLE) return sizeof_long_double_image();
542 if (ty == MPI_PACKED) return 1;
543 if (ty == MPI_LONG_LONG_INT) return sizeof(signed long long int);
545 # if defined(MPI_REAL8)
546 if (ty == MPI_REAL8) return 8; /* MPI2 spec */;
547 # endif
548 # if defined(MPI_REAL4)
549 if (ty == MPI_REAL4) return 4; /* MPI2 spec */;
550 # endif
551 # if defined(MPI_REAL)
552 if (ty == MPI_REAL) return 4; /* MPI2 spec */;
553 # endif
554 # if defined(MPI_INTEGER8)
555 if (ty == MPI_INTEGER8) return 8; /* MPI2 spec */;
556 # endif
557 # if defined(MPI_INTEGER4)
558 if (ty == MPI_INTEGER4) return 4; /* MPI2 spec */;
559 # endif
560 # if defined(MPI_INTEGER)
561 if (ty == MPI_INTEGER) return 4; /* MPI2 spec */;
562 # endif
563 # if defined(MPI_DOUBLE_PRECISION)
564 if (ty == MPI_DOUBLE_PRECISION) return 8; /* MPI2 spec */;
565 # endif
567 /* new in MPI2: */
568 # if defined(MPI_WCHAR)
569 if (ty == MPI_WCHAR) return 2; /* MPI2 spec */;
570 # endif
571 # if defined(MPI_SIGNED_CHAR)
572 if (ty == MPI_SIGNED_CHAR) return 1; /* MPI2 spec */;
573 # endif
574 # if defined(MPI_UNSIGNED_LONG_LONG)
575 if (ty == MPI_UNSIGNED_LONG_LONG) return 8; /* MPI2 spec */;
576 # endif
577 # if defined(MPI_COMPLEX)
578 if (ty == MPI_COMPLEX) return 2 * 4; /* MPI2 spec */
579 # endif
580 # if defined(MPI_DOUBLE_COMPLEX)
581 if (ty == MPI_DOUBLE_COMPLEX) return 2 * 8; /* MPI2 spec */
582 # endif
583 # if defined(MPI_LOGICAL)
584 if (ty == MPI_LOGICAL) return 4; /* MPI2 spec */
585 # endif
586 # if defined(MPI_2INTEGER)
587 if (ty == MPI_2INTEGER) return 2 * 4; /* undocumented in MPI2 */
588 # endif
589 # if defined(MPI_2COMPLEX)
590 if (ty == MPI_2COMPLEX) return 2 * 8; /* undocumented in MPI2 */
591 # endif
592 # if defined(MPI_2DOUBLE_COMPLEX)
593 /* 32: this is how openmpi-1.2.2 behaves on x86-linux, but I have
594 really no idea if this is right. */
595 if (ty == MPI_2DOUBLE_COMPLEX) return 32; /* undocumented in MPI2 */
596 # endif
597 # if defined(MPI_2REAL)
598 if (ty == MPI_2REAL) return 2 * 4; /* undocumented in MPI2 */
599 # endif
600 # if defined(MPI_2DOUBLE_PRECISION)
601 if (ty == MPI_2DOUBLE_PRECISION) return 2 * 8; /* undocumented in MPI2 */
602 # endif
603 # if defined(MPI_CHARACTER)
604 if (ty == MPI_CHARACTER) return 1; /* MPI2 spec */
605 # endif
607 /* Note: the following are named structs, not named basic types,
608 and so are not handled here:
609 FLOAT_INT DOUBLE_INT LONG_INT 2INT SHORT_INT LONG_DOUBLE_INT
610 My guess is they are probably for doing max-w-index style
611 reductions, the INT carrying the index of the max/min and the
612 other type its actual value.
614 return 0;
618 /* Find the size of long double image (not 'sizeof(long double)').
619 See comments in sizeofOneNamedTy.
621 static long sizeof_long_double_image ( void )
623 long i;
624 unsigned char* p;
625 static long cached_result = 0;
627 /* Hopefully we have it already. */
628 if (cached_result != 0) {
629 assert(cached_result == 10 || cached_result == 16 || cached_result == 8);
630 return cached_result;
633 /* No? Then we'll have to compute it. This isn't thread-safe but
634 it doesn't really matter since all races to compute it should
635 produce the same answer. */
636 p = malloc(64);
637 assert(p);
638 for (i = 0; i < 64; i++)
639 p[i] = 0x55;
641 /* Write a value which isn't known at compile time and therefore
642 must come out of a register. If we just store a constant here,
643 some compilers write more data than a store from a machine
644 register would. Therefore we have to force a store from a
645 machine register by storing a value which isn't known at compile
646 time. Since getpid() will return a value < 1 million, turn it
647 into a zero by dividing by 1e+30. */
648 *(long double*)(&p[16]) = (long double)(1.0e-30 * (double)getpid());
650 for (i = 0; i < 16; i++) {
651 assert(p[i] == 0x55);
652 assert(p[i+48] == 0x55);
654 for (i = 16; i <= 48; i++) {
655 if (p[i] == 0x55)
656 break;
659 assert(i < 48);
660 assert(i > 16);
661 free(p);
662 cached_result = i - 16;
664 if (0)
665 printf("sizeof_long_double_image: computed %d\n", (int)cached_result);
667 assert(cached_result == 10 || cached_result == 16 || cached_result == 8);
668 return cached_result;
672 /*------------------------------------------------------------*/
673 /*--- Unpicking datatypes ---*/
674 /*------------------------------------------------------------*/
676 static __inline__
677 void walk_type_array ( void(*f)(void*,long), char* base,
678 MPI_Datatype ty, long count );
681 /* Walk over all fragments of the object of type 'ty' with base
682 address 'base', and apply 'f' to the start/length of each
683 contiguous fragment. */
684 static
685 void walk_type ( void(*f)(void*,long), char* base, MPI_Datatype ty )
687 int r, n_ints, n_addrs, n_dtys, tycon;
688 long ex, i;
689 int* ints = NULL;
690 MPI_Aint* addrs = NULL;
691 MPI_Datatype* dtys = NULL;
693 /* Stuff for limiting how much complaining text it spews out */
694 static int complaints = 3;
695 static int last_complained_about_tycon = -987654321; /* presumably bogus */
697 if (0)
698 printf("walk_type %p\n", (void*)(unsigned long)ty);
700 r = PMPI_Type_get_envelope( ty, &n_ints, &n_addrs, &n_dtys, &tycon );
701 assert(r == MPI_SUCCESS);
703 /* Handle the base cases fast(er/ish). */
704 if (tycon == MPI_COMBINER_NAMED) {
705 long sz = sizeofOneNamedTy(ty);
706 if (sz > 0) {
707 f(base, sz);
708 return;
710 /* Hmm. Perhaps it's a named struct? Unfortunately we can't
711 take them to bits so we have to do a really ugly hack, which
712 makes assumptions about how the MPI implementation has laid
713 out these types. At least Open MPI 1.0.1 appears to put
714 the 'val' field first. MPICH2 agrees.
716 if (ty == MPI_2INT) {
717 typedef struct { int val; int loc; } Ty;
718 f(base + offsetof(Ty,val), sizeof(int));
719 f(base + offsetof(Ty,loc), sizeof(int));
720 return;
722 if (ty == MPI_LONG_INT) {
723 typedef struct { long val; int loc; } Ty;
724 f(base + offsetof(Ty,val), sizeof(long));
725 f(base + offsetof(Ty,loc), sizeof(int));
726 return;
728 if (ty == MPI_DOUBLE_INT) {
729 typedef struct { double val; int loc; } Ty;
730 f(base + offsetof(Ty,val), sizeof(double));
731 f(base + offsetof(Ty,loc), sizeof(int));
732 return;
734 if (ty == MPI_SHORT_INT) {
735 typedef struct { short val; int loc; } Ty;
736 f(base + offsetof(Ty,val), sizeof(short));
737 f(base + offsetof(Ty,loc), sizeof(int));
738 return;
740 if (ty == MPI_FLOAT_INT) {
741 typedef struct { float val; int loc; } Ty;
742 f(base + offsetof(Ty,val), sizeof(float));
743 f(base + offsetof(Ty,loc), sizeof(int));
744 return;
746 if (ty == MPI_LONG_DOUBLE_INT) {
747 typedef struct { long double val; int loc; } Ty;
748 f(base + offsetof(Ty,val), sizeof_long_double_image());
749 f(base + offsetof(Ty,loc), sizeof(int));
750 return;
752 # if defined(MPI_LB) && defined(MPI_UB) && \
753 (!defined(OMPI_MAJOR_VERSION) || OMPI_MAJOR_VERSION < 3)
754 if (ty == MPI_LB || ty == MPI_UB)
755 return; /* have zero size, so nothing needs to be done */
756 # endif
757 goto unhandled;
758 /*NOTREACHED*/
761 if (0) {
762 ex = extentOfTy(ty);
763 printf("tycon 0x%llx %d %d %d (ext %d)\n",
764 (unsigned long long int)tycon,
765 n_ints, n_addrs, n_dtys, (int)ex );
768 /* Now safe to do MPI_Type_get_contents */
769 assert(n_ints >= 0);
770 assert(n_addrs >= 0);
771 assert(n_dtys >= 0);
773 if (n_ints > 0) {
774 ints = malloc(n_ints * sizeof(int));
775 assert(ints);
777 if (n_addrs > 0) {
778 addrs = malloc(n_addrs * sizeof(MPI_Aint));
779 assert(addrs);
781 if (n_dtys > 0) {
782 dtys = malloc(n_dtys * sizeof(MPI_Datatype));
783 assert(dtys);
786 r = PMPI_Type_get_contents( ty, n_ints, n_addrs, n_dtys,
787 ints, addrs, dtys );
788 assert(r == MPI_SUCCESS);
790 switch (tycon) {
792 case MPI_COMBINER_CONTIGUOUS:
793 assert(n_ints == 1 && n_addrs == 0 && n_dtys == 1);
794 walk_type_array( f, base, dtys[0], ints[0] );
795 maybeFreeTy( &dtys[0] );
796 break;
798 case MPI_COMBINER_VECTOR:
799 assert(n_ints == 3 && n_addrs == 0 && n_dtys == 1);
800 ex = extentOfTy(dtys[0]);
801 if (0)
802 printf("vector count %d x (bl %d stride %d)\n",
803 (int)ints[0], (int)ints[1], (int)ints[2]);
804 for (i = 0; i < ints[0]; i++) {
805 walk_type_array( f, base + i * ints[2]/*stride*/ * ex,
806 dtys[0], ints[1]/*blocklength*/ );
808 maybeFreeTy( &dtys[0] );
809 break;
811 case MPI_COMBINER_HVECTOR:
812 assert(n_ints == 2 && n_addrs == 1 && n_dtys == 1);
813 ex = extentOfTy(dtys[0]);
814 if (0)
815 printf("hvector count %d x (bl %d hstride %d)\n",
816 (int)ints[0], (int)ints[1], (int)addrs[0]);
817 for (i = 0; i < ints[0]; i++) {
818 walk_type_array( f, base + i * addrs[0]/*hstride*/,
819 dtys[0], ints[1]/*blocklength*/ );
821 maybeFreeTy( &dtys[0] );
822 break;
824 case MPI_COMBINER_INDEXED:
825 assert(n_addrs == 0 && n_dtys == 1);
826 assert(n_ints > 0);
827 assert(n_ints == 2 * ints[0] + 1);
828 ex = extentOfTy(dtys[0]);
829 for (i = 0; i < ints[0]; i++) {
830 if (0)
831 printf("indexed (elem %d) off %d copies %d\n",
832 (int)i, ints[i+1+ints[0]], ints[i+1] );
833 walk_type_array( f, base + ex * ints[i+1+ints[0]],
834 dtys[0], ints[i+1] );
836 maybeFreeTy( &dtys[0] );
837 break;
839 case MPI_COMBINER_HINDEXED:
840 assert(n_ints > 0);
841 assert(n_ints == ints[0] + 1);
842 assert(n_addrs == ints[0] && n_dtys == 1);
843 ex = extentOfTy(dtys[0]);
844 for (i = 0; i < ints[0]; i++) {
845 if (0)
846 printf("hindexed (elem %d) hoff %d copies %d\n",
847 (int)i, (int)addrs[i], ints[i+1] );
848 walk_type_array( f, base + addrs[i],
849 dtys[0], ints[i+1] );
851 maybeFreeTy( &dtys[0] );
852 break;
854 case MPI_COMBINER_STRUCT:
855 assert(n_addrs == n_ints-1);
856 assert(n_dtys == n_ints-1);
857 assert(n_ints > 0);
858 assert(n_ints == ints[0] + 1);
859 for (i = 0; i < ints[0]; i++) {
860 if (0)
861 printf("struct (elem %d limit %d) hoff %d copies %d\n",
862 (int)i, (int)ints[0], (int)addrs[i], (int)ints[i+1]);
863 walk_type_array( f, base + addrs[i], dtys[i], (long)ints[i+1] );
864 maybeFreeTy( &dtys[i] );
866 break;
868 default:
869 goto unhandled;
873 /* normal exit */
874 if (n_ints > 0) {
875 free(ints);
877 if (n_addrs > 0) {
878 free(addrs);
880 if (n_dtys) {
881 free(dtys);
883 return;
885 unhandled:
886 /* Complain, but limit the amount of complaining that can happen to
887 the first 3 different unhandled tycons that show up, so as to
888 avoid swamping users with thousands of duplicate messages. */
889 if (complaints > 0 && tycon != last_complained_about_tycon) {
890 complaints--;
891 last_complained_about_tycon = tycon;
892 if (tycon == MPI_COMBINER_NAMED) {
893 fprintf(stderr, "%s %5d: walk_type: unhandled base type 0x%lx ",
894 preamble, my_pid, (long)ty);
895 showTy(stderr, ty);
896 fprintf(stderr, "\n");
897 } else {
898 fprintf(stderr, "%s %5d: walk_type: unhandled combiner 0x%lx\n",
899 preamble, my_pid, (long)tycon);
902 if (ints) free(ints);
903 if (addrs) free(addrs);
904 if (dtys) free(dtys);
905 if (opt_missing >= 2)
906 barf("walk_type: unhandled combiner, strict checking selected");
910 /* Same as walk_type but apply 'f' to every element in an array of
911 'count' items starting at 'base'. The only purpose of pushing this
912 into a different routine is so it can attempt to optimise the case
913 where the array elements are contiguous and packed together without
914 holes. */
915 static __inline__
916 void walk_type_array ( void(*f)(void*,long), char* base,
917 MPI_Datatype elemTy, long count )
919 long i, ex;
921 assert(sizeof(unsigned long) == sizeof(char*));
923 /* First see if we can do this the fast way. */
924 ex = sizeofOneNamedTy(elemTy);
926 if ( /* ty is a primitive type with power-of-2 size */
927 (ex == 8 || ex == 4 || ex == 2 || ex == 1)
928 && /* base is suitably aligned for ty */
929 ( ((unsigned long)base) & (ex-1)) == 0) {
931 /* We're sure it's contiguous, so just paint/check it in one
932 go. */
933 if (0) printf("walk_type_array fast %ld of size %ld\n", count, ex );
934 f ( base, count * ex );
936 } else {
938 /* Bad news. We have to futz with each element individually.
939 This could be very expensive.
941 Note: subtle. If ty is LONG_DOUBLE then the extent will be
942 12, so the following loop will jump along in steps of 12, but
943 the size painted by walk_type will be 10 since it uses
944 sizeofOneNamedTy to establish the size of base types. Which
945 is what we need to happen. */
946 ex = extentOfTy(elemTy);
947 if (0) printf("walk_type_array SLOW %ld of size %ld\n", count, ex );
948 for (i = 0; i < count; i++)
949 walk_type( f, base + i * ex, elemTy );
955 /* Hook so it's visible from outside (can be handy to dlopen/dlsym
956 it) */
957 void mpiwrap_walk_type_EXTERNALLY_VISIBLE
958 ( void(*f)(void*,long), char* base, MPI_Datatype ty )
960 walk_type(f, base, ty);
964 /*------------------------------------------------------------*/
965 /*--- Address-range helpers ---*/
966 /*------------------------------------------------------------*/
968 /* ----------------
969 Do corresponding checks on memory areas defined using a
970 straightforward (start, length) description.
971 ----------------
974 static __inline__
975 void check_mem_is_defined_untyped ( void* buffer, long nbytes )
977 if (nbytes > 0) {
978 VALGRIND_CHECK_MEM_IS_DEFINED(buffer, nbytes);
982 static __inline__
983 void check_mem_is_addressable_untyped ( void* buffer, long nbytes )
985 if (nbytes > 0) {
986 VALGRIND_CHECK_MEM_IS_ADDRESSABLE(buffer, nbytes);
990 static __inline__
991 void make_mem_defined_if_addressable_untyped ( void* buffer, long nbytes )
993 if (nbytes > 0) {
994 VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(buffer, nbytes);
998 static __inline__
999 void make_mem_defined_if_addressable_if_success_untyped ( int err,
1000 void* buffer, long nbytes )
1002 if (err == MPI_SUCCESS && nbytes > 0) {
1003 VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(buffer, nbytes);
1008 /* ----------------
1009 Do checks on memory areas defined using the MPI (buffer, count,
1010 type) convention.
1011 ----------------
1014 /* Check that the specified area is both addressible and contains
1015 initialised data, and cause V to complain if not. */
1017 static __inline__
1018 void check_mem_is_defined ( char* buffer, long count, MPI_Datatype datatype )
1020 walk_type_array( check_mem_is_defined_untyped, buffer, datatype, count );
1024 /* Check that the specified area is addressible, and cause V to
1025 complain if not. Doesn't matter whether the data there is
1026 initialised or not. */
1028 static __inline__
1029 void check_mem_is_addressable ( void *buffer, long count, MPI_Datatype datatype )
1031 walk_type_array( check_mem_is_addressable_untyped, buffer, datatype, count );
1035 /* Set the specified area to 'defined for each byte which is
1036 addressible' state. */
1038 static __inline__
1039 void make_mem_defined_if_addressable ( void *buffer, int count, MPI_Datatype datatype )
1041 walk_type_array( make_mem_defined_if_addressable_untyped,
1042 buffer, datatype, count );
1045 static __inline__
1046 void
1047 make_mem_defined_if_addressable_if_success ( int err, void *buffer, int count,
1048 MPI_Datatype datatype )
1050 if (err == MPI_SUCCESS)
1051 make_mem_defined_if_addressable(buffer, count, datatype);
1055 /*------------------------------------------------------------*/
1056 /*--- ---*/
1057 /*--- The wrappers proper. They are listed in the order ---*/
1058 /*--- in which they appear in "MPI: A Message-Passing ---*/
1059 /*--- Interface Standard, MPIF, Nov 15 2003" (the MPI 1.1 ---*/
1060 /*--- spec. All unimplemented wrappers are listed at the ---*/
1061 /*--- end of the file. The list of function names is ---*/
1062 /*--- taken from the headers of Open MPI svn r9191. ---*/
1063 /*--- Hopefully it is a complete list of all the MPI 2 ---*/
1064 /*--- functions. ---*/
1065 /*--- ---*/
1066 /*------------------------------------------------------------*/
1068 /* Handy abbreviation */
1069 #define WRAPPER_FOR(name) I_WRAP_FNNAME_U(name)
1071 /* Generates (conceptually) a wrapper which does nothing. In
1072 fact just generate no wrapper at all. */
1073 #define HAS_NO_WRAPPER(basename) /* */
1076 /*------------------------------------------------------------*/
1077 /*--- ---*/
1078 /*--- Sec 3.2, Blocking Send and Receive Operations ---*/
1079 /*--- ---*/
1080 /*------------------------------------------------------------*/
1082 /* --- {,B,S,R}Send --- */
1083 /* pre: rd: (buf,count,datatype) */
1084 static
1085 int generic_Send(void *buf, int count, MPI_Datatype datatype,
1086 int dest, int tag, MPI_Comm comm)
1088 OrigFn fn;
1089 int err;
1090 VALGRIND_GET_ORIG_FN(fn);
1091 before("{,B,S,R}Send");
1092 check_mem_is_defined(buf, count, datatype);
1093 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1094 CALL_FN_W_6W(err, fn, buf,count,datatype,dest,tag,comm);
1095 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1096 after("{,B,S,R}Send", err);
1097 return err;
1099 int WRAPPER_FOR(PMPI_Send)(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_Bsend)(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);
1107 int WRAPPER_FOR(PMPI_Ssend)(void *buf, int count, MPI_Datatype datatype,
1108 int dest, int tag, MPI_Comm comm) {
1109 return generic_Send(buf,count,datatype, dest,tag,comm);
1111 int WRAPPER_FOR(PMPI_Rsend)(void *buf, int count, MPI_Datatype datatype,
1112 int dest, int tag, MPI_Comm comm) {
1113 return generic_Send(buf,count,datatype, dest,tag,comm);
1116 /* --- Recv --- */
1117 /* pre: must be writable: (buf,count,datatype)
1118 must be writable: status
1119 post: make readable: (buf,recv_count,datatype)
1120 where recv_count is determined from *status
1122 int WRAPPER_FOR(PMPI_Recv)(void *buf, int count, MPI_Datatype datatype,
1123 int source, int tag,
1124 MPI_Comm comm, MPI_Status *status)
1126 OrigFn fn;
1127 int err, recv_count = 0;
1128 MPI_Status fake_status;
1129 VALGRIND_GET_ORIG_FN(fn);
1130 before("Recv");
1131 if (isMSI(status))
1132 status = &fake_status;
1133 check_mem_is_addressable(buf, count, datatype);
1134 check_mem_is_addressable_untyped(status, sizeof(*status));
1135 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1136 CALL_FN_W_7W(err, fn, buf,count,datatype,source,tag,comm,status);
1137 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1138 make_mem_defined_if_addressable_if_success_untyped(err, status, sizeof(*status));
1139 if (err == MPI_SUCCESS && count_from_Status(&recv_count,datatype,status)) {
1140 make_mem_defined_if_addressable(buf, recv_count, datatype);
1142 after("Recv", err);
1143 return err;
1146 /* --- Get_count --- */
1147 /* pre: must be readable: *status
1148 post: make defined: *count -- don't bother, libmpi will surely do this
1150 int WRAPPER_FOR(PMPI_Get_count)(MPI_Status* status,
1151 MPI_Datatype ty, int* count )
1153 OrigFn fn;
1154 int err;
1155 VALGRIND_GET_ORIG_FN(fn);
1156 before("Get_count");
1157 check_mem_is_defined_untyped(status, sizeof(*status));
1158 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1159 CALL_FN_W_WWW(err, fn, status,ty,count);
1160 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1161 after("Get_count", err);
1162 return err;
1166 /*------------------------------------------------------------*/
1167 /*--- ---*/
1168 /*--- Sec 3.7, Nonblocking communication ---*/
1169 /*--- ---*/
1170 /*------------------------------------------------------------*/
1172 /* Maintain a table that makes it possible for the wrappers to
1173 complete MPI_Irecv successfully.
1175 The issue is that MPI_Irecv states the recv buffer and returns
1176 immediately, giving a handle (MPI_Request) for the transaction.
1177 Later the user will have to poll for completion with MPI_Wait etc,
1178 and at that point these wrappers have to paint the recv buffer.
1179 But the recv buffer details are not presented to MPI_Wait - only
1180 the handle is. We therefore have to use a shadow table
1181 (sReqs{,_size,_used,_lock}) which associates uncompleted
1182 MPI_Requests with the corresponding buffer address/count/type.
1184 Only read requests are placed in the table, since there is no need
1185 to do any buffer painting following completion of an Isend - all
1186 the checks for that are done at the time Isend is called.
1188 Care has to be take to remove completed requests from the table.
1190 Access to the table is guarded by sReqs_lock so as to make it
1191 thread-safe.
1194 typedef
1195 struct {
1196 Bool inUse;
1197 MPI_Request key;
1198 void* buf;
1199 int count;
1200 MPI_Datatype datatype;
1202 ShadowRequest;
1204 static ShadowRequest* sReqs = NULL;
1205 static int sReqs_size = 0;
1206 static int sReqs_used = 0;
1207 static pthread_mutex_t sReqs_lock = PTHREAD_MUTEX_INITIALIZER;
1209 #define LOCK_SREQS \
1210 do { int pr = pthread_mutex_lock(&sReqs_lock); \
1211 assert(pr == 0); \
1212 } while (0)
1214 #define UNLOCK_SREQS \
1215 do { int pr = pthread_mutex_unlock(&sReqs_lock); \
1216 assert(pr == 0); \
1217 } while (0)
1220 /* Ensure the sReqs expandable array has at least one free slot, by
1221 copying it into a larger one if necessary. NOTE: sReqs_lock is
1222 held throughout this procedure.*/
1223 static void ensure_sReq_space ( void )
1225 int i;
1226 ShadowRequest* sReqs2;
1227 if (sReqs_used == sReqs_size) {
1228 sReqs_size = sReqs_size==0 ? 2 : 2*sReqs_size;
1229 sReqs2 = malloc( sReqs_size * sizeof(ShadowRequest) );
1230 if (sReqs2 == NULL) {
1231 UNLOCK_SREQS;
1232 barf("add_shadow_Request: malloc failed.\n");
1234 for (i = 0; i < sReqs_used; i++)
1235 sReqs2[i] = sReqs[i];
1236 if (sReqs)
1237 free(sReqs);
1238 sReqs = sReqs2;
1240 assert(sReqs_used < sReqs_size);
1244 /* Find shadow info for 'request', or NULL if none. */
1246 static
1247 ShadowRequest* find_shadow_Request ( MPI_Request request )
1249 ShadowRequest* ret = NULL;
1250 int i;
1251 LOCK_SREQS;
1252 for (i = 0; i < sReqs_used; i++) {
1253 if (sReqs[i].inUse && eq_MPI_Request(sReqs[i].key,request)) {
1254 ret = &sReqs[i];
1255 break;
1258 UNLOCK_SREQS;
1259 return ret;
1263 /* Delete shadow info for 'request', if any. */
1265 static void delete_shadow_Request ( MPI_Request request )
1267 int i;
1268 LOCK_SREQS;
1269 for (i = 0; i < sReqs_used; i++) {
1270 if (sReqs[i].inUse && eq_MPI_Request(sReqs[i].key,request)) {
1271 sReqs[i].inUse = False;
1272 break;
1275 UNLOCK_SREQS;
1279 /* Add a shadow for 'request', overwriting any old binding for it. */
1281 static
1282 void add_shadow_Request( MPI_Request request,
1283 void* buf, int count,
1284 MPI_Datatype datatype )
1286 int i, ix = -1;
1287 LOCK_SREQS;
1288 assert(sReqs_used >= 0);
1289 assert(sReqs_size >= 0);
1290 assert(sReqs_used <= sReqs_size);
1291 if (sReqs == NULL) assert(sReqs_size == 0);
1293 /* First of all see if we already have a binding for this key; if
1294 so just replace it, and have done. */
1295 for (i = 0; i < sReqs_used; i++) {
1296 if (sReqs[i].inUse && eq_MPI_Request(sReqs[i].key,request)) {
1297 ix = i;
1298 break;
1302 if (ix < 0) {
1303 /* Ok, we don't have it, so will have to add it. First search
1304 to see if there is an existing empty slot. */
1305 for (i = 0; i < sReqs_used; i++) {
1306 if (!sReqs[i].inUse) {
1307 ix = i;
1308 break;
1313 /* No empty slots. Allocate a new one. */
1314 if (ix < 0) {
1315 ensure_sReq_space();
1316 assert(sReqs_used < sReqs_size);
1317 ix = sReqs_used;
1318 sReqs_used++;
1321 assert(ix >= 0 && ix < sReqs_used);
1322 assert(sReqs_used <= sReqs_size);
1324 sReqs[ix].inUse = True;
1325 sReqs[ix].key = request;
1326 sReqs[ix].buf = buf;
1327 sReqs[ix].count = count;
1328 sReqs[ix].datatype = datatype;
1330 UNLOCK_SREQS;
1331 if (opt_verbosity > 1)
1332 fprintf(stderr, "%s %5d: sReq+ 0x%lx -> b/c/d %p/%d/0x%lx [slot %d]\n",
1333 preamble, my_pid, (unsigned long)request,
1334 buf, count, (long)datatype, ix);
1337 static
1338 MPI_Request* clone_Request_array ( int count, MPI_Request* orig )
1340 MPI_Request* copy;
1341 int i;
1342 LOCK_SREQS;
1343 if (count < 0)
1344 count = 0; /* Hmm. Call Mulder and Scully. */
1345 copy = malloc( count * sizeof(MPI_Request) );
1346 if (copy == NULL && count > 0) {
1347 UNLOCK_SREQS;
1348 barf("clone_Request_array: malloc failed");
1350 for (i = 0; i < count; i++)
1351 copy[i] = orig[i];
1352 UNLOCK_SREQS;
1353 return copy;
1356 #undef LOCK_SREQS
1357 #undef UNLOCK_SREQS
1360 static void maybe_complete ( Bool error_in_status,
1361 MPI_Request request_before,
1362 MPI_Request request_after,
1363 MPI_Status* status )
1365 int recv_count = 0;
1366 ShadowRequest* shadow;
1367 /* How do we know if this is an Irecv request that has now
1368 finished successfully?
1370 request_before isn't MPI_REQUEST_NULL
1371 and request_before is found in the shadow table
1372 and request_after *is* MPI_REQUEST_NULL
1373 and (if error_in_status then status.MPI_ERROR is MPI_SUCCESS)
1375 (when error_in_status == False, then we expect not to get
1376 called at all if there was an error.)
1378 if (request_before != MPI_REQUEST_NULL
1379 && request_after == MPI_REQUEST_NULL
1380 && (error_in_status ? status->MPI_ERROR == MPI_SUCCESS : True)
1381 && ( (shadow=find_shadow_Request(request_before)) != NULL) ) {
1382 /* The Irecv detailed in 'shadow' completed. Paint the result
1383 buffer, and delete the entry. */
1384 if (count_from_Status(&recv_count, shadow->datatype, status)) {
1385 make_mem_defined_if_addressable(shadow->buf, recv_count, shadow->datatype);
1386 if (opt_verbosity > 1)
1387 fprintf(stderr, "%s %5d: sReq- 0x%lx (completed)\n",
1388 preamble, my_pid, (unsigned long) request_before);
1390 delete_shadow_Request(request_before);
1395 /* --- Isend --- */
1396 /* rd: (buf,count,datatype) */
1397 /* wr: *request */
1398 static __inline__
1399 int generic_Isend(void *buf, int count, MPI_Datatype datatype,
1400 int dest, int tag, MPI_Comm comm,
1401 MPI_Request* request)
1403 OrigFn fn;
1404 int err;
1405 VALGRIND_GET_ORIG_FN(fn);
1406 before("{,B,S,R}Isend");
1407 check_mem_is_defined(buf, count, datatype);
1408 check_mem_is_addressable_untyped(request, sizeof(*request));
1409 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1410 CALL_FN_W_7W(err, fn, buf,count,datatype,dest,tag,comm,request);
1411 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1412 make_mem_defined_if_addressable_if_success_untyped(err, request, sizeof(*request));
1413 after("{,B,S,R}Isend", err);
1414 return err;
1416 int WRAPPER_FOR(PMPI_Isend)(void *buf, int count, MPI_Datatype datatype,
1417 int dest, int tag, MPI_Comm comm,
1418 MPI_Request* request) {
1419 return generic_Isend(buf,count,datatype, dest,tag,comm, request);
1421 int WRAPPER_FOR(PMPI_Ibsend)(void *buf, int count, MPI_Datatype datatype,
1422 int dest, int tag, MPI_Comm comm,
1423 MPI_Request* request) {
1424 return generic_Isend(buf,count,datatype, dest,tag,comm, request);
1426 int WRAPPER_FOR(PMPI_Issend)(void *buf, int count, MPI_Datatype datatype,
1427 int dest, int tag, MPI_Comm comm,
1428 MPI_Request* request) {
1429 return generic_Isend(buf,count,datatype, dest,tag,comm, request);
1431 int WRAPPER_FOR(PMPI_Irsend)(void *buf, int count, MPI_Datatype datatype,
1432 int dest, int tag, MPI_Comm comm,
1433 MPI_Request* request) {
1434 return generic_Isend(buf,count,datatype, dest,tag,comm, request);
1438 /* --- Irecv --- */
1439 /* pre: must be writable: (buf,count,datatype), *request
1440 post: make readable *request
1441 add a request->(buf,count,ty) binding to the
1442 shadow request table.
1444 int WRAPPER_FOR(PMPI_Irecv)( void* buf, int count, MPI_Datatype datatype,
1445 int source, int tag, MPI_Comm comm,
1446 MPI_Request* request )
1448 OrigFn fn;
1449 int err;
1450 VALGRIND_GET_ORIG_FN(fn);
1451 before("Irecv");
1452 check_mem_is_addressable(buf, count, datatype);
1453 check_mem_is_addressable_untyped(request, sizeof(*request));
1454 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1455 CALL_FN_W_7W(err, fn, buf,count,datatype,source,tag,comm,request);
1456 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1457 if (err == MPI_SUCCESS) {
1458 make_mem_defined_if_addressable_untyped(request, sizeof(*request));
1459 add_shadow_Request( *request, buf,count,datatype );
1461 after("Irecv", err);
1462 return err;
1465 /* --- Wait --- */
1466 /* The MPI1 spec (imprecisely) defines 3 request states:
1467 - "null" if the request is MPI_REQUEST_NULL
1468 - "inactive" if not "null" and not associated with ongoing comms
1469 - "active" if not "null" and is associated with ongoing comms
1471 int WRAPPER_FOR(PMPI_Wait)( MPI_Request* request,
1472 MPI_Status* status )
1474 MPI_Request request_before;
1475 MPI_Status fake_status;
1476 OrigFn fn;
1477 int err;
1478 VALGRIND_GET_ORIG_FN(fn);
1479 before("Wait");
1480 if (isMSI(status))
1481 status = &fake_status;
1482 check_mem_is_addressable_untyped(status, sizeof(MPI_Status));
1483 check_mem_is_defined_untyped(request, sizeof(MPI_Request));
1484 request_before = *request;
1485 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1486 CALL_FN_W_WW(err, fn, request,status);
1487 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1488 if (err == MPI_SUCCESS) {
1489 maybe_complete(False/*err in status?*/,
1490 request_before, *request, status);
1491 make_mem_defined_if_addressable_untyped(status, sizeof(MPI_Status));
1493 after("Wait", err);
1494 return err;
1497 /* --- Waitany --- */
1498 int WRAPPER_FOR(PMPI_Waitany)( int count,
1499 MPI_Request* requests,
1500 int* index,
1501 MPI_Status* status )
1503 MPI_Request* requests_before = NULL;
1504 MPI_Status fake_status;
1505 OrigFn fn;
1506 int err, i;
1507 VALGRIND_GET_ORIG_FN(fn);
1508 before("Waitany");
1509 if (isMSI(status))
1510 status = &fake_status;
1511 if (0) fprintf(stderr, "Waitany: %d\n", count);
1512 check_mem_is_addressable_untyped(index, sizeof(int));
1513 check_mem_is_addressable_untyped(status, sizeof(MPI_Status));
1514 for (i = 0; i < count; i++) {
1515 check_mem_is_defined_untyped(&requests[i], sizeof(MPI_Request));
1517 requests_before = clone_Request_array( count, requests );
1518 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1519 CALL_FN_W_WWWW(err, fn, count,requests,index,status);
1520 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1521 if (err == MPI_SUCCESS && *index >= 0 && *index < count) {
1522 maybe_complete(False/*err in status?*/,
1523 requests_before[*index], requests[*index], status);
1524 make_mem_defined_if_addressable_untyped(status, sizeof(MPI_Status));
1526 if (requests_before)
1527 free(requests_before);
1528 after("Waitany", err);
1529 return err;
1532 /* --- Waitall --- */
1533 int WRAPPER_FOR(PMPI_Waitall)( int count,
1534 MPI_Request* requests,
1535 MPI_Status* statuses )
1537 MPI_Request* requests_before = NULL;
1538 OrigFn fn;
1539 int err, i;
1540 Bool free_sta = False;
1541 VALGRIND_GET_ORIG_FN(fn);
1542 before("Waitall");
1543 if (0) fprintf(stderr, "Waitall: %d\n", count);
1544 if (isMSI(statuses)) {
1545 free_sta = True;
1546 statuses = malloc( (count < 0 ? 0 : count) * sizeof(MPI_Status) );
1548 for (i = 0; i < count; i++) {
1549 check_mem_is_addressable_untyped(&statuses[i], sizeof(MPI_Status));
1550 check_mem_is_defined_untyped(&requests[i], sizeof(MPI_Request));
1552 requests_before = clone_Request_array( count, requests );
1553 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1554 CALL_FN_W_WWW(err, fn, count,requests,statuses);
1555 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1556 if (err == MPI_SUCCESS /*complete success*/
1557 || err == MPI_ERR_IN_STATUS /* partial success */) {
1558 Bool e_i_s = err == MPI_ERR_IN_STATUS;
1559 for (i = 0; i < count; i++) {
1560 maybe_complete(e_i_s, requests_before[i], requests[i],
1561 &statuses[i]);
1562 make_mem_defined_if_addressable_untyped(&statuses[i],
1563 sizeof(MPI_Status));
1566 if (requests_before)
1567 free(requests_before);
1568 if (free_sta)
1569 free(statuses);
1570 after("Waitall", err);
1571 return err;
1574 /* --- Test --- */
1575 /* nonblocking version of Wait */
1576 int WRAPPER_FOR(PMPI_Test)( MPI_Request* request, int* flag,
1577 MPI_Status* status )
1579 MPI_Request request_before;
1580 MPI_Status fake_status;
1581 OrigFn fn;
1582 int err;
1583 VALGRIND_GET_ORIG_FN(fn);
1584 before("Test");
1585 if (isMSI(status))
1586 status = &fake_status;
1587 check_mem_is_addressable_untyped(status, sizeof(MPI_Status));
1588 check_mem_is_addressable_untyped(flag, sizeof(int));
1589 check_mem_is_defined_untyped(request, sizeof(MPI_Request));
1590 request_before = *request;
1591 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1592 CALL_FN_W_WWW(err, fn, request,flag,status);
1593 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1594 if (err == MPI_SUCCESS && *flag) {
1595 maybe_complete(False/*err in status?*/,
1596 request_before, *request, status);
1597 make_mem_defined_if_addressable_untyped(status, sizeof(MPI_Status));
1599 after("Test", err);
1600 return err;
1603 /* --- Testall --- */
1604 /* nonblocking version of Waitall */
1605 int WRAPPER_FOR(PMPI_Testall)( int count, MPI_Request* requests,
1606 int* flag, MPI_Status* statuses )
1608 MPI_Request* requests_before = NULL;
1609 OrigFn fn;
1610 int err, i;
1611 Bool free_sta = False;
1612 VALGRIND_GET_ORIG_FN(fn);
1613 before("Testall");
1614 if (0) fprintf(stderr, "Testall: %d\n", count);
1615 if (isMSI(statuses)) {
1616 free_sta = True;
1617 statuses = malloc( (count < 0 ? 0 : count) * sizeof(MPI_Status) );
1619 check_mem_is_addressable_untyped(flag, sizeof(int));
1620 for (i = 0; i < count; i++) {
1621 check_mem_is_addressable_untyped(&statuses[i], sizeof(MPI_Status));
1622 check_mem_is_defined_untyped(&requests[i], sizeof(MPI_Request));
1624 requests_before = clone_Request_array( count, requests );
1625 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1626 CALL_FN_W_WWWW(err, fn, count,requests,flag,statuses);
1627 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1628 /* Urk. Is the following "if (...)" really right? I don't know. */
1629 if (*flag
1630 && (err == MPI_SUCCESS /*complete success*/
1631 || err == MPI_ERR_IN_STATUS /* partial success */)) {
1632 Bool e_i_s = err == MPI_ERR_IN_STATUS;
1633 for (i = 0; i < count; i++) {
1634 maybe_complete(e_i_s, requests_before[i], requests[i],
1635 &statuses[i]);
1636 make_mem_defined_if_addressable_untyped(&statuses[i],
1637 sizeof(MPI_Status));
1640 if (requests_before)
1641 free(requests_before);
1642 if (free_sta)
1643 free(statuses);
1644 after("Testall", err);
1645 return err;
1648 /* --- Iprobe --- */
1649 /* pre: must-be-writable: *flag, *status */
1650 /* post: make-readable *flag
1651 if *flag==True make-defined *status */
1652 int WRAPPER_FOR(PMPI_Iprobe)(int source, int tag,
1653 MPI_Comm comm,
1654 int* flag, MPI_Status* status)
1656 MPI_Status fake_status;
1657 OrigFn fn;
1658 int err;
1659 VALGRIND_GET_ORIG_FN(fn);
1660 before("Iprobe");
1661 if (isMSI(status))
1662 status = &fake_status;
1663 check_mem_is_addressable_untyped(flag, sizeof(*flag));
1664 check_mem_is_addressable_untyped(status, sizeof(*status));
1665 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1666 CALL_FN_W_5W(err, fn, source,tag,comm,flag,status);
1667 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1668 if (err == MPI_SUCCESS) {
1669 make_mem_defined_if_addressable_untyped(flag, sizeof(*flag));
1670 if (*flag)
1671 make_mem_defined_if_addressable_untyped(status, sizeof(*status));
1673 after("Iprobe", err);
1674 return err;
1677 /* --- Probe --- */
1678 /* pre: must-be-writable *status */
1679 /* post: make-defined *status */
1680 int WRAPPER_FOR(PMPI_Probe)(int source, int tag,
1681 MPI_Comm comm, MPI_Status* status)
1683 MPI_Status fake_status;
1684 OrigFn fn;
1685 int err;
1686 VALGRIND_GET_ORIG_FN(fn);
1687 before("Probe");
1688 if (isMSI(status))
1689 status = &fake_status;
1690 check_mem_is_addressable_untyped(status, sizeof(*status));
1691 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1692 CALL_FN_W_WWWW(err, fn, source,tag,comm,status);
1693 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1694 make_mem_defined_if_addressable_if_success_untyped(err, status, sizeof(*status));
1695 after("Probe", err);
1696 return err;
1699 /* --- Cancel --- */
1700 /* Wrapping PMPI_Cancel is interesting only to the extent that we need
1701 to be able to detect when a request should be removed from our
1702 shadow table due to cancellation. */
1703 int WRAPPER_FOR(PMPI_Cancel)(MPI_Request* request)
1705 OrigFn fn;
1706 int err;
1707 MPI_Request tmp;
1708 VALGRIND_GET_ORIG_FN(fn);
1709 before("Cancel");
1710 check_mem_is_addressable_untyped(request, sizeof(*request));
1711 tmp = *request;
1712 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1713 CALL_FN_W_W(err, fn, request);
1714 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1715 if (err == MPI_SUCCESS)
1716 delete_shadow_Request(tmp);
1717 after("Cancel", err);
1718 return err;
1722 /*------------------------------------------------------------*/
1723 /*--- ---*/
1724 /*--- Sec 3.10, Send-receive ---*/
1725 /*--- ---*/
1726 /*------------------------------------------------------------*/
1728 /* --- Sendrecv --- */
1729 /* pre: must be readable: (sendbuf,sendcount,sendtype)
1730 must be writable: (recvbuf,recvcount,recvtype)
1731 post: make readable: (recvbuf,recvcount_actual,datatype)
1732 where recvcount_actual is determined from *status
1734 int WRAPPER_FOR(PMPI_Sendrecv)(
1735 void *sendbuf, int sendcount, MPI_Datatype sendtype,
1736 int dest, int sendtag,
1737 void *recvbuf, int recvcount, MPI_Datatype recvtype,
1738 int source, int recvtag,
1739 MPI_Comm comm, MPI_Status *status)
1741 MPI_Status fake_status;
1742 OrigFn fn;
1743 int err, recvcount_actual = 0;
1744 VALGRIND_GET_ORIG_FN(fn);
1745 before("Sendrecv");
1746 if (isMSI(status))
1747 status = &fake_status;
1748 check_mem_is_defined(sendbuf, sendcount, sendtype);
1749 check_mem_is_addressable(recvbuf, recvcount, recvtype);
1750 check_mem_is_addressable_untyped(status, sizeof(*status));
1751 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1752 CALL_FN_W_12W(err, fn, sendbuf,sendcount,sendtype,dest,sendtag,
1753 recvbuf,recvcount,recvtype,source,recvtag,
1754 comm,status);
1755 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1756 make_mem_defined_if_addressable_if_success_untyped(err, status, sizeof(*status));
1757 if (err == MPI_SUCCESS
1758 && count_from_Status(&recvcount_actual,recvtype,status)) {
1759 make_mem_defined_if_addressable(recvbuf, recvcount_actual, recvtype);
1761 after("Sendrecv", err);
1762 return err;
1766 /*------------------------------------------------------------*/
1767 /*--- ---*/
1768 /*--- Sec 3.12, Derived datatypes ---*/
1769 /*--- ---*/
1770 /*------------------------------------------------------------*/
1772 /* --- Address --- */
1773 /* Does this have anything worth checking? */
1774 HAS_NO_WRAPPER(Address)
1776 /* --- MPI 2 stuff --- */
1777 /* Type_extent, Type_get_contents and Type_get_envelope sometimes get
1778 used intensively by the type walker (walk_type). There's no reason
1779 why they couldn't be properly wrapped if needed, but doing so slows
1780 everything down, so don't bother until needed. */
1781 HAS_NO_WRAPPER(Type_extent)
1782 HAS_NO_WRAPPER(Type_get_contents)
1783 HAS_NO_WRAPPER(Type_get_envelope)
1785 /* --- Type_commit --- */
1786 int WRAPPER_FOR(PMPI_Type_commit)( MPI_Datatype* ty )
1788 OrigFn fn;
1789 int err;
1790 VALGRIND_GET_ORIG_FN(fn);
1791 before("Type_commit");
1792 check_mem_is_defined_untyped(ty, sizeof(*ty));
1793 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1794 CALL_FN_W_W(err, fn, ty);
1795 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1796 after("Type_commit", err);
1797 return err;
1800 /* --- Type_free --- */
1801 int WRAPPER_FOR(PMPI_Type_free)( MPI_Datatype* ty )
1803 OrigFn fn;
1804 int err;
1805 VALGRIND_GET_ORIG_FN(fn);
1806 before("Type_free");
1807 check_mem_is_defined_untyped(ty, sizeof(*ty));
1808 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1809 CALL_FN_W_W(err, fn, ty);
1810 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1811 after("Type_free", err);
1812 return err;
1816 /*------------------------------------------------------------*/
1817 /*--- ---*/
1818 /*--- Sec 3.13, Pack and unpack ---*/
1819 /*--- ---*/
1820 /*------------------------------------------------------------*/
1822 /* --- Pack --- */
1823 /* pre: must be readable: position
1824 must be readable: (inbuf,incount,datatype)
1825 must be writable: outbuf[0 .. outsize-1]
1826 must be writable: outbuf[*position ..
1827 *position - 1
1828 + however much space PMPI_Pack_size
1829 says we will need]
1830 post: make readable: outbuf[old *position .. new *position]
1832 int WRAPPER_FOR(PMPI_Pack)( void* inbuf, int incount, MPI_Datatype datatype,
1833 void* outbuf, int outsize,
1834 int* position, MPI_Comm comm )
1836 OrigFn fn;
1837 int err, szB = 0;
1838 int position_ORIG = *position;
1839 VALGRIND_GET_ORIG_FN(fn);
1840 before("Pack");
1841 /* stay sane */
1842 check_mem_is_defined_untyped(position, sizeof(*position));
1843 /* check input */
1844 check_mem_is_defined(inbuf, incount, datatype);
1845 /* check output area's stated bounds make sense */
1846 check_mem_is_addressable_untyped(outbuf, outsize);
1847 /* check output area's actual used size properly */
1848 err = PMPI_Pack_size( incount, datatype, comm, &szB );
1849 if (err == MPI_SUCCESS && szB > 0) {
1850 check_mem_is_addressable_untyped(
1851 ((char*)outbuf) + position_ORIG, szB
1855 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1856 CALL_FN_W_7W(err, fn, inbuf,incount,datatype, outbuf,outsize,position, comm);
1857 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1859 if (err == MPI_SUCCESS && (*position) > position_ORIG) {
1860 /* paint output */
1861 make_mem_defined_if_addressable_untyped(
1862 ((char*)outbuf) + position_ORIG, *position - position_ORIG
1865 after("Pack", err);
1866 return err;
1869 /* --- Unpack --- */
1870 /* pre: must be readable: position
1871 must be writable: (outbuf,outcount,datatype)
1872 must be writable: outbuf[0 .. outsize-1]
1873 must be writable: outbuf[*position ..
1874 *position - 1
1875 + however much space PMPI_Pack_size
1876 says we will need]
1877 post: make readable: (outbuf,outcount,datatype)
1878 and also do a readability check of
1879 inbuf[old *position .. new *position]
1881 int WRAPPER_FOR(PMPI_Unpack)( void* inbuf, int insize, int* position,
1882 void* outbuf, int outcount, MPI_Datatype datatype,
1883 MPI_Comm comm )
1885 OrigFn fn;
1886 int err, szB = 0;
1887 int position_ORIG = *position;
1888 VALGRIND_GET_ORIG_FN(fn);
1889 before("Unpack");
1890 /* stay sane */
1891 check_mem_is_defined_untyped(position, sizeof(*position));
1892 /* check output area is accessible */
1893 check_mem_is_addressable(outbuf, outcount, datatype);
1894 /* check input area's stated bounds make sense */
1895 check_mem_is_addressable_untyped(inbuf, insize);
1896 /* check input area's actual used size properly */
1897 err = PMPI_Pack_size( outcount, datatype, comm, &szB );
1898 if (err == MPI_SUCCESS && szB > 0) {
1899 check_mem_is_addressable_untyped(
1900 ((char*)inbuf) + position_ORIG, szB
1904 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1905 CALL_FN_W_7W(err, fn, inbuf,insize,position, outbuf,outcount,datatype, comm);
1906 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1908 if (err == MPI_SUCCESS && (*position) > position_ORIG) {
1909 /* recheck input more carefully */
1910 check_mem_is_defined_untyped(
1911 ((char*)inbuf) + position_ORIG, *position - position_ORIG
1913 /* paint output */
1914 make_mem_defined_if_addressable( outbuf, outcount, datatype );
1916 after("Unpack", err);
1917 return err;
1921 /*------------------------------------------------------------*/
1922 /*--- ---*/
1923 /*--- Sec 4.4, Broadcast ---*/
1924 /*--- ---*/
1925 /*------------------------------------------------------------*/
1927 /* --- Bcast --- */
1928 /* pre: must-be-readable (buffer,count,datatype) for rank==root
1929 must-be-writable (buffer,count,datatype) for rank!=root
1930 post: make-readable (buffer,count,datatype) for all
1932 Resulting behaviour is: if root sends uninitialised stuff, then
1933 V complains, but then all ranks, including itself, see the buffer
1934 as initialised after that.
1936 int WRAPPER_FOR(PMPI_Bcast)(void *buffer, int count,
1937 MPI_Datatype datatype,
1938 int root, MPI_Comm comm)
1940 OrigFn fn;
1941 int err;
1942 Bool i_am_sender;
1943 VALGRIND_GET_ORIG_FN(fn);
1944 before("Bcast");
1945 i_am_sender = root == comm_rank(comm);
1946 if (i_am_sender) {
1947 check_mem_is_defined(buffer, count, datatype);
1948 } else {
1949 check_mem_is_addressable(buffer, count, datatype);
1951 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1952 CALL_FN_W_5W(err, fn, buffer,count,datatype,root,comm);
1953 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1954 make_mem_defined_if_addressable_if_success(err, buffer, count, datatype);
1955 after("Bcast", err);
1956 return err;
1960 /*------------------------------------------------------------*/
1961 /*--- ---*/
1962 /*--- Sec 4.5, Gather ---*/
1963 /*--- ---*/
1964 /*------------------------------------------------------------*/
1966 /* --- Gather --- */
1967 /* JRS 20060217: I don't really understand this. Each process is
1968 going to send sendcount items of type sendtype to the root. So
1969 the root is going to receive comm_size*sendcount items of type
1970 sendtype (right?) So why specify recvcount and recvtype?
1972 Anyway, assuming the MPI Spec is correct (seems likely :-) we have:
1974 pre: (all) must be readable: (sendbuf,sendcount,sendtype)
1975 (root only): must be writable: (recvbuf,recvcount * comm_size,recvtype)
1976 post: (root only): make readable: (recvbuf,recvcount * comm_size,recvtype)
1978 int WRAPPER_FOR(PMPI_Gather)(
1979 void *sendbuf, int sendcount, MPI_Datatype sendtype,
1980 void *recvbuf, int recvcount, MPI_Datatype recvtype,
1981 int root, MPI_Comm comm)
1983 OrigFn fn;
1984 int err, me, sz;
1985 VALGRIND_GET_ORIG_FN(fn);
1986 before("Gather");
1987 me = comm_rank(comm);
1988 sz = comm_size(comm);
1989 check_mem_is_defined(sendbuf, sendcount, sendtype);
1990 if (me == root)
1991 check_mem_is_addressable(recvbuf, recvcount * sz, recvtype);
1992 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1993 CALL_FN_W_8W(err, fn, sendbuf,sendcount,sendtype,
1994 recvbuf,recvcount,recvtype,
1995 root,comm);
1996 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1997 if (me == root)
1998 make_mem_defined_if_addressable_if_success(err, recvbuf, recvcount * sz, recvtype);
1999 after("Gather", err);
2000 return err;
2004 /*------------------------------------------------------------*/
2005 /*--- ---*/
2006 /*--- Sec 4.6, Scatter ---*/
2007 /*--- ---*/
2008 /*------------------------------------------------------------*/
2010 /* pre: (root only): must be readable: (sendbuf,sendcount * comm_size,sendtype)
2011 (all): must be writable: (recvbuf,recvbuf,recvtype)
2012 post: (all): make defined: (recvbuf,recvbuf,recvtype)
2014 int WRAPPER_FOR(PMPI_Scatter)(
2015 void* sendbuf, int sendcount, MPI_Datatype sendtype,
2016 void* recvbuf, int recvcount, MPI_Datatype recvtype,
2017 int root, MPI_Comm comm)
2019 OrigFn fn;
2020 int err, me, sz;
2021 VALGRIND_GET_ORIG_FN(fn);
2022 before("Scatter");
2023 me = comm_rank(comm);
2024 sz = comm_size(comm);
2025 check_mem_is_addressable(recvbuf, recvcount, recvtype);
2026 if (me == root)
2027 check_mem_is_defined(sendbuf, sendcount * sz, sendtype);
2028 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2029 CALL_FN_W_8W(err, fn, sendbuf,sendcount,sendtype,
2030 recvbuf,recvcount,recvtype,
2031 root,comm);
2032 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2033 make_mem_defined_if_addressable_if_success(err, recvbuf, recvcount, recvtype);
2034 after("Scatter", err);
2035 return err;
2039 /*------------------------------------------------------------*/
2040 /*--- ---*/
2041 /*--- Sec 4.8, All-to-All Scatter/Gather ---*/
2042 /*--- ---*/
2043 /*------------------------------------------------------------*/
2045 /* pre: (all) must be readable: (sendbuf,sendcount * comm_size,sendtype)
2046 (all) must be writable: (recvbuf,recvcount * comm_size,recvtype)
2047 post: (all) make defined: (recvbuf,recvcount * comm_size,recvtype)
2049 int WRAPPER_FOR(PMPI_Alltoall)(
2050 void* sendbuf, int sendcount, MPI_Datatype sendtype,
2051 void* recvbuf, int recvcount, MPI_Datatype recvtype,
2052 MPI_Comm comm)
2054 OrigFn fn;
2055 int err, sz;
2056 VALGRIND_GET_ORIG_FN(fn);
2057 before("Alltoall");
2058 sz = comm_size(comm);
2059 check_mem_is_defined(sendbuf, sendcount * sz, sendtype);
2060 check_mem_is_addressable(recvbuf, recvcount * sz, recvtype);
2061 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2062 CALL_FN_W_7W(err, fn, sendbuf,sendcount,sendtype,
2063 recvbuf,recvcount,recvtype,
2064 comm);
2065 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2066 make_mem_defined_if_addressable_if_success(err, recvbuf, recvcount * sz, recvtype);
2067 after("Alltoall", err);
2068 return err;
2072 /*------------------------------------------------------------*/
2073 /*--- ---*/
2074 /*--- Sec 4.9, Global Reduction Operations ---*/
2075 /*--- ---*/
2076 /*------------------------------------------------------------*/
2078 /* --- Reduce --- */
2079 /* rd: (sendbuf,count,datatype) for all
2080 wr: (recvbuf,count,datatype) but only for rank == root
2082 int WRAPPER_FOR(PMPI_Reduce)(void *sendbuf, void *recvbuf,
2083 int count,
2084 MPI_Datatype datatype, MPI_Op op,
2085 int root, MPI_Comm comm)
2087 OrigFn fn;
2088 int err;
2089 Bool i_am_root;
2090 VALGRIND_GET_ORIG_FN(fn);
2091 before("Reduce");
2092 i_am_root = root == comm_rank(comm);
2093 check_mem_is_defined(sendbuf, count, datatype);
2094 if (i_am_root)
2095 check_mem_is_addressable(recvbuf, count, datatype);
2096 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2097 CALL_FN_W_7W(err, fn, sendbuf,recvbuf,count,datatype,op,root,comm);
2098 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2099 if (i_am_root)
2100 make_mem_defined_if_addressable_if_success(err, recvbuf, count, datatype);
2101 after("Reduce", err);
2102 return err;
2106 /* --- Allreduce --- */
2107 /* rd: (sendbuf,count,datatype) for all
2108 wr: (recvbuf,count,datatype) for all
2110 int WRAPPER_FOR(PMPI_Allreduce)(void *sendbuf, void *recvbuf,
2111 int count,
2112 MPI_Datatype datatype, MPI_Op op,
2113 MPI_Comm comm)
2115 OrigFn fn;
2116 int err;
2117 VALGRIND_GET_ORIG_FN(fn);
2118 before("Allreduce");
2119 check_mem_is_defined(sendbuf, count, datatype);
2120 check_mem_is_addressable(recvbuf, count, datatype);
2121 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2122 CALL_FN_W_6W(err, fn, sendbuf,recvbuf,count,datatype,op,comm);
2123 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2124 make_mem_defined_if_addressable_if_success(err, recvbuf, count, datatype);
2125 after("Allreduce", err);
2126 return err;
2130 /* --- Op_create --- */
2131 /* This is a bit dubious. I suppose it takes 'function' and
2132 writes something at *op, but who knows what an MPI_Op is?
2133 Can we safely do 'sizeof' on it? */
2134 int WRAPPER_FOR(PMPI_Op_create)( MPI_User_function* function,
2135 int commute,
2136 MPI_Op* op )
2138 OrigFn fn;
2139 int err;
2140 VALGRIND_GET_ORIG_FN(fn);
2141 before("Op_create");
2142 check_mem_is_addressable_untyped(op, sizeof(*op));
2143 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2144 CALL_FN_W_WWW(err, fn, function,commute,op);
2145 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2146 make_mem_defined_if_addressable_if_success_untyped(err, op, sizeof(*op));
2147 after("Op_create", err);
2148 return err;
2152 /*------------------------------------------------------------*/
2153 /*--- ---*/
2154 /*--- Sec 5.4, Communicator management ---*/
2155 /*--- ---*/
2156 /*------------------------------------------------------------*/
2158 /* Hardly seems worth wrapping Comm_rank and Comm_size, but
2159 since it's done now .. */
2161 /* --- Comm_create --- */
2162 /* Let normal memcheck tracking handle this. */
2163 int WRAPPER_FOR(PMPI_Comm_create)(MPI_Comm comm, MPI_Group group,
2164 MPI_Comm* newcomm)
2166 OrigFn fn;
2167 int err;
2168 VALGRIND_GET_ORIG_FN(fn);
2169 before("Comm_create");
2170 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2171 CALL_FN_W_WWW(err, fn, comm,group,newcomm);
2172 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2173 after("Comm_create", err);
2174 return err;
2177 /* --- Comm_dup --- */
2178 /* Let normal memcheck tracking handle this. */
2179 int WRAPPER_FOR(PMPI_Comm_dup)(MPI_Comm comm, MPI_Comm* newcomm)
2181 OrigFn fn;
2182 int err;
2183 VALGRIND_GET_ORIG_FN(fn);
2184 before("Comm_dup");
2185 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2186 CALL_FN_W_WW(err, fn, comm,newcomm);
2187 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2188 after("Comm_dup", err);
2189 return err;
2192 /* --- Comm_free --- */
2193 /* Let normal memcheck tracking handle this. */
2194 int WRAPPER_FOR(PMPI_Comm_free)(MPI_Comm* comm)
2196 OrigFn fn;
2197 int err;
2198 VALGRIND_GET_ORIG_FN(fn);
2199 before("Comm_free");
2200 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2201 CALL_FN_W_W(err, fn, comm);
2202 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2203 after("Comm_free", err);
2204 return err;
2207 /* --- Comm_rank --- */
2208 /* wr: (rank, sizeof(*rank)) */
2209 int WRAPPER_FOR(PMPI_Comm_rank)(MPI_Comm comm, int *rank)
2211 OrigFn fn;
2212 int err;
2213 VALGRIND_GET_ORIG_FN(fn);
2214 before("Comm_rank");
2215 check_mem_is_addressable_untyped(rank, sizeof(*rank));
2216 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2217 CALL_FN_W_WW(err, fn, comm,rank);
2218 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2219 make_mem_defined_if_addressable_if_success_untyped(err, rank, sizeof(*rank));
2220 after("Comm_rank", err);
2221 return err;
2224 /* --- Comm_size --- */
2225 /* wr: (size, sizeof(*size)) */
2226 int WRAPPER_FOR(PMPI_Comm_size)(MPI_Comm comm, int *size)
2228 OrigFn fn;
2229 int err;
2230 VALGRIND_GET_ORIG_FN(fn);
2231 before("Comm_size");
2232 check_mem_is_addressable_untyped(size, sizeof(*size));
2233 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2234 CALL_FN_W_WW(err, fn, comm,size);
2235 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2236 make_mem_defined_if_addressable_if_success_untyped(err, size, sizeof(*size));
2237 after("Comm_size", err);
2238 return err;
2242 /*------------------------------------------------------------*/
2243 /*--- ---*/
2244 /*--- Sec 5.7, Caching ---*/
2245 /*--- ---*/
2246 /*------------------------------------------------------------*/
2249 /*------------------------------------------------------------*/
2250 /*--- ---*/
2251 /*--- Sec 7.3, Error codes and classes ---*/
2252 /*--- ---*/
2253 /*------------------------------------------------------------*/
2255 /* --- Error_string --- */
2256 int WRAPPER_FOR(PMPI_Error_string)( int errorcode, char* string,
2257 int* resultlen )
2259 OrigFn fn;
2260 int err;
2261 VALGRIND_GET_ORIG_FN(fn);
2262 before("Error_string");
2263 check_mem_is_addressable_untyped(resultlen, sizeof(int));
2264 check_mem_is_addressable_untyped(string, MPI_MAX_ERROR_STRING);
2265 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2266 CALL_FN_W_WWW(err, fn, errorcode,string,resultlen);
2267 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2268 /* Don't bother to paint the result; we assume the real function
2269 will have filled it with defined characters :-) */
2270 after("Error_string", err);
2271 return err;
2275 /*------------------------------------------------------------*/
2276 /*--- ---*/
2277 /*--- Sec 7.5, Startup ---*/
2278 /*--- ---*/
2279 /*------------------------------------------------------------*/
2281 /* --- Init --- */
2282 /* rd: *argc, *argv[0 .. *argc-1] */
2283 long WRAPPER_FOR(PMPI_Init)(int *argc, char ***argv)
2285 OrigFn fn;
2286 int err;
2287 VALGRIND_GET_ORIG_FN(fn);
2288 before("Init");
2289 if (argc) {
2290 check_mem_is_defined_untyped(argc, sizeof(*argc));
2292 if (argc && argv) {
2293 check_mem_is_defined_untyped(*argv, *argc * sizeof(**argv));
2295 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2296 CALL_FN_W_WW(err, fn, argc,argv);
2297 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2298 after("Init", err);
2299 if (opt_initkludge)
2300 return (long)(void*)&mpiwrap_walk_type_EXTERNALLY_VISIBLE;
2301 else
2302 return (long)err;
2305 /* --- Initialized --- */
2306 int WRAPPER_FOR(PMPI_Initialized)(int* flag)
2308 OrigFn fn;
2309 int err;
2310 VALGRIND_GET_ORIG_FN(fn);
2311 before("Initialized");
2312 check_mem_is_addressable_untyped(flag, sizeof(int));
2313 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2314 CALL_FN_W_W(err, fn, flag);
2315 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2316 make_mem_defined_if_addressable_if_success_untyped(err, flag, sizeof(int));
2317 after("Initialized", err);
2318 return err;
2321 /* --- Finalize --- */
2322 int WRAPPER_FOR(PMPI_Finalize)(void)
2324 OrigFn fn;
2325 int err;
2326 VALGRIND_GET_ORIG_FN(fn);
2327 before("Finalize");
2328 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2329 CALL_FN_W_v(err, fn);
2330 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2331 after("Finalize", err);
2332 return err;
2336 /*------------------------------------------------------------*/
2337 /*--- ---*/
2338 /*--- Default wrappers for all remaining functions ---*/
2339 /*--- ---*/
2340 /*------------------------------------------------------------*/
2342 /* Boilerplate for default wrappers. */
2343 #define DEFAULT_WRAPPER_PREAMBLE(basename) \
2344 OrigFn fn; \
2345 UWord res; \
2346 static int complaints = 1; \
2347 VALGRIND_GET_ORIG_FN(fn); \
2348 before(#basename); \
2349 if (opt_missing >= 2) { \
2350 barf("no wrapper for PMPI_" #basename \
2351 ",\n\t\t\t and you have " \
2352 "requested strict checking"); \
2354 if (opt_missing == 1 && complaints > 0) { \
2355 fprintf(stderr, "%s %5d: warning: no wrapper " \
2356 "for PMPI_" #basename "\n", \
2357 preamble, my_pid); \
2358 complaints--; \
2361 #define DEFAULT_WRAPPER_W_0W(basename) \
2362 UWord WRAPPER_FOR(PMPI_##basename)( void ) \
2364 DEFAULT_WRAPPER_PREAMBLE(basename) \
2365 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2366 CALL_FN_W_v(res, fn); \
2367 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2368 return res; \
2371 #define DEFAULT_WRAPPER_W_1W(basename) \
2372 UWord WRAPPER_FOR(PMPI_##basename)( UWord a1 ) \
2374 DEFAULT_WRAPPER_PREAMBLE(basename) \
2375 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2376 CALL_FN_W_W(res, fn, a1); \
2377 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2378 return res; \
2381 #define DEFAULT_WRAPPER_W_2W(basename) \
2382 UWord WRAPPER_FOR(PMPI_##basename)( UWord a1, UWord a2 ) \
2384 DEFAULT_WRAPPER_PREAMBLE(basename) \
2385 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2386 CALL_FN_W_WW(res, fn, a1,a2); \
2387 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2388 return res; \
2391 #define DEFAULT_WRAPPER_W_3W(basename) \
2392 UWord WRAPPER_FOR(PMPI_##basename) \
2393 ( UWord a1, UWord a2, UWord a3 ) \
2395 DEFAULT_WRAPPER_PREAMBLE(basename) \
2396 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2397 CALL_FN_W_WWW(res, fn, a1,a2,a3); \
2398 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2399 return res; \
2402 #define DEFAULT_WRAPPER_W_4W(basename) \
2403 UWord WRAPPER_FOR(PMPI_##basename) \
2404 ( UWord a1, UWord a2, UWord a3, UWord a4 ) \
2406 DEFAULT_WRAPPER_PREAMBLE(basename) \
2407 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2408 CALL_FN_W_WWWW(res, fn, a1,a2,a3,a4); \
2409 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2410 return res; \
2413 #define DEFAULT_WRAPPER_W_5W(basename) \
2414 UWord WRAPPER_FOR(PMPI_##basename) \
2415 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5 ) \
2417 DEFAULT_WRAPPER_PREAMBLE(basename) \
2418 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2419 CALL_FN_W_5W(res, fn, a1,a2,a3,a4,a5); \
2420 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2421 return res; \
2424 #define DEFAULT_WRAPPER_W_6W(basename) \
2425 UWord WRAPPER_FOR(PMPI_##basename) \
2426 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2427 UWord a6 ) \
2429 DEFAULT_WRAPPER_PREAMBLE(basename) \
2430 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2431 CALL_FN_W_6W(res, fn, a1,a2,a3,a4,a5,a6); \
2432 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2433 return res; \
2436 #define DEFAULT_WRAPPER_W_7W(basename) \
2437 UWord WRAPPER_FOR(PMPI_##basename) \
2438 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2439 UWord a6, UWord a7 ) \
2441 DEFAULT_WRAPPER_PREAMBLE(basename) \
2442 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2443 CALL_FN_W_7W(res, fn, a1,a2,a3,a4,a5,a6,a7); \
2444 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2445 return res; \
2448 #define DEFAULT_WRAPPER_W_8W(basename) \
2449 UWord WRAPPER_FOR(PMPI_##basename) \
2450 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2451 UWord a6, UWord a7, UWord a8 ) \
2453 DEFAULT_WRAPPER_PREAMBLE(basename) \
2454 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2455 CALL_FN_W_8W(res, fn, a1,a2,a3,a4,a5,a6,a7,a8); \
2456 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2457 return res; \
2460 #define DEFAULT_WRAPPER_W_9W(basename) \
2461 UWord WRAPPER_FOR(PMPI_##basename) \
2462 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2463 UWord a6, UWord a7, UWord a8, UWord a9 ) \
2465 DEFAULT_WRAPPER_PREAMBLE(basename) \
2466 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2467 CALL_FN_W_9W(res, fn, a1,a2,a3,a4,a5,a6,a7,a8,a9); \
2468 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2469 return res; \
2472 #define DEFAULT_WRAPPER_W_10W(basename) \
2473 UWord WRAPPER_FOR(PMPI_##basename) \
2474 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2475 UWord a6, UWord a7, UWord a8, UWord a9, UWord a10 ) \
2477 DEFAULT_WRAPPER_PREAMBLE(basename) \
2478 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2479 CALL_FN_W_10W(res, fn, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10); \
2480 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2481 return res; \
2484 #define DEFAULT_WRAPPER_W_12W(basename) \
2485 UWord WRAPPER_FOR(PMPI_##basename) \
2486 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2487 UWord a6, UWord a7, UWord a8, UWord a9, UWord a10, \
2488 UWord a11, UWord a12 ) \
2490 DEFAULT_WRAPPER_PREAMBLE(basename) \
2491 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2492 CALL_FN_W_12W(res, fn, a1,a2,a3,a4,a5,a6, \
2493 a7,a8,a9,a10,a11,a12); \
2494 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2495 return res; \
2499 /* Canned summary of MPI-1.1/MPI-2 entry points, as derived from mpi.h
2500 from Open MPI svn rev 9191 (somewhere between Open MPI versions
2501 1.0.1 and 1.1.0). */
2503 /* If a function is commented out in this list, it's because it has a
2504 proper wrapper written elsewhere (above here). */
2506 DEFAULT_WRAPPER_W_2W(Abort)
2507 DEFAULT_WRAPPER_W_9W(Accumulate)
2508 DEFAULT_WRAPPER_W_1W(Add_error_class)
2509 DEFAULT_WRAPPER_W_2W(Add_error_code)
2510 DEFAULT_WRAPPER_W_2W(Add_error_string)
2511 /* DEFAULT_WRAPPER_W_2W(Address) */
2512 DEFAULT_WRAPPER_W_7W(Allgather)
2513 DEFAULT_WRAPPER_W_8W(Allgatherv)
2514 DEFAULT_WRAPPER_W_3W(Alloc_mem)
2515 /* DEFAULT_WRAPPER_W_6W(Allreduce) */
2516 /* DEFAULT_WRAPPER_W_7W(Alltoall) */
2517 DEFAULT_WRAPPER_W_9W(Alltoallv)
2518 DEFAULT_WRAPPER_W_9W(Alltoallw)
2519 DEFAULT_WRAPPER_W_2W(Attr_delete)
2520 DEFAULT_WRAPPER_W_4W(Attr_get)
2521 DEFAULT_WRAPPER_W_3W(Attr_put)
2522 DEFAULT_WRAPPER_W_1W(Barrier)
2523 /* DEFAULT_WRAPPER_W_5W(Bcast) */
2524 /* DEFAULT_WRAPPER_W_6W(Bsend) */
2525 DEFAULT_WRAPPER_W_7W(Bsend_init)
2526 DEFAULT_WRAPPER_W_2W(Buffer_attach)
2527 DEFAULT_WRAPPER_W_2W(Buffer_detach)
2528 /* DEFAULT_WRAPPER_W_1W(Cancel) */
2529 DEFAULT_WRAPPER_W_4W(Cart_coords)
2530 DEFAULT_WRAPPER_W_6W(Cart_create)
2531 DEFAULT_WRAPPER_W_5W(Cart_get)
2532 DEFAULT_WRAPPER_W_5W(Cart_map)
2533 DEFAULT_WRAPPER_W_3W(Cart_rank)
2534 DEFAULT_WRAPPER_W_5W(Cart_shift)
2535 DEFAULT_WRAPPER_W_3W(Cart_sub)
2536 DEFAULT_WRAPPER_W_2W(Cartdim_get)
2537 DEFAULT_WRAPPER_W_1W(Close_port)
2538 DEFAULT_WRAPPER_W_5W(Comm_accept)
2539 DEFAULT_WRAPPER_W_1W(Comm_c2f)
2540 DEFAULT_WRAPPER_W_2W(Comm_call_errhandler)
2541 DEFAULT_WRAPPER_W_3W(Comm_compare)
2542 DEFAULT_WRAPPER_W_5W(Comm_connect)
2543 DEFAULT_WRAPPER_W_2W(Comm_create_errhandler)
2544 DEFAULT_WRAPPER_W_4W(Comm_create_keyval)
2545 /* DEFAULT_WRAPPER_W_3W(Comm_create) */
2546 DEFAULT_WRAPPER_W_2W(Comm_delete_attr)
2547 DEFAULT_WRAPPER_W_1W(Comm_disconnect)
2548 /* DEFAULT_WRAPPER_W_2W(Comm_dup) */
2549 DEFAULT_WRAPPER_W_1W(Comm_f2c)
2550 DEFAULT_WRAPPER_W_1W(Comm_free_keyval)
2551 /* DEFAULT_WRAPPER_W_1W(Comm_free) */
2552 DEFAULT_WRAPPER_W_4W(Comm_get_attr)
2553 DEFAULT_WRAPPER_W_2W(Comm_get_errhandler)
2554 DEFAULT_WRAPPER_W_3W(Comm_get_name)
2555 DEFAULT_WRAPPER_W_1W(Comm_get_parent)
2556 DEFAULT_WRAPPER_W_2W(Comm_group)
2557 DEFAULT_WRAPPER_W_2W(Comm_join)
2558 /* DEFAULT_WRAPPER_W_2W(Comm_rank) */
2559 DEFAULT_WRAPPER_W_2W(Comm_remote_group)
2560 DEFAULT_WRAPPER_W_2W(Comm_remote_size)
2561 DEFAULT_WRAPPER_W_3W(Comm_set_attr)
2562 DEFAULT_WRAPPER_W_2W(Comm_set_errhandler)
2563 DEFAULT_WRAPPER_W_2W(Comm_set_name)
2564 /* DEFAULT_WRAPPER_W_2W(Comm_size) */
2565 DEFAULT_WRAPPER_W_8W(Comm_spawn)
2566 DEFAULT_WRAPPER_W_9W(Comm_spawn_multiple)
2567 DEFAULT_WRAPPER_W_4W(Comm_split)
2568 DEFAULT_WRAPPER_W_2W(Comm_test_inter)
2569 DEFAULT_WRAPPER_W_3W(Dims_create)
2570 DEFAULT_WRAPPER_W_1W(Errhandler_c2f)
2571 DEFAULT_WRAPPER_W_2W(Errhandler_create)
2572 DEFAULT_WRAPPER_W_1W(Errhandler_f2c)
2573 DEFAULT_WRAPPER_W_1W(Errhandler_free)
2574 DEFAULT_WRAPPER_W_2W(Errhandler_get)
2575 DEFAULT_WRAPPER_W_2W(Errhandler_set)
2576 DEFAULT_WRAPPER_W_2W(Error_class)
2577 /* DEFAULT_WRAPPER_W_3W(Error_string) */
2578 DEFAULT_WRAPPER_W_6W(Exscan)
2579 DEFAULT_WRAPPER_W_1W(File_c2f)
2580 DEFAULT_WRAPPER_W_1W(File_f2c)
2581 DEFAULT_WRAPPER_W_2W(File_call_errhandler)
2582 DEFAULT_WRAPPER_W_2W(File_create_errhandler)
2583 DEFAULT_WRAPPER_W_2W(File_set_errhandler)
2584 DEFAULT_WRAPPER_W_2W(File_get_errhandler)
2585 DEFAULT_WRAPPER_W_5W(File_open)
2586 DEFAULT_WRAPPER_W_1W(File_close)
2587 DEFAULT_WRAPPER_W_2W(File_delete)
2588 DEFAULT_WRAPPER_W_2W(File_set_size)
2589 DEFAULT_WRAPPER_W_2W(File_preallocate)
2590 DEFAULT_WRAPPER_W_2W(File_get_size)
2591 DEFAULT_WRAPPER_W_2W(File_get_group)
2592 DEFAULT_WRAPPER_W_2W(File_get_amode)
2593 DEFAULT_WRAPPER_W_2W(File_set_info)
2594 DEFAULT_WRAPPER_W_2W(File_get_info)
2595 DEFAULT_WRAPPER_W_6W(File_set_view)
2596 DEFAULT_WRAPPER_W_5W(File_get_view)
2597 DEFAULT_WRAPPER_W_6W(File_read_at)
2598 DEFAULT_WRAPPER_W_6W(File_read_at_all)
2599 DEFAULT_WRAPPER_W_6W(File_write_at)
2600 DEFAULT_WRAPPER_W_6W(File_write_at_all)
2601 DEFAULT_WRAPPER_W_6W(File_iread_at)
2602 DEFAULT_WRAPPER_W_6W(File_iwrite_at)
2603 DEFAULT_WRAPPER_W_5W(File_read)
2604 DEFAULT_WRAPPER_W_5W(File_read_all)
2605 DEFAULT_WRAPPER_W_5W(File_write)
2606 DEFAULT_WRAPPER_W_5W(File_write_all)
2607 DEFAULT_WRAPPER_W_5W(File_iread)
2608 DEFAULT_WRAPPER_W_5W(File_iwrite)
2609 DEFAULT_WRAPPER_W_3W(File_seek)
2610 DEFAULT_WRAPPER_W_2W(File_get_position)
2611 DEFAULT_WRAPPER_W_3W(File_get_byte_offset)
2612 DEFAULT_WRAPPER_W_5W(File_read_shared)
2613 DEFAULT_WRAPPER_W_5W(File_write_shared)
2614 DEFAULT_WRAPPER_W_5W(File_iread_shared)
2615 DEFAULT_WRAPPER_W_5W(File_iwrite_shared)
2616 DEFAULT_WRAPPER_W_5W(File_read_ordered)
2617 DEFAULT_WRAPPER_W_5W(File_write_ordered)
2618 DEFAULT_WRAPPER_W_3W(File_seek_shared)
2619 DEFAULT_WRAPPER_W_2W(File_get_position_shared)
2620 DEFAULT_WRAPPER_W_5W(File_read_at_all_begin)
2621 DEFAULT_WRAPPER_W_3W(File_read_at_all_end)
2622 DEFAULT_WRAPPER_W_5W(File_write_at_all_begin)
2623 DEFAULT_WRAPPER_W_3W(File_write_at_all_end)
2624 DEFAULT_WRAPPER_W_4W(File_read_all_begin)
2625 DEFAULT_WRAPPER_W_3W(File_read_all_end)
2626 DEFAULT_WRAPPER_W_4W(File_write_all_begin)
2627 DEFAULT_WRAPPER_W_3W(File_write_all_end)
2628 DEFAULT_WRAPPER_W_4W(File_read_ordered_begin)
2629 DEFAULT_WRAPPER_W_3W(File_read_ordered_end)
2630 DEFAULT_WRAPPER_W_4W(File_write_ordered_begin)
2631 DEFAULT_WRAPPER_W_3W(File_write_ordered_end)
2632 DEFAULT_WRAPPER_W_3W(File_get_type_extent)
2633 DEFAULT_WRAPPER_W_2W(File_set_atomicity)
2634 DEFAULT_WRAPPER_W_2W(File_get_atomicity)
2635 DEFAULT_WRAPPER_W_1W(File_sync)
2636 /* DEFAULT_WRAPPER_W_0W(Finalize) */
2637 DEFAULT_WRAPPER_W_1W(Finalized)
2638 DEFAULT_WRAPPER_W_1W(Free_mem)
2639 /* DEFAULT_WRAPPER_W_8W(Gather) */
2640 DEFAULT_WRAPPER_W_9W(Gatherv)
2641 DEFAULT_WRAPPER_W_2W(Get_address)
2642 /* DEFAULT_WRAPPER_W_3W(Get_count) */
2643 DEFAULT_WRAPPER_W_3W(Get_elements)
2644 DEFAULT_WRAPPER_W_8W(Get)
2645 DEFAULT_WRAPPER_W_2W(Get_processor_name)
2646 DEFAULT_WRAPPER_W_2W(Get_version)
2647 DEFAULT_WRAPPER_W_6W(Graph_create)
2648 DEFAULT_WRAPPER_W_5W(Graph_get)
2649 DEFAULT_WRAPPER_W_5W(Graph_map)
2650 DEFAULT_WRAPPER_W_3W(Graph_neighbors_count)
2651 DEFAULT_WRAPPER_W_4W(Graph_neighbors)
2652 DEFAULT_WRAPPER_W_3W(Graphdims_get)
2653 DEFAULT_WRAPPER_W_1W(Grequest_complete)
2654 DEFAULT_WRAPPER_W_5W(Grequest_start)
2655 DEFAULT_WRAPPER_W_1W(Group_c2f)
2656 DEFAULT_WRAPPER_W_3W(Group_compare)
2657 DEFAULT_WRAPPER_W_3W(Group_difference)
2658 DEFAULT_WRAPPER_W_4W(Group_excl)
2659 DEFAULT_WRAPPER_W_1W(Group_f2c)
2660 DEFAULT_WRAPPER_W_1W(Group_free)
2661 DEFAULT_WRAPPER_W_4W(Group_incl)
2662 DEFAULT_WRAPPER_W_3W(Group_intersection)
2663 DEFAULT_WRAPPER_W_4W(Group_range_excl)
2664 DEFAULT_WRAPPER_W_4W(Group_range_incl)
2665 DEFAULT_WRAPPER_W_2W(Group_rank)
2666 DEFAULT_WRAPPER_W_2W(Group_size)
2667 DEFAULT_WRAPPER_W_5W(Group_translate_ranks)
2668 DEFAULT_WRAPPER_W_3W(Group_union)
2669 /* DEFAULT_WRAPPER_W_7W(Ibsend) */
2670 DEFAULT_WRAPPER_W_1W(Info_c2f)
2671 DEFAULT_WRAPPER_W_1W(Info_create)
2672 DEFAULT_WRAPPER_W_2W(Info_delete)
2673 DEFAULT_WRAPPER_W_2W(Info_dup)
2674 DEFAULT_WRAPPER_W_1W(Info_f2c)
2675 DEFAULT_WRAPPER_W_1W(Info_free)
2676 DEFAULT_WRAPPER_W_5W(Info_get)
2677 DEFAULT_WRAPPER_W_2W(Info_get_nkeys)
2678 DEFAULT_WRAPPER_W_3W(Info_get_nthkey)
2679 DEFAULT_WRAPPER_W_4W(Info_get_valuelen)
2680 DEFAULT_WRAPPER_W_3W(Info_set)
2681 /* DEFAULT_WRAPPER_W_2W(Init) */
2682 /* DEFAULT_WRAPPER_W_1W(Initialized) */
2683 DEFAULT_WRAPPER_W_4W(Init_thread)
2684 DEFAULT_WRAPPER_W_6W(Intercomm_create)
2685 DEFAULT_WRAPPER_W_3W(Intercomm_merge)
2686 /* DEFAULT_WRAPPER_W_5W(Iprobe) */
2687 /* DEFAULT_WRAPPER_W_7W(Irecv) */
2688 /* DEFAULT_WRAPPER_W_7W(Irsend) */
2689 /* DEFAULT_WRAPPER_W_7W(Isend) */
2690 /* DEFAULT_WRAPPER_W_7W(Issend) */
2691 DEFAULT_WRAPPER_W_1W(Is_thread_main)
2692 DEFAULT_WRAPPER_W_4W(Keyval_create)
2693 DEFAULT_WRAPPER_W_1W(Keyval_free)
2694 DEFAULT_WRAPPER_W_3W(Lookup_name)
2695 DEFAULT_WRAPPER_W_1W(Op_c2f)
2696 /* DEFAULT_WRAPPER_W_3W(Op_create) */
2697 DEFAULT_WRAPPER_W_2W(Open_port)
2698 DEFAULT_WRAPPER_W_1W(Op_f2c)
2699 DEFAULT_WRAPPER_W_1W(Op_free)
2700 DEFAULT_WRAPPER_W_7W(Pack_external)
2701 DEFAULT_WRAPPER_W_4W(Pack_external_size)
2702 /* DEFAULT_WRAPPER_W_7W(Pack) */
2703 DEFAULT_WRAPPER_W_4W(Pack_size)
2704 /* int MPI_Pcontrol(const int level, ...) */
2705 /* DEFAULT_WRAPPER_W_4W(Probe) */
2706 DEFAULT_WRAPPER_W_3W(Publish_name)
2707 DEFAULT_WRAPPER_W_8W(Put)
2708 DEFAULT_WRAPPER_W_1W(Query_thread)
2709 DEFAULT_WRAPPER_W_7W(Recv_init)
2710 /* DEFAULT_WRAPPER_W_7W(Recv) */
2711 /* DEFAULT_WRAPPER_W_7W(Reduce) */
2712 DEFAULT_WRAPPER_W_6W(Reduce_scatter)
2713 DEFAULT_WRAPPER_W_5W(Register_datarep)
2714 DEFAULT_WRAPPER_W_1W(Request_c2f)
2715 DEFAULT_WRAPPER_W_1W(Request_f2c)
2716 DEFAULT_WRAPPER_W_1W(Request_free)
2717 DEFAULT_WRAPPER_W_3W(Request_get_status)
2718 /* DEFAULT_WRAPPER_W_6W(Rsend) */
2719 DEFAULT_WRAPPER_W_7W(Rsend_init)
2720 DEFAULT_WRAPPER_W_6W(Scan)
2721 /* DEFAULT_WRAPPER_W_8W(Scatter) */
2722 DEFAULT_WRAPPER_W_9W(Scatterv)
2723 DEFAULT_WRAPPER_W_7W(Send_init)
2724 /* DEFAULT_WRAPPER_W_6W(Send) */
2725 /* DEFAULT_WRAPPER_W_12W(Sendrecv) */
2726 DEFAULT_WRAPPER_W_9W(Sendrecv_replace)
2727 DEFAULT_WRAPPER_W_7W(Ssend_init)
2728 /* DEFAULT_WRAPPER_W_6W(Ssend) */
2729 DEFAULT_WRAPPER_W_1W(Start)
2730 DEFAULT_WRAPPER_W_2W(Startall)
2731 DEFAULT_WRAPPER_W_2W(Status_c2f)
2732 DEFAULT_WRAPPER_W_2W(Status_f2c)
2733 DEFAULT_WRAPPER_W_2W(Status_set_cancelled)
2734 DEFAULT_WRAPPER_W_3W(Status_set_elements)
2735 /* DEFAULT_WRAPPER_W_4W(Testall) */
2736 DEFAULT_WRAPPER_W_5W(Testany)
2737 /* DEFAULT_WRAPPER_W_3W(Test) */
2738 DEFAULT_WRAPPER_W_2W(Test_cancelled)
2739 DEFAULT_WRAPPER_W_5W(Testsome)
2740 DEFAULT_WRAPPER_W_2W(Topo_test)
2741 DEFAULT_WRAPPER_W_1W(Type_c2f)
2742 /* DEFAULT_WRAPPER_W_1W(Type_commit) */
2743 DEFAULT_WRAPPER_W_3W(Type_contiguous)
2744 DEFAULT_WRAPPER_W_10W(Type_create_darray)
2745 DEFAULT_WRAPPER_W_3W(Type_create_f90_complex)
2746 DEFAULT_WRAPPER_W_2W(Type_create_f90_integer)
2747 DEFAULT_WRAPPER_W_3W(Type_create_f90_real)
2748 DEFAULT_WRAPPER_W_5W(Type_create_hindexed)
2749 DEFAULT_WRAPPER_W_5W(Type_create_hvector)
2750 DEFAULT_WRAPPER_W_4W(Type_create_keyval)
2751 DEFAULT_WRAPPER_W_5W(Type_create_indexed_block)
2752 DEFAULT_WRAPPER_W_5W(Type_create_struct)
2753 DEFAULT_WRAPPER_W_7W(Type_create_subarray)
2754 DEFAULT_WRAPPER_W_4W(Type_create_resized)
2755 DEFAULT_WRAPPER_W_2W(Type_delete_attr)
2756 DEFAULT_WRAPPER_W_2W(Type_dup)
2757 /* DEFAULT_WRAPPER_W_2W(Type_extent) */
2758 /* DEFAULT_WRAPPER_W_1W(Type_free) */
2759 DEFAULT_WRAPPER_W_1W(Type_free_keyval)
2760 DEFAULT_WRAPPER_W_1W(Type_f2c)
2761 DEFAULT_WRAPPER_W_4W(Type_get_attr)
2762 /* DEFAULT_WRAPPER_W_7W(Type_get_contents) */
2763 /* DEFAULT_WRAPPER_W_5W(Type_get_envelope) */
2764 DEFAULT_WRAPPER_W_3W(Type_get_extent)
2765 DEFAULT_WRAPPER_W_3W(Type_get_name)
2766 DEFAULT_WRAPPER_W_3W(Type_get_true_extent)
2767 DEFAULT_WRAPPER_W_5W(Type_hindexed)
2768 DEFAULT_WRAPPER_W_5W(Type_hvector)
2769 DEFAULT_WRAPPER_W_5W(Type_indexed)
2770 DEFAULT_WRAPPER_W_2W(Type_lb)
2771 DEFAULT_WRAPPER_W_3W(Type_match_size)
2772 DEFAULT_WRAPPER_W_3W(Type_set_attr)
2773 DEFAULT_WRAPPER_W_2W(Type_set_name)
2774 DEFAULT_WRAPPER_W_2W(Type_size)
2775 DEFAULT_WRAPPER_W_5W(Type_struct)
2776 DEFAULT_WRAPPER_W_2W(Type_ub)
2777 DEFAULT_WRAPPER_W_5W(Type_vector)
2778 /* DEFAULT_WRAPPER_W_7W(Unpack) */
2779 DEFAULT_WRAPPER_W_3W(Unpublish_name)
2780 DEFAULT_WRAPPER_W_7W(Unpack_external)
2781 /* DEFAULT_WRAPPER_W_3W(Waitall) */
2782 /* DEFAULT_WRAPPER_W_4W(Waitany) */
2783 /* DEFAULT_WRAPPER_W_2W(Wait) */
2784 DEFAULT_WRAPPER_W_5W(Waitsome)
2785 DEFAULT_WRAPPER_W_1W(Win_c2f)
2786 DEFAULT_WRAPPER_W_2W(Win_call_errhandler)
2787 DEFAULT_WRAPPER_W_1W(Win_complete)
2788 DEFAULT_WRAPPER_W_6W(Win_create)
2789 DEFAULT_WRAPPER_W_2W(Win_create_errhandler)
2790 DEFAULT_WRAPPER_W_4W(Win_create_keyval)
2791 DEFAULT_WRAPPER_W_2W(Win_delete_attr)
2792 DEFAULT_WRAPPER_W_1W(Win_f2c)
2793 DEFAULT_WRAPPER_W_2W(Win_fence)
2794 DEFAULT_WRAPPER_W_1W(Win_free)
2795 DEFAULT_WRAPPER_W_1W(Win_free_keyval)
2796 DEFAULT_WRAPPER_W_4W(Win_get_attr)
2797 DEFAULT_WRAPPER_W_2W(Win_get_errhandler)
2798 DEFAULT_WRAPPER_W_2W(Win_get_group)
2799 DEFAULT_WRAPPER_W_3W(Win_get_name)
2800 DEFAULT_WRAPPER_W_4W(Win_lock)
2801 DEFAULT_WRAPPER_W_3W(Win_post)
2802 DEFAULT_WRAPPER_W_3W(Win_set_attr)
2803 DEFAULT_WRAPPER_W_2W(Win_set_errhandler)
2804 DEFAULT_WRAPPER_W_2W(Win_set_name)
2805 DEFAULT_WRAPPER_W_3W(Win_start)
2806 DEFAULT_WRAPPER_W_2W(Win_test)
2807 DEFAULT_WRAPPER_W_2W(Win_unlock)
2808 DEFAULT_WRAPPER_W_1W(Win_wait)
2809 /* double MPI_Wtick(void) */
2810 /* double MPI_Wtime(void) */
2813 /*------------------------------------------------------------*/
2814 /*--- ---*/
2815 /*--- ---*/
2816 /*--- ---*/
2817 /*------------------------------------------------------------*/
2819 /*---------------------------------------------------------------*/
2820 /*--- end mpiwrap.c ---*/
2821 /*---------------------------------------------------------------*/