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