Add a bunch more wrappers and generally tidy up a bit.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@5739 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/auxprogs/mpiwrap.c b/auxprogs/mpiwrap.c
index c329fc0..71c57c0 100644
--- a/auxprogs/mpiwrap.c
+++ b/auxprogs/mpiwrap.c
@@ -59,11 +59,6 @@
 
 
 /*------------------------------------------------------------*/
-/*---                                                      ---*/
-/*------------------------------------------------------------*/
-
-
-/*------------------------------------------------------------*/
 /*--- includes                                             ---*/
 /*------------------------------------------------------------*/
 
@@ -130,7 +125,7 @@
 static Bool  opt_missing   = 0; /* 0:silent; 1:warn; 2:abort */
 static Bool  opt_help      = False;
 
-static inline void before ( char* fnname )
+static void before ( char* fnname )
 {
    /* This isn't thread-safe wrt 'done' (no locking).  It's not
       critical. */
@@ -438,7 +433,7 @@
    if (0)
       printf("walk_type %p\n", (void*)ty);
 
-   r = MPI_Type_get_envelope( ty, &n_ints, &n_addrs, &n_dtys, &tycon );
+   r = PMPI_Type_get_envelope( ty, &n_ints, &n_addrs, &n_dtys, &tycon );
    assert(r == MPI_SUCCESS);
 
    /* Handle the base cases fast(er/ish). */
@@ -500,8 +495,8 @@
       assert(dtys);
    }
 
