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