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