-   r = MPI_Type_get_contents( ty, n_ints, n_addrs, n_dtys,
-                                  ints, addrs, dtys );
+   r = PMPI_Type_get_contents( ty, n_ints, n_addrs, n_dtys,
+                                   ints, addrs, dtys );
    assert(r == MPI_SUCCESS);
 
    switch (tycon) {
@@ -773,29 +768,18 @@
 /*--- Interface Standard, MPIF, Nov 15 2003" (the MPI 1.1  ---*/
 /*--- spec.  All unimplemented wrappers are listed at the  ---*/
 /*--- end of the file.  The list of function names is      ---*/
-/*--- taken from the headers of lampi-1.5.12.  Hopefully   ---*/
-/*--- it is a complete list of all the MPI 1.1 functions.  ---*/
+/*--- taken from the headers of Open MPI svn r9191.        ---*/
+/*--- Hopefully it is a complete list of all the MPI 2     ---*/
+/*--- functions.                                           ---*/
 /*---                                                      ---*/
 /*------------------------------------------------------------*/
 
 /* Handy abbreviation */
 #define WRAPPER_FOR(name) I_WRAP_FNNAME_U(name)
 
-/* Generates a wrapper which aborts when called. */
-#define UNIMPLEMENTED_WRAPPER(name)                            \
-   void I_WRAP_FNNAME_U(PMPI_##name) ( void )                  \
-   {                                                           \
-      fprintf(stderr, "%s %5d: UNIMPLEMENTED wrapper: "        \
-                              "PMPI_%s\n",                     \
-                      preamble, my_pid, #name);                \
-      fprintf(stderr, "%s %5d: exiting now.\n",                \
-                      preamble, my_pid);                       \
-      exit(1);                                                 \
-   }
-
 /* Generates (conceptually) a wrapper which does nothing.  In
    fact just generate no wrapper at all. */
-#define NO_OP_WRAPPER(name) /* */
+#define HAS_NO_WRAPPER(basename) /* */
 
 
 /*------------------------------------------------------------*/
@@ -804,20 +788,37 @@
 /*---                                                      ---*/
 /*------------------------------------------------------------*/
 
-/* --- Send --- */
+/* --- {,B,S,R}Send --- */
 /* pre: rd: (buf,count,datatype) */
-int WRAPPER_FOR(PMPI_Send)(void *buf, int count, MPI_Datatype datatype, 
-                           int dest, int tag, MPI_Comm comm)
+static
+int generic_Send(void *buf, int count, MPI_Datatype datatype, 
+                            int dest, int tag, MPI_Comm comm)
 {
    OrigFn fn;
    int    err;
    VALGRIND_GET_ORIG_FN(fn);
-   before("Send");
+   before("{,B,S,R}Send");
    check_readable(buf, count, datatype);
    CALL_FN_W_6W(err, fn, buf,count,datatype,dest,tag,comm);
-   after("Send", err);
+   after("{,B,S,R}Send", err);
    return err;
 }
+int WRAPPER_FOR(PMPI_Send)(void *buf, int count, MPI_Datatype datatype, 
+                           int dest, int tag, MPI_Comm comm) {
+   return generic_Send(buf,count,datatype, dest,tag,comm);
+}
+int WRAPPER_FOR(PMPI_Bsend)(void *buf, int count, MPI_Datatype datatype, 
+                            int dest, int tag, MPI_Comm comm) {
+   return generic_Send(buf,count,datatype, dest,tag,comm);
+}
+int WRAPPER_FOR(PMPI_Ssend)(void *buf, int count, MPI_Datatype datatype, 
+                            int dest, int tag, MPI_Comm comm) {
+   return generic_Send(buf,count,datatype, dest,tag,comm);
+}
+int WRAPPER_FOR(PMPI_Rsend)(void *buf, int count, MPI_Datatype datatype, 
+                            int dest, int tag, MPI_Comm comm) {
+   return generic_Send(buf,count,datatype, dest,tag,comm);
+}
 
 /* --- Recv --- */
 /* pre:  must be writable: (buf,count,datatype)
@@ -843,6 +844,23 @@
    return err;
 }
 
+/* --- Get_count --- */
+/* pre:  must be readable: *status
+   post: make defined: *count -- don't bother, libmpi will surely do this
+*/
+int WRAPPER_FOR(PMPI_Get_count)(MPI_Status* status, 
+                                MPI_Datatype ty, int* count )
+{
+   OrigFn fn;
+   int    err;
+   VALGRIND_GET_ORIG_FN(fn);
+   before("Get_count");
+   check_readable_untyped(status, sizeof(*status));
+   CALL_FN_W_WWW(err, fn, status,ty,count);
+   after("Get_count", err);
+   return err;
+}
+
 
 /*------------------------------------------------------------*/
 /*---                                                      ---*/
@@ -850,6 +868,28 @@
 /*---                                                      ---*/
 /*------------------------------------------------------------*/
 
+/* Maintain a table that makes it possible for the wrappers to
+   complete MPI_Irecv successfully.
+
+   The issue is that MPI_Irecv states the recv buffer and returns
+   immediately, giving a handle (MPI_Request) for the transaction.
+   Later the user will have to poll for completion with MPI_Wait etc,
+   and at that point these wrappers have to paint the recv buffer.
+   But the recv buffer details are not presented to MPI_Wait - only
+   the handle is.  We therefore have to use a shadow table
+   (sReqs{,_size,_used,_lock}) which associates uncompleted
+   MPI_Requests with the corresponding buffer address/count/type.
+
+   Only read requests are placed in the table, since there is no need
+   to do any buffer painting following completion of an Isend - all
+   the checks for that are done at the time Isend is called.
+
+   Care has to be take to remove completed requests from the table.
+
+   Access to the table is guarded by sReqs_lock so as to make it
+   thread-safe.
+*/
+
 typedef
    struct {
       Bool         inUse;
@@ -993,9 +1033,29 @@
                                 buf, count, (long)datatype, ix);
 }
 
+static 
+MPI_Request* clone_Request_array ( int count, MPI_Request* orig )
+{
+   MPI_Request* copy;
+   int i;
+   LOCK_SREQS;
+   if (count < 0) 
+      count = 0; /* Hmm.  Call Mulder and Scully. */
+   copy = malloc( count * sizeof(MPI_Request) );
+   if (copy == NULL) {
+      UNLOCK_SREQS;
+      barf("clone_Request_array: malloc failed");
+   }
+   for (i = 0; i < count; i++)
+      copy[i] = orig[i];
+   UNLOCK_SREQS;
+   return copy;
+}
+
 #undef LOCK_SREQS
 #undef UNLOCK_SREQS
 
+
 static void maybe_complete ( Bool         error_in_status,
                              MPI_Request  request_before,
                              MPI_Request  request_after,
@@ -1031,40 +1091,46 @@
 }
 
 
-static 
-MPI_Request* clone_Request_array ( int count, MPI_Request* orig )
-{
-   MPI_Request* copy;
-   int i;
-   if (count < 0) 
-      count = 0; /* Hmm.  Call Mulder and Scully. */
-   copy = malloc( count * sizeof(MPI_Request) );
-   if (copy == NULL)
-      barf("clone_Request_array: malloc failed");
-   for (i = 0; i < count; i++)
-      copy[i] = orig[i];
-   return copy;
-}
-
-
 /* --- Isend --- */
 /* rd: (buf,count,datatype) */
 /* wr: *request */
-int WRAPPER_FOR(PMPI_Isend)(void *buf, int count, MPI_Datatype datatype, 
-                            int dest, int tag, MPI_Comm comm, 
-                            MPI_Request* request)
+static
+int generic_Isend(void *buf, int count, MPI_Datatype datatype, 
+                             int dest, int tag, MPI_Comm comm, 
+                             MPI_Request* request)
 {
    OrigFn fn;
    int    err;
    VALGRIND_GET_ORIG_FN(fn);
-   before("Isend");
+   before("{,B,S,R}Isend");
    check_readable(buf, count, datatype);
    check_writable_untyped(request, sizeof(*request));
    CALL_FN_W_7W(err, fn, buf,count,datatype,dest,tag,comm,request);
    make_defined_if_success_untyped(err, request, sizeof(*request));
-   after("Isend", err);
+   after("{,B,S,R}Isend", err);
    return err;
 }
+int WRAPPER_FOR(PMPI_Isend)(void *buf, int count, MPI_Datatype datatype, 
+                            int dest, int tag, MPI_Comm comm, 
+                            MPI_Request* request) {
+   return generic_Isend(buf,count,datatype, dest,tag,comm, request);
+}
+int WRAPPER_FOR(PMPI_Ibsend)(void *buf, int count, MPI_Datatype datatype, 
+                             int dest, int tag, MPI_Comm comm, 
+                             MPI_Request* request) {
+   return generic_Isend(buf,count,datatype, dest,tag,comm, request);
+}
+int WRAPPER_FOR(PMPI_Issend)(void *buf, int count, MPI_Datatype datatype, 
+                             int dest, int tag, MPI_Comm comm, 
+                             MPI_Request* request) {
+   return generic_Isend(buf,count,datatype, dest,tag,comm, request);
+}
+int WRAPPER_FOR(PMPI_Irsend)(void *buf, int count, MPI_Datatype datatype, 
+                             int dest, int tag, MPI_Comm comm, 
+                             MPI_Request* request) {
+   return generic_Isend(buf,count,datatype, dest,tag,comm, request);
+}
+
 
 /* --- Irecv --- */
 /* pre:  must be writable: (buf,count,datatype), *request
@@ -1221,6 +1287,42 @@
 
 /* --- Address --- */
 /* Does this have anything worth checking? */
+HAS_NO_WRAPPER(Address)
+
+/* --- MPI 2 stuff --- */
+/* Type_extent, Type_get_contents and Type_get_envelope sometimes get
+   used intensively by the type walker (walk_type).  There's no reason
+   why they couldn't be properly wrapped if needed, but doing so slows
+   everything down, so don't bother until needed. */
+HAS_NO_WRAPPER(Type_extent)
+HAS_NO_WRAPPER(Type_get_contents)
+HAS_NO_WRAPPER(Type_get_envelope)
+
+/* --- Type_commit --- */
+int WRAPPER_FOR(PMPI_Type_commit)( MPI_Datatype* ty )
+{
+   OrigFn fn;
+   int    err;
+   VALGRIND_GET_ORIG_FN(fn);
+   before("Type_commit");
+   check_readable_untyped(ty, sizeof(*ty));
+   CALL_FN_W_W(err, fn, ty);
+   after("Type_commit", err);
+   return err;
+}
+
+/* --- Type_free --- */
+int WRAPPER_FOR(PMPI_Type_free)( MPI_Datatype* ty )
+{
+   OrigFn fn;
+   int    err;
+   VALGRIND_GET_ORIG_FN(fn);
+   before("Type_free");
+   check_readable_untyped(ty, sizeof(*ty));
+   CALL_FN_W_W(err, fn, ty);
+   after("Type_free", err);
+   return err;
+}
 
 
 /*------------------------------------------------------------*/
@@ -1384,6 +1486,46 @@
 /* Hardly seems worth wrapping Comm_rank and Comm_size, but
    since it's done now .. */
 
+/* --- Comm_create --- */
+/* Let normal memcheck tracking handle this. */
+int WRAPPER_FOR(PMPI_Comm_create)(MPI_Comm comm, MPI_Group group,
+                                  MPI_Comm* newcomm)
+{
+   OrigFn fn;
+   int    err;
+   VALGRIND_GET_ORIG_FN(fn);
+   before("Comm_create");
+   CALL_FN_W_WWW(err, fn, comm,group,newcomm);
+   after("Comm_create", err);
+   return err;
+}
+
+/* --- Comm_dup --- */
+/* Let normal memcheck tracking handle this. */
+int WRAPPER_FOR(PMPI_Comm_dup)(MPI_Comm comm, MPI_Comm* newcomm)
+{
+   OrigFn fn;
+   int    err;
+   VALGRIND_GET_ORIG_FN(fn);
+   before("Comm_dup");
+   CALL_FN_W_WW(err, fn, comm,newcomm);
+   after("Comm_dup", err);
+   return err;
+}
+
+/* --- Comm_free --- */
+/* Let normal memcheck tracking handle this. */
+int WRAPPER_FOR(PMPI_Comm_free)(MPI_Comm* comm)
+{
+   OrigFn fn;
+   int    err;
+   VALGRIND_GET_ORIG_FN(fn);
+   before("Comm_free");
+   CALL_FN_W_W(err, fn, comm);
+   after("Comm_free", err);
+   return err;
+}
+
 /* --- Comm_rank --- */
 /* wr: (rank, sizeof(*rank)) */
 int WRAPPER_FOR(PMPI_Comm_rank)(MPI_Comm comm, int *rank)
@@ -1429,7 +1571,8 @@
 /*------------------------------------------------------------*/
 
 /* --- Error_string --- */
-int WRAPPER_FOR(PMPI_Error_string)( int errorcode, char* string, int* resultlen )
+int WRAPPER_FOR(PMPI_Error_string)( int errorcode, char* string, 
+                                    int* resultlen )
 {
    OrigFn fn;
    int    err;
@@ -1499,6 +1642,7 @@
 /*---                                                      ---*/
 /*------------------------------------------------------------*/
 
+/* Boilerplate for default wrappers. */
 #define DEFAULT_WRAPPER_PREAMBLE(basename)                        \
       OrigFn fn;                                                  \
       UWord  res;                                                 \
@@ -1643,7 +1787,7 @@
 DEFAULT_WRAPPER_W_1W(Add_error_class)
 DEFAULT_WRAPPER_W_2W(Add_error_code)
 DEFAULT_WRAPPER_W_2W(Add_error_string)
-DEFAULT_WRAPPER_W_2W(Address)
+/* DEFAULT_WRAPPER_W_2W(Address) */
 DEFAULT_WRAPPER_W_7W(Allgather)
 DEFAULT_WRAPPER_W_8W(Allgatherv)
 DEFAULT_WRAPPER_W_3W(Alloc_mem)
@@ -1656,7 +1800,7 @@
 DEFAULT_WRAPPER_W_3W(Attr_put)
 DEFAULT_WRAPPER_W_1W(Barrier)
 /* DEFAULT_WRAPPER_W_5W(Bcast) */
-DEFAULT_WRAPPER_W_6W(Bsend)
+/* DEFAULT_WRAPPER_W_6W(Bsend) */
 DEFAULT_WRAPPER_W_7W(Bsend_init)
 DEFAULT_WRAPPER_W_2W(Buffer_attach)
 DEFAULT_WRAPPER_W_2W(Buffer_detach)
@@ -1677,13 +1821,13 @@
 DEFAULT_WRAPPER_W_5W(Comm_connect)
 DEFAULT_WRAPPER_W_2W(Comm_create_errhandler)
 DEFAULT_WRAPPER_W_4W(Comm_create_keyval)
-DEFAULT_WRAPPER_W_3W(Comm_create)
+/* DEFAULT_WRAPPER_W_3W(Comm_create) */
 DEFAULT_WRAPPER_W_2W(Comm_delete_attr)
 DEFAULT_WRAPPER_W_1W(Comm_disconnect)
-DEFAULT_WRAPPER_W_2W(Comm_dup)
+/* DEFAULT_WRAPPER_W_2W(Comm_dup) */
 DEFAULT_WRAPPER_W_1W(Comm_f2c)
 DEFAULT_WRAPPER_W_1W(Comm_free_keyval)
-DEFAULT_WRAPPER_W_1W(Comm_free)
+/* DEFAULT_WRAPPER_W_1W(Comm_free) */
 DEFAULT_WRAPPER_W_4W(Comm_get_attr)
 DEFAULT_WRAPPER_W_2W(Comm_get_errhandler)
 DEFAULT_WRAPPER_W_3W(Comm_get_name)
@@ -1774,7 +1918,7 @@
 /* DEFAULT_WRAPPER_W_8W(Gather) */
 DEFAULT_WRAPPER_W_9W(Gatherv)
 DEFAULT_WRAPPER_W_2W(Get_address)
-DEFAULT_WRAPPER_W_3W(Get_count)
+/* DEFAULT_WRAPPER_W_3W(Get_count) */
 DEFAULT_WRAPPER_W_3W(Get_elements)
 DEFAULT_WRAPPER_W_8W(Get)
 DEFAULT_WRAPPER_W_2W(Get_processor_name)
@@ -1801,7 +1945,7 @@
 DEFAULT_WRAPPER_W_2W(Group_size)
 DEFAULT_WRAPPER_W_5W(Group_translate_ranks)
 DEFAULT_WRAPPER_W_3W(Group_union)
-DEFAULT_WRAPPER_W_7W(Ibsend)
+/* DEFAULT_WRAPPER_W_7W(Ibsend) */
 DEFAULT_WRAPPER_W_1W(Info_c2f)
 DEFAULT_WRAPPER_W_1W(Info_create)
 DEFAULT_WRAPPER_W_2W(Info_delete)
@@ -1820,9 +1964,9 @@
 DEFAULT_WRAPPER_W_3W(Intercomm_merge)
 /* DEFAULT_WRAPPER_W_5W(Iprobe) */
 /* DEFAULT_WRAPPER_W_7W(Irecv) */
-DEFAULT_WRAPPER_W_7W(Irsend)
+/* DEFAULT_WRAPPER_W_7W(Irsend) */
 /* DEFAULT_WRAPPER_W_7W(Isend) */
-DEFAULT_WRAPPER_W_7W(Issend)
+/* DEFAULT_WRAPPER_W_7W(Issend) */
 DEFAULT_WRAPPER_W_1W(Is_thread_main)
 DEFAULT_WRAPPER_W_4W(Keyval_create)
 DEFAULT_WRAPPER_W_1W(Keyval_free)
@@ -1850,7 +1994,7 @@
 DEFAULT_WRAPPER_W_1W(Request_f2c)
 DEFAULT_WRAPPER_W_1W(Request_free)
 DEFAULT_WRAPPER_W_3W(Request_get_status)
-DEFAULT_WRAPPER_W_6W(Rsend)
+/* DEFAULT_WRAPPER_W_6W(Rsend) */
 DEFAULT_WRAPPER_W_7W(Rsend_init)
 DEFAULT_WRAPPER_W_6W(Scan)
 DEFAULT_WRAPPER_W_8W(Scatter)
@@ -1860,7 +2004,7 @@
 /* DEFAULT_WRAPPER_W_12W(Sendrecv) */
 DEFAULT_WRAPPER_W_9W(Sendrecv_replace)
 DEFAULT_WRAPPER_W_7W(Ssend_init)
-DEFAULT_WRAPPER_W_6W(Ssend)
+/* DEFAULT_WRAPPER_W_6W(Ssend) */
 DEFAULT_WRAPPER_W_1W(Start)
 DEFAULT_WRAPPER_W_2W(Startall)
 DEFAULT_WRAPPER_W_2W(Status_c2f)
@@ -1874,7 +2018,7 @@
 DEFAULT_WRAPPER_W_5W(Testsome)
 DEFAULT_WRAPPER_W_2W(Topo_test)
 DEFAULT_WRAPPER_W_1W(Type_c2f)
-DEFAULT_WRAPPER_W_1W(Type_commit)
+/* DEFAULT_WRAPPER_W_1W(Type_commit) */
 DEFAULT_WRAPPER_W_3W(Type_contiguous)
 DEFAULT_WRAPPER_W_10W(Type_create_darray)
 DEFAULT_WRAPPER_W_3W(Type_create_f90_complex)
@@ -1889,13 +2033,13 @@
 DEFAULT_WRAPPER_W_4W(Type_create_resized)
 DEFAULT_WRAPPER_W_2W(Type_delete_attr)
 DEFAULT_WRAPPER_W_2W(Type_dup)
-DEFAULT_WRAPPER_W_2W(Type_extent)
-DEFAULT_WRAPPER_W_1W(Type_free)
+/* DEFAULT_WRAPPER_W_2W(Type_extent) */
+/* DEFAULT_WRAPPER_W_1W(Type_free) */
 DEFAULT_WRAPPER_W_1W(Type_free_keyval)
 DEFAULT_WRAPPER_W_1W(Type_f2c)
 DEFAULT_WRAPPER_W_4W(Type_get_attr)
-DEFAULT_WRAPPER_W_7W(Type_get_contents)
-DEFAULT_WRAPPER_W_5W(Type_get_envelope)
+/* DEFAULT_WRAPPER_W_7W(Type_get_contents) */
+/* DEFAULT_WRAPPER_W_5W(Type_get_envelope) */
 DEFAULT_WRAPPER_W_3W(Type_get_extent)
 DEFAULT_WRAPPER_W_3W(Type_get_name)
 DEFAULT_WRAPPER_W_3W(Type_get_true_extent)