Install dhat viewer files in libexec.
[valgrind.git] / mpi / libmpiwrap.c
blob488bb13fdf595748609e46daa2ad26100f7e3560
2 /*---------------------------------------------------------------*/
3 /*--- ---*/
4 /*--- A library of wrappers for MPI 2 functions. ---*/
5 /*--- ---*/
6 /*---------------------------------------------------------------*/
8 /* ----------------------------------------------------------------
10 Notice that the following BSD-style license applies to this one
11 file (mpiwrap.c) only. The rest of Valgrind is licensed under the
12 terms of the GNU General Public License, version 2, unless
13 otherwise indicated. See the COPYING file in the source
14 distribution for details.
16 ----------------------------------------------------------------
18 This file is part of Valgrind, a dynamic binary instrumentation
19 framework.
21 Copyright (C) 2006-2017 OpenWorks LLP. All rights reserved.
23 Redistribution and use in source and binary forms, with or without
24 modification, are permitted provided that the following conditions
25 are met:
27 1. Redistributions of source code must retain the above copyright
28 notice, this list of conditions and the following disclaimer.
30 2. The origin of this software must not be misrepresented; you must
31 not claim that you wrote the original software. If you use this
32 software in a product, an acknowledgment in the product
33 documentation would be appreciated but is not required.
35 3. Altered source versions must be plainly marked as such, and must
36 not be misrepresented as being the original software.
38 4. The name of the author may not be used to endorse or promote
39 products derived from this software without specific prior written
40 permission.
42 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
43 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
44 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
46 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
48 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
49 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
50 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
51 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
52 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 Neither the names of the U.S. Department of Energy nor the
55 University of California nor the names of its contributors may be
56 used to endorse or promote products derived from this software
57 without prior written permission.
60 /* Handling of MPI_STATUS{ES}_IGNORE for MPI_Status* arguments.
62 The MPI-2 spec allows many functions which have MPI_Status* purely
63 as an out parameter, to accept the constants MPI_STATUS_IGNORE or
64 MPI_STATUSES_IGNORE there instead, if the caller does not care
65 about the status. See the MPI-2 spec sec 4.5.1 ("Passing
66 MPI_STATUS_IGNORE for Status"). (mpi2-report.pdf, 1615898 bytes,
67 md5=694a5efe2fd291eecf7e8c9875b5f43f).
69 This library handles such cases by allocating a fake MPI_Status
70 object (on the stack) or an array thereof (on the heap), and
71 passing that onwards instead. From the outside the caller sees no
72 difference. Unfortunately the simpler approach of merely detecting
73 and handling these special cases at a lower level does not work,
74 because we need to use information returned in MPI_Status*
75 arguments to paint result buffers, even if the caller doesn't
76 supply a real MPI_Status object.
78 Eg, MPI_Recv. We can't paint the result buffer without knowing how
79 many items arrived; but we can't find that out without passing a
80 real MPI_Status object to the (real) MPI_Recv call. Hence, if the
81 caller did not supply one, we have no option but to use a temporary
82 stack allocated one for the inner call. Ditto, more indirectly
83 (via maybe_complete) for nonblocking receives and the various
84 associated wait/test calls. */
87 /*------------------------------------------------------------*/
88 /*--- includes ---*/
89 /*------------------------------------------------------------*/
91 #include <stdio.h>
92 #include <assert.h>
93 #include <unistd.h> /* getpid */
94 #include <stdlib.h> /* exit */
95 #include <string.h> /* strstr */
96 #include <pthread.h> /* pthread_mutex_{lock,unlock} */
98 /* Include Valgrind magic macros for writing wrappers. */
99 #include "../memcheck/memcheck.h"
101 /* Include macros for VALGRIND_{DIS,EN}ABLE_ERROR_REPORTING.
102 This is somewhat experimental and hence disable-able, by
103 setting cONFIG_DER to zero. */
104 #include "../include/valgrind.h"
106 #define cONFIG_DER 1 /* set to 0 to disable */
109 /*------------------------------------------------------------*/
110 /*--- Connect to MPI library ---*/
111 /*------------------------------------------------------------*/
113 /* Include headers for whatever MPI implementation the wrappers are to
114 be used with. The configure system will tell us what the path to
115 the chosen MPI implementation is, via -I.. to the compiler. */
116 #include "mpi.h"
118 /* Where are API symbols?
119 Open MPI lib/libmpi.so, soname = libmpi.so.0
120 Quadrics MPI lib/libmpi.so, soname = libmpi.so.0
121 MPICH libmpich.so.1.0, soname = libmpich.so.1.0
123 A suitable soname to match with is therefore "libmpi*.so*".
125 #define I_WRAP_FNNAME_U(_name) \
126 I_WRAP_SONAME_FNNAME_ZU(libmpiZaZdsoZa,_name)
129 /* Define HAVE_MPI_STATUS_IGNORE iff we have to deal with
130 MPI_STATUS{ES}_IGNORE. */
131 #if MPI_VERSION >= 2 \
132 || (defined(MPI_STATUS_IGNORE) && defined(MPI_STATUSES_IGNORE))
133 # undef HAVE_MPI_STATUS_IGNORE
134 # define HAVE_MPI_STATUS_IGNORE 1
135 #else
136 # undef HAVE_MPI_STATUS_IGNORE
137 #endif
140 /*------------------------------------------------------------*/
141 /*--- Decls ---*/
142 /*------------------------------------------------------------*/
144 typedef unsigned char Bool;
145 #define False ((Bool)0)
146 #define True ((Bool)1)
148 /* Word, UWord are machine words - same size as a pointer. This is
149 checked at startup. The wrappers below use 'long' to mean a
150 machine word - this too is tested at startup. */
151 typedef signed long Word;
152 typedef unsigned long UWord;
154 #if !defined(offsetof)
155 # define offsetof(type,memb) ((UWord)&((type*)0)->memb)
156 #endif
158 /* Find the size of long double image (not 'sizeof(long double)').
159 See comments in sizeofOneNamedTy. */
160 static long sizeof_long_double_image ( void );
163 /*------------------------------------------------------------*/
164 /*--- Simple helpers ---*/
165 /*------------------------------------------------------------*/
167 /* ------ Helpers for debug printing ------ */
169 /* constant */
170 static const char* preamble = "valgrind MPI wrappers";
172 /* established at startup */
173 static pid_t my_pid = -1;
174 static char* options_str = NULL;
175 static int opt_verbosity = 1;
176 static Bool opt_missing = 0; /* 0:silent; 1:warn; 2:abort */
177 static Bool opt_help = False;
178 static Bool opt_initkludge = False;
180 static void before ( char* fnname )
182 /* This isn't thread-safe wrt 'done' (no locking). It's not
183 critical. */
184 static int done = 0;
185 if (done == 0) {
186 done = 1;
187 my_pid = getpid();
188 options_str = getenv("MPIWRAP_DEBUG");
189 if (options_str) {
190 if (NULL != strstr(options_str, "warn"))
191 opt_missing = 1;
192 if (NULL != strstr(options_str, "strict"))
193 opt_missing = 2;
194 if (NULL != strstr(options_str, "verbose"))
195 opt_verbosity++;
196 if (NULL != strstr(options_str, "quiet"))
197 opt_verbosity--;
198 if (NULL != strstr(options_str, "help"))
199 opt_help = True;
200 if (NULL != strstr(options_str, "initkludge"))
201 opt_initkludge = True;
203 if (opt_verbosity > 0)
204 fprintf(stderr, "%s %5d: Active for pid %d\n",
205 preamble, my_pid, my_pid);
206 /* Sanity check - that Word/UWord really are machine words. */
207 assert(sizeof(Word) == sizeof(void*));
208 assert(sizeof(UWord) == sizeof(void*));
209 /* Sanity check - char is byte-sized (else address calculations
210 in walk_type don't work. */
211 assert(sizeof(char) == 1);
212 if (opt_help) {
213 fprintf(stderr, "\n");
214 fprintf(stderr, "Valid options for the MPIWRAP_DEBUG environment"
215 " variable are:\n");
216 fprintf(stderr, "\n");
217 fprintf(stderr, " quiet be silent except for errors\n");
218 fprintf(stderr, " verbose show wrapper entries/exits\n");
219 fprintf(stderr, " strict abort the program if a function"
220 " with no wrapper is used\n");
221 fprintf(stderr, " warn give a warning if a function"
222 " with no wrapper is used\n");
223 fprintf(stderr, " help display this message, then exit\n");
224 fprintf(stderr, " initkludge debugging hack; do not use\n");
225 fprintf(stderr, "\n");
226 fprintf(stderr, "Multiple options are allowed, eg"
227 " MPIWRAP_DEBUG=strict,verbose\n");
228 fprintf(stderr, "Note: 'warn' generates output even if 'quiet'"
229 " is also specified\n");
230 fprintf(stderr, "\n");
231 fprintf(stderr, "%s %5d: exiting now\n", preamble, my_pid );
232 exit(1);
234 if (opt_verbosity > 0)
235 fprintf(stderr,
236 "%s %5d: Try MPIWRAP_DEBUG=help for possible options\n",
237 preamble, my_pid);
240 if (opt_verbosity > 1)
241 fprintf(stderr, "%s %5d: enter PMPI_%s\n", preamble, my_pid, fnname );
244 static __inline__ void after ( char* fnname, int err )
246 if (opt_verbosity > 1)
247 fprintf(stderr, "%s %5d: exit PMPI_%s (err = %d)\n",
248 preamble, my_pid, fnname, err );
251 static void barf ( char* msg )
253 fprintf(stderr, "%s %5d: fatal: %s\n", preamble, my_pid, msg);
254 fprintf(stderr, "%s %5d: exiting now\n", preamble, my_pid );
255 exit(1);
258 /* Half-hearted type-showing function (for debugging). */
259 static void showTy ( FILE* f, MPI_Datatype ty )
261 if (ty == MPI_DATATYPE_NULL) fprintf(f,"DATATYPE_NULL");
262 else if (ty == MPI_BYTE) fprintf(f,"BYTE");
263 else if (ty == MPI_PACKED) fprintf(f,"PACKED");
264 else if (ty == MPI_CHAR) fprintf(f,"CHAR");
265 else if (ty == MPI_SHORT) fprintf(f,"SHORT");
266 else if (ty == MPI_INT) fprintf(f,"INT");
267 else if (ty == MPI_LONG) fprintf(f,"LONG");
268 else if (ty == MPI_FLOAT) fprintf(f,"FLOAT");
269 else if (ty == MPI_DOUBLE) fprintf(f,"DOUBLE");
270 else if (ty == MPI_LONG_DOUBLE) fprintf(f,"LONG_DOUBLE");
271 else if (ty == MPI_UNSIGNED_CHAR) fprintf(f,"UNSIGNED_CHAR");
272 else if (ty == MPI_UNSIGNED_SHORT) fprintf(f,"UNSIGNED_SHORT");
273 else if (ty == MPI_UNSIGNED_LONG) fprintf(f,"UNSIGNED_LONG");
274 else if (ty == MPI_UNSIGNED) fprintf(f,"UNSIGNED");
275 else if (ty == MPI_FLOAT_INT) fprintf(f,"FLOAT_INT");
276 else if (ty == MPI_DOUBLE_INT) fprintf(f,"DOUBLE_INT");
277 else if (ty == MPI_LONG_DOUBLE_INT) fprintf(f,"LONG_DOUBLE_INT");
278 else if (ty == MPI_LONG_INT) fprintf(f,"LONG_INT");
279 else if (ty == MPI_SHORT_INT) fprintf(f,"SHORT_INT");
280 else if (ty == MPI_2INT) fprintf(f,"2INT");
281 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 VALGRIND_MAKE_MEM_DEFINED(&n, sizeof(n));
421 *recv_count = n;
422 return True;
423 } else {
424 return False;
428 /* It's critical that we can do equality on MPI_Requests.
429 Unfortunately these are opaque objects to us (handles, in the
430 parlance of the MPI 1.1 spec). Fortunately Sec 2.4.1 ("Opaque
431 Objects") specifies that "In C, [...] These [handles] should be
432 types that support assignment and equality operations." Hence the
433 following function should compile for any compliant definition of
434 MPI_Request. */
435 static __inline__
436 Bool eq_MPI_Request ( MPI_Request r1, MPI_Request r2 )
438 return r1 == r2;
441 /* Return True if status is MPI_STATUS_IGNORE or MPI_STATUSES_IGNORE.
442 On MPI-1.x platforms which don't have these symbols (and they would
443 only have them if they've been backported from 2.x) always return
444 False. */
445 static __inline__
446 Bool isMSI ( MPI_Status* status )
448 # if defined(HAVE_MPI_STATUS_IGNORE)
449 return status == MPI_STATUSES_IGNORE || status == MPI_STATUS_IGNORE;
450 # else
451 return False;
452 # endif
455 /* Get the 'extent' of a type. Note, as per the MPI spec this
456 includes whatever padding would be required when using 'ty' in an
457 array. */
458 static long extentOfTy ( MPI_Datatype ty )
460 int r;
461 MPI_Aint n;
462 r = PMPI_Type_extent(ty, &n);
463 assert(r == MPI_SUCCESS);
464 return (long)n;
467 /* Free up *ty, if it is safe to do so */
468 static void maybeFreeTy ( MPI_Datatype* ty )
470 int r, n_ints, n_addrs, n_dtys, tycon;
472 r = PMPI_Type_get_envelope( *ty, &n_ints, &n_addrs, &n_dtys, &tycon );
473 assert(r == MPI_SUCCESS);
475 /* can't free named types */
476 if (tycon == MPI_COMBINER_NAMED)
477 return;
479 /* some kinds of structs are predefined so we can't free them
480 either. */
481 if (*ty == MPI_FLOAT_INT || *ty == MPI_DOUBLE_INT
482 || *ty == MPI_LONG_INT || *ty == MPI_2INT
483 || *ty == MPI_SHORT_INT || *ty == MPI_LONG_DOUBLE_INT)
484 return;
486 /* Looks OK - free it. */
487 if (0) {
488 /* show me what you're about to free .. */
489 fprintf(stderr, "freeing combiner ");
490 showCombiner(stderr,tycon);
491 fprintf(stderr, " ty= ");
492 showTy(stderr,*ty);
493 fprintf(stderr,"\n");
495 r = PMPI_Type_free(ty);
496 assert(r == MPI_SUCCESS);
499 /* How big is a "named" (base) type? Returns 0 if not known. Note.
500 There is a subtlety, which is that this is required to return the
501 exact size of one item of the type, NOT the size of it when padded
502 suitably to make an array of them. In particular that's why the
503 size of LONG_DOUBLE is computed by looking at the result of doing a
504 long double store, rather than just asking what is the sizeof(long
505 double).
507 For LONG_DOUBLE on x86-linux and amd64-linux my impression is that
508 the right answer is 10 even though sizeof(long double) says 12 and
509 16 respectively. On ppc32-linux it appears to be 16.
511 Ref: MPI 1.1 doc p18 */
512 static long sizeofOneNamedTy ( MPI_Datatype ty )
514 if (ty == MPI_CHAR) return sizeof(signed char);
515 if (ty == MPI_SHORT) return sizeof(signed short int);
516 if (ty == MPI_INT) return sizeof(signed int);
517 if (ty == MPI_LONG) return sizeof(signed long int);
518 if (ty == MPI_UNSIGNED_CHAR) return sizeof(unsigned char);
519 if (ty == MPI_UNSIGNED_SHORT) return sizeof(unsigned short int);
520 if (ty == MPI_UNSIGNED) return sizeof(unsigned int);
521 if (ty == MPI_UNSIGNED_LONG) return sizeof(unsigned long int);
522 if (ty == MPI_FLOAT) return sizeof(float);
523 if (ty == MPI_DOUBLE) return sizeof(double);
524 if (ty == MPI_BYTE) return 1;
525 if (ty == MPI_LONG_DOUBLE) return sizeof_long_double_image();
526 if (ty == MPI_PACKED) return 1;
527 if (ty == MPI_LONG_LONG_INT) return sizeof(signed long long int);
529 # if defined(MPI_REAL8)
530 if (ty == MPI_REAL8) return 8; /* MPI2 spec */;
531 # endif
532 # if defined(MPI_REAL4)
533 if (ty == MPI_REAL4) return 4; /* MPI2 spec */;
534 # endif
535 # if defined(MPI_REAL)
536 if (ty == MPI_REAL) return 4; /* MPI2 spec */;
537 # endif
538 # if defined(MPI_INTEGER8)
539 if (ty == MPI_INTEGER8) return 8; /* MPI2 spec */;
540 # endif
541 # if defined(MPI_INTEGER4)
542 if (ty == MPI_INTEGER4) return 4; /* MPI2 spec */;
543 # endif
544 # if defined(MPI_INTEGER)
545 if (ty == MPI_INTEGER) return 4; /* MPI2 spec */;
546 # endif
547 # if defined(MPI_DOUBLE_PRECISION)
548 if (ty == MPI_DOUBLE_PRECISION) return 8; /* MPI2 spec */;
549 # endif
551 /* new in MPI2: */
552 # if defined(MPI_WCHAR)
553 if (ty == MPI_WCHAR) return 2; /* MPI2 spec */;
554 # endif
555 # if defined(MPI_SIGNED_CHAR)
556 if (ty == MPI_SIGNED_CHAR) return 1; /* MPI2 spec */;
557 # endif
558 # if defined(MPI_UNSIGNED_LONG_LONG)
559 if (ty == MPI_UNSIGNED_LONG_LONG) return 8; /* MPI2 spec */;
560 # endif
561 # if defined(MPI_COMPLEX)
562 if (ty == MPI_COMPLEX) return 2 * 4; /* MPI2 spec */
563 # endif
564 # if defined(MPI_DOUBLE_COMPLEX)
565 if (ty == MPI_DOUBLE_COMPLEX) return 2 * 8; /* MPI2 spec */
566 # endif
567 # if defined(MPI_LOGICAL)
568 if (ty == MPI_LOGICAL) return 4; /* MPI2 spec */
569 # endif
570 # if defined(MPI_2INTEGER)
571 if (ty == MPI_2INTEGER) return 2 * 4; /* undocumented in MPI2 */
572 # endif
573 # if defined(MPI_2COMPLEX)
574 if (ty == MPI_2COMPLEX) return 2 * 8; /* undocumented in MPI2 */
575 # endif
576 # if defined(MPI_2DOUBLE_COMPLEX)
577 /* 32: this is how openmpi-1.2.2 behaves on x86-linux, but I have
578 really no idea if this is right. */
579 if (ty == MPI_2DOUBLE_COMPLEX) return 32; /* undocumented in MPI2 */
580 # endif
581 # if defined(MPI_2REAL)
582 if (ty == MPI_2REAL) return 2 * 4; /* undocumented in MPI2 */
583 # endif
584 # if defined(MPI_2DOUBLE_PRECISION)
585 if (ty == MPI_2DOUBLE_PRECISION) return 2 * 8; /* undocumented in MPI2 */
586 # endif
587 # if defined(MPI_CHARACTER)
588 if (ty == MPI_CHARACTER) return 1; /* MPI2 spec */
589 # endif
591 /* Note: the following are named structs, not named basic types,
592 and so are not handled here:
593 FLOAT_INT DOUBLE_INT LONG_INT 2INT SHORT_INT LONG_DOUBLE_INT
594 My guess is they are probably for doing max-w-index style
595 reductions, the INT carrying the index of the max/min and the
596 other type its actual value.
598 return 0;
602 /* Find the size of long double image (not 'sizeof(long double)').
603 See comments in sizeofOneNamedTy.
605 static long sizeof_long_double_image ( void )
607 long i;
608 unsigned char* p;
609 static long cached_result = 0;
611 /* Hopefully we have it already. */
612 if (cached_result != 0) {
613 assert(cached_result == 10 || cached_result == 16 || cached_result == 8);
614 return cached_result;
617 /* No? Then we'll have to compute it. This isn't thread-safe but
618 it doesn't really matter since all races to compute it should
619 produce the same answer. */
620 p = malloc(64);
621 assert(p);
622 for (i = 0; i < 64; i++)
623 p[i] = 0x55;
625 /* Write a value which isn't known at compile time and therefore
626 must come out of a register. If we just store a constant here,
627 some compilers write more data than a store from a machine
628 register would. Therefore we have to force a store from a
629 machine register by storing a value which isn't known at compile
630 time. Since getpid() will return a value < 1 million, turn it
631 into a zero by dividing by 1e+30. */
632 *(long double*)(&p[16]) = (long double)(1.0e-30 * (double)getpid());
634 for (i = 0; i < 16; i++) {
635 assert(p[i] == 0x55);
636 assert(p[i+48] == 0x55);
638 for (i = 16; i <= 48; i++) {
639 if (p[i] == 0x55)
640 break;
643 assert(i < 48);
644 assert(i > 16);
645 free(p);
646 cached_result = i - 16;
648 if (0)
649 printf("sizeof_long_double_image: computed %d\n", (int)cached_result);
651 assert(cached_result == 10 || cached_result == 16 || cached_result == 8);
652 return cached_result;
656 /*------------------------------------------------------------*/
657 /*--- Unpicking datatypes ---*/
658 /*------------------------------------------------------------*/
660 static __inline__
661 void walk_type_array ( void(*f)(void*,long), char* base,
662 MPI_Datatype ty, long count );
665 /* Walk over all fragments of the object of type 'ty' with base
666 address 'base', and apply 'f' to the start/length of each
667 contiguous fragment. */
668 static
669 void walk_type ( void(*f)(void*,long), char* base, MPI_Datatype ty )
671 int r, n_ints, n_addrs, n_dtys, tycon;
672 long ex, i;
673 int* ints = NULL;
674 MPI_Aint* addrs = NULL;
675 MPI_Datatype* dtys = NULL;
677 /* Stuff for limiting how much complaining text it spews out */
678 static int complaints = 3;
679 static int last_complained_about_tycon = -987654321; /* presumably bogus */
681 if (0)
682 printf("walk_type %p\n", (void*)(unsigned long)ty);
684 r = PMPI_Type_get_envelope( ty, &n_ints, &n_addrs, &n_dtys, &tycon );
685 assert(r == MPI_SUCCESS);
687 /* Handle the base cases fast(er/ish). */
688 if (tycon == MPI_COMBINER_NAMED) {
689 long sz = sizeofOneNamedTy(ty);
690 if (sz > 0) {
691 f(base, sz);
692 return;
694 /* Hmm. Perhaps it's a named struct? Unfortunately we can't
695 take them to bits so we have to do a really ugly hack, which
696 makes assumptions about how the MPI implementation has laid
697 out these types. At least Open MPI 1.0.1 appears to put
698 the 'val' field first. MPICH2 agrees.
700 if (ty == MPI_2INT) {
701 typedef struct { int val; int loc; } Ty;
702 f(base + offsetof(Ty,val), sizeof(int));
703 f(base + offsetof(Ty,loc), sizeof(int));
704 return;
706 if (ty == MPI_LONG_INT) {
707 typedef struct { long val; int loc; } Ty;
708 f(base + offsetof(Ty,val), sizeof(long));
709 f(base + offsetof(Ty,loc), sizeof(int));
710 return;
712 if (ty == MPI_DOUBLE_INT) {
713 typedef struct { double val; int loc; } Ty;
714 f(base + offsetof(Ty,val), sizeof(double));
715 f(base + offsetof(Ty,loc), sizeof(int));
716 return;
718 if (ty == MPI_SHORT_INT) {
719 typedef struct { short val; int loc; } Ty;
720 f(base + offsetof(Ty,val), sizeof(short));
721 f(base + offsetof(Ty,loc), sizeof(int));
722 return;
724 if (ty == MPI_FLOAT_INT) {
725 typedef struct { float val; int loc; } Ty;
726 f(base + offsetof(Ty,val), sizeof(float));
727 f(base + offsetof(Ty,loc), sizeof(int));
728 return;
730 if (ty == MPI_LONG_DOUBLE_INT) {
731 typedef struct { long double val; int loc; } Ty;
732 f(base + offsetof(Ty,val), sizeof_long_double_image());
733 f(base + offsetof(Ty,loc), sizeof(int));
734 return;
736 if (ty == MPI_LB || ty == MPI_UB)
737 return; /* have zero size, so nothing needs to be done */
738 goto unhandled;
739 /*NOTREACHED*/
742 if (0) {
743 ex = extentOfTy(ty);
744 printf("tycon 0x%llx %d %d %d (ext %d)\n",
745 (unsigned long long int)tycon,
746 n_ints, n_addrs, n_dtys, (int)ex );
749 /* Now safe to do MPI_Type_get_contents */
750 assert(n_ints >= 0);
751 assert(n_addrs >= 0);
752 assert(n_dtys >= 0);
754 if (n_ints > 0) {
755 ints = malloc(n_ints * sizeof(int));
756 assert(ints);
758 if (n_addrs > 0) {
759 addrs = malloc(n_addrs * sizeof(MPI_Aint));
760 assert(addrs);
762 if (n_dtys > 0) {
763 dtys = malloc(n_dtys * sizeof(MPI_Datatype));
764 assert(dtys);
767 r = PMPI_Type_get_contents( ty, n_ints, n_addrs, n_dtys,
768 ints, addrs, dtys );
769 assert(r == MPI_SUCCESS);
771 switch (tycon) {
773 case MPI_COMBINER_CONTIGUOUS:
774 assert(n_ints == 1 && n_addrs == 0 && n_dtys == 1);
775 walk_type_array( f, base, dtys[0], ints[0] );
776 maybeFreeTy( &dtys[0] );
777 break;
779 case MPI_COMBINER_VECTOR:
780 assert(n_ints == 3 && n_addrs == 0 && n_dtys == 1);
781 ex = extentOfTy(dtys[0]);
782 if (0)
783 printf("vector count %d x (bl %d stride %d)\n",
784 (int)ints[0], (int)ints[1], (int)ints[2]);
785 for (i = 0; i < ints[0]; i++) {
786 walk_type_array( f, base + i * ints[2]/*stride*/ * ex,
787 dtys[0], ints[1]/*blocklength*/ );
789 maybeFreeTy( &dtys[0] );
790 break;
792 case MPI_COMBINER_HVECTOR:
793 assert(n_ints == 2 && n_addrs == 1 && n_dtys == 1);
794 ex = extentOfTy(dtys[0]);
795 if (0)
796 printf("hvector count %d x (bl %d hstride %d)\n",
797 (int)ints[0], (int)ints[1], (int)addrs[0]);
798 for (i = 0; i < ints[0]; i++) {
799 walk_type_array( f, base + i * addrs[0]/*hstride*/,
800 dtys[0], ints[1]/*blocklength*/ );
802 maybeFreeTy( &dtys[0] );
803 break;
805 case MPI_COMBINER_INDEXED:
806 assert(n_addrs == 0 && n_dtys == 1);
807 assert(n_ints > 0);
808 assert(n_ints == 2 * ints[0] + 1);
809 ex = extentOfTy(dtys[0]);
810 for (i = 0; i < ints[0]; i++) {
811 if (0)
812 printf("indexed (elem %d) off %d copies %d\n",
813 (int)i, ints[i+1+ints[0]], ints[i+1] );
814 walk_type_array( f, base + ex * ints[i+1+ints[0]],
815 dtys[0], ints[i+1] );
817 maybeFreeTy( &dtys[0] );
818 break;
820 case MPI_COMBINER_HINDEXED:
821 assert(n_ints > 0);
822 assert(n_ints == ints[0] + 1);
823 assert(n_addrs == ints[0] && n_dtys == 1);
824 ex = extentOfTy(dtys[0]);
825 for (i = 0; i < ints[0]; i++) {
826 if (0)
827 printf("hindexed (elem %d) hoff %d copies %d\n",
828 (int)i, (int)addrs[i], ints[i+1] );
829 walk_type_array( f, base + addrs[i],
830 dtys[0], ints[i+1] );
832 maybeFreeTy( &dtys[0] );
833 break;
835 case MPI_COMBINER_STRUCT:
836 assert(n_addrs == n_ints-1);
837 assert(n_dtys == n_ints-1);
838 assert(n_ints > 0);
839 assert(n_ints == ints[0] + 1);
840 for (i = 0; i < ints[0]; i++) {
841 if (0)
842 printf("struct (elem %d limit %d) hoff %d copies %d\n",
843 (int)i, (int)ints[0], (int)addrs[i], (int)ints[i+1]);
844 walk_type_array( f, base + addrs[i], dtys[i], (long)ints[i+1] );
845 maybeFreeTy( &dtys[i] );
847 break;
849 default:
850 goto unhandled;
854 /* normal exit */
855 if (ints) free(ints);
856 if (addrs) free(addrs);
857 if (dtys) free(dtys);
858 return;
860 unhandled:
861 /* Complain, but limit the amount of complaining that can happen to
862 the first 3 different unhandled tycons that show up, so as to
863 avoid swamping users with thousands of duplicate messages. */
864 if (complaints > 0 && tycon != last_complained_about_tycon) {
865 complaints--;
866 last_complained_about_tycon = tycon;
867 if (tycon == MPI_COMBINER_NAMED) {
868 fprintf(stderr, "%s %5d: walk_type: unhandled base type 0x%lx ",
869 preamble, my_pid, (long)ty);
870 showTy(stderr, ty);
871 fprintf(stderr, "\n");
872 } else {
873 fprintf(stderr, "%s %5d: walk_type: unhandled combiner 0x%lx\n",
874 preamble, my_pid, (long)tycon);
877 if (ints) free(ints);
878 if (addrs) free(addrs);
879 if (dtys) free(dtys);
880 if (opt_missing >= 2)
881 barf("walk_type: unhandled combiner, strict checking selected");
885 /* Same as walk_type but apply 'f' to every element in an array of
886 'count' items starting at 'base'. The only purpose of pushing this
887 into a different routine is so it can attempt to optimise the case
888 where the array elements are contiguous and packed together without
889 holes. */
890 static __inline__
891 void walk_type_array ( void(*f)(void*,long), char* base,
892 MPI_Datatype elemTy, long count )
894 long i, ex;
896 assert(sizeof(unsigned long) == sizeof(char*));
898 /* First see if we can do this the fast way. */
899 ex = sizeofOneNamedTy(elemTy);
901 if ( /* ty is a primitive type with power-of-2 size */
902 (ex == 8 || ex == 4 || ex == 2 || ex == 1)
903 && /* base is suitably aligned for ty */
904 ( ((unsigned long)base) & (ex-1)) == 0) {
906 /* We're sure it's contiguous, so just paint/check it in one
907 go. */
908 if (0) printf("walk_type_array fast %ld of size %ld\n", count, ex );
909 f ( base, count * ex );
911 } else {
913 /* Bad news. We have to futz with each element individually.
914 This could be very expensive.
916 Note: subtle. If ty is LONG_DOUBLE then the extent will be
917 12, so the following loop will jump along in steps of 12, but
918 the size painted by walk_type will be 10 since it uses
919 sizeofOneNamedTy to establish the size of base types. Which
920 is what we need to happen. */
921 ex = extentOfTy(elemTy);
922 if (0) printf("walk_type_array SLOW %ld of size %ld\n", count, ex );
923 for (i = 0; i < count; i++)
924 walk_type( f, base + i * ex, elemTy );
930 /* Hook so it's visible from outside (can be handy to dlopen/dlsym
931 it) */
932 void mpiwrap_walk_type_EXTERNALLY_VISIBLE
933 ( void(*f)(void*,long), char* base, MPI_Datatype ty )
935 walk_type(f, base, ty);
939 /*------------------------------------------------------------*/
940 /*--- Address-range helpers ---*/
941 /*------------------------------------------------------------*/
943 /* ----------------
944 Do corresponding checks on memory areas defined using a
945 straightforward (start, length) description.
946 ----------------
949 static __inline__
950 void check_mem_is_defined_untyped ( void* buffer, long nbytes )
952 if (nbytes > 0) {
953 VALGRIND_CHECK_MEM_IS_DEFINED(buffer, nbytes);
957 static __inline__
958 void check_mem_is_addressable_untyped ( void* buffer, long nbytes )
960 if (nbytes > 0) {
961 VALGRIND_CHECK_MEM_IS_ADDRESSABLE(buffer, nbytes);
965 static __inline__
966 void make_mem_defined_if_addressable_untyped ( void* buffer, long nbytes )
968 if (nbytes > 0) {
969 VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(buffer, nbytes);
973 static __inline__
974 void make_mem_defined_if_addressable_if_success_untyped ( int err,
975 void* buffer, long nbytes )
977 if (err == MPI_SUCCESS && nbytes > 0) {
978 VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(buffer, nbytes);
983 /* ----------------
984 Do checks on memory areas defined using the MPI (buffer, count,
985 type) convention.
986 ----------------
989 /* Check that the specified area is both addressible and contains
990 initialised data, and cause V to complain if not. */
992 static __inline__
993 void check_mem_is_defined ( char* buffer, long count, MPI_Datatype datatype )
995 walk_type_array( check_mem_is_defined_untyped, buffer, datatype, count );
999 /* Check that the specified area is addressible, and cause V to
1000 complain if not. Doesn't matter whether the data there is
1001 initialised or not. */
1003 static __inline__
1004 void check_mem_is_addressable ( void *buffer, long count, MPI_Datatype datatype )
1006 walk_type_array( check_mem_is_addressable_untyped, buffer, datatype, count );
1010 /* Set the specified area to 'defined for each byte which is
1011 addressible' state. */
1013 static __inline__
1014 void make_mem_defined_if_addressable ( void *buffer, int count, MPI_Datatype datatype )
1016 walk_type_array( make_mem_defined_if_addressable_untyped,
1017 buffer, datatype, count );
1020 static __inline__
1021 void
1022 make_mem_defined_if_addressable_if_success ( int err, void *buffer, int count,
1023 MPI_Datatype datatype )
1025 if (err == MPI_SUCCESS)
1026 make_mem_defined_if_addressable(buffer, count, datatype);
1030 /*------------------------------------------------------------*/
1031 /*--- ---*/
1032 /*--- The wrappers proper. They are listed in the order ---*/
1033 /*--- in which they appear in "MPI: A Message-Passing ---*/
1034 /*--- Interface Standard, MPIF, Nov 15 2003" (the MPI 1.1 ---*/
1035 /*--- spec. All unimplemented wrappers are listed at the ---*/
1036 /*--- end of the file. The list of function names is ---*/
1037 /*--- taken from the headers of Open MPI svn r9191. ---*/
1038 /*--- Hopefully it is a complete list of all the MPI 2 ---*/
1039 /*--- functions. ---*/
1040 /*--- ---*/
1041 /*------------------------------------------------------------*/
1043 /* Handy abbreviation */
1044 #define WRAPPER_FOR(name) I_WRAP_FNNAME_U(name)
1046 /* Generates (conceptually) a wrapper which does nothing. In
1047 fact just generate no wrapper at all. */
1048 #define HAS_NO_WRAPPER(basename) /* */
1051 /*------------------------------------------------------------*/
1052 /*--- ---*/
1053 /*--- Sec 3.2, Blocking Send and Receive Operations ---*/
1054 /*--- ---*/
1055 /*------------------------------------------------------------*/
1057 /* --- {,B,S,R}Send --- */
1058 /* pre: rd: (buf,count,datatype) */
1059 static
1060 int generic_Send(void *buf, int count, MPI_Datatype datatype,
1061 int dest, int tag, MPI_Comm comm)
1063 OrigFn fn;
1064 int err;
1065 VALGRIND_GET_ORIG_FN(fn);
1066 before("{,B,S,R}Send");
1067 check_mem_is_defined(buf, count, datatype);
1068 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1069 CALL_FN_W_6W(err, fn, buf,count,datatype,dest,tag,comm);
1070 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1071 after("{,B,S,R}Send", err);
1072 return err;
1074 int WRAPPER_FOR(PMPI_Send)(void *buf, int count, MPI_Datatype datatype,
1075 int dest, int tag, MPI_Comm comm) {
1076 return generic_Send(buf,count,datatype, dest,tag,comm);
1078 int WRAPPER_FOR(PMPI_Bsend)(void *buf, int count, MPI_Datatype datatype,
1079 int dest, int tag, MPI_Comm comm) {
1080 return generic_Send(buf,count,datatype, dest,tag,comm);
1082 int WRAPPER_FOR(PMPI_Ssend)(void *buf, int count, MPI_Datatype datatype,
1083 int dest, int tag, MPI_Comm comm) {
1084 return generic_Send(buf,count,datatype, dest,tag,comm);
1086 int WRAPPER_FOR(PMPI_Rsend)(void *buf, int count, MPI_Datatype datatype,
1087 int dest, int tag, MPI_Comm comm) {
1088 return generic_Send(buf,count,datatype, dest,tag,comm);
1091 /* --- Recv --- */
1092 /* pre: must be writable: (buf,count,datatype)
1093 must be writable: status
1094 post: make readable: (buf,recv_count,datatype)
1095 where recv_count is determined from *status
1097 int WRAPPER_FOR(PMPI_Recv)(void *buf, int count, MPI_Datatype datatype,
1098 int source, int tag,
1099 MPI_Comm comm, MPI_Status *status)
1101 OrigFn fn;
1102 int err, recv_count = 0;
1103 MPI_Status fake_status;
1104 VALGRIND_GET_ORIG_FN(fn);
1105 before("Recv");
1106 if (isMSI(status))
1107 status = &fake_status;
1108 check_mem_is_addressable(buf, count, datatype);
1109 check_mem_is_addressable_untyped(status, sizeof(*status));
1110 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1111 CALL_FN_W_7W(err, fn, buf,count,datatype,source,tag,comm,status);
1112 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1113 make_mem_defined_if_addressable_if_success_untyped(err, status, sizeof(*status));
1114 if (err == MPI_SUCCESS && count_from_Status(&recv_count,datatype,status)) {
1115 make_mem_defined_if_addressable(buf, recv_count, datatype);
1117 after("Recv", err);
1118 return err;
1121 /* --- Get_count --- */
1122 /* pre: must be readable: *status
1123 post: make defined: *count -- don't bother, libmpi will surely do this
1125 int WRAPPER_FOR(PMPI_Get_count)(MPI_Status* status,
1126 MPI_Datatype ty, int* count )
1128 OrigFn fn;
1129 int err;
1130 VALGRIND_GET_ORIG_FN(fn);
1131 before("Get_count");
1132 check_mem_is_defined_untyped(status, sizeof(*status));
1133 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1134 CALL_FN_W_WWW(err, fn, status,ty,count);
1135 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1136 after("Get_count", err);
1137 return err;
1141 /*------------------------------------------------------------*/
1142 /*--- ---*/
1143 /*--- Sec 3.7, Nonblocking communication ---*/
1144 /*--- ---*/
1145 /*------------------------------------------------------------*/
1147 /* Maintain a table that makes it possible for the wrappers to
1148 complete MPI_Irecv successfully.
1150 The issue is that MPI_Irecv states the recv buffer and returns
1151 immediately, giving a handle (MPI_Request) for the transaction.
1152 Later the user will have to poll for completion with MPI_Wait etc,
1153 and at that point these wrappers have to paint the recv buffer.
1154 But the recv buffer details are not presented to MPI_Wait - only
1155 the handle is. We therefore have to use a shadow table
1156 (sReqs{,_size,_used,_lock}) which associates uncompleted
1157 MPI_Requests with the corresponding buffer address/count/type.
1159 Only read requests are placed in the table, since there is no need
1160 to do any buffer painting following completion of an Isend - all
1161 the checks for that are done at the time Isend is called.
1163 Care has to be take to remove completed requests from the table.
1165 Access to the table is guarded by sReqs_lock so as to make it
1166 thread-safe.
1169 typedef
1170 struct {
1171 Bool inUse;
1172 MPI_Request key;
1173 void* buf;
1174 int count;
1175 MPI_Datatype datatype;
1177 ShadowRequest;
1179 static ShadowRequest* sReqs = NULL;
1180 static int sReqs_size = 0;
1181 static int sReqs_used = 0;
1182 static pthread_mutex_t sReqs_lock = PTHREAD_MUTEX_INITIALIZER;
1184 #define LOCK_SREQS \
1185 do { int pr = pthread_mutex_lock(&sReqs_lock); \
1186 assert(pr == 0); \
1187 } while (0)
1189 #define UNLOCK_SREQS \
1190 do { int pr = pthread_mutex_unlock(&sReqs_lock); \
1191 assert(pr == 0); \
1192 } while (0)
1195 /* Ensure the sReqs expandable array has at least one free slot, by
1196 copying it into a larger one if necessary. NOTE: sReqs_lock is
1197 held throughout this procedure.*/
1198 static void ensure_sReq_space ( void )
1200 int i;
1201 ShadowRequest* sReqs2;
1202 if (sReqs_used == sReqs_size) {
1203 sReqs_size = sReqs_size==0 ? 2 : 2*sReqs_size;
1204 sReqs2 = malloc( sReqs_size * sizeof(ShadowRequest) );
1205 if (sReqs2 == NULL) {
1206 UNLOCK_SREQS;
1207 barf("add_shadow_Request: malloc failed.\n");
1209 for (i = 0; i < sReqs_used; i++)
1210 sReqs2[i] = sReqs[i];
1211 if (sReqs)
1212 free(sReqs);
1213 sReqs = sReqs2;
1215 assert(sReqs_used < sReqs_size);
1219 /* Find shadow info for 'request', or NULL if none. */
1221 static
1222 ShadowRequest* find_shadow_Request ( MPI_Request request )
1224 ShadowRequest* ret = NULL;
1225 int i;
1226 LOCK_SREQS;
1227 for (i = 0; i < sReqs_used; i++) {
1228 if (sReqs[i].inUse && eq_MPI_Request(sReqs[i].key,request)) {
1229 ret = &sReqs[i];
1230 break;
1233 UNLOCK_SREQS;
1234 return ret;
1238 /* Delete shadow info for 'request', if any. */
1240 static void delete_shadow_Request ( MPI_Request request )
1242 int i;
1243 LOCK_SREQS;
1244 for (i = 0; i < sReqs_used; i++) {
1245 if (sReqs[i].inUse && eq_MPI_Request(sReqs[i].key,request)) {
1246 sReqs[i].inUse = False;
1247 break;
1250 UNLOCK_SREQS;
1254 /* Add a shadow for 'request', overwriting any old binding for it. */
1256 static
1257 void add_shadow_Request( MPI_Request request,
1258 void* buf, int count,
1259 MPI_Datatype datatype )
1261 int i, ix = -1;
1262 LOCK_SREQS;
1263 assert(sReqs_used >= 0);
1264 assert(sReqs_size >= 0);
1265 assert(sReqs_used <= sReqs_size);
1266 if (sReqs == NULL) assert(sReqs_size == 0);
1268 /* First of all see if we already have a binding for this key; if
1269 so just replace it, and have done. */
1270 for (i = 0; i < sReqs_used; i++) {
1271 if (sReqs[i].inUse && eq_MPI_Request(sReqs[i].key,request)) {
1272 ix = i;
1273 break;
1277 if (ix < 0) {
1278 /* Ok, we don't have it, so will have to add it. First search
1279 to see if there is an existing empty slot. */
1280 for (i = 0; i < sReqs_used; i++) {
1281 if (!sReqs[i].inUse) {
1282 ix = i;
1283 break;
1288 /* No empty slots. Allocate a new one. */
1289 if (ix < 0) {
1290 ensure_sReq_space();
1291 assert(sReqs_used < sReqs_size);
1292 ix = sReqs_used;
1293 sReqs_used++;
1296 assert(ix >= 0 && ix < sReqs_used);
1297 assert(sReqs_used <= sReqs_size);
1299 sReqs[ix].inUse = True;
1300 sReqs[ix].key = request;
1301 sReqs[ix].buf = buf;
1302 sReqs[ix].count = count;
1303 sReqs[ix].datatype = datatype;
1305 UNLOCK_SREQS;
1306 if (opt_verbosity > 1)
1307 fprintf(stderr, "%s %5d: sReq+ 0x%lx -> b/c/d %p/%d/0x%lx [slot %d]\n",
1308 preamble, my_pid, (unsigned long)request,
1309 buf, count, (long)datatype, ix);
1312 static
1313 MPI_Request* clone_Request_array ( int count, MPI_Request* orig )
1315 MPI_Request* copy;
1316 int i;
1317 LOCK_SREQS;
1318 if (count < 0)
1319 count = 0; /* Hmm. Call Mulder and Scully. */
1320 copy = malloc( count * sizeof(MPI_Request) );
1321 if (copy == NULL && count > 0) {
1322 UNLOCK_SREQS;
1323 barf("clone_Request_array: malloc failed");
1325 for (i = 0; i < count; i++)
1326 copy[i] = orig[i];
1327 UNLOCK_SREQS;
1328 return copy;
1331 #undef LOCK_SREQS
1332 #undef UNLOCK_SREQS
1335 static void maybe_complete ( Bool error_in_status,
1336 MPI_Request request_before,
1337 MPI_Request request_after,
1338 MPI_Status* status )
1340 int recv_count = 0;
1341 ShadowRequest* shadow;
1342 /* How do we know if this is an Irecv request that has now
1343 finished successfully?
1345 request_before isn't MPI_REQUEST_NULL
1346 and request_before is found in the shadow table
1347 and request_after *is* MPI_REQUEST_NULL
1348 and (if error_in_status then status.MPI_ERROR is MPI_SUCCESS)
1350 (when error_in_status == False, then we expect not to get
1351 called at all if there was an error.)
1353 if (request_before != MPI_REQUEST_NULL
1354 && request_after == MPI_REQUEST_NULL
1355 && (error_in_status ? status->MPI_ERROR == MPI_SUCCESS : True)
1356 && ( (shadow=find_shadow_Request(request_before)) != NULL) ) {
1357 /* The Irecv detailed in 'shadow' completed. Paint the result
1358 buffer, and delete the entry. */
1359 if (count_from_Status(&recv_count, shadow->datatype, status)) {
1360 make_mem_defined_if_addressable(shadow->buf, recv_count, shadow->datatype);
1361 if (opt_verbosity > 1)
1362 fprintf(stderr, "%s %5d: sReq- %p (completed)\n",
1363 preamble, my_pid, request_before);
1365 delete_shadow_Request(request_before);
1370 /* --- Isend --- */
1371 /* rd: (buf,count,datatype) */
1372 /* wr: *request */
1373 static __inline__
1374 int generic_Isend(void *buf, int count, MPI_Datatype datatype,
1375 int dest, int tag, MPI_Comm comm,
1376 MPI_Request* request)
1378 OrigFn fn;
1379 int err;
1380 VALGRIND_GET_ORIG_FN(fn);
1381 before("{,B,S,R}Isend");
1382 check_mem_is_defined(buf, count, datatype);
1383 check_mem_is_addressable_untyped(request, sizeof(*request));
1384 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1385 CALL_FN_W_7W(err, fn, buf,count,datatype,dest,tag,comm,request);
1386 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1387 make_mem_defined_if_addressable_if_success_untyped(err, request, sizeof(*request));
1388 after("{,B,S,R}Isend", err);
1389 return err;
1391 int WRAPPER_FOR(PMPI_Isend)(void *buf, int count, MPI_Datatype datatype,
1392 int dest, int tag, MPI_Comm comm,
1393 MPI_Request* request) {
1394 return generic_Isend(buf,count,datatype, dest,tag,comm, request);
1396 int WRAPPER_FOR(PMPI_Ibsend)(void *buf, int count, MPI_Datatype datatype,
1397 int dest, int tag, MPI_Comm comm,
1398 MPI_Request* request) {
1399 return generic_Isend(buf,count,datatype, dest,tag,comm, request);
1401 int WRAPPER_FOR(PMPI_Issend)(void *buf, int count, MPI_Datatype datatype,
1402 int dest, int tag, MPI_Comm comm,
1403 MPI_Request* request) {
1404 return generic_Isend(buf,count,datatype, dest,tag,comm, request);
1406 int WRAPPER_FOR(PMPI_Irsend)(void *buf, int count, MPI_Datatype datatype,
1407 int dest, int tag, MPI_Comm comm,
1408 MPI_Request* request) {
1409 return generic_Isend(buf,count,datatype, dest,tag,comm, request);
1413 /* --- Irecv --- */
1414 /* pre: must be writable: (buf,count,datatype), *request
1415 post: make readable *request
1416 add a request->(buf,count,ty) binding to the
1417 shadow request table.
1419 int WRAPPER_FOR(PMPI_Irecv)( void* buf, int count, MPI_Datatype datatype,
1420 int source, int tag, MPI_Comm comm,
1421 MPI_Request* request )
1423 OrigFn fn;
1424 int err;
1425 VALGRIND_GET_ORIG_FN(fn);
1426 before("Irecv");
1427 check_mem_is_addressable(buf, count, datatype);
1428 check_mem_is_addressable_untyped(request, sizeof(*request));
1429 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1430 CALL_FN_W_7W(err, fn, buf,count,datatype,source,tag,comm,request);
1431 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1432 if (err == MPI_SUCCESS) {
1433 make_mem_defined_if_addressable_untyped(request, sizeof(*request));
1434 add_shadow_Request( *request, buf,count,datatype );
1436 after("Irecv", err);
1437 return err;
1440 /* --- Wait --- */
1441 /* The MPI1 spec (imprecisely) defines 3 request states:
1442 - "null" if the request is MPI_REQUEST_NULL
1443 - "inactive" if not "null" and not associated with ongoing comms
1444 - "active" if not "null" and is associated with ongoing comms
1446 int WRAPPER_FOR(PMPI_Wait)( MPI_Request* request,
1447 MPI_Status* status )
1449 MPI_Request request_before;
1450 MPI_Status fake_status;
1451 OrigFn fn;
1452 int err;
1453 VALGRIND_GET_ORIG_FN(fn);
1454 before("Wait");
1455 if (isMSI(status))
1456 status = &fake_status;
1457 check_mem_is_addressable_untyped(status, sizeof(MPI_Status));
1458 check_mem_is_defined_untyped(request, sizeof(MPI_Request));
1459 request_before = *request;
1460 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1461 CALL_FN_W_WW(err, fn, request,status);
1462 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1463 if (err == MPI_SUCCESS) {
1464 maybe_complete(False/*err in status?*/,
1465 request_before, *request, status);
1466 make_mem_defined_if_addressable_untyped(status, sizeof(MPI_Status));
1468 after("Wait", err);
1469 return err;
1472 /* --- Waitany --- */
1473 int WRAPPER_FOR(PMPI_Waitany)( int count,
1474 MPI_Request* requests,
1475 int* index,
1476 MPI_Status* status )
1478 MPI_Request* requests_before = NULL;
1479 MPI_Status fake_status;
1480 OrigFn fn;
1481 int err, i;
1482 VALGRIND_GET_ORIG_FN(fn);
1483 before("Waitany");
1484 if (isMSI(status))
1485 status = &fake_status;
1486 if (0) fprintf(stderr, "Waitany: %d\n", count);
1487 check_mem_is_addressable_untyped(index, sizeof(int));
1488 check_mem_is_addressable_untyped(status, sizeof(MPI_Status));
1489 for (i = 0; i < count; i++) {
1490 check_mem_is_defined_untyped(&requests[i], sizeof(MPI_Request));
1492 requests_before = clone_Request_array( count, requests );
1493 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1494 CALL_FN_W_WWWW(err, fn, count,requests,index,status);
1495 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1496 if (err == MPI_SUCCESS && *index >= 0 && *index < count) {
1497 maybe_complete(False/*err in status?*/,
1498 requests_before[*index], requests[*index], status);
1499 make_mem_defined_if_addressable_untyped(status, sizeof(MPI_Status));
1501 if (requests_before)
1502 free(requests_before);
1503 after("Waitany", err);
1504 return err;
1507 /* --- Waitall --- */
1508 int WRAPPER_FOR(PMPI_Waitall)( int count,
1509 MPI_Request* requests,
1510 MPI_Status* statuses )
1512 MPI_Request* requests_before = NULL;
1513 OrigFn fn;
1514 int err, i;
1515 Bool free_sta = False;
1516 VALGRIND_GET_ORIG_FN(fn);
1517 before("Waitall");
1518 if (0) fprintf(stderr, "Waitall: %d\n", count);
1519 if (isMSI(statuses)) {
1520 free_sta = True;
1521 statuses = malloc( (count < 0 ? 0 : count) * sizeof(MPI_Status) );
1523 for (i = 0; i < count; i++) {
1524 check_mem_is_addressable_untyped(&statuses[i], sizeof(MPI_Status));
1525 check_mem_is_defined_untyped(&requests[i], sizeof(MPI_Request));
1527 requests_before = clone_Request_array( count, requests );
1528 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1529 CALL_FN_W_WWW(err, fn, count,requests,statuses);
1530 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1531 if (err == MPI_SUCCESS /*complete success*/
1532 || err == MPI_ERR_IN_STATUS /* partial success */) {
1533 Bool e_i_s = err == MPI_ERR_IN_STATUS;
1534 for (i = 0; i < count; i++) {
1535 maybe_complete(e_i_s, requests_before[i], requests[i],
1536 &statuses[i]);
1537 make_mem_defined_if_addressable_untyped(&statuses[i],
1538 sizeof(MPI_Status));
1541 if (requests_before)
1542 free(requests_before);
1543 if (free_sta)
1544 free(statuses);
1545 after("Waitall", err);
1546 return err;
1549 /* --- Test --- */
1550 /* nonblocking version of Wait */
1551 int WRAPPER_FOR(PMPI_Test)( MPI_Request* request, int* flag,
1552 MPI_Status* status )
1554 MPI_Request request_before;
1555 MPI_Status fake_status;
1556 OrigFn fn;
1557 int err;
1558 VALGRIND_GET_ORIG_FN(fn);
1559 before("Test");
1560 if (isMSI(status))
1561 status = &fake_status;
1562 check_mem_is_addressable_untyped(status, sizeof(MPI_Status));
1563 check_mem_is_addressable_untyped(flag, sizeof(int));
1564 check_mem_is_defined_untyped(request, sizeof(MPI_Request));
1565 request_before = *request;
1566 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1567 CALL_FN_W_WWW(err, fn, request,flag,status);
1568 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1569 if (err == MPI_SUCCESS && *flag) {
1570 maybe_complete(False/*err in status?*/,
1571 request_before, *request, status);
1572 make_mem_defined_if_addressable_untyped(status, sizeof(MPI_Status));
1574 after("Test", err);
1575 return err;
1578 /* --- Testall --- */
1579 /* nonblocking version of Waitall */
1580 int WRAPPER_FOR(PMPI_Testall)( int count, MPI_Request* requests,
1581 int* flag, MPI_Status* statuses )
1583 MPI_Request* requests_before = NULL;
1584 OrigFn fn;
1585 int err, i;
1586 Bool free_sta = False;
1587 VALGRIND_GET_ORIG_FN(fn);
1588 before("Testall");
1589 if (0) fprintf(stderr, "Testall: %d\n", count);
1590 if (isMSI(statuses)) {
1591 free_sta = True;
1592 statuses = malloc( (count < 0 ? 0 : count) * sizeof(MPI_Status) );
1594 check_mem_is_addressable_untyped(flag, sizeof(int));
1595 for (i = 0; i < count; i++) {
1596 check_mem_is_addressable_untyped(&statuses[i], sizeof(MPI_Status));
1597 check_mem_is_defined_untyped(&requests[i], sizeof(MPI_Request));
1599 requests_before = clone_Request_array( count, requests );
1600 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1601 CALL_FN_W_WWWW(err, fn, count,requests,flag,statuses);
1602 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1603 /* Urk. Is the following "if (...)" really right? I don't know. */
1604 if (*flag
1605 && (err == MPI_SUCCESS /*complete success*/
1606 || err == MPI_ERR_IN_STATUS /* partial success */)) {
1607 Bool e_i_s = err == MPI_ERR_IN_STATUS;
1608 for (i = 0; i < count; i++) {
1609 maybe_complete(e_i_s, requests_before[i], requests[i],
1610 &statuses[i]);
1611 make_mem_defined_if_addressable_untyped(&statuses[i],
1612 sizeof(MPI_Status));
1615 if (requests_before)
1616 free(requests_before);
1617 if (free_sta)
1618 free(statuses);
1619 after("Testall", err);
1620 return err;
1623 /* --- Iprobe --- */
1624 /* pre: must-be-writable: *flag, *status */
1625 /* post: make-readable *flag
1626 if *flag==True make-defined *status */
1627 int WRAPPER_FOR(PMPI_Iprobe)(int source, int tag,
1628 MPI_Comm comm,
1629 int* flag, MPI_Status* status)
1631 MPI_Status fake_status;
1632 OrigFn fn;
1633 int err;
1634 VALGRIND_GET_ORIG_FN(fn);
1635 before("Iprobe");
1636 if (isMSI(status))
1637 status = &fake_status;
1638 check_mem_is_addressable_untyped(flag, sizeof(*flag));
1639 check_mem_is_addressable_untyped(status, sizeof(*status));
1640 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1641 CALL_FN_W_5W(err, fn, source,tag,comm,flag,status);
1642 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1643 if (err == MPI_SUCCESS) {
1644 make_mem_defined_if_addressable_untyped(flag, sizeof(*flag));
1645 if (*flag)
1646 make_mem_defined_if_addressable_untyped(status, sizeof(*status));
1648 after("Iprobe", err);
1649 return err;
1652 /* --- Probe --- */
1653 /* pre: must-be-writable *status */
1654 /* post: make-defined *status */
1655 int WRAPPER_FOR(PMPI_Probe)(int source, int tag,
1656 MPI_Comm comm, MPI_Status* status)
1658 MPI_Status fake_status;
1659 OrigFn fn;
1660 int err;
1661 VALGRIND_GET_ORIG_FN(fn);
1662 before("Probe");
1663 if (isMSI(status))
1664 status = &fake_status;
1665 check_mem_is_addressable_untyped(status, sizeof(*status));
1666 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1667 CALL_FN_W_WWWW(err, fn, source,tag,comm,status);
1668 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1669 make_mem_defined_if_addressable_if_success_untyped(err, status, sizeof(*status));
1670 after("Probe", err);
1671 return err;
1674 /* --- Cancel --- */
1675 /* Wrapping PMPI_Cancel is interesting only to the extent that we need
1676 to be able to detect when a request should be removed from our
1677 shadow table due to cancellation. */
1678 int WRAPPER_FOR(PMPI_Cancel)(MPI_Request* request)
1680 OrigFn fn;
1681 int err;
1682 MPI_Request tmp;
1683 VALGRIND_GET_ORIG_FN(fn);
1684 before("Cancel");
1685 check_mem_is_addressable_untyped(request, sizeof(*request));
1686 tmp = *request;
1687 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1688 CALL_FN_W_W(err, fn, request);
1689 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1690 if (err == MPI_SUCCESS)
1691 delete_shadow_Request(tmp);
1692 after("Cancel", err);
1693 return err;
1697 /*------------------------------------------------------------*/
1698 /*--- ---*/
1699 /*--- Sec 3.10, Send-receive ---*/
1700 /*--- ---*/
1701 /*------------------------------------------------------------*/
1703 /* --- Sendrecv --- */
1704 /* pre: must be readable: (sendbuf,sendcount,sendtype)
1705 must be writable: (recvbuf,recvcount,recvtype)
1706 post: make readable: (recvbuf,recvcount_actual,datatype)
1707 where recvcount_actual is determined from *status
1709 int WRAPPER_FOR(PMPI_Sendrecv)(
1710 void *sendbuf, int sendcount, MPI_Datatype sendtype,
1711 int dest, int sendtag,
1712 void *recvbuf, int recvcount, MPI_Datatype recvtype,
1713 int source, int recvtag,
1714 MPI_Comm comm, MPI_Status *status)
1716 MPI_Status fake_status;
1717 OrigFn fn;
1718 int err, recvcount_actual = 0;
1719 VALGRIND_GET_ORIG_FN(fn);
1720 before("Sendrecv");
1721 if (isMSI(status))
1722 status = &fake_status;
1723 check_mem_is_defined(sendbuf, sendcount, sendtype);
1724 check_mem_is_addressable(recvbuf, recvcount, recvtype);
1725 check_mem_is_addressable_untyped(status, sizeof(*status));
1726 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1727 CALL_FN_W_12W(err, fn, sendbuf,sendcount,sendtype,dest,sendtag,
1728 recvbuf,recvcount,recvtype,source,recvtag,
1729 comm,status);
1730 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1731 make_mem_defined_if_addressable_if_success_untyped(err, status, sizeof(*status));
1732 if (err == MPI_SUCCESS
1733 && count_from_Status(&recvcount_actual,recvtype,status)) {
1734 make_mem_defined_if_addressable(recvbuf, recvcount_actual, recvtype);
1736 after("Sendrecv", err);
1737 return err;
1741 /*------------------------------------------------------------*/
1742 /*--- ---*/
1743 /*--- Sec 3.12, Derived datatypes ---*/
1744 /*--- ---*/
1745 /*------------------------------------------------------------*/
1747 /* --- Address --- */
1748 /* Does this have anything worth checking? */
1749 HAS_NO_WRAPPER(Address)
1751 /* --- MPI 2 stuff --- */
1752 /* Type_extent, Type_get_contents and Type_get_envelope sometimes get
1753 used intensively by the type walker (walk_type). There's no reason
1754 why they couldn't be properly wrapped if needed, but doing so slows
1755 everything down, so don't bother until needed. */
1756 HAS_NO_WRAPPER(Type_extent)
1757 HAS_NO_WRAPPER(Type_get_contents)
1758 HAS_NO_WRAPPER(Type_get_envelope)
1760 /* --- Type_commit --- */
1761 int WRAPPER_FOR(PMPI_Type_commit)( MPI_Datatype* ty )
1763 OrigFn fn;
1764 int err;
1765 VALGRIND_GET_ORIG_FN(fn);
1766 before("Type_commit");
1767 check_mem_is_defined_untyped(ty, sizeof(*ty));
1768 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1769 CALL_FN_W_W(err, fn, ty);
1770 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1771 after("Type_commit", err);
1772 return err;
1775 /* --- Type_free --- */
1776 int WRAPPER_FOR(PMPI_Type_free)( MPI_Datatype* ty )
1778 OrigFn fn;
1779 int err;
1780 VALGRIND_GET_ORIG_FN(fn);
1781 before("Type_free");
1782 check_mem_is_defined_untyped(ty, sizeof(*ty));
1783 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1784 CALL_FN_W_W(err, fn, ty);
1785 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1786 after("Type_free", err);
1787 return err;
1791 /*------------------------------------------------------------*/
1792 /*--- ---*/
1793 /*--- Sec 3.13, Pack and unpack ---*/
1794 /*--- ---*/
1795 /*------------------------------------------------------------*/
1797 /* --- Pack --- */
1798 /* pre: must be readable: position
1799 must be readable: (inbuf,incount,datatype)
1800 must be writable: outbuf[0 .. outsize-1]
1801 must be writable: outbuf[*position ..
1802 *position - 1
1803 + however much space PMPI_Pack_size
1804 says we will need]
1805 post: make readable: outbuf[old *position .. new *position]
1807 int WRAPPER_FOR(PMPI_Pack)( void* inbuf, int incount, MPI_Datatype datatype,
1808 void* outbuf, int outsize,
1809 int* position, MPI_Comm comm )
1811 OrigFn fn;
1812 int err, szB = 0;
1813 int position_ORIG = *position;
1814 VALGRIND_GET_ORIG_FN(fn);
1815 before("Pack");
1816 /* stay sane */
1817 check_mem_is_defined_untyped(position, sizeof(*position));
1818 /* check input */
1819 check_mem_is_defined(inbuf, incount, datatype);
1820 /* check output area's stated bounds make sense */
1821 check_mem_is_addressable_untyped(outbuf, outsize);
1822 /* check output area's actual used size properly */
1823 err = PMPI_Pack_size( incount, datatype, comm, &szB );
1824 if (err == MPI_SUCCESS && szB > 0) {
1825 check_mem_is_addressable_untyped(
1826 ((char*)outbuf) + position_ORIG, szB
1830 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1831 CALL_FN_W_7W(err, fn, inbuf,incount,datatype, outbuf,outsize,position, comm);
1832 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1834 if (err == MPI_SUCCESS && (*position) > position_ORIG) {
1835 /* paint output */
1836 make_mem_defined_if_addressable_untyped(
1837 ((char*)outbuf) + position_ORIG, *position - position_ORIG
1840 after("Pack", err);
1841 return err;
1844 /* --- Unpack --- */
1845 /* pre: must be readable: position
1846 must be writable: (outbuf,outcount,datatype)
1847 must be writable: outbuf[0 .. outsize-1]
1848 must be writable: outbuf[*position ..
1849 *position - 1
1850 + however much space PMPI_Pack_size
1851 says we will need]
1852 post: make readable: (outbuf,outcount,datatype)
1853 and also do a readability check of
1854 inbuf[old *position .. new *position]
1856 int WRAPPER_FOR(PMPI_Unpack)( void* inbuf, int insize, int* position,
1857 void* outbuf, int outcount, MPI_Datatype datatype,
1858 MPI_Comm comm )
1860 OrigFn fn;
1861 int err, szB = 0;
1862 int position_ORIG = *position;
1863 VALGRIND_GET_ORIG_FN(fn);
1864 before("Unpack");
1865 /* stay sane */
1866 check_mem_is_defined_untyped(position, sizeof(*position));
1867 /* check output area is accessible */
1868 check_mem_is_addressable(outbuf, outcount, datatype);
1869 /* check input area's stated bounds make sense */
1870 check_mem_is_addressable_untyped(inbuf, insize);
1871 /* check input area's actual used size properly */
1872 err = PMPI_Pack_size( outcount, datatype, comm, &szB );
1873 if (err == MPI_SUCCESS && szB > 0) {
1874 check_mem_is_addressable_untyped(
1875 ((char*)inbuf) + position_ORIG, szB
1879 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1880 CALL_FN_W_7W(err, fn, inbuf,insize,position, outbuf,outcount,datatype, comm);
1881 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1883 if (err == MPI_SUCCESS && (*position) > position_ORIG) {
1884 /* recheck input more carefully */
1885 check_mem_is_defined_untyped(
1886 ((char*)inbuf) + position_ORIG, *position - position_ORIG
1888 /* paint output */
1889 make_mem_defined_if_addressable( outbuf, outcount, datatype );
1891 after("Unpack", err);
1892 return err;
1896 /*------------------------------------------------------------*/
1897 /*--- ---*/
1898 /*--- Sec 4.4, Broadcast ---*/
1899 /*--- ---*/
1900 /*------------------------------------------------------------*/
1902 /* --- Bcast --- */
1903 /* pre: must-be-readable (buffer,count,datatype) for rank==root
1904 must-be-writable (buffer,count,datatype) for rank!=root
1905 post: make-readable (buffer,count,datatype) for all
1907 Resulting behaviour is: if root sends uninitialised stuff, then
1908 V complains, but then all ranks, including itself, see the buffer
1909 as initialised after that.
1911 int WRAPPER_FOR(PMPI_Bcast)(void *buffer, int count,
1912 MPI_Datatype datatype,
1913 int root, MPI_Comm comm)
1915 OrigFn fn;
1916 int err;
1917 Bool i_am_sender;
1918 VALGRIND_GET_ORIG_FN(fn);
1919 before("Bcast");
1920 i_am_sender = root == comm_rank(comm);
1921 if (i_am_sender) {
1922 check_mem_is_defined(buffer, count, datatype);
1923 } else {
1924 check_mem_is_addressable(buffer, count, datatype);
1926 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1927 CALL_FN_W_5W(err, fn, buffer,count,datatype,root,comm);
1928 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1929 make_mem_defined_if_addressable_if_success(err, buffer, count, datatype);
1930 after("Bcast", err);
1931 return err;
1935 /*------------------------------------------------------------*/
1936 /*--- ---*/
1937 /*--- Sec 4.5, Gather ---*/
1938 /*--- ---*/
1939 /*------------------------------------------------------------*/
1941 /* --- Gather --- */
1942 /* JRS 20060217: I don't really understand this. Each process is
1943 going to send sendcount items of type sendtype to the root. So
1944 the root is going to receive comm_size*sendcount items of type
1945 sendtype (right?) So why specify recvcount and recvtype?
1947 Anyway, assuming the MPI Spec is correct (seems likely :-) we have:
1949 pre: (all) must be readable: (sendbuf,sendcount,sendtype)
1950 (root only): must be writable: (recvbuf,recvcount * comm_size,recvtype)
1951 post: (root only): make readable: (recvbuf,recvcount * comm_size,recvtype)
1953 int WRAPPER_FOR(PMPI_Gather)(
1954 void *sendbuf, int sendcount, MPI_Datatype sendtype,
1955 void *recvbuf, int recvcount, MPI_Datatype recvtype,
1956 int root, MPI_Comm comm)
1958 OrigFn fn;
1959 int err, me, sz;
1960 VALGRIND_GET_ORIG_FN(fn);
1961 before("Gather");
1962 me = comm_rank(comm);
1963 sz = comm_size(comm);
1964 check_mem_is_defined(sendbuf, sendcount, sendtype);
1965 if (me == root)
1966 check_mem_is_addressable(recvbuf, recvcount * sz, recvtype);
1967 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
1968 CALL_FN_W_8W(err, fn, sendbuf,sendcount,sendtype,
1969 recvbuf,recvcount,recvtype,
1970 root,comm);
1971 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
1972 if (me == root)
1973 make_mem_defined_if_addressable_if_success(err, recvbuf, recvcount * sz, recvtype);
1974 after("Gather", err);
1975 return err;
1979 /*------------------------------------------------------------*/
1980 /*--- ---*/
1981 /*--- Sec 4.6, Scatter ---*/
1982 /*--- ---*/
1983 /*------------------------------------------------------------*/
1985 /* pre: (root only): must be readable: (sendbuf,sendcount * comm_size,sendtype)
1986 (all): must be writable: (recvbuf,recvbuf,recvtype)
1987 post: (all): make defined: (recvbuf,recvbuf,recvtype)
1989 int WRAPPER_FOR(PMPI_Scatter)(
1990 void* sendbuf, int sendcount, MPI_Datatype sendtype,
1991 void* recvbuf, int recvcount, MPI_Datatype recvtype,
1992 int root, MPI_Comm comm)
1994 OrigFn fn;
1995 int err, me, sz;
1996 VALGRIND_GET_ORIG_FN(fn);
1997 before("Scatter");
1998 me = comm_rank(comm);
1999 sz = comm_size(comm);
2000 check_mem_is_addressable(recvbuf, recvcount, recvtype);
2001 if (me == root)
2002 check_mem_is_defined(sendbuf, sendcount * sz, sendtype);
2003 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2004 CALL_FN_W_8W(err, fn, sendbuf,sendcount,sendtype,
2005 recvbuf,recvcount,recvtype,
2006 root,comm);
2007 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2008 make_mem_defined_if_addressable_if_success(err, recvbuf, recvcount, recvtype);
2009 after("Scatter", err);
2010 return err;
2014 /*------------------------------------------------------------*/
2015 /*--- ---*/
2016 /*--- Sec 4.8, All-to-All Scatter/Gather ---*/
2017 /*--- ---*/
2018 /*------------------------------------------------------------*/
2020 /* pre: (all) must be readable: (sendbuf,sendcount * comm_size,sendtype)
2021 (all) must be writable: (recvbuf,recvcount * comm_size,recvtype)
2022 post: (all) make defined: (recvbuf,recvcount * comm_size,recvtype)
2024 int WRAPPER_FOR(PMPI_Alltoall)(
2025 void* sendbuf, int sendcount, MPI_Datatype sendtype,
2026 void* recvbuf, int recvcount, MPI_Datatype recvtype,
2027 MPI_Comm comm)
2029 OrigFn fn;
2030 int err, sz;
2031 VALGRIND_GET_ORIG_FN(fn);
2032 before("Alltoall");
2033 sz = comm_size(comm);
2034 check_mem_is_defined(sendbuf, sendcount * sz, sendtype);
2035 check_mem_is_addressable(recvbuf, recvcount * sz, recvtype);
2036 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2037 CALL_FN_W_7W(err, fn, sendbuf,sendcount,sendtype,
2038 recvbuf,recvcount,recvtype,
2039 comm);
2040 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2041 make_mem_defined_if_addressable_if_success(err, recvbuf, recvcount * sz, recvtype);
2042 after("Alltoall", err);
2043 return err;
2047 /*------------------------------------------------------------*/
2048 /*--- ---*/
2049 /*--- Sec 4.9, Global Reduction Operations ---*/
2050 /*--- ---*/
2051 /*------------------------------------------------------------*/
2053 /* --- Reduce --- */
2054 /* rd: (sendbuf,count,datatype) for all
2055 wr: (recvbuf,count,datatype) but only for rank == root
2057 int WRAPPER_FOR(PMPI_Reduce)(void *sendbuf, void *recvbuf,
2058 int count,
2059 MPI_Datatype datatype, MPI_Op op,
2060 int root, MPI_Comm comm)
2062 OrigFn fn;
2063 int err;
2064 Bool i_am_root;
2065 VALGRIND_GET_ORIG_FN(fn);
2066 before("Reduce");
2067 i_am_root = root == comm_rank(comm);
2068 check_mem_is_defined(sendbuf, count, datatype);
2069 if (i_am_root)
2070 check_mem_is_addressable(recvbuf, count, datatype);
2071 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2072 CALL_FN_W_7W(err, fn, sendbuf,recvbuf,count,datatype,op,root,comm);
2073 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2074 if (i_am_root)
2075 make_mem_defined_if_addressable_if_success(err, recvbuf, count, datatype);
2076 after("Reduce", err);
2077 return err;
2081 /* --- Allreduce --- */
2082 /* rd: (sendbuf,count,datatype) for all
2083 wr: (recvbuf,count,datatype) for all
2085 int WRAPPER_FOR(PMPI_Allreduce)(void *sendbuf, void *recvbuf,
2086 int count,
2087 MPI_Datatype datatype, MPI_Op op,
2088 MPI_Comm comm)
2090 OrigFn fn;
2091 int err;
2092 VALGRIND_GET_ORIG_FN(fn);
2093 before("Allreduce");
2094 check_mem_is_defined(sendbuf, count, datatype);
2095 check_mem_is_addressable(recvbuf, count, datatype);
2096 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2097 CALL_FN_W_6W(err, fn, sendbuf,recvbuf,count,datatype,op,comm);
2098 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2099 make_mem_defined_if_addressable_if_success(err, recvbuf, count, datatype);
2100 after("Allreduce", err);
2101 return err;
2105 /* --- Op_create --- */
2106 /* This is a bit dubious. I suppose it takes 'function' and
2107 writes something at *op, but who knows what an MPI_Op is?
2108 Can we safely do 'sizeof' on it? */
2109 int WRAPPER_FOR(PMPI_Op_create)( MPI_User_function* function,
2110 int commute,
2111 MPI_Op* op )
2113 OrigFn fn;
2114 int err;
2115 VALGRIND_GET_ORIG_FN(fn);
2116 before("Op_create");
2117 check_mem_is_addressable_untyped(op, sizeof(*op));
2118 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2119 CALL_FN_W_WWW(err, fn, function,commute,op);
2120 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2121 make_mem_defined_if_addressable_if_success_untyped(err, op, sizeof(*op));
2122 after("Op_create", err);
2123 return err;
2127 /*------------------------------------------------------------*/
2128 /*--- ---*/
2129 /*--- Sec 5.4, Communicator management ---*/
2130 /*--- ---*/
2131 /*------------------------------------------------------------*/
2133 /* Hardly seems worth wrapping Comm_rank and Comm_size, but
2134 since it's done now .. */
2136 /* --- Comm_create --- */
2137 /* Let normal memcheck tracking handle this. */
2138 int WRAPPER_FOR(PMPI_Comm_create)(MPI_Comm comm, MPI_Group group,
2139 MPI_Comm* newcomm)
2141 OrigFn fn;
2142 int err;
2143 VALGRIND_GET_ORIG_FN(fn);
2144 before("Comm_create");
2145 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2146 CALL_FN_W_WWW(err, fn, comm,group,newcomm);
2147 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2148 after("Comm_create", err);
2149 return err;
2152 /* --- Comm_dup --- */
2153 /* Let normal memcheck tracking handle this. */
2154 int WRAPPER_FOR(PMPI_Comm_dup)(MPI_Comm comm, MPI_Comm* newcomm)
2156 OrigFn fn;
2157 int err;
2158 VALGRIND_GET_ORIG_FN(fn);
2159 before("Comm_dup");
2160 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2161 CALL_FN_W_WW(err, fn, comm,newcomm);
2162 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2163 after("Comm_dup", err);
2164 return err;
2167 /* --- Comm_free --- */
2168 /* Let normal memcheck tracking handle this. */
2169 int WRAPPER_FOR(PMPI_Comm_free)(MPI_Comm* comm)
2171 OrigFn fn;
2172 int err;
2173 VALGRIND_GET_ORIG_FN(fn);
2174 before("Comm_free");
2175 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2176 CALL_FN_W_W(err, fn, comm);
2177 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2178 after("Comm_free", err);
2179 return err;
2182 /* --- Comm_rank --- */
2183 /* wr: (rank, sizeof(*rank)) */
2184 int WRAPPER_FOR(PMPI_Comm_rank)(MPI_Comm comm, int *rank)
2186 OrigFn fn;
2187 int err;
2188 VALGRIND_GET_ORIG_FN(fn);
2189 before("Comm_rank");
2190 check_mem_is_addressable_untyped(rank, sizeof(*rank));
2191 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2192 CALL_FN_W_WW(err, fn, comm,rank);
2193 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2194 make_mem_defined_if_addressable_if_success_untyped(err, rank, sizeof(*rank));
2195 after("Comm_rank", err);
2196 return err;
2199 /* --- Comm_size --- */
2200 /* wr: (size, sizeof(*size)) */
2201 int WRAPPER_FOR(PMPI_Comm_size)(MPI_Comm comm, int *size)
2203 OrigFn fn;
2204 int err;
2205 VALGRIND_GET_ORIG_FN(fn);
2206 before("Comm_size");
2207 check_mem_is_addressable_untyped(size, sizeof(*size));
2208 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2209 CALL_FN_W_WW(err, fn, comm,size);
2210 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2211 make_mem_defined_if_addressable_if_success_untyped(err, size, sizeof(*size));
2212 after("Comm_size", err);
2213 return err;
2217 /*------------------------------------------------------------*/
2218 /*--- ---*/
2219 /*--- Sec 5.7, Caching ---*/
2220 /*--- ---*/
2221 /*------------------------------------------------------------*/
2224 /*------------------------------------------------------------*/
2225 /*--- ---*/
2226 /*--- Sec 7.3, Error codes and classes ---*/
2227 /*--- ---*/
2228 /*------------------------------------------------------------*/
2230 /* --- Error_string --- */
2231 int WRAPPER_FOR(PMPI_Error_string)( int errorcode, char* string,
2232 int* resultlen )
2234 OrigFn fn;
2235 int err;
2236 VALGRIND_GET_ORIG_FN(fn);
2237 before("Error_string");
2238 check_mem_is_addressable_untyped(resultlen, sizeof(int));
2239 check_mem_is_addressable_untyped(string, MPI_MAX_ERROR_STRING);
2240 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2241 CALL_FN_W_WWW(err, fn, errorcode,string,resultlen);
2242 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2243 /* Don't bother to paint the result; we assume the real function
2244 will have filled it with defined characters :-) */
2245 after("Error_string", err);
2246 return err;
2250 /*------------------------------------------------------------*/
2251 /*--- ---*/
2252 /*--- Sec 7.5, Startup ---*/
2253 /*--- ---*/
2254 /*------------------------------------------------------------*/
2256 /* --- Init --- */
2257 /* rd: *argc, *argv[0 .. *argc-1] */
2258 long WRAPPER_FOR(PMPI_Init)(int *argc, char ***argv)
2260 OrigFn fn;
2261 int err;
2262 VALGRIND_GET_ORIG_FN(fn);
2263 before("Init");
2264 if (argc) {
2265 check_mem_is_defined_untyped(argc, sizeof(int));
2267 if (argc && argv) {
2268 check_mem_is_defined_untyped(*argv, *argc * sizeof(char**));
2270 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2271 CALL_FN_W_WW(err, fn, argc,argv);
2272 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2273 after("Init", err);
2274 if (opt_initkludge)
2275 return (long)(void*)&mpiwrap_walk_type_EXTERNALLY_VISIBLE;
2276 else
2277 return (long)err;
2280 /* --- Initialized --- */
2281 int WRAPPER_FOR(PMPI_Initialized)(int* flag)
2283 OrigFn fn;
2284 int err;
2285 VALGRIND_GET_ORIG_FN(fn);
2286 before("Initialized");
2287 check_mem_is_addressable_untyped(flag, sizeof(int));
2288 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2289 CALL_FN_W_W(err, fn, flag);
2290 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2291 make_mem_defined_if_addressable_if_success_untyped(err, flag, sizeof(int));
2292 after("Initialized", err);
2293 return err;
2296 /* --- Finalize --- */
2297 int WRAPPER_FOR(PMPI_Finalize)(void)
2299 OrigFn fn;
2300 int err;
2301 VALGRIND_GET_ORIG_FN(fn);
2302 before("Finalize");
2303 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING;
2304 CALL_FN_W_v(err, fn);
2305 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING;
2306 after("Finalize", err);
2307 return err;
2311 /*------------------------------------------------------------*/
2312 /*--- ---*/
2313 /*--- Default wrappers for all remaining functions ---*/
2314 /*--- ---*/
2315 /*------------------------------------------------------------*/
2317 /* Boilerplate for default wrappers. */
2318 #define DEFAULT_WRAPPER_PREAMBLE(basename) \
2319 OrigFn fn; \
2320 UWord res; \
2321 static int complaints = 1; \
2322 VALGRIND_GET_ORIG_FN(fn); \
2323 before(#basename); \
2324 if (opt_missing >= 2) { \
2325 barf("no wrapper for PMPI_" #basename \
2326 ",\n\t\t\t and you have " \
2327 "requested strict checking"); \
2329 if (opt_missing == 1 && complaints > 0) { \
2330 fprintf(stderr, "%s %5d: warning: no wrapper " \
2331 "for PMPI_" #basename "\n", \
2332 preamble, my_pid); \
2333 complaints--; \
2336 #define DEFAULT_WRAPPER_W_0W(basename) \
2337 UWord WRAPPER_FOR(PMPI_##basename)( void ) \
2339 DEFAULT_WRAPPER_PREAMBLE(basename) \
2340 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2341 CALL_FN_W_v(res, fn); \
2342 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2343 return res; \
2346 #define DEFAULT_WRAPPER_W_1W(basename) \
2347 UWord WRAPPER_FOR(PMPI_##basename)( UWord a1 ) \
2349 DEFAULT_WRAPPER_PREAMBLE(basename) \
2350 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2351 CALL_FN_W_W(res, fn, a1); \
2352 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2353 return res; \
2356 #define DEFAULT_WRAPPER_W_2W(basename) \
2357 UWord WRAPPER_FOR(PMPI_##basename)( UWord a1, UWord a2 ) \
2359 DEFAULT_WRAPPER_PREAMBLE(basename) \
2360 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2361 CALL_FN_W_WW(res, fn, a1,a2); \
2362 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2363 return res; \
2366 #define DEFAULT_WRAPPER_W_3W(basename) \
2367 UWord WRAPPER_FOR(PMPI_##basename) \
2368 ( UWord a1, UWord a2, UWord a3 ) \
2370 DEFAULT_WRAPPER_PREAMBLE(basename) \
2371 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2372 CALL_FN_W_WWW(res, fn, a1,a2,a3); \
2373 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2374 return res; \
2377 #define DEFAULT_WRAPPER_W_4W(basename) \
2378 UWord WRAPPER_FOR(PMPI_##basename) \
2379 ( UWord a1, UWord a2, UWord a3, UWord a4 ) \
2381 DEFAULT_WRAPPER_PREAMBLE(basename) \
2382 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2383 CALL_FN_W_WWWW(res, fn, a1,a2,a3,a4); \
2384 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2385 return res; \
2388 #define DEFAULT_WRAPPER_W_5W(basename) \
2389 UWord WRAPPER_FOR(PMPI_##basename) \
2390 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5 ) \
2392 DEFAULT_WRAPPER_PREAMBLE(basename) \
2393 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2394 CALL_FN_W_5W(res, fn, a1,a2,a3,a4,a5); \
2395 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2396 return res; \
2399 #define DEFAULT_WRAPPER_W_6W(basename) \
2400 UWord WRAPPER_FOR(PMPI_##basename) \
2401 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2402 UWord a6 ) \
2404 DEFAULT_WRAPPER_PREAMBLE(basename) \
2405 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2406 CALL_FN_W_6W(res, fn, a1,a2,a3,a4,a5,a6); \
2407 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2408 return res; \
2411 #define DEFAULT_WRAPPER_W_7W(basename) \
2412 UWord WRAPPER_FOR(PMPI_##basename) \
2413 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2414 UWord a6, UWord a7 ) \
2416 DEFAULT_WRAPPER_PREAMBLE(basename) \
2417 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2418 CALL_FN_W_7W(res, fn, a1,a2,a3,a4,a5,a6,a7); \
2419 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2420 return res; \
2423 #define DEFAULT_WRAPPER_W_8W(basename) \
2424 UWord WRAPPER_FOR(PMPI_##basename) \
2425 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2426 UWord a6, UWord a7, UWord a8 ) \
2428 DEFAULT_WRAPPER_PREAMBLE(basename) \
2429 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2430 CALL_FN_W_8W(res, fn, a1,a2,a3,a4,a5,a6,a7,a8); \
2431 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2432 return res; \
2435 #define DEFAULT_WRAPPER_W_9W(basename) \
2436 UWord WRAPPER_FOR(PMPI_##basename) \
2437 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2438 UWord a6, UWord a7, UWord a8, UWord a9 ) \
2440 DEFAULT_WRAPPER_PREAMBLE(basename) \
2441 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2442 CALL_FN_W_9W(res, fn, a1,a2,a3,a4,a5,a6,a7,a8,a9); \
2443 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2444 return res; \
2447 #define DEFAULT_WRAPPER_W_10W(basename) \
2448 UWord WRAPPER_FOR(PMPI_##basename) \
2449 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2450 UWord a6, UWord a7, UWord a8, UWord a9, UWord a10 ) \
2452 DEFAULT_WRAPPER_PREAMBLE(basename) \
2453 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2454 CALL_FN_W_10W(res, fn, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10); \
2455 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2456 return res; \
2459 #define DEFAULT_WRAPPER_W_12W(basename) \
2460 UWord WRAPPER_FOR(PMPI_##basename) \
2461 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2462 UWord a6, UWord a7, UWord a8, UWord a9, UWord a10, \
2463 UWord a11, UWord a12 ) \
2465 DEFAULT_WRAPPER_PREAMBLE(basename) \
2466 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2467 CALL_FN_W_12W(res, fn, a1,a2,a3,a4,a5,a6, \
2468 a7,a8,a9,a10,a11,a12); \
2469 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2470 return res; \
2474 /* Canned summary of MPI-1.1/MPI-2 entry points, as derived from mpi.h
2475 from Open MPI svn rev 9191 (somewhere between Open MPI versions
2476 1.0.1 and 1.1.0). */
2478 /* If a function is commented out in this list, it's because it has a
2479 proper wrapper written elsewhere (above here). */
2481 DEFAULT_WRAPPER_W_2W(Abort)
2482 DEFAULT_WRAPPER_W_9W(Accumulate)
2483 DEFAULT_WRAPPER_W_1W(Add_error_class)
2484 DEFAULT_WRAPPER_W_2W(Add_error_code)
2485 DEFAULT_WRAPPER_W_2W(Add_error_string)
2486 /* DEFAULT_WRAPPER_W_2W(Address) */
2487 DEFAULT_WRAPPER_W_7W(Allgather)
2488 DEFAULT_WRAPPER_W_8W(Allgatherv)
2489 DEFAULT_WRAPPER_W_3W(Alloc_mem)
2490 /* DEFAULT_WRAPPER_W_6W(Allreduce) */
2491 /* DEFAULT_WRAPPER_W_7W(Alltoall) */
2492 DEFAULT_WRAPPER_W_9W(Alltoallv)
2493 DEFAULT_WRAPPER_W_9W(Alltoallw)
2494 DEFAULT_WRAPPER_W_2W(Attr_delete)
2495 DEFAULT_WRAPPER_W_4W(Attr_get)
2496 DEFAULT_WRAPPER_W_3W(Attr_put)
2497 DEFAULT_WRAPPER_W_1W(Barrier)
2498 /* DEFAULT_WRAPPER_W_5W(Bcast) */
2499 /* DEFAULT_WRAPPER_W_6W(Bsend) */
2500 DEFAULT_WRAPPER_W_7W(Bsend_init)
2501 DEFAULT_WRAPPER_W_2W(Buffer_attach)
2502 DEFAULT_WRAPPER_W_2W(Buffer_detach)
2503 /* DEFAULT_WRAPPER_W_1W(Cancel) */
2504 DEFAULT_WRAPPER_W_4W(Cart_coords)
2505 DEFAULT_WRAPPER_W_6W(Cart_create)
2506 DEFAULT_WRAPPER_W_5W(Cart_get)
2507 DEFAULT_WRAPPER_W_5W(Cart_map)
2508 DEFAULT_WRAPPER_W_3W(Cart_rank)
2509 DEFAULT_WRAPPER_W_5W(Cart_shift)
2510 DEFAULT_WRAPPER_W_3W(Cart_sub)
2511 DEFAULT_WRAPPER_W_2W(Cartdim_get)
2512 DEFAULT_WRAPPER_W_1W(Close_port)
2513 DEFAULT_WRAPPER_W_5W(Comm_accept)
2514 DEFAULT_WRAPPER_W_1W(Comm_c2f)
2515 DEFAULT_WRAPPER_W_2W(Comm_call_errhandler)
2516 DEFAULT_WRAPPER_W_3W(Comm_compare)
2517 DEFAULT_WRAPPER_W_5W(Comm_connect)
2518 DEFAULT_WRAPPER_W_2W(Comm_create_errhandler)
2519 DEFAULT_WRAPPER_W_4W(Comm_create_keyval)
2520 /* DEFAULT_WRAPPER_W_3W(Comm_create) */
2521 DEFAULT_WRAPPER_W_2W(Comm_delete_attr)
2522 DEFAULT_WRAPPER_W_1W(Comm_disconnect)
2523 /* DEFAULT_WRAPPER_W_2W(Comm_dup) */
2524 DEFAULT_WRAPPER_W_1W(Comm_f2c)
2525 DEFAULT_WRAPPER_W_1W(Comm_free_keyval)
2526 /* DEFAULT_WRAPPER_W_1W(Comm_free) */
2527 DEFAULT_WRAPPER_W_4W(Comm_get_attr)
2528 DEFAULT_WRAPPER_W_2W(Comm_get_errhandler)
2529 DEFAULT_WRAPPER_W_3W(Comm_get_name)
2530 DEFAULT_WRAPPER_W_1W(Comm_get_parent)
2531 DEFAULT_WRAPPER_W_2W(Comm_group)
2532 DEFAULT_WRAPPER_W_2W(Comm_join)
2533 /* DEFAULT_WRAPPER_W_2W(Comm_rank) */
2534 DEFAULT_WRAPPER_W_2W(Comm_remote_group)
2535 DEFAULT_WRAPPER_W_2W(Comm_remote_size)
2536 DEFAULT_WRAPPER_W_3W(Comm_set_attr)
2537 DEFAULT_WRAPPER_W_2W(Comm_set_errhandler)
2538 DEFAULT_WRAPPER_W_2W(Comm_set_name)
2539 /* DEFAULT_WRAPPER_W_2W(Comm_size) */
2540 DEFAULT_WRAPPER_W_8W(Comm_spawn)
2541 DEFAULT_WRAPPER_W_9W(Comm_spawn_multiple)
2542 DEFAULT_WRAPPER_W_4W(Comm_split)
2543 DEFAULT_WRAPPER_W_2W(Comm_test_inter)
2544 DEFAULT_WRAPPER_W_3W(Dims_create)
2545 DEFAULT_WRAPPER_W_1W(Errhandler_c2f)
2546 DEFAULT_WRAPPER_W_2W(Errhandler_create)
2547 DEFAULT_WRAPPER_W_1W(Errhandler_f2c)
2548 DEFAULT_WRAPPER_W_1W(Errhandler_free)
2549 DEFAULT_WRAPPER_W_2W(Errhandler_get)
2550 DEFAULT_WRAPPER_W_2W(Errhandler_set)
2551 DEFAULT_WRAPPER_W_2W(Error_class)
2552 /* DEFAULT_WRAPPER_W_3W(Error_string) */
2553 DEFAULT_WRAPPER_W_6W(Exscan)
2554 DEFAULT_WRAPPER_W_1W(File_c2f)
2555 DEFAULT_WRAPPER_W_1W(File_f2c)
2556 DEFAULT_WRAPPER_W_2W(File_call_errhandler)
2557 DEFAULT_WRAPPER_W_2W(File_create_errhandler)
2558 DEFAULT_WRAPPER_W_2W(File_set_errhandler)
2559 DEFAULT_WRAPPER_W_2W(File_get_errhandler)
2560 DEFAULT_WRAPPER_W_5W(File_open)
2561 DEFAULT_WRAPPER_W_1W(File_close)
2562 DEFAULT_WRAPPER_W_2W(File_delete)
2563 DEFAULT_WRAPPER_W_2W(File_set_size)
2564 DEFAULT_WRAPPER_W_2W(File_preallocate)
2565 DEFAULT_WRAPPER_W_2W(File_get_size)
2566 DEFAULT_WRAPPER_W_2W(File_get_group)
2567 DEFAULT_WRAPPER_W_2W(File_get_amode)
2568 DEFAULT_WRAPPER_W_2W(File_set_info)
2569 DEFAULT_WRAPPER_W_2W(File_get_info)
2570 DEFAULT_WRAPPER_W_6W(File_set_view)
2571 DEFAULT_WRAPPER_W_5W(File_get_view)
2572 DEFAULT_WRAPPER_W_6W(File_read_at)
2573 DEFAULT_WRAPPER_W_6W(File_read_at_all)
2574 DEFAULT_WRAPPER_W_6W(File_write_at)
2575 DEFAULT_WRAPPER_W_6W(File_write_at_all)
2576 DEFAULT_WRAPPER_W_6W(File_iread_at)
2577 DEFAULT_WRAPPER_W_6W(File_iwrite_at)
2578 DEFAULT_WRAPPER_W_5W(File_read)
2579 DEFAULT_WRAPPER_W_5W(File_read_all)
2580 DEFAULT_WRAPPER_W_5W(File_write)
2581 DEFAULT_WRAPPER_W_5W(File_write_all)
2582 DEFAULT_WRAPPER_W_5W(File_iread)
2583 DEFAULT_WRAPPER_W_5W(File_iwrite)
2584 DEFAULT_WRAPPER_W_3W(File_seek)
2585 DEFAULT_WRAPPER_W_2W(File_get_position)
2586 DEFAULT_WRAPPER_W_3W(File_get_byte_offset)
2587 DEFAULT_WRAPPER_W_5W(File_read_shared)
2588 DEFAULT_WRAPPER_W_5W(File_write_shared)
2589 DEFAULT_WRAPPER_W_5W(File_iread_shared)
2590 DEFAULT_WRAPPER_W_5W(File_iwrite_shared)
2591 DEFAULT_WRAPPER_W_5W(File_read_ordered)
2592 DEFAULT_WRAPPER_W_5W(File_write_ordered)
2593 DEFAULT_WRAPPER_W_3W(File_seek_shared)
2594 DEFAULT_WRAPPER_W_2W(File_get_position_shared)
2595 DEFAULT_WRAPPER_W_5W(File_read_at_all_begin)
2596 DEFAULT_WRAPPER_W_3W(File_read_at_all_end)
2597 DEFAULT_WRAPPER_W_5W(File_write_at_all_begin)
2598 DEFAULT_WRAPPER_W_3W(File_write_at_all_end)
2599 DEFAULT_WRAPPER_W_4W(File_read_all_begin)
2600 DEFAULT_WRAPPER_W_3W(File_read_all_end)
2601 DEFAULT_WRAPPER_W_4W(File_write_all_begin)
2602 DEFAULT_WRAPPER_W_3W(File_write_all_end)
2603 DEFAULT_WRAPPER_W_4W(File_read_ordered_begin)
2604 DEFAULT_WRAPPER_W_3W(File_read_ordered_end)
2605 DEFAULT_WRAPPER_W_4W(File_write_ordered_begin)
2606 DEFAULT_WRAPPER_W_3W(File_write_ordered_end)
2607 DEFAULT_WRAPPER_W_3W(File_get_type_extent)
2608 DEFAULT_WRAPPER_W_2W(File_set_atomicity)
2609 DEFAULT_WRAPPER_W_2W(File_get_atomicity)
2610 DEFAULT_WRAPPER_W_1W(File_sync)
2611 /* DEFAULT_WRAPPER_W_0W(Finalize) */
2612 DEFAULT_WRAPPER_W_1W(Finalized)
2613 DEFAULT_WRAPPER_W_1W(Free_mem)
2614 /* DEFAULT_WRAPPER_W_8W(Gather) */
2615 DEFAULT_WRAPPER_W_9W(Gatherv)
2616 DEFAULT_WRAPPER_W_2W(Get_address)
2617 /* DEFAULT_WRAPPER_W_3W(Get_count) */
2618 DEFAULT_WRAPPER_W_3W(Get_elements)
2619 DEFAULT_WRAPPER_W_8W(Get)
2620 DEFAULT_WRAPPER_W_2W(Get_processor_name)
2621 DEFAULT_WRAPPER_W_2W(Get_version)
2622 DEFAULT_WRAPPER_W_6W(Graph_create)
2623 DEFAULT_WRAPPER_W_5W(Graph_get)
2624 DEFAULT_WRAPPER_W_5W(Graph_map)
2625 DEFAULT_WRAPPER_W_3W(Graph_neighbors_count)
2626 DEFAULT_WRAPPER_W_4W(Graph_neighbors)
2627 DEFAULT_WRAPPER_W_3W(Graphdims_get)
2628 DEFAULT_WRAPPER_W_1W(Grequest_complete)
2629 DEFAULT_WRAPPER_W_5W(Grequest_start)
2630 DEFAULT_WRAPPER_W_1W(Group_c2f)
2631 DEFAULT_WRAPPER_W_3W(Group_compare)
2632 DEFAULT_WRAPPER_W_3W(Group_difference)
2633 DEFAULT_WRAPPER_W_4W(Group_excl)
2634 DEFAULT_WRAPPER_W_1W(Group_f2c)
2635 DEFAULT_WRAPPER_W_1W(Group_free)
2636 DEFAULT_WRAPPER_W_4W(Group_incl)
2637 DEFAULT_WRAPPER_W_3W(Group_intersection)
2638 DEFAULT_WRAPPER_W_4W(Group_range_excl)
2639 DEFAULT_WRAPPER_W_4W(Group_range_incl)
2640 DEFAULT_WRAPPER_W_2W(Group_rank)
2641 DEFAULT_WRAPPER_W_2W(Group_size)
2642 DEFAULT_WRAPPER_W_5W(Group_translate_ranks)
2643 DEFAULT_WRAPPER_W_3W(Group_union)
2644 /* DEFAULT_WRAPPER_W_7W(Ibsend) */
2645 DEFAULT_WRAPPER_W_1W(Info_c2f)
2646 DEFAULT_WRAPPER_W_1W(Info_create)
2647 DEFAULT_WRAPPER_W_2W(Info_delete)
2648 DEFAULT_WRAPPER_W_2W(Info_dup)
2649 DEFAULT_WRAPPER_W_1W(Info_f2c)
2650 DEFAULT_WRAPPER_W_1W(Info_free)
2651 DEFAULT_WRAPPER_W_5W(Info_get)
2652 DEFAULT_WRAPPER_W_2W(Info_get_nkeys)
2653 DEFAULT_WRAPPER_W_3W(Info_get_nthkey)
2654 DEFAULT_WRAPPER_W_4W(Info_get_valuelen)
2655 DEFAULT_WRAPPER_W_3W(Info_set)
2656 /* DEFAULT_WRAPPER_W_2W(Init) */
2657 /* DEFAULT_WRAPPER_W_1W(Initialized) */
2658 DEFAULT_WRAPPER_W_4W(Init_thread)
2659 DEFAULT_WRAPPER_W_6W(Intercomm_create)
2660 DEFAULT_WRAPPER_W_3W(Intercomm_merge)
2661 /* DEFAULT_WRAPPER_W_5W(Iprobe) */
2662 /* DEFAULT_WRAPPER_W_7W(Irecv) */
2663 /* DEFAULT_WRAPPER_W_7W(Irsend) */
2664 /* DEFAULT_WRAPPER_W_7W(Isend) */
2665 /* DEFAULT_WRAPPER_W_7W(Issend) */
2666 DEFAULT_WRAPPER_W_1W(Is_thread_main)
2667 DEFAULT_WRAPPER_W_4W(Keyval_create)
2668 DEFAULT_WRAPPER_W_1W(Keyval_free)
2669 DEFAULT_WRAPPER_W_3W(Lookup_name)
2670 DEFAULT_WRAPPER_W_1W(Op_c2f)
2671 /* DEFAULT_WRAPPER_W_3W(Op_create) */
2672 DEFAULT_WRAPPER_W_2W(Open_port)
2673 DEFAULT_WRAPPER_W_1W(Op_f2c)
2674 DEFAULT_WRAPPER_W_1W(Op_free)
2675 DEFAULT_WRAPPER_W_7W(Pack_external)
2676 DEFAULT_WRAPPER_W_4W(Pack_external_size)
2677 /* DEFAULT_WRAPPER_W_7W(Pack) */
2678 DEFAULT_WRAPPER_W_4W(Pack_size)
2679 /* int MPI_Pcontrol(const int level, ...) */
2680 /* DEFAULT_WRAPPER_W_4W(Probe) */
2681 DEFAULT_WRAPPER_W_3W(Publish_name)
2682 DEFAULT_WRAPPER_W_8W(Put)
2683 DEFAULT_WRAPPER_W_1W(Query_thread)
2684 DEFAULT_WRAPPER_W_7W(Recv_init)
2685 /* DEFAULT_WRAPPER_W_7W(Recv) */
2686 /* DEFAULT_WRAPPER_W_7W(Reduce) */
2687 DEFAULT_WRAPPER_W_6W(Reduce_scatter)
2688 DEFAULT_WRAPPER_W_5W(Register_datarep)
2689 DEFAULT_WRAPPER_W_1W(Request_c2f)
2690 DEFAULT_WRAPPER_W_1W(Request_f2c)
2691 DEFAULT_WRAPPER_W_1W(Request_free)
2692 DEFAULT_WRAPPER_W_3W(Request_get_status)
2693 /* DEFAULT_WRAPPER_W_6W(Rsend) */
2694 DEFAULT_WRAPPER_W_7W(Rsend_init)
2695 DEFAULT_WRAPPER_W_6W(Scan)
2696 /* DEFAULT_WRAPPER_W_8W(Scatter) */
2697 DEFAULT_WRAPPER_W_9W(Scatterv)
2698 DEFAULT_WRAPPER_W_7W(Send_init)
2699 /* DEFAULT_WRAPPER_W_6W(Send) */
2700 /* DEFAULT_WRAPPER_W_12W(Sendrecv) */
2701 DEFAULT_WRAPPER_W_9W(Sendrecv_replace)
2702 DEFAULT_WRAPPER_W_7W(Ssend_init)
2703 /* DEFAULT_WRAPPER_W_6W(Ssend) */
2704 DEFAULT_WRAPPER_W_1W(Start)
2705 DEFAULT_WRAPPER_W_2W(Startall)
2706 DEFAULT_WRAPPER_W_2W(Status_c2f)
2707 DEFAULT_WRAPPER_W_2W(Status_f2c)
2708 DEFAULT_WRAPPER_W_2W(Status_set_cancelled)
2709 DEFAULT_WRAPPER_W_3W(Status_set_elements)
2710 /* DEFAULT_WRAPPER_W_4W(Testall) */
2711 DEFAULT_WRAPPER_W_5W(Testany)
2712 /* DEFAULT_WRAPPER_W_3W(Test) */
2713 DEFAULT_WRAPPER_W_2W(Test_cancelled)
2714 DEFAULT_WRAPPER_W_5W(Testsome)
2715 DEFAULT_WRAPPER_W_2W(Topo_test)
2716 DEFAULT_WRAPPER_W_1W(Type_c2f)
2717 /* DEFAULT_WRAPPER_W_1W(Type_commit) */
2718 DEFAULT_WRAPPER_W_3W(Type_contiguous)
2719 DEFAULT_WRAPPER_W_10W(Type_create_darray)
2720 DEFAULT_WRAPPER_W_3W(Type_create_f90_complex)
2721 DEFAULT_WRAPPER_W_2W(Type_create_f90_integer)
2722 DEFAULT_WRAPPER_W_3W(Type_create_f90_real)
2723 DEFAULT_WRAPPER_W_5W(Type_create_hindexed)
2724 DEFAULT_WRAPPER_W_5W(Type_create_hvector)
2725 DEFAULT_WRAPPER_W_4W(Type_create_keyval)
2726 DEFAULT_WRAPPER_W_5W(Type_create_indexed_block)
2727 DEFAULT_WRAPPER_W_5W(Type_create_struct)
2728 DEFAULT_WRAPPER_W_7W(Type_create_subarray)
2729 DEFAULT_WRAPPER_W_4W(Type_create_resized)
2730 DEFAULT_WRAPPER_W_2W(Type_delete_attr)
2731 DEFAULT_WRAPPER_W_2W(Type_dup)
2732 /* DEFAULT_WRAPPER_W_2W(Type_extent) */
2733 /* DEFAULT_WRAPPER_W_1W(Type_free) */
2734 DEFAULT_WRAPPER_W_1W(Type_free_keyval)
2735 DEFAULT_WRAPPER_W_1W(Type_f2c)
2736 DEFAULT_WRAPPER_W_4W(Type_get_attr)
2737 /* DEFAULT_WRAPPER_W_7W(Type_get_contents) */
2738 /* DEFAULT_WRAPPER_W_5W(Type_get_envelope) */
2739 DEFAULT_WRAPPER_W_3W(Type_get_extent)
2740 DEFAULT_WRAPPER_W_3W(Type_get_name)
2741 DEFAULT_WRAPPER_W_3W(Type_get_true_extent)
2742 DEFAULT_WRAPPER_W_5W(Type_hindexed)
2743 DEFAULT_WRAPPER_W_5W(Type_hvector)
2744 DEFAULT_WRAPPER_W_5W(Type_indexed)
2745 DEFAULT_WRAPPER_W_2W(Type_lb)
2746 DEFAULT_WRAPPER_W_3W(Type_match_size)
2747 DEFAULT_WRAPPER_W_3W(Type_set_attr)
2748 DEFAULT_WRAPPER_W_2W(Type_set_name)
2749 DEFAULT_WRAPPER_W_2W(Type_size)
2750 DEFAULT_WRAPPER_W_5W(Type_struct)
2751 DEFAULT_WRAPPER_W_2W(Type_ub)
2752 DEFAULT_WRAPPER_W_5W(Type_vector)
2753 /* DEFAULT_WRAPPER_W_7W(Unpack) */
2754 DEFAULT_WRAPPER_W_3W(Unpublish_name)
2755 DEFAULT_WRAPPER_W_7W(Unpack_external)
2756 /* DEFAULT_WRAPPER_W_3W(Waitall) */
2757 /* DEFAULT_WRAPPER_W_4W(Waitany) */
2758 /* DEFAULT_WRAPPER_W_2W(Wait) */
2759 DEFAULT_WRAPPER_W_5W(Waitsome)
2760 DEFAULT_WRAPPER_W_1W(Win_c2f)
2761 DEFAULT_WRAPPER_W_2W(Win_call_errhandler)
2762 DEFAULT_WRAPPER_W_1W(Win_complete)
2763 DEFAULT_WRAPPER_W_6W(Win_create)
2764 DEFAULT_WRAPPER_W_2W(Win_create_errhandler)
2765 DEFAULT_WRAPPER_W_4W(Win_create_keyval)
2766 DEFAULT_WRAPPER_W_2W(Win_delete_attr)
2767 DEFAULT_WRAPPER_W_1W(Win_f2c)
2768 DEFAULT_WRAPPER_W_2W(Win_fence)
2769 DEFAULT_WRAPPER_W_1W(Win_free)
2770 DEFAULT_WRAPPER_W_1W(Win_free_keyval)
2771 DEFAULT_WRAPPER_W_4W(Win_get_attr)
2772 DEFAULT_WRAPPER_W_2W(Win_get_errhandler)
2773 DEFAULT_WRAPPER_W_2W(Win_get_group)
2774 DEFAULT_WRAPPER_W_3W(Win_get_name)
2775 DEFAULT_WRAPPER_W_4W(Win_lock)
2776 DEFAULT_WRAPPER_W_3W(Win_post)
2777 DEFAULT_WRAPPER_W_3W(Win_set_attr)
2778 DEFAULT_WRAPPER_W_2W(Win_set_errhandler)
2779 DEFAULT_WRAPPER_W_2W(Win_set_name)
2780 DEFAULT_WRAPPER_W_3W(Win_start)
2781 DEFAULT_WRAPPER_W_2W(Win_test)
2782 DEFAULT_WRAPPER_W_2W(Win_unlock)
2783 DEFAULT_WRAPPER_W_1W(Win_wait)
2784 /* double MPI_Wtick(void) */
2785 /* double MPI_Wtime(void) */
2788 /*------------------------------------------------------------*/
2789 /*--- ---*/
2790 /*--- ---*/
2791 /*--- ---*/
2792 /*------------------------------------------------------------*/
2794 /*---------------------------------------------------------------*/
2795 /*--- end mpiwrap.c ---*/
2796 /*---------------------------------------------------------------*/