Do RCEC_GC when approaching the max nr of RCEC, not when reaching it.
[valgrind.git] / mpi / libmpiwrap.c
bloba5349e066eb4204d96844286200a311578da5202
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-2013 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 else if (ty == MPI_UB) fprintf(f,"UB");
282 else if (ty == MPI_LB) fprintf(f,"LB");
283 # if defined(MPI_WCHAR)
284 else if (ty == MPI_WCHAR) fprintf(f,"WCHAR");
285 # endif
286 else if (ty == MPI_LONG_LONG_INT) fprintf(f,"LONG_LONG_INT");
287 # if defined(MPI_LONG_LONG)
288 else if (ty == MPI_LONG_LONG) fprintf(f,"LONG_LONG");
289 # endif
290 # if defined(MPI_UNSIGNED_LONG_LONG)
291 else if (ty == MPI_UNSIGNED_LONG_LONG) fprintf(f,"UNSIGNED_LONG_LONG");
292 # endif
293 # if defined(MPI_REAL8)
294 else if (ty == MPI_REAL8) fprintf(f, "REAL8");
295 # endif
296 # if defined(MPI_REAL4)
297 else if (ty == MPI_REAL4) fprintf(f, "REAL4");
298 # endif
299 # if defined(MPI_REAL)
300 else if (ty == MPI_REAL) fprintf(f, "REAL");
301 # endif
302 # if defined(MPI_INTEGER8)
303 else if (ty == MPI_INTEGER8) fprintf(f, "INTEGER8");
304 # endif
305 # if defined(MPI_INTEGER4)
306 else if (ty == MPI_INTEGER4) fprintf(f, "INTEGER4");
307 # endif
308 # if defined(MPI_INTEGER)
309 else if (ty == MPI_INTEGER) fprintf(f, "INTEGER");
310 # endif
311 # if defined(MPI_DOUBLE_PRECISION)
312 else if (ty == MPI_DOUBLE_PRECISION) fprintf(f, "DOUBLE_PRECISION");
313 # endif
314 # if defined(MPI_COMPLEX)
315 else if (ty == MPI_COMPLEX) fprintf(f, "COMPLEX");
316 # endif
317 # if defined(MPI_DOUBLE_COMPLEX)
318 else if (ty == MPI_DOUBLE_COMPLEX) fprintf(f, "DOUBLE_COMPLEX");
319 # endif
320 # if defined(MPI_LOGICAL)
321 else if (ty == MPI_LOGICAL) fprintf(f, "LOGICAL");
322 # endif
323 # if defined(MPI_2INTEGER)
324 else if (ty == MPI_2INTEGER) fprintf(f, "2INTEGER");
325 # endif
326 # if defined(MPI_2COMPLEX)
327 else if (ty == MPI_2COMPLEX) fprintf(f, "2COMPLEX");
328 # endif
329 # if defined(MPI_2DOUBLE_COMPLEX)
330 else if (ty == MPI_2DOUBLE_COMPLEX) fprintf(f, "2DOUBLE_COMPLEX");
331 # endif
332 # if defined(MPI_2REAL)
333 else if (ty == MPI_2REAL) fprintf(f, "2REAL");
334 # endif
335 # if defined(MPI_2DOUBLE_PRECISION)
336 else if (ty == MPI_2DOUBLE_PRECISION) fprintf(f, "2DOUBLE_PRECISION");
337 # endif
338 # if defined(MPI_CHARACTER)
339 else if (ty == MPI_CHARACTER) fprintf(f, "CHARACTER");
340 # endif
341 else fprintf(f,"showTy:???");
344 static void showCombiner ( FILE* f, int combiner )
346 switch (combiner) {
347 case MPI_COMBINER_NAMED: fprintf(f, "NAMED"); break;
348 #if defined(MPI_COMBINER_DUP)
349 case MPI_COMBINER_DUP: fprintf(f, "DUP"); break;
350 # endif
351 case MPI_COMBINER_CONTIGUOUS: fprintf(f, "CONTIGUOUS"); break;
352 case MPI_COMBINER_VECTOR: fprintf(f, "VECTOR"); break;
353 #if defined(MPI_COMBINER_HVECTOR_INTEGER)
354 case MPI_COMBINER_HVECTOR_INTEGER: fprintf(f, "HVECTOR_INTEGER"); break;
355 # endif
356 case MPI_COMBINER_HVECTOR: fprintf(f, "HVECTOR"); break;
357 case MPI_COMBINER_INDEXED: fprintf(f, "INDEXED"); break;
358 #if defined(MPI_COMBINER_HINDEXED_INTEGER)
359 case MPI_COMBINER_HINDEXED_INTEGER: fprintf(f, "HINDEXED_INTEGER"); break;
360 # endif
361 case MPI_COMBINER_HINDEXED: fprintf(f, "HINDEXED"); break;
362 #if defined(MPI_COMBINER_INDEXED_BLOCK)
363 case MPI_COMBINER_INDEXED_BLOCK: fprintf(f, "INDEXED_BLOCK"); break;
364 # endif
365 #if defined(MPI_COMBINER_STRUCT_INTEGER)
366 case MPI_COMBINER_STRUCT_INTEGER: fprintf(f, "STRUCT_INTEGER"); break;
367 # endif
368 case MPI_COMBINER_STRUCT: fprintf(f, "STRUCT"); break;
369 #if defined(MPI_COMBINER_SUBARRAY)
370 case MPI_COMBINER_SUBARRAY: fprintf(f, "SUBARRAY"); break;
371 # endif
372 #if defined(MPI_COMBINER_DARRAY)
373 case MPI_COMBINER_DARRAY: fprintf(f, "DARRAY"); break;
374 # endif
375 #if defined(MPI_COMBINER_F90_REAL)
376 case MPI_COMBINER_F90_REAL: fprintf(f, "F90_REAL"); break;
377 # endif
378 #if defined(MPI_COMBINER_F90_COMPLEX)
379 case MPI_COMBINER_F90_COMPLEX: fprintf(f, "F90_COMPLEX"); break;
380 # endif
381 #if defined(MPI_COMBINER_F90_INTEGER)
382 case MPI_COMBINER_F90_INTEGER: fprintf(f, "F90_INTEGER"); break;
383 # endif
384 #if defined(MPI_COMBINER_RESIZED)
385 case MPI_COMBINER_RESIZED: fprintf(f, "RESIZED"); break;
386 # endif
387 default: fprintf(f, "showCombiner:??"); break;
392 /* ------ Get useful bits of info ------ */
394 /* Note, PMPI_Comm_rank/size are themselves wrapped. Should work
395 fine. */
397 static __inline__ int comm_rank ( MPI_Comm comm )
399 int err, r;
400 err = PMPI_Comm_rank(comm, &r);
401 return err ? 0/*arbitrary*/ : r;
404 static __inline__ int comm_size ( MPI_Comm comm )
406 int err, r;
407 err = PMPI_Comm_size(comm, &r);
408 return err ? 0/*arbitrary*/ : r;
411 static __inline__ Bool count_from_Status( /*OUT*/int* recv_count,
412 MPI_Datatype datatype,
413 MPI_Status* status)
415 int n;
416 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
417 int err = PMPI_Get_count(status, datatype, &n);
418 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
419 if (err == MPI_SUCCESS) {
420 *recv_count = n;
421 return True;
422 } else {
423 return False;
427 /* It's critical that we can do equality on MPI_Requests.
428 Unfortunately these are opaque objects to us (handles, in the
429 parlance of the MPI 1.1 spec). Fortunately Sec 2.4.1 ("Opaque
430 Objects") specifies that "In C, [...] These [handles] should be
431 types that support assignment and equality operations." Hence the
432 following function should compile for any compliant definition of
433 MPI_Request. */
434 static __inline__
435 Bool eq_MPI_Request ( MPI_Request r1, MPI_Request r2 )
437 return r1 == r2;
440 /* Return True if status is MPI_STATUS_IGNORE or MPI_STATUSES_IGNORE.
441 On MPI-1.x platforms which don't have these symbols (and they would
442 only have them if they've been backported from 2.x) always return
443 False. */
444 static __inline__
445 Bool isMSI ( MPI_Status* status )
447 # if defined(HAVE_MPI_STATUS_IGNORE)
448 return status == MPI_STATUSES_IGNORE || status == MPI_STATUS_IGNORE;
449 # else
450 return False;
451 # endif
454 /* Get the 'extent' of a type. Note, as per the MPI spec this
455 includes whatever padding would be required when using 'ty' in an
456 array. */
457 static long extentOfTy ( MPI_Datatype ty )
459 int r;
460 MPI_Aint n;
461 r = PMPI_Type_extent(ty, &n);
462 assert(r == MPI_SUCCESS);
463 return (long)n;
466 /* Free up *ty, if it is safe to do so */
467 static void maybeFreeTy ( MPI_Datatype* ty )
469 int r, n_ints, n_addrs, n_dtys, tycon;
471 r = PMPI_Type_get_envelope( *ty, &n_ints, &n_addrs, &n_dtys, &tycon );
472 assert(r == MPI_SUCCESS);
474 /* can't free named types */
475 if (tycon == MPI_COMBINER_NAMED)
476 return;
478 /* some kinds of structs are predefined so we can't free them
479 either. */
480 if (*ty == MPI_FLOAT_INT || *ty == MPI_DOUBLE_INT
481 || *ty == MPI_LONG_INT || *ty == MPI_2INT
482 || *ty == MPI_SHORT_INT || *ty == MPI_LONG_DOUBLE_INT)
483 return;
485 /* Looks OK - free it. */
486 if (0) {
487 /* show me what you're about to free .. */
488 fprintf(stderr, "freeing combiner ");
489 showCombiner(stderr,tycon);
490 fprintf(stderr, " ty= ");
491 showTy(stderr,*ty);
492 fprintf(stderr,"\n");
494 r = PMPI_Type_free(ty);
495 assert(r == MPI_SUCCESS);
498 /* How big is a "named" (base) type? Returns 0 if not known. Note.
499 There is a subtlety, which is that this is required to return the
500 exact size of one item of the type, NOT the size of it when padded
501 suitably to make an array of them. In particular that's why the
502 size of LONG_DOUBLE is computed by looking at the result of doing a
503 long double store, rather than just asking what is the sizeof(long
504 double).
506 For LONG_DOUBLE on x86-linux and amd64-linux my impression is that
507 the right answer is 10 even though sizeof(long double) says 12 and
508 16 respectively. On ppc32-linux it appears to be 16.
510 Ref: MPI 1.1 doc p18 */
511 static long sizeofOneNamedTy ( MPI_Datatype ty )
513 if (ty == MPI_CHAR) return sizeof(signed char);
514 if (ty == MPI_SHORT) return sizeof(signed short int);
515 if (ty == MPI_INT) return sizeof(signed int);
516 if (ty == MPI_LONG) return sizeof(signed long int);
517 if (ty == MPI_UNSIGNED_CHAR) return sizeof(unsigned char);
518 if (ty == MPI_UNSIGNED_SHORT) return sizeof(unsigned short int);
519 if (ty == MPI_UNSIGNED) return sizeof(unsigned int);
520 if (ty == MPI_UNSIGNED_LONG) return sizeof(unsigned long int);
521 if (ty == MPI_FLOAT) return sizeof(float);
522 if (ty == MPI_DOUBLE) return sizeof(double);
523 if (ty == MPI_BYTE) return 1;
524 if (ty == MPI_LONG_DOUBLE) return sizeof_long_double_image();
525 if (ty == MPI_PACKED) return 1;
526 if (ty == MPI_LONG_LONG_INT) return sizeof(signed long long int);
528 # if defined(MPI_REAL8)
529 if (ty == MPI_REAL8) return 8; /* MPI2 spec */;
530 # endif
531 # if defined(MPI_REAL4)
532 if (ty == MPI_REAL4) return 4; /* MPI2 spec */;
533 # endif
534 # if defined(MPI_REAL)
535 if (ty == MPI_REAL) return 4; /* MPI2 spec */;
536 # endif
537 # if defined(MPI_INTEGER8)
538 if (ty == MPI_INTEGER8) return 8; /* MPI2 spec */;
539 # endif
540 # if defined(MPI_INTEGER4)
541 if (ty == MPI_INTEGER4) return 4; /* MPI2 spec */;
542 # endif
543 # if defined(MPI_INTEGER)
544 if (ty == MPI_INTEGER) return 4; /* MPI2 spec */;
545 # endif
546 # if defined(MPI_DOUBLE_PRECISION)
547 if (ty == MPI_DOUBLE_PRECISION) return 8; /* MPI2 spec */;
548 # endif
550 /* new in MPI2: */
551 # if defined(MPI_WCHAR)
552 if (ty == MPI_WCHAR) return 2; /* MPI2 spec */;
553 # endif
554 # if defined(MPI_SIGNED_CHAR)
555 if (ty == MPI_SIGNED_CHAR) return 1; /* MPI2 spec */;
556 # endif
557 # if defined(MPI_UNSIGNED_LONG_LONG)
558 if (ty == MPI_UNSIGNED_LONG_LONG) return 8; /* MPI2 spec */;
559 # endif
560 # if defined(MPI_COMPLEX)
561 if (ty == MPI_COMPLEX) return 2 * 4; /* MPI2 spec */
562 # endif
563 # if defined(MPI_DOUBLE_COMPLEX)
564 if (ty == MPI_DOUBLE_COMPLEX) return 2 * 8; /* MPI2 spec */
565 # endif
566 # if defined(MPI_LOGICAL)
567 if (ty == MPI_LOGICAL) return 4; /* MPI2 spec */
568 # endif
569 # if defined(MPI_2INTEGER)
570 if (ty == MPI_2INTEGER) return 2 * 4; /* undocumented in MPI2 */
571 # endif
572 # if defined(MPI_2COMPLEX)
573 if (ty == MPI_2COMPLEX) return 2 * 8; /* undocumented in MPI2 */
574 # endif
575 # if defined(MPI_2DOUBLE_COMPLEX)
576 /* 32: this is how openmpi-1.2.2 behaves on x86-linux, but I have
577 really no idea if this is right. */
578 if (ty == MPI_2DOUBLE_COMPLEX) return 32; /* undocumented in MPI2 */
579 # endif
580 # if defined(MPI_2REAL)
581 if (ty == MPI_2REAL) return 2 * 4; /* undocumented in MPI2 */
582 # endif
583 # if defined(MPI_2DOUBLE_PRECISION)
584 if (ty == MPI_2DOUBLE_PRECISION) return 2 * 8; /* undocumented in MPI2 */
585 # endif
586 # if defined(MPI_CHARACTER)
587 if (ty == MPI_CHARACTER) return 1; /* MPI2 spec */
588 # endif
590 /* Note: the following are named structs, not named basic types,
591 and so are not handled here:
592 FLOAT_INT DOUBLE_INT LONG_INT 2INT SHORT_INT LONG_DOUBLE_INT
593 My guess is they are probably for doing max-w-index style
594 reductions, the INT carrying the index of the max/min and the
595 other type its actual value.
597 return 0;
601 /* Find the size of long double image (not 'sizeof(long double)').
602 See comments in sizeofOneNamedTy.
604 static long sizeof_long_double_image ( void )
606 long i;
607 unsigned char* p;
608 static long cached_result = 0;
610 /* Hopefully we have it already. */
611 if (cached_result != 0) {
612 assert(cached_result == 10 || cached_result == 16 || cached_result == 8);
613 return cached_result;
616 /* No? Then we'll have to compute it. This isn't thread-safe but
617 it doesn't really matter since all races to compute it should
618 produce the same answer. */
619 p = malloc(64);
620 assert(p);
621 for (i = 0; i < 64; i++)
622 p[i] = 0x55;
624 /* Write a value which isn't known at compile time and therefore
625 must come out of a register. If we just store a constant here,
626 some compilers write more data than a store from a machine
627 register would. Therefore we have to force a store from a
628 machine register by storing a value which isn't known at compile
629 time. Since getpid() will return a value < 1 million, turn it
630 into a zero by dividing by 1e+30. */
631 *(long double*)(&p[16]) = (long double)(1.0e-30 * (double)getpid());
633 for (i = 0; i < 16; i++) {
634 assert(p[i] == 0x55);
635 assert(p[i+48] == 0x55);
637 for (i = 16; i <= 48; i++) {
638 if (p[i] == 0x55)
639 break;
642 assert(i < 48);
643 assert(i > 16);
644 free(p);
645 cached_result = i - 16;
647 if (0)
648 printf("sizeof_long_double_image: computed %d\n", (int)cached_result);
650 assert(cached_result == 10 || cached_result == 16 || cached_result == 8);
651 return cached_result;
655 /*------------------------------------------------------------*/
656 /*--- Unpicking datatypes ---*/
657 /*------------------------------------------------------------*/
659 static __inline__
660 void walk_type_array ( void(*f)(void*,long), char* base,
661 MPI_Datatype ty, long count );
664 /* Walk over all fragments of the object of type 'ty' with base
665 address 'base', and apply 'f' to the start/length of each
666 contiguous fragment. */
667 static
668 void walk_type ( void(*f)(void*,long), char* base, MPI_Datatype ty )
670 int r, n_ints, n_addrs, n_dtys, tycon;
671 long ex, i;
672 int* ints = NULL;
673 MPI_Aint* addrs = NULL;
674 MPI_Datatype* dtys = NULL;
676 /* Stuff for limiting how much complaining text it spews out */
677 static int complaints = 3;
678 static int last_complained_about_tycon = -987654321; /* presumably bogus */
680 if (0)
681 printf("walk_type %p\n", (void*)(unsigned long)ty);
683 r = PMPI_Type_get_envelope( ty, &n_ints, &n_addrs, &n_dtys, &tycon );
684 assert(r == MPI_SUCCESS);
686 /* Handle the base cases fast(er/ish). */
687 if (tycon == MPI_COMBINER_NAMED) {
688 long sz = sizeofOneNamedTy(ty);
689 if (sz > 0) {
690 f(base, sz);
691 return;
693 /* Hmm. Perhaps it's a named struct? Unfortunately we can't
694 take them to bits so we have to do a really ugly hack, which
695 makes assumptions about how the MPI implementation has laid
696 out these types. At least Open MPI 1.0.1 appears to put
697 the 'val' field first. MPICH2 agrees.
699 if (ty == MPI_2INT) {
700 typedef struct { int val; int loc; } Ty;
701 f(base + offsetof(Ty,val), sizeof(int));
702 f(base + offsetof(Ty,loc), sizeof(int));
703 return;
705 if (ty == MPI_LONG_INT) {
706 typedef struct { long val; int loc; } Ty;
707 f(base + offsetof(Ty,val), sizeof(long));
708 f(base + offsetof(Ty,loc), sizeof(int));
709 return;
711 if (ty == MPI_DOUBLE_INT) {
712 typedef struct { double val; int loc; } Ty;
713 f(base + offsetof(Ty,val), sizeof(double));
714 f(base + offsetof(Ty,loc), sizeof(int));
715 return;
717 if (ty == MPI_SHORT_INT) {
718 typedef struct { short val; int loc; } Ty;
719 f(base + offsetof(Ty,val), sizeof(short));
720 f(base + offsetof(Ty,loc), sizeof(int));
721 return;
723 if (ty == MPI_FLOAT_INT) {
724 typedef struct { float val; int loc; } Ty;
725 f(base + offsetof(Ty,val), sizeof(float));
726 f(base + offsetof(Ty,loc), sizeof(int));
727 return;
729 if (ty == MPI_LONG_DOUBLE_INT) {
730 typedef struct { long double val; int loc; } Ty;
731 f(base + offsetof(Ty,val), sizeof_long_double_image());
732 f(base + offsetof(Ty,loc), sizeof(int));
733 return;
735 if (ty == MPI_LB || ty == MPI_UB)
736 return; /* have zero size, so nothing needs to be done */
737 goto unhandled;
738 /*NOTREACHED*/
741 if (0) {
742 ex = extentOfTy(ty);
743 printf("tycon 0x%llx %d %d %d (ext %d)\n",
744 (unsigned long long int)tycon,
745 n_ints, n_addrs, n_dtys, (int)ex );
748 /* Now safe to do MPI_Type_get_contents */
749 assert(n_ints >= 0);
750 assert(n_addrs >= 0);
751 assert(n_dtys >= 0);
753 if (n_ints > 0) {
754 ints = malloc(n_ints * sizeof(int));
755 assert(ints);
757 if (n_addrs > 0) {
758 addrs = malloc(n_addrs * sizeof(MPI_Aint));
759 assert(addrs);
761 if (n_dtys > 0) {
762 dtys = malloc(n_dtys * sizeof(MPI_Datatype));
763 assert(dtys);
766 r = PMPI_Type_get_contents( ty, n_ints, n_addrs, n_dtys,
767 ints, addrs, dtys );
768 assert(r == MPI_SUCCESS);
770 switch (tycon) {
772 case MPI_COMBINER_CONTIGUOUS:
773 assert(n_ints == 1 && n_addrs == 0 && n_dtys == 1);
774 walk_type_array( f, base, dtys[0], ints[0] );
775 maybeFreeTy( &dtys[0] );
776 break;
778 case MPI_COMBINER_VECTOR:
779 assert(n_ints == 3 && n_addrs == 0 && n_dtys == 1);
780 ex = extentOfTy(dtys[0]);
781 if (0)
782 printf("vector count %d x (bl %d stride %d)\n",
783 (int)ints[0], (int)ints[1], (int)ints[2]);
784 for (i = 0; i < ints[0]; i++) {
785 walk_type_array( f, base + i * ints[2]/*stride*/ * ex,
786 dtys[0], ints[1]/*blocklength*/ );
788 maybeFreeTy( &dtys[0] );
789 break;
791 case MPI_COMBINER_HVECTOR:
792 assert(n_ints == 2 && n_addrs == 1 && n_dtys == 1);
793 ex = extentOfTy(dtys[0]);
794 if (0)
795 printf("hvector count %d x (bl %d hstride %d)\n",
796 (int)ints[0], (int)ints[1], (int)addrs[0]);
797 for (i = 0; i < ints[0]; i++) {
798 walk_type_array( f, base + i * addrs[0]/*hstride*/,
799 dtys[0], ints[1]/*blocklength*/ );
801 maybeFreeTy( &dtys[0] );
802 break;
804 case MPI_COMBINER_INDEXED:
805 assert(n_addrs == 0 && n_dtys == 1);
806 assert(n_ints > 0);
807 assert(n_ints == 2 * ints[0] + 1);
808 ex = extentOfTy(dtys[0]);
809 for (i = 0; i < ints[0]; i++) {
810 if (0)
811 printf("indexed (elem %d) off %d copies %d\n",
812 (int)i, ints[i+1+ints[0]], ints[i+1] );
813 walk_type_array( f, base + ex * ints[i+1+ints[0]],
814 dtys[0], ints[i+1] );
816 maybeFreeTy( &dtys[0] );
817 break;
819 case MPI_COMBINER_HINDEXED:
820 assert(n_ints > 0);
821 assert(n_ints == ints[0] + 1);
822 assert(n_addrs == ints[0] && n_dtys == 1);
823 ex = extentOfTy(dtys[0]);
824 for (i = 0; i < ints[0]; i++) {
825 if (0)
826 printf("hindexed (elem %d) hoff %d copies %d\n",
827 (int)i, (int)addrs[i], ints[i+1] );
828 walk_type_array( f, base + addrs[i],
829 dtys[0], ints[i+1] );
831 maybeFreeTy( &dtys[0] );
832 break;
834 case MPI_COMBINER_STRUCT:
835 assert(n_addrs == n_ints-1);
836 assert(n_dtys == n_ints-1);
837 assert(n_ints > 0);
838 assert(n_ints == ints[0] + 1);
839 for (i = 0; i < ints[0]; i++) {
840 if (0)
841 printf("struct (elem %d limit %d) hoff %d copies %d\n",
842 (int)i, (int)ints[0], (int)addrs[i], (int)ints[i+1]);
843 walk_type_array( f, base + addrs[i], dtys[i], (long)ints[i+1] );
844 maybeFreeTy( &dtys[i] );
846 break;
848 default:
849 goto unhandled;
853 /* normal exit */
854 if (ints) free(ints);
855 if (addrs) free(addrs);
856 if (dtys) free(dtys);
857 return;
859 unhandled:
860 /* Complain, but limit the amount of complaining that can happen to
861 the first 3 different unhandled tycons that show up, so as to
862 avoid swamping users with thousands of duplicate messages. */
863 if (complaints > 0 && tycon != last_complained_about_tycon) {
864 complaints--;
865 last_complained_about_tycon = tycon;
866 if (tycon == MPI_COMBINER_NAMED) {
867 fprintf(stderr, "%s %5d: walk_type: unhandled base type 0x%lx ",
868 preamble, my_pid, (long)ty);
869 showTy(stderr, ty);
870 fprintf(stderr, "\n");
871 } else {
872 fprintf(stderr, "%s %5d: walk_type: unhandled combiner 0x%lx\n",
873 preamble, my_pid, (long)tycon);
876 if (ints) free(ints);
877 if (addrs) free(addrs);
878 if (dtys) free(dtys);
879 if (opt_missing >= 2)
880 barf("walk_type: unhandled combiner, strict checking selected");
884 /* Same as walk_type but apply 'f' to every element in an array of
885 'count' items starting at 'base'. The only purpose of pushing this
886 into a different routine is so it can attempt to optimise the case
887 where the array elements are contiguous and packed together without
888 holes. */
889 static __inline__
890 void walk_type_array ( void(*f)(void*,long), char* base,
891 MPI_Datatype elemTy, long count )
893 long i, ex;
895 assert(sizeof(unsigned long) == sizeof(char*));
897 /* First see if we can do this the fast way. */
898 ex = sizeofOneNamedTy(elemTy);
900 if ( /* ty is a primitive type with power-of-2 size */
901 (ex == 8 || ex == 4 || ex == 2 || ex == 1)
902 && /* base is suitably aligned for ty */
903 ( ((unsigned long)base) & (ex-1)) == 0) {
905 /* We're sure it's contiguous, so just paint/check it in one
906 go. */
907 if (0) printf("walk_type_array fast %ld of size %ld\n", count, ex );
908 f ( base, count * ex );
910 } else {
912 /* Bad news. We have to futz with each element individually.
913 This could be very expensive.
915 Note: subtle. If ty is LONG_DOUBLE then the extent will be
916 12, so the following loop will jump along in steps of 12, but
917 the size painted by walk_type will be 10 since it uses
918 sizeofOneNamedTy to establish the size of base types. Which
919 is what we need to happen. */
920 ex = extentOfTy(elemTy);
921 if (0) printf("walk_type_array SLOW %ld of size %ld\n", count, ex );
922 for (i = 0; i < count; i++)
923 walk_type( f, base + i * ex, elemTy );
929 /* Hook so it's visible from outside (can be handy to dlopen/dlsym
930 it) */
931 void mpiwrap_walk_type_EXTERNALLY_VISIBLE
932 ( void(*f)(void*,long), char* base, MPI_Datatype ty )
934 walk_type(f, base, ty);
938 /*------------------------------------------------------------*/
939 /*--- Address-range helpers ---*/
940 /*------------------------------------------------------------*/
942 /* ----------------
943 Do corresponding checks on memory areas defined using a
944 straightforward (start, length) description.
945 ----------------
948 static __inline__
949 void check_mem_is_defined_untyped ( void* buffer, long nbytes )
951 if (nbytes > 0) {
952 VALGRIND_CHECK_MEM_IS_DEFINED(buffer, nbytes);
956 static __inline__
957 void check_mem_is_addressable_untyped ( void* buffer, long nbytes )
959 if (nbytes > 0) {
960 VALGRIND_CHECK_MEM_IS_ADDRESSABLE(buffer, nbytes);
964 static __inline__
965 void make_mem_defined_if_addressable_untyped ( void* buffer, long nbytes )
967 if (nbytes > 0) {
968 VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(buffer, nbytes);
972 static __inline__
973 void make_mem_defined_if_addressable_if_success_untyped ( int err,
974 void* buffer, long nbytes )
976 if (err == MPI_SUCCESS && nbytes > 0) {
977 VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(buffer, nbytes);
982 /* ----------------
983 Do checks on memory areas defined using the MPI (buffer, count,
984 type) convention.
985 ----------------
988 /* Check that the specified area is both addressible and contains
989 initialised data, and cause V to complain if not. */
991 static __inline__
992 void check_mem_is_defined ( char* buffer, long count, MPI_Datatype datatype )
994 walk_type_array( check_mem_is_defined_untyped, buffer, datatype, count );
998 /* Check that the specified area is addressible, and cause V to
999 complain if not. Doesn't matter whether the data there is
1000 initialised or not. */
1002 static __inline__
1003 void check_mem_is_addressable ( void *buffer, long count, MPI_Datatype datatype )
1005 walk_type_array( check_mem_is_addressable_untyped, buffer, datatype, count );
1009 /* Set the specified area to 'defined for each byte which is
1010 addressible' state. */
1012 static __inline__
1013 void make_mem_defined_if_addressable ( void *buffer, int count, MPI_Datatype datatype )
1015 walk_type_array( make_mem_defined_if_addressable_untyped,
1016 buffer, datatype, count );
1019 static __inline__
1020 void
1021 make_mem_defined_if_addressable_if_success ( int err, void *buffer, int count,
1022 MPI_Datatype datatype )
1024 if (err == MPI_SUCCESS)
1025 make_mem_defined_if_addressable(buffer, count, datatype);
1029 /*------------------------------------------------------------*/
1030 /*--- ---*/
1031 /*--- The wrappers proper. They are listed in the order ---*/
1032 /*--- in which they appear in "MPI: A Message-Passing ---*/
1033 /*--- Interface Standard, MPIF, Nov 15 2003" (the MPI 1.1 ---*/
1034 /*--- spec. All unimplemented wrappers are listed at the ---*/
1035 /*--- end of the file. The list of function names is ---*/
1036 /*--- taken from the headers of Open MPI svn r9191. ---*/
1037 /*--- Hopefully it is a complete list of all the MPI 2 ---*/
1038 /*--- functions. ---*/
1039 /*--- ---*/
1040 /*------------------------------------------------------------*/
1042 /* Handy abbreviation */
1043 #define WRAPPER_FOR(name) I_WRAP_FNNAME_U(name)
1045 /* Generates (conceptually) a wrapper which does nothing. In
1046 fact just generate no wrapper at all. */
1047 #define HAS_NO_WRAPPER(basename) /* */
1050 /*------------------------------------------------------------*/
1051 /*--- ---*/
1052 /*--- Sec 3.2, Blocking Send and Receive Operations ---*/
1053 /*--- ---*/
1054 /*------------------------------------------------------------*/
1056 /* --- {,B,S,R}Send --- */
1057 /* pre: rd: (buf,count,datatype) */
1058 static
1059 int generic_Send(void *buf, int count, MPI_Datatype datatype,
1060 int dest, int tag, MPI_Comm comm)
1062 OrigFn fn;
1063 int err;
1064 VALGRIND_GET_ORIG_FN(fn);
1065 before("{,B,S,R}Send");
1066 check_mem_is_defined(buf, count, datatype);
1067 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1068 CALL_FN_W_6W(err, fn, buf,count,datatype,dest,tag,comm);
1069 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1070 after("{,B,S,R}Send", err);
1071 return err;
1073 int WRAPPER_FOR(PMPI_Send)(void *buf, int count, MPI_Datatype datatype,
1074 int dest, int tag, MPI_Comm comm) {
1075 return generic_Send(buf,count,datatype, dest,tag,comm);
1077 int WRAPPER_FOR(PMPI_Bsend)(void *buf, int count, MPI_Datatype datatype,
1078 int dest, int tag, MPI_Comm comm) {
1079 return generic_Send(buf,count,datatype, dest,tag,comm);
1081 int WRAPPER_FOR(PMPI_Ssend)(void *buf, int count, MPI_Datatype datatype,
1082 int dest, int tag, MPI_Comm comm) {
1083 return generic_Send(buf,count,datatype, dest,tag,comm);
1085 int WRAPPER_FOR(PMPI_Rsend)(void *buf, int count, MPI_Datatype datatype,
1086 int dest, int tag, MPI_Comm comm) {
1087 return generic_Send(buf,count,datatype, dest,tag,comm);
1090 /* --- Recv --- */
1091 /* pre: must be writable: (buf,count,datatype)
1092 must be writable: status
1093 post: make readable: (buf,recv_count,datatype)
1094 where recv_count is determined from *status
1096 int WRAPPER_FOR(PMPI_Recv)(void *buf, int count, MPI_Datatype datatype,
1097 int source, int tag,
1098 MPI_Comm comm, MPI_Status *status)
1100 OrigFn fn;
1101 int err, recv_count = 0;
1102 MPI_Status fake_status;
1103 VALGRIND_GET_ORIG_FN(fn);
1104 before("Recv");
1105 if (isMSI(status))
1106 status = &fake_status;
1107 check_mem_is_addressable(buf, count, datatype);
1108 check_mem_is_addressable_untyped(status, sizeof(*status));
1109 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1110 CALL_FN_W_7W(err, fn, buf,count,datatype,source,tag,comm,status);
1111 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1112 make_mem_defined_if_addressable_if_success_untyped(err, status, sizeof(*status));
1113 if (err == MPI_SUCCESS && count_from_Status(&recv_count,datatype,status)) {
1114 make_mem_defined_if_addressable(buf, recv_count, datatype);
1116 after("Recv", err);
1117 return err;
1120 /* --- Get_count --- */
1121 /* pre: must be readable: *status
1122 post: make defined: *count -- don't bother, libmpi will surely do this
1124 int WRAPPER_FOR(PMPI_Get_count)(MPI_Status* status,
1125 MPI_Datatype ty, int* count )
1127 OrigFn fn;
1128 int err;
1129 VALGRIND_GET_ORIG_FN(fn);
1130 before("Get_count");
1131 check_mem_is_defined_untyped(status, sizeof(*status));
1132 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1133 CALL_FN_W_WWW(err, fn, status,ty,count);
1134 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1135 after("Get_count", err);
1136 return err;
1140 /*------------------------------------------------------------*/
1141 /*--- ---*/
1142 /*--- Sec 3.7, Nonblocking communication ---*/
1143 /*--- ---*/
1144 /*------------------------------------------------------------*/
1146 /* Maintain a table that makes it possible for the wrappers to
1147 complete MPI_Irecv successfully.
1149 The issue is that MPI_Irecv states the recv buffer and returns
1150 immediately, giving a handle (MPI_Request) for the transaction.
1151 Later the user will have to poll for completion with MPI_Wait etc,
1152 and at that point these wrappers have to paint the recv buffer.
1153 But the recv buffer details are not presented to MPI_Wait - only
1154 the handle is. We therefore have to use a shadow table
1155 (sReqs{,_size,_used,_lock}) which associates uncompleted
1156 MPI_Requests with the corresponding buffer address/count/type.
1158 Only read requests are placed in the table, since there is no need
1159 to do any buffer painting following completion of an Isend - all
1160 the checks for that are done at the time Isend is called.
1162 Care has to be take to remove completed requests from the table.
1164 Access to the table is guarded by sReqs_lock so as to make it
1165 thread-safe.
1168 typedef
1169 struct {
1170 Bool inUse;
1171 MPI_Request key;
1172 void* buf;
1173 int count;
1174 MPI_Datatype datatype;
1176 ShadowRequest;
1178 static ShadowRequest* sReqs = NULL;
1179 static int sReqs_size = 0;
1180 static int sReqs_used = 0;
1181 static pthread_mutex_t sReqs_lock = PTHREAD_MUTEX_INITIALIZER;
1183 #define LOCK_SREQS \
1184 do { int pr = pthread_mutex_lock(&sReqs_lock); \
1185 assert(pr == 0); \
1186 } while (0)
1188 #define UNLOCK_SREQS \
1189 do { int pr = pthread_mutex_unlock(&sReqs_lock); \
1190 assert(pr == 0); \
1191 } while (0)
1194 /* Ensure the sReqs expandable array has at least one free slot, by
1195 copying it into a larger one if necessary. NOTE: sReqs_lock is
1196 held throughout this procedure.*/
1197 static void ensure_sReq_space ( void )
1199 int i;
1200 ShadowRequest* sReqs2;
1201 if (sReqs_used == sReqs_size) {
1202 sReqs_size = sReqs_size==0 ? 2 : 2*sReqs_size;
1203 sReqs2 = malloc( sReqs_size * sizeof(ShadowRequest) );
1204 if (sReqs2 == NULL) {
1205 UNLOCK_SREQS;
1206 barf("add_shadow_Request: malloc failed.\n");
1208 for (i = 0; i < sReqs_used; i++)
1209 sReqs2[i] = sReqs[i];
1210 if (sReqs)
1211 free(sReqs);
1212 sReqs = sReqs2;
1214 assert(sReqs_used < sReqs_size);
1218 /* Find shadow info for 'request', or NULL if none. */
1220 static
1221 ShadowRequest* find_shadow_Request ( MPI_Request request )
1223 ShadowRequest* ret = NULL;
1224 int i;
1225 LOCK_SREQS;
1226 for (i = 0; i < sReqs_used; i++) {
1227 if (sReqs[i].inUse && eq_MPI_Request(sReqs[i].key,request)) {
1228 ret = &sReqs[i];
1229 break;
1232 UNLOCK_SREQS;
1233 return ret;
1237 /* Delete shadow info for 'request', if any. */
1239 static void delete_shadow_Request ( MPI_Request request )
1241 int i;
1242 LOCK_SREQS;
1243 for (i = 0; i < sReqs_used; i++) {
1244 if (sReqs[i].inUse && eq_MPI_Request(sReqs[i].key,request)) {
1245 sReqs[i].inUse = False;
1246 break;
1249 UNLOCK_SREQS;
1253 /* Add a shadow for 'request', overwriting any old binding for it. */
1255 static
1256 void add_shadow_Request( MPI_Request request,
1257 void* buf, int count,
1258 MPI_Datatype datatype )
1260 int i, ix = -1;
1261 LOCK_SREQS;
1262 assert(sReqs_used >= 0);
1263 assert(sReqs_size >= 0);
1264 assert(sReqs_used <= sReqs_size);
1265 if (sReqs == NULL) assert(sReqs_size == 0);
1267 /* First of all see if we already have a binding for this key; if
1268 so just replace it, and have done. */
1269 for (i = 0; i < sReqs_used; i++) {
1270 if (sReqs[i].inUse && eq_MPI_Request(sReqs[i].key,request)) {
1271 ix = i;
1272 break;
1276 if (ix < 0) {
1277 /* Ok, we don't have it, so will have to add it. First search
1278 to see if there is an existing empty slot. */
1279 for (i = 0; i < sReqs_used; i++) {
1280 if (!sReqs[i].inUse) {
1281 ix = i;
1282 break;
1287 /* No empty slots. Allocate a new one. */
1288 if (ix < 0) {
1289 ensure_sReq_space();
1290 assert(sReqs_used < sReqs_size);
1291 ix = sReqs_used;
1292 sReqs_used++;
1295 assert(ix >= 0 && ix < sReqs_used);
1296 assert(sReqs_used <= sReqs_size);
1298 sReqs[ix].inUse = True;
1299 sReqs[ix].key = request;
1300 sReqs[ix].buf = buf;
1301 sReqs[ix].count = count;
1302 sReqs[ix].datatype = datatype;
1304 UNLOCK_SREQS;
1305 if (opt_verbosity > 1)
1306 fprintf(stderr, "%s %5d: sReq+ 0x%lx -> b/c/d %p/%d/0x%lx [slot %d]\n",
1307 preamble, my_pid, (unsigned long)request,
1308 buf, count, (long)datatype, ix);
1311 static
1312 MPI_Request* clone_Request_array ( int count, MPI_Request* orig )
1314 MPI_Request* copy;
1315 int i;
1316 LOCK_SREQS;
1317 if (count < 0)
1318 count = 0; /* Hmm. Call Mulder and Scully. */
1319 copy = malloc( count * sizeof(MPI_Request) );
1320 if (copy == NULL && count > 0) {
1321 UNLOCK_SREQS;
1322 barf("clone_Request_array: malloc failed");
1324 for (i = 0; i < count; i++)
1325 copy[i] = orig[i];
1326 UNLOCK_SREQS;
1327 return copy;
1330 #undef LOCK_SREQS
1331 #undef UNLOCK_SREQS
1334 static void maybe_complete ( Bool error_in_status,
1335 MPI_Request request_before,
1336 MPI_Request request_after,
1337 MPI_Status* status )
1339 int recv_count = 0;
1340 ShadowRequest* shadow;
1341 /* How do we know if this is an Irecv request that has now
1342 finished successfully?
1344 request_before isn't MPI_REQUEST_NULL
1345 and request_before is found in the shadow table
1346 and request_after *is* MPI_REQUEST_NULL
1347 and (if error_in_status then status.MPI_ERROR is MPI_SUCCESS)
1349 (when error_in_status == False, then we expect not to get
1350 called at all if there was an error.)
1352 if (request_before != MPI_REQUEST_NULL
1353 && request_after == MPI_REQUEST_NULL
1354 && (error_in_status ? status->MPI_ERROR == MPI_SUCCESS : True)
1355 && ( (shadow=find_shadow_Request(request_before)) != NULL) ) {
1356 /* The Irecv detailed in 'shadow' completed. Paint the result
1357 buffer, and delete the entry. */
1358 if (count_from_Status(&recv_count, shadow->datatype, status)) {
1359 make_mem_defined_if_addressable(shadow->buf, recv_count, shadow->datatype);
1360 if (opt_verbosity > 1)
1361 fprintf(stderr, "%s %5d: sReq- %p (completed)\n",
1362 preamble, my_pid, request_before);
1364 delete_shadow_Request(request_before);
1369 /* --- Isend --- */
1370 /* rd: (buf,count,datatype) */
1371 /* wr: *request */
1372 static __inline__
1373 int generic_Isend(void *buf, int count, MPI_Datatype datatype,
1374 int dest, int tag, MPI_Comm comm,
1375 MPI_Request* request)
1377 OrigFn fn;
1378 int err;
1379 VALGRIND_GET_ORIG_FN(fn);
1380 before("{,B,S,R}Isend");
1381 check_mem_is_defined(buf, count, datatype);
1382 check_mem_is_addressable_untyped(request, sizeof(*request));
1383 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1384 CALL_FN_W_7W(err, fn, buf,count,datatype,dest,tag,comm,request);
1385 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1386 make_mem_defined_if_addressable_if_success_untyped(err, request, sizeof(*request));
1387 after("{,B,S,R}Isend", err);
1388 return err;
1390 int WRAPPER_FOR(PMPI_Isend)(void *buf, int count, MPI_Datatype datatype,
1391 int dest, int tag, MPI_Comm comm,
1392 MPI_Request* request) {
1393 return generic_Isend(buf,count,datatype, dest,tag,comm, request);
1395 int WRAPPER_FOR(PMPI_Ibsend)(void *buf, int count, MPI_Datatype datatype,
1396 int dest, int tag, MPI_Comm comm,
1397 MPI_Request* request) {
1398 return generic_Isend(buf,count,datatype, dest,tag,comm, request);
1400 int WRAPPER_FOR(PMPI_Issend)(void *buf, int count, MPI_Datatype datatype,
1401 int dest, int tag, MPI_Comm comm,
1402 MPI_Request* request) {
1403 return generic_Isend(buf,count,datatype, dest,tag,comm, request);
1405 int WRAPPER_FOR(PMPI_Irsend)(void *buf, int count, MPI_Datatype datatype,
1406 int dest, int tag, MPI_Comm comm,
1407 MPI_Request* request) {
1408 return generic_Isend(buf,count,datatype, dest,tag,comm, request);
1412 /* --- Irecv --- */
1413 /* pre: must be writable: (buf,count,datatype), *request
1414 post: make readable *request
1415 add a request->(buf,count,ty) binding to the
1416 shadow request table.
1418 int WRAPPER_FOR(PMPI_Irecv)( void* buf, int count, MPI_Datatype datatype,
1419 int source, int tag, MPI_Comm comm,
1420 MPI_Request* request )
1422 OrigFn fn;
1423 int err;
1424 VALGRIND_GET_ORIG_FN(fn);
1425 before("Irecv");
1426 check_mem_is_addressable(buf, count, datatype);
1427 check_mem_is_addressable_untyped(request, sizeof(*request));
1428 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1429 CALL_FN_W_7W(err, fn, buf,count,datatype,source,tag,comm,request);
1430 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1431 if (err == MPI_SUCCESS) {
1432 make_mem_defined_if_addressable_untyped(request, sizeof(*request));
1433 add_shadow_Request( *request, buf,count,datatype );
1435 after("Irecv", err);
1436 return err;
1439 /* --- Wait --- */
1440 /* The MPI1 spec (imprecisely) defines 3 request states:
1441 - "null" if the request is MPI_REQUEST_NULL
1442 - "inactive" if not "null" and not associated with ongoing comms
1443 - "active" if not "null" and is associated with ongoing comms
1445 int WRAPPER_FOR(PMPI_Wait)( MPI_Request* request,
1446 MPI_Status* status )
1448 MPI_Request request_before;
1449 MPI_Status fake_status;
1450 OrigFn fn;
1451 int err;
1452 VALGRIND_GET_ORIG_FN(fn);
1453 before("Wait");
1454 if (isMSI(status))
1455 status = &fake_status;
1456 check_mem_is_addressable_untyped(status, sizeof(MPI_Status));
1457 check_mem_is_defined_untyped(request, sizeof(MPI_Request));
1458 request_before = *request;
1459 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1460 CALL_FN_W_WW(err, fn, request,status);
1461 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1462 if (err == MPI_SUCCESS) {
1463 maybe_complete(False/*err in status?*/,
1464 request_before, *request, status);
1465 make_mem_defined_if_addressable_untyped(status, sizeof(MPI_Status));
1467 after("Wait", err);
1468 return err;
1471 /* --- Waitany --- */
1472 int WRAPPER_FOR(PMPI_Waitany)( int count,
1473 MPI_Request* requests,
1474 int* index,
1475 MPI_Status* status )
1477 MPI_Request* requests_before = NULL;
1478 MPI_Status fake_status;
1479 OrigFn fn;
1480 int err, i;
1481 VALGRIND_GET_ORIG_FN(fn);
1482 before("Waitany");
1483 if (isMSI(status))
1484 status = &fake_status;
1485 if (0) fprintf(stderr, "Waitany: %d\n", count);
1486 check_mem_is_addressable_untyped(index, sizeof(int));
1487 check_mem_is_addressable_untyped(status, sizeof(MPI_Status));
1488 for (i = 0; i < count; i++) {
1489 check_mem_is_defined_untyped(&requests[i], sizeof(MPI_Request));
1491 requests_before = clone_Request_array( count, requests );
1492 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1493 CALL_FN_W_WWWW(err, fn, count,requests,index,status);
1494 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1495 if (err == MPI_SUCCESS && *index >= 0 && *index < count) {
1496 maybe_complete(False/*err in status?*/,
1497 requests_before[*index], requests[*index], status);
1498 make_mem_defined_if_addressable_untyped(status, sizeof(MPI_Status));
1500 if (requests_before)
1501 free(requests_before);
1502 after("Waitany", err);
1503 return err;
1506 /* --- Waitall --- */
1507 int WRAPPER_FOR(PMPI_Waitall)( int count,
1508 MPI_Request* requests,
1509 MPI_Status* statuses )
1511 MPI_Request* requests_before = NULL;
1512 OrigFn fn;
1513 int err, i;
1514 Bool free_sta = False;
1515 VALGRIND_GET_ORIG_FN(fn);
1516 before("Waitall");
1517 if (0) fprintf(stderr, "Waitall: %d\n", count);
1518 if (isMSI(statuses)) {
1519 free_sta = True;
1520 statuses = malloc( (count < 0 ? 0 : count) * sizeof(MPI_Status) );
1522 for (i = 0; i < count; i++) {
1523 check_mem_is_addressable_untyped(&statuses[i], sizeof(MPI_Status));
1524 check_mem_is_defined_untyped(&requests[i], sizeof(MPI_Request));
1526 requests_before = clone_Request_array( count, requests );
1527 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1528 CALL_FN_W_WWW(err, fn, count,requests,statuses);
1529 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1530 if (err == MPI_SUCCESS /*complete success*/
1531 || err == MPI_ERR_IN_STATUS /* partial success */) {
1532 Bool e_i_s = err == MPI_ERR_IN_STATUS;
1533 for (i = 0; i < count; i++) {
1534 maybe_complete(e_i_s, requests_before[i], requests[i],
1535 &statuses[i]);
1536 make_mem_defined_if_addressable_untyped(&statuses[i],
1537 sizeof(MPI_Status));
1540 if (requests_before)
1541 free(requests_before);
1542 if (free_sta)
1543 free(statuses);
1544 after("Waitall", err);
1545 return err;
1548 /* --- Test --- */
1549 /* nonblocking version of Wait */
1550 int WRAPPER_FOR(PMPI_Test)( MPI_Request* request, int* flag,
1551 MPI_Status* status )
1553 MPI_Request request_before;
1554 MPI_Status fake_status;
1555 OrigFn fn;
1556 int err;
1557 VALGRIND_GET_ORIG_FN(fn);
1558 before("Test");
1559 if (isMSI(status))
1560 status = &fake_status;
1561 check_mem_is_addressable_untyped(status, sizeof(MPI_Status));
1562 check_mem_is_addressable_untyped(flag, sizeof(int));
1563 check_mem_is_defined_untyped(request, sizeof(MPI_Request));
1564 request_before = *request;
1565 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1566 CALL_FN_W_WWW(err, fn, request,flag,status);
1567 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1568 if (err == MPI_SUCCESS && *flag) {
1569 maybe_complete(False/*err in status?*/,
1570 request_before, *request, status);
1571 make_mem_defined_if_addressable_untyped(status, sizeof(MPI_Status));
1573 after("Test", err);
1574 return err;
1577 /* --- Testall --- */
1578 /* nonblocking version of Waitall */
1579 int WRAPPER_FOR(PMPI_Testall)( int count, MPI_Request* requests,
1580 int* flag, MPI_Status* statuses )
1582 MPI_Request* requests_before = NULL;
1583 OrigFn fn;
1584 int err, i;
1585 Bool free_sta = False;
1586 VALGRIND_GET_ORIG_FN(fn);
1587 before("Testall");
1588 if (0) fprintf(stderr, "Testall: %d\n", count);
1589 if (isMSI(statuses)) {
1590 free_sta = True;
1591 statuses = malloc( (count < 0 ? 0 : count) * sizeof(MPI_Status) );
1593 check_mem_is_addressable_untyped(flag, sizeof(int));
1594 for (i = 0; i < count; i++) {
1595 check_mem_is_addressable_untyped(&statuses[i], sizeof(MPI_Status));
1596 check_mem_is_defined_untyped(&requests[i], sizeof(MPI_Request));
1598 requests_before = clone_Request_array( count, requests );
1599 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1600 CALL_FN_W_WWWW(err, fn, count,requests,flag,statuses);
1601 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1602 /* Urk. Is the following "if (...)" really right? I don't know. */
1603 if (*flag
1604 && (err == MPI_SUCCESS /*complete success*/
1605 || err == MPI_ERR_IN_STATUS /* partial success */)) {
1606 Bool e_i_s = err == MPI_ERR_IN_STATUS;
1607 for (i = 0; i < count; i++) {
1608 maybe_complete(e_i_s, requests_before[i], requests[i],
1609 &statuses[i]);
1610 make_mem_defined_if_addressable_untyped(&statuses[i],
1611 sizeof(MPI_Status));
1614 if (requests_before)
1615 free(requests_before);
1616 if (free_sta)
1617 free(statuses);
1618 after("Testall", err);
1619 return err;
1622 /* --- Iprobe --- */
1623 /* pre: must-be-writable: *flag, *status */
1624 /* post: make-readable *flag
1625 if *flag==True make-defined *status */
1626 int WRAPPER_FOR(PMPI_Iprobe)(int source, int tag,
1627 MPI_Comm comm,
1628 int* flag, MPI_Status* status)
1630 MPI_Status fake_status;
1631 OrigFn fn;
1632 int err;
1633 VALGRIND_GET_ORIG_FN(fn);
1634 before("Iprobe");
1635 if (isMSI(status))
1636 status = &fake_status;
1637 check_mem_is_addressable_untyped(flag, sizeof(*flag));
1638 check_mem_is_addressable_untyped(status, sizeof(*status));
1639 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1640 CALL_FN_W_5W(err, fn, source,tag,comm,flag,status);
1641 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1642 if (err == MPI_SUCCESS) {
1643 make_mem_defined_if_addressable_untyped(flag, sizeof(*flag));
1644 if (*flag)
1645 make_mem_defined_if_addressable_untyped(status, sizeof(*status));
1647 after("Iprobe", err);
1648 return err;
1651 /* --- Probe --- */
1652 /* pre: must-be-writable *status */
1653 /* post: make-defined *status */
1654 int WRAPPER_FOR(PMPI_Probe)(int source, int tag,
1655 MPI_Comm comm, MPI_Status* status)
1657 MPI_Status fake_status;
1658 OrigFn fn;
1659 int err;
1660 VALGRIND_GET_ORIG_FN(fn);
1661 before("Probe");
1662 if (isMSI(status))
1663 status = &fake_status;
1664 check_mem_is_addressable_untyped(status, sizeof(*status));
1665 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1666 CALL_FN_W_WWWW(err, fn, source,tag,comm,status);
1667 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1668 make_mem_defined_if_addressable_if_success_untyped(err, status, sizeof(*status));
1669 after("Probe", err);
1670 return err;
1673 /* --- Cancel --- */
1674 /* Wrapping PMPI_Cancel is interesting only to the extent that we need
1675 to be able to detect when a request should be removed from our
1676 shadow table due to cancellation. */
1677 int WRAPPER_FOR(PMPI_Cancel)(MPI_Request* request)
1679 OrigFn fn;
1680 int err;
1681 MPI_Request tmp;
1682 VALGRIND_GET_ORIG_FN(fn);
1683 before("Cancel");
1684 check_mem_is_addressable_untyped(request, sizeof(*request));
1685 tmp = *request;
1686 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1687 CALL_FN_W_W(err, fn, request);
1688 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1689 if (err == MPI_SUCCESS)
1690 delete_shadow_Request(tmp);
1691 after("Cancel", err);
1692 return err;
1696 /*------------------------------------------------------------*/
1697 /*--- ---*/
1698 /*--- Sec 3.10, Send-receive ---*/
1699 /*--- ---*/
1700 /*------------------------------------------------------------*/
1702 /* --- Sendrecv --- */
1703 /* pre: must be readable: (sendbuf,sendcount,sendtype)
1704 must be writable: (recvbuf,recvcount,recvtype)
1705 post: make readable: (recvbuf,recvcount_actual,datatype)
1706 where recvcount_actual is determined from *status
1708 int WRAPPER_FOR(PMPI_Sendrecv)(
1709 void *sendbuf, int sendcount, MPI_Datatype sendtype,
1710 int dest, int sendtag,
1711 void *recvbuf, int recvcount, MPI_Datatype recvtype,
1712 int source, int recvtag,
1713 MPI_Comm comm, MPI_Status *status)
1715 MPI_Status fake_status;
1716 OrigFn fn;
1717 int err, recvcount_actual = 0;
1718 VALGRIND_GET_ORIG_FN(fn);
1719 before("Sendrecv");
1720 if (isMSI(status))
1721 status = &fake_status;
1722 check_mem_is_defined(sendbuf, sendcount, sendtype);
1723 check_mem_is_addressable(recvbuf, recvcount, recvtype);
1724 check_mem_is_addressable_untyped(status, sizeof(*status));
1725 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1726 CALL_FN_W_12W(err, fn, sendbuf,sendcount,sendtype,dest,sendtag,
1727 recvbuf,recvcount,recvtype,source,recvtag,
1728 comm,status);
1729 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1730 make_mem_defined_if_addressable_if_success_untyped(err, status, sizeof(*status));
1731 if (err == MPI_SUCCESS
1732 && count_from_Status(&recvcount_actual,recvtype,status)) {
1733 make_mem_defined_if_addressable(recvbuf, recvcount_actual, recvtype);
1735 after("Sendrecv", err);
1736 return err;
1740 /*------------------------------------------------------------*/
1741 /*--- ---*/
1742 /*--- Sec 3.12, Derived datatypes ---*/
1743 /*--- ---*/
1744 /*------------------------------------------------------------*/
1746 /* --- Address --- */
1747 /* Does this have anything worth checking? */
1748 HAS_NO_WRAPPER(Address)
1750 /* --- MPI 2 stuff --- */
1751 /* Type_extent, Type_get_contents and Type_get_envelope sometimes get
1752 used intensively by the type walker (walk_type). There's no reason
1753 why they couldn't be properly wrapped if needed, but doing so slows
1754 everything down, so don't bother until needed. */
1755 HAS_NO_WRAPPER(Type_extent)
1756 HAS_NO_WRAPPER(Type_get_contents)
1757 HAS_NO_WRAPPER(Type_get_envelope)
1759 /* --- Type_commit --- */
1760 int WRAPPER_FOR(PMPI_Type_commit)( MPI_Datatype* ty )
1762 OrigFn fn;
1763 int err;
1764 VALGRIND_GET_ORIG_FN(fn);
1765 before("Type_commit");
1766 check_mem_is_defined_untyped(ty, sizeof(*ty));
1767 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1768 CALL_FN_W_W(err, fn, ty);
1769 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1770 after("Type_commit", err);
1771 return err;
1774 /* --- Type_free --- */
1775 int WRAPPER_FOR(PMPI_Type_free)( MPI_Datatype* ty )
1777 OrigFn fn;
1778 int err;
1779 VALGRIND_GET_ORIG_FN(fn);
1780 before("Type_free");
1781 check_mem_is_defined_untyped(ty, sizeof(*ty));
1782 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1783 CALL_FN_W_W(err, fn, ty);
1784 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1785 after("Type_free", err);
1786 return err;
1790 /*------------------------------------------------------------*/
1791 /*--- ---*/
1792 /*--- Sec 3.13, Pack and unpack ---*/
1793 /*--- ---*/
1794 /*------------------------------------------------------------*/
1796 /* --- Pack --- */
1797 /* pre: must be readable: position
1798 must be readable: (inbuf,incount,datatype)
1799 must be writable: outbuf[0 .. outsize-1]
1800 must be writable: outbuf[*position ..
1801 *position - 1
1802 + however much space PMPI_Pack_size
1803 says we will need]
1804 post: make readable: outbuf[old *position .. new *position]
1806 int WRAPPER_FOR(PMPI_Pack)( void* inbuf, int incount, MPI_Datatype datatype,
1807 void* outbuf, int outsize,
1808 int* position, MPI_Comm comm )
1810 OrigFn fn;
1811 int err, szB = 0;
1812 int position_ORIG = *position;
1813 VALGRIND_GET_ORIG_FN(fn);
1814 before("Pack");
1815 /* stay sane */
1816 check_mem_is_defined_untyped(position, sizeof(*position));
1817 /* check input */
1818 check_mem_is_defined(inbuf, incount, datatype);
1819 /* check output area's stated bounds make sense */
1820 check_mem_is_addressable_untyped(outbuf, outsize);
1821 /* check output area's actual used size properly */
1822 err = PMPI_Pack_size( incount, datatype, comm, &szB );
1823 if (err == MPI_SUCCESS && szB > 0) {
1824 check_mem_is_addressable_untyped(
1825 ((char*)outbuf) + position_ORIG, szB
1829 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1830 CALL_FN_W_7W(err, fn, inbuf,incount,datatype, outbuf,outsize,position, comm);
1831 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1833 if (err == MPI_SUCCESS && (*position) > position_ORIG) {
1834 /* paint output */
1835 make_mem_defined_if_addressable_untyped(
1836 ((char*)outbuf) + position_ORIG, *position - position_ORIG
1839 after("Pack", err);
1840 return err;
1843 /* --- Unpack --- */
1844 /* pre: must be readable: position
1845 must be writable: (outbuf,outcount,datatype)
1846 must be writable: outbuf[0 .. outsize-1]
1847 must be writable: outbuf[*position ..
1848 *position - 1
1849 + however much space PMPI_Pack_size
1850 says we will need]
1851 post: make readable: (outbuf,outcount,datatype)
1852 and also do a readability check of
1853 inbuf[old *position .. new *position]
1855 int WRAPPER_FOR(PMPI_Unpack)( void* inbuf, int insize, int* position,
1856 void* outbuf, int outcount, MPI_Datatype datatype,
1857 MPI_Comm comm )
1859 OrigFn fn;
1860 int err, szB = 0;
1861 int position_ORIG = *position;
1862 VALGRIND_GET_ORIG_FN(fn);
1863 before("Unpack");
1864 /* stay sane */
1865 check_mem_is_defined_untyped(position, sizeof(*position));
1866 /* check output area is accessible */
1867 check_mem_is_addressable(outbuf, outcount, datatype);
1868 /* check input area's stated bounds make sense */
1869 check_mem_is_addressable_untyped(inbuf, insize);
1870 /* check input area's actual used size properly */
1871 err = PMPI_Pack_size( outcount, datatype, comm, &szB );
1872 if (err == MPI_SUCCESS && szB > 0) {
1873 check_mem_is_addressable_untyped(
1874 ((char*)inbuf) + position_ORIG, szB
1878 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1879 CALL_FN_W_7W(err, fn, inbuf,insize,position, outbuf,outcount,datatype, comm);
1880 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1882 if (err == MPI_SUCCESS && (*position) > position_ORIG) {
1883 /* recheck input more carefully */
1884 check_mem_is_defined_untyped(
1885 ((char*)inbuf) + position_ORIG, *position - position_ORIG
1887 /* paint output */
1888 make_mem_defined_if_addressable( outbuf, outcount, datatype );
1890 after("Unpack", err);
1891 return err;
1895 /*------------------------------------------------------------*/
1896 /*--- ---*/
1897 /*--- Sec 4.4, Broadcast ---*/
1898 /*--- ---*/
1899 /*------------------------------------------------------------*/
1901 /* --- Bcast --- */
1902 /* pre: must-be-readable (buffer,count,datatype) for rank==root
1903 must-be-writable (buffer,count,datatype) for rank!=root
1904 post: make-readable (buffer,count,datatype) for all
1906 Resulting behaviour is: if root sends uninitialised stuff, then
1907 V complains, but then all ranks, including itself, see the buffer
1908 as initialised after that.
1910 int WRAPPER_FOR(PMPI_Bcast)(void *buffer, int count,
1911 MPI_Datatype datatype,
1912 int root, MPI_Comm comm)
1914 OrigFn fn;
1915 int err;
1916 Bool i_am_sender;
1917 VALGRIND_GET_ORIG_FN(fn);
1918 before("Bcast");
1919 i_am_sender = root == comm_rank(comm);
1920 if (i_am_sender) {
1921 check_mem_is_defined(buffer, count, datatype);
1922 } else {
1923 check_mem_is_addressable(buffer, count, datatype);
1925 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1926 CALL_FN_W_5W(err, fn, buffer,count,datatype,root,comm);
1927 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1928 make_mem_defined_if_addressable_if_success(err, buffer, count, datatype);
1929 after("Bcast", err);
1930 return err;
1934 /*------------------------------------------------------------*/
1935 /*--- ---*/
1936 /*--- Sec 4.5, Gather ---*/
1937 /*--- ---*/
1938 /*------------------------------------------------------------*/
1940 /* --- Gather --- */
1941 /* JRS 20060217: I don't really understand this. Each process is
1942 going to send sendcount items of type sendtype to the root. So
1943 the root is going to receive comm_size*sendcount items of type
1944 sendtype (right?) So why specify recvcount and recvtype?
1946 Anyway, assuming the MPI Spec is correct (seems likely :-) we have:
1948 pre: (all) must be readable: (sendbuf,sendcount,sendtype)
1949 (root only): must be writable: (recvbuf,recvcount * comm_size,recvtype)
1950 post: (root only): make readable: (recvbuf,recvcount * comm_size,recvtype)
1952 int WRAPPER_FOR(PMPI_Gather)(
1953 void *sendbuf, int sendcount, MPI_Datatype sendtype,
1954 void *recvbuf, int recvcount, MPI_Datatype recvtype,
1955 int root, MPI_Comm comm)
1957 OrigFn fn;
1958 int err, me, sz;
1959 VALGRIND_GET_ORIG_FN(fn);
1960 before("Gather");
1961 me = comm_rank(comm);
1962 sz = comm_size(comm);
1963 check_mem_is_defined(sendbuf, sendcount, sendtype);
1964 if (me == root)
1965 check_mem_is_addressable(recvbuf, recvcount * sz, recvtype);
1966 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1967 CALL_FN_W_8W(err, fn, sendbuf,sendcount,sendtype,
1968 recvbuf,recvcount,recvtype,
1969 root,comm);
1970 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1971 if (me == root)
1972 make_mem_defined_if_addressable_if_success(err, recvbuf, recvcount * sz, recvtype);
1973 after("Gather", err);
1974 return err;
1978 /*------------------------------------------------------------*/
1979 /*--- ---*/
1980 /*--- Sec 4.6, Scatter ---*/
1981 /*--- ---*/
1982 /*------------------------------------------------------------*/
1984 /* pre: (root only): must be readable: (sendbuf,sendcount * comm_size,sendtype)
1985 (all): must be writable: (recvbuf,recvbuf,recvtype)
1986 post: (all): make defined: (recvbuf,recvbuf,recvtype)
1988 int WRAPPER_FOR(PMPI_Scatter)(
1989 void* sendbuf, int sendcount, MPI_Datatype sendtype,
1990 void* recvbuf, int recvcount, MPI_Datatype recvtype,
1991 int root, MPI_Comm comm)
1993 OrigFn fn;
1994 int err, me, sz;
1995 VALGRIND_GET_ORIG_FN(fn);
1996 before("Scatter");
1997 me = comm_rank(comm);
1998 sz = comm_size(comm);
1999 check_mem_is_addressable(recvbuf, recvcount, recvtype);
2000 if (me == root)
2001 check_mem_is_defined(sendbuf, sendcount * sz, sendtype);
2002 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2003 CALL_FN_W_8W(err, fn, sendbuf,sendcount,sendtype,
2004 recvbuf,recvcount,recvtype,
2005 root,comm);
2006 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2007 make_mem_defined_if_addressable_if_success(err, recvbuf, recvcount, recvtype);
2008 after("Scatter", err);
2009 return err;
2013 /*------------------------------------------------------------*/
2014 /*--- ---*/
2015 /*--- Sec 4.8, All-to-All Scatter/Gather ---*/
2016 /*--- ---*/
2017 /*------------------------------------------------------------*/
2019 /* pre: (all) must be readable: (sendbuf,sendcount * comm_size,sendtype)
2020 (all) must be writable: (recvbuf,recvcount * comm_size,recvtype)
2021 post: (all) make defined: (recvbuf,recvcount * comm_size,recvtype)
2023 int WRAPPER_FOR(PMPI_Alltoall)(
2024 void* sendbuf, int sendcount, MPI_Datatype sendtype,
2025 void* recvbuf, int recvcount, MPI_Datatype recvtype,
2026 MPI_Comm comm)
2028 OrigFn fn;
2029 int err, sz;
2030 VALGRIND_GET_ORIG_FN(fn);
2031 before("Alltoall");
2032 sz = comm_size(comm);
2033 check_mem_is_defined(sendbuf, sendcount * sz, sendtype);
2034 check_mem_is_addressable(recvbuf, recvcount * sz, recvtype);
2035 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2036 CALL_FN_W_7W(err, fn, sendbuf,sendcount,sendtype,
2037 recvbuf,recvcount,recvtype,
2038 comm);
2039 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2040 make_mem_defined_if_addressable_if_success(err, recvbuf, recvcount * sz, recvtype);
2041 after("Alltoall", err);
2042 return err;
2046 /*------------------------------------------------------------*/
2047 /*--- ---*/
2048 /*--- Sec 4.9, Global Reduction Operations ---*/
2049 /*--- ---*/
2050 /*------------------------------------------------------------*/
2052 /* --- Reduce --- */
2053 /* rd: (sendbuf,count,datatype) for all
2054 wr: (recvbuf,count,datatype) but only for rank == root
2056 int WRAPPER_FOR(PMPI_Reduce)(void *sendbuf, void *recvbuf,
2057 int count,
2058 MPI_Datatype datatype, MPI_Op op,
2059 int root, MPI_Comm comm)
2061 OrigFn fn;
2062 int err;
2063 Bool i_am_root;
2064 VALGRIND_GET_ORIG_FN(fn);
2065 before("Reduce");
2066 i_am_root = root == comm_rank(comm);
2067 check_mem_is_defined(sendbuf, count, datatype);
2068 if (i_am_root)
2069 check_mem_is_addressable(recvbuf, count, datatype);
2070 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2071 CALL_FN_W_7W(err, fn, sendbuf,recvbuf,count,datatype,op,root,comm);
2072 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2073 if (i_am_root)
2074 make_mem_defined_if_addressable_if_success(err, recvbuf, count, datatype);
2075 after("Reduce", err);
2076 return err;
2080 /* --- Allreduce --- */
2081 /* rd: (sendbuf,count,datatype) for all
2082 wr: (recvbuf,count,datatype) for all
2084 int WRAPPER_FOR(PMPI_Allreduce)(void *sendbuf, void *recvbuf,
2085 int count,
2086 MPI_Datatype datatype, MPI_Op op,
2087 MPI_Comm comm)
2089 OrigFn fn;
2090 int err;
2091 VALGRIND_GET_ORIG_FN(fn);
2092 before("Allreduce");
2093 check_mem_is_defined(sendbuf, count, datatype);
2094 check_mem_is_addressable(recvbuf, count, datatype);
2095 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2096 CALL_FN_W_6W(err, fn, sendbuf,recvbuf,count,datatype,op,comm);
2097 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2098 make_mem_defined_if_addressable_if_success(err, recvbuf, count, datatype);
2099 after("Allreduce", err);
2100 return err;
2104 /* --- Op_create --- */
2105 /* This is a bit dubious. I suppose it takes 'function' and
2106 writes something at *op, but who knows what an MPI_Op is?
2107 Can we safely do 'sizeof' on it? */
2108 int WRAPPER_FOR(PMPI_Op_create)( MPI_User_function* function,
2109 int commute,
2110 MPI_Op* op )
2112 OrigFn fn;
2113 int err;
2114 VALGRIND_GET_ORIG_FN(fn);
2115 before("Op_create");
2116 check_mem_is_addressable_untyped(op, sizeof(*op));
2117 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2118 CALL_FN_W_WWW(err, fn, function,commute,op);
2119 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2120 make_mem_defined_if_addressable_if_success_untyped(err, op, sizeof(*op));
2121 after("Op_create", err);
2122 return err;
2126 /*------------------------------------------------------------*/
2127 /*--- ---*/
2128 /*--- Sec 5.4, Communicator management ---*/
2129 /*--- ---*/
2130 /*------------------------------------------------------------*/
2132 /* Hardly seems worth wrapping Comm_rank and Comm_size, but
2133 since it's done now .. */
2135 /* --- Comm_create --- */
2136 /* Let normal memcheck tracking handle this. */
2137 int WRAPPER_FOR(PMPI_Comm_create)(MPI_Comm comm, MPI_Group group,
2138 MPI_Comm* newcomm)
2140 OrigFn fn;
2141 int err;
2142 VALGRIND_GET_ORIG_FN(fn);
2143 before("Comm_create");
2144 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2145 CALL_FN_W_WWW(err, fn, comm,group,newcomm);
2146 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2147 after("Comm_create", err);
2148 return err;
2151 /* --- Comm_dup --- */
2152 /* Let normal memcheck tracking handle this. */
2153 int WRAPPER_FOR(PMPI_Comm_dup)(MPI_Comm comm, MPI_Comm* newcomm)
2155 OrigFn fn;
2156 int err;
2157 VALGRIND_GET_ORIG_FN(fn);
2158 before("Comm_dup");
2159 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2160 CALL_FN_W_WW(err, fn, comm,newcomm);
2161 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2162 after("Comm_dup", err);
2163 return err;
2166 /* --- Comm_free --- */
2167 /* Let normal memcheck tracking handle this. */
2168 int WRAPPER_FOR(PMPI_Comm_free)(MPI_Comm* comm)
2170 OrigFn fn;
2171 int err;
2172 VALGRIND_GET_ORIG_FN(fn);
2173 before("Comm_free");
2174 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2175 CALL_FN_W_W(err, fn, comm);
2176 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2177 after("Comm_free", err);
2178 return err;
2181 /* --- Comm_rank --- */
2182 /* wr: (rank, sizeof(*rank)) */
2183 int WRAPPER_FOR(PMPI_Comm_rank)(MPI_Comm comm, int *rank)
2185 OrigFn fn;
2186 int err;
2187 VALGRIND_GET_ORIG_FN(fn);
2188 before("Comm_rank");
2189 check_mem_is_addressable_untyped(rank, sizeof(*rank));
2190 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2191 CALL_FN_W_WW(err, fn, comm,rank);
2192 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2193 make_mem_defined_if_addressable_if_success_untyped(err, rank, sizeof(*rank));
2194 after("Comm_rank", err);
2195 return err;
2198 /* --- Comm_size --- */
2199 /* wr: (size, sizeof(*size)) */
2200 int WRAPPER_FOR(PMPI_Comm_size)(MPI_Comm comm, int *size)
2202 OrigFn fn;
2203 int err;
2204 VALGRIND_GET_ORIG_FN(fn);
2205 before("Comm_size");
2206 check_mem_is_addressable_untyped(size, sizeof(*size));
2207 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2208 CALL_FN_W_WW(err, fn, comm,size);
2209 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2210 make_mem_defined_if_addressable_if_success_untyped(err, size, sizeof(*size));
2211 after("Comm_size", err);
2212 return err;
2216 /*------------------------------------------------------------*/
2217 /*--- ---*/
2218 /*--- Sec 5.7, Caching ---*/
2219 /*--- ---*/
2220 /*------------------------------------------------------------*/
2223 /*------------------------------------------------------------*/
2224 /*--- ---*/
2225 /*--- Sec 7.3, Error codes and classes ---*/
2226 /*--- ---*/
2227 /*------------------------------------------------------------*/
2229 /* --- Error_string --- */
2230 int WRAPPER_FOR(PMPI_Error_string)( int errorcode, char* string,
2231 int* resultlen )
2233 OrigFn fn;
2234 int err;
2235 VALGRIND_GET_ORIG_FN(fn);
2236 before("Error_string");
2237 check_mem_is_addressable_untyped(resultlen, sizeof(int));
2238 check_mem_is_addressable_untyped(string, MPI_MAX_ERROR_STRING);
2239 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2240 CALL_FN_W_WWW(err, fn, errorcode,string,resultlen);
2241 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2242 /* Don't bother to paint the result; we assume the real function
2243 will have filled it with defined characters :-) */
2244 after("Error_string", err);
2245 return err;
2249 /*------------------------------------------------------------*/
2250 /*--- ---*/
2251 /*--- Sec 7.5, Startup ---*/
2252 /*--- ---*/
2253 /*------------------------------------------------------------*/
2255 /* --- Init --- */
2256 /* rd: *argc, *argv[0 .. *argc-1] */
2257 long WRAPPER_FOR(PMPI_Init)(int *argc, char ***argv)
2259 OrigFn fn;
2260 int err;
2261 VALGRIND_GET_ORIG_FN(fn);
2262 before("Init");
2263 if (argc) {
2264 check_mem_is_defined_untyped(argc, sizeof(int));
2266 if (argc && argv) {
2267 check_mem_is_defined_untyped(*argv, *argc * sizeof(char**));
2269 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2270 CALL_FN_W_WW(err, fn, argc,argv);
2271 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2272 after("Init", err);
2273 if (opt_initkludge)
2274 return (long)(void*)&mpiwrap_walk_type_EXTERNALLY_VISIBLE;
2275 else
2276 return (long)err;
2279 /* --- Initialized --- */
2280 int WRAPPER_FOR(PMPI_Initialized)(int* flag)
2282 OrigFn fn;
2283 int err;
2284 VALGRIND_GET_ORIG_FN(fn);
2285 before("Initialized");
2286 check_mem_is_addressable_untyped(flag, sizeof(int));
2287 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2288 CALL_FN_W_W(err, fn, flag);
2289 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2290 make_mem_defined_if_addressable_if_success_untyped(err, flag, sizeof(int));
2291 after("Initialized", err);
2292 return err;
2295 /* --- Finalize --- */
2296 int WRAPPER_FOR(PMPI_Finalize)(void)
2298 OrigFn fn;
2299 int err;
2300 VALGRIND_GET_ORIG_FN(fn);
2301 before("Finalize");
2302 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2303 CALL_FN_W_v(err, fn);
2304 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2305 after("Finalize", err);
2306 return err;
2310 /*------------------------------------------------------------*/
2311 /*--- ---*/
2312 /*--- Default wrappers for all remaining functions ---*/
2313 /*--- ---*/
2314 /*------------------------------------------------------------*/
2316 /* Boilerplate for default wrappers. */
2317 #define DEFAULT_WRAPPER_PREAMBLE(basename) \
2318 OrigFn fn; \
2319 UWord res; \
2320 static int complaints = 1; \
2321 VALGRIND_GET_ORIG_FN(fn); \
2322 before(#basename); \
2323 if (opt_missing >= 2) { \
2324 barf("no wrapper for PMPI_" #basename \
2325 ",\n\t\t\t and you have " \
2326 "requested strict checking"); \
2328 if (opt_missing == 1 && complaints > 0) { \
2329 fprintf(stderr, "%s %5d: warning: no wrapper " \
2330 "for PMPI_" #basename "\n", \
2331 preamble, my_pid); \
2332 complaints--; \
2335 #define DEFAULT_WRAPPER_W_0W(basename) \
2336 UWord WRAPPER_FOR(PMPI_##basename)( void ) \
2338 DEFAULT_WRAPPER_PREAMBLE(basename) \
2339 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2340 CALL_FN_W_v(res, fn); \
2341 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2342 return res; \
2345 #define DEFAULT_WRAPPER_W_1W(basename) \
2346 UWord WRAPPER_FOR(PMPI_##basename)( UWord a1 ) \
2348 DEFAULT_WRAPPER_PREAMBLE(basename) \
2349 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2350 CALL_FN_W_W(res, fn, a1); \
2351 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2352 return res; \
2355 #define DEFAULT_WRAPPER_W_2W(basename) \
2356 UWord WRAPPER_FOR(PMPI_##basename)( UWord a1, UWord a2 ) \
2358 DEFAULT_WRAPPER_PREAMBLE(basename) \
2359 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2360 CALL_FN_W_WW(res, fn, a1,a2); \
2361 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2362 return res; \
2365 #define DEFAULT_WRAPPER_W_3W(basename) \
2366 UWord WRAPPER_FOR(PMPI_##basename) \
2367 ( UWord a1, UWord a2, UWord a3 ) \
2369 DEFAULT_WRAPPER_PREAMBLE(basename) \
2370 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2371 CALL_FN_W_WWW(res, fn, a1,a2,a3); \
2372 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2373 return res; \
2376 #define DEFAULT_WRAPPER_W_4W(basename) \
2377 UWord WRAPPER_FOR(PMPI_##basename) \
2378 ( UWord a1, UWord a2, UWord a3, UWord a4 ) \
2380 DEFAULT_WRAPPER_PREAMBLE(basename) \
2381 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2382 CALL_FN_W_WWWW(res, fn, a1,a2,a3,a4); \
2383 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2384 return res; \
2387 #define DEFAULT_WRAPPER_W_5W(basename) \
2388 UWord WRAPPER_FOR(PMPI_##basename) \
2389 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5 ) \
2391 DEFAULT_WRAPPER_PREAMBLE(basename) \
2392 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2393 CALL_FN_W_5W(res, fn, a1,a2,a3,a4,a5); \
2394 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2395 return res; \
2398 #define DEFAULT_WRAPPER_W_6W(basename) \
2399 UWord WRAPPER_FOR(PMPI_##basename) \
2400 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2401 UWord a6 ) \
2403 DEFAULT_WRAPPER_PREAMBLE(basename) \
2404 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2405 CALL_FN_W_6W(res, fn, a1,a2,a3,a4,a5,a6); \
2406 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2407 return res; \
2410 #define DEFAULT_WRAPPER_W_7W(basename) \
2411 UWord WRAPPER_FOR(PMPI_##basename) \
2412 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2413 UWord a6, UWord a7 ) \
2415 DEFAULT_WRAPPER_PREAMBLE(basename) \
2416 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2417 CALL_FN_W_7W(res, fn, a1,a2,a3,a4,a5,a6,a7); \
2418 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2419 return res; \
2422 #define DEFAULT_WRAPPER_W_8W(basename) \
2423 UWord WRAPPER_FOR(PMPI_##basename) \
2424 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2425 UWord a6, UWord a7, UWord a8 ) \
2427 DEFAULT_WRAPPER_PREAMBLE(basename) \
2428 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2429 CALL_FN_W_8W(res, fn, a1,a2,a3,a4,a5,a6,a7,a8); \
2430 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2431 return res; \
2434 #define DEFAULT_WRAPPER_W_9W(basename) \
2435 UWord WRAPPER_FOR(PMPI_##basename) \
2436 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2437 UWord a6, UWord a7, UWord a8, UWord a9 ) \
2439 DEFAULT_WRAPPER_PREAMBLE(basename) \
2440 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2441 CALL_FN_W_9W(res, fn, a1,a2,a3,a4,a5,a6,a7,a8,a9); \
2442 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2443 return res; \
2446 #define DEFAULT_WRAPPER_W_10W(basename) \
2447 UWord WRAPPER_FOR(PMPI_##basename) \
2448 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2449 UWord a6, UWord a7, UWord a8, UWord a9, UWord a10 ) \
2451 DEFAULT_WRAPPER_PREAMBLE(basename) \
2452 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2453 CALL_FN_W_10W(res, fn, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10); \
2454 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2455 return res; \
2458 #define DEFAULT_WRAPPER_W_12W(basename) \
2459 UWord WRAPPER_FOR(PMPI_##basename) \
2460 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2461 UWord a6, UWord a7, UWord a8, UWord a9, UWord a10, \
2462 UWord a11, UWord a12 ) \
2464 DEFAULT_WRAPPER_PREAMBLE(basename) \
2465 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2466 CALL_FN_W_12W(res, fn, a1,a2,a3,a4,a5,a6, \
2467 a7,a8,a9,a10,a11,a12); \
2468 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2469 return res; \
2473 /* Canned summary of MPI-1.1/MPI-2 entry points, as derived from mpi.h
2474 from Open MPI svn rev 9191 (somewhere between Open MPI versions
2475 1.0.1 and 1.1.0). */
2477 /* If a function is commented out in this list, it's because it has a
2478 proper wrapper written elsewhere (above here). */
2480 DEFAULT_WRAPPER_W_2W(Abort)
2481 DEFAULT_WRAPPER_W_9W(Accumulate)
2482 DEFAULT_WRAPPER_W_1W(Add_error_class)
2483 DEFAULT_WRAPPER_W_2W(Add_error_code)
2484 DEFAULT_WRAPPER_W_2W(Add_error_string)
2485 /* DEFAULT_WRAPPER_W_2W(Address) */
2486 DEFAULT_WRAPPER_W_7W(Allgather)
2487 DEFAULT_WRAPPER_W_8W(Allgatherv)
2488 DEFAULT_WRAPPER_W_3W(Alloc_mem)
2489 /* DEFAULT_WRAPPER_W_6W(Allreduce) */
2490 /* DEFAULT_WRAPPER_W_7W(Alltoall) */
2491 DEFAULT_WRAPPER_W_9W(Alltoallv)
2492 DEFAULT_WRAPPER_W_9W(Alltoallw)
2493 DEFAULT_WRAPPER_W_2W(Attr_delete)
2494 DEFAULT_WRAPPER_W_4W(Attr_get)
2495 DEFAULT_WRAPPER_W_3W(Attr_put)
2496 DEFAULT_WRAPPER_W_1W(Barrier)
2497 /* DEFAULT_WRAPPER_W_5W(Bcast) */
2498 /* DEFAULT_WRAPPER_W_6W(Bsend) */
2499 DEFAULT_WRAPPER_W_7W(Bsend_init)
2500 DEFAULT_WRAPPER_W_2W(Buffer_attach)
2501 DEFAULT_WRAPPER_W_2W(Buffer_detach)
2502 /* DEFAULT_WRAPPER_W_1W(Cancel) */
2503 DEFAULT_WRAPPER_W_4W(Cart_coords)
2504 DEFAULT_WRAPPER_W_6W(Cart_create)
2505 DEFAULT_WRAPPER_W_5W(Cart_get)
2506 DEFAULT_WRAPPER_W_5W(Cart_map)
2507 DEFAULT_WRAPPER_W_3W(Cart_rank)
2508 DEFAULT_WRAPPER_W_5W(Cart_shift)
2509 DEFAULT_WRAPPER_W_3W(Cart_sub)
2510 DEFAULT_WRAPPER_W_2W(Cartdim_get)
2511 DEFAULT_WRAPPER_W_1W(Close_port)
2512 DEFAULT_WRAPPER_W_5W(Comm_accept)
2513 DEFAULT_WRAPPER_W_1W(Comm_c2f)
2514 DEFAULT_WRAPPER_W_2W(Comm_call_errhandler)
2515 DEFAULT_WRAPPER_W_3W(Comm_compare)
2516 DEFAULT_WRAPPER_W_5W(Comm_connect)
2517 DEFAULT_WRAPPER_W_2W(Comm_create_errhandler)
2518 DEFAULT_WRAPPER_W_4W(Comm_create_keyval)
2519 /* DEFAULT_WRAPPER_W_3W(Comm_create) */
2520 DEFAULT_WRAPPER_W_2W(Comm_delete_attr)
2521 DEFAULT_WRAPPER_W_1W(Comm_disconnect)
2522 /* DEFAULT_WRAPPER_W_2W(Comm_dup) */
2523 DEFAULT_WRAPPER_W_1W(Comm_f2c)
2524 DEFAULT_WRAPPER_W_1W(Comm_free_keyval)
2525 /* DEFAULT_WRAPPER_W_1W(Comm_free) */
2526 DEFAULT_WRAPPER_W_4W(Comm_get_attr)
2527 DEFAULT_WRAPPER_W_2W(Comm_get_errhandler)
2528 DEFAULT_WRAPPER_W_3W(Comm_get_name)
2529 DEFAULT_WRAPPER_W_1W(Comm_get_parent)
2530 DEFAULT_WRAPPER_W_2W(Comm_group)
2531 DEFAULT_WRAPPER_W_2W(Comm_join)
2532 /* DEFAULT_WRAPPER_W_2W(Comm_rank) */
2533 DEFAULT_WRAPPER_W_2W(Comm_remote_group)
2534 DEFAULT_WRAPPER_W_2W(Comm_remote_size)
2535 DEFAULT_WRAPPER_W_3W(Comm_set_attr)
2536 DEFAULT_WRAPPER_W_2W(Comm_set_errhandler)
2537 DEFAULT_WRAPPER_W_2W(Comm_set_name)
2538 /* DEFAULT_WRAPPER_W_2W(Comm_size) */
2539 DEFAULT_WRAPPER_W_8W(Comm_spawn)
2540 DEFAULT_WRAPPER_W_9W(Comm_spawn_multiple)
2541 DEFAULT_WRAPPER_W_4W(Comm_split)
2542 DEFAULT_WRAPPER_W_2W(Comm_test_inter)
2543 DEFAULT_WRAPPER_W_3W(Dims_create)
2544 DEFAULT_WRAPPER_W_1W(Errhandler_c2f)
2545 DEFAULT_WRAPPER_W_2W(Errhandler_create)
2546 DEFAULT_WRAPPER_W_1W(Errhandler_f2c)
2547 DEFAULT_WRAPPER_W_1W(Errhandler_free)
2548 DEFAULT_WRAPPER_W_2W(Errhandler_get)
2549 DEFAULT_WRAPPER_W_2W(Errhandler_set)
2550 DEFAULT_WRAPPER_W_2W(Error_class)
2551 /* DEFAULT_WRAPPER_W_3W(Error_string) */
2552 DEFAULT_WRAPPER_W_6W(Exscan)
2553 DEFAULT_WRAPPER_W_1W(File_c2f)
2554 DEFAULT_WRAPPER_W_1W(File_f2c)
2555 DEFAULT_WRAPPER_W_2W(File_call_errhandler)
2556 DEFAULT_WRAPPER_W_2W(File_create_errhandler)
2557 DEFAULT_WRAPPER_W_2W(File_set_errhandler)
2558 DEFAULT_WRAPPER_W_2W(File_get_errhandler)
2559 DEFAULT_WRAPPER_W_5W(File_open)
2560 DEFAULT_WRAPPER_W_1W(File_close)
2561 DEFAULT_WRAPPER_W_2W(File_delete)
2562 DEFAULT_WRAPPER_W_2W(File_set_size)
2563 DEFAULT_WRAPPER_W_2W(File_preallocate)
2564 DEFAULT_WRAPPER_W_2W(File_get_size)
2565 DEFAULT_WRAPPER_W_2W(File_get_group)
2566 DEFAULT_WRAPPER_W_2W(File_get_amode)
2567 DEFAULT_WRAPPER_W_2W(File_set_info)
2568 DEFAULT_WRAPPER_W_2W(File_get_info)
2569 DEFAULT_WRAPPER_W_6W(File_set_view)
2570 DEFAULT_WRAPPER_W_5W(File_get_view)
2571 DEFAULT_WRAPPER_W_6W(File_read_at)
2572 DEFAULT_WRAPPER_W_6W(File_read_at_all)
2573 DEFAULT_WRAPPER_W_6W(File_write_at)
2574 DEFAULT_WRAPPER_W_6W(File_write_at_all)
2575 DEFAULT_WRAPPER_W_6W(File_iread_at)
2576 DEFAULT_WRAPPER_W_6W(File_iwrite_at)
2577 DEFAULT_WRAPPER_W_5W(File_read)
2578 DEFAULT_WRAPPER_W_5W(File_read_all)
2579 DEFAULT_WRAPPER_W_5W(File_write)
2580 DEFAULT_WRAPPER_W_5W(File_write_all)
2581 DEFAULT_WRAPPER_W_5W(File_iread)
2582 DEFAULT_WRAPPER_W_5W(File_iwrite)
2583 DEFAULT_WRAPPER_W_3W(File_seek)
2584 DEFAULT_WRAPPER_W_2W(File_get_position)
2585 DEFAULT_WRAPPER_W_3W(File_get_byte_offset)
2586 DEFAULT_WRAPPER_W_5W(File_read_shared)
2587 DEFAULT_WRAPPER_W_5W(File_write_shared)
2588 DEFAULT_WRAPPER_W_5W(File_iread_shared)
2589 DEFAULT_WRAPPER_W_5W(File_iwrite_shared)
2590 DEFAULT_WRAPPER_W_5W(File_read_ordered)
2591 DEFAULT_WRAPPER_W_5W(File_write_ordered)
2592 DEFAULT_WRAPPER_W_3W(File_seek_shared)
2593 DEFAULT_WRAPPER_W_2W(File_get_position_shared)
2594 DEFAULT_WRAPPER_W_5W(File_read_at_all_begin)
2595 DEFAULT_WRAPPER_W_3W(File_read_at_all_end)
2596 DEFAULT_WRAPPER_W_5W(File_write_at_all_begin)
2597 DEFAULT_WRAPPER_W_3W(File_write_at_all_end)
2598 DEFAULT_WRAPPER_W_4W(File_read_all_begin)
2599 DEFAULT_WRAPPER_W_3W(File_read_all_end)
2600 DEFAULT_WRAPPER_W_4W(File_write_all_begin)
2601 DEFAULT_WRAPPER_W_3W(File_write_all_end)
2602 DEFAULT_WRAPPER_W_4W(File_read_ordered_begin)
2603 DEFAULT_WRAPPER_W_3W(File_read_ordered_end)
2604 DEFAULT_WRAPPER_W_4W(File_write_ordered_begin)
2605 DEFAULT_WRAPPER_W_3W(File_write_ordered_end)
2606 DEFAULT_WRAPPER_W_3W(File_get_type_extent)
2607 DEFAULT_WRAPPER_W_2W(File_set_atomicity)
2608 DEFAULT_WRAPPER_W_2W(File_get_atomicity)
2609 DEFAULT_WRAPPER_W_1W(File_sync)
2610 /* DEFAULT_WRAPPER_W_0W(Finalize) */
2611 DEFAULT_WRAPPER_W_1W(Finalized)
2612 DEFAULT_WRAPPER_W_1W(Free_mem)
2613 /* DEFAULT_WRAPPER_W_8W(Gather) */
2614 DEFAULT_WRAPPER_W_9W(Gatherv)
2615 DEFAULT_WRAPPER_W_2W(Get_address)
2616 /* DEFAULT_WRAPPER_W_3W(Get_count) */
2617 DEFAULT_WRAPPER_W_3W(Get_elements)
2618 DEFAULT_WRAPPER_W_8W(Get)
2619 DEFAULT_WRAPPER_W_2W(Get_processor_name)
2620 DEFAULT_WRAPPER_W_2W(Get_version)
2621 DEFAULT_WRAPPER_W_6W(Graph_create)
2622 DEFAULT_WRAPPER_W_5W(Graph_get)
2623 DEFAULT_WRAPPER_W_5W(Graph_map)
2624 DEFAULT_WRAPPER_W_3W(Graph_neighbors_count)
2625 DEFAULT_WRAPPER_W_4W(Graph_neighbors)
2626 DEFAULT_WRAPPER_W_3W(Graphdims_get)
2627 DEFAULT_WRAPPER_W_1W(Grequest_complete)
2628 DEFAULT_WRAPPER_W_5W(Grequest_start)
2629 DEFAULT_WRAPPER_W_1W(Group_c2f)
2630 DEFAULT_WRAPPER_W_3W(Group_compare)
2631 DEFAULT_WRAPPER_W_3W(Group_difference)
2632 DEFAULT_WRAPPER_W_4W(Group_excl)
2633 DEFAULT_WRAPPER_W_1W(Group_f2c)
2634 DEFAULT_WRAPPER_W_1W(Group_free)
2635 DEFAULT_WRAPPER_W_4W(Group_incl)
2636 DEFAULT_WRAPPER_W_3W(Group_intersection)
2637 DEFAULT_WRAPPER_W_4W(Group_range_excl)
2638 DEFAULT_WRAPPER_W_4W(Group_range_incl)
2639 DEFAULT_WRAPPER_W_2W(Group_rank)
2640 DEFAULT_WRAPPER_W_2W(Group_size)
2641 DEFAULT_WRAPPER_W_5W(Group_translate_ranks)
2642 DEFAULT_WRAPPER_W_3W(Group_union)
2643 /* DEFAULT_WRAPPER_W_7W(Ibsend) */
2644 DEFAULT_WRAPPER_W_1W(Info_c2f)
2645 DEFAULT_WRAPPER_W_1W(Info_create)
2646 DEFAULT_WRAPPER_W_2W(Info_delete)
2647 DEFAULT_WRAPPER_W_2W(Info_dup)
2648 DEFAULT_WRAPPER_W_1W(Info_f2c)
2649 DEFAULT_WRAPPER_W_1W(Info_free)
2650 DEFAULT_WRAPPER_W_5W(Info_get)
2651 DEFAULT_WRAPPER_W_2W(Info_get_nkeys)
2652 DEFAULT_WRAPPER_W_3W(Info_get_nthkey)
2653 DEFAULT_WRAPPER_W_4W(Info_get_valuelen)
2654 DEFAULT_WRAPPER_W_3W(Info_set)
2655 /* DEFAULT_WRAPPER_W_2W(Init) */
2656 /* DEFAULT_WRAPPER_W_1W(Initialized) */
2657 DEFAULT_WRAPPER_W_4W(Init_thread)
2658 DEFAULT_WRAPPER_W_6W(Intercomm_create)
2659 DEFAULT_WRAPPER_W_3W(Intercomm_merge)
2660 /* DEFAULT_WRAPPER_W_5W(Iprobe) */
2661 /* DEFAULT_WRAPPER_W_7W(Irecv) */
2662 /* DEFAULT_WRAPPER_W_7W(Irsend) */
2663 /* DEFAULT_WRAPPER_W_7W(Isend) */
2664 /* DEFAULT_WRAPPER_W_7W(Issend) */
2665 DEFAULT_WRAPPER_W_1W(Is_thread_main)
2666 DEFAULT_WRAPPER_W_4W(Keyval_create)
2667 DEFAULT_WRAPPER_W_1W(Keyval_free)
2668 DEFAULT_WRAPPER_W_3W(Lookup_name)
2669 DEFAULT_WRAPPER_W_1W(Op_c2f)
2670 /* DEFAULT_WRAPPER_W_3W(Op_create) */
2671 DEFAULT_WRAPPER_W_2W(Open_port)
2672 DEFAULT_WRAPPER_W_1W(Op_f2c)
2673 DEFAULT_WRAPPER_W_1W(Op_free)
2674 DEFAULT_WRAPPER_W_7W(Pack_external)
2675 DEFAULT_WRAPPER_W_4W(Pack_external_size)
2676 /* DEFAULT_WRAPPER_W_7W(Pack) */
2677 DEFAULT_WRAPPER_W_4W(Pack_size)
2678 /* int MPI_Pcontrol(const int level, ...) */
2679 /* DEFAULT_WRAPPER_W_4W(Probe) */
2680 DEFAULT_WRAPPER_W_3W(Publish_name)
2681 DEFAULT_WRAPPER_W_8W(Put)
2682 DEFAULT_WRAPPER_W_1W(Query_thread)
2683 DEFAULT_WRAPPER_W_7W(Recv_init)
2684 /* DEFAULT_WRAPPER_W_7W(Recv) */
2685 /* DEFAULT_WRAPPER_W_7W(Reduce) */
2686 DEFAULT_WRAPPER_W_6W(Reduce_scatter)
2687 DEFAULT_WRAPPER_W_5W(Register_datarep)
2688 DEFAULT_WRAPPER_W_1W(Request_c2f)
2689 DEFAULT_WRAPPER_W_1W(Request_f2c)
2690 DEFAULT_WRAPPER_W_1W(Request_free)
2691 DEFAULT_WRAPPER_W_3W(Request_get_status)
2692 /* DEFAULT_WRAPPER_W_6W(Rsend) */
2693 DEFAULT_WRAPPER_W_7W(Rsend_init)
2694 DEFAULT_WRAPPER_W_6W(Scan)
2695 /* DEFAULT_WRAPPER_W_8W(Scatter) */
2696 DEFAULT_WRAPPER_W_9W(Scatterv)
2697 DEFAULT_WRAPPER_W_7W(Send_init)
2698 /* DEFAULT_WRAPPER_W_6W(Send) */
2699 /* DEFAULT_WRAPPER_W_12W(Sendrecv) */
2700 DEFAULT_WRAPPER_W_9W(Sendrecv_replace)
2701 DEFAULT_WRAPPER_W_7W(Ssend_init)
2702 /* DEFAULT_WRAPPER_W_6W(Ssend) */
2703 DEFAULT_WRAPPER_W_1W(Start)
2704 DEFAULT_WRAPPER_W_2W(Startall)
2705 DEFAULT_WRAPPER_W_2W(Status_c2f)
2706 DEFAULT_WRAPPER_W_2W(Status_f2c)
2707 DEFAULT_WRAPPER_W_2W(Status_set_cancelled)
2708 DEFAULT_WRAPPER_W_3W(Status_set_elements)
2709 /* DEFAULT_WRAPPER_W_4W(Testall) */
2710 DEFAULT_WRAPPER_W_5W(Testany)
2711 /* DEFAULT_WRAPPER_W_3W(Test) */
2712 DEFAULT_WRAPPER_W_2W(Test_cancelled)
2713 DEFAULT_WRAPPER_W_5W(Testsome)
2714 DEFAULT_WRAPPER_W_2W(Topo_test)
2715 DEFAULT_WRAPPER_W_1W(Type_c2f)
2716 /* DEFAULT_WRAPPER_W_1W(Type_commit) */
2717 DEFAULT_WRAPPER_W_3W(Type_contiguous)
2718 DEFAULT_WRAPPER_W_10W(Type_create_darray)
2719 DEFAULT_WRAPPER_W_3W(Type_create_f90_complex)
2720 DEFAULT_WRAPPER_W_2W(Type_create_f90_integer)
2721 DEFAULT_WRAPPER_W_3W(Type_create_f90_real)
2722 DEFAULT_WRAPPER_W_5W(Type_create_hindexed)
2723 DEFAULT_WRAPPER_W_5W(Type_create_hvector)
2724 DEFAULT_WRAPPER_W_4W(Type_create_keyval)
2725 DEFAULT_WRAPPER_W_5W(Type_create_indexed_block)
2726 DEFAULT_WRAPPER_W_5W(Type_create_struct)
2727 DEFAULT_WRAPPER_W_7W(Type_create_subarray)
2728 DEFAULT_WRAPPER_W_4W(Type_create_resized)
2729 DEFAULT_WRAPPER_W_2W(Type_delete_attr)
2730 DEFAULT_WRAPPER_W_2W(Type_dup)
2731 /* DEFAULT_WRAPPER_W_2W(Type_extent) */
2732 /* DEFAULT_WRAPPER_W_1W(Type_free) */
2733 DEFAULT_WRAPPER_W_1W(Type_free_keyval)
2734 DEFAULT_WRAPPER_W_1W(Type_f2c)
2735 DEFAULT_WRAPPER_W_4W(Type_get_attr)
2736 /* DEFAULT_WRAPPER_W_7W(Type_get_contents) */
2737 /* DEFAULT_WRAPPER_W_5W(Type_get_envelope) */
2738 DEFAULT_WRAPPER_W_3W(Type_get_extent)
2739 DEFAULT_WRAPPER_W_3W(Type_get_name)
2740 DEFAULT_WRAPPER_W_3W(Type_get_true_extent)
2741 DEFAULT_WRAPPER_W_5W(Type_hindexed)
2742 DEFAULT_WRAPPER_W_5W(Type_hvector)
2743 DEFAULT_WRAPPER_W_5W(Type_indexed)
2744 DEFAULT_WRAPPER_W_2W(Type_lb)
2745 DEFAULT_WRAPPER_W_3W(Type_match_size)
2746 DEFAULT_WRAPPER_W_3W(Type_set_attr)
2747 DEFAULT_WRAPPER_W_2W(Type_set_name)
2748 DEFAULT_WRAPPER_W_2W(Type_size)
2749 DEFAULT_WRAPPER_W_5W(Type_struct)
2750 DEFAULT_WRAPPER_W_2W(Type_ub)
2751 DEFAULT_WRAPPER_W_5W(Type_vector)
2752 /* DEFAULT_WRAPPER_W_7W(Unpack) */
2753 DEFAULT_WRAPPER_W_3W(Unpublish_name)
2754 DEFAULT_WRAPPER_W_7W(Unpack_external)
2755 /* DEFAULT_WRAPPER_W_3W(Waitall) */
2756 /* DEFAULT_WRAPPER_W_4W(Waitany) */
2757 /* DEFAULT_WRAPPER_W_2W(Wait) */
2758 DEFAULT_WRAPPER_W_5W(Waitsome)
2759 DEFAULT_WRAPPER_W_1W(Win_c2f)
2760 DEFAULT_WRAPPER_W_2W(Win_call_errhandler)
2761 DEFAULT_WRAPPER_W_1W(Win_complete)
2762 DEFAULT_WRAPPER_W_6W(Win_create)
2763 DEFAULT_WRAPPER_W_2W(Win_create_errhandler)
2764 DEFAULT_WRAPPER_W_4W(Win_create_keyval)
2765 DEFAULT_WRAPPER_W_2W(Win_delete_attr)
2766 DEFAULT_WRAPPER_W_1W(Win_f2c)
2767 DEFAULT_WRAPPER_W_2W(Win_fence)
2768 DEFAULT_WRAPPER_W_1W(Win_free)
2769 DEFAULT_WRAPPER_W_1W(Win_free_keyval)
2770 DEFAULT_WRAPPER_W_4W(Win_get_attr)
2771 DEFAULT_WRAPPER_W_2W(Win_get_errhandler)
2772 DEFAULT_WRAPPER_W_2W(Win_get_group)
2773 DEFAULT_WRAPPER_W_3W(Win_get_name)
2774 DEFAULT_WRAPPER_W_4W(Win_lock)
2775 DEFAULT_WRAPPER_W_3W(Win_post)
2776 DEFAULT_WRAPPER_W_3W(Win_set_attr)
2777 DEFAULT_WRAPPER_W_2W(Win_set_errhandler)
2778 DEFAULT_WRAPPER_W_2W(Win_set_name)
2779 DEFAULT_WRAPPER_W_3W(Win_start)
2780 DEFAULT_WRAPPER_W_2W(Win_test)
2781 DEFAULT_WRAPPER_W_2W(Win_unlock)
2782 DEFAULT_WRAPPER_W_1W(Win_wait)
2783 /* double MPI_Wtick(void) */
2784 /* double MPI_Wtime(void) */
2787 /*------------------------------------------------------------*/
2788 /*--- ---*/
2789 /*--- ---*/
2790 /*--- ---*/
2791 /*------------------------------------------------------------*/
2793 /*---------------------------------------------------------------*/
2794 /*--- end mpiwrap.c ---*/
2795 /*---------------------------------------------------------------*/