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