blob: 0e1d8247b26b3505108eb1b44a802b6539a35a46 [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
sewardj9ebd6e02007-01-08 06:01:59 +000021 Copyright (C) 2006-2007 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
sewardjc3a47092006-02-18 23:13:33 +00001406/* --- Waitall --- */
1407int WRAPPER_FOR(PMPI_Waitall)( int count,
1408 MPI_Request* requests,
1409 MPI_Status* statuses )
1410{
1411 MPI_Request* requests_before = NULL;
1412 OrigFn fn;
1413 int err, i;
1414 VALGRIND_GET_ORIG_FN(fn);
1415 before("Waitall");
1416 if (0) fprintf(stderr, "Waitall: %d\n", count);
1417 for (i = 0; i < count; i++) {
njndbf7ca72006-03-31 11:57:59 +00001418 check_mem_is_addressable_untyped(&statuses[i], sizeof(MPI_Status));
1419 check_mem_is_defined_untyped(&requests[i], sizeof(MPI_Request));
sewardjc3a47092006-02-18 23:13:33 +00001420 }
1421 requests_before = clone_Request_array( count, requests );
1422 CALL_FN_W_WWW(err, fn, count,requests,statuses);
1423 if (err == MPI_SUCCESS /*complete success*/
1424 || err == MPI_ERR_IN_STATUS /* partial success */) {
1425 Bool e_i_s = err == MPI_ERR_IN_STATUS;
1426 for (i = 0; i < count; i++) {
1427 maybe_complete(e_i_s, requests_before[i], requests[i],
1428 &statuses[i]);
njndbf7ca72006-03-31 11:57:59 +00001429 make_mem_defined_if_addressable_untyped(&statuses[i],
1430 sizeof(MPI_Status));
sewardjc3a47092006-02-18 23:13:33 +00001431 }
1432 }
1433 if (requests_before)
1434 free(requests_before);
1435 after("Waitall", err);
1436 return err;
1437}
1438
sewardjb727b542006-03-10 21:41:01 +00001439/* --- Test --- */
1440/* nonblocking version of Wait */
1441int WRAPPER_FOR(PMPI_Test)( MPI_Request* request, int* flag,
1442 MPI_Status* status )
1443{
1444 MPI_Request request_before;
1445 OrigFn fn;
1446 int err;
1447 VALGRIND_GET_ORIG_FN(fn);
1448 before("Test");
njndbf7ca72006-03-31 11:57:59 +00001449 check_mem_is_addressable_untyped(status, sizeof(MPI_Status));
1450 check_mem_is_addressable_untyped(flag, sizeof(int));
1451 check_mem_is_defined_untyped(request, sizeof(MPI_Request));
sewardjb727b542006-03-10 21:41:01 +00001452 request_before = *request;
1453 CALL_FN_W_WWW(err, fn, request,flag,status);
1454 if (err == MPI_SUCCESS && *flag) {
1455 maybe_complete(False/*err in status?*/,
1456 request_before, *request, status);
njndbf7ca72006-03-31 11:57:59 +00001457 make_mem_defined_if_addressable_untyped(status, sizeof(MPI_Status));
sewardjb727b542006-03-10 21:41:01 +00001458 }
1459 after("Test", err);
1460 return err;
1461}
1462
1463/* --- Testall --- */
1464/* nonblocking version of Waitall */
1465int WRAPPER_FOR(PMPI_Testall)( int count, MPI_Request* requests,
1466 int* flag, MPI_Status* statuses )
1467{
1468 MPI_Request* requests_before = NULL;
1469 OrigFn fn;
1470 int err, i;
1471 VALGRIND_GET_ORIG_FN(fn);
1472 before("Testall");
1473 if (0) fprintf(stderr, "Testall: %d\n", count);
njndbf7ca72006-03-31 11:57:59 +00001474 check_mem_is_addressable_untyped(flag, sizeof(int));
sewardjb727b542006-03-10 21:41:01 +00001475 for (i = 0; i < count; i++) {
njndbf7ca72006-03-31 11:57:59 +00001476 check_mem_is_addressable_untyped(&statuses[i], sizeof(MPI_Status));
1477 check_mem_is_defined_untyped(&requests[i], sizeof(MPI_Request));
sewardjb727b542006-03-10 21:41:01 +00001478 }
1479 requests_before = clone_Request_array( count, requests );
1480 CALL_FN_W_WWWW(err, fn, count,requests,flag,statuses);
1481 /* Urk. Is the following "if (...)" really right? I don't know. */
1482 if (*flag
1483 && (err == MPI_SUCCESS /*complete success*/
1484 || err == MPI_ERR_IN_STATUS /* partial success */)) {
1485 Bool e_i_s = err == MPI_ERR_IN_STATUS;
1486 for (i = 0; i < count; i++) {
1487 maybe_complete(e_i_s, requests_before[i], requests[i],
1488 &statuses[i]);
njndbf7ca72006-03-31 11:57:59 +00001489 make_mem_defined_if_addressable_untyped(&statuses[i], sizeof(MPI_Status));
sewardjb727b542006-03-10 21:41:01 +00001490 }
1491 }
1492 if (requests_before)
1493 free(requests_before);
1494 after("Testall", err);
1495 return err;
1496}
1497
sewardjc3a47092006-02-18 23:13:33 +00001498/* --- Iprobe --- */
sewardjc3a47092006-02-18 23:13:33 +00001499/* pre: must-be-writable: *flag, *status */
1500/* post: make-readable *flag
sewardjb727b542006-03-10 21:41:01 +00001501 if *flag==True make-defined *status */
sewardjc3a47092006-02-18 23:13:33 +00001502int WRAPPER_FOR(PMPI_Iprobe)(int source, int tag,
1503 MPI_Comm comm,
1504 int* flag, MPI_Status* status)
1505{
1506 OrigFn fn;
1507 int err;
1508 VALGRIND_GET_ORIG_FN(fn);
1509 before("Iprobe");
njndbf7ca72006-03-31 11:57:59 +00001510 check_mem_is_addressable_untyped(flag, sizeof(*flag));
1511 check_mem_is_addressable_untyped(status, sizeof(*status));
sewardjc3a47092006-02-18 23:13:33 +00001512 CALL_FN_W_5W(err, fn, source,tag,comm,flag,status);
1513 if (err == MPI_SUCCESS) {
njndbf7ca72006-03-31 11:57:59 +00001514 make_mem_defined_if_addressable_untyped(flag, sizeof(*flag));
sewardjc3a47092006-02-18 23:13:33 +00001515 if (*flag)
njndbf7ca72006-03-31 11:57:59 +00001516 make_mem_defined_if_addressable_untyped(status, sizeof(*status));
sewardjc3a47092006-02-18 23:13:33 +00001517 }
1518 after("Iprobe", err);
1519 return err;
1520}
1521
sewardjb727b542006-03-10 21:41:01 +00001522/* --- Probe --- */
1523/* pre: must-be-writable *status */
1524/* post: make-defined *status */
1525int WRAPPER_FOR(PMPI_Probe)(int source, int tag,
1526 MPI_Comm comm, MPI_Status* status)
1527{
1528 OrigFn fn;
1529 int err;
1530 VALGRIND_GET_ORIG_FN(fn);
1531 before("Probe");
njndbf7ca72006-03-31 11:57:59 +00001532 check_mem_is_addressable_untyped(status, sizeof(*status));
sewardjb727b542006-03-10 21:41:01 +00001533 CALL_FN_W_WWWW(err, fn, source,tag,comm,status);
njndbf7ca72006-03-31 11:57:59 +00001534 make_mem_defined_if_addressable_if_success_untyped(err, status, sizeof(*status));
sewardjb727b542006-03-10 21:41:01 +00001535 after("Probe", err);
1536 return err;
1537}
1538
1539/* --- Cancel --- */
1540/* Wrapping PMPI_Cancel is interesting only to the extent that we need
1541 to be able to detect when a request should be removed from our
1542 shadow table due to cancellation. */
1543int WRAPPER_FOR(PMPI_Cancel)(MPI_Request* request)
1544{
1545 OrigFn fn;
1546 int err;
1547 MPI_Request tmp;
1548 VALGRIND_GET_ORIG_FN(fn);
1549 before("Cancel");
njndbf7ca72006-03-31 11:57:59 +00001550 check_mem_is_addressable_untyped(request, sizeof(*request));
sewardjb727b542006-03-10 21:41:01 +00001551 tmp = *request;
1552 CALL_FN_W_W(err, fn, request);
1553 if (err == MPI_SUCCESS)
1554 delete_shadow_Request(tmp);
1555 after("Cancel", err);
1556 return err;
1557}
1558
sewardjc3a47092006-02-18 23:13:33 +00001559
1560/*------------------------------------------------------------*/
1561/*--- ---*/
1562/*--- Sec 3.10, Send-receive ---*/
1563/*--- ---*/
1564/*------------------------------------------------------------*/
1565
1566/* --- Sendrecv --- */
1567/* pre: must be readable: (sendbuf,sendcount,sendtype)
1568 must be writable: (recvbuf,recvcount,recvtype)
1569 post: make readable: (recvbuf,recvcount_actual,datatype)
1570 where recvcount_actual is determined from *status
1571*/
1572int WRAPPER_FOR(PMPI_Sendrecv)(
1573 void *sendbuf, int sendcount, MPI_Datatype sendtype,
1574 int dest, int sendtag,
1575 void *recvbuf, int recvcount, MPI_Datatype recvtype,
1576 int source, int recvtag,
1577 MPI_Comm comm, MPI_Status *status)
1578{
1579 OrigFn fn;
1580 int err, recvcount_actual = 0;
1581 VALGRIND_GET_ORIG_FN(fn);
1582 before("Sendrecv");
njndbf7ca72006-03-31 11:57:59 +00001583 check_mem_is_defined(sendbuf, sendcount, sendtype);
1584 check_mem_is_addressable(recvbuf, recvcount, recvtype);
sewardjc3a47092006-02-18 23:13:33 +00001585 CALL_FN_W_12W(err, fn, sendbuf,sendcount,sendtype,dest,sendtag,
1586 recvbuf,recvcount,recvtype,source,recvtag,
1587 comm,status);
1588 if (err == MPI_SUCCESS
1589 && count_from_Status(&recvcount_actual,recvtype,status)) {
njndbf7ca72006-03-31 11:57:59 +00001590 make_mem_defined_if_addressable(recvbuf, recvcount_actual, recvtype);
sewardjc3a47092006-02-18 23:13:33 +00001591 }
1592 after("Sendrecv", err);
1593 return err;
1594}
1595
sewardjc3a47092006-02-18 23:13:33 +00001596
1597/*------------------------------------------------------------*/
1598/*--- ---*/
1599/*--- Sec 3.12, Derived datatypes ---*/
1600/*--- ---*/
1601/*------------------------------------------------------------*/
1602
1603/* --- Address --- */
1604/* Does this have anything worth checking? */
sewardj9c969c32006-03-10 18:37:45 +00001605HAS_NO_WRAPPER(Address)
1606
1607/* --- MPI 2 stuff --- */
1608/* Type_extent, Type_get_contents and Type_get_envelope sometimes get
1609 used intensively by the type walker (walk_type). There's no reason
1610 why they couldn't be properly wrapped if needed, but doing so slows
1611 everything down, so don't bother until needed. */
1612HAS_NO_WRAPPER(Type_extent)
1613HAS_NO_WRAPPER(Type_get_contents)
1614HAS_NO_WRAPPER(Type_get_envelope)
1615
1616/* --- Type_commit --- */
1617int WRAPPER_FOR(PMPI_Type_commit)( MPI_Datatype* ty )
1618{
1619 OrigFn fn;
1620 int err;
1621 VALGRIND_GET_ORIG_FN(fn);
1622 before("Type_commit");
njndbf7ca72006-03-31 11:57:59 +00001623 check_mem_is_defined_untyped(ty, sizeof(*ty));
sewardj9c969c32006-03-10 18:37:45 +00001624 CALL_FN_W_W(err, fn, ty);
1625 after("Type_commit", err);
1626 return err;
1627}
1628
1629/* --- Type_free --- */
1630int WRAPPER_FOR(PMPI_Type_free)( MPI_Datatype* ty )
1631{
1632 OrigFn fn;
1633 int err;
1634 VALGRIND_GET_ORIG_FN(fn);
1635 before("Type_free");
njndbf7ca72006-03-31 11:57:59 +00001636 check_mem_is_defined_untyped(ty, sizeof(*ty));
sewardj9c969c32006-03-10 18:37:45 +00001637 CALL_FN_W_W(err, fn, ty);
1638 after("Type_free", err);
1639 return err;
1640}
sewardjc3a47092006-02-18 23:13:33 +00001641
1642
1643/*------------------------------------------------------------*/
1644/*--- ---*/
sewardjee346592007-02-08 12:05:03 +00001645/*--- Sec 3.13, Pack and unpack ---*/
1646/*--- ---*/
1647/*------------------------------------------------------------*/
1648
1649/* --- Pack --- */
1650/* pre: must be readable: position
1651 must be readable: (inbuf,incount,datatype)
1652 must be writable: outbuf[0 .. outsize-1]
1653 must be writable: outbuf[*position ..
1654 *position - 1
1655 + however much space PMPI_Pack_size
1656 says we will need]
1657 post: make readable: outbuf[old *position .. new *position]
1658*/
1659int WRAPPER_FOR(PMPI_Pack)( void* inbuf, int incount, MPI_Datatype datatype,
1660 void* outbuf, int outsize,
1661 int* position, MPI_Comm comm )
1662{
1663 OrigFn fn;
1664 int err, szB = 0;
1665 int position_ORIG = *position;
1666 VALGRIND_GET_ORIG_FN(fn);
1667 before("Pack");
1668 /* stay sane */
1669 check_mem_is_defined_untyped(position, sizeof(*position));
1670 /* check input */
1671 check_mem_is_defined(inbuf, incount, datatype);
1672 /* check output area's stated bounds make sense */
1673 check_mem_is_addressable_untyped(outbuf, outsize);
1674 /* check output area's actual used size properly */
1675 err = PMPI_Pack_size( incount, datatype, comm, &szB );
1676 if (err == MPI_SUCCESS && szB > 0) {
1677 check_mem_is_addressable_untyped(
1678 ((char*)outbuf) + position_ORIG, szB
1679 );
1680 }
1681
1682 CALL_FN_W_7W(err, fn, inbuf,incount,datatype, outbuf,outsize,position, comm);
1683
1684 if (err == MPI_SUCCESS && (*position) > position_ORIG) {
1685 /* paint output */
1686 make_mem_defined_if_addressable_untyped(
1687 ((char*)outbuf) + position_ORIG, *position - position_ORIG
1688 );
1689 }
1690 after("Pack", err);
1691 return err;
1692}
1693
1694/* --- Unpack --- */
1695/* pre: must be readable: position
1696 must be writable: (outbuf,outcount,datatype)
1697 must be writable: outbuf[0 .. outsize-1]
1698 must be writable: outbuf[*position ..
1699 *position - 1
1700 + however much space PMPI_Pack_size
1701 says we will need]
1702 post: make readable: (outbuf,outcount,datatype)
1703 and also do a readability check of
1704 inbuf[old *position .. new *position]
1705*/
1706int WRAPPER_FOR(PMPI_Unpack)( void* inbuf, int insize, int* position,
1707 void* outbuf, int outcount, MPI_Datatype datatype,
1708 MPI_Comm comm )
1709{
1710 OrigFn fn;
1711 int err, szB = 0;
1712 int position_ORIG = *position;
1713 VALGRIND_GET_ORIG_FN(fn);
1714 before("Unpack");
1715 /* stay sane */
1716 check_mem_is_defined_untyped(position, sizeof(*position));
1717 /* check output area is accessible */
1718 check_mem_is_addressable(outbuf, outcount, datatype);
1719 /* check input area's stated bounds make sense */
1720 check_mem_is_addressable_untyped(inbuf, insize);
1721 /* check input area's actual used size properly */
1722 err = PMPI_Pack_size( outcount, datatype, comm, &szB );
1723 if (err == MPI_SUCCESS && szB > 0) {
1724 check_mem_is_addressable_untyped(
1725 ((char*)inbuf) + position_ORIG, szB
1726 );
1727 }
1728
1729 CALL_FN_W_7W(err, fn, inbuf,insize,position, outbuf,outcount,datatype, comm);
1730
1731 if (err == MPI_SUCCESS && (*position) > position_ORIG) {
1732 /* recheck input more carefully */
1733 check_mem_is_defined_untyped(
1734 ((char*)inbuf) + position_ORIG, *position - position_ORIG
1735 );
1736 /* paint output */
1737 make_mem_defined_if_addressable( outbuf, outcount, datatype );
1738 }
1739 after("Unpack", err);
1740 return err;
1741}
1742
1743
1744/*------------------------------------------------------------*/
1745/*--- ---*/
sewardjc3a47092006-02-18 23:13:33 +00001746/*--- Sec 4.4, Broadcast ---*/
1747/*--- ---*/
1748/*------------------------------------------------------------*/
1749
1750/* --- Bcast --- */
1751/* pre: must-be-readable (buffer,count,datatype) for rank==root
1752 must-be-writable (buffer,count,datatype) for rank!=root
1753 post: make-readable (buffer,count,datatype) for all
1754
1755 Resulting behaviour is: if root sends uninitialised stuff, then
1756 V complains, but then all ranks, including itself, see the buffer
1757 as initialised after that.
1758*/
1759int WRAPPER_FOR(PMPI_Bcast)(void *buffer, int count,
1760 MPI_Datatype datatype,
1761 int root, MPI_Comm comm)
1762{
1763 OrigFn fn;
1764 int err;
1765 Bool i_am_sender;
1766 VALGRIND_GET_ORIG_FN(fn);
1767 before("Bcast");
1768 i_am_sender = root == comm_rank(comm);
1769 if (i_am_sender) {
njndbf7ca72006-03-31 11:57:59 +00001770 check_mem_is_defined(buffer, count, datatype);
sewardjc3a47092006-02-18 23:13:33 +00001771 } else {
njndbf7ca72006-03-31 11:57:59 +00001772 check_mem_is_addressable(buffer, count, datatype);
sewardjc3a47092006-02-18 23:13:33 +00001773 }
1774 CALL_FN_W_5W(err, fn, buffer,count,datatype,root,comm);
njndbf7ca72006-03-31 11:57:59 +00001775 make_mem_defined_if_addressable_if_success(err, buffer, count, datatype);
sewardjc3a47092006-02-18 23:13:33 +00001776 after("Bcast", err);
1777 return err;
1778}
1779
1780
1781/*------------------------------------------------------------*/
1782/*--- ---*/
1783/*--- Sec 4.5, Gather ---*/
1784/*--- ---*/
1785/*------------------------------------------------------------*/
1786
1787/* --- Gather --- */
1788/* JRS 20060217: I don't really understand this. Each process is
1789 going to send sendcount items of type sendtype to the root. So
1790 the root is going to receive comm_size*sendcount items of type
1791 sendtype (right?) So why specify recvcount and recvtype?
1792
1793 Anyway, assuming the MPI Spec is correct (seems likely :-) we have:
1794
1795 pre: (all) must be readable: (sendbuf,sendcount,sendtype)
1796 (root only): must be writable: (recvbuf,recvcount * comm_size,recvtype)
1797 post: (root only): make readable: (recvbuf,recvcount * comm_size,recvtype)
1798*/
1799int WRAPPER_FOR(PMPI_Gather)(
1800 void *sendbuf, int sendcount, MPI_Datatype sendtype,
1801 void *recvbuf, int recvcount, MPI_Datatype recvtype,
1802 int root, MPI_Comm comm)
1803{
1804 OrigFn fn;
1805 int err, me, sz;
1806 VALGRIND_GET_ORIG_FN(fn);
1807 before("Gather");
1808 me = comm_rank(comm);
1809 sz = comm_size(comm);
njndbf7ca72006-03-31 11:57:59 +00001810 check_mem_is_defined(sendbuf, sendcount, sendtype);
sewardjc3a47092006-02-18 23:13:33 +00001811 if (me == root)
njndbf7ca72006-03-31 11:57:59 +00001812 check_mem_is_addressable(recvbuf, recvcount * sz, recvtype);
sewardjc3a47092006-02-18 23:13:33 +00001813 CALL_FN_W_8W(err, fn, sendbuf,sendcount,sendtype,
1814 recvbuf,recvcount,recvtype,
1815 root,comm);
sewardjb727b542006-03-10 21:41:01 +00001816 if (me == root)
njndbf7ca72006-03-31 11:57:59 +00001817 make_mem_defined_if_addressable_if_success(err, recvbuf, recvcount * sz, recvtype);
sewardjc3a47092006-02-18 23:13:33 +00001818 after("Gather", err);
1819 return err;
1820}
1821
1822
1823/*------------------------------------------------------------*/
1824/*--- ---*/
sewardjb727b542006-03-10 21:41:01 +00001825/*--- Sec 4.6, Scatter ---*/
1826/*--- ---*/
1827/*------------------------------------------------------------*/
1828
1829/* pre: (root only): must be readable: (sendbuf,sendcount * comm_size,sendtype)
1830 (all): must be writable: (recvbuf,recvbuf,recvtype)
1831 post: (all): make defined: (recvbuf,recvbuf,recvtype)
1832*/
1833int WRAPPER_FOR(PMPI_Scatter)(
1834 void* sendbuf, int sendcount, MPI_Datatype sendtype,
1835 void* recvbuf, int recvcount, MPI_Datatype recvtype,
1836 int root, MPI_Comm comm)
1837{
1838 OrigFn fn;
1839 int err, me, sz;
1840 VALGRIND_GET_ORIG_FN(fn);
1841 before("Scatter");
1842 me = comm_rank(comm);
1843 sz = comm_size(comm);
njndbf7ca72006-03-31 11:57:59 +00001844 check_mem_is_addressable(recvbuf, recvcount, recvtype);
sewardjb727b542006-03-10 21:41:01 +00001845 if (me == root)
njndbf7ca72006-03-31 11:57:59 +00001846 check_mem_is_defined(sendbuf, sendcount * sz, sendtype);
sewardjb727b542006-03-10 21:41:01 +00001847 CALL_FN_W_8W(err, fn, sendbuf,sendcount,sendtype,
1848 recvbuf,recvcount,recvtype,
1849 root,comm);
njndbf7ca72006-03-31 11:57:59 +00001850 make_mem_defined_if_addressable_if_success(err, recvbuf, recvcount, recvtype);
sewardjb727b542006-03-10 21:41:01 +00001851 after("Scatter", err);
1852 return err;
1853}
1854
1855
1856/*------------------------------------------------------------*/
1857/*--- ---*/
1858/*--- Sec 4.8, All-to-All Scatter/Gather ---*/
1859/*--- ---*/
1860/*------------------------------------------------------------*/
1861
1862/* pre: (all) must be readable: (sendbuf,sendcount * comm_size,sendtype)
1863 (all) must be writable: (recvbuf,recvcount * comm_size,recvtype)
1864 post: (all) make defined: (recvbuf,recvcount * comm_size,recvtype)
1865*/
1866int WRAPPER_FOR(PMPI_Alltoall)(
1867 void* sendbuf, int sendcount, MPI_Datatype sendtype,
1868 void* recvbuf, int recvcount, MPI_Datatype recvtype,
1869 MPI_Comm comm)
1870{
1871 OrigFn fn;
1872 int err, sz;
1873 VALGRIND_GET_ORIG_FN(fn);
1874 before("Alltoall");
1875 sz = comm_size(comm);
njndbf7ca72006-03-31 11:57:59 +00001876 check_mem_is_defined(sendbuf, sendcount * sz, sendtype);
1877 check_mem_is_addressable(recvbuf, recvcount * sz, recvtype);
sewardjb727b542006-03-10 21:41:01 +00001878 CALL_FN_W_7W(err, fn, sendbuf,sendcount,sendtype,
1879 recvbuf,recvcount,recvtype,
1880 comm);
njndbf7ca72006-03-31 11:57:59 +00001881 make_mem_defined_if_addressable_if_success(err, recvbuf, recvcount * sz, recvtype);
sewardjb727b542006-03-10 21:41:01 +00001882 after("Alltoall", err);
1883 return err;
1884}
1885
1886
1887/*------------------------------------------------------------*/
1888/*--- ---*/
sewardjc3a47092006-02-18 23:13:33 +00001889/*--- Sec 4.9, Global Reduction Operations ---*/
1890/*--- ---*/
1891/*------------------------------------------------------------*/
1892
1893/* --- Reduce --- */
1894/* rd: (sendbuf,count,datatype) for all
1895 wr: (recvbuf,count,datatype) but only for rank == root
1896*/
1897int WRAPPER_FOR(PMPI_Reduce)(void *sendbuf, void *recvbuf,
1898 int count,
1899 MPI_Datatype datatype, MPI_Op op,
1900 int root, MPI_Comm comm)
1901{
1902 OrigFn fn;
1903 int err;
1904 Bool i_am_root;
1905 VALGRIND_GET_ORIG_FN(fn);
1906 before("Reduce");
1907 i_am_root = root == comm_rank(comm);
njndbf7ca72006-03-31 11:57:59 +00001908 check_mem_is_defined(sendbuf, count, datatype);
sewardjc3a47092006-02-18 23:13:33 +00001909 if (i_am_root)
njndbf7ca72006-03-31 11:57:59 +00001910 check_mem_is_addressable(recvbuf, count, datatype);
sewardjc3a47092006-02-18 23:13:33 +00001911 CALL_FN_W_7W(err, fn, sendbuf,recvbuf,count,datatype,op,root,comm);
1912 if (i_am_root)
njndbf7ca72006-03-31 11:57:59 +00001913 make_mem_defined_if_addressable_if_success(err, recvbuf, count, datatype);
sewardjc3a47092006-02-18 23:13:33 +00001914 after("Reduce", err);
1915 return err;
1916}
1917
1918
1919/* --- Allreduce --- */
1920/* rd: (sendbuf,count,datatype) for all
1921 wr: (recvbuf,count,datatype) for all
1922*/
1923int WRAPPER_FOR(PMPI_Allreduce)(void *sendbuf, void *recvbuf,
1924 int count,
1925 MPI_Datatype datatype, MPI_Op op,
1926 MPI_Comm comm)
1927{
1928 OrigFn fn;
1929 int err;
1930 VALGRIND_GET_ORIG_FN(fn);
1931 before("Allreduce");
njndbf7ca72006-03-31 11:57:59 +00001932 check_mem_is_defined(sendbuf, count, datatype);
1933 check_mem_is_addressable(recvbuf, count, datatype);
sewardjc3a47092006-02-18 23:13:33 +00001934 CALL_FN_W_6W(err, fn, sendbuf,recvbuf,count,datatype,op,comm);
njndbf7ca72006-03-31 11:57:59 +00001935 make_mem_defined_if_addressable_if_success(err, recvbuf, count, datatype);
sewardjc3a47092006-02-18 23:13:33 +00001936 after("Allreduce", err);
1937 return err;
1938}
1939
1940
1941/* --- Op_create --- */
1942/* This is a bit dubious. I suppose it takes 'function' and
1943 writes something at *op, but who knows what an MPI_Op is?
1944 Can we safely do 'sizeof' on it? */
1945int WRAPPER_FOR(PMPI_Op_create)( MPI_User_function* function,
1946 int commute,
1947 MPI_Op* op )
1948{
1949 OrigFn fn;
1950 int err;
1951 VALGRIND_GET_ORIG_FN(fn);
1952 before("Op_create");
njndbf7ca72006-03-31 11:57:59 +00001953 check_mem_is_addressable_untyped(op, sizeof(*op));
sewardjc3a47092006-02-18 23:13:33 +00001954 CALL_FN_W_WWW(err, fn, function,commute,op);
njndbf7ca72006-03-31 11:57:59 +00001955 make_mem_defined_if_addressable_if_success_untyped(err, op, sizeof(*op));
sewardjc3a47092006-02-18 23:13:33 +00001956 after("Op_create", err);
1957 return err;
1958}
1959
1960
1961/*------------------------------------------------------------*/
1962/*--- ---*/
1963/*--- Sec 5.4, Communicator management ---*/
1964/*--- ---*/
1965/*------------------------------------------------------------*/
1966
1967/* Hardly seems worth wrapping Comm_rank and Comm_size, but
1968 since it's done now .. */
1969
sewardj9c969c32006-03-10 18:37:45 +00001970/* --- Comm_create --- */
1971/* Let normal memcheck tracking handle this. */
1972int WRAPPER_FOR(PMPI_Comm_create)(MPI_Comm comm, MPI_Group group,
1973 MPI_Comm* newcomm)
1974{
1975 OrigFn fn;
1976 int err;
1977 VALGRIND_GET_ORIG_FN(fn);
1978 before("Comm_create");
1979 CALL_FN_W_WWW(err, fn, comm,group,newcomm);
1980 after("Comm_create", err);
1981 return err;
1982}
1983
1984/* --- Comm_dup --- */
1985/* Let normal memcheck tracking handle this. */
1986int WRAPPER_FOR(PMPI_Comm_dup)(MPI_Comm comm, MPI_Comm* newcomm)
1987{
1988 OrigFn fn;
1989 int err;
1990 VALGRIND_GET_ORIG_FN(fn);
1991 before("Comm_dup");
1992 CALL_FN_W_WW(err, fn, comm,newcomm);
1993 after("Comm_dup", err);
1994 return err;
1995}
1996
1997/* --- Comm_free --- */
1998/* Let normal memcheck tracking handle this. */
1999int WRAPPER_FOR(PMPI_Comm_free)(MPI_Comm* comm)
2000{
2001 OrigFn fn;
2002 int err;
2003 VALGRIND_GET_ORIG_FN(fn);
2004 before("Comm_free");
2005 CALL_FN_W_W(err, fn, comm);
2006 after("Comm_free", err);
2007 return err;
2008}
2009
sewardjc3a47092006-02-18 23:13:33 +00002010/* --- Comm_rank --- */
2011/* wr: (rank, sizeof(*rank)) */
2012int WRAPPER_FOR(PMPI_Comm_rank)(MPI_Comm comm, int *rank)
2013{
2014 OrigFn fn;
2015 int err;
2016 VALGRIND_GET_ORIG_FN(fn);
2017 before("Comm_rank");
njndbf7ca72006-03-31 11:57:59 +00002018 check_mem_is_addressable_untyped(rank, sizeof(*rank));
sewardjc3a47092006-02-18 23:13:33 +00002019 CALL_FN_W_WW(err, fn, comm,rank);
njndbf7ca72006-03-31 11:57:59 +00002020 make_mem_defined_if_addressable_if_success_untyped(err, rank, sizeof(*rank));
sewardjc3a47092006-02-18 23:13:33 +00002021 after("Comm_rank", err);
2022 return err;
2023}
2024
sewardjc3a47092006-02-18 23:13:33 +00002025/* --- Comm_size --- */
2026/* wr: (size, sizeof(*size)) */
2027int WRAPPER_FOR(PMPI_Comm_size)(MPI_Comm comm, int *size)
2028{
2029 OrigFn fn;
2030 int err;
2031 VALGRIND_GET_ORIG_FN(fn);
2032 before("Comm_size");
njndbf7ca72006-03-31 11:57:59 +00002033 check_mem_is_addressable_untyped(size, sizeof(*size));
sewardjc3a47092006-02-18 23:13:33 +00002034 CALL_FN_W_WW(err, fn, comm,size);
njndbf7ca72006-03-31 11:57:59 +00002035 make_mem_defined_if_addressable_if_success_untyped(err, size, sizeof(*size));
sewardjc3a47092006-02-18 23:13:33 +00002036 after("Comm_size", err);
2037 return err;
2038}
2039
2040
2041/*------------------------------------------------------------*/
2042/*--- ---*/
2043/*--- Sec 5.7, Caching ---*/
2044/*--- ---*/
2045/*------------------------------------------------------------*/
2046
sewardjc3a47092006-02-18 23:13:33 +00002047
2048/*------------------------------------------------------------*/
2049/*--- ---*/
sewardj7d3f4bb2006-03-08 15:27:37 +00002050/*--- Sec 7.3, Error codes and classes ---*/
2051/*--- ---*/
2052/*------------------------------------------------------------*/
2053
2054/* --- Error_string --- */
sewardj9c969c32006-03-10 18:37:45 +00002055int WRAPPER_FOR(PMPI_Error_string)( int errorcode, char* string,
2056 int* resultlen )
sewardj7d3f4bb2006-03-08 15:27:37 +00002057{
2058 OrigFn fn;
2059 int err;
2060 VALGRIND_GET_ORIG_FN(fn);
2061 before("Error_string");
njndbf7ca72006-03-31 11:57:59 +00002062 check_mem_is_addressable_untyped(resultlen, sizeof(int));
2063 check_mem_is_addressable_untyped(string, MPI_MAX_ERROR_STRING);
sewardj7d3f4bb2006-03-08 15:27:37 +00002064 CALL_FN_W_WWW(err, fn, errorcode,string,resultlen);
2065 /* Don't bother to paint the result; we assume the real function
2066 will have filled it with defined characters :-) */
2067 after("Error_string", err);
2068 return err;
2069}
2070
2071
2072/*------------------------------------------------------------*/
2073/*--- ---*/
sewardjc3a47092006-02-18 23:13:33 +00002074/*--- Sec 7.5, Startup ---*/
2075/*--- ---*/
2076/*------------------------------------------------------------*/
2077
2078/* --- Init --- */
2079/* rd: *argc, *argv[0 .. *argc-1] */
sewardjd465d992006-10-17 01:46:55 +00002080long WRAPPER_FOR(PMPI_Init)(int *argc, char ***argv)
sewardjc3a47092006-02-18 23:13:33 +00002081{
2082 OrigFn fn;
2083 int err;
2084 VALGRIND_GET_ORIG_FN(fn);
2085 before("Init");
njndbf7ca72006-03-31 11:57:59 +00002086 check_mem_is_defined_untyped(argc, sizeof(int));
2087 check_mem_is_defined_untyped(*argv, *argc * sizeof(char**));
sewardjc3a47092006-02-18 23:13:33 +00002088 CALL_FN_W_WW(err, fn, argc,argv);
2089 after("Init", err);
sewardjd465d992006-10-17 01:46:55 +00002090 if (opt_initkludge)
2091 return (long)(void*)&mpiwrap_walk_type_EXTERNALLY_VISIBLE;
2092 else
2093 return (long)err;
sewardjc3a47092006-02-18 23:13:33 +00002094}
2095
2096/* --- Initialized --- */
2097int WRAPPER_FOR(PMPI_Initialized)(int* flag)
2098{
2099 OrigFn fn;
2100 int err;
2101 VALGRIND_GET_ORIG_FN(fn);
2102 before("Initialized");
njndbf7ca72006-03-31 11:57:59 +00002103 check_mem_is_addressable_untyped(flag, sizeof(int));
sewardjc3a47092006-02-18 23:13:33 +00002104 CALL_FN_W_W(err, fn, flag);
njndbf7ca72006-03-31 11:57:59 +00002105 make_mem_defined_if_addressable_if_success_untyped(err, flag, sizeof(int));
sewardjc3a47092006-02-18 23:13:33 +00002106 after("Initialized", err);
2107 return err;
2108}
2109
2110/* --- Finalize --- */
2111int WRAPPER_FOR(PMPI_Finalize)(void)
2112{
2113 OrigFn fn;
2114 int err;
2115 VALGRIND_GET_ORIG_FN(fn);
2116 before("Finalize");
2117 CALL_FN_W_v(err, fn);
2118 after("Finalize", err);
2119 return err;
2120}
2121
2122
2123/*------------------------------------------------------------*/
2124/*--- ---*/
sewardj63daa8a2006-03-09 19:08:20 +00002125/*--- Default wrappers for all remaining functions ---*/
sewardjc3a47092006-02-18 23:13:33 +00002126/*--- ---*/
2127/*------------------------------------------------------------*/
2128
sewardj9c969c32006-03-10 18:37:45 +00002129/* Boilerplate for default wrappers. */
sewardj63daa8a2006-03-09 19:08:20 +00002130#define DEFAULT_WRAPPER_PREAMBLE(basename) \
2131 OrigFn fn; \
2132 UWord res; \
sewardj0d17f242006-03-28 01:02:38 +00002133 static int complaints = 1; \
sewardj63daa8a2006-03-09 19:08:20 +00002134 VALGRIND_GET_ORIG_FN(fn); \
2135 before(#basename); \
2136 if (opt_missing >= 2) { \
2137 barf("no wrapper for PMPI_" #basename \
2138 ",\n\t\t\t and you have " \
2139 "requested strict checking"); \
2140 } \
2141 if (opt_missing == 1 && complaints > 0) { \
2142 fprintf(stderr, "%s %5d: warning: no wrapper " \
2143 "for PMPI_" #basename "\n", \
2144 preamble, my_pid); \
2145 complaints--; \
2146 } \
2147
2148#define DEFAULT_WRAPPER_W_0W(basename) \
2149 UWord WRAPPER_FOR(PMPI_##basename)( void ) \
2150 { \
2151 DEFAULT_WRAPPER_PREAMBLE(basename) \
2152 CALL_FN_W_v(res, fn); \
2153 return res; \
2154 }
2155
2156#define DEFAULT_WRAPPER_W_1W(basename) \
2157 UWord WRAPPER_FOR(PMPI_##basename)( UWord a1 ) \
2158 { \
2159 DEFAULT_WRAPPER_PREAMBLE(basename) \
2160 CALL_FN_W_W(res, fn, a1); \
2161 return res; \
2162 }
2163
2164#define DEFAULT_WRAPPER_W_2W(basename) \
2165 UWord WRAPPER_FOR(PMPI_##basename)( UWord a1, UWord a2 ) \
2166 { \
2167 DEFAULT_WRAPPER_PREAMBLE(basename) \
2168 CALL_FN_W_WW(res, fn, a1,a2); \
2169 return res; \
2170 }
2171
2172#define DEFAULT_WRAPPER_W_3W(basename) \
2173 UWord WRAPPER_FOR(PMPI_##basename) \
2174 ( UWord a1, UWord a2, UWord a3 ) \
2175 { \
2176 DEFAULT_WRAPPER_PREAMBLE(basename) \
2177 CALL_FN_W_WWW(res, fn, a1,a2,a3); \
2178 return res; \
2179 }
2180
2181#define DEFAULT_WRAPPER_W_4W(basename) \
2182 UWord WRAPPER_FOR(PMPI_##basename) \
2183 ( UWord a1, UWord a2, UWord a3, UWord a4 ) \
2184 { \
2185 DEFAULT_WRAPPER_PREAMBLE(basename) \
2186 CALL_FN_W_WWWW(res, fn, a1,a2,a3,a4); \
2187 return res; \
2188 }
2189
2190#define DEFAULT_WRAPPER_W_5W(basename) \
2191 UWord WRAPPER_FOR(PMPI_##basename) \
2192 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5 ) \
2193 { \
2194 DEFAULT_WRAPPER_PREAMBLE(basename) \
2195 CALL_FN_W_5W(res, fn, a1,a2,a3,a4,a5); \
2196 return res; \
2197 }
2198
2199#define DEFAULT_WRAPPER_W_6W(basename) \
2200 UWord WRAPPER_FOR(PMPI_##basename) \
2201 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2202 UWord a6 ) \
2203 { \
2204 DEFAULT_WRAPPER_PREAMBLE(basename) \
2205 CALL_FN_W_6W(res, fn, a1,a2,a3,a4,a5,a6); \
2206 return res; \
2207 }
2208
2209#define DEFAULT_WRAPPER_W_7W(basename) \
2210 UWord WRAPPER_FOR(PMPI_##basename) \
2211 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2212 UWord a6, UWord a7 ) \
2213 { \
2214 DEFAULT_WRAPPER_PREAMBLE(basename) \
2215 CALL_FN_W_7W(res, fn, a1,a2,a3,a4,a5,a6,a7); \
2216 return res; \
2217 }
2218
2219#define DEFAULT_WRAPPER_W_8W(basename) \
2220 UWord WRAPPER_FOR(PMPI_##basename) \
2221 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2222 UWord a6, UWord a7, UWord a8 ) \
2223 { \
2224 DEFAULT_WRAPPER_PREAMBLE(basename) \
2225 CALL_FN_W_8W(res, fn, a1,a2,a3,a4,a5,a6,a7,a8); \
2226 return res; \
2227 }
2228
2229#define DEFAULT_WRAPPER_W_9W(basename) \
2230 UWord WRAPPER_FOR(PMPI_##basename) \
2231 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2232 UWord a6, UWord a7, UWord a8, UWord a9 ) \
2233 { \
2234 DEFAULT_WRAPPER_PREAMBLE(basename) \
2235 CALL_FN_W_9W(res, fn, a1,a2,a3,a4,a5,a6,a7,a8,a9); \
2236 return res; \
2237 }
2238
2239#define DEFAULT_WRAPPER_W_10W(basename) \
2240 UWord WRAPPER_FOR(PMPI_##basename) \
2241 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2242 UWord a6, UWord a7, UWord a8, UWord a9, UWord a10 ) \
2243 { \
2244 DEFAULT_WRAPPER_PREAMBLE(basename) \
2245 CALL_FN_W_10W(res, fn, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10); \
2246 return res; \
2247 }
2248
2249#define DEFAULT_WRAPPER_W_12W(basename) \
2250 UWord WRAPPER_FOR(PMPI_##basename) \
2251 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2252 UWord a6, UWord a7, UWord a8, UWord a9, UWord a10, \
2253 UWord a11, UWord a12 ) \
2254 { \
2255 DEFAULT_WRAPPER_PREAMBLE(basename) \
2256 CALL_FN_W_12W(res, fn, a1,a2,a3,a4,a5,a6, \
2257 a7,a8,a9,a10,a11,a12); \
2258 return res; \
2259 }
2260
2261
2262/* Canned summary of MPI-1.1/MPI-2 entry points, as derived from mpi.h
2263 from Open MPI svn rev 9191 (somewhere between Open MPI versions
2264 1.0.1 and 1.1.0). */
2265
2266/* If a function is commented out in this list, it's because it has a
2267 proper wrapper written elsewhere (above here). */
2268
2269DEFAULT_WRAPPER_W_2W(Abort)
2270DEFAULT_WRAPPER_W_9W(Accumulate)
2271DEFAULT_WRAPPER_W_1W(Add_error_class)
2272DEFAULT_WRAPPER_W_2W(Add_error_code)
2273DEFAULT_WRAPPER_W_2W(Add_error_string)
sewardj9c969c32006-03-10 18:37:45 +00002274/* DEFAULT_WRAPPER_W_2W(Address) */
sewardj63daa8a2006-03-09 19:08:20 +00002275DEFAULT_WRAPPER_W_7W(Allgather)
2276DEFAULT_WRAPPER_W_8W(Allgatherv)
2277DEFAULT_WRAPPER_W_3W(Alloc_mem)
2278/* DEFAULT_WRAPPER_W_6W(Allreduce) */
sewardjb727b542006-03-10 21:41:01 +00002279/* DEFAULT_WRAPPER_W_7W(Alltoall) */
sewardj63daa8a2006-03-09 19:08:20 +00002280DEFAULT_WRAPPER_W_9W(Alltoallv)
2281DEFAULT_WRAPPER_W_9W(Alltoallw)
2282DEFAULT_WRAPPER_W_2W(Attr_delete)
2283DEFAULT_WRAPPER_W_4W(Attr_get)
2284DEFAULT_WRAPPER_W_3W(Attr_put)
2285DEFAULT_WRAPPER_W_1W(Barrier)
2286/* DEFAULT_WRAPPER_W_5W(Bcast) */
sewardj9c969c32006-03-10 18:37:45 +00002287/* DEFAULT_WRAPPER_W_6W(Bsend) */
sewardj63daa8a2006-03-09 19:08:20 +00002288DEFAULT_WRAPPER_W_7W(Bsend_init)
2289DEFAULT_WRAPPER_W_2W(Buffer_attach)
2290DEFAULT_WRAPPER_W_2W(Buffer_detach)
sewardjb727b542006-03-10 21:41:01 +00002291/* DEFAULT_WRAPPER_W_1W(Cancel) */
sewardj63daa8a2006-03-09 19:08:20 +00002292DEFAULT_WRAPPER_W_4W(Cart_coords)
2293DEFAULT_WRAPPER_W_6W(Cart_create)
2294DEFAULT_WRAPPER_W_5W(Cart_get)
2295DEFAULT_WRAPPER_W_5W(Cart_map)
2296DEFAULT_WRAPPER_W_3W(Cart_rank)
2297DEFAULT_WRAPPER_W_5W(Cart_shift)
2298DEFAULT_WRAPPER_W_3W(Cart_sub)
2299DEFAULT_WRAPPER_W_2W(Cartdim_get)
2300DEFAULT_WRAPPER_W_1W(Close_port)
2301DEFAULT_WRAPPER_W_5W(Comm_accept)
2302DEFAULT_WRAPPER_W_1W(Comm_c2f)
2303DEFAULT_WRAPPER_W_2W(Comm_call_errhandler)
2304DEFAULT_WRAPPER_W_3W(Comm_compare)
2305DEFAULT_WRAPPER_W_5W(Comm_connect)
2306DEFAULT_WRAPPER_W_2W(Comm_create_errhandler)
2307DEFAULT_WRAPPER_W_4W(Comm_create_keyval)
sewardj9c969c32006-03-10 18:37:45 +00002308/* DEFAULT_WRAPPER_W_3W(Comm_create) */
sewardj63daa8a2006-03-09 19:08:20 +00002309DEFAULT_WRAPPER_W_2W(Comm_delete_attr)
2310DEFAULT_WRAPPER_W_1W(Comm_disconnect)
sewardj9c969c32006-03-10 18:37:45 +00002311/* DEFAULT_WRAPPER_W_2W(Comm_dup) */
sewardj63daa8a2006-03-09 19:08:20 +00002312DEFAULT_WRAPPER_W_1W(Comm_f2c)
2313DEFAULT_WRAPPER_W_1W(Comm_free_keyval)
sewardj9c969c32006-03-10 18:37:45 +00002314/* DEFAULT_WRAPPER_W_1W(Comm_free) */
sewardj63daa8a2006-03-09 19:08:20 +00002315DEFAULT_WRAPPER_W_4W(Comm_get_attr)
2316DEFAULT_WRAPPER_W_2W(Comm_get_errhandler)
2317DEFAULT_WRAPPER_W_3W(Comm_get_name)
2318DEFAULT_WRAPPER_W_1W(Comm_get_parent)
2319DEFAULT_WRAPPER_W_2W(Comm_group)
2320DEFAULT_WRAPPER_W_2W(Comm_join)
2321/* DEFAULT_WRAPPER_W_2W(Comm_rank) */
2322DEFAULT_WRAPPER_W_2W(Comm_remote_group)
2323DEFAULT_WRAPPER_W_2W(Comm_remote_size)
2324DEFAULT_WRAPPER_W_3W(Comm_set_attr)
2325DEFAULT_WRAPPER_W_2W(Comm_set_errhandler)
2326DEFAULT_WRAPPER_W_2W(Comm_set_name)
2327/* DEFAULT_WRAPPER_W_2W(Comm_size) */
2328DEFAULT_WRAPPER_W_8W(Comm_spawn)
2329DEFAULT_WRAPPER_W_9W(Comm_spawn_multiple)
2330DEFAULT_WRAPPER_W_4W(Comm_split)
2331DEFAULT_WRAPPER_W_2W(Comm_test_inter)
2332DEFAULT_WRAPPER_W_3W(Dims_create)
2333DEFAULT_WRAPPER_W_1W(Errhandler_c2f)
2334DEFAULT_WRAPPER_W_2W(Errhandler_create)
2335DEFAULT_WRAPPER_W_1W(Errhandler_f2c)
2336DEFAULT_WRAPPER_W_1W(Errhandler_free)
2337DEFAULT_WRAPPER_W_2W(Errhandler_get)
2338DEFAULT_WRAPPER_W_2W(Errhandler_set)
2339DEFAULT_WRAPPER_W_2W(Error_class)
2340/* DEFAULT_WRAPPER_W_3W(Error_string) */
2341DEFAULT_WRAPPER_W_6W(Exscan)
2342DEFAULT_WRAPPER_W_1W(File_c2f)
2343DEFAULT_WRAPPER_W_1W(File_f2c)
2344DEFAULT_WRAPPER_W_2W(File_call_errhandler)
2345DEFAULT_WRAPPER_W_2W(File_create_errhandler)
2346DEFAULT_WRAPPER_W_2W(File_set_errhandler)
2347DEFAULT_WRAPPER_W_2W(File_get_errhandler)
2348DEFAULT_WRAPPER_W_5W(File_open)
2349DEFAULT_WRAPPER_W_1W(File_close)
2350DEFAULT_WRAPPER_W_2W(File_delete)
2351DEFAULT_WRAPPER_W_2W(File_set_size)
2352DEFAULT_WRAPPER_W_2W(File_preallocate)
2353DEFAULT_WRAPPER_W_2W(File_get_size)
2354DEFAULT_WRAPPER_W_2W(File_get_group)
2355DEFAULT_WRAPPER_W_2W(File_get_amode)
2356DEFAULT_WRAPPER_W_2W(File_set_info)
2357DEFAULT_WRAPPER_W_2W(File_get_info)
2358DEFAULT_WRAPPER_W_6W(File_set_view)
2359DEFAULT_WRAPPER_W_5W(File_get_view)
2360DEFAULT_WRAPPER_W_6W(File_read_at)
2361DEFAULT_WRAPPER_W_6W(File_read_at_all)
2362DEFAULT_WRAPPER_W_6W(File_write_at)
2363DEFAULT_WRAPPER_W_6W(File_write_at_all)
2364DEFAULT_WRAPPER_W_6W(File_iread_at)
2365DEFAULT_WRAPPER_W_6W(File_iwrite_at)
2366DEFAULT_WRAPPER_W_5W(File_read)
2367DEFAULT_WRAPPER_W_5W(File_read_all)
2368DEFAULT_WRAPPER_W_5W(File_write)
2369DEFAULT_WRAPPER_W_5W(File_write_all)
2370DEFAULT_WRAPPER_W_5W(File_iread)
2371DEFAULT_WRAPPER_W_5W(File_iwrite)
2372DEFAULT_WRAPPER_W_3W(File_seek)
2373DEFAULT_WRAPPER_W_2W(File_get_position)
2374DEFAULT_WRAPPER_W_3W(File_get_byte_offset)
2375DEFAULT_WRAPPER_W_5W(File_read_shared)
2376DEFAULT_WRAPPER_W_5W(File_write_shared)
2377DEFAULT_WRAPPER_W_5W(File_iread_shared)
2378DEFAULT_WRAPPER_W_5W(File_iwrite_shared)
2379DEFAULT_WRAPPER_W_5W(File_read_ordered)
2380DEFAULT_WRAPPER_W_5W(File_write_ordered)
2381DEFAULT_WRAPPER_W_3W(File_seek_shared)
2382DEFAULT_WRAPPER_W_2W(File_get_position_shared)
2383DEFAULT_WRAPPER_W_5W(File_read_at_all_begin)
2384DEFAULT_WRAPPER_W_3W(File_read_at_all_end)
2385DEFAULT_WRAPPER_W_5W(File_write_at_all_begin)
2386DEFAULT_WRAPPER_W_3W(File_write_at_all_end)
2387DEFAULT_WRAPPER_W_4W(File_read_all_begin)
2388DEFAULT_WRAPPER_W_3W(File_read_all_end)
2389DEFAULT_WRAPPER_W_4W(File_write_all_begin)
2390DEFAULT_WRAPPER_W_3W(File_write_all_end)
2391DEFAULT_WRAPPER_W_4W(File_read_ordered_begin)
2392DEFAULT_WRAPPER_W_3W(File_read_ordered_end)
2393DEFAULT_WRAPPER_W_4W(File_write_ordered_begin)
2394DEFAULT_WRAPPER_W_3W(File_write_ordered_end)
2395DEFAULT_WRAPPER_W_3W(File_get_type_extent)
2396DEFAULT_WRAPPER_W_2W(File_set_atomicity)
2397DEFAULT_WRAPPER_W_2W(File_get_atomicity)
2398DEFAULT_WRAPPER_W_1W(File_sync)
2399/* DEFAULT_WRAPPER_W_0W(Finalize) */
2400DEFAULT_WRAPPER_W_1W(Finalized)
2401DEFAULT_WRAPPER_W_1W(Free_mem)
2402/* DEFAULT_WRAPPER_W_8W(Gather) */
2403DEFAULT_WRAPPER_W_9W(Gatherv)
2404DEFAULT_WRAPPER_W_2W(Get_address)
sewardj9c969c32006-03-10 18:37:45 +00002405/* DEFAULT_WRAPPER_W_3W(Get_count) */
sewardj63daa8a2006-03-09 19:08:20 +00002406DEFAULT_WRAPPER_W_3W(Get_elements)
2407DEFAULT_WRAPPER_W_8W(Get)
2408DEFAULT_WRAPPER_W_2W(Get_processor_name)
2409DEFAULT_WRAPPER_W_2W(Get_version)
2410DEFAULT_WRAPPER_W_6W(Graph_create)
2411DEFAULT_WRAPPER_W_5W(Graph_get)
2412DEFAULT_WRAPPER_W_5W(Graph_map)
2413DEFAULT_WRAPPER_W_3W(Graph_neighbors_count)
2414DEFAULT_WRAPPER_W_4W(Graph_neighbors)
2415DEFAULT_WRAPPER_W_3W(Graphdims_get)
2416DEFAULT_WRAPPER_W_1W(Grequest_complete)
2417DEFAULT_WRAPPER_W_5W(Grequest_start)
2418DEFAULT_WRAPPER_W_1W(Group_c2f)
2419DEFAULT_WRAPPER_W_3W(Group_compare)
2420DEFAULT_WRAPPER_W_3W(Group_difference)
2421DEFAULT_WRAPPER_W_4W(Group_excl)
2422DEFAULT_WRAPPER_W_1W(Group_f2c)
2423DEFAULT_WRAPPER_W_1W(Group_free)
2424DEFAULT_WRAPPER_W_4W(Group_incl)
2425DEFAULT_WRAPPER_W_3W(Group_intersection)
2426DEFAULT_WRAPPER_W_4W(Group_range_excl)
2427DEFAULT_WRAPPER_W_4W(Group_range_incl)
2428DEFAULT_WRAPPER_W_2W(Group_rank)
2429DEFAULT_WRAPPER_W_2W(Group_size)
2430DEFAULT_WRAPPER_W_5W(Group_translate_ranks)
2431DEFAULT_WRAPPER_W_3W(Group_union)
sewardj9c969c32006-03-10 18:37:45 +00002432/* DEFAULT_WRAPPER_W_7W(Ibsend) */
sewardj63daa8a2006-03-09 19:08:20 +00002433DEFAULT_WRAPPER_W_1W(Info_c2f)
2434DEFAULT_WRAPPER_W_1W(Info_create)
2435DEFAULT_WRAPPER_W_2W(Info_delete)
2436DEFAULT_WRAPPER_W_2W(Info_dup)
2437DEFAULT_WRAPPER_W_1W(Info_f2c)
2438DEFAULT_WRAPPER_W_1W(Info_free)
2439DEFAULT_WRAPPER_W_5W(Info_get)
2440DEFAULT_WRAPPER_W_2W(Info_get_nkeys)
2441DEFAULT_WRAPPER_W_3W(Info_get_nthkey)
2442DEFAULT_WRAPPER_W_4W(Info_get_valuelen)
2443DEFAULT_WRAPPER_W_3W(Info_set)
2444/* DEFAULT_WRAPPER_W_2W(Init) */
2445/* DEFAULT_WRAPPER_W_1W(Initialized) */
2446DEFAULT_WRAPPER_W_4W(Init_thread)
2447DEFAULT_WRAPPER_W_6W(Intercomm_create)
2448DEFAULT_WRAPPER_W_3W(Intercomm_merge)
2449/* DEFAULT_WRAPPER_W_5W(Iprobe) */
2450/* DEFAULT_WRAPPER_W_7W(Irecv) */
sewardj9c969c32006-03-10 18:37:45 +00002451/* DEFAULT_WRAPPER_W_7W(Irsend) */
sewardj63daa8a2006-03-09 19:08:20 +00002452/* DEFAULT_WRAPPER_W_7W(Isend) */
sewardj9c969c32006-03-10 18:37:45 +00002453/* DEFAULT_WRAPPER_W_7W(Issend) */
sewardj63daa8a2006-03-09 19:08:20 +00002454DEFAULT_WRAPPER_W_1W(Is_thread_main)
2455DEFAULT_WRAPPER_W_4W(Keyval_create)
2456DEFAULT_WRAPPER_W_1W(Keyval_free)
2457DEFAULT_WRAPPER_W_3W(Lookup_name)
2458DEFAULT_WRAPPER_W_1W(Op_c2f)
2459/* DEFAULT_WRAPPER_W_3W(Op_create) */
2460DEFAULT_WRAPPER_W_2W(Open_port)
2461DEFAULT_WRAPPER_W_1W(Op_f2c)
2462DEFAULT_WRAPPER_W_1W(Op_free)
2463DEFAULT_WRAPPER_W_7W(Pack_external)
2464DEFAULT_WRAPPER_W_4W(Pack_external_size)
sewardjee346592007-02-08 12:05:03 +00002465/* DEFAULT_WRAPPER_W_7W(Pack) */
sewardj63daa8a2006-03-09 19:08:20 +00002466DEFAULT_WRAPPER_W_4W(Pack_size)
2467/* int MPI_Pcontrol(const int level, ...) */
sewardjb727b542006-03-10 21:41:01 +00002468/* DEFAULT_WRAPPER_W_4W(Probe) */
sewardj63daa8a2006-03-09 19:08:20 +00002469DEFAULT_WRAPPER_W_3W(Publish_name)
2470DEFAULT_WRAPPER_W_8W(Put)
2471DEFAULT_WRAPPER_W_1W(Query_thread)
2472DEFAULT_WRAPPER_W_7W(Recv_init)
2473/* DEFAULT_WRAPPER_W_7W(Recv) */
2474/* DEFAULT_WRAPPER_W_7W(Reduce) */
2475DEFAULT_WRAPPER_W_6W(Reduce_scatter)
2476DEFAULT_WRAPPER_W_5W(Register_datarep)
2477DEFAULT_WRAPPER_W_1W(Request_c2f)
2478DEFAULT_WRAPPER_W_1W(Request_f2c)
2479DEFAULT_WRAPPER_W_1W(Request_free)
2480DEFAULT_WRAPPER_W_3W(Request_get_status)
sewardj9c969c32006-03-10 18:37:45 +00002481/* DEFAULT_WRAPPER_W_6W(Rsend) */
sewardj63daa8a2006-03-09 19:08:20 +00002482DEFAULT_WRAPPER_W_7W(Rsend_init)
2483DEFAULT_WRAPPER_W_6W(Scan)
sewardjb727b542006-03-10 21:41:01 +00002484/* DEFAULT_WRAPPER_W_8W(Scatter) */
sewardj63daa8a2006-03-09 19:08:20 +00002485DEFAULT_WRAPPER_W_9W(Scatterv)
2486DEFAULT_WRAPPER_W_7W(Send_init)
2487/* DEFAULT_WRAPPER_W_6W(Send) */
2488/* DEFAULT_WRAPPER_W_12W(Sendrecv) */
2489DEFAULT_WRAPPER_W_9W(Sendrecv_replace)
2490DEFAULT_WRAPPER_W_7W(Ssend_init)
sewardj9c969c32006-03-10 18:37:45 +00002491/* DEFAULT_WRAPPER_W_6W(Ssend) */
sewardj63daa8a2006-03-09 19:08:20 +00002492DEFAULT_WRAPPER_W_1W(Start)
2493DEFAULT_WRAPPER_W_2W(Startall)
2494DEFAULT_WRAPPER_W_2W(Status_c2f)
2495DEFAULT_WRAPPER_W_2W(Status_f2c)
2496DEFAULT_WRAPPER_W_2W(Status_set_cancelled)
2497DEFAULT_WRAPPER_W_3W(Status_set_elements)
sewardjb727b542006-03-10 21:41:01 +00002498/* DEFAULT_WRAPPER_W_4W(Testall) */
sewardj63daa8a2006-03-09 19:08:20 +00002499DEFAULT_WRAPPER_W_5W(Testany)
sewardjb727b542006-03-10 21:41:01 +00002500/* DEFAULT_WRAPPER_W_3W(Test) */
sewardj63daa8a2006-03-09 19:08:20 +00002501DEFAULT_WRAPPER_W_2W(Test_cancelled)
2502DEFAULT_WRAPPER_W_5W(Testsome)
2503DEFAULT_WRAPPER_W_2W(Topo_test)
2504DEFAULT_WRAPPER_W_1W(Type_c2f)
sewardj9c969c32006-03-10 18:37:45 +00002505/* DEFAULT_WRAPPER_W_1W(Type_commit) */
sewardj63daa8a2006-03-09 19:08:20 +00002506DEFAULT_WRAPPER_W_3W(Type_contiguous)
2507DEFAULT_WRAPPER_W_10W(Type_create_darray)
2508DEFAULT_WRAPPER_W_3W(Type_create_f90_complex)
2509DEFAULT_WRAPPER_W_2W(Type_create_f90_integer)
2510DEFAULT_WRAPPER_W_3W(Type_create_f90_real)
2511DEFAULT_WRAPPER_W_5W(Type_create_hindexed)
2512DEFAULT_WRAPPER_W_5W(Type_create_hvector)
2513DEFAULT_WRAPPER_W_4W(Type_create_keyval)
2514DEFAULT_WRAPPER_W_5W(Type_create_indexed_block)
2515DEFAULT_WRAPPER_W_5W(Type_create_struct)
2516DEFAULT_WRAPPER_W_7W(Type_create_subarray)
2517DEFAULT_WRAPPER_W_4W(Type_create_resized)
2518DEFAULT_WRAPPER_W_2W(Type_delete_attr)
2519DEFAULT_WRAPPER_W_2W(Type_dup)
sewardj9c969c32006-03-10 18:37:45 +00002520/* DEFAULT_WRAPPER_W_2W(Type_extent) */
2521/* DEFAULT_WRAPPER_W_1W(Type_free) */
sewardj63daa8a2006-03-09 19:08:20 +00002522DEFAULT_WRAPPER_W_1W(Type_free_keyval)
2523DEFAULT_WRAPPER_W_1W(Type_f2c)
2524DEFAULT_WRAPPER_W_4W(Type_get_attr)
sewardj9c969c32006-03-10 18:37:45 +00002525/* DEFAULT_WRAPPER_W_7W(Type_get_contents) */
2526/* DEFAULT_WRAPPER_W_5W(Type_get_envelope) */
sewardj63daa8a2006-03-09 19:08:20 +00002527DEFAULT_WRAPPER_W_3W(Type_get_extent)
2528DEFAULT_WRAPPER_W_3W(Type_get_name)
2529DEFAULT_WRAPPER_W_3W(Type_get_true_extent)
2530DEFAULT_WRAPPER_W_5W(Type_hindexed)
2531DEFAULT_WRAPPER_W_5W(Type_hvector)
2532DEFAULT_WRAPPER_W_5W(Type_indexed)
2533DEFAULT_WRAPPER_W_2W(Type_lb)
2534DEFAULT_WRAPPER_W_3W(Type_match_size)
2535DEFAULT_WRAPPER_W_3W(Type_set_attr)
2536DEFAULT_WRAPPER_W_2W(Type_set_name)
2537DEFAULT_WRAPPER_W_2W(Type_size)
2538DEFAULT_WRAPPER_W_5W(Type_struct)
2539DEFAULT_WRAPPER_W_2W(Type_ub)
2540DEFAULT_WRAPPER_W_5W(Type_vector)
sewardjee346592007-02-08 12:05:03 +00002541/* DEFAULT_WRAPPER_W_7W(Unpack) */
sewardj63daa8a2006-03-09 19:08:20 +00002542DEFAULT_WRAPPER_W_3W(Unpublish_name)
2543DEFAULT_WRAPPER_W_7W(Unpack_external)
2544/* DEFAULT_WRAPPER_W_3W(Waitall) */
2545DEFAULT_WRAPPER_W_4W(Waitany)
2546/* DEFAULT_WRAPPER_W_2W(Wait) */
2547DEFAULT_WRAPPER_W_5W(Waitsome)
2548DEFAULT_WRAPPER_W_1W(Win_c2f)
2549DEFAULT_WRAPPER_W_2W(Win_call_errhandler)
2550DEFAULT_WRAPPER_W_1W(Win_complete)
2551DEFAULT_WRAPPER_W_6W(Win_create)
2552DEFAULT_WRAPPER_W_2W(Win_create_errhandler)
2553DEFAULT_WRAPPER_W_4W(Win_create_keyval)
2554DEFAULT_WRAPPER_W_2W(Win_delete_attr)
2555DEFAULT_WRAPPER_W_1W(Win_f2c)
2556DEFAULT_WRAPPER_W_2W(Win_fence)
2557DEFAULT_WRAPPER_W_1W(Win_free)
2558DEFAULT_WRAPPER_W_1W(Win_free_keyval)
2559DEFAULT_WRAPPER_W_4W(Win_get_attr)
2560DEFAULT_WRAPPER_W_2W(Win_get_errhandler)
2561DEFAULT_WRAPPER_W_2W(Win_get_group)
2562DEFAULT_WRAPPER_W_3W(Win_get_name)
2563DEFAULT_WRAPPER_W_4W(Win_lock)
2564DEFAULT_WRAPPER_W_3W(Win_post)
2565DEFAULT_WRAPPER_W_3W(Win_set_attr)
2566DEFAULT_WRAPPER_W_2W(Win_set_errhandler)
2567DEFAULT_WRAPPER_W_2W(Win_set_name)
2568DEFAULT_WRAPPER_W_3W(Win_start)
2569DEFAULT_WRAPPER_W_2W(Win_test)
2570DEFAULT_WRAPPER_W_2W(Win_unlock)
2571DEFAULT_WRAPPER_W_1W(Win_wait)
2572/* double MPI_Wtick(void) */
2573/* double MPI_Wtime(void) */
2574
2575
sewardjc3a47092006-02-18 23:13:33 +00002576/*------------------------------------------------------------*/
2577/*--- ---*/
2578/*--- ---*/
2579/*--- ---*/
2580/*------------------------------------------------------------*/
2581
sewardjc3a47092006-02-18 23:13:33 +00002582/*---------------------------------------------------------------*/
2583/*--- end mpiwrap.c ---*/
2584/*---------------------------------------------------------------*/