blob: 6369c986dcb9b1efb52d7e57e9248d911a5f892e [file] [log] [blame]
sewardjc3a47092006-02-18 23:13:33 +00001
2/*---------------------------------------------------------------*/
3/*--- ---*/
sewardj157a8c42006-03-12 00:35:42 +00004/*--- A library of wrappers for MPI 2 functions. ---*/
sewardjc3a47092006-02-18 23:13:33 +00005/*--- ---*/
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
sewardj4d474d02008-02-11 11:34:59 +000021 Copyright (C) 2006-2008 OpenWorks LLP. All rights reserved.
sewardjc3a47092006-02-18 23:13:33 +000022
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
61/*------------------------------------------------------------*/
sewardjc3a47092006-02-18 23:13:33 +000062/*--- includes ---*/
63/*------------------------------------------------------------*/
64
65#include <stdio.h>
66#include <assert.h>
67#include <unistd.h> /* getpid */
68#include <stdlib.h> /* exit */
69#include <string.h> /* strstr */
70#include <pthread.h> /* pthread_mutex_{lock,unlock} */
71
72/* Include Valgrind magic macros for writing wrappers. */
sewardj20974012006-02-19 14:05:28 +000073#include "../memcheck/memcheck.h"
sewardjc3a47092006-02-18 23:13:33 +000074
75
76/*------------------------------------------------------------*/
77/*--- Connect to MPI library ---*/
78/*------------------------------------------------------------*/
79
80/* Include headers for whatever MPI implementation the wrappers are to
sewardj80637752006-03-02 13:48:21 +000081 be used with. The configure system will tell us what the path to
82 the chosen MPI implementation is, via -I.. to the compiler. */
sewardjc3a47092006-02-18 23:13:33 +000083#include "mpi.h"
84
85/* Where are API symbols?
sewardjabbad832007-01-06 05:28:27 +000086 Open MPI lib/libmpi.so, soname = libmpi.so.0
87 Quadrics MPI lib/libmpi.so, soname = libmpi.so.0
88 MPICH libmpich.so.1.0, soname = libmpich.so.1.0
sewardjd465d992006-10-17 01:46:55 +000089 AIX: in /usr/lpp/ppe.poe/lib/libmpi_r.a(mpicore*_r.o)
sewardjabbad832007-01-06 05:28:27 +000090
91 For the non-AIX targets, a suitable soname to match with
92 is "libmpi*.so*".
sewardjc3a47092006-02-18 23:13:33 +000093*/
sewardjd465d992006-10-17 01:46:55 +000094#if defined(_AIX)
95# define I_WRAP_FNNAME_U(_name) \
96 I_WRAP_SONAME_FNNAME_ZU(libmpiZurZdaZLmpicoreZaZurZdoZR,_name)
97 /* Don't change this without also changing all the names in
98 libmpiwrap.exp. */
99#else
100# define I_WRAP_FNNAME_U(_name) \
sewardjabbad832007-01-06 05:28:27 +0000101 I_WRAP_SONAME_FNNAME_ZU(libmpiZaZdsoZa,_name)
sewardjc3a47092006-02-18 23:13:33 +0000102
sewardjd465d992006-10-17 01:46:55 +0000103#endif
sewardjc3a47092006-02-18 23:13:33 +0000104
sewardjcb7fa502006-11-24 15:18:15 +0000105
sewardjc3a47092006-02-18 23:13:33 +0000106/*------------------------------------------------------------*/
107/*--- Decls ---*/
108/*------------------------------------------------------------*/
109
110typedef unsigned char Bool;
111#define False ((Bool)0)
112#define True ((Bool)1)
113
sewardj63daa8a2006-03-09 19:08:20 +0000114/* Word, UWord are machine words - same size as a pointer. This is
115 checked at startup. The wrappers below use 'long' to mean a
116 machine word - this too is tested at startup. */
117typedef signed long Word;
118typedef unsigned long UWord;
119
sewardjcd8aaef2006-03-10 13:43:49 +0000120#if !defined(offsetof)
121# define offsetof(type,memb) ((int)&((type*)0)->memb)
122#endif
123
sewardjcb7fa502006-11-24 15:18:15 +0000124/* Find the size of long double image (not 'sizeof(long double)').
125 See comments in sizeofOneNamedTy. */
126static long sizeof_long_double_image ( void );
127
sewardjc3a47092006-02-18 23:13:33 +0000128
129/*------------------------------------------------------------*/
130/*--- Simple helpers ---*/
131/*------------------------------------------------------------*/
132
133/* ------ Helpers for debug printing ------ */
134
135/* constant */
136static const char* preamble = "valgrind MPI wrappers";
137
138/* established at startup */
sewardjd465d992006-10-17 01:46:55 +0000139static pid_t my_pid = -1;
140static char* options_str = NULL;
141static int opt_verbosity = 1;
142static Bool opt_missing = 0; /* 0:silent; 1:warn; 2:abort */
143static Bool opt_help = False;
144static Bool opt_initkludge = False;
sewardjc3a47092006-02-18 23:13:33 +0000145
sewardj9c969c32006-03-10 18:37:45 +0000146static void before ( char* fnname )
sewardjc3a47092006-02-18 23:13:33 +0000147{
148 /* This isn't thread-safe wrt 'done' (no locking). It's not
149 critical. */
150 static int done = 0;
151 if (done == 0) {
152 done = 1;
153 my_pid = getpid();
154 options_str = getenv("MPIWRAP_DEBUG");
sewardjec8b6142006-03-09 03:05:17 +0000155 if (options_str) {
sewardj63daa8a2006-03-09 19:08:20 +0000156 if (NULL != strstr(options_str, "warn"))
157 opt_missing = 1;
158 if (NULL != strstr(options_str, "strict"))
159 opt_missing = 2;
sewardjec8b6142006-03-09 03:05:17 +0000160 if (NULL != strstr(options_str, "verbose"))
161 opt_verbosity++;
162 if (NULL != strstr(options_str, "quiet"))
163 opt_verbosity--;
sewardj63daa8a2006-03-09 19:08:20 +0000164 if (NULL != strstr(options_str, "help"))
165 opt_help = True;
sewardjd465d992006-10-17 01:46:55 +0000166 if (NULL != strstr(options_str, "initkludge"))
167 opt_initkludge = True;
sewardjec8b6142006-03-09 03:05:17 +0000168 }
169 if (opt_verbosity > 0)
170 fprintf(stderr, "%s %5d: Active for pid %d\n",
171 preamble, my_pid, my_pid);
sewardj63daa8a2006-03-09 19:08:20 +0000172 /* Sanity check - that Word/UWord really are machine words. */
173 assert(sizeof(Word) == sizeof(void*));
174 assert(sizeof(UWord) == sizeof(void*));
sewardj301a50f2006-03-03 16:14:18 +0000175 /* Sanity check - char is byte-sized (else address calculations
176 in walk_type don't work. */
177 assert(sizeof(char) == 1);
sewardjc3a47092006-02-18 23:13:33 +0000178 if (opt_help) {
179 fprintf(stderr, "\n");
180 fprintf(stderr, "Valid options for the MPIWRAP_DEBUG environment"
181 " variable are:\n");
182 fprintf(stderr, "\n");
sewardjd465d992006-10-17 01:46:55 +0000183 fprintf(stderr, " quiet be silent except for errors\n");
184 fprintf(stderr, " verbose show wrapper entries/exits\n");
185 fprintf(stderr, " strict abort the program if a function"
sewardjc3a47092006-02-18 23:13:33 +0000186 " with no wrapper is used\n");
sewardjd465d992006-10-17 01:46:55 +0000187 fprintf(stderr, " warn give a warning if a function"
sewardj63daa8a2006-03-09 19:08:20 +0000188 " with no wrapper is used\n");
sewardjd465d992006-10-17 01:46:55 +0000189 fprintf(stderr, " help display this message, then exit\n");
190 fprintf(stderr, " initkludge debugging hack; do not use\n");
sewardjc3a47092006-02-18 23:13:33 +0000191 fprintf(stderr, "\n");
192 fprintf(stderr, "Multiple options are allowed, eg"
193 " MPIWRAP_DEBUG=strict,verbose\n");
sewardj63daa8a2006-03-09 19:08:20 +0000194 fprintf(stderr, "Note: 'warn' generates output even if 'quiet'"
195 " is also specified\n");
sewardjc3a47092006-02-18 23:13:33 +0000196 fprintf(stderr, "\n");
197 fprintf(stderr, "%s %5d: exiting now\n", preamble, my_pid );
198 exit(1);
199 }
sewardjec8b6142006-03-09 03:05:17 +0000200 if (opt_verbosity > 0)
201 fprintf(stderr,
202 "%s %5d: Try MPIWRAP_DEBUG=help for possible options\n",
203 preamble, my_pid);
sewardjc3a47092006-02-18 23:13:33 +0000204
205 }
sewardjec8b6142006-03-09 03:05:17 +0000206 if (opt_verbosity > 1)
sewardjc3a47092006-02-18 23:13:33 +0000207 fprintf(stderr, "%s %5d: enter PMPI_%s\n", preamble, my_pid, fnname );
208}
209
sewardjd465d992006-10-17 01:46:55 +0000210static __inline__ void after ( char* fnname, int err )
sewardjc3a47092006-02-18 23:13:33 +0000211{
sewardjec8b6142006-03-09 03:05:17 +0000212 if (opt_verbosity > 1)
sewardjc3a47092006-02-18 23:13:33 +0000213 fprintf(stderr, "%s %5d: exit PMPI_%s (err = %d)\n",
214 preamble, my_pid, fnname, err );
215}
216
217static void barf ( char* msg )
218{
219 fprintf(stderr, "%s %5d: fatal: %s\n", preamble, my_pid, msg);
220 fprintf(stderr, "%s %5d: exiting now\n", preamble, my_pid );
221 exit(1);
222}
223
sewardj533bfda2006-03-08 20:41:44 +0000224/* Half-hearted type-showing function (for debugging). */
225static void showTy ( FILE* f, MPI_Datatype ty )
226{
227 if (ty == MPI_DATATYPE_NULL) fprintf(f,"DATATYPE_NULL");
228 else if (ty == MPI_BYTE) fprintf(f,"BYTE");
229 else if (ty == MPI_PACKED) fprintf(f,"PACKED");
230 else if (ty == MPI_CHAR) fprintf(f,"CHAR");
231 else if (ty == MPI_SHORT) fprintf(f,"SHORT");
232 else if (ty == MPI_INT) fprintf(f,"INT");
233 else if (ty == MPI_LONG) fprintf(f,"LONG");
234 else if (ty == MPI_FLOAT) fprintf(f,"FLOAT");
235 else if (ty == MPI_DOUBLE) fprintf(f,"DOUBLE");
236 else if (ty == MPI_LONG_DOUBLE) fprintf(f,"LONG_DOUBLE");
237 else if (ty == MPI_UNSIGNED_CHAR) fprintf(f,"UNSIGNED_CHAR");
238 else if (ty == MPI_UNSIGNED_SHORT) fprintf(f,"UNSIGNED_SHORT");
239 else if (ty == MPI_UNSIGNED_LONG) fprintf(f,"UNSIGNED_LONG");
240 else if (ty == MPI_UNSIGNED) fprintf(f,"UNSIGNED");
241 else if (ty == MPI_FLOAT_INT) fprintf(f,"FLOAT_INT");
242 else if (ty == MPI_DOUBLE_INT) fprintf(f,"DOUBLE_INT");
243 else if (ty == MPI_LONG_DOUBLE_INT) fprintf(f,"LONG_DOUBLE_INT");
244 else if (ty == MPI_LONG_INT) fprintf(f,"LONG_INT");
245 else if (ty == MPI_SHORT_INT) fprintf(f,"SHORT_INT");
246 else if (ty == MPI_2INT) fprintf(f,"2INT");
247 else if (ty == MPI_UB) fprintf(f,"UB");
248 else if (ty == MPI_LB) fprintf(f,"LB");
249# if defined(MPI_WCHAR)
250 else if (ty == MPI_WCHAR) fprintf(f,"WCHAR");
251# endif
252 else if (ty == MPI_LONG_LONG_INT) fprintf(f,"LONG_LONG_INT");
sewardj87f75f72006-03-12 16:44:05 +0000253# if defined(MPI_LONG_LONG)
sewardj533bfda2006-03-08 20:41:44 +0000254 else if (ty == MPI_LONG_LONG) fprintf(f,"LONG_LONG");
sewardj87f75f72006-03-12 16:44:05 +0000255# endif
sewardj582031b2006-04-13 22:03:16 +0000256# if defined(MPI_UNSIGNED_LONG_LONG)
sewardj533bfda2006-03-08 20:41:44 +0000257 else if (ty == MPI_UNSIGNED_LONG_LONG) fprintf(f,"UNSIGNED_LONG_LONG");
sewardj582031b2006-04-13 22:03:16 +0000258# endif
sewardj443aa372007-04-05 00:35:20 +0000259# if defined(MPI_REAL8)
260 else if (ty == MPI_REAL8) fprintf(f, "REAL8");
261# endif
262# if defined(MPI_REAL4)
263 else if (ty == MPI_REAL4) fprintf(f, "REAL4");
264# endif
sewardja7802962007-06-05 19:51:35 +0000265# if defined(MPI_REAL)
266 else if (ty == MPI_REAL) fprintf(f, "REAL");
267# endif
sewardj443aa372007-04-05 00:35:20 +0000268# if defined(MPI_INTEGER8)
269 else if (ty == MPI_INTEGER8) fprintf(f, "INTEGER8");
270# endif
271# if defined(MPI_INTEGER4)
272 else if (ty == MPI_INTEGER4) fprintf(f, "INTEGER4");
273# endif
sewardja7802962007-06-05 19:51:35 +0000274# if defined(MPI_INTEGER)
275 else if (ty == MPI_INTEGER) fprintf(f, "INTEGER");
276# endif
sewardja8c487f2007-06-04 21:14:36 +0000277# if defined(MPI_DOUBLE_PRECISION)
278 else if (ty == MPI_DOUBLE_PRECISION) fprintf(f, "DOUBLE_PRECISION");
279# endif
sewardja7802962007-06-05 19:51:35 +0000280# if defined(MPI_COMPLEX)
281 else if (ty == MPI_COMPLEX) fprintf(f, "COMPLEX");
282# endif
283# if defined(MPI_DOUBLE_COMPLEX)
284 else if (ty == MPI_DOUBLE_COMPLEX) fprintf(f, "DOUBLE_COMPLEX");
285# endif
286# if defined(MPI_LOGICAL)
287 else if (ty == MPI_LOGICAL) fprintf(f, "LOGICAL");
288# endif
289# if defined(MPI_2INTEGER)
290 else if (ty == MPI_2INTEGER) fprintf(f, "2INTEGER");
291# endif
292# if defined(MPI_2COMPLEX)
293 else if (ty == MPI_2COMPLEX) fprintf(f, "2COMPLEX");
294# endif
295# if defined(MPI_2DOUBLE_COMPLEX)
296 else if (ty == MPI_2DOUBLE_COMPLEX) fprintf(f, "2DOUBLE_COMPLEX");
297# endif
298# if defined(MPI_2REAL)
299 else if (ty == MPI_2REAL) fprintf(f, "2REAL");
300# endif
301# if defined(MPI_2DOUBLE_PRECISION)
302 else if (ty == MPI_2DOUBLE_PRECISION) fprintf(f, "2DOUBLE_PRECISION");
303# endif
304# if defined(MPI_CHARACTER)
305 else if (ty == MPI_CHARACTER) fprintf(f, "CHARACTER");
306# endif
sewardj533bfda2006-03-08 20:41:44 +0000307 else fprintf(f,"showTy:???");
308}
309
310static void showCombiner ( FILE* f, int combiner )
311{
312 switch (combiner) {
313 case MPI_COMBINER_NAMED: fprintf(f, "NAMED"); break;
sewardjcc8c3992006-03-08 21:40:34 +0000314#if defined(MPI_COMBINER_DUP)
sewardj533bfda2006-03-08 20:41:44 +0000315 case MPI_COMBINER_DUP: fprintf(f, "DUP"); break;
sewardjcc8c3992006-03-08 21:40:34 +0000316# endif
sewardj533bfda2006-03-08 20:41:44 +0000317 case MPI_COMBINER_CONTIGUOUS: fprintf(f, "CONTIGUOUS"); break;
318 case MPI_COMBINER_VECTOR: fprintf(f, "VECTOR"); break;
sewardjcc8c3992006-03-08 21:40:34 +0000319#if defined(MPI_COMBINER_HVECTOR_INTEGER)
sewardj533bfda2006-03-08 20:41:44 +0000320 case MPI_COMBINER_HVECTOR_INTEGER: fprintf(f, "HVECTOR_INTEGER"); break;
sewardjcc8c3992006-03-08 21:40:34 +0000321# endif
sewardj533bfda2006-03-08 20:41:44 +0000322 case MPI_COMBINER_HVECTOR: fprintf(f, "HVECTOR"); break;
323 case MPI_COMBINER_INDEXED: fprintf(f, "INDEXED"); break;
sewardjcc8c3992006-03-08 21:40:34 +0000324#if defined(MPI_COMBINER_HINDEXED_INTEGER)
sewardj533bfda2006-03-08 20:41:44 +0000325 case MPI_COMBINER_HINDEXED_INTEGER: fprintf(f, "HINDEXED_INTEGER"); break;
sewardjcc8c3992006-03-08 21:40:34 +0000326# endif
sewardj533bfda2006-03-08 20:41:44 +0000327 case MPI_COMBINER_HINDEXED: fprintf(f, "HINDEXED"); break;
sewardjcc8c3992006-03-08 21:40:34 +0000328#if defined(MPI_COMBINER_INDEXED_BLOCK)
sewardj533bfda2006-03-08 20:41:44 +0000329 case MPI_COMBINER_INDEXED_BLOCK: fprintf(f, "INDEXED_BLOCK"); break;
sewardjcc8c3992006-03-08 21:40:34 +0000330# endif
331#if defined(MPI_COMBINER_STRUCT_INTEGER)
sewardj533bfda2006-03-08 20:41:44 +0000332 case MPI_COMBINER_STRUCT_INTEGER: fprintf(f, "STRUCT_INTEGER"); break;
sewardjcc8c3992006-03-08 21:40:34 +0000333# endif
sewardj533bfda2006-03-08 20:41:44 +0000334 case MPI_COMBINER_STRUCT: fprintf(f, "STRUCT"); break;
sewardjcc8c3992006-03-08 21:40:34 +0000335#if defined(MPI_COMBINER_SUBARRAY)
sewardj533bfda2006-03-08 20:41:44 +0000336 case MPI_COMBINER_SUBARRAY: fprintf(f, "SUBARRAY"); break;
sewardjcc8c3992006-03-08 21:40:34 +0000337# endif
338#if defined(MPI_COMBINER_DARRAY)
sewardj533bfda2006-03-08 20:41:44 +0000339 case MPI_COMBINER_DARRAY: fprintf(f, "DARRAY"); break;
sewardjcc8c3992006-03-08 21:40:34 +0000340# endif
341#if defined(MPI_COMBINER_F90_REAL)
sewardj533bfda2006-03-08 20:41:44 +0000342 case MPI_COMBINER_F90_REAL: fprintf(f, "F90_REAL"); break;
sewardjcc8c3992006-03-08 21:40:34 +0000343# endif
344#if defined(MPI_COMBINER_F90_COMPLEX)
sewardj533bfda2006-03-08 20:41:44 +0000345 case MPI_COMBINER_F90_COMPLEX: fprintf(f, "F90_COMPLEX"); break;
sewardjcc8c3992006-03-08 21:40:34 +0000346# endif
347#if defined(MPI_COMBINER_F90_INTEGER)
sewardj533bfda2006-03-08 20:41:44 +0000348 case MPI_COMBINER_F90_INTEGER: fprintf(f, "F90_INTEGER"); break;
sewardjcc8c3992006-03-08 21:40:34 +0000349# endif
350#if defined(MPI_COMBINER_RESIZED)
sewardj533bfda2006-03-08 20:41:44 +0000351 case MPI_COMBINER_RESIZED: fprintf(f, "RESIZED"); break;
sewardjcc8c3992006-03-08 21:40:34 +0000352# endif
sewardj533bfda2006-03-08 20:41:44 +0000353 default: fprintf(f, "showCombiner:??"); break;
354 }
355}
356
357
sewardjc3a47092006-02-18 23:13:33 +0000358/* ------ Get useful bits of info ------ */
359
360/* Note, PMPI_Comm_rank/size are themselves wrapped. Should work
361 fine. */
362
sewardjd465d992006-10-17 01:46:55 +0000363static __inline__ int comm_rank ( MPI_Comm comm )
sewardjc3a47092006-02-18 23:13:33 +0000364{
365 int err, r;
366 err = PMPI_Comm_rank(comm, &r);
367 return err ? 0/*arbitrary*/ : r;
368}
369
sewardjd465d992006-10-17 01:46:55 +0000370static __inline__ int comm_size ( MPI_Comm comm )
sewardjc3a47092006-02-18 23:13:33 +0000371{
372 int err, r;
373 err = PMPI_Comm_size(comm, &r);
374 return err ? 0/*arbitrary*/ : r;
375}
376
sewardjd465d992006-10-17 01:46:55 +0000377static __inline__ Bool count_from_Status( /*OUT*/int* recv_count,
sewardjc3a47092006-02-18 23:13:33 +0000378 MPI_Datatype datatype,
379 MPI_Status* status)
380{
381 int n;
382 int err = PMPI_Get_count(status, datatype, &n);
383 if (err == MPI_SUCCESS) {
384 *recv_count = n;
385 return True;
386 } else {
387 return False;
388 }
389}
390
391/* It's critical that we can do equality on MPI_Requests.
392 Unfortunately these are opaque objects to us (handles, in the
393 parlance of the MPI 1.1 spec). Fortunately Sec 2.4.1 ("Opaque
394 Objects") specifies that "In C, [...] These [handles] should be
395 types that support assignment and equality operations." Hence the
396 following function should compile for any compliant definition of
397 MPI_Request. */
sewardjd465d992006-10-17 01:46:55 +0000398static __inline__
sewardjc3a47092006-02-18 23:13:33 +0000399Bool eq_MPI_Request ( MPI_Request r1, MPI_Request r2 )
400{
401 return r1 == r2;
402}
403
sewardj8717d1a2006-03-04 02:31:52 +0000404/* Get the 'extent' of a type. Note, as per the MPI spec this
405 includes whatever padding would be required when using 'ty' in an
406 array. */
sewardj301a50f2006-03-03 16:14:18 +0000407static long extentOfTy ( MPI_Datatype ty )
408{
409 int r;
410 MPI_Aint n;
411 r = PMPI_Type_extent(ty, &n);
412 assert(r == MPI_SUCCESS);
413 return (long)n;
414}
415
sewardjcd8aaef2006-03-10 13:43:49 +0000416/* Free up *ty, if it is safe to do so */
sewardj301a50f2006-03-03 16:14:18 +0000417static void maybeFreeTy ( MPI_Datatype* ty )
418{
419 int r, n_ints, n_addrs, n_dtys, tycon;
420
421 r = PMPI_Type_get_envelope( *ty, &n_ints, &n_addrs, &n_dtys, &tycon );
422 assert(r == MPI_SUCCESS);
423
sewardjcd8aaef2006-03-10 13:43:49 +0000424 /* can't free named types */
425 if (tycon == MPI_COMBINER_NAMED)
426 return;
427
428 /* some kinds of structs are predefined so we can't free them
429 either. */
430 if (*ty == MPI_FLOAT_INT || *ty == MPI_DOUBLE_INT
431 || *ty == MPI_LONG_INT || *ty == MPI_2INT
432 || *ty == MPI_SHORT_INT || *ty == MPI_LONG_DOUBLE_INT)
433 return;
434
435 /* Looks OK - free it. */
436 if (0) {
437 /* show me what you're about to free .. */
438 fprintf(stderr, "freeing combiner ");
439 showCombiner(stderr,tycon);
440 fprintf(stderr, " ty= ");
441 showTy(stderr,*ty);
442 fprintf(stderr,"\n");
sewardj301a50f2006-03-03 16:14:18 +0000443 }
sewardjcd8aaef2006-03-10 13:43:49 +0000444 r = PMPI_Type_free(ty);
445 assert(r == MPI_SUCCESS);
sewardj301a50f2006-03-03 16:14:18 +0000446}
447
sewardj8717d1a2006-03-04 02:31:52 +0000448/* How big is a "named" (base) type? Returns 0 if not known. Note.
449 There is a subtlety, which is that this is required to return the
450 exact size of one item of the type, NOT the size of it when padded
451 suitably to make an array of them. In particular that's why the
sewardjcb7fa502006-11-24 15:18:15 +0000452 size of LONG_DOUBLE is computed by looking at the result of doing a
453 long double store, rather than just asking what is the sizeof(long
454 double).
455
456 For LONG_DOUBLE on x86-linux and amd64-linux my impression is that
457 the right answer is 10 even though sizeof(long double) says 12 and
458 16 respectively. On ppc32-linux it appears to be 16.
sewardj3f55c9c2006-03-12 13:37:19 +0000459
460 Ref: MPI 1.1 doc p18 */
sewardj8717d1a2006-03-04 02:31:52 +0000461static long sizeofOneNamedTy ( MPI_Datatype ty )
sewardj1646f752006-03-03 21:03:10 +0000462{
sewardjcd8aaef2006-03-10 13:43:49 +0000463 if (ty == MPI_CHAR) return sizeof(signed char);
464 if (ty == MPI_SHORT) return sizeof(signed short int);
465 if (ty == MPI_INT) return sizeof(signed int);
466 if (ty == MPI_LONG) return sizeof(signed long int);
sewardjc0526f72006-03-08 03:54:37 +0000467 if (ty == MPI_UNSIGNED_CHAR) return sizeof(unsigned char);
468 if (ty == MPI_UNSIGNED_SHORT) return sizeof(unsigned short int);
sewardjcd8aaef2006-03-10 13:43:49 +0000469 if (ty == MPI_UNSIGNED) return sizeof(unsigned int);
470 if (ty == MPI_UNSIGNED_LONG) return sizeof(unsigned long int);
471 if (ty == MPI_FLOAT) return sizeof(float);
472 if (ty == MPI_DOUBLE) return sizeof(double);
sewardjcd8aaef2006-03-10 13:43:49 +0000473 if (ty == MPI_BYTE) return 1;
sewardjcb7fa502006-11-24 15:18:15 +0000474 if (ty == MPI_LONG_DOUBLE) return sizeof_long_double_image();
sewardjee346592007-02-08 12:05:03 +0000475 if (ty == MPI_PACKED) return 1;
sewardja7802962007-06-05 19:51:35 +0000476 if (ty == MPI_LONG_LONG_INT) return sizeof(signed long long int);
sewardjcb7fa502006-11-24 15:18:15 +0000477
sewardj443aa372007-04-05 00:35:20 +0000478# if defined(MPI_REAL8)
sewardja7802962007-06-05 19:51:35 +0000479 if (ty == MPI_REAL8) return 8; /* MPI2 spec */;
sewardj443aa372007-04-05 00:35:20 +0000480# endif
481# if defined(MPI_REAL4)
sewardja7802962007-06-05 19:51:35 +0000482 if (ty == MPI_REAL4) return 4; /* MPI2 spec */;
483# endif
484# if defined(MPI_REAL)
485 if (ty == MPI_REAL) return 4; /* MPI2 spec */;
sewardj443aa372007-04-05 00:35:20 +0000486# endif
487# if defined(MPI_INTEGER8)
sewardja7802962007-06-05 19:51:35 +0000488 if (ty == MPI_INTEGER8) return 8; /* MPI2 spec */;
sewardj443aa372007-04-05 00:35:20 +0000489# endif
490# if defined(MPI_INTEGER4)
sewardja7802962007-06-05 19:51:35 +0000491 if (ty == MPI_INTEGER4) return 4; /* MPI2 spec */;
492# endif
493# if defined(MPI_INTEGER)
494 if (ty == MPI_INTEGER) return 4; /* MPI2 spec */;
sewardj443aa372007-04-05 00:35:20 +0000495# endif
sewardja8c487f2007-06-04 21:14:36 +0000496# if defined(MPI_DOUBLE_PRECISION)
sewardja7802962007-06-05 19:51:35 +0000497 if (ty == MPI_DOUBLE_PRECISION) return 8; /* MPI2 spec */;
sewardja8c487f2007-06-04 21:14:36 +0000498# endif
sewardj443aa372007-04-05 00:35:20 +0000499
sewardjcd8aaef2006-03-10 13:43:49 +0000500 /* new in MPI2: */
sewardj493743f2006-03-10 22:17:57 +0000501# if defined(MPI_WCHAR)
sewardja7802962007-06-05 19:51:35 +0000502 if (ty == MPI_WCHAR) return 2; /* MPI2 spec */;
sewardj493743f2006-03-10 22:17:57 +0000503# endif
504# if defined(MPI_SIGNED_CHAR)
sewardja7802962007-06-05 19:51:35 +0000505 if (ty == MPI_SIGNED_CHAR) return 1; /* MPI2 spec */;
sewardj493743f2006-03-10 22:17:57 +0000506# endif
sewardj582031b2006-04-13 22:03:16 +0000507# if defined(MPI_UNSIGNED_LONG_LONG)
sewardja7802962007-06-05 19:51:35 +0000508 if (ty == MPI_UNSIGNED_LONG_LONG) return 8; /* MPI2 spec */;
sewardj582031b2006-04-13 22:03:16 +0000509# endif
sewardja7802962007-06-05 19:51:35 +0000510# if defined(MPI_COMPLEX)
511 if (ty == MPI_COMPLEX) return 2 * 4; /* MPI2 spec */
512# endif
513# if defined(MPI_DOUBLE_COMPLEX)
514 if (ty == MPI_DOUBLE_COMPLEX) return 2 * 8; /* MPI2 spec */
515# endif
516# if defined(MPI_LOGICAL)
517 if (ty == MPI_LOGICAL) return 4; /* MPI2 spec */
518# endif
519# if defined(MPI_2INTEGER)
520 if (ty == MPI_2INTEGER) return 2 * 4; /* undocumented in MPI2 */
521# endif
522# if defined(MPI_2COMPLEX)
523 if (ty == MPI_2COMPLEX) return 2 * 8; /* undocumented in MPI2 */
524# endif
525# if defined(MPI_2DOUBLE_COMPLEX)
526 /* 32: this is how openmpi-1.2.2 behaves on x86-linux, but I have
527 really no idea if this is right. */
528 if (ty == MPI_2DOUBLE_COMPLEX) return 32; /* undocumented in MPI2 */
529# endif
530# if defined(MPI_2REAL)
531 if (ty == MPI_2REAL) return 2 * 4; /* undocumented in MPI2 */
532# endif
533# if defined(MPI_2DOUBLE_PRECISION)
534 if (ty == MPI_2DOUBLE_PRECISION) return 2 * 8; /* undocumented in MPI2 */
535# endif
536# if defined(MPI_CHARACTER)
537 if (ty == MPI_CHARACTER) return 1; /* MPI2 spec */
538# endif
539
sewardjcd8aaef2006-03-10 13:43:49 +0000540 /* Note: the following are named structs, not named basic types,
541 and so are not handled here:
542 FLOAT_INT DOUBLE_INT LONG_INT 2INT SHORT_INT LONG_DOUBLE_INT
543 My guess is they are probably for doing max-w-index style
544 reductions, the INT carrying the index of the max/min and the
545 other type its actual value.
546 */
sewardj1646f752006-03-03 21:03:10 +0000547 return 0;
548}
549
sewardj301a50f2006-03-03 16:14:18 +0000550
sewardjcb7fa502006-11-24 15:18:15 +0000551/* Find the size of long double image (not 'sizeof(long double)').
552 See comments in sizeofOneNamedTy.
553*/
554static long sizeof_long_double_image ( void )
555{
556 long i;
557 unsigned char* p;
558 static long cached_result = 0;
559
560 /* Hopefully we have it already. */
561 if (cached_result != 0) {
562 assert(cached_result == 10 || cached_result == 16 || cached_result == 8);
563 return cached_result;
564 }
565
566 /* No? Then we'll have to compute it. This isn't thread-safe but
567 it doesn't really matter since all races to compute it should
568 produce the same answer. */
569 p = malloc(64);
570 assert(p);
571 for (i = 0; i < 64; i++)
572 p[i] = 0x55;
573
574 /* Write a value which isn't known at compile time and therefore
575 must come out of a register. If we just store a constant here,
576 some compilers write more data than a store from a machine
577 register would. Therefore we have to force a store from a
578 machine register by storing a value which isn't known at compile
579 time. Since getpid() will return a value < 1 million, turn it
580 into a zero by dividing by 1e+30. */
581 *(long double*)(&p[16]) = (long double)(1.0e-30 * (double)getpid());
582
583 for (i = 0; i < 16; i++) {
584 assert(p[i] == 0x55);
585 assert(p[i+48] == 0x55);
586 }
587 for (i = 16; i <= 48; i++) {
588 if (p[i] == 0x55)
589 break;
590 }
591
592 assert(i < 48);
593 assert(i > 16);
594 free(p);
595 cached_result = i - 16;
596
597 if (0)
598 printf("sizeof_long_double_image: computed %d\n", (int)cached_result);
599
600 assert(cached_result == 10 || cached_result == 16 || cached_result == 8);
601 return cached_result;
602}
603
604
sewardj301a50f2006-03-03 16:14:18 +0000605/*------------------------------------------------------------*/
606/*--- Unpicking datatypes ---*/
607/*------------------------------------------------------------*/
608
sewardjcf375342007-01-16 05:35:46 +0000609static __inline__
sewardj301a50f2006-03-03 16:14:18 +0000610void walk_type_array ( void(*f)(void*,long), char* base,
611 MPI_Datatype ty, long count );
612
613
614/* Walk over all fragments of the object of type 'ty' with base
615 address 'base', and apply 'f' to the start/length of each
616 contiguous fragment. */
617static
618void walk_type ( void(*f)(void*,long), char* base, MPI_Datatype ty )
619{
620 int r, n_ints, n_addrs, n_dtys, tycon;
sewardj1646f752006-03-03 21:03:10 +0000621 long ex, i;
sewardj301a50f2006-03-03 16:14:18 +0000622 int* ints = NULL;
623 MPI_Aint* addrs = NULL;
624 MPI_Datatype* dtys = NULL;
sewardj301a50f2006-03-03 16:14:18 +0000625
sewardj443aa372007-04-05 00:35:20 +0000626 /* Stuff for limiting how much complaining text it spews out */
627 static int complaints = 3;
628 static int last_complained_about_tycon = -987654321; /* presumably bogus */
629
sewardj1646f752006-03-03 21:03:10 +0000630 if (0)
sewardjabbad832007-01-06 05:28:27 +0000631 printf("walk_type %p\n", (void*)(unsigned long)ty);
sewardj301a50f2006-03-03 16:14:18 +0000632
sewardj9c969c32006-03-10 18:37:45 +0000633 r = PMPI_Type_get_envelope( ty, &n_ints, &n_addrs, &n_dtys, &tycon );
sewardj301a50f2006-03-03 16:14:18 +0000634 assert(r == MPI_SUCCESS);
635
636 /* Handle the base cases fast(er/ish). */
637 if (tycon == MPI_COMBINER_NAMED) {
sewardj8717d1a2006-03-04 02:31:52 +0000638 long sz = sizeofOneNamedTy(ty);
sewardjcd8aaef2006-03-10 13:43:49 +0000639 if (sz > 0) {
640 f(base, sz);
641 return;
642 }
643 /* Hmm. Perhaps it's a named struct? Unfortunately we can't
644 take them to bits so we have to do a really ugly hack, which
645 makes assumptions about how the MPI implementation has laid
sewardj558cc222006-03-10 14:51:19 +0000646 out these types. At least Open MPI 1.0.1 appears to put
sewardja7802962007-06-05 19:51:35 +0000647 the 'val' field first. MPICH2 agrees.
sewardjcd8aaef2006-03-10 13:43:49 +0000648 */
sewardj443aa372007-04-05 00:35:20 +0000649 if (ty == MPI_2INT) {
650 typedef struct { int val; int loc; } Ty;
651 f(base + offsetof(Ty,val), sizeof(int));
652 f(base + offsetof(Ty,loc), sizeof(int));
653 return;
654 }
sewardjcd8aaef2006-03-10 13:43:49 +0000655 if (ty == MPI_LONG_INT) {
sewardj558cc222006-03-10 14:51:19 +0000656 typedef struct { long val; int loc; } Ty;
657 f(base + offsetof(Ty,val), sizeof(long));
658 f(base + offsetof(Ty,loc), sizeof(int));
659 return;
660 }
661 if (ty == MPI_DOUBLE_INT) {
662 typedef struct { double val; int loc; } Ty;
663 f(base + offsetof(Ty,val), sizeof(double));
664 f(base + offsetof(Ty,loc), sizeof(int));
665 return;
666 }
667 if (ty == MPI_SHORT_INT) {
668 typedef struct { short val; int loc; } Ty;
669 f(base + offsetof(Ty,val), sizeof(short));
sewardjcd8aaef2006-03-10 13:43:49 +0000670 f(base + offsetof(Ty,loc), sizeof(int));
671 return;
672 }
sewardja7802962007-06-05 19:51:35 +0000673 if (ty == MPI_FLOAT_INT) {
674 typedef struct { float val; int loc; } Ty;
675 f(base + offsetof(Ty,val), sizeof(float));
676 f(base + offsetof(Ty,loc), sizeof(int));
677 return;
678 }
679 if (ty == MPI_LONG_DOUBLE_INT) {
680 typedef struct { long double val; int loc; } Ty;
681 f(base + offsetof(Ty,val), sizeof_long_double_image());
682 f(base + offsetof(Ty,loc), sizeof(int));
683 return;
684 }
sewardj493743f2006-03-10 22:17:57 +0000685 if (ty == MPI_LB || ty == MPI_UB)
686 return; /* have zero size, so nothing needs to be done */
sewardjcd8aaef2006-03-10 13:43:49 +0000687 goto unhandled;
sewardj301a50f2006-03-03 16:14:18 +0000688 /*NOTREACHED*/
689 }
690
sewardj1646f752006-03-03 21:03:10 +0000691 if (0) {
sewardj301a50f2006-03-03 16:14:18 +0000692 ex = extentOfTy(ty);
sewardj157a8c42006-03-12 00:35:42 +0000693 printf("tycon 0x%llx %d %d %d (ext %d)\n",
694 (unsigned long long int)tycon,
695 n_ints, n_addrs, n_dtys, (int)ex );
sewardj301a50f2006-03-03 16:14:18 +0000696 }
697
698 /* Now safe to do MPI_Type_get_contents */
699 assert(n_ints >= 0);
700 assert(n_addrs >= 0);
701 assert(n_dtys >= 0);
702
703 if (n_ints > 0) {
704 ints = malloc(n_ints * sizeof(int));
705 assert(ints);
706 }
707 if (n_addrs > 0) {
708 addrs = malloc(n_addrs * sizeof(MPI_Aint));
709 assert(addrs);
710 }
711 if (n_dtys > 0) {
712 dtys = malloc(n_dtys * sizeof(MPI_Datatype));
713 assert(dtys);
714 }
715
sewardj9c969c32006-03-10 18:37:45 +0000716 r = PMPI_Type_get_contents( ty, n_ints, n_addrs, n_dtys,
717 ints, addrs, dtys );
sewardj301a50f2006-03-03 16:14:18 +0000718 assert(r == MPI_SUCCESS);
719
720 switch (tycon) {
721
722 case MPI_COMBINER_CONTIGUOUS:
723 assert(n_ints == 1 && n_addrs == 0 && n_dtys == 1);
724 walk_type_array( f, base, dtys[0], ints[0] );
725 maybeFreeTy( &dtys[0] );
726 break;
727
sewardjc0526f72006-03-08 03:54:37 +0000728 case MPI_COMBINER_VECTOR:
729 assert(n_ints == 3 && n_addrs == 0 && n_dtys == 1);
730 ex = extentOfTy(dtys[0]);
731 if (0)
732 printf("vector count %d x (bl %d stride %d)\n",
733 (int)ints[0], (int)ints[1], (int)ints[2]);
734 for (i = 0; i < ints[0]; i++) {
735 walk_type_array( f, base + i * ints[2]/*stride*/ * ex,
736 dtys[0], ints[1]/*blocklength*/ );
737 }
738 maybeFreeTy( &dtys[0] );
739 break;
740
741 case MPI_COMBINER_HVECTOR:
742 assert(n_ints == 2 && n_addrs == 1 && n_dtys == 1);
743 ex = extentOfTy(dtys[0]);
744 if (0)
745 printf("hvector count %d x (bl %d hstride %d)\n",
746 (int)ints[0], (int)ints[1], (int)addrs[0]);
747 for (i = 0; i < ints[0]; i++) {
748 walk_type_array( f, base + i * addrs[0]/*hstride*/,
749 dtys[0], ints[1]/*blocklength*/ );
750 }
751 maybeFreeTy( &dtys[0] );
752 break;
753
754 case MPI_COMBINER_INDEXED:
755 assert(n_addrs == 0 && n_dtys == 1);
756 assert(n_ints > 0);
757 assert(n_ints == 2 * ints[0] + 1);
758 ex = extentOfTy(dtys[0]);
759 for (i = 0; i < ints[0]; i++) {
760 if (0)
761 printf("indexed (elem %d) off %d copies %d\n",
762 (int)i, ints[i+1+ints[0]], ints[i+1] );
763 walk_type_array( f, base + ex * ints[i+1+ints[0]],
764 dtys[0], ints[i+1] );
765 }
766 maybeFreeTy( &dtys[0] );
767 break;
768
769 case MPI_COMBINER_HINDEXED:
770 assert(n_ints > 0);
771 assert(n_ints == ints[0] + 1);
772 assert(n_addrs == ints[0] && n_dtys == 1);
773 ex = extentOfTy(dtys[0]);
774 for (i = 0; i < ints[0]; i++) {
775 if (0)
776 printf("hindexed (elem %d) hoff %d copies %d\n",
777 (int)i, (int)addrs[i], ints[i+1] );
778 walk_type_array( f, base + addrs[i],
779 dtys[0], ints[i+1] );
780 }
781 maybeFreeTy( &dtys[0] );
782 break;
783
sewardj301a50f2006-03-03 16:14:18 +0000784 case MPI_COMBINER_STRUCT:
785 assert(n_addrs == n_ints-1);
786 assert(n_dtys == n_ints-1);
sewardjc0526f72006-03-08 03:54:37 +0000787 assert(n_ints > 0);
788 assert(n_ints == ints[0] + 1);
sewardj301a50f2006-03-03 16:14:18 +0000789 for (i = 0; i < ints[0]; i++) {
sewardj1646f752006-03-03 21:03:10 +0000790 if (0)
sewardjc0526f72006-03-08 03:54:37 +0000791 printf("struct (elem %d limit %d) hoff %d copies %d\n",
sewardj301a50f2006-03-03 16:14:18 +0000792 (int)i, (int)ints[0], (int)addrs[i], (int)ints[i+1]);
793 walk_type_array( f, base + addrs[i], dtys[i], (long)ints[i+1] );
794 maybeFreeTy( &dtys[i] );
795 }
796 break;
797
798 default:
799 goto unhandled;
800
801 }
802
803 /* normal exit */
804 if (ints) free(ints);
805 if (addrs) free(addrs);
806 if (dtys) free(dtys);
807 return;
808
809 unhandled:
sewardj443aa372007-04-05 00:35:20 +0000810 /* Complain, but limit the amount of complaining that can happen to
811 the first 3 different unhandled tycons that show up, so as to
812 avoid swamping users with thousands of duplicate messages. */
813 if (complaints > 0 && tycon != last_complained_about_tycon) {
814 complaints--;
815 last_complained_about_tycon = tycon;
816 if (tycon == MPI_COMBINER_NAMED) {
817 fprintf(stderr, "%s %5d: walk_type: unhandled base type 0x%lx ",
818 preamble, my_pid, (long)ty);
819 showTy(stderr, ty);
820 fprintf(stderr, "\n");
821 } else {
822 fprintf(stderr, "%s %5d: walk_type: unhandled combiner 0x%lx\n",
823 preamble, my_pid, (long)tycon);
824 }
sewardj301a50f2006-03-03 16:14:18 +0000825 }
826 if (ints) free(ints);
827 if (addrs) free(addrs);
828 if (dtys) free(dtys);
sewardjcd8aaef2006-03-10 13:43:49 +0000829 if (opt_missing >= 2)
830 barf("walk_type: unhandled combiner, strict checking selected");
sewardj301a50f2006-03-03 16:14:18 +0000831}
832
833
sewardjcd8aaef2006-03-10 13:43:49 +0000834/* Same as walk_type but apply 'f' to every element in an array of
835 'count' items starting at 'base'. The only purpose of pushing this
836 into a different routine is so it can attempt to optimise the case
837 where the array elements are contiguous and packed together without
838 holes. */
sewardjcf375342007-01-16 05:35:46 +0000839static __inline__
sewardj301a50f2006-03-03 16:14:18 +0000840void walk_type_array ( void(*f)(void*,long), char* base,
841 MPI_Datatype elemTy, long count )
842{
843 long i, ex;
sewardj1646f752006-03-03 21:03:10 +0000844
845 assert(sizeof(unsigned long) == sizeof(char*));
846
847 /* First see if we can do this the fast way. */
sewardj8717d1a2006-03-04 02:31:52 +0000848 ex = sizeofOneNamedTy(elemTy);
sewardj1646f752006-03-03 21:03:10 +0000849
850 if ( /* ty is a primitive type with power-of-2 size */
851 (ex == 8 || ex == 4 || ex == 2 || ex == 1)
852 && /* base is suitably aligned for ty */
853 ( ((unsigned long)base) & (ex-1)) == 0) {
854
855 /* We're sure it's contiguous, so just paint/check it in one
856 go. */
857 if (0) printf("walk_type_array fast %ld of size %ld\n", count, ex );
858 f ( base, count * ex );
859
860 } else {
861
862 /* Bad news. We have to futz with each element individually.
sewardj8717d1a2006-03-04 02:31:52 +0000863 This could be very expensive.
864
865 Note: subtle. If ty is LONG_DOUBLE then the extent will be
866 12, so the following loop will jump along in steps of 12, but
867 the size painted by walk_type will be 10 since it uses
868 sizeofOneNamedTy to establish the size of base types. Which
869 is what we need to happen. */
sewardj1646f752006-03-03 21:03:10 +0000870 ex = extentOfTy(elemTy);
871 if (0) printf("walk_type_array SLOW %ld of size %ld\n", count, ex );
872 for (i = 0; i < count; i++)
873 walk_type( f, base + i * ex, elemTy );
874
875 }
sewardj301a50f2006-03-03 16:14:18 +0000876}
877
sewardjc3a47092006-02-18 23:13:33 +0000878
sewardj558cc222006-03-10 14:51:19 +0000879/* Hook so it's visible from outside (can be handy to dlopen/dlsym
880 it) */
881void mpiwrap_walk_type_EXTERNALLY_VISIBLE
sewardjc0526f72006-03-08 03:54:37 +0000882 ( void(*f)(void*,long), char* base, MPI_Datatype ty )
883{
sewardjd465d992006-10-17 01:46:55 +0000884 walk_type(f, base, ty);
sewardjc0526f72006-03-08 03:54:37 +0000885}
886
887
sewardjc3a47092006-02-18 23:13:33 +0000888/*------------------------------------------------------------*/
889/*--- Address-range helpers ---*/
890/*------------------------------------------------------------*/
891
892/* ----------------
sewardjc3a47092006-02-18 23:13:33 +0000893 Do corresponding checks on memory areas defined using a
sewardjcf375342007-01-16 05:35:46 +0000894 straightforward (start, length) description.
sewardjc3a47092006-02-18 23:13:33 +0000895 ----------------
896*/
897
sewardjcf375342007-01-16 05:35:46 +0000898static __inline__
njndbf7ca72006-03-31 11:57:59 +0000899void check_mem_is_defined_untyped ( void* buffer, long nbytes )
sewardjc3a47092006-02-18 23:13:33 +0000900{
901 if (nbytes > 0) {
njndbf7ca72006-03-31 11:57:59 +0000902 VALGRIND_CHECK_MEM_IS_DEFINED(buffer, nbytes);
sewardjc3a47092006-02-18 23:13:33 +0000903 }
904}
905
sewardjcf375342007-01-16 05:35:46 +0000906static __inline__
njndbf7ca72006-03-31 11:57:59 +0000907void check_mem_is_addressable_untyped ( void* buffer, long nbytes )
sewardjc3a47092006-02-18 23:13:33 +0000908{
909 if (nbytes > 0) {
njndbf7ca72006-03-31 11:57:59 +0000910 VALGRIND_CHECK_MEM_IS_ADDRESSABLE(buffer, nbytes);
sewardjc3a47092006-02-18 23:13:33 +0000911 }
912}
913
sewardjcf375342007-01-16 05:35:46 +0000914static __inline__
njndbf7ca72006-03-31 11:57:59 +0000915void make_mem_defined_if_addressable_untyped ( void* buffer, long nbytes )
sewardjc3a47092006-02-18 23:13:33 +0000916{
917 if (nbytes > 0) {
njndbf7ca72006-03-31 11:57:59 +0000918 VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(buffer, nbytes);
sewardjc3a47092006-02-18 23:13:33 +0000919 }
920}
921
sewardjcf375342007-01-16 05:35:46 +0000922static __inline__
njndbf7ca72006-03-31 11:57:59 +0000923void make_mem_defined_if_addressable_if_success_untyped ( int err,
sewardjcd8aaef2006-03-10 13:43:49 +0000924 void* buffer, long nbytes )
sewardjc3a47092006-02-18 23:13:33 +0000925{
926 if (err == MPI_SUCCESS && nbytes > 0) {
njndbf7ca72006-03-31 11:57:59 +0000927 VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(buffer, nbytes);
sewardjc3a47092006-02-18 23:13:33 +0000928 }
929}
930
sewardjc3a47092006-02-18 23:13:33 +0000931
sewardj301a50f2006-03-03 16:14:18 +0000932/* ----------------
933 Do checks on memory areas defined using the MPI (buffer, count,
934 type) convention.
935 ----------------
936*/
937
938/* Check that the specified area is both addressible and contains
939 initialised data, and cause V to complain if not. */
940
sewardjcf375342007-01-16 05:35:46 +0000941static __inline__
njndbf7ca72006-03-31 11:57:59 +0000942void check_mem_is_defined ( char* buffer, long count, MPI_Datatype datatype )
sewardj301a50f2006-03-03 16:14:18 +0000943{
njndbf7ca72006-03-31 11:57:59 +0000944 walk_type_array( check_mem_is_defined_untyped, buffer, datatype, count );
sewardj301a50f2006-03-03 16:14:18 +0000945}
946
947
948/* Check that the specified area is addressible, and cause V to
949 complain if not. Doesn't matter whether the data there is
950 initialised or not. */
951
sewardjcf375342007-01-16 05:35:46 +0000952static __inline__
njndbf7ca72006-03-31 11:57:59 +0000953void check_mem_is_addressable ( void *buffer, long count, MPI_Datatype datatype )
sewardj301a50f2006-03-03 16:14:18 +0000954{
njndbf7ca72006-03-31 11:57:59 +0000955 walk_type_array( check_mem_is_addressable_untyped, buffer, datatype, count );
sewardj301a50f2006-03-03 16:14:18 +0000956}
957
958
sewardjcd8aaef2006-03-10 13:43:49 +0000959/* Set the specified area to 'defined for each byte which is
960 addressible' state. */
sewardj301a50f2006-03-03 16:14:18 +0000961
sewardjcf375342007-01-16 05:35:46 +0000962static __inline__
njndbf7ca72006-03-31 11:57:59 +0000963void make_mem_defined_if_addressable ( void *buffer, int count, MPI_Datatype datatype )
sewardj301a50f2006-03-03 16:14:18 +0000964{
njndbf7ca72006-03-31 11:57:59 +0000965 walk_type_array( make_mem_defined_if_addressable_untyped,
966 buffer, datatype, count );
sewardj301a50f2006-03-03 16:14:18 +0000967}
968
sewardjcf375342007-01-16 05:35:46 +0000969static __inline__
sewardj301a50f2006-03-03 16:14:18 +0000970void
njndbf7ca72006-03-31 11:57:59 +0000971make_mem_defined_if_addressable_if_success ( int err, void *buffer, int count,
972 MPI_Datatype datatype )
sewardj301a50f2006-03-03 16:14:18 +0000973{
974 if (err == MPI_SUCCESS)
njndbf7ca72006-03-31 11:57:59 +0000975 make_mem_defined_if_addressable(buffer, count, datatype);
sewardj301a50f2006-03-03 16:14:18 +0000976}
977
978
sewardjc3a47092006-02-18 23:13:33 +0000979/*------------------------------------------------------------*/
980/*--- ---*/
981/*--- The wrappers proper. They are listed in the order ---*/
982/*--- in which they appear in "MPI: A Message-Passing ---*/
983/*--- Interface Standard, MPIF, Nov 15 2003" (the MPI 1.1 ---*/
984/*--- spec. All unimplemented wrappers are listed at the ---*/
985/*--- end of the file. The list of function names is ---*/
sewardj9c969c32006-03-10 18:37:45 +0000986/*--- taken from the headers of Open MPI svn r9191. ---*/
987/*--- Hopefully it is a complete list of all the MPI 2 ---*/
988/*--- functions. ---*/
sewardjc3a47092006-02-18 23:13:33 +0000989/*--- ---*/
990/*------------------------------------------------------------*/
991
992/* Handy abbreviation */
993#define WRAPPER_FOR(name) I_WRAP_FNNAME_U(name)
994
sewardjc3a47092006-02-18 23:13:33 +0000995/* Generates (conceptually) a wrapper which does nothing. In
996 fact just generate no wrapper at all. */
sewardj9c969c32006-03-10 18:37:45 +0000997#define HAS_NO_WRAPPER(basename) /* */
sewardjc3a47092006-02-18 23:13:33 +0000998
999
1000/*------------------------------------------------------------*/
1001/*--- ---*/
1002/*--- Sec 3.2, Blocking Send and Receive Operations ---*/
1003/*--- ---*/
1004/*------------------------------------------------------------*/
1005
sewardj9c969c32006-03-10 18:37:45 +00001006/* --- {,B,S,R}Send --- */
sewardjc3a47092006-02-18 23:13:33 +00001007/* pre: rd: (buf,count,datatype) */
sewardj9c969c32006-03-10 18:37:45 +00001008static
1009int generic_Send(void *buf, int count, MPI_Datatype datatype,
1010 int dest, int tag, MPI_Comm comm)
sewardjc3a47092006-02-18 23:13:33 +00001011{
1012 OrigFn fn;
1013 int err;
1014 VALGRIND_GET_ORIG_FN(fn);
sewardj9c969c32006-03-10 18:37:45 +00001015 before("{,B,S,R}Send");
njndbf7ca72006-03-31 11:57:59 +00001016 check_mem_is_defined(buf, count, datatype);
sewardjc3a47092006-02-18 23:13:33 +00001017 CALL_FN_W_6W(err, fn, buf,count,datatype,dest,tag,comm);
sewardj9c969c32006-03-10 18:37:45 +00001018 after("{,B,S,R}Send", err);
sewardjc3a47092006-02-18 23:13:33 +00001019 return err;
1020}
sewardj9c969c32006-03-10 18:37:45 +00001021int WRAPPER_FOR(PMPI_Send)(void *buf, int count, MPI_Datatype datatype,
1022 int dest, int tag, MPI_Comm comm) {
1023 return generic_Send(buf,count,datatype, dest,tag,comm);
1024}
1025int WRAPPER_FOR(PMPI_Bsend)(void *buf, int count, MPI_Datatype datatype,
1026 int dest, int tag, MPI_Comm comm) {
1027 return generic_Send(buf,count,datatype, dest,tag,comm);
1028}
1029int WRAPPER_FOR(PMPI_Ssend)(void *buf, int count, MPI_Datatype datatype,
1030 int dest, int tag, MPI_Comm comm) {
1031 return generic_Send(buf,count,datatype, dest,tag,comm);
1032}
1033int WRAPPER_FOR(PMPI_Rsend)(void *buf, int count, MPI_Datatype datatype,
1034 int dest, int tag, MPI_Comm comm) {
1035 return generic_Send(buf,count,datatype, dest,tag,comm);
1036}
sewardjc3a47092006-02-18 23:13:33 +00001037
sewardjc3a47092006-02-18 23:13:33 +00001038/* --- Recv --- */
1039/* pre: must be writable: (buf,count,datatype)
1040 must be writable: status
1041 post: make readable: (buf,recv_count,datatype)
1042 where recv_count is determined from *status
1043*/
1044int WRAPPER_FOR(PMPI_Recv)(void *buf, int count, MPI_Datatype datatype,
1045 int source, int tag,
1046 MPI_Comm comm, MPI_Status *status)
1047{
1048 OrigFn fn;
1049 int err, recv_count = 0;
1050 VALGRIND_GET_ORIG_FN(fn);
1051 before("Recv");
njndbf7ca72006-03-31 11:57:59 +00001052 check_mem_is_addressable(buf, count, datatype);
1053 check_mem_is_addressable_untyped(status, sizeof(*status));
sewardjc3a47092006-02-18 23:13:33 +00001054 CALL_FN_W_7W(err, fn, buf,count,datatype,source,tag,comm,status);
1055 if (err == MPI_SUCCESS && count_from_Status(&recv_count,datatype,status)) {
njndbf7ca72006-03-31 11:57:59 +00001056 make_mem_defined_if_addressable(buf, recv_count, datatype);
sewardjc3a47092006-02-18 23:13:33 +00001057 }
1058 after("Recv", err);
1059 return err;
1060}
1061
sewardj9c969c32006-03-10 18:37:45 +00001062/* --- Get_count --- */
1063/* pre: must be readable: *status
1064 post: make defined: *count -- don't bother, libmpi will surely do this
1065*/
1066int WRAPPER_FOR(PMPI_Get_count)(MPI_Status* status,
1067 MPI_Datatype ty, int* count )
1068{
1069 OrigFn fn;
1070 int err;
1071 VALGRIND_GET_ORIG_FN(fn);
1072 before("Get_count");
sewardjd465d992006-10-17 01:46:55 +00001073# if defined(_AIX)
1074 check_mem_is_addressable_untyped(status, sizeof(*status));
1075# else
njndbf7ca72006-03-31 11:57:59 +00001076 check_mem_is_defined_untyped(status, sizeof(*status));
sewardjd465d992006-10-17 01:46:55 +00001077# endif
sewardj9c969c32006-03-10 18:37:45 +00001078 CALL_FN_W_WWW(err, fn, status,ty,count);
1079 after("Get_count", err);
1080 return err;
1081}
1082
sewardjc3a47092006-02-18 23:13:33 +00001083
1084/*------------------------------------------------------------*/
1085/*--- ---*/
1086/*--- Sec 3.7, Nonblocking communication ---*/
1087/*--- ---*/
1088/*------------------------------------------------------------*/
1089
sewardj9c969c32006-03-10 18:37:45 +00001090/* Maintain a table that makes it possible for the wrappers to
1091 complete MPI_Irecv successfully.
1092
1093 The issue is that MPI_Irecv states the recv buffer and returns
1094 immediately, giving a handle (MPI_Request) for the transaction.
1095 Later the user will have to poll for completion with MPI_Wait etc,
1096 and at that point these wrappers have to paint the recv buffer.
1097 But the recv buffer details are not presented to MPI_Wait - only
1098 the handle is. We therefore have to use a shadow table
1099 (sReqs{,_size,_used,_lock}) which associates uncompleted
1100 MPI_Requests with the corresponding buffer address/count/type.
1101
1102 Only read requests are placed in the table, since there is no need
1103 to do any buffer painting following completion of an Isend - all
1104 the checks for that are done at the time Isend is called.
1105
1106 Care has to be take to remove completed requests from the table.
1107
1108 Access to the table is guarded by sReqs_lock so as to make it
1109 thread-safe.
1110*/
1111
sewardjc3a47092006-02-18 23:13:33 +00001112typedef
1113 struct {
1114 Bool inUse;
1115 MPI_Request key;
1116 void* buf;
1117 int count;
1118 MPI_Datatype datatype;
1119 }
1120 ShadowRequest;
1121
1122static ShadowRequest* sReqs = NULL;
1123static int sReqs_size = 0;
1124static int sReqs_used = 0;
sewardj558cc222006-03-10 14:51:19 +00001125static pthread_mutex_t sReqs_lock = PTHREAD_MUTEX_INITIALIZER;
1126
1127#define LOCK_SREQS \
1128 do { int pr = pthread_mutex_lock(&sReqs_lock); \
1129 assert(pr == 0); \
1130 } while (0)
1131
1132#define UNLOCK_SREQS \
1133 do { int pr = pthread_mutex_unlock(&sReqs_lock); \
1134 assert(pr == 0); \
1135 } while (0)
sewardjc3a47092006-02-18 23:13:33 +00001136
1137
1138/* Ensure the sReqs expandable array has at least one free slot, by
1139 copying it into a larger one if necessary. NOTE: sReqs_lock is
1140 held throughout this procedure.*/
1141static void ensure_sReq_space ( void )
1142{
1143 int i;
1144 ShadowRequest* sReqs2;
1145 if (sReqs_used == sReqs_size) {
1146 sReqs_size = sReqs_size==0 ? 2 : 2*sReqs_size;
1147 sReqs2 = malloc( sReqs_size * sizeof(ShadowRequest) );
1148 if (sReqs2 == NULL) {
sewardj558cc222006-03-10 14:51:19 +00001149 UNLOCK_SREQS;
sewardjc3a47092006-02-18 23:13:33 +00001150 barf("add_shadow_Request: malloc failed.\n");
1151 }
1152 for (i = 0; i < sReqs_used; i++)
1153 sReqs2[i] = sReqs[i];
1154 if (sReqs)
1155 free(sReqs);
1156 sReqs = sReqs2;
1157 }
1158 assert(sReqs_used < sReqs_size);
1159}
1160
1161
1162/* Find shadow info for 'request', or NULL if none. */
1163
1164static
1165ShadowRequest* find_shadow_Request ( MPI_Request request )
1166{
1167 ShadowRequest* ret = NULL;
1168 int i;
sewardj558cc222006-03-10 14:51:19 +00001169 LOCK_SREQS;
sewardjc3a47092006-02-18 23:13:33 +00001170 for (i = 0; i < sReqs_used; i++) {
1171 if (sReqs[i].inUse && eq_MPI_Request(sReqs[i].key,request)) {
1172 ret = &sReqs[i];
1173 break;
1174 }
1175 }
sewardj558cc222006-03-10 14:51:19 +00001176 UNLOCK_SREQS;
sewardjc3a47092006-02-18 23:13:33 +00001177 return ret;
1178}
1179
1180
1181/* Delete shadow info for 'request', if any. */
1182
1183static void delete_shadow_Request ( MPI_Request request )
1184{
1185 int i;
sewardj558cc222006-03-10 14:51:19 +00001186 LOCK_SREQS;
sewardjc3a47092006-02-18 23:13:33 +00001187 for (i = 0; i < sReqs_used; i++) {
1188 if (sReqs[i].inUse && eq_MPI_Request(sReqs[i].key,request)) {
1189 sReqs[i].inUse = False;
1190 break;
1191 }
1192 }
sewardj558cc222006-03-10 14:51:19 +00001193 UNLOCK_SREQS;
sewardjc3a47092006-02-18 23:13:33 +00001194}
1195
1196
1197/* Add a shadow for 'request', overwriting any old binding for it. */
1198
1199static
1200void add_shadow_Request( MPI_Request request,
1201 void* buf, int count,
1202 MPI_Datatype datatype )
1203{
1204 int i, ix = -1;
sewardj558cc222006-03-10 14:51:19 +00001205 LOCK_SREQS;
sewardjc3a47092006-02-18 23:13:33 +00001206 assert(sReqs_used >= 0);
1207 assert(sReqs_size >= 0);
1208 assert(sReqs_used <= sReqs_size);
1209 if (sReqs == NULL) assert(sReqs_size == 0);
1210
1211 /* First of all see if we already have a binding for this key; if
1212 so just replace it, and have done. */
1213 for (i = 0; i < sReqs_used; i++) {
1214 if (sReqs[i].inUse && eq_MPI_Request(sReqs[i].key,request)) {
1215 ix = i;
1216 break;
1217 }
1218 }
1219
1220 if (ix < 0) {
1221 /* Ok, we don't have it, so will have to add it. First search
1222 to see if there is an existing empty slot. */
1223 for (i = 0; i < sReqs_used; i++) {
1224 if (!sReqs[i].inUse) {
1225 ix = i;
1226 break;
1227 }
1228 }
1229 }
1230
1231 /* No empty slots. Allocate a new one. */
1232 if (ix < 0) {
1233 ensure_sReq_space();
1234 assert(sReqs_used < sReqs_size);
1235 ix = sReqs_used;
1236 sReqs_used++;
1237 }
1238
1239 assert(ix >= 0 && ix < sReqs_used);
1240 assert(sReqs_used <= sReqs_size);
1241
1242 sReqs[ix].inUse = True;
1243 sReqs[ix].key = request;
1244 sReqs[ix].buf = buf;
1245 sReqs[ix].count = count;
1246 sReqs[ix].datatype = datatype;
1247
sewardj558cc222006-03-10 14:51:19 +00001248 UNLOCK_SREQS;
sewardjec8b6142006-03-09 03:05:17 +00001249 if (opt_verbosity > 1)
sewardjc3a47092006-02-18 23:13:33 +00001250 fprintf(stderr, "%s %5d: sReq+ 0x%lx -> b/c/d %p/%d/0x%lx [slot %d]\n",
1251 preamble, my_pid, (unsigned long)request,
1252 buf, count, (long)datatype, ix);
1253}
1254
sewardj9c969c32006-03-10 18:37:45 +00001255static
1256MPI_Request* clone_Request_array ( int count, MPI_Request* orig )
1257{
1258 MPI_Request* copy;
1259 int i;
1260 LOCK_SREQS;
1261 if (count < 0)
1262 count = 0; /* Hmm. Call Mulder and Scully. */
1263 copy = malloc( count * sizeof(MPI_Request) );
sewardjd465d992006-10-17 01:46:55 +00001264 if (copy == NULL && count > 0) {
sewardj9c969c32006-03-10 18:37:45 +00001265 UNLOCK_SREQS;
1266 barf("clone_Request_array: malloc failed");
1267 }
1268 for (i = 0; i < count; i++)
1269 copy[i] = orig[i];
1270 UNLOCK_SREQS;
1271 return copy;
1272}
1273
sewardj558cc222006-03-10 14:51:19 +00001274#undef LOCK_SREQS
1275#undef UNLOCK_SREQS
sewardjc3a47092006-02-18 23:13:33 +00001276
sewardj9c969c32006-03-10 18:37:45 +00001277
sewardjc3a47092006-02-18 23:13:33 +00001278static void maybe_complete ( Bool error_in_status,
1279 MPI_Request request_before,
1280 MPI_Request request_after,
1281 MPI_Status* status )
1282{
1283 int recv_count = 0;
1284 ShadowRequest* shadow;
1285 /* How do we know if this is an Irecv request that has now
1286 finished successfully?
1287
1288 request_before isn't MPI_REQUEST_NULL
1289 and request_before is found in the shadow table
1290 and request_after *is* MPI_REQUEST_NULL
1291 and (if error_in_status then status.MPI_ERROR is MPI_SUCCESS)
1292
1293 (when error_in_status == False, then we expect not to get
1294 called at all if there was an error.)
1295 */
1296 if (request_before != MPI_REQUEST_NULL
1297 && request_after == MPI_REQUEST_NULL
1298 && (error_in_status ? status->MPI_ERROR == MPI_SUCCESS : True)
1299 && ( (shadow=find_shadow_Request(request_before)) != NULL) ) {
sewardjb727b542006-03-10 21:41:01 +00001300 /* The Irecv detailed in 'shadow' completed. Paint the result
1301 buffer, and delete the entry. */
sewardjc3a47092006-02-18 23:13:33 +00001302 if (count_from_Status(&recv_count, shadow->datatype, status)) {
njndbf7ca72006-03-31 11:57:59 +00001303 make_mem_defined_if_addressable(shadow->buf, recv_count, shadow->datatype);
sewardjec8b6142006-03-09 03:05:17 +00001304 if (opt_verbosity > 1)
sewardjc3a47092006-02-18 23:13:33 +00001305 fprintf(stderr, "%s %5d: sReq- %p (completed)\n",
1306 preamble, my_pid, request_before);
1307 }
1308 delete_shadow_Request(request_before);
1309 }
1310}
1311
1312
sewardjc3a47092006-02-18 23:13:33 +00001313/* --- Isend --- */
1314/* rd: (buf,count,datatype) */
1315/* wr: *request */
sewardjcf375342007-01-16 05:35:46 +00001316static __inline__
sewardj9c969c32006-03-10 18:37:45 +00001317int generic_Isend(void *buf, int count, MPI_Datatype datatype,
1318 int dest, int tag, MPI_Comm comm,
1319 MPI_Request* request)
sewardjc3a47092006-02-18 23:13:33 +00001320{
1321 OrigFn fn;
1322 int err;
1323 VALGRIND_GET_ORIG_FN(fn);
sewardj9c969c32006-03-10 18:37:45 +00001324 before("{,B,S,R}Isend");
njndbf7ca72006-03-31 11:57:59 +00001325 check_mem_is_defined(buf, count, datatype);
1326 check_mem_is_addressable_untyped(request, sizeof(*request));
sewardjc3a47092006-02-18 23:13:33 +00001327 CALL_FN_W_7W(err, fn, buf,count,datatype,dest,tag,comm,request);
njndbf7ca72006-03-31 11:57:59 +00001328 make_mem_defined_if_addressable_if_success_untyped(err, request, sizeof(*request));
sewardj9c969c32006-03-10 18:37:45 +00001329 after("{,B,S,R}Isend", err);
sewardjc3a47092006-02-18 23:13:33 +00001330 return err;
1331}
sewardj9c969c32006-03-10 18:37:45 +00001332int WRAPPER_FOR(PMPI_Isend)(void *buf, int count, MPI_Datatype datatype,
1333 int dest, int tag, MPI_Comm comm,
1334 MPI_Request* request) {
1335 return generic_Isend(buf,count,datatype, dest,tag,comm, request);
1336}
1337int WRAPPER_FOR(PMPI_Ibsend)(void *buf, int count, MPI_Datatype datatype,
1338 int dest, int tag, MPI_Comm comm,
1339 MPI_Request* request) {
1340 return generic_Isend(buf,count,datatype, dest,tag,comm, request);
1341}
1342int WRAPPER_FOR(PMPI_Issend)(void *buf, int count, MPI_Datatype datatype,
1343 int dest, int tag, MPI_Comm comm,
1344 MPI_Request* request) {
1345 return generic_Isend(buf,count,datatype, dest,tag,comm, request);
1346}
1347int WRAPPER_FOR(PMPI_Irsend)(void *buf, int count, MPI_Datatype datatype,
1348 int dest, int tag, MPI_Comm comm,
1349 MPI_Request* request) {
1350 return generic_Isend(buf,count,datatype, dest,tag,comm, request);
1351}
1352
sewardjc3a47092006-02-18 23:13:33 +00001353
sewardjc3a47092006-02-18 23:13:33 +00001354/* --- Irecv --- */
1355/* pre: must be writable: (buf,count,datatype), *request
1356 post: make readable *request
1357 add a request->(buf,count,ty) binding to the
1358 shadow request table.
1359*/
1360int WRAPPER_FOR(PMPI_Irecv)( void* buf, int count, MPI_Datatype datatype,
1361 int source, int tag, MPI_Comm comm,
1362 MPI_Request* request )
1363{
1364 OrigFn fn;
1365 int err;
1366 VALGRIND_GET_ORIG_FN(fn);
1367 before("Irecv");
njndbf7ca72006-03-31 11:57:59 +00001368 check_mem_is_addressable(buf, count, datatype);
1369 check_mem_is_addressable_untyped(request, sizeof(*request));
sewardjc3a47092006-02-18 23:13:33 +00001370 CALL_FN_W_7W(err, fn, buf,count,datatype,source,tag,comm,request);
1371 if (err == MPI_SUCCESS) {
njndbf7ca72006-03-31 11:57:59 +00001372 make_mem_defined_if_addressable_untyped(request, sizeof(*request));
sewardjc3a47092006-02-18 23:13:33 +00001373 add_shadow_Request( *request, buf,count,datatype );
1374 }
1375 after("Irecv", err);
1376 return err;
1377}
1378
sewardjc3a47092006-02-18 23:13:33 +00001379/* --- Wait --- */
sewardjb727b542006-03-10 21:41:01 +00001380/* The MPI1 spec (imprecisely) defines 3 request states:
1381 - "null" if the request is MPI_REQUEST_NULL
1382 - "inactive" if not "null" and not associated with ongoing comms
1383 - "active" if not "null" and is associated with ongoing comms
1384*/
sewardjc3a47092006-02-18 23:13:33 +00001385int WRAPPER_FOR(PMPI_Wait)( MPI_Request* request,
1386 MPI_Status* status )
1387{
1388 MPI_Request request_before;
1389 OrigFn fn;
1390 int err;
1391 VALGRIND_GET_ORIG_FN(fn);
1392 before("Wait");
njndbf7ca72006-03-31 11:57:59 +00001393 check_mem_is_addressable_untyped(status, sizeof(MPI_Status));
1394 check_mem_is_defined_untyped(request, sizeof(MPI_Request));
sewardjc3a47092006-02-18 23:13:33 +00001395 request_before = *request;
1396 CALL_FN_W_WW(err, fn, request,status);
1397 if (err == MPI_SUCCESS) {
1398 maybe_complete(False/*err in status?*/,
1399 request_before, *request, status);
njndbf7ca72006-03-31 11:57:59 +00001400 make_mem_defined_if_addressable_untyped(status, sizeof(MPI_Status));
sewardjc3a47092006-02-18 23:13:33 +00001401 }
1402 after("Wait", err);
1403 return err;
1404}
1405
sewardj982751b2008-05-15 05:48:16 +00001406/* --- Waitany --- */
1407int WRAPPER_FOR(PMPI_Waitany)( int count,
1408 MPI_Request* requests,
1409 int* index,
1410 MPI_Status* status )
1411{
1412 MPI_Request* requests_before = NULL;
1413 OrigFn fn;
1414 int err, i;
1415 VALGRIND_GET_ORIG_FN(fn);
1416 before("Waitany");
1417 if (0) fprintf(stderr, "Waitany: %d\n", count);
1418 check_mem_is_addressable_untyped(index, sizeof(int));
1419 check_mem_is_addressable_untyped(status, sizeof(MPI_Status));
1420 for (i = 0; i < count; i++) {
1421 check_mem_is_defined_untyped(&requests[i], sizeof(MPI_Request));
1422 }
1423 requests_before = clone_Request_array( count, requests );
1424 CALL_FN_W_WWWW(err, fn, count,requests,index,status);
1425 if (err == MPI_SUCCESS && *index >= 0 && *index < count) {
1426 maybe_complete(False/*err in status?*/,
1427 requests_before[*index], requests[*index], status);
1428 make_mem_defined_if_addressable_untyped(status, sizeof(MPI_Status));
1429 }
1430 if (requests_before)
1431 free(requests_before);
1432 after("Waitany", err);
1433 return err;
1434}
1435
sewardjc3a47092006-02-18 23:13:33 +00001436/* --- Waitall --- */
1437int WRAPPER_FOR(PMPI_Waitall)( int count,
1438 MPI_Request* requests,
1439 MPI_Status* statuses )
1440{
1441 MPI_Request* requests_before = NULL;
1442 OrigFn fn;
1443 int err, i;
1444 VALGRIND_GET_ORIG_FN(fn);
1445 before("Waitall");
1446 if (0) fprintf(stderr, "Waitall: %d\n", count);
1447 for (i = 0; i < count; i++) {
njndbf7ca72006-03-31 11:57:59 +00001448 check_mem_is_addressable_untyped(&statuses[i], sizeof(MPI_Status));
1449 check_mem_is_defined_untyped(&requests[i], sizeof(MPI_Request));
sewardjc3a47092006-02-18 23:13:33 +00001450 }
1451 requests_before = clone_Request_array( count, requests );
1452 CALL_FN_W_WWW(err, fn, count,requests,statuses);
1453 if (err == MPI_SUCCESS /*complete success*/
1454 || err == MPI_ERR_IN_STATUS /* partial success */) {
1455 Bool e_i_s = err == MPI_ERR_IN_STATUS;
1456 for (i = 0; i < count; i++) {
1457 maybe_complete(e_i_s, requests_before[i], requests[i],
1458 &statuses[i]);
njndbf7ca72006-03-31 11:57:59 +00001459 make_mem_defined_if_addressable_untyped(&statuses[i],
1460 sizeof(MPI_Status));
sewardjc3a47092006-02-18 23:13:33 +00001461 }
1462 }
1463 if (requests_before)
1464 free(requests_before);
1465 after("Waitall", err);
1466 return err;
1467}
1468
sewardjb727b542006-03-10 21:41:01 +00001469/* --- Test --- */
1470/* nonblocking version of Wait */
1471int WRAPPER_FOR(PMPI_Test)( MPI_Request* request, int* flag,
1472 MPI_Status* status )
1473{
1474 MPI_Request request_before;
1475 OrigFn fn;
1476 int err;
1477 VALGRIND_GET_ORIG_FN(fn);
1478 before("Test");
njndbf7ca72006-03-31 11:57:59 +00001479 check_mem_is_addressable_untyped(status, sizeof(MPI_Status));
1480 check_mem_is_addressable_untyped(flag, sizeof(int));
1481 check_mem_is_defined_untyped(request, sizeof(MPI_Request));
sewardjb727b542006-03-10 21:41:01 +00001482 request_before = *request;
1483 CALL_FN_W_WWW(err, fn, request,flag,status);
1484 if (err == MPI_SUCCESS && *flag) {
1485 maybe_complete(False/*err in status?*/,
1486 request_before, *request, status);
njndbf7ca72006-03-31 11:57:59 +00001487 make_mem_defined_if_addressable_untyped(status, sizeof(MPI_Status));
sewardjb727b542006-03-10 21:41:01 +00001488 }
1489 after("Test", err);
1490 return err;
1491}
1492
1493/* --- Testall --- */
1494/* nonblocking version of Waitall */
1495int WRAPPER_FOR(PMPI_Testall)( int count, MPI_Request* requests,
1496 int* flag, MPI_Status* statuses )
1497{
1498 MPI_Request* requests_before = NULL;
1499 OrigFn fn;
1500 int err, i;
1501 VALGRIND_GET_ORIG_FN(fn);
1502 before("Testall");
1503 if (0) fprintf(stderr, "Testall: %d\n", count);
njndbf7ca72006-03-31 11:57:59 +00001504 check_mem_is_addressable_untyped(flag, sizeof(int));
sewardjb727b542006-03-10 21:41:01 +00001505 for (i = 0; i < count; i++) {
njndbf7ca72006-03-31 11:57:59 +00001506 check_mem_is_addressable_untyped(&statuses[i], sizeof(MPI_Status));
1507 check_mem_is_defined_untyped(&requests[i], sizeof(MPI_Request));
sewardjb727b542006-03-10 21:41:01 +00001508 }
1509 requests_before = clone_Request_array( count, requests );
1510 CALL_FN_W_WWWW(err, fn, count,requests,flag,statuses);
1511 /* Urk. Is the following "if (...)" really right? I don't know. */
1512 if (*flag
1513 && (err == MPI_SUCCESS /*complete success*/
1514 || err == MPI_ERR_IN_STATUS /* partial success */)) {
1515 Bool e_i_s = err == MPI_ERR_IN_STATUS;
1516 for (i = 0; i < count; i++) {
1517 maybe_complete(e_i_s, requests_before[i], requests[i],
1518 &statuses[i]);
njndbf7ca72006-03-31 11:57:59 +00001519 make_mem_defined_if_addressable_untyped(&statuses[i], sizeof(MPI_Status));
sewardjb727b542006-03-10 21:41:01 +00001520 }
1521 }
1522 if (requests_before)
1523 free(requests_before);
1524 after("Testall", err);
1525 return err;
1526}
1527
sewardjc3a47092006-02-18 23:13:33 +00001528/* --- Iprobe --- */
sewardjc3a47092006-02-18 23:13:33 +00001529/* pre: must-be-writable: *flag, *status */
1530/* post: make-readable *flag
sewardjb727b542006-03-10 21:41:01 +00001531 if *flag==True make-defined *status */
sewardjc3a47092006-02-18 23:13:33 +00001532int WRAPPER_FOR(PMPI_Iprobe)(int source, int tag,
1533 MPI_Comm comm,
1534 int* flag, MPI_Status* status)
1535{
1536 OrigFn fn;
1537 int err;
1538 VALGRIND_GET_ORIG_FN(fn);
1539 before("Iprobe");
njndbf7ca72006-03-31 11:57:59 +00001540 check_mem_is_addressable_untyped(flag, sizeof(*flag));
1541 check_mem_is_addressable_untyped(status, sizeof(*status));
sewardjc3a47092006-02-18 23:13:33 +00001542 CALL_FN_W_5W(err, fn, source,tag,comm,flag,status);
1543 if (err == MPI_SUCCESS) {
njndbf7ca72006-03-31 11:57:59 +00001544 make_mem_defined_if_addressable_untyped(flag, sizeof(*flag));
sewardjc3a47092006-02-18 23:13:33 +00001545 if (*flag)
njndbf7ca72006-03-31 11:57:59 +00001546 make_mem_defined_if_addressable_untyped(status, sizeof(*status));
sewardjc3a47092006-02-18 23:13:33 +00001547 }
1548 after("Iprobe", err);
1549 return err;
1550}
1551
sewardjb727b542006-03-10 21:41:01 +00001552/* --- Probe --- */
1553/* pre: must-be-writable *status */
1554/* post: make-defined *status */
1555int WRAPPER_FOR(PMPI_Probe)(int source, int tag,
1556 MPI_Comm comm, MPI_Status* status)
1557{
1558 OrigFn fn;
1559 int err;
1560 VALGRIND_GET_ORIG_FN(fn);
1561 before("Probe");
njndbf7ca72006-03-31 11:57:59 +00001562 check_mem_is_addressable_untyped(status, sizeof(*status));
sewardjb727b542006-03-10 21:41:01 +00001563 CALL_FN_W_WWWW(err, fn, source,tag,comm,status);
njndbf7ca72006-03-31 11:57:59 +00001564 make_mem_defined_if_addressable_if_success_untyped(err, status, sizeof(*status));
sewardjb727b542006-03-10 21:41:01 +00001565 after("Probe", err);
1566 return err;
1567}
1568
1569/* --- Cancel --- */
1570/* Wrapping PMPI_Cancel is interesting only to the extent that we need
1571 to be able to detect when a request should be removed from our
1572 shadow table due to cancellation. */
1573int WRAPPER_FOR(PMPI_Cancel)(MPI_Request* request)
1574{
1575 OrigFn fn;
1576 int err;
1577 MPI_Request tmp;
1578 VALGRIND_GET_ORIG_FN(fn);
1579 before("Cancel");
njndbf7ca72006-03-31 11:57:59 +00001580 check_mem_is_addressable_untyped(request, sizeof(*request));
sewardjb727b542006-03-10 21:41:01 +00001581 tmp = *request;
1582 CALL_FN_W_W(err, fn, request);
1583 if (err == MPI_SUCCESS)
1584 delete_shadow_Request(tmp);
1585 after("Cancel", err);
1586 return err;
1587}
1588
sewardjc3a47092006-02-18 23:13:33 +00001589
1590/*------------------------------------------------------------*/
1591/*--- ---*/
1592/*--- Sec 3.10, Send-receive ---*/
1593/*--- ---*/
1594/*------------------------------------------------------------*/
1595
1596/* --- Sendrecv --- */
1597/* pre: must be readable: (sendbuf,sendcount,sendtype)
1598 must be writable: (recvbuf,recvcount,recvtype)
1599 post: make readable: (recvbuf,recvcount_actual,datatype)
1600 where recvcount_actual is determined from *status
1601*/
1602int WRAPPER_FOR(PMPI_Sendrecv)(
1603 void *sendbuf, int sendcount, MPI_Datatype sendtype,
1604 int dest, int sendtag,
1605 void *recvbuf, int recvcount, MPI_Datatype recvtype,
1606 int source, int recvtag,
1607 MPI_Comm comm, MPI_Status *status)
1608{
1609 OrigFn fn;
1610 int err, recvcount_actual = 0;
1611 VALGRIND_GET_ORIG_FN(fn);
1612 before("Sendrecv");
njndbf7ca72006-03-31 11:57:59 +00001613 check_mem_is_defined(sendbuf, sendcount, sendtype);
1614 check_mem_is_addressable(recvbuf, recvcount, recvtype);
sewardjc3a47092006-02-18 23:13:33 +00001615 CALL_FN_W_12W(err, fn, sendbuf,sendcount,sendtype,dest,sendtag,
1616 recvbuf,recvcount,recvtype,source,recvtag,
1617 comm,status);
1618 if (err == MPI_SUCCESS
1619 && count_from_Status(&recvcount_actual,recvtype,status)) {
njndbf7ca72006-03-31 11:57:59 +00001620 make_mem_defined_if_addressable(recvbuf, recvcount_actual, recvtype);
sewardjc3a47092006-02-18 23:13:33 +00001621 }
1622 after("Sendrecv", err);
1623 return err;
1624}
1625
sewardjc3a47092006-02-18 23:13:33 +00001626
1627/*------------------------------------------------------------*/
1628/*--- ---*/
1629/*--- Sec 3.12, Derived datatypes ---*/
1630/*--- ---*/
1631/*------------------------------------------------------------*/
1632
1633/* --- Address --- */
1634/* Does this have anything worth checking? */
sewardj9c969c32006-03-10 18:37:45 +00001635HAS_NO_WRAPPER(Address)
1636
1637/* --- MPI 2 stuff --- */
1638/* Type_extent, Type_get_contents and Type_get_envelope sometimes get
1639 used intensively by the type walker (walk_type). There's no reason
1640 why they couldn't be properly wrapped if needed, but doing so slows
1641 everything down, so don't bother until needed. */
1642HAS_NO_WRAPPER(Type_extent)
1643HAS_NO_WRAPPER(Type_get_contents)
1644HAS_NO_WRAPPER(Type_get_envelope)
1645
1646/* --- Type_commit --- */
1647int WRAPPER_FOR(PMPI_Type_commit)( MPI_Datatype* ty )
1648{
1649 OrigFn fn;
1650 int err;
1651 VALGRIND_GET_ORIG_FN(fn);
1652 before("Type_commit");
njndbf7ca72006-03-31 11:57:59 +00001653 check_mem_is_defined_untyped(ty, sizeof(*ty));
sewardj9c969c32006-03-10 18:37:45 +00001654 CALL_FN_W_W(err, fn, ty);
1655 after("Type_commit", err);
1656 return err;
1657}
1658
1659/* --- Type_free --- */
1660int WRAPPER_FOR(PMPI_Type_free)( MPI_Datatype* ty )
1661{
1662 OrigFn fn;
1663 int err;
1664 VALGRIND_GET_ORIG_FN(fn);
1665 before("Type_free");
njndbf7ca72006-03-31 11:57:59 +00001666 check_mem_is_defined_untyped(ty, sizeof(*ty));
sewardj9c969c32006-03-10 18:37:45 +00001667 CALL_FN_W_W(err, fn, ty);
1668 after("Type_free", err);
1669 return err;
1670}
sewardjc3a47092006-02-18 23:13:33 +00001671
1672
1673/*------------------------------------------------------------*/
1674/*--- ---*/
sewardjee346592007-02-08 12:05:03 +00001675/*--- Sec 3.13, Pack and unpack ---*/
1676/*--- ---*/
1677/*------------------------------------------------------------*/
1678
1679/* --- Pack --- */
1680/* pre: must be readable: position
1681 must be readable: (inbuf,incount,datatype)
1682 must be writable: outbuf[0 .. outsize-1]
1683 must be writable: outbuf[*position ..
1684 *position - 1
1685 + however much space PMPI_Pack_size
1686 says we will need]
1687 post: make readable: outbuf[old *position .. new *position]
1688*/
1689int WRAPPER_FOR(PMPI_Pack)( void* inbuf, int incount, MPI_Datatype datatype,
1690 void* outbuf, int outsize,
1691 int* position, MPI_Comm comm )
1692{
1693 OrigFn fn;
1694 int err, szB = 0;
1695 int position_ORIG = *position;
1696 VALGRIND_GET_ORIG_FN(fn);
1697 before("Pack");
1698 /* stay sane */
1699 check_mem_is_defined_untyped(position, sizeof(*position));
1700 /* check input */
1701 check_mem_is_defined(inbuf, incount, datatype);
1702 /* check output area's stated bounds make sense */
1703 check_mem_is_addressable_untyped(outbuf, outsize);
1704 /* check output area's actual used size properly */
1705 err = PMPI_Pack_size( incount, datatype, comm, &szB );
1706 if (err == MPI_SUCCESS && szB > 0) {
1707 check_mem_is_addressable_untyped(
1708 ((char*)outbuf) + position_ORIG, szB
1709 );
1710 }
1711
1712 CALL_FN_W_7W(err, fn, inbuf,incount,datatype, outbuf,outsize,position, comm);
1713
1714 if (err == MPI_SUCCESS && (*position) > position_ORIG) {
1715 /* paint output */
1716 make_mem_defined_if_addressable_untyped(
1717 ((char*)outbuf) + position_ORIG, *position - position_ORIG
1718 );
1719 }
1720 after("Pack", err);
1721 return err;
1722}
1723
1724/* --- Unpack --- */
1725/* pre: must be readable: position
1726 must be writable: (outbuf,outcount,datatype)
1727 must be writable: outbuf[0 .. outsize-1]
1728 must be writable: outbuf[*position ..
1729 *position - 1
1730 + however much space PMPI_Pack_size
1731 says we will need]
1732 post: make readable: (outbuf,outcount,datatype)
1733 and also do a readability check of
1734 inbuf[old *position .. new *position]
1735*/
1736int WRAPPER_FOR(PMPI_Unpack)( void* inbuf, int insize, int* position,
1737 void* outbuf, int outcount, MPI_Datatype datatype,
1738 MPI_Comm comm )
1739{
1740 OrigFn fn;
1741 int err, szB = 0;
1742 int position_ORIG = *position;
1743 VALGRIND_GET_ORIG_FN(fn);
1744 before("Unpack");
1745 /* stay sane */
1746 check_mem_is_defined_untyped(position, sizeof(*position));
1747 /* check output area is accessible */
1748 check_mem_is_addressable(outbuf, outcount, datatype);
1749 /* check input area's stated bounds make sense */
1750 check_mem_is_addressable_untyped(inbuf, insize);
1751 /* check input area's actual used size properly */
1752 err = PMPI_Pack_size( outcount, datatype, comm, &szB );
1753 if (err == MPI_SUCCESS && szB > 0) {
1754 check_mem_is_addressable_untyped(
1755 ((char*)inbuf) + position_ORIG, szB
1756 );
1757 }
1758
1759 CALL_FN_W_7W(err, fn, inbuf,insize,position, outbuf,outcount,datatype, comm);
1760
1761 if (err == MPI_SUCCESS && (*position) > position_ORIG) {
1762 /* recheck input more carefully */
1763 check_mem_is_defined_untyped(
1764 ((char*)inbuf) + position_ORIG, *position - position_ORIG
1765 );
1766 /* paint output */
1767 make_mem_defined_if_addressable( outbuf, outcount, datatype );
1768 }
1769 after("Unpack", err);
1770 return err;
1771}
1772
1773
1774/*------------------------------------------------------------*/
1775/*--- ---*/
sewardjc3a47092006-02-18 23:13:33 +00001776/*--- Sec 4.4, Broadcast ---*/
1777/*--- ---*/
1778/*------------------------------------------------------------*/
1779
1780/* --- Bcast --- */
1781/* pre: must-be-readable (buffer,count,datatype) for rank==root
1782 must-be-writable (buffer,count,datatype) for rank!=root
1783 post: make-readable (buffer,count,datatype) for all
1784
1785 Resulting behaviour is: if root sends uninitialised stuff, then
1786 V complains, but then all ranks, including itself, see the buffer
1787 as initialised after that.
1788*/
1789int WRAPPER_FOR(PMPI_Bcast)(void *buffer, int count,
1790 MPI_Datatype datatype,
1791 int root, MPI_Comm comm)
1792{
1793 OrigFn fn;
1794 int err;
1795 Bool i_am_sender;
1796 VALGRIND_GET_ORIG_FN(fn);
1797 before("Bcast");
1798 i_am_sender = root == comm_rank(comm);
1799 if (i_am_sender) {
njndbf7ca72006-03-31 11:57:59 +00001800 check_mem_is_defined(buffer, count, datatype);
sewardjc3a47092006-02-18 23:13:33 +00001801 } else {
njndbf7ca72006-03-31 11:57:59 +00001802 check_mem_is_addressable(buffer, count, datatype);
sewardjc3a47092006-02-18 23:13:33 +00001803 }
1804 CALL_FN_W_5W(err, fn, buffer,count,datatype,root,comm);
njndbf7ca72006-03-31 11:57:59 +00001805 make_mem_defined_if_addressable_if_success(err, buffer, count, datatype);
sewardjc3a47092006-02-18 23:13:33 +00001806 after("Bcast", err);
1807 return err;
1808}
1809
1810
1811/*------------------------------------------------------------*/
1812/*--- ---*/
1813/*--- Sec 4.5, Gather ---*/
1814/*--- ---*/
1815/*------------------------------------------------------------*/
1816
1817/* --- Gather --- */
1818/* JRS 20060217: I don't really understand this. Each process is
1819 going to send sendcount items of type sendtype to the root. So
1820 the root is going to receive comm_size*sendcount items of type
1821 sendtype (right?) So why specify recvcount and recvtype?
1822
1823 Anyway, assuming the MPI Spec is correct (seems likely :-) we have:
1824
1825 pre: (all) must be readable: (sendbuf,sendcount,sendtype)
1826 (root only): must be writable: (recvbuf,recvcount * comm_size,recvtype)
1827 post: (root only): make readable: (recvbuf,recvcount * comm_size,recvtype)
1828*/
1829int WRAPPER_FOR(PMPI_Gather)(
1830 void *sendbuf, int sendcount, MPI_Datatype sendtype,
1831 void *recvbuf, int recvcount, MPI_Datatype recvtype,
1832 int root, MPI_Comm comm)
1833{
1834 OrigFn fn;
1835 int err, me, sz;
1836 VALGRIND_GET_ORIG_FN(fn);
1837 before("Gather");
1838 me = comm_rank(comm);
1839 sz = comm_size(comm);
njndbf7ca72006-03-31 11:57:59 +00001840 check_mem_is_defined(sendbuf, sendcount, sendtype);
sewardjc3a47092006-02-18 23:13:33 +00001841 if (me == root)
njndbf7ca72006-03-31 11:57:59 +00001842 check_mem_is_addressable(recvbuf, recvcount * sz, recvtype);
sewardjc3a47092006-02-18 23:13:33 +00001843 CALL_FN_W_8W(err, fn, sendbuf,sendcount,sendtype,
1844 recvbuf,recvcount,recvtype,
1845 root,comm);
sewardjb727b542006-03-10 21:41:01 +00001846 if (me == root)
njndbf7ca72006-03-31 11:57:59 +00001847 make_mem_defined_if_addressable_if_success(err, recvbuf, recvcount * sz, recvtype);
sewardjc3a47092006-02-18 23:13:33 +00001848 after("Gather", err);
1849 return err;
1850}
1851
1852
1853/*------------------------------------------------------------*/
1854/*--- ---*/
sewardjb727b542006-03-10 21:41:01 +00001855/*--- Sec 4.6, Scatter ---*/
1856/*--- ---*/
1857/*------------------------------------------------------------*/
1858
1859/* pre: (root only): must be readable: (sendbuf,sendcount * comm_size,sendtype)
1860 (all): must be writable: (recvbuf,recvbuf,recvtype)
1861 post: (all): make defined: (recvbuf,recvbuf,recvtype)
1862*/
1863int WRAPPER_FOR(PMPI_Scatter)(
1864 void* sendbuf, int sendcount, MPI_Datatype sendtype,
1865 void* recvbuf, int recvcount, MPI_Datatype recvtype,
1866 int root, MPI_Comm comm)
1867{
1868 OrigFn fn;
1869 int err, me, sz;
1870 VALGRIND_GET_ORIG_FN(fn);
1871 before("Scatter");
1872 me = comm_rank(comm);
1873 sz = comm_size(comm);
njndbf7ca72006-03-31 11:57:59 +00001874 check_mem_is_addressable(recvbuf, recvcount, recvtype);
sewardjb727b542006-03-10 21:41:01 +00001875 if (me == root)
njndbf7ca72006-03-31 11:57:59 +00001876 check_mem_is_defined(sendbuf, sendcount * sz, sendtype);
sewardjb727b542006-03-10 21:41:01 +00001877 CALL_FN_W_8W(err, fn, sendbuf,sendcount,sendtype,
1878 recvbuf,recvcount,recvtype,
1879 root,comm);
njndbf7ca72006-03-31 11:57:59 +00001880 make_mem_defined_if_addressable_if_success(err, recvbuf, recvcount, recvtype);
sewardjb727b542006-03-10 21:41:01 +00001881 after("Scatter", err);
1882 return err;
1883}
1884
1885
1886/*------------------------------------------------------------*/
1887/*--- ---*/
1888/*--- Sec 4.8, All-to-All Scatter/Gather ---*/
1889/*--- ---*/
1890/*------------------------------------------------------------*/
1891
1892/* pre: (all) must be readable: (sendbuf,sendcount * comm_size,sendtype)
1893 (all) must be writable: (recvbuf,recvcount * comm_size,recvtype)
1894 post: (all) make defined: (recvbuf,recvcount * comm_size,recvtype)
1895*/
1896int WRAPPER_FOR(PMPI_Alltoall)(
1897 void* sendbuf, int sendcount, MPI_Datatype sendtype,
1898 void* recvbuf, int recvcount, MPI_Datatype recvtype,
1899 MPI_Comm comm)
1900{
1901 OrigFn fn;
1902 int err, sz;
1903 VALGRIND_GET_ORIG_FN(fn);
1904 before("Alltoall");
1905 sz = comm_size(comm);
njndbf7ca72006-03-31 11:57:59 +00001906 check_mem_is_defined(sendbuf, sendcount * sz, sendtype);
1907 check_mem_is_addressable(recvbuf, recvcount * sz, recvtype);
sewardjb727b542006-03-10 21:41:01 +00001908 CALL_FN_W_7W(err, fn, sendbuf,sendcount,sendtype,
1909 recvbuf,recvcount,recvtype,
1910 comm);
njndbf7ca72006-03-31 11:57:59 +00001911 make_mem_defined_if_addressable_if_success(err, recvbuf, recvcount * sz, recvtype);
sewardjb727b542006-03-10 21:41:01 +00001912 after("Alltoall", err);
1913 return err;
1914}
1915
1916
1917/*------------------------------------------------------------*/
1918/*--- ---*/
sewardjc3a47092006-02-18 23:13:33 +00001919/*--- Sec 4.9, Global Reduction Operations ---*/
1920/*--- ---*/
1921/*------------------------------------------------------------*/
1922
1923/* --- Reduce --- */
1924/* rd: (sendbuf,count,datatype) for all
1925 wr: (recvbuf,count,datatype) but only for rank == root
1926*/
1927int WRAPPER_FOR(PMPI_Reduce)(void *sendbuf, void *recvbuf,
1928 int count,
1929 MPI_Datatype datatype, MPI_Op op,
1930 int root, MPI_Comm comm)
1931{
1932 OrigFn fn;
1933 int err;
1934 Bool i_am_root;
1935 VALGRIND_GET_ORIG_FN(fn);
1936 before("Reduce");
1937 i_am_root = root == comm_rank(comm);
njndbf7ca72006-03-31 11:57:59 +00001938 check_mem_is_defined(sendbuf, count, datatype);
sewardjc3a47092006-02-18 23:13:33 +00001939 if (i_am_root)
njndbf7ca72006-03-31 11:57:59 +00001940 check_mem_is_addressable(recvbuf, count, datatype);
sewardjc3a47092006-02-18 23:13:33 +00001941 CALL_FN_W_7W(err, fn, sendbuf,recvbuf,count,datatype,op,root,comm);
1942 if (i_am_root)
njndbf7ca72006-03-31 11:57:59 +00001943 make_mem_defined_if_addressable_if_success(err, recvbuf, count, datatype);
sewardjc3a47092006-02-18 23:13:33 +00001944 after("Reduce", err);
1945 return err;
1946}
1947
1948
1949/* --- Allreduce --- */
1950/* rd: (sendbuf,count,datatype) for all
1951 wr: (recvbuf,count,datatype) for all
1952*/
1953int WRAPPER_FOR(PMPI_Allreduce)(void *sendbuf, void *recvbuf,
1954 int count,
1955 MPI_Datatype datatype, MPI_Op op,
1956 MPI_Comm comm)
1957{
1958 OrigFn fn;
1959 int err;
1960 VALGRIND_GET_ORIG_FN(fn);
1961 before("Allreduce");
njndbf7ca72006-03-31 11:57:59 +00001962 check_mem_is_defined(sendbuf, count, datatype);
1963 check_mem_is_addressable(recvbuf, count, datatype);
sewardjc3a47092006-02-18 23:13:33 +00001964 CALL_FN_W_6W(err, fn, sendbuf,recvbuf,count,datatype,op,comm);
njndbf7ca72006-03-31 11:57:59 +00001965 make_mem_defined_if_addressable_if_success(err, recvbuf, count, datatype);
sewardjc3a47092006-02-18 23:13:33 +00001966 after("Allreduce", err);
1967 return err;
1968}
1969
1970
1971/* --- Op_create --- */
1972/* This is a bit dubious. I suppose it takes 'function' and
1973 writes something at *op, but who knows what an MPI_Op is?
1974 Can we safely do 'sizeof' on it? */
1975int WRAPPER_FOR(PMPI_Op_create)( MPI_User_function* function,
1976 int commute,
1977 MPI_Op* op )
1978{
1979 OrigFn fn;
1980 int err;
1981 VALGRIND_GET_ORIG_FN(fn);
1982 before("Op_create");
njndbf7ca72006-03-31 11:57:59 +00001983 check_mem_is_addressable_untyped(op, sizeof(*op));
sewardjc3a47092006-02-18 23:13:33 +00001984 CALL_FN_W_WWW(err, fn, function,commute,op);
njndbf7ca72006-03-31 11:57:59 +00001985 make_mem_defined_if_addressable_if_success_untyped(err, op, sizeof(*op));
sewardjc3a47092006-02-18 23:13:33 +00001986 after("Op_create", err);
1987 return err;
1988}
1989
1990
1991/*------------------------------------------------------------*/
1992/*--- ---*/
1993/*--- Sec 5.4, Communicator management ---*/
1994/*--- ---*/
1995/*------------------------------------------------------------*/
1996
1997/* Hardly seems worth wrapping Comm_rank and Comm_size, but
1998 since it's done now .. */
1999
sewardj9c969c32006-03-10 18:37:45 +00002000/* --- Comm_create --- */
2001/* Let normal memcheck tracking handle this. */
2002int WRAPPER_FOR(PMPI_Comm_create)(MPI_Comm comm, MPI_Group group,
2003 MPI_Comm* newcomm)
2004{
2005 OrigFn fn;
2006 int err;
2007 VALGRIND_GET_ORIG_FN(fn);
2008 before("Comm_create");
2009 CALL_FN_W_WWW(err, fn, comm,group,newcomm);
2010 after("Comm_create", err);
2011 return err;
2012}
2013
2014/* --- Comm_dup --- */
2015/* Let normal memcheck tracking handle this. */
2016int WRAPPER_FOR(PMPI_Comm_dup)(MPI_Comm comm, MPI_Comm* newcomm)
2017{
2018 OrigFn fn;
2019 int err;
2020 VALGRIND_GET_ORIG_FN(fn);
2021 before("Comm_dup");
2022 CALL_FN_W_WW(err, fn, comm,newcomm);
2023 after("Comm_dup", err);
2024 return err;
2025}
2026
2027/* --- Comm_free --- */
2028/* Let normal memcheck tracking handle this. */
2029int WRAPPER_FOR(PMPI_Comm_free)(MPI_Comm* comm)
2030{
2031 OrigFn fn;
2032 int err;
2033 VALGRIND_GET_ORIG_FN(fn);
2034 before("Comm_free");
2035 CALL_FN_W_W(err, fn, comm);
2036 after("Comm_free", err);
2037 return err;
2038}
2039
sewardjc3a47092006-02-18 23:13:33 +00002040/* --- Comm_rank --- */
2041/* wr: (rank, sizeof(*rank)) */
2042int WRAPPER_FOR(PMPI_Comm_rank)(MPI_Comm comm, int *rank)
2043{
2044 OrigFn fn;
2045 int err;
2046 VALGRIND_GET_ORIG_FN(fn);
2047 before("Comm_rank");
njndbf7ca72006-03-31 11:57:59 +00002048 check_mem_is_addressable_untyped(rank, sizeof(*rank));
sewardjc3a47092006-02-18 23:13:33 +00002049 CALL_FN_W_WW(err, fn, comm,rank);
njndbf7ca72006-03-31 11:57:59 +00002050 make_mem_defined_if_addressable_if_success_untyped(err, rank, sizeof(*rank));
sewardjc3a47092006-02-18 23:13:33 +00002051 after("Comm_rank", err);
2052 return err;
2053}
2054
sewardjc3a47092006-02-18 23:13:33 +00002055/* --- Comm_size --- */
2056/* wr: (size, sizeof(*size)) */
2057int WRAPPER_FOR(PMPI_Comm_size)(MPI_Comm comm, int *size)
2058{
2059 OrigFn fn;
2060 int err;
2061 VALGRIND_GET_ORIG_FN(fn);
2062 before("Comm_size");
njndbf7ca72006-03-31 11:57:59 +00002063 check_mem_is_addressable_untyped(size, sizeof(*size));
sewardjc3a47092006-02-18 23:13:33 +00002064 CALL_FN_W_WW(err, fn, comm,size);
njndbf7ca72006-03-31 11:57:59 +00002065 make_mem_defined_if_addressable_if_success_untyped(err, size, sizeof(*size));
sewardjc3a47092006-02-18 23:13:33 +00002066 after("Comm_size", err);
2067 return err;
2068}
2069
2070
2071/*------------------------------------------------------------*/
2072/*--- ---*/
2073/*--- Sec 5.7, Caching ---*/
2074/*--- ---*/
2075/*------------------------------------------------------------*/
2076
sewardjc3a47092006-02-18 23:13:33 +00002077
2078/*------------------------------------------------------------*/
2079/*--- ---*/
sewardj7d3f4bb2006-03-08 15:27:37 +00002080/*--- Sec 7.3, Error codes and classes ---*/
2081/*--- ---*/
2082/*------------------------------------------------------------*/
2083
2084/* --- Error_string --- */
sewardj9c969c32006-03-10 18:37:45 +00002085int WRAPPER_FOR(PMPI_Error_string)( int errorcode, char* string,
2086 int* resultlen )
sewardj7d3f4bb2006-03-08 15:27:37 +00002087{
2088 OrigFn fn;
2089 int err;
2090 VALGRIND_GET_ORIG_FN(fn);
2091 before("Error_string");
njndbf7ca72006-03-31 11:57:59 +00002092 check_mem_is_addressable_untyped(resultlen, sizeof(int));
2093 check_mem_is_addressable_untyped(string, MPI_MAX_ERROR_STRING);
sewardj7d3f4bb2006-03-08 15:27:37 +00002094 CALL_FN_W_WWW(err, fn, errorcode,string,resultlen);
2095 /* Don't bother to paint the result; we assume the real function
2096 will have filled it with defined characters :-) */
2097 after("Error_string", err);
2098 return err;
2099}
2100
2101
2102/*------------------------------------------------------------*/
2103/*--- ---*/
sewardjc3a47092006-02-18 23:13:33 +00002104/*--- Sec 7.5, Startup ---*/
2105/*--- ---*/
2106/*------------------------------------------------------------*/
2107
2108/* --- Init --- */
2109/* rd: *argc, *argv[0 .. *argc-1] */
sewardjd465d992006-10-17 01:46:55 +00002110long WRAPPER_FOR(PMPI_Init)(int *argc, char ***argv)
sewardjc3a47092006-02-18 23:13:33 +00002111{
2112 OrigFn fn;
2113 int err;
2114 VALGRIND_GET_ORIG_FN(fn);
2115 before("Init");
sewardj1ba0e9b2008-12-08 10:27:31 +00002116 if (argc) {
2117 check_mem_is_defined_untyped(argc, sizeof(int));
2118 }
2119 if (argc && argv) {
2120 check_mem_is_defined_untyped(*argv, *argc * sizeof(char**));
2121 }
sewardjc3a47092006-02-18 23:13:33 +00002122 CALL_FN_W_WW(err, fn, argc,argv);
2123 after("Init", err);
sewardjd465d992006-10-17 01:46:55 +00002124 if (opt_initkludge)
2125 return (long)(void*)&mpiwrap_walk_type_EXTERNALLY_VISIBLE;
2126 else
2127 return (long)err;
sewardjc3a47092006-02-18 23:13:33 +00002128}
2129
2130/* --- Initialized --- */
2131int WRAPPER_FOR(PMPI_Initialized)(int* flag)
2132{
2133 OrigFn fn;
2134 int err;
2135 VALGRIND_GET_ORIG_FN(fn);
2136 before("Initialized");
njndbf7ca72006-03-31 11:57:59 +00002137 check_mem_is_addressable_untyped(flag, sizeof(int));
sewardjc3a47092006-02-18 23:13:33 +00002138 CALL_FN_W_W(err, fn, flag);
njndbf7ca72006-03-31 11:57:59 +00002139 make_mem_defined_if_addressable_if_success_untyped(err, flag, sizeof(int));
sewardjc3a47092006-02-18 23:13:33 +00002140 after("Initialized", err);
2141 return err;
2142}
2143
2144/* --- Finalize --- */
2145int WRAPPER_FOR(PMPI_Finalize)(void)
2146{
2147 OrigFn fn;
2148 int err;
2149 VALGRIND_GET_ORIG_FN(fn);
2150 before("Finalize");
2151 CALL_FN_W_v(err, fn);
2152 after("Finalize", err);
2153 return err;
2154}
2155
2156
2157/*------------------------------------------------------------*/
2158/*--- ---*/
sewardj63daa8a2006-03-09 19:08:20 +00002159/*--- Default wrappers for all remaining functions ---*/
sewardjc3a47092006-02-18 23:13:33 +00002160/*--- ---*/
2161/*------------------------------------------------------------*/
2162
sewardj9c969c32006-03-10 18:37:45 +00002163/* Boilerplate for default wrappers. */
sewardj63daa8a2006-03-09 19:08:20 +00002164#define DEFAULT_WRAPPER_PREAMBLE(basename) \
2165 OrigFn fn; \
2166 UWord res; \
sewardj0d17f242006-03-28 01:02:38 +00002167 static int complaints = 1; \
sewardj63daa8a2006-03-09 19:08:20 +00002168 VALGRIND_GET_ORIG_FN(fn); \
2169 before(#basename); \
2170 if (opt_missing >= 2) { \
2171 barf("no wrapper for PMPI_" #basename \
2172 ",\n\t\t\t and you have " \
2173 "requested strict checking"); \
2174 } \
2175 if (opt_missing == 1 && complaints > 0) { \
2176 fprintf(stderr, "%s %5d: warning: no wrapper " \
2177 "for PMPI_" #basename "\n", \
2178 preamble, my_pid); \
2179 complaints--; \
2180 } \
2181
2182#define DEFAULT_WRAPPER_W_0W(basename) \
2183 UWord WRAPPER_FOR(PMPI_##basename)( void ) \
2184 { \
2185 DEFAULT_WRAPPER_PREAMBLE(basename) \
2186 CALL_FN_W_v(res, fn); \
2187 return res; \
2188 }
2189
2190#define DEFAULT_WRAPPER_W_1W(basename) \
2191 UWord WRAPPER_FOR(PMPI_##basename)( UWord a1 ) \
2192 { \
2193 DEFAULT_WRAPPER_PREAMBLE(basename) \
2194 CALL_FN_W_W(res, fn, a1); \
2195 return res; \
2196 }
2197
2198#define DEFAULT_WRAPPER_W_2W(basename) \
2199 UWord WRAPPER_FOR(PMPI_##basename)( UWord a1, UWord a2 ) \
2200 { \
2201 DEFAULT_WRAPPER_PREAMBLE(basename) \
2202 CALL_FN_W_WW(res, fn, a1,a2); \
2203 return res; \
2204 }
2205
2206#define DEFAULT_WRAPPER_W_3W(basename) \
2207 UWord WRAPPER_FOR(PMPI_##basename) \
2208 ( UWord a1, UWord a2, UWord a3 ) \
2209 { \
2210 DEFAULT_WRAPPER_PREAMBLE(basename) \
2211 CALL_FN_W_WWW(res, fn, a1,a2,a3); \
2212 return res; \
2213 }
2214
2215#define DEFAULT_WRAPPER_W_4W(basename) \
2216 UWord WRAPPER_FOR(PMPI_##basename) \
2217 ( UWord a1, UWord a2, UWord a3, UWord a4 ) \
2218 { \
2219 DEFAULT_WRAPPER_PREAMBLE(basename) \
2220 CALL_FN_W_WWWW(res, fn, a1,a2,a3,a4); \
2221 return res; \
2222 }
2223
2224#define DEFAULT_WRAPPER_W_5W(basename) \
2225 UWord WRAPPER_FOR(PMPI_##basename) \
2226 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5 ) \
2227 { \
2228 DEFAULT_WRAPPER_PREAMBLE(basename) \
2229 CALL_FN_W_5W(res, fn, a1,a2,a3,a4,a5); \
2230 return res; \
2231 }
2232
2233#define DEFAULT_WRAPPER_W_6W(basename) \
2234 UWord WRAPPER_FOR(PMPI_##basename) \
2235 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2236 UWord a6 ) \
2237 { \
2238 DEFAULT_WRAPPER_PREAMBLE(basename) \
2239 CALL_FN_W_6W(res, fn, a1,a2,a3,a4,a5,a6); \
2240 return res; \
2241 }
2242
2243#define DEFAULT_WRAPPER_W_7W(basename) \
2244 UWord WRAPPER_FOR(PMPI_##basename) \
2245 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2246 UWord a6, UWord a7 ) \
2247 { \
2248 DEFAULT_WRAPPER_PREAMBLE(basename) \
2249 CALL_FN_W_7W(res, fn, a1,a2,a3,a4,a5,a6,a7); \
2250 return res; \
2251 }
2252
2253#define DEFAULT_WRAPPER_W_8W(basename) \
2254 UWord WRAPPER_FOR(PMPI_##basename) \
2255 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2256 UWord a6, UWord a7, UWord a8 ) \
2257 { \
2258 DEFAULT_WRAPPER_PREAMBLE(basename) \
2259 CALL_FN_W_8W(res, fn, a1,a2,a3,a4,a5,a6,a7,a8); \
2260 return res; \
2261 }
2262
2263#define DEFAULT_WRAPPER_W_9W(basename) \
2264 UWord WRAPPER_FOR(PMPI_##basename) \
2265 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2266 UWord a6, UWord a7, UWord a8, UWord a9 ) \
2267 { \
2268 DEFAULT_WRAPPER_PREAMBLE(basename) \
2269 CALL_FN_W_9W(res, fn, a1,a2,a3,a4,a5,a6,a7,a8,a9); \
2270 return res; \
2271 }
2272
2273#define DEFAULT_WRAPPER_W_10W(basename) \
2274 UWord WRAPPER_FOR(PMPI_##basename) \
2275 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2276 UWord a6, UWord a7, UWord a8, UWord a9, UWord a10 ) \
2277 { \
2278 DEFAULT_WRAPPER_PREAMBLE(basename) \
2279 CALL_FN_W_10W(res, fn, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10); \
2280 return res; \
2281 }
2282
2283#define DEFAULT_WRAPPER_W_12W(basename) \
2284 UWord WRAPPER_FOR(PMPI_##basename) \
2285 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2286 UWord a6, UWord a7, UWord a8, UWord a9, UWord a10, \
2287 UWord a11, UWord a12 ) \
2288 { \
2289 DEFAULT_WRAPPER_PREAMBLE(basename) \
2290 CALL_FN_W_12W(res, fn, a1,a2,a3,a4,a5,a6, \
2291 a7,a8,a9,a10,a11,a12); \
2292 return res; \
2293 }
2294
2295
2296/* Canned summary of MPI-1.1/MPI-2 entry points, as derived from mpi.h
2297 from Open MPI svn rev 9191 (somewhere between Open MPI versions
2298 1.0.1 and 1.1.0). */
2299
2300/* If a function is commented out in this list, it's because it has a
2301 proper wrapper written elsewhere (above here). */
2302
2303DEFAULT_WRAPPER_W_2W(Abort)
2304DEFAULT_WRAPPER_W_9W(Accumulate)
2305DEFAULT_WRAPPER_W_1W(Add_error_class)
2306DEFAULT_WRAPPER_W_2W(Add_error_code)
2307DEFAULT_WRAPPER_W_2W(Add_error_string)
sewardj9c969c32006-03-10 18:37:45 +00002308/* DEFAULT_WRAPPER_W_2W(Address) */
sewardj63daa8a2006-03-09 19:08:20 +00002309DEFAULT_WRAPPER_W_7W(Allgather)
2310DEFAULT_WRAPPER_W_8W(Allgatherv)
2311DEFAULT_WRAPPER_W_3W(Alloc_mem)
2312/* DEFAULT_WRAPPER_W_6W(Allreduce) */
sewardjb727b542006-03-10 21:41:01 +00002313/* DEFAULT_WRAPPER_W_7W(Alltoall) */
sewardj63daa8a2006-03-09 19:08:20 +00002314DEFAULT_WRAPPER_W_9W(Alltoallv)
2315DEFAULT_WRAPPER_W_9W(Alltoallw)
2316DEFAULT_WRAPPER_W_2W(Attr_delete)
2317DEFAULT_WRAPPER_W_4W(Attr_get)
2318DEFAULT_WRAPPER_W_3W(Attr_put)
2319DEFAULT_WRAPPER_W_1W(Barrier)
2320/* DEFAULT_WRAPPER_W_5W(Bcast) */
sewardj9c969c32006-03-10 18:37:45 +00002321/* DEFAULT_WRAPPER_W_6W(Bsend) */
sewardj63daa8a2006-03-09 19:08:20 +00002322DEFAULT_WRAPPER_W_7W(Bsend_init)
2323DEFAULT_WRAPPER_W_2W(Buffer_attach)
2324DEFAULT_WRAPPER_W_2W(Buffer_detach)
sewardjb727b542006-03-10 21:41:01 +00002325/* DEFAULT_WRAPPER_W_1W(Cancel) */
sewardj63daa8a2006-03-09 19:08:20 +00002326DEFAULT_WRAPPER_W_4W(Cart_coords)
2327DEFAULT_WRAPPER_W_6W(Cart_create)
2328DEFAULT_WRAPPER_W_5W(Cart_get)
2329DEFAULT_WRAPPER_W_5W(Cart_map)
2330DEFAULT_WRAPPER_W_3W(Cart_rank)
2331DEFAULT_WRAPPER_W_5W(Cart_shift)
2332DEFAULT_WRAPPER_W_3W(Cart_sub)
2333DEFAULT_WRAPPER_W_2W(Cartdim_get)
2334DEFAULT_WRAPPER_W_1W(Close_port)
2335DEFAULT_WRAPPER_W_5W(Comm_accept)
2336DEFAULT_WRAPPER_W_1W(Comm_c2f)
2337DEFAULT_WRAPPER_W_2W(Comm_call_errhandler)
2338DEFAULT_WRAPPER_W_3W(Comm_compare)
2339DEFAULT_WRAPPER_W_5W(Comm_connect)
2340DEFAULT_WRAPPER_W_2W(Comm_create_errhandler)
2341DEFAULT_WRAPPER_W_4W(Comm_create_keyval)
sewardj9c969c32006-03-10 18:37:45 +00002342/* DEFAULT_WRAPPER_W_3W(Comm_create) */
sewardj63daa8a2006-03-09 19:08:20 +00002343DEFAULT_WRAPPER_W_2W(Comm_delete_attr)
2344DEFAULT_WRAPPER_W_1W(Comm_disconnect)
sewardj9c969c32006-03-10 18:37:45 +00002345/* DEFAULT_WRAPPER_W_2W(Comm_dup) */
sewardj63daa8a2006-03-09 19:08:20 +00002346DEFAULT_WRAPPER_W_1W(Comm_f2c)
2347DEFAULT_WRAPPER_W_1W(Comm_free_keyval)
sewardj9c969c32006-03-10 18:37:45 +00002348/* DEFAULT_WRAPPER_W_1W(Comm_free) */
sewardj63daa8a2006-03-09 19:08:20 +00002349DEFAULT_WRAPPER_W_4W(Comm_get_attr)
2350DEFAULT_WRAPPER_W_2W(Comm_get_errhandler)
2351DEFAULT_WRAPPER_W_3W(Comm_get_name)
2352DEFAULT_WRAPPER_W_1W(Comm_get_parent)
2353DEFAULT_WRAPPER_W_2W(Comm_group)
2354DEFAULT_WRAPPER_W_2W(Comm_join)
2355/* DEFAULT_WRAPPER_W_2W(Comm_rank) */
2356DEFAULT_WRAPPER_W_2W(Comm_remote_group)
2357DEFAULT_WRAPPER_W_2W(Comm_remote_size)
2358DEFAULT_WRAPPER_W_3W(Comm_set_attr)
2359DEFAULT_WRAPPER_W_2W(Comm_set_errhandler)
2360DEFAULT_WRAPPER_W_2W(Comm_set_name)
2361/* DEFAULT_WRAPPER_W_2W(Comm_size) */
2362DEFAULT_WRAPPER_W_8W(Comm_spawn)
2363DEFAULT_WRAPPER_W_9W(Comm_spawn_multiple)
2364DEFAULT_WRAPPER_W_4W(Comm_split)
2365DEFAULT_WRAPPER_W_2W(Comm_test_inter)
2366DEFAULT_WRAPPER_W_3W(Dims_create)
2367DEFAULT_WRAPPER_W_1W(Errhandler_c2f)
2368DEFAULT_WRAPPER_W_2W(Errhandler_create)
2369DEFAULT_WRAPPER_W_1W(Errhandler_f2c)
2370DEFAULT_WRAPPER_W_1W(Errhandler_free)
2371DEFAULT_WRAPPER_W_2W(Errhandler_get)
2372DEFAULT_WRAPPER_W_2W(Errhandler_set)
2373DEFAULT_WRAPPER_W_2W(Error_class)
2374/* DEFAULT_WRAPPER_W_3W(Error_string) */
2375DEFAULT_WRAPPER_W_6W(Exscan)
2376DEFAULT_WRAPPER_W_1W(File_c2f)
2377DEFAULT_WRAPPER_W_1W(File_f2c)
2378DEFAULT_WRAPPER_W_2W(File_call_errhandler)
2379DEFAULT_WRAPPER_W_2W(File_create_errhandler)
2380DEFAULT_WRAPPER_W_2W(File_set_errhandler)
2381DEFAULT_WRAPPER_W_2W(File_get_errhandler)
2382DEFAULT_WRAPPER_W_5W(File_open)
2383DEFAULT_WRAPPER_W_1W(File_close)
2384DEFAULT_WRAPPER_W_2W(File_delete)
2385DEFAULT_WRAPPER_W_2W(File_set_size)
2386DEFAULT_WRAPPER_W_2W(File_preallocate)
2387DEFAULT_WRAPPER_W_2W(File_get_size)
2388DEFAULT_WRAPPER_W_2W(File_get_group)
2389DEFAULT_WRAPPER_W_2W(File_get_amode)
2390DEFAULT_WRAPPER_W_2W(File_set_info)
2391DEFAULT_WRAPPER_W_2W(File_get_info)
2392DEFAULT_WRAPPER_W_6W(File_set_view)
2393DEFAULT_WRAPPER_W_5W(File_get_view)
2394DEFAULT_WRAPPER_W_6W(File_read_at)
2395DEFAULT_WRAPPER_W_6W(File_read_at_all)
2396DEFAULT_WRAPPER_W_6W(File_write_at)
2397DEFAULT_WRAPPER_W_6W(File_write_at_all)
2398DEFAULT_WRAPPER_W_6W(File_iread_at)
2399DEFAULT_WRAPPER_W_6W(File_iwrite_at)
2400DEFAULT_WRAPPER_W_5W(File_read)
2401DEFAULT_WRAPPER_W_5W(File_read_all)
2402DEFAULT_WRAPPER_W_5W(File_write)
2403DEFAULT_WRAPPER_W_5W(File_write_all)
2404DEFAULT_WRAPPER_W_5W(File_iread)
2405DEFAULT_WRAPPER_W_5W(File_iwrite)
2406DEFAULT_WRAPPER_W_3W(File_seek)
2407DEFAULT_WRAPPER_W_2W(File_get_position)
2408DEFAULT_WRAPPER_W_3W(File_get_byte_offset)
2409DEFAULT_WRAPPER_W_5W(File_read_shared)
2410DEFAULT_WRAPPER_W_5W(File_write_shared)
2411DEFAULT_WRAPPER_W_5W(File_iread_shared)
2412DEFAULT_WRAPPER_W_5W(File_iwrite_shared)
2413DEFAULT_WRAPPER_W_5W(File_read_ordered)
2414DEFAULT_WRAPPER_W_5W(File_write_ordered)
2415DEFAULT_WRAPPER_W_3W(File_seek_shared)
2416DEFAULT_WRAPPER_W_2W(File_get_position_shared)
2417DEFAULT_WRAPPER_W_5W(File_read_at_all_begin)
2418DEFAULT_WRAPPER_W_3W(File_read_at_all_end)
2419DEFAULT_WRAPPER_W_5W(File_write_at_all_begin)
2420DEFAULT_WRAPPER_W_3W(File_write_at_all_end)
2421DEFAULT_WRAPPER_W_4W(File_read_all_begin)
2422DEFAULT_WRAPPER_W_3W(File_read_all_end)
2423DEFAULT_WRAPPER_W_4W(File_write_all_begin)
2424DEFAULT_WRAPPER_W_3W(File_write_all_end)
2425DEFAULT_WRAPPER_W_4W(File_read_ordered_begin)
2426DEFAULT_WRAPPER_W_3W(File_read_ordered_end)
2427DEFAULT_WRAPPER_W_4W(File_write_ordered_begin)
2428DEFAULT_WRAPPER_W_3W(File_write_ordered_end)
2429DEFAULT_WRAPPER_W_3W(File_get_type_extent)
2430DEFAULT_WRAPPER_W_2W(File_set_atomicity)
2431DEFAULT_WRAPPER_W_2W(File_get_atomicity)
2432DEFAULT_WRAPPER_W_1W(File_sync)
2433/* DEFAULT_WRAPPER_W_0W(Finalize) */
2434DEFAULT_WRAPPER_W_1W(Finalized)
2435DEFAULT_WRAPPER_W_1W(Free_mem)
2436/* DEFAULT_WRAPPER_W_8W(Gather) */
2437DEFAULT_WRAPPER_W_9W(Gatherv)
2438DEFAULT_WRAPPER_W_2W(Get_address)
sewardj9c969c32006-03-10 18:37:45 +00002439/* DEFAULT_WRAPPER_W_3W(Get_count) */
sewardj63daa8a2006-03-09 19:08:20 +00002440DEFAULT_WRAPPER_W_3W(Get_elements)
2441DEFAULT_WRAPPER_W_8W(Get)
2442DEFAULT_WRAPPER_W_2W(Get_processor_name)
2443DEFAULT_WRAPPER_W_2W(Get_version)
2444DEFAULT_WRAPPER_W_6W(Graph_create)
2445DEFAULT_WRAPPER_W_5W(Graph_get)
2446DEFAULT_WRAPPER_W_5W(Graph_map)
2447DEFAULT_WRAPPER_W_3W(Graph_neighbors_count)
2448DEFAULT_WRAPPER_W_4W(Graph_neighbors)
2449DEFAULT_WRAPPER_W_3W(Graphdims_get)
2450DEFAULT_WRAPPER_W_1W(Grequest_complete)
2451DEFAULT_WRAPPER_W_5W(Grequest_start)
2452DEFAULT_WRAPPER_W_1W(Group_c2f)
2453DEFAULT_WRAPPER_W_3W(Group_compare)
2454DEFAULT_WRAPPER_W_3W(Group_difference)
2455DEFAULT_WRAPPER_W_4W(Group_excl)
2456DEFAULT_WRAPPER_W_1W(Group_f2c)
2457DEFAULT_WRAPPER_W_1W(Group_free)
2458DEFAULT_WRAPPER_W_4W(Group_incl)
2459DEFAULT_WRAPPER_W_3W(Group_intersection)
2460DEFAULT_WRAPPER_W_4W(Group_range_excl)
2461DEFAULT_WRAPPER_W_4W(Group_range_incl)
2462DEFAULT_WRAPPER_W_2W(Group_rank)
2463DEFAULT_WRAPPER_W_2W(Group_size)
2464DEFAULT_WRAPPER_W_5W(Group_translate_ranks)
2465DEFAULT_WRAPPER_W_3W(Group_union)
sewardj9c969c32006-03-10 18:37:45 +00002466/* DEFAULT_WRAPPER_W_7W(Ibsend) */
sewardj63daa8a2006-03-09 19:08:20 +00002467DEFAULT_WRAPPER_W_1W(Info_c2f)
2468DEFAULT_WRAPPER_W_1W(Info_create)
2469DEFAULT_WRAPPER_W_2W(Info_delete)
2470DEFAULT_WRAPPER_W_2W(Info_dup)
2471DEFAULT_WRAPPER_W_1W(Info_f2c)
2472DEFAULT_WRAPPER_W_1W(Info_free)
2473DEFAULT_WRAPPER_W_5W(Info_get)
2474DEFAULT_WRAPPER_W_2W(Info_get_nkeys)
2475DEFAULT_WRAPPER_W_3W(Info_get_nthkey)
2476DEFAULT_WRAPPER_W_4W(Info_get_valuelen)
2477DEFAULT_WRAPPER_W_3W(Info_set)
2478/* DEFAULT_WRAPPER_W_2W(Init) */
2479/* DEFAULT_WRAPPER_W_1W(Initialized) */
2480DEFAULT_WRAPPER_W_4W(Init_thread)
2481DEFAULT_WRAPPER_W_6W(Intercomm_create)
2482DEFAULT_WRAPPER_W_3W(Intercomm_merge)
2483/* DEFAULT_WRAPPER_W_5W(Iprobe) */
2484/* DEFAULT_WRAPPER_W_7W(Irecv) */
sewardj9c969c32006-03-10 18:37:45 +00002485/* DEFAULT_WRAPPER_W_7W(Irsend) */
sewardj63daa8a2006-03-09 19:08:20 +00002486/* DEFAULT_WRAPPER_W_7W(Isend) */
sewardj9c969c32006-03-10 18:37:45 +00002487/* DEFAULT_WRAPPER_W_7W(Issend) */
sewardj63daa8a2006-03-09 19:08:20 +00002488DEFAULT_WRAPPER_W_1W(Is_thread_main)
2489DEFAULT_WRAPPER_W_4W(Keyval_create)
2490DEFAULT_WRAPPER_W_1W(Keyval_free)
2491DEFAULT_WRAPPER_W_3W(Lookup_name)
2492DEFAULT_WRAPPER_W_1W(Op_c2f)
2493/* DEFAULT_WRAPPER_W_3W(Op_create) */
2494DEFAULT_WRAPPER_W_2W(Open_port)
2495DEFAULT_WRAPPER_W_1W(Op_f2c)
2496DEFAULT_WRAPPER_W_1W(Op_free)
2497DEFAULT_WRAPPER_W_7W(Pack_external)
2498DEFAULT_WRAPPER_W_4W(Pack_external_size)
sewardjee346592007-02-08 12:05:03 +00002499/* DEFAULT_WRAPPER_W_7W(Pack) */
sewardj63daa8a2006-03-09 19:08:20 +00002500DEFAULT_WRAPPER_W_4W(Pack_size)
2501/* int MPI_Pcontrol(const int level, ...) */
sewardjb727b542006-03-10 21:41:01 +00002502/* DEFAULT_WRAPPER_W_4W(Probe) */
sewardj63daa8a2006-03-09 19:08:20 +00002503DEFAULT_WRAPPER_W_3W(Publish_name)
2504DEFAULT_WRAPPER_W_8W(Put)
2505DEFAULT_WRAPPER_W_1W(Query_thread)
2506DEFAULT_WRAPPER_W_7W(Recv_init)
2507/* DEFAULT_WRAPPER_W_7W(Recv) */
2508/* DEFAULT_WRAPPER_W_7W(Reduce) */
2509DEFAULT_WRAPPER_W_6W(Reduce_scatter)
2510DEFAULT_WRAPPER_W_5W(Register_datarep)
2511DEFAULT_WRAPPER_W_1W(Request_c2f)
2512DEFAULT_WRAPPER_W_1W(Request_f2c)
2513DEFAULT_WRAPPER_W_1W(Request_free)
2514DEFAULT_WRAPPER_W_3W(Request_get_status)
sewardj9c969c32006-03-10 18:37:45 +00002515/* DEFAULT_WRAPPER_W_6W(Rsend) */
sewardj63daa8a2006-03-09 19:08:20 +00002516DEFAULT_WRAPPER_W_7W(Rsend_init)
2517DEFAULT_WRAPPER_W_6W(Scan)
sewardjb727b542006-03-10 21:41:01 +00002518/* DEFAULT_WRAPPER_W_8W(Scatter) */
sewardj63daa8a2006-03-09 19:08:20 +00002519DEFAULT_WRAPPER_W_9W(Scatterv)
2520DEFAULT_WRAPPER_W_7W(Send_init)
2521/* DEFAULT_WRAPPER_W_6W(Send) */
2522/* DEFAULT_WRAPPER_W_12W(Sendrecv) */
2523DEFAULT_WRAPPER_W_9W(Sendrecv_replace)
2524DEFAULT_WRAPPER_W_7W(Ssend_init)
sewardj9c969c32006-03-10 18:37:45 +00002525/* DEFAULT_WRAPPER_W_6W(Ssend) */
sewardj63daa8a2006-03-09 19:08:20 +00002526DEFAULT_WRAPPER_W_1W(Start)
2527DEFAULT_WRAPPER_W_2W(Startall)
2528DEFAULT_WRAPPER_W_2W(Status_c2f)
2529DEFAULT_WRAPPER_W_2W(Status_f2c)
2530DEFAULT_WRAPPER_W_2W(Status_set_cancelled)
2531DEFAULT_WRAPPER_W_3W(Status_set_elements)
sewardjb727b542006-03-10 21:41:01 +00002532/* DEFAULT_WRAPPER_W_4W(Testall) */
sewardj63daa8a2006-03-09 19:08:20 +00002533DEFAULT_WRAPPER_W_5W(Testany)
sewardjb727b542006-03-10 21:41:01 +00002534/* DEFAULT_WRAPPER_W_3W(Test) */
sewardj63daa8a2006-03-09 19:08:20 +00002535DEFAULT_WRAPPER_W_2W(Test_cancelled)
2536DEFAULT_WRAPPER_W_5W(Testsome)
2537DEFAULT_WRAPPER_W_2W(Topo_test)
2538DEFAULT_WRAPPER_W_1W(Type_c2f)
sewardj9c969c32006-03-10 18:37:45 +00002539/* DEFAULT_WRAPPER_W_1W(Type_commit) */
sewardj63daa8a2006-03-09 19:08:20 +00002540DEFAULT_WRAPPER_W_3W(Type_contiguous)
2541DEFAULT_WRAPPER_W_10W(Type_create_darray)
2542DEFAULT_WRAPPER_W_3W(Type_create_f90_complex)
2543DEFAULT_WRAPPER_W_2W(Type_create_f90_integer)
2544DEFAULT_WRAPPER_W_3W(Type_create_f90_real)
2545DEFAULT_WRAPPER_W_5W(Type_create_hindexed)
2546DEFAULT_WRAPPER_W_5W(Type_create_hvector)
2547DEFAULT_WRAPPER_W_4W(Type_create_keyval)
2548DEFAULT_WRAPPER_W_5W(Type_create_indexed_block)
2549DEFAULT_WRAPPER_W_5W(Type_create_struct)
2550DEFAULT_WRAPPER_W_7W(Type_create_subarray)
2551DEFAULT_WRAPPER_W_4W(Type_create_resized)
2552DEFAULT_WRAPPER_W_2W(Type_delete_attr)
2553DEFAULT_WRAPPER_W_2W(Type_dup)
sewardj9c969c32006-03-10 18:37:45 +00002554/* DEFAULT_WRAPPER_W_2W(Type_extent) */
2555/* DEFAULT_WRAPPER_W_1W(Type_free) */
sewardj63daa8a2006-03-09 19:08:20 +00002556DEFAULT_WRAPPER_W_1W(Type_free_keyval)
2557DEFAULT_WRAPPER_W_1W(Type_f2c)
2558DEFAULT_WRAPPER_W_4W(Type_get_attr)
sewardj9c969c32006-03-10 18:37:45 +00002559/* DEFAULT_WRAPPER_W_7W(Type_get_contents) */
2560/* DEFAULT_WRAPPER_W_5W(Type_get_envelope) */
sewardj63daa8a2006-03-09 19:08:20 +00002561DEFAULT_WRAPPER_W_3W(Type_get_extent)
2562DEFAULT_WRAPPER_W_3W(Type_get_name)
2563DEFAULT_WRAPPER_W_3W(Type_get_true_extent)
2564DEFAULT_WRAPPER_W_5W(Type_hindexed)
2565DEFAULT_WRAPPER_W_5W(Type_hvector)
2566DEFAULT_WRAPPER_W_5W(Type_indexed)
2567DEFAULT_WRAPPER_W_2W(Type_lb)
2568DEFAULT_WRAPPER_W_3W(Type_match_size)
2569DEFAULT_WRAPPER_W_3W(Type_set_attr)
2570DEFAULT_WRAPPER_W_2W(Type_set_name)
2571DEFAULT_WRAPPER_W_2W(Type_size)
2572DEFAULT_WRAPPER_W_5W(Type_struct)
2573DEFAULT_WRAPPER_W_2W(Type_ub)
2574DEFAULT_WRAPPER_W_5W(Type_vector)
sewardjee346592007-02-08 12:05:03 +00002575/* DEFAULT_WRAPPER_W_7W(Unpack) */
sewardj63daa8a2006-03-09 19:08:20 +00002576DEFAULT_WRAPPER_W_3W(Unpublish_name)
2577DEFAULT_WRAPPER_W_7W(Unpack_external)
2578/* DEFAULT_WRAPPER_W_3W(Waitall) */
sewardj982751b2008-05-15 05:48:16 +00002579/* DEFAULT_WRAPPER_W_4W(Waitany) */
sewardj63daa8a2006-03-09 19:08:20 +00002580/* DEFAULT_WRAPPER_W_2W(Wait) */
2581DEFAULT_WRAPPER_W_5W(Waitsome)
2582DEFAULT_WRAPPER_W_1W(Win_c2f)
2583DEFAULT_WRAPPER_W_2W(Win_call_errhandler)
2584DEFAULT_WRAPPER_W_1W(Win_complete)
2585DEFAULT_WRAPPER_W_6W(Win_create)
2586DEFAULT_WRAPPER_W_2W(Win_create_errhandler)
2587DEFAULT_WRAPPER_W_4W(Win_create_keyval)
2588DEFAULT_WRAPPER_W_2W(Win_delete_attr)
2589DEFAULT_WRAPPER_W_1W(Win_f2c)
2590DEFAULT_WRAPPER_W_2W(Win_fence)
2591DEFAULT_WRAPPER_W_1W(Win_free)
2592DEFAULT_WRAPPER_W_1W(Win_free_keyval)
2593DEFAULT_WRAPPER_W_4W(Win_get_attr)
2594DEFAULT_WRAPPER_W_2W(Win_get_errhandler)
2595DEFAULT_WRAPPER_W_2W(Win_get_group)
2596DEFAULT_WRAPPER_W_3W(Win_get_name)
2597DEFAULT_WRAPPER_W_4W(Win_lock)
2598DEFAULT_WRAPPER_W_3W(Win_post)
2599DEFAULT_WRAPPER_W_3W(Win_set_attr)
2600DEFAULT_WRAPPER_W_2W(Win_set_errhandler)
2601DEFAULT_WRAPPER_W_2W(Win_set_name)
2602DEFAULT_WRAPPER_W_3W(Win_start)
2603DEFAULT_WRAPPER_W_2W(Win_test)
2604DEFAULT_WRAPPER_W_2W(Win_unlock)
2605DEFAULT_WRAPPER_W_1W(Win_wait)
2606/* double MPI_Wtick(void) */
2607/* double MPI_Wtime(void) */
2608
2609
sewardjc3a47092006-02-18 23:13:33 +00002610/*------------------------------------------------------------*/
2611/*--- ---*/
2612/*--- ---*/
2613/*--- ---*/
2614/*------------------------------------------------------------*/
2615
sewardjc3a47092006-02-18 23:13:33 +00002616/*---------------------------------------------------------------*/
2617/*--- end mpiwrap.c ---*/
2618/*---------------------------------------------------------------*/