2 /*---------------------------------------------------------------*/
4 /*--- A library of wrappers for MPI 2 functions. ---*/
6 /*---------------------------------------------------------------*/
8 /* ----------------------------------------------------------------
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.
16 ----------------------------------------------------------------
18 This file is part of Valgrind, a dynamic binary instrumentation
21 Copyright (C) 2006-2017 OpenWorks LLP. All rights reserved.
23 Redistribution and use in source and binary forms, with or without
24 modification, are permitted provided that the following conditions
27 1. Redistributions of source code must retain the above copyright
28 notice, this list of conditions and the following disclaimer.
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.
35 3. Altered source versions must be plainly marked as such, and must
36 not be misrepresented as being the original software.
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
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.
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.
60 /* Handling of MPI_STATUS{ES}_IGNORE for MPI_Status* arguments.
62 The MPI-2 spec allows many functions which have MPI_Status* purely
63 as an out parameter, to accept the constants MPI_STATUS_IGNORE or
64 MPI_STATUSES_IGNORE there instead, if the caller does not care
65 about the status. See the MPI-2 spec sec 4.5.1 ("Passing
66 MPI_STATUS_IGNORE for Status"). (mpi2-report.pdf, 1615898 bytes,
67 md5=694a5efe2fd291eecf7e8c9875b5f43f).
69 This library handles such cases by allocating a fake MPI_Status
70 object (on the stack) or an array thereof (on the heap), and
71 passing that onwards instead. From the outside the caller sees no
72 difference. Unfortunately the simpler approach of merely detecting
73 and handling these special cases at a lower level does not work,
74 because we need to use information returned in MPI_Status*
75 arguments to paint result buffers, even if the caller doesn't
76 supply a real MPI_Status object.
78 Eg, MPI_Recv. We can't paint the result buffer without knowing how
79 many items arrived; but we can't find that out without passing a
80 real MPI_Status object to the (real) MPI_Recv call. Hence, if the
81 caller did not supply one, we have no option but to use a temporary
82 stack allocated one for the inner call. Ditto, more indirectly
83 (via maybe_complete) for nonblocking receives and the various
84 associated wait/test calls. */
87 /*------------------------------------------------------------*/
89 /*------------------------------------------------------------*/
93 #include <unistd.h> /* getpid */
94 #include <stdlib.h> /* exit */
95 #include <string.h> /* strstr */
96 #include <pthread.h> /* pthread_mutex_{lock,unlock} */
98 /* Include Valgrind magic macros for writing wrappers. */
99 #include "../memcheck/memcheck.h"
101 /* Include macros for VALGRIND_{DIS,EN}ABLE_ERROR_REPORTING.
102 This is somewhat experimental and hence disable-able, by
103 setting cONFIG_DER to zero. */
104 #include "../include/valgrind.h"
106 #define cONFIG_DER 1 /* set to 0 to disable */
109 /*------------------------------------------------------------*/
110 /*--- Connect to MPI library ---*/
111 /*------------------------------------------------------------*/
113 /* Include headers for whatever MPI implementation the wrappers are to
114 be used with. The configure system will tell us what the path to
115 the chosen MPI implementation is, via -I.. to the compiler. */
118 /* Where are API symbols?
119 Open MPI lib/libmpi.so, soname = libmpi.so.0
120 Quadrics MPI lib/libmpi.so, soname = libmpi.so.0
121 MPICH libmpich.so.1.0, soname = libmpich.so.1.0
123 A suitable soname to match with is therefore "libmpi*.so*".
125 #define I_WRAP_FNNAME_U(_name) \
126 I_WRAP_SONAME_FNNAME_ZU(libmpiZaZdsoZa,_name)
129 /* Define HAVE_MPI_STATUS_IGNORE iff we have to deal with
130 MPI_STATUS{ES}_IGNORE. */
131 #if MPI_VERSION >= 2 \
132 || (defined(MPI_STATUS_IGNORE) && defined(MPI_STATUSES_IGNORE))
133 # undef HAVE_MPI_STATUS_IGNORE
134 # define HAVE_MPI_STATUS_IGNORE 1
136 # undef HAVE_MPI_STATUS_IGNORE
140 /*------------------------------------------------------------*/
142 /*------------------------------------------------------------*/
144 typedef unsigned char Bool
;
145 #define False ((Bool)0)
146 #define True ((Bool)1)
148 /* Word, UWord are machine words - same size as a pointer. This is
149 checked at startup. The wrappers below use 'long' to mean a
150 machine word - this too is tested at startup. */
151 typedef signed long Word
;
152 typedef unsigned long UWord
;
154 #if !defined(offsetof)
155 # define offsetof(type,memb) ((UWord)&((type*)0)->memb)
158 /* Find the size of long double image (not 'sizeof(long double)').
159 See comments in sizeofOneNamedTy. */
160 static long sizeof_long_double_image ( void );
163 /*------------------------------------------------------------*/
164 /*--- Simple helpers ---*/
165 /*------------------------------------------------------------*/
167 /* ------ Helpers for debug printing ------ */
170 static const char* preamble
= "valgrind MPI wrappers";
172 /* established at startup */
173 static pid_t my_pid
= -1;
174 static char* options_str
= NULL
;
175 static int opt_verbosity
= 1;
176 static Bool opt_missing
= 0; /* 0:silent; 1:warn; 2:abort */
177 static Bool opt_help
= False
;
178 static Bool opt_initkludge
= False
;
180 static void before ( char* fnname
)
182 /* This isn't thread-safe wrt 'done' (no locking). It's not
188 options_str
= getenv("MPIWRAP_DEBUG");
190 if (NULL
!= strstr(options_str
, "warn"))
192 if (NULL
!= strstr(options_str
, "strict"))
194 if (NULL
!= strstr(options_str
, "verbose"))
196 if (NULL
!= strstr(options_str
, "quiet"))
198 if (NULL
!= strstr(options_str
, "help"))
200 if (NULL
!= strstr(options_str
, "initkludge"))
201 opt_initkludge
= True
;
203 if (opt_verbosity
> 0)
204 fprintf(stderr
, "%s %5d: Active for pid %d\n",
205 preamble
, my_pid
, my_pid
);
206 /* Sanity check - that Word/UWord really are machine words. */
207 assert(sizeof(Word
) == sizeof(void*));
208 assert(sizeof(UWord
) == sizeof(void*));
209 /* Sanity check - char is byte-sized (else address calculations
210 in walk_type don't work. */
211 assert(sizeof(char) == 1);
213 fprintf(stderr
, "\n");
214 fprintf(stderr
, "Valid options for the MPIWRAP_DEBUG environment"
216 fprintf(stderr
, "\n");
217 fprintf(stderr
, " quiet be silent except for errors\n");
218 fprintf(stderr
, " verbose show wrapper entries/exits\n");
219 fprintf(stderr
, " strict abort the program if a function"
220 " with no wrapper is used\n");
221 fprintf(stderr
, " warn give a warning if a function"
222 " with no wrapper is used\n");
223 fprintf(stderr
, " help display this message, then exit\n");
224 fprintf(stderr
, " initkludge debugging hack; do not use\n");
225 fprintf(stderr
, "\n");
226 fprintf(stderr
, "Multiple options are allowed, eg"
227 " MPIWRAP_DEBUG=strict,verbose\n");
228 fprintf(stderr
, "Note: 'warn' generates output even if 'quiet'"
229 " is also specified\n");
230 fprintf(stderr
, "\n");
231 fprintf(stderr
, "%s %5d: exiting now\n", preamble
, my_pid
);
234 if (opt_verbosity
> 0)
236 "%s %5d: Try MPIWRAP_DEBUG=help for possible options\n",
240 if (opt_verbosity
> 1)
241 fprintf(stderr
, "%s %5d: enter PMPI_%s\n", preamble
, my_pid
, fnname
);
244 static __inline__
void after ( char* fnname
, int err
)
246 if (opt_verbosity
> 1)
247 fprintf(stderr
, "%s %5d: exit PMPI_%s (err = %d)\n",
248 preamble
, my_pid
, fnname
, err
);
251 static void barf ( char* msg
)
253 fprintf(stderr
, "%s %5d: fatal: %s\n", preamble
, my_pid
, msg
);
254 fprintf(stderr
, "%s %5d: exiting now\n", preamble
, my_pid
);
258 /* Half-hearted type-showing function (for debugging). */
259 static void showTy ( FILE* f
, MPI_Datatype ty
)
261 if (ty
== MPI_DATATYPE_NULL
) fprintf(f
,"DATATYPE_NULL");
262 else if (ty
== MPI_BYTE
) fprintf(f
,"BYTE");
263 else if (ty
== MPI_PACKED
) fprintf(f
,"PACKED");
264 else if (ty
== MPI_CHAR
) fprintf(f
,"CHAR");
265 else if (ty
== MPI_SHORT
) fprintf(f
,"SHORT");
266 else if (ty
== MPI_INT
) fprintf(f
,"INT");
267 else if (ty
== MPI_LONG
) fprintf(f
,"LONG");
268 else if (ty
== MPI_FLOAT
) fprintf(f
,"FLOAT");
269 else if (ty
== MPI_DOUBLE
) fprintf(f
,"DOUBLE");
270 else if (ty
== MPI_LONG_DOUBLE
) fprintf(f
,"LONG_DOUBLE");
271 else if (ty
== MPI_UNSIGNED_CHAR
) fprintf(f
,"UNSIGNED_CHAR");
272 else if (ty
== MPI_UNSIGNED_SHORT
) fprintf(f
,"UNSIGNED_SHORT");
273 else if (ty
== MPI_UNSIGNED_LONG
) fprintf(f
,"UNSIGNED_LONG");
274 else if (ty
== MPI_UNSIGNED
) fprintf(f
,"UNSIGNED");
275 else if (ty
== MPI_FLOAT_INT
) fprintf(f
,"FLOAT_INT");
276 else if (ty
== MPI_DOUBLE_INT
) fprintf(f
,"DOUBLE_INT");
277 else if (ty
== MPI_LONG_DOUBLE_INT
) fprintf(f
,"LONG_DOUBLE_INT");
278 else if (ty
== MPI_LONG_INT
) fprintf(f
,"LONG_INT");
279 else if (ty
== MPI_SHORT_INT
) fprintf(f
,"SHORT_INT");
280 else if (ty
== MPI_2INT
) fprintf(f
,"2INT");
281 # if defined(MPI_UB) && \
282 (!defined(OMPI_MAJOR_VERSION) || OMPI_MAJOR_VERSION < 3)
283 else if (ty
== MPI_UB
) fprintf(f
,"UB");
285 # if defined(MPI_LB) && \
286 (!defined(OMPI_MAJOR_VERSION) || OMPI_MAJOR_VERSION < 3)
287 else if (ty
== MPI_LB
) fprintf(f
,"LB");
289 # if defined(MPI_WCHAR)
290 else if (ty
== MPI_WCHAR
) fprintf(f
,"WCHAR");
292 else if (ty
== MPI_LONG_LONG_INT
) fprintf(f
,"LONG_LONG_INT");
293 # if defined(MPI_LONG_LONG)
294 else if (ty
== MPI_LONG_LONG
) fprintf(f
,"LONG_LONG");
296 # if defined(MPI_UNSIGNED_LONG_LONG)
297 else if (ty
== MPI_UNSIGNED_LONG_LONG
) fprintf(f
,"UNSIGNED_LONG_LONG");
299 # if defined(MPI_REAL8)
300 else if (ty
== MPI_REAL8
) fprintf(f
, "REAL8");
302 # if defined(MPI_REAL4)
303 else if (ty
== MPI_REAL4
) fprintf(f
, "REAL4");
305 # if defined(MPI_REAL)
306 else if (ty
== MPI_REAL
) fprintf(f
, "REAL");
308 # if defined(MPI_INTEGER8)
309 else if (ty
== MPI_INTEGER8
) fprintf(f
, "INTEGER8");
311 # if defined(MPI_INTEGER4)
312 else if (ty
== MPI_INTEGER4
) fprintf(f
, "INTEGER4");
314 # if defined(MPI_INTEGER)
315 else if (ty
== MPI_INTEGER
) fprintf(f
, "INTEGER");
317 # if defined(MPI_DOUBLE_PRECISION)
318 else if (ty
== MPI_DOUBLE_PRECISION
) fprintf(f
, "DOUBLE_PRECISION");
320 # if defined(MPI_COMPLEX)
321 else if (ty
== MPI_COMPLEX
) fprintf(f
, "COMPLEX");
323 # if defined(MPI_DOUBLE_COMPLEX)
324 else if (ty
== MPI_DOUBLE_COMPLEX
) fprintf(f
, "DOUBLE_COMPLEX");
326 # if defined(MPI_LOGICAL)
327 else if (ty
== MPI_LOGICAL
) fprintf(f
, "LOGICAL");
329 # if defined(MPI_2INTEGER)
330 else if (ty
== MPI_2INTEGER
) fprintf(f
, "2INTEGER");
332 # if defined(MPI_2COMPLEX)
333 else if (ty
== MPI_2COMPLEX
) fprintf(f
, "2COMPLEX");
335 # if defined(MPI_2DOUBLE_COMPLEX)
336 else if (ty
== MPI_2DOUBLE_COMPLEX
) fprintf(f
, "2DOUBLE_COMPLEX");
338 # if defined(MPI_2REAL)
339 else if (ty
== MPI_2REAL
) fprintf(f
, "2REAL");
341 # if defined(MPI_2DOUBLE_PRECISION)
342 else if (ty
== MPI_2DOUBLE_PRECISION
) fprintf(f
, "2DOUBLE_PRECISION");
344 # if defined(MPI_CHARACTER)
345 else if (ty
== MPI_CHARACTER
) fprintf(f
, "CHARACTER");
347 else fprintf(f
,"showTy:???");
350 static void showCombiner ( FILE* f
, int combiner
)
353 case MPI_COMBINER_NAMED
: fprintf(f
, "NAMED"); break;
354 # if defined(MPI_COMBINER_DUP)
355 case MPI_COMBINER_DUP
: fprintf(f
, "DUP"); break;
357 case MPI_COMBINER_CONTIGUOUS
: fprintf(f
, "CONTIGUOUS"); break;
358 case MPI_COMBINER_VECTOR
: fprintf(f
, "VECTOR"); break;
359 # if defined(MPI_COMBINER_HVECTOR_INTEGER) && \
360 (!defined(OMPI_MAJOR_VERSION) || OMPI_MAJOR_VERSION < 3)
361 case MPI_COMBINER_HVECTOR_INTEGER
: fprintf(f
, "HVECTOR_INTEGER"); break;
363 case MPI_COMBINER_HVECTOR
: fprintf(f
, "HVECTOR"); break;
364 case MPI_COMBINER_INDEXED
: fprintf(f
, "INDEXED"); break;
365 # if defined(MPI_COMBINER_HINDEXED_INTEGER) && \
366 (!defined(OMPI_MAJOR_VERSION) || OMPI_MAJOR_VERSION < 3)
367 case MPI_COMBINER_HINDEXED_INTEGER
: fprintf(f
, "HINDEXED_INTEGER"); break;
369 case MPI_COMBINER_HINDEXED
: fprintf(f
, "HINDEXED"); break;
370 # if defined(MPI_COMBINER_INDEXED_BLOCK)
371 case MPI_COMBINER_INDEXED_BLOCK
: fprintf(f
, "INDEXED_BLOCK"); break;
373 # if defined(MPI_COMBINER_STRUCT_INTEGER) && \
374 (!defined(OMPI_MAJOR_VERSION) || OMPI_MAJOR_VERSION < 3)
375 case MPI_COMBINER_STRUCT_INTEGER
: fprintf(f
, "STRUCT_INTEGER"); break;
377 case MPI_COMBINER_STRUCT
: fprintf(f
, "STRUCT"); break;
378 # if defined(MPI_COMBINER_SUBARRAY)
379 case MPI_COMBINER_SUBARRAY
: fprintf(f
, "SUBARRAY"); break;
381 # if defined(MPI_COMBINER_DARRAY)
382 case MPI_COMBINER_DARRAY
: fprintf(f
, "DARRAY"); break;
384 # if defined(MPI_COMBINER_F90_REAL)
385 case MPI_COMBINER_F90_REAL
: fprintf(f
, "F90_REAL"); break;
387 # if defined(MPI_COMBINER_F90_COMPLEX)
388 case MPI_COMBINER_F90_COMPLEX
: fprintf(f
, "F90_COMPLEX"); break;
390 # if defined(MPI_COMBINER_F90_INTEGER)
391 case MPI_COMBINER_F90_INTEGER
: fprintf(f
, "F90_INTEGER"); break;
393 # if defined(MPI_COMBINER_RESIZED)
394 case MPI_COMBINER_RESIZED
: fprintf(f
, "RESIZED"); break;
396 default: fprintf(f
, "showCombiner:??"); break;
401 /* ------ Get useful bits of info ------ */
403 /* Note, PMPI_Comm_rank/size are themselves wrapped. Should work
406 static __inline__
int comm_rank ( MPI_Comm comm
)
409 err
= PMPI_Comm_rank(comm
, &r
);
410 return err
? 0/*arbitrary*/ : r
;
413 static __inline__
int comm_size ( MPI_Comm comm
)
416 err
= PMPI_Comm_size(comm
, &r
);
417 return err
? 0/*arbitrary*/ : r
;
420 static __inline__ Bool
count_from_Status( /*OUT*/int* recv_count
,
421 MPI_Datatype datatype
,
425 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
426 int err
= PMPI_Get_count(status
, datatype
, &n
);
427 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
428 if (err
== MPI_SUCCESS
) {
429 VALGRIND_MAKE_MEM_DEFINED(&n
, sizeof(n
));
437 /* It's critical that we can do equality on MPI_Requests.
438 Unfortunately these are opaque objects to us (handles, in the
439 parlance of the MPI 1.1 spec). Fortunately Sec 2.4.1 ("Opaque
440 Objects") specifies that "In C, [...] These [handles] should be
441 types that support assignment and equality operations." Hence the
442 following function should compile for any compliant definition of
445 Bool
eq_MPI_Request ( MPI_Request r1
, MPI_Request r2
)
450 /* Return True if status is MPI_STATUS_IGNORE or MPI_STATUSES_IGNORE.
451 On MPI-1.x platforms which don't have these symbols (and they would
452 only have them if they've been backported from 2.x) always return
455 Bool
isMSI ( MPI_Status
* status
)
457 # if defined(HAVE_MPI_STATUS_IGNORE)
458 return status
== MPI_STATUSES_IGNORE
|| status
== MPI_STATUS_IGNORE
;
464 /* Get the 'extent' of a type. Note, as per the MPI spec this
465 includes whatever padding would be required when using 'ty' in an
467 static long extentOfTy ( MPI_Datatype ty
)
471 # if defined(MPI_TYPE_EXTENT)
472 r
= PMPI_Type_extent(ty
, &n
);
475 r
= MPI_Type_get_extent(ty
, &lb
, &n
);
477 assert(r
== MPI_SUCCESS
);
481 /* Free up *ty, if it is safe to do so */
482 static void maybeFreeTy ( MPI_Datatype
* ty
)
484 int r
, n_ints
, n_addrs
, n_dtys
, tycon
;
486 r
= PMPI_Type_get_envelope( *ty
, &n_ints
, &n_addrs
, &n_dtys
, &tycon
);
487 assert(r
== MPI_SUCCESS
);
489 /* can't free named types */
490 if (tycon
== MPI_COMBINER_NAMED
)
493 /* some kinds of structs are predefined so we can't free them
495 if (*ty
== MPI_FLOAT_INT
|| *ty
== MPI_DOUBLE_INT
496 || *ty
== MPI_LONG_INT
|| *ty
== MPI_2INT
497 || *ty
== MPI_SHORT_INT
|| *ty
== MPI_LONG_DOUBLE_INT
)
500 /* Looks OK - free it. */
502 /* show me what you're about to free .. */
503 fprintf(stderr
, "freeing combiner ");
504 showCombiner(stderr
,tycon
);
505 fprintf(stderr
, " ty= ");
507 fprintf(stderr
,"\n");
509 r
= PMPI_Type_free(ty
);
510 assert(r
== MPI_SUCCESS
);
513 /* How big is a "named" (base) type? Returns 0 if not known. Note.
514 There is a subtlety, which is that this is required to return the
515 exact size of one item of the type, NOT the size of it when padded
516 suitably to make an array of them. In particular that's why the
517 size of LONG_DOUBLE is computed by looking at the result of doing a
518 long double store, rather than just asking what is the sizeof(long
521 For LONG_DOUBLE on x86-linux and amd64-linux my impression is that
522 the right answer is 10 even though sizeof(long double) says 12 and
523 16 respectively. On ppc32-linux it appears to be 16.
525 Ref: MPI 1.1 doc p18 */
526 static long sizeofOneNamedTy ( MPI_Datatype ty
)
528 if (ty
== MPI_CHAR
) return sizeof(signed char);
529 if (ty
== MPI_SHORT
) return sizeof(signed short int);
530 if (ty
== MPI_INT
) return sizeof(signed int);
531 if (ty
== MPI_LONG
) return sizeof(signed long int);
532 if (ty
== MPI_UNSIGNED_CHAR
) return sizeof(unsigned char);
533 if (ty
== MPI_UNSIGNED_SHORT
) return sizeof(unsigned short int);
534 if (ty
== MPI_UNSIGNED
) return sizeof(unsigned int);
535 if (ty
== MPI_UNSIGNED_LONG
) return sizeof(unsigned long int);
536 if (ty
== MPI_FLOAT
) return sizeof(float);
537 if (ty
== MPI_DOUBLE
) return sizeof(double);
538 if (ty
== MPI_BYTE
) return 1;
539 if (ty
== MPI_LONG_DOUBLE
) return sizeof_long_double_image();
540 if (ty
== MPI_PACKED
) return 1;
541 if (ty
== MPI_LONG_LONG_INT
) return sizeof(signed long long int);
543 # if defined(MPI_REAL8)
544 if (ty
== MPI_REAL8
) return 8; /* MPI2 spec */;
546 # if defined(MPI_REAL4)
547 if (ty
== MPI_REAL4
) return 4; /* MPI2 spec */;
549 # if defined(MPI_REAL)
550 if (ty
== MPI_REAL
) return 4; /* MPI2 spec */;
552 # if defined(MPI_INTEGER8)
553 if (ty
== MPI_INTEGER8
) return 8; /* MPI2 spec */;
555 # if defined(MPI_INTEGER4)
556 if (ty
== MPI_INTEGER4
) return 4; /* MPI2 spec */;
558 # if defined(MPI_INTEGER)
559 if (ty
== MPI_INTEGER
) return 4; /* MPI2 spec */;
561 # if defined(MPI_DOUBLE_PRECISION)
562 if (ty
== MPI_DOUBLE_PRECISION
) return 8; /* MPI2 spec */;
566 # if defined(MPI_WCHAR)
567 if (ty
== MPI_WCHAR
) return 2; /* MPI2 spec */;
569 # if defined(MPI_SIGNED_CHAR)
570 if (ty
== MPI_SIGNED_CHAR
) return 1; /* MPI2 spec */;
572 # if defined(MPI_UNSIGNED_LONG_LONG)
573 if (ty
== MPI_UNSIGNED_LONG_LONG
) return 8; /* MPI2 spec */;
575 # if defined(MPI_COMPLEX)
576 if (ty
== MPI_COMPLEX
) return 2 * 4; /* MPI2 spec */
578 # if defined(MPI_DOUBLE_COMPLEX)
579 if (ty
== MPI_DOUBLE_COMPLEX
) return 2 * 8; /* MPI2 spec */
581 # if defined(MPI_LOGICAL)
582 if (ty
== MPI_LOGICAL
) return 4; /* MPI2 spec */
584 # if defined(MPI_2INTEGER)
585 if (ty
== MPI_2INTEGER
) return 2 * 4; /* undocumented in MPI2 */
587 # if defined(MPI_2COMPLEX)
588 if (ty
== MPI_2COMPLEX
) return 2 * 8; /* undocumented in MPI2 */
590 # if defined(MPI_2DOUBLE_COMPLEX)
591 /* 32: this is how openmpi-1.2.2 behaves on x86-linux, but I have
592 really no idea if this is right. */
593 if (ty
== MPI_2DOUBLE_COMPLEX
) return 32; /* undocumented in MPI2 */
595 # if defined(MPI_2REAL)
596 if (ty
== MPI_2REAL
) return 2 * 4; /* undocumented in MPI2 */
598 # if defined(MPI_2DOUBLE_PRECISION)
599 if (ty
== MPI_2DOUBLE_PRECISION
) return 2 * 8; /* undocumented in MPI2 */
601 # if defined(MPI_CHARACTER)
602 if (ty
== MPI_CHARACTER
) return 1; /* MPI2 spec */
605 /* Note: the following are named structs, not named basic types,
606 and so are not handled here:
607 FLOAT_INT DOUBLE_INT LONG_INT 2INT SHORT_INT LONG_DOUBLE_INT
608 My guess is they are probably for doing max-w-index style
609 reductions, the INT carrying the index of the max/min and the
610 other type its actual value.
616 /* Find the size of long double image (not 'sizeof(long double)').
617 See comments in sizeofOneNamedTy.
619 static long sizeof_long_double_image ( void )
623 static long cached_result
= 0;
625 /* Hopefully we have it already. */
626 if (cached_result
!= 0) {
627 assert(cached_result
== 10 || cached_result
== 16 || cached_result
== 8);
628 return cached_result
;
631 /* No? Then we'll have to compute it. This isn't thread-safe but
632 it doesn't really matter since all races to compute it should
633 produce the same answer. */
636 for (i
= 0; i
< 64; i
++)
639 /* Write a value which isn't known at compile time and therefore
640 must come out of a register. If we just store a constant here,
641 some compilers write more data than a store from a machine
642 register would. Therefore we have to force a store from a
643 machine register by storing a value which isn't known at compile
644 time. Since getpid() will return a value < 1 million, turn it
645 into a zero by dividing by 1e+30. */
646 *(long double*)(&p
[16]) = (long double)(1.0e-30 * (double)getpid());
648 for (i
= 0; i
< 16; i
++) {
649 assert(p
[i
] == 0x55);
650 assert(p
[i
+48] == 0x55);
652 for (i
= 16; i
<= 48; i
++) {
660 cached_result
= i
- 16;
663 printf("sizeof_long_double_image: computed %d\n", (int)cached_result
);
665 assert(cached_result
== 10 || cached_result
== 16 || cached_result
== 8);
666 return cached_result
;
670 /*------------------------------------------------------------*/
671 /*--- Unpicking datatypes ---*/
672 /*------------------------------------------------------------*/
675 void walk_type_array ( void(*f
)(void*,long), char* base
,
676 MPI_Datatype ty
, long count
);
679 /* Walk over all fragments of the object of type 'ty' with base
680 address 'base', and apply 'f' to the start/length of each
681 contiguous fragment. */
683 void walk_type ( void(*f
)(void*,long), char* base
, MPI_Datatype ty
)
685 int r
, n_ints
, n_addrs
, n_dtys
, tycon
;
688 MPI_Aint
* addrs
= NULL
;
689 MPI_Datatype
* dtys
= NULL
;
691 /* Stuff for limiting how much complaining text it spews out */
692 static int complaints
= 3;
693 static int last_complained_about_tycon
= -987654321; /* presumably bogus */
696 printf("walk_type %p\n", (void*)(unsigned long)ty
);
698 r
= PMPI_Type_get_envelope( ty
, &n_ints
, &n_addrs
, &n_dtys
, &tycon
);
699 assert(r
== MPI_SUCCESS
);
701 /* Handle the base cases fast(er/ish). */
702 if (tycon
== MPI_COMBINER_NAMED
) {
703 long sz
= sizeofOneNamedTy(ty
);
708 /* Hmm. Perhaps it's a named struct? Unfortunately we can't
709 take them to bits so we have to do a really ugly hack, which
710 makes assumptions about how the MPI implementation has laid
711 out these types. At least Open MPI 1.0.1 appears to put
712 the 'val' field first. MPICH2 agrees.
714 if (ty
== MPI_2INT
) {
715 typedef struct { int val
; int loc
; } Ty
;
716 f(base
+ offsetof(Ty
,val
), sizeof(int));
717 f(base
+ offsetof(Ty
,loc
), sizeof(int));
720 if (ty
== MPI_LONG_INT
) {
721 typedef struct { long val
; int loc
; } Ty
;
722 f(base
+ offsetof(Ty
,val
), sizeof(long));
723 f(base
+ offsetof(Ty
,loc
), sizeof(int));
726 if (ty
== MPI_DOUBLE_INT
) {
727 typedef struct { double val
; int loc
; } Ty
;
728 f(base
+ offsetof(Ty
,val
), sizeof(double));
729 f(base
+ offsetof(Ty
,loc
), sizeof(int));
732 if (ty
== MPI_SHORT_INT
) {
733 typedef struct { short val
; int loc
; } Ty
;
734 f(base
+ offsetof(Ty
,val
), sizeof(short));
735 f(base
+ offsetof(Ty
,loc
), sizeof(int));
738 if (ty
== MPI_FLOAT_INT
) {
739 typedef struct { float val
; int loc
; } Ty
;
740 f(base
+ offsetof(Ty
,val
), sizeof(float));
741 f(base
+ offsetof(Ty
,loc
), sizeof(int));
744 if (ty
== MPI_LONG_DOUBLE_INT
) {
745 typedef struct { long double val
; int loc
; } Ty
;
746 f(base
+ offsetof(Ty
,val
), sizeof_long_double_image());
747 f(base
+ offsetof(Ty
,loc
), sizeof(int));
750 # if defined(MPI_LB) && defined(MPI_UB) && \
751 (!defined(OMPI_MAJOR_VERSION) || OMPI_MAJOR_VERSION < 3)
752 if (ty
== MPI_LB
|| ty
== MPI_UB
)
753 return; /* have zero size, so nothing needs to be done */
761 printf("tycon 0x%llx %d %d %d (ext %d)\n",
762 (unsigned long long int)tycon
,
763 n_ints
, n_addrs
, n_dtys
, (int)ex
);
766 /* Now safe to do MPI_Type_get_contents */
768 assert(n_addrs
>= 0);
772 ints
= malloc(n_ints
* sizeof(int));
776 addrs
= malloc(n_addrs
* sizeof(MPI_Aint
));
780 dtys
= malloc(n_dtys
* sizeof(MPI_Datatype
));
784 r
= PMPI_Type_get_contents( ty
, n_ints
, n_addrs
, n_dtys
,
786 assert(r
== MPI_SUCCESS
);
790 case MPI_COMBINER_CONTIGUOUS
:
791 assert(n_ints
== 1 && n_addrs
== 0 && n_dtys
== 1);
792 walk_type_array( f
, base
, dtys
[0], ints
[0] );
793 maybeFreeTy( &dtys
[0] );
796 case MPI_COMBINER_VECTOR
:
797 assert(n_ints
== 3 && n_addrs
== 0 && n_dtys
== 1);
798 ex
= extentOfTy(dtys
[0]);
800 printf("vector count %d x (bl %d stride %d)\n",
801 (int)ints
[0], (int)ints
[1], (int)ints
[2]);
802 for (i
= 0; i
< ints
[0]; i
++) {
803 walk_type_array( f
, base
+ i
* ints
[2]/*stride*/ * ex
,
804 dtys
[0], ints
[1]/*blocklength*/ );
806 maybeFreeTy( &dtys
[0] );
809 case MPI_COMBINER_HVECTOR
:
810 assert(n_ints
== 2 && n_addrs
== 1 && n_dtys
== 1);
811 ex
= extentOfTy(dtys
[0]);
813 printf("hvector count %d x (bl %d hstride %d)\n",
814 (int)ints
[0], (int)ints
[1], (int)addrs
[0]);
815 for (i
= 0; i
< ints
[0]; i
++) {
816 walk_type_array( f
, base
+ i
* addrs
[0]/*hstride*/,
817 dtys
[0], ints
[1]/*blocklength*/ );
819 maybeFreeTy( &dtys
[0] );
822 case MPI_COMBINER_INDEXED
:
823 assert(n_addrs
== 0 && n_dtys
== 1);
825 assert(n_ints
== 2 * ints
[0] + 1);
826 ex
= extentOfTy(dtys
[0]);
827 for (i
= 0; i
< ints
[0]; i
++) {
829 printf("indexed (elem %d) off %d copies %d\n",
830 (int)i
, ints
[i
+1+ints
[0]], ints
[i
+1] );
831 walk_type_array( f
, base
+ ex
* ints
[i
+1+ints
[0]],
832 dtys
[0], ints
[i
+1] );
834 maybeFreeTy( &dtys
[0] );
837 case MPI_COMBINER_HINDEXED
:
839 assert(n_ints
== ints
[0] + 1);
840 assert(n_addrs
== ints
[0] && n_dtys
== 1);
841 ex
= extentOfTy(dtys
[0]);
842 for (i
= 0; i
< ints
[0]; i
++) {
844 printf("hindexed (elem %d) hoff %d copies %d\n",
845 (int)i
, (int)addrs
[i
], ints
[i
+1] );
846 walk_type_array( f
, base
+ addrs
[i
],
847 dtys
[0], ints
[i
+1] );
849 maybeFreeTy( &dtys
[0] );
852 case MPI_COMBINER_STRUCT
:
853 assert(n_addrs
== n_ints
-1);
854 assert(n_dtys
== n_ints
-1);
856 assert(n_ints
== ints
[0] + 1);
857 for (i
= 0; i
< ints
[0]; i
++) {
859 printf("struct (elem %d limit %d) hoff %d copies %d\n",
860 (int)i
, (int)ints
[0], (int)addrs
[i
], (int)ints
[i
+1]);
861 walk_type_array( f
, base
+ addrs
[i
], dtys
[i
], (long)ints
[i
+1] );
862 maybeFreeTy( &dtys
[i
] );
872 if (ints
) free(ints
);
873 if (addrs
) free(addrs
);
874 if (dtys
) free(dtys
);
878 /* Complain, but limit the amount of complaining that can happen to
879 the first 3 different unhandled tycons that show up, so as to
880 avoid swamping users with thousands of duplicate messages. */
881 if (complaints
> 0 && tycon
!= last_complained_about_tycon
) {
883 last_complained_about_tycon
= tycon
;
884 if (tycon
== MPI_COMBINER_NAMED
) {
885 fprintf(stderr
, "%s %5d: walk_type: unhandled base type 0x%lx ",
886 preamble
, my_pid
, (long)ty
);
888 fprintf(stderr
, "\n");
890 fprintf(stderr
, "%s %5d: walk_type: unhandled combiner 0x%lx\n",
891 preamble
, my_pid
, (long)tycon
);
894 if (ints
) free(ints
);
895 if (addrs
) free(addrs
);
896 if (dtys
) free(dtys
);
897 if (opt_missing
>= 2)
898 barf("walk_type: unhandled combiner, strict checking selected");
902 /* Same as walk_type but apply 'f' to every element in an array of
903 'count' items starting at 'base'. The only purpose of pushing this
904 into a different routine is so it can attempt to optimise the case
905 where the array elements are contiguous and packed together without
908 void walk_type_array ( void(*f
)(void*,long), char* base
,
909 MPI_Datatype elemTy
, long count
)
913 assert(sizeof(unsigned long) == sizeof(char*));
915 /* First see if we can do this the fast way. */
916 ex
= sizeofOneNamedTy(elemTy
);
918 if ( /* ty is a primitive type with power-of-2 size */
919 (ex
== 8 || ex
== 4 || ex
== 2 || ex
== 1)
920 && /* base is suitably aligned for ty */
921 ( ((unsigned long)base
) & (ex
-1)) == 0) {
923 /* We're sure it's contiguous, so just paint/check it in one
925 if (0) printf("walk_type_array fast %ld of size %ld\n", count
, ex
);
926 f ( base
, count
* ex
);
930 /* Bad news. We have to futz with each element individually.
931 This could be very expensive.
933 Note: subtle. If ty is LONG_DOUBLE then the extent will be
934 12, so the following loop will jump along in steps of 12, but
935 the size painted by walk_type will be 10 since it uses
936 sizeofOneNamedTy to establish the size of base types. Which
937 is what we need to happen. */
938 ex
= extentOfTy(elemTy
);
939 if (0) printf("walk_type_array SLOW %ld of size %ld\n", count
, ex
);
940 for (i
= 0; i
< count
; i
++)
941 walk_type( f
, base
+ i
* ex
, elemTy
);
947 /* Hook so it's visible from outside (can be handy to dlopen/dlsym
949 void mpiwrap_walk_type_EXTERNALLY_VISIBLE
950 ( void(*f
)(void*,long), char* base
, MPI_Datatype ty
)
952 walk_type(f
, base
, ty
);
956 /*------------------------------------------------------------*/
957 /*--- Address-range helpers ---*/
958 /*------------------------------------------------------------*/
961 Do corresponding checks on memory areas defined using a
962 straightforward (start, length) description.
967 void check_mem_is_defined_untyped ( void* buffer
, long nbytes
)
970 VALGRIND_CHECK_MEM_IS_DEFINED(buffer
, nbytes
);
975 void check_mem_is_addressable_untyped ( void* buffer
, long nbytes
)
978 VALGRIND_CHECK_MEM_IS_ADDRESSABLE(buffer
, nbytes
);
983 void make_mem_defined_if_addressable_untyped ( void* buffer
, long nbytes
)
986 VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(buffer
, nbytes
);
991 void make_mem_defined_if_addressable_if_success_untyped ( int err
,
992 void* buffer
, long nbytes
)
994 if (err
== MPI_SUCCESS
&& nbytes
> 0) {
995 VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(buffer
, nbytes
);
1001 Do checks on memory areas defined using the MPI (buffer, count,
1006 /* Check that the specified area is both addressible and contains
1007 initialised data, and cause V to complain if not. */
1010 void check_mem_is_defined ( char* buffer
, long count
, MPI_Datatype datatype
)
1012 walk_type_array( check_mem_is_defined_untyped
, buffer
, datatype
, count
);
1016 /* Check that the specified area is addressible, and cause V to
1017 complain if not. Doesn't matter whether the data there is
1018 initialised or not. */
1021 void check_mem_is_addressable ( void *buffer
, long count
, MPI_Datatype datatype
)
1023 walk_type_array( check_mem_is_addressable_untyped
, buffer
, datatype
, count
);
1027 /* Set the specified area to 'defined for each byte which is
1028 addressible' state. */
1031 void make_mem_defined_if_addressable ( void *buffer
, int count
, MPI_Datatype datatype
)
1033 walk_type_array( make_mem_defined_if_addressable_untyped
,
1034 buffer
, datatype
, count
);
1039 make_mem_defined_if_addressable_if_success ( int err
, void *buffer
, int count
,
1040 MPI_Datatype datatype
)
1042 if (err
== MPI_SUCCESS
)
1043 make_mem_defined_if_addressable(buffer
, count
, datatype
);
1047 /*------------------------------------------------------------*/
1049 /*--- The wrappers proper. They are listed in the order ---*/
1050 /*--- in which they appear in "MPI: A Message-Passing ---*/
1051 /*--- Interface Standard, MPIF, Nov 15 2003" (the MPI 1.1 ---*/
1052 /*--- spec. All unimplemented wrappers are listed at the ---*/
1053 /*--- end of the file. The list of function names is ---*/
1054 /*--- taken from the headers of Open MPI svn r9191. ---*/
1055 /*--- Hopefully it is a complete list of all the MPI 2 ---*/
1056 /*--- functions. ---*/
1058 /*------------------------------------------------------------*/
1060 /* Handy abbreviation */
1061 #define WRAPPER_FOR(name) I_WRAP_FNNAME_U(name)
1063 /* Generates (conceptually) a wrapper which does nothing. In
1064 fact just generate no wrapper at all. */
1065 #define HAS_NO_WRAPPER(basename) /* */
1068 /*------------------------------------------------------------*/
1070 /*--- Sec 3.2, Blocking Send and Receive Operations ---*/
1072 /*------------------------------------------------------------*/
1074 /* --- {,B,S,R}Send --- */
1075 /* pre: rd: (buf,count,datatype) */
1077 int generic_Send(void *buf
, int count
, MPI_Datatype datatype
,
1078 int dest
, int tag
, MPI_Comm comm
)
1082 VALGRIND_GET_ORIG_FN(fn
);
1083 before("{,B,S,R}Send");
1084 check_mem_is_defined(buf
, count
, datatype
);
1085 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
1086 CALL_FN_W_6W(err
, fn
, buf
,count
,datatype
,dest
,tag
,comm
);
1087 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
1088 after("{,B,S,R}Send", err
);
1091 int WRAPPER_FOR(PMPI_Send
)(void *buf
, int count
, MPI_Datatype datatype
,
1092 int dest
, int tag
, MPI_Comm comm
) {
1093 return generic_Send(buf
,count
,datatype
, dest
,tag
,comm
);
1095 int WRAPPER_FOR(PMPI_Bsend
)(void *buf
, int count
, MPI_Datatype datatype
,
1096 int dest
, int tag
, MPI_Comm comm
) {
1097 return generic_Send(buf
,count
,datatype
, dest
,tag
,comm
);
1099 int WRAPPER_FOR(PMPI_Ssend
)(void *buf
, int count
, MPI_Datatype datatype
,
1100 int dest
, int tag
, MPI_Comm comm
) {
1101 return generic_Send(buf
,count
,datatype
, dest
,tag
,comm
);
1103 int WRAPPER_FOR(PMPI_Rsend
)(void *buf
, int count
, MPI_Datatype datatype
,
1104 int dest
, int tag
, MPI_Comm comm
) {
1105 return generic_Send(buf
,count
,datatype
, dest
,tag
,comm
);
1109 /* pre: must be writable: (buf,count,datatype)
1110 must be writable: status
1111 post: make readable: (buf,recv_count,datatype)
1112 where recv_count is determined from *status
1114 int WRAPPER_FOR(PMPI_Recv
)(void *buf
, int count
, MPI_Datatype datatype
,
1115 int source
, int tag
,
1116 MPI_Comm comm
, MPI_Status
*status
)
1119 int err
, recv_count
= 0;
1120 MPI_Status fake_status
;
1121 VALGRIND_GET_ORIG_FN(fn
);
1124 status
= &fake_status
;
1125 check_mem_is_addressable(buf
, count
, datatype
);
1126 check_mem_is_addressable_untyped(status
, sizeof(*status
));
1127 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
1128 CALL_FN_W_7W(err
, fn
, buf
,count
,datatype
,source
,tag
,comm
,status
);
1129 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
1130 make_mem_defined_if_addressable_if_success_untyped(err
, status
, sizeof(*status
));
1131 if (err
== MPI_SUCCESS
&& count_from_Status(&recv_count
,datatype
,status
)) {
1132 make_mem_defined_if_addressable(buf
, recv_count
, datatype
);
1138 /* --- Get_count --- */
1139 /* pre: must be readable: *status
1140 post: make defined: *count -- don't bother, libmpi will surely do this
1142 int WRAPPER_FOR(PMPI_Get_count
)(MPI_Status
* status
,
1143 MPI_Datatype ty
, int* count
)
1147 VALGRIND_GET_ORIG_FN(fn
);
1148 before("Get_count");
1149 check_mem_is_defined_untyped(status
, sizeof(*status
));
1150 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
1151 CALL_FN_W_WWW(err
, fn
, status
,ty
,count
);
1152 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
1153 after("Get_count", err
);
1158 /*------------------------------------------------------------*/
1160 /*--- Sec 3.7, Nonblocking communication ---*/
1162 /*------------------------------------------------------------*/
1164 /* Maintain a table that makes it possible for the wrappers to
1165 complete MPI_Irecv successfully.
1167 The issue is that MPI_Irecv states the recv buffer and returns
1168 immediately, giving a handle (MPI_Request) for the transaction.
1169 Later the user will have to poll for completion with MPI_Wait etc,
1170 and at that point these wrappers have to paint the recv buffer.
1171 But the recv buffer details are not presented to MPI_Wait - only
1172 the handle is. We therefore have to use a shadow table
1173 (sReqs{,_size,_used,_lock}) which associates uncompleted
1174 MPI_Requests with the corresponding buffer address/count/type.
1176 Only read requests are placed in the table, since there is no need
1177 to do any buffer painting following completion of an Isend - all
1178 the checks for that are done at the time Isend is called.
1180 Care has to be take to remove completed requests from the table.
1182 Access to the table is guarded by sReqs_lock so as to make it
1192 MPI_Datatype datatype
;
1196 static ShadowRequest
* sReqs
= NULL
;
1197 static int sReqs_size
= 0;
1198 static int sReqs_used
= 0;
1199 static pthread_mutex_t sReqs_lock
= PTHREAD_MUTEX_INITIALIZER
;
1201 #define LOCK_SREQS \
1202 do { int pr = pthread_mutex_lock(&sReqs_lock); \
1206 #define UNLOCK_SREQS \
1207 do { int pr = pthread_mutex_unlock(&sReqs_lock); \
1212 /* Ensure the sReqs expandable array has at least one free slot, by
1213 copying it into a larger one if necessary. NOTE: sReqs_lock is
1214 held throughout this procedure.*/
1215 static void ensure_sReq_space ( void )
1218 ShadowRequest
* sReqs2
;
1219 if (sReqs_used
== sReqs_size
) {
1220 sReqs_size
= sReqs_size
==0 ? 2 : 2*sReqs_size
;
1221 sReqs2
= malloc( sReqs_size
* sizeof(ShadowRequest
) );
1222 if (sReqs2
== NULL
) {
1224 barf("add_shadow_Request: malloc failed.\n");
1226 for (i
= 0; i
< sReqs_used
; i
++)
1227 sReqs2
[i
] = sReqs
[i
];
1232 assert(sReqs_used
< sReqs_size
);
1236 /* Find shadow info for 'request', or NULL if none. */
1239 ShadowRequest
* find_shadow_Request ( MPI_Request request
)
1241 ShadowRequest
* ret
= NULL
;
1244 for (i
= 0; i
< sReqs_used
; i
++) {
1245 if (sReqs
[i
].inUse
&& eq_MPI_Request(sReqs
[i
].key
,request
)) {
1255 /* Delete shadow info for 'request', if any. */
1257 static void delete_shadow_Request ( MPI_Request request
)
1261 for (i
= 0; i
< sReqs_used
; i
++) {
1262 if (sReqs
[i
].inUse
&& eq_MPI_Request(sReqs
[i
].key
,request
)) {
1263 sReqs
[i
].inUse
= False
;
1271 /* Add a shadow for 'request', overwriting any old binding for it. */
1274 void add_shadow_Request( MPI_Request request
,
1275 void* buf
, int count
,
1276 MPI_Datatype datatype
)
1280 assert(sReqs_used
>= 0);
1281 assert(sReqs_size
>= 0);
1282 assert(sReqs_used
<= sReqs_size
);
1283 if (sReqs
== NULL
) assert(sReqs_size
== 0);
1285 /* First of all see if we already have a binding for this key; if
1286 so just replace it, and have done. */
1287 for (i
= 0; i
< sReqs_used
; i
++) {
1288 if (sReqs
[i
].inUse
&& eq_MPI_Request(sReqs
[i
].key
,request
)) {
1295 /* Ok, we don't have it, so will have to add it. First search
1296 to see if there is an existing empty slot. */
1297 for (i
= 0; i
< sReqs_used
; i
++) {
1298 if (!sReqs
[i
].inUse
) {
1305 /* No empty slots. Allocate a new one. */
1307 ensure_sReq_space();
1308 assert(sReqs_used
< sReqs_size
);
1313 assert(ix
>= 0 && ix
< sReqs_used
);
1314 assert(sReqs_used
<= sReqs_size
);
1316 sReqs
[ix
].inUse
= True
;
1317 sReqs
[ix
].key
= request
;
1318 sReqs
[ix
].buf
= buf
;
1319 sReqs
[ix
].count
= count
;
1320 sReqs
[ix
].datatype
= datatype
;
1323 if (opt_verbosity
> 1)
1324 fprintf(stderr
, "%s %5d: sReq+ 0x%lx -> b/c/d %p/%d/0x%lx [slot %d]\n",
1325 preamble
, my_pid
, (unsigned long)request
,
1326 buf
, count
, (long)datatype
, ix
);
1330 MPI_Request
* clone_Request_array ( int count
, MPI_Request
* orig
)
1336 count
= 0; /* Hmm. Call Mulder and Scully. */
1337 copy
= malloc( count
* sizeof(MPI_Request
) );
1338 if (copy
== NULL
&& count
> 0) {
1340 barf("clone_Request_array: malloc failed");
1342 for (i
= 0; i
< count
; i
++)
1352 static void maybe_complete ( Bool error_in_status
,
1353 MPI_Request request_before
,
1354 MPI_Request request_after
,
1355 MPI_Status
* status
)
1358 ShadowRequest
* shadow
;
1359 /* How do we know if this is an Irecv request that has now
1360 finished successfully?
1362 request_before isn't MPI_REQUEST_NULL
1363 and request_before is found in the shadow table
1364 and request_after *is* MPI_REQUEST_NULL
1365 and (if error_in_status then status.MPI_ERROR is MPI_SUCCESS)
1367 (when error_in_status == False, then we expect not to get
1368 called at all if there was an error.)
1370 if (request_before
!= MPI_REQUEST_NULL
1371 && request_after
== MPI_REQUEST_NULL
1372 && (error_in_status
? status
->MPI_ERROR
== MPI_SUCCESS
: True
)
1373 && ( (shadow
=find_shadow_Request(request_before
)) != NULL
) ) {
1374 /* The Irecv detailed in 'shadow' completed. Paint the result
1375 buffer, and delete the entry. */
1376 if (count_from_Status(&recv_count
, shadow
->datatype
, status
)) {
1377 make_mem_defined_if_addressable(shadow
->buf
, recv_count
, shadow
->datatype
);
1378 if (opt_verbosity
> 1)
1379 fprintf(stderr
, "%s %5d: sReq- 0x%lx (completed)\n",
1380 preamble
, my_pid
, (unsigned long) request_before
);
1382 delete_shadow_Request(request_before
);
1388 /* rd: (buf,count,datatype) */
1391 int generic_Isend(void *buf
, int count
, MPI_Datatype datatype
,
1392 int dest
, int tag
, MPI_Comm comm
,
1393 MPI_Request
* request
)
1397 VALGRIND_GET_ORIG_FN(fn
);
1398 before("{,B,S,R}Isend");
1399 check_mem_is_defined(buf
, count
, datatype
);
1400 check_mem_is_addressable_untyped(request
, sizeof(*request
));
1401 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
1402 CALL_FN_W_7W(err
, fn
, buf
,count
,datatype
,dest
,tag
,comm
,request
);
1403 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
1404 make_mem_defined_if_addressable_if_success_untyped(err
, request
, sizeof(*request
));
1405 after("{,B,S,R}Isend", err
);
1408 int WRAPPER_FOR(PMPI_Isend
)(void *buf
, int count
, MPI_Datatype datatype
,
1409 int dest
, int tag
, MPI_Comm comm
,
1410 MPI_Request
* request
) {
1411 return generic_Isend(buf
,count
,datatype
, dest
,tag
,comm
, request
);
1413 int WRAPPER_FOR(PMPI_Ibsend
)(void *buf
, int count
, MPI_Datatype datatype
,
1414 int dest
, int tag
, MPI_Comm comm
,
1415 MPI_Request
* request
) {
1416 return generic_Isend(buf
,count
,datatype
, dest
,tag
,comm
, request
);
1418 int WRAPPER_FOR(PMPI_Issend
)(void *buf
, int count
, MPI_Datatype datatype
,
1419 int dest
, int tag
, MPI_Comm comm
,
1420 MPI_Request
* request
) {
1421 return generic_Isend(buf
,count
,datatype
, dest
,tag
,comm
, request
);
1423 int WRAPPER_FOR(PMPI_Irsend
)(void *buf
, int count
, MPI_Datatype datatype
,
1424 int dest
, int tag
, MPI_Comm comm
,
1425 MPI_Request
* request
) {
1426 return generic_Isend(buf
,count
,datatype
, dest
,tag
,comm
, request
);
1431 /* pre: must be writable: (buf,count,datatype), *request
1432 post: make readable *request
1433 add a request->(buf,count,ty) binding to the
1434 shadow request table.
1436 int WRAPPER_FOR(PMPI_Irecv
)( void* buf
, int count
, MPI_Datatype datatype
,
1437 int source
, int tag
, MPI_Comm comm
,
1438 MPI_Request
* request
)
1442 VALGRIND_GET_ORIG_FN(fn
);
1444 check_mem_is_addressable(buf
, count
, datatype
);
1445 check_mem_is_addressable_untyped(request
, sizeof(*request
));
1446 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
1447 CALL_FN_W_7W(err
, fn
, buf
,count
,datatype
,source
,tag
,comm
,request
);
1448 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
1449 if (err
== MPI_SUCCESS
) {
1450 make_mem_defined_if_addressable_untyped(request
, sizeof(*request
));
1451 add_shadow_Request( *request
, buf
,count
,datatype
);
1453 after("Irecv", err
);
1458 /* The MPI1 spec (imprecisely) defines 3 request states:
1459 - "null" if the request is MPI_REQUEST_NULL
1460 - "inactive" if not "null" and not associated with ongoing comms
1461 - "active" if not "null" and is associated with ongoing comms
1463 int WRAPPER_FOR(PMPI_Wait
)( MPI_Request
* request
,
1464 MPI_Status
* status
)
1466 MPI_Request request_before
;
1467 MPI_Status fake_status
;
1470 VALGRIND_GET_ORIG_FN(fn
);
1473 status
= &fake_status
;
1474 check_mem_is_addressable_untyped(status
, sizeof(MPI_Status
));
1475 check_mem_is_defined_untyped(request
, sizeof(MPI_Request
));
1476 request_before
= *request
;
1477 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
1478 CALL_FN_W_WW(err
, fn
, request
,status
);
1479 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
1480 if (err
== MPI_SUCCESS
) {
1481 maybe_complete(False
/*err in status?*/,
1482 request_before
, *request
, status
);
1483 make_mem_defined_if_addressable_untyped(status
, sizeof(MPI_Status
));
1489 /* --- Waitany --- */
1490 int WRAPPER_FOR(PMPI_Waitany
)( int count
,
1491 MPI_Request
* requests
,
1493 MPI_Status
* status
)
1495 MPI_Request
* requests_before
= NULL
;
1496 MPI_Status fake_status
;
1499 VALGRIND_GET_ORIG_FN(fn
);
1502 status
= &fake_status
;
1503 if (0) fprintf(stderr
, "Waitany: %d\n", count
);
1504 check_mem_is_addressable_untyped(index
, sizeof(int));
1505 check_mem_is_addressable_untyped(status
, sizeof(MPI_Status
));
1506 for (i
= 0; i
< count
; i
++) {
1507 check_mem_is_defined_untyped(&requests
[i
], sizeof(MPI_Request
));
1509 requests_before
= clone_Request_array( count
, requests
);
1510 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
1511 CALL_FN_W_WWWW(err
, fn
, count
,requests
,index
,status
);
1512 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
1513 if (err
== MPI_SUCCESS
&& *index
>= 0 && *index
< count
) {
1514 maybe_complete(False
/*err in status?*/,
1515 requests_before
[*index
], requests
[*index
], status
);
1516 make_mem_defined_if_addressable_untyped(status
, sizeof(MPI_Status
));
1518 if (requests_before
)
1519 free(requests_before
);
1520 after("Waitany", err
);
1524 /* --- Waitall --- */
1525 int WRAPPER_FOR(PMPI_Waitall
)( int count
,
1526 MPI_Request
* requests
,
1527 MPI_Status
* statuses
)
1529 MPI_Request
* requests_before
= NULL
;
1532 Bool free_sta
= False
;
1533 VALGRIND_GET_ORIG_FN(fn
);
1535 if (0) fprintf(stderr
, "Waitall: %d\n", count
);
1536 if (isMSI(statuses
)) {
1538 statuses
= malloc( (count
< 0 ? 0 : count
) * sizeof(MPI_Status
) );
1540 for (i
= 0; i
< count
; i
++) {
1541 check_mem_is_addressable_untyped(&statuses
[i
], sizeof(MPI_Status
));
1542 check_mem_is_defined_untyped(&requests
[i
], sizeof(MPI_Request
));
1544 requests_before
= clone_Request_array( count
, requests
);
1545 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
1546 CALL_FN_W_WWW(err
, fn
, count
,requests
,statuses
);
1547 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
1548 if (err
== MPI_SUCCESS
/*complete success*/
1549 || err
== MPI_ERR_IN_STATUS
/* partial success */) {
1550 Bool e_i_s
= err
== MPI_ERR_IN_STATUS
;
1551 for (i
= 0; i
< count
; i
++) {
1552 maybe_complete(e_i_s
, requests_before
[i
], requests
[i
],
1554 make_mem_defined_if_addressable_untyped(&statuses
[i
],
1555 sizeof(MPI_Status
));
1558 if (requests_before
)
1559 free(requests_before
);
1562 after("Waitall", err
);
1567 /* nonblocking version of Wait */
1568 int WRAPPER_FOR(PMPI_Test
)( MPI_Request
* request
, int* flag
,
1569 MPI_Status
* status
)
1571 MPI_Request request_before
;
1572 MPI_Status fake_status
;
1575 VALGRIND_GET_ORIG_FN(fn
);
1578 status
= &fake_status
;
1579 check_mem_is_addressable_untyped(status
, sizeof(MPI_Status
));
1580 check_mem_is_addressable_untyped(flag
, sizeof(int));
1581 check_mem_is_defined_untyped(request
, sizeof(MPI_Request
));
1582 request_before
= *request
;
1583 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
1584 CALL_FN_W_WWW(err
, fn
, request
,flag
,status
);
1585 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
1586 if (err
== MPI_SUCCESS
&& *flag
) {
1587 maybe_complete(False
/*err in status?*/,
1588 request_before
, *request
, status
);
1589 make_mem_defined_if_addressable_untyped(status
, sizeof(MPI_Status
));
1595 /* --- Testall --- */
1596 /* nonblocking version of Waitall */
1597 int WRAPPER_FOR(PMPI_Testall
)( int count
, MPI_Request
* requests
,
1598 int* flag
, MPI_Status
* statuses
)
1600 MPI_Request
* requests_before
= NULL
;
1603 Bool free_sta
= False
;
1604 VALGRIND_GET_ORIG_FN(fn
);
1606 if (0) fprintf(stderr
, "Testall: %d\n", count
);
1607 if (isMSI(statuses
)) {
1609 statuses
= malloc( (count
< 0 ? 0 : count
) * sizeof(MPI_Status
) );
1611 check_mem_is_addressable_untyped(flag
, sizeof(int));
1612 for (i
= 0; i
< count
; i
++) {
1613 check_mem_is_addressable_untyped(&statuses
[i
], sizeof(MPI_Status
));
1614 check_mem_is_defined_untyped(&requests
[i
], sizeof(MPI_Request
));
1616 requests_before
= clone_Request_array( count
, requests
);
1617 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
1618 CALL_FN_W_WWWW(err
, fn
, count
,requests
,flag
,statuses
);
1619 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
1620 /* Urk. Is the following "if (...)" really right? I don't know. */
1622 && (err
== MPI_SUCCESS
/*complete success*/
1623 || err
== MPI_ERR_IN_STATUS
/* partial success */)) {
1624 Bool e_i_s
= err
== MPI_ERR_IN_STATUS
;
1625 for (i
= 0; i
< count
; i
++) {
1626 maybe_complete(e_i_s
, requests_before
[i
], requests
[i
],
1628 make_mem_defined_if_addressable_untyped(&statuses
[i
],
1629 sizeof(MPI_Status
));
1632 if (requests_before
)
1633 free(requests_before
);
1636 after("Testall", err
);
1640 /* --- Iprobe --- */
1641 /* pre: must-be-writable: *flag, *status */
1642 /* post: make-readable *flag
1643 if *flag==True make-defined *status */
1644 int WRAPPER_FOR(PMPI_Iprobe
)(int source
, int tag
,
1646 int* flag
, MPI_Status
* status
)
1648 MPI_Status fake_status
;
1651 VALGRIND_GET_ORIG_FN(fn
);
1654 status
= &fake_status
;
1655 check_mem_is_addressable_untyped(flag
, sizeof(*flag
));
1656 check_mem_is_addressable_untyped(status
, sizeof(*status
));
1657 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
1658 CALL_FN_W_5W(err
, fn
, source
,tag
,comm
,flag
,status
);
1659 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
1660 if (err
== MPI_SUCCESS
) {
1661 make_mem_defined_if_addressable_untyped(flag
, sizeof(*flag
));
1663 make_mem_defined_if_addressable_untyped(status
, sizeof(*status
));
1665 after("Iprobe", err
);
1670 /* pre: must-be-writable *status */
1671 /* post: make-defined *status */
1672 int WRAPPER_FOR(PMPI_Probe
)(int source
, int tag
,
1673 MPI_Comm comm
, MPI_Status
* status
)
1675 MPI_Status fake_status
;
1678 VALGRIND_GET_ORIG_FN(fn
);
1681 status
= &fake_status
;
1682 check_mem_is_addressable_untyped(status
, sizeof(*status
));
1683 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
1684 CALL_FN_W_WWWW(err
, fn
, source
,tag
,comm
,status
);
1685 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
1686 make_mem_defined_if_addressable_if_success_untyped(err
, status
, sizeof(*status
));
1687 after("Probe", err
);
1691 /* --- Cancel --- */
1692 /* Wrapping PMPI_Cancel is interesting only to the extent that we need
1693 to be able to detect when a request should be removed from our
1694 shadow table due to cancellation. */
1695 int WRAPPER_FOR(PMPI_Cancel
)(MPI_Request
* request
)
1700 VALGRIND_GET_ORIG_FN(fn
);
1702 check_mem_is_addressable_untyped(request
, sizeof(*request
));
1704 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
1705 CALL_FN_W_W(err
, fn
, request
);
1706 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
1707 if (err
== MPI_SUCCESS
)
1708 delete_shadow_Request(tmp
);
1709 after("Cancel", err
);
1714 /*------------------------------------------------------------*/
1716 /*--- Sec 3.10, Send-receive ---*/
1718 /*------------------------------------------------------------*/
1720 /* --- Sendrecv --- */
1721 /* pre: must be readable: (sendbuf,sendcount,sendtype)
1722 must be writable: (recvbuf,recvcount,recvtype)
1723 post: make readable: (recvbuf,recvcount_actual,datatype)
1724 where recvcount_actual is determined from *status
1726 int WRAPPER_FOR(PMPI_Sendrecv
)(
1727 void *sendbuf
, int sendcount
, MPI_Datatype sendtype
,
1728 int dest
, int sendtag
,
1729 void *recvbuf
, int recvcount
, MPI_Datatype recvtype
,
1730 int source
, int recvtag
,
1731 MPI_Comm comm
, MPI_Status
*status
)
1733 MPI_Status fake_status
;
1735 int err
, recvcount_actual
= 0;
1736 VALGRIND_GET_ORIG_FN(fn
);
1739 status
= &fake_status
;
1740 check_mem_is_defined(sendbuf
, sendcount
, sendtype
);
1741 check_mem_is_addressable(recvbuf
, recvcount
, recvtype
);
1742 check_mem_is_addressable_untyped(status
, sizeof(*status
));
1743 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
1744 CALL_FN_W_12W(err
, fn
, sendbuf
,sendcount
,sendtype
,dest
,sendtag
,
1745 recvbuf
,recvcount
,recvtype
,source
,recvtag
,
1747 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
1748 make_mem_defined_if_addressable_if_success_untyped(err
, status
, sizeof(*status
));
1749 if (err
== MPI_SUCCESS
1750 && count_from_Status(&recvcount_actual
,recvtype
,status
)) {
1751 make_mem_defined_if_addressable(recvbuf
, recvcount_actual
, recvtype
);
1753 after("Sendrecv", err
);
1758 /*------------------------------------------------------------*/
1760 /*--- Sec 3.12, Derived datatypes ---*/
1762 /*------------------------------------------------------------*/
1764 /* --- Address --- */
1765 /* Does this have anything worth checking? */
1766 HAS_NO_WRAPPER(Address
)
1768 /* --- MPI 2 stuff --- */
1769 /* Type_extent, Type_get_contents and Type_get_envelope sometimes get
1770 used intensively by the type walker (walk_type). There's no reason
1771 why they couldn't be properly wrapped if needed, but doing so slows
1772 everything down, so don't bother until needed. */
1773 HAS_NO_WRAPPER(Type_extent
)
1774 HAS_NO_WRAPPER(Type_get_contents
)
1775 HAS_NO_WRAPPER(Type_get_envelope
)
1777 /* --- Type_commit --- */
1778 int WRAPPER_FOR(PMPI_Type_commit
)( MPI_Datatype
* ty
)
1782 VALGRIND_GET_ORIG_FN(fn
);
1783 before("Type_commit");
1784 check_mem_is_defined_untyped(ty
, sizeof(*ty
));
1785 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
1786 CALL_FN_W_W(err
, fn
, ty
);
1787 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
1788 after("Type_commit", err
);
1792 /* --- Type_free --- */
1793 int WRAPPER_FOR(PMPI_Type_free
)( MPI_Datatype
* ty
)
1797 VALGRIND_GET_ORIG_FN(fn
);
1798 before("Type_free");
1799 check_mem_is_defined_untyped(ty
, sizeof(*ty
));
1800 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
1801 CALL_FN_W_W(err
, fn
, ty
);
1802 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
1803 after("Type_free", err
);
1808 /*------------------------------------------------------------*/
1810 /*--- Sec 3.13, Pack and unpack ---*/
1812 /*------------------------------------------------------------*/
1815 /* pre: must be readable: position
1816 must be readable: (inbuf,incount,datatype)
1817 must be writable: outbuf[0 .. outsize-1]
1818 must be writable: outbuf[*position ..
1820 + however much space PMPI_Pack_size
1822 post: make readable: outbuf[old *position .. new *position]
1824 int WRAPPER_FOR(PMPI_Pack
)( void* inbuf
, int incount
, MPI_Datatype datatype
,
1825 void* outbuf
, int outsize
,
1826 int* position
, MPI_Comm comm
)
1830 int position_ORIG
= *position
;
1831 VALGRIND_GET_ORIG_FN(fn
);
1834 check_mem_is_defined_untyped(position
, sizeof(*position
));
1836 check_mem_is_defined(inbuf
, incount
, datatype
);
1837 /* check output area's stated bounds make sense */
1838 check_mem_is_addressable_untyped(outbuf
, outsize
);
1839 /* check output area's actual used size properly */
1840 err
= PMPI_Pack_size( incount
, datatype
, comm
, &szB
);
1841 if (err
== MPI_SUCCESS
&& szB
> 0) {
1842 check_mem_is_addressable_untyped(
1843 ((char*)outbuf
) + position_ORIG
, szB
1847 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
1848 CALL_FN_W_7W(err
, fn
, inbuf
,incount
,datatype
, outbuf
,outsize
,position
, comm
);
1849 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
1851 if (err
== MPI_SUCCESS
&& (*position
) > position_ORIG
) {
1853 make_mem_defined_if_addressable_untyped(
1854 ((char*)outbuf
) + position_ORIG
, *position
- position_ORIG
1861 /* --- Unpack --- */
1862 /* pre: must be readable: position
1863 must be writable: (outbuf,outcount,datatype)
1864 must be writable: outbuf[0 .. outsize-1]
1865 must be writable: outbuf[*position ..
1867 + however much space PMPI_Pack_size
1869 post: make readable: (outbuf,outcount,datatype)
1870 and also do a readability check of
1871 inbuf[old *position .. new *position]
1873 int WRAPPER_FOR(PMPI_Unpack
)( void* inbuf
, int insize
, int* position
,
1874 void* outbuf
, int outcount
, MPI_Datatype datatype
,
1879 int position_ORIG
= *position
;
1880 VALGRIND_GET_ORIG_FN(fn
);
1883 check_mem_is_defined_untyped(position
, sizeof(*position
));
1884 /* check output area is accessible */
1885 check_mem_is_addressable(outbuf
, outcount
, datatype
);
1886 /* check input area's stated bounds make sense */
1887 check_mem_is_addressable_untyped(inbuf
, insize
);
1888 /* check input area's actual used size properly */
1889 err
= PMPI_Pack_size( outcount
, datatype
, comm
, &szB
);
1890 if (err
== MPI_SUCCESS
&& szB
> 0) {
1891 check_mem_is_addressable_untyped(
1892 ((char*)inbuf
) + position_ORIG
, szB
1896 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
1897 CALL_FN_W_7W(err
, fn
, inbuf
,insize
,position
, outbuf
,outcount
,datatype
, comm
);
1898 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
1900 if (err
== MPI_SUCCESS
&& (*position
) > position_ORIG
) {
1901 /* recheck input more carefully */
1902 check_mem_is_defined_untyped(
1903 ((char*)inbuf
) + position_ORIG
, *position
- position_ORIG
1906 make_mem_defined_if_addressable( outbuf
, outcount
, datatype
);
1908 after("Unpack", err
);
1913 /*------------------------------------------------------------*/
1915 /*--- Sec 4.4, Broadcast ---*/
1917 /*------------------------------------------------------------*/
1920 /* pre: must-be-readable (buffer,count,datatype) for rank==root
1921 must-be-writable (buffer,count,datatype) for rank!=root
1922 post: make-readable (buffer,count,datatype) for all
1924 Resulting behaviour is: if root sends uninitialised stuff, then
1925 V complains, but then all ranks, including itself, see the buffer
1926 as initialised after that.
1928 int WRAPPER_FOR(PMPI_Bcast
)(void *buffer
, int count
,
1929 MPI_Datatype datatype
,
1930 int root
, MPI_Comm comm
)
1935 VALGRIND_GET_ORIG_FN(fn
);
1937 i_am_sender
= root
== comm_rank(comm
);
1939 check_mem_is_defined(buffer
, count
, datatype
);
1941 check_mem_is_addressable(buffer
, count
, datatype
);
1943 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
1944 CALL_FN_W_5W(err
, fn
, buffer
,count
,datatype
,root
,comm
);
1945 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
1946 make_mem_defined_if_addressable_if_success(err
, buffer
, count
, datatype
);
1947 after("Bcast", err
);
1952 /*------------------------------------------------------------*/
1954 /*--- Sec 4.5, Gather ---*/
1956 /*------------------------------------------------------------*/
1958 /* --- Gather --- */
1959 /* JRS 20060217: I don't really understand this. Each process is
1960 going to send sendcount items of type sendtype to the root. So
1961 the root is going to receive comm_size*sendcount items of type
1962 sendtype (right?) So why specify recvcount and recvtype?
1964 Anyway, assuming the MPI Spec is correct (seems likely :-) we have:
1966 pre: (all) must be readable: (sendbuf,sendcount,sendtype)
1967 (root only): must be writable: (recvbuf,recvcount * comm_size,recvtype)
1968 post: (root only): make readable: (recvbuf,recvcount * comm_size,recvtype)
1970 int WRAPPER_FOR(PMPI_Gather
)(
1971 void *sendbuf
, int sendcount
, MPI_Datatype sendtype
,
1972 void *recvbuf
, int recvcount
, MPI_Datatype recvtype
,
1973 int root
, MPI_Comm comm
)
1977 VALGRIND_GET_ORIG_FN(fn
);
1979 me
= comm_rank(comm
);
1980 sz
= comm_size(comm
);
1981 check_mem_is_defined(sendbuf
, sendcount
, sendtype
);
1983 check_mem_is_addressable(recvbuf
, recvcount
* sz
, recvtype
);
1984 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
1985 CALL_FN_W_8W(err
, fn
, sendbuf
,sendcount
,sendtype
,
1986 recvbuf
,recvcount
,recvtype
,
1988 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
1990 make_mem_defined_if_addressable_if_success(err
, recvbuf
, recvcount
* sz
, recvtype
);
1991 after("Gather", err
);
1996 /*------------------------------------------------------------*/
1998 /*--- Sec 4.6, Scatter ---*/
2000 /*------------------------------------------------------------*/
2002 /* pre: (root only): must be readable: (sendbuf,sendcount * comm_size,sendtype)
2003 (all): must be writable: (recvbuf,recvbuf,recvtype)
2004 post: (all): make defined: (recvbuf,recvbuf,recvtype)
2006 int WRAPPER_FOR(PMPI_Scatter
)(
2007 void* sendbuf
, int sendcount
, MPI_Datatype sendtype
,
2008 void* recvbuf
, int recvcount
, MPI_Datatype recvtype
,
2009 int root
, MPI_Comm comm
)
2013 VALGRIND_GET_ORIG_FN(fn
);
2015 me
= comm_rank(comm
);
2016 sz
= comm_size(comm
);
2017 check_mem_is_addressable(recvbuf
, recvcount
, recvtype
);
2019 check_mem_is_defined(sendbuf
, sendcount
* sz
, sendtype
);
2020 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
2021 CALL_FN_W_8W(err
, fn
, sendbuf
,sendcount
,sendtype
,
2022 recvbuf
,recvcount
,recvtype
,
2024 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
2025 make_mem_defined_if_addressable_if_success(err
, recvbuf
, recvcount
, recvtype
);
2026 after("Scatter", err
);
2031 /*------------------------------------------------------------*/
2033 /*--- Sec 4.8, All-to-All Scatter/Gather ---*/
2035 /*------------------------------------------------------------*/
2037 /* pre: (all) must be readable: (sendbuf,sendcount * comm_size,sendtype)
2038 (all) must be writable: (recvbuf,recvcount * comm_size,recvtype)
2039 post: (all) make defined: (recvbuf,recvcount * comm_size,recvtype)
2041 int WRAPPER_FOR(PMPI_Alltoall
)(
2042 void* sendbuf
, int sendcount
, MPI_Datatype sendtype
,
2043 void* recvbuf
, int recvcount
, MPI_Datatype recvtype
,
2048 VALGRIND_GET_ORIG_FN(fn
);
2050 sz
= comm_size(comm
);
2051 check_mem_is_defined(sendbuf
, sendcount
* sz
, sendtype
);
2052 check_mem_is_addressable(recvbuf
, recvcount
* sz
, recvtype
);
2053 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
2054 CALL_FN_W_7W(err
, fn
, sendbuf
,sendcount
,sendtype
,
2055 recvbuf
,recvcount
,recvtype
,
2057 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
2058 make_mem_defined_if_addressable_if_success(err
, recvbuf
, recvcount
* sz
, recvtype
);
2059 after("Alltoall", err
);
2064 /*------------------------------------------------------------*/
2066 /*--- Sec 4.9, Global Reduction Operations ---*/
2068 /*------------------------------------------------------------*/
2070 /* --- Reduce --- */
2071 /* rd: (sendbuf,count,datatype) for all
2072 wr: (recvbuf,count,datatype) but only for rank == root
2074 int WRAPPER_FOR(PMPI_Reduce
)(void *sendbuf
, void *recvbuf
,
2076 MPI_Datatype datatype
, MPI_Op op
,
2077 int root
, MPI_Comm comm
)
2082 VALGRIND_GET_ORIG_FN(fn
);
2084 i_am_root
= root
== comm_rank(comm
);
2085 check_mem_is_defined(sendbuf
, count
, datatype
);
2087 check_mem_is_addressable(recvbuf
, count
, datatype
);
2088 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
2089 CALL_FN_W_7W(err
, fn
, sendbuf
,recvbuf
,count
,datatype
,op
,root
,comm
);
2090 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
2092 make_mem_defined_if_addressable_if_success(err
, recvbuf
, count
, datatype
);
2093 after("Reduce", err
);
2098 /* --- Allreduce --- */
2099 /* rd: (sendbuf,count,datatype) for all
2100 wr: (recvbuf,count,datatype) for all
2102 int WRAPPER_FOR(PMPI_Allreduce
)(void *sendbuf
, void *recvbuf
,
2104 MPI_Datatype datatype
, MPI_Op op
,
2109 VALGRIND_GET_ORIG_FN(fn
);
2110 before("Allreduce");
2111 check_mem_is_defined(sendbuf
, count
, datatype
);
2112 check_mem_is_addressable(recvbuf
, count
, datatype
);
2113 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
2114 CALL_FN_W_6W(err
, fn
, sendbuf
,recvbuf
,count
,datatype
,op
,comm
);
2115 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
2116 make_mem_defined_if_addressable_if_success(err
, recvbuf
, count
, datatype
);
2117 after("Allreduce", err
);
2122 /* --- Op_create --- */
2123 /* This is a bit dubious. I suppose it takes 'function' and
2124 writes something at *op, but who knows what an MPI_Op is?
2125 Can we safely do 'sizeof' on it? */
2126 int WRAPPER_FOR(PMPI_Op_create
)( MPI_User_function
* function
,
2132 VALGRIND_GET_ORIG_FN(fn
);
2133 before("Op_create");
2134 check_mem_is_addressable_untyped(op
, sizeof(*op
));
2135 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
2136 CALL_FN_W_WWW(err
, fn
, function
,commute
,op
);
2137 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
2138 make_mem_defined_if_addressable_if_success_untyped(err
, op
, sizeof(*op
));
2139 after("Op_create", err
);
2144 /*------------------------------------------------------------*/
2146 /*--- Sec 5.4, Communicator management ---*/
2148 /*------------------------------------------------------------*/
2150 /* Hardly seems worth wrapping Comm_rank and Comm_size, but
2151 since it's done now .. */
2153 /* --- Comm_create --- */
2154 /* Let normal memcheck tracking handle this. */
2155 int WRAPPER_FOR(PMPI_Comm_create
)(MPI_Comm comm
, MPI_Group group
,
2160 VALGRIND_GET_ORIG_FN(fn
);
2161 before("Comm_create");
2162 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
2163 CALL_FN_W_WWW(err
, fn
, comm
,group
,newcomm
);
2164 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
2165 after("Comm_create", err
);
2169 /* --- Comm_dup --- */
2170 /* Let normal memcheck tracking handle this. */
2171 int WRAPPER_FOR(PMPI_Comm_dup
)(MPI_Comm comm
, MPI_Comm
* newcomm
)
2175 VALGRIND_GET_ORIG_FN(fn
);
2177 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
2178 CALL_FN_W_WW(err
, fn
, comm
,newcomm
);
2179 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
2180 after("Comm_dup", err
);
2184 /* --- Comm_free --- */
2185 /* Let normal memcheck tracking handle this. */
2186 int WRAPPER_FOR(PMPI_Comm_free
)(MPI_Comm
* comm
)
2190 VALGRIND_GET_ORIG_FN(fn
);
2191 before("Comm_free");
2192 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
2193 CALL_FN_W_W(err
, fn
, comm
);
2194 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
2195 after("Comm_free", err
);
2199 /* --- Comm_rank --- */
2200 /* wr: (rank, sizeof(*rank)) */
2201 int WRAPPER_FOR(PMPI_Comm_rank
)(MPI_Comm comm
, int *rank
)
2205 VALGRIND_GET_ORIG_FN(fn
);
2206 before("Comm_rank");
2207 check_mem_is_addressable_untyped(rank
, sizeof(*rank
));
2208 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
2209 CALL_FN_W_WW(err
, fn
, comm
,rank
);
2210 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
2211 make_mem_defined_if_addressable_if_success_untyped(err
, rank
, sizeof(*rank
));
2212 after("Comm_rank", err
);
2216 /* --- Comm_size --- */
2217 /* wr: (size, sizeof(*size)) */
2218 int WRAPPER_FOR(PMPI_Comm_size
)(MPI_Comm comm
, int *size
)
2222 VALGRIND_GET_ORIG_FN(fn
);
2223 before("Comm_size");
2224 check_mem_is_addressable_untyped(size
, sizeof(*size
));
2225 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
2226 CALL_FN_W_WW(err
, fn
, comm
,size
);
2227 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
2228 make_mem_defined_if_addressable_if_success_untyped(err
, size
, sizeof(*size
));
2229 after("Comm_size", err
);
2234 /*------------------------------------------------------------*/
2236 /*--- Sec 5.7, Caching ---*/
2238 /*------------------------------------------------------------*/
2241 /*------------------------------------------------------------*/
2243 /*--- Sec 7.3, Error codes and classes ---*/
2245 /*------------------------------------------------------------*/
2247 /* --- Error_string --- */
2248 int WRAPPER_FOR(PMPI_Error_string
)( int errorcode
, char* string
,
2253 VALGRIND_GET_ORIG_FN(fn
);
2254 before("Error_string");
2255 check_mem_is_addressable_untyped(resultlen
, sizeof(int));
2256 check_mem_is_addressable_untyped(string
, MPI_MAX_ERROR_STRING
);
2257 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
2258 CALL_FN_W_WWW(err
, fn
, errorcode
,string
,resultlen
);
2259 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
2260 /* Don't bother to paint the result; we assume the real function
2261 will have filled it with defined characters :-) */
2262 after("Error_string", err
);
2267 /*------------------------------------------------------------*/
2269 /*--- Sec 7.5, Startup ---*/
2271 /*------------------------------------------------------------*/
2274 /* rd: *argc, *argv[0 .. *argc-1] */
2275 long WRAPPER_FOR(PMPI_Init
)(int *argc
, char ***argv
)
2279 VALGRIND_GET_ORIG_FN(fn
);
2282 check_mem_is_defined_untyped(argc
, sizeof(*argc
));
2285 check_mem_is_defined_untyped(*argv
, *argc
* sizeof(**argv
));
2287 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
2288 CALL_FN_W_WW(err
, fn
, argc
,argv
);
2289 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
2292 return (long)(void*)&mpiwrap_walk_type_EXTERNALLY_VISIBLE
;
2297 /* --- Initialized --- */
2298 int WRAPPER_FOR(PMPI_Initialized
)(int* flag
)
2302 VALGRIND_GET_ORIG_FN(fn
);
2303 before("Initialized");
2304 check_mem_is_addressable_untyped(flag
, sizeof(int));
2305 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
2306 CALL_FN_W_W(err
, fn
, flag
);
2307 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
2308 make_mem_defined_if_addressable_if_success_untyped(err
, flag
, sizeof(int));
2309 after("Initialized", err
);
2313 /* --- Finalize --- */
2314 int WRAPPER_FOR(PMPI_Finalize
)(void)
2318 VALGRIND_GET_ORIG_FN(fn
);
2320 if (cONFIG_DER
) VALGRIND_DISABLE_ERROR_REPORTING
;
2321 CALL_FN_W_v(err
, fn
);
2322 if (cONFIG_DER
) VALGRIND_ENABLE_ERROR_REPORTING
;
2323 after("Finalize", err
);
2328 /*------------------------------------------------------------*/
2330 /*--- Default wrappers for all remaining functions ---*/
2332 /*------------------------------------------------------------*/
2334 /* Boilerplate for default wrappers. */
2335 #define DEFAULT_WRAPPER_PREAMBLE(basename) \
2338 static int complaints = 1; \
2339 VALGRIND_GET_ORIG_FN(fn); \
2340 before(#basename); \
2341 if (opt_missing >= 2) { \
2342 barf("no wrapper for PMPI_" #basename \
2343 ",\n\t\t\t and you have " \
2344 "requested strict checking"); \
2346 if (opt_missing == 1 && complaints > 0) { \
2347 fprintf(stderr, "%s %5d: warning: no wrapper " \
2348 "for PMPI_" #basename "\n", \
2349 preamble, my_pid); \
2353 #define DEFAULT_WRAPPER_W_0W(basename) \
2354 UWord WRAPPER_FOR(PMPI_##basename)( void ) \
2356 DEFAULT_WRAPPER_PREAMBLE(basename) \
2357 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2358 CALL_FN_W_v(res, fn); \
2359 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2363 #define DEFAULT_WRAPPER_W_1W(basename) \
2364 UWord WRAPPER_FOR(PMPI_##basename)( UWord a1 ) \
2366 DEFAULT_WRAPPER_PREAMBLE(basename) \
2367 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2368 CALL_FN_W_W(res, fn, a1); \
2369 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2373 #define DEFAULT_WRAPPER_W_2W(basename) \
2374 UWord WRAPPER_FOR(PMPI_##basename)( UWord a1, UWord a2 ) \
2376 DEFAULT_WRAPPER_PREAMBLE(basename) \
2377 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2378 CALL_FN_W_WW(res, fn, a1,a2); \
2379 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2383 #define DEFAULT_WRAPPER_W_3W(basename) \
2384 UWord WRAPPER_FOR(PMPI_##basename) \
2385 ( UWord a1, UWord a2, UWord a3 ) \
2387 DEFAULT_WRAPPER_PREAMBLE(basename) \
2388 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2389 CALL_FN_W_WWW(res, fn, a1,a2,a3); \
2390 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2394 #define DEFAULT_WRAPPER_W_4W(basename) \
2395 UWord WRAPPER_FOR(PMPI_##basename) \
2396 ( UWord a1, UWord a2, UWord a3, UWord a4 ) \
2398 DEFAULT_WRAPPER_PREAMBLE(basename) \
2399 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2400 CALL_FN_W_WWWW(res, fn, a1,a2,a3,a4); \
2401 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2405 #define DEFAULT_WRAPPER_W_5W(basename) \
2406 UWord WRAPPER_FOR(PMPI_##basename) \
2407 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5 ) \
2409 DEFAULT_WRAPPER_PREAMBLE(basename) \
2410 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2411 CALL_FN_W_5W(res, fn, a1,a2,a3,a4,a5); \
2412 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2416 #define DEFAULT_WRAPPER_W_6W(basename) \
2417 UWord WRAPPER_FOR(PMPI_##basename) \
2418 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2421 DEFAULT_WRAPPER_PREAMBLE(basename) \
2422 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2423 CALL_FN_W_6W(res, fn, a1,a2,a3,a4,a5,a6); \
2424 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2428 #define DEFAULT_WRAPPER_W_7W(basename) \
2429 UWord WRAPPER_FOR(PMPI_##basename) \
2430 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2431 UWord a6, UWord a7 ) \
2433 DEFAULT_WRAPPER_PREAMBLE(basename) \
2434 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2435 CALL_FN_W_7W(res, fn, a1,a2,a3,a4,a5,a6,a7); \
2436 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2440 #define DEFAULT_WRAPPER_W_8W(basename) \
2441 UWord WRAPPER_FOR(PMPI_##basename) \
2442 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2443 UWord a6, UWord a7, UWord a8 ) \
2445 DEFAULT_WRAPPER_PREAMBLE(basename) \
2446 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2447 CALL_FN_W_8W(res, fn, a1,a2,a3,a4,a5,a6,a7,a8); \
2448 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2452 #define DEFAULT_WRAPPER_W_9W(basename) \
2453 UWord WRAPPER_FOR(PMPI_##basename) \
2454 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2455 UWord a6, UWord a7, UWord a8, UWord a9 ) \
2457 DEFAULT_WRAPPER_PREAMBLE(basename) \
2458 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2459 CALL_FN_W_9W(res, fn, a1,a2,a3,a4,a5,a6,a7,a8,a9); \
2460 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2464 #define DEFAULT_WRAPPER_W_10W(basename) \
2465 UWord WRAPPER_FOR(PMPI_##basename) \
2466 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2467 UWord a6, UWord a7, UWord a8, UWord a9, UWord a10 ) \
2469 DEFAULT_WRAPPER_PREAMBLE(basename) \
2470 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2471 CALL_FN_W_10W(res, fn, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10); \
2472 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2476 #define DEFAULT_WRAPPER_W_12W(basename) \
2477 UWord WRAPPER_FOR(PMPI_##basename) \
2478 ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, \
2479 UWord a6, UWord a7, UWord a8, UWord a9, UWord a10, \
2480 UWord a11, UWord a12 ) \
2482 DEFAULT_WRAPPER_PREAMBLE(basename) \
2483 if (cONFIG_DER) VALGRIND_DISABLE_ERROR_REPORTING; \
2484 CALL_FN_W_12W(res, fn, a1,a2,a3,a4,a5,a6, \
2485 a7,a8,a9,a10,a11,a12); \
2486 if (cONFIG_DER) VALGRIND_ENABLE_ERROR_REPORTING; \
2491 /* Canned summary of MPI-1.1/MPI-2 entry points, as derived from mpi.h
2492 from Open MPI svn rev 9191 (somewhere between Open MPI versions
2493 1.0.1 and 1.1.0). */
2495 /* If a function is commented out in this list, it's because it has a
2496 proper wrapper written elsewhere (above here). */
2498 DEFAULT_WRAPPER_W_2W(Abort
)
2499 DEFAULT_WRAPPER_W_9W(Accumulate
)
2500 DEFAULT_WRAPPER_W_1W(Add_error_class
)
2501 DEFAULT_WRAPPER_W_2W(Add_error_code
)
2502 DEFAULT_WRAPPER_W_2W(Add_error_string
)
2503 /* DEFAULT_WRAPPER_W_2W(Address) */
2504 DEFAULT_WRAPPER_W_7W(Allgather
)
2505 DEFAULT_WRAPPER_W_8W(Allgatherv
)
2506 DEFAULT_WRAPPER_W_3W(Alloc_mem
)
2507 /* DEFAULT_WRAPPER_W_6W(Allreduce) */
2508 /* DEFAULT_WRAPPER_W_7W(Alltoall) */
2509 DEFAULT_WRAPPER_W_9W(Alltoallv
)
2510 DEFAULT_WRAPPER_W_9W(Alltoallw
)
2511 DEFAULT_WRAPPER_W_2W(Attr_delete
)
2512 DEFAULT_WRAPPER_W_4W(Attr_get
)
2513 DEFAULT_WRAPPER_W_3W(Attr_put
)
2514 DEFAULT_WRAPPER_W_1W(Barrier
)
2515 /* DEFAULT_WRAPPER_W_5W(Bcast) */
2516 /* DEFAULT_WRAPPER_W_6W(Bsend) */
2517 DEFAULT_WRAPPER_W_7W(Bsend_init
)
2518 DEFAULT_WRAPPER_W_2W(Buffer_attach
)
2519 DEFAULT_WRAPPER_W_2W(Buffer_detach
)
2520 /* DEFAULT_WRAPPER_W_1W(Cancel) */
2521 DEFAULT_WRAPPER_W_4W(Cart_coords
)
2522 DEFAULT_WRAPPER_W_6W(Cart_create
)
2523 DEFAULT_WRAPPER_W_5W(Cart_get
)
2524 DEFAULT_WRAPPER_W_5W(Cart_map
)
2525 DEFAULT_WRAPPER_W_3W(Cart_rank
)
2526 DEFAULT_WRAPPER_W_5W(Cart_shift
)
2527 DEFAULT_WRAPPER_W_3W(Cart_sub
)
2528 DEFAULT_WRAPPER_W_2W(Cartdim_get
)
2529 DEFAULT_WRAPPER_W_1W(Close_port
)
2530 DEFAULT_WRAPPER_W_5W(Comm_accept
)
2531 DEFAULT_WRAPPER_W_1W(Comm_c2f
)
2532 DEFAULT_WRAPPER_W_2W(Comm_call_errhandler
)
2533 DEFAULT_WRAPPER_W_3W(Comm_compare
)
2534 DEFAULT_WRAPPER_W_5W(Comm_connect
)
2535 DEFAULT_WRAPPER_W_2W(Comm_create_errhandler
)
2536 DEFAULT_WRAPPER_W_4W(Comm_create_keyval
)
2537 /* DEFAULT_WRAPPER_W_3W(Comm_create) */
2538 DEFAULT_WRAPPER_W_2W(Comm_delete_attr
)
2539 DEFAULT_WRAPPER_W_1W(Comm_disconnect
)
2540 /* DEFAULT_WRAPPER_W_2W(Comm_dup) */
2541 DEFAULT_WRAPPER_W_1W(Comm_f2c
)
2542 DEFAULT_WRAPPER_W_1W(Comm_free_keyval
)
2543 /* DEFAULT_WRAPPER_W_1W(Comm_free) */
2544 DEFAULT_WRAPPER_W_4W(Comm_get_attr
)
2545 DEFAULT_WRAPPER_W_2W(Comm_get_errhandler
)
2546 DEFAULT_WRAPPER_W_3W(Comm_get_name
)
2547 DEFAULT_WRAPPER_W_1W(Comm_get_parent
)
2548 DEFAULT_WRAPPER_W_2W(Comm_group
)
2549 DEFAULT_WRAPPER_W_2W(Comm_join
)
2550 /* DEFAULT_WRAPPER_W_2W(Comm_rank) */
2551 DEFAULT_WRAPPER_W_2W(Comm_remote_group
)
2552 DEFAULT_WRAPPER_W_2W(Comm_remote_size
)
2553 DEFAULT_WRAPPER_W_3W(Comm_set_attr
)
2554 DEFAULT_WRAPPER_W_2W(Comm_set_errhandler
)
2555 DEFAULT_WRAPPER_W_2W(Comm_set_name
)
2556 /* DEFAULT_WRAPPER_W_2W(Comm_size) */
2557 DEFAULT_WRAPPER_W_8W(Comm_spawn
)
2558 DEFAULT_WRAPPER_W_9W(Comm_spawn_multiple
)
2559 DEFAULT_WRAPPER_W_4W(Comm_split
)
2560 DEFAULT_WRAPPER_W_2W(Comm_test_inter
)
2561 DEFAULT_WRAPPER_W_3W(Dims_create
)
2562 DEFAULT_WRAPPER_W_1W(Errhandler_c2f
)
2563 DEFAULT_WRAPPER_W_2W(Errhandler_create
)
2564 DEFAULT_WRAPPER_W_1W(Errhandler_f2c
)
2565 DEFAULT_WRAPPER_W_1W(Errhandler_free
)
2566 DEFAULT_WRAPPER_W_2W(Errhandler_get
)
2567 DEFAULT_WRAPPER_W_2W(Errhandler_set
)
2568 DEFAULT_WRAPPER_W_2W(Error_class
)
2569 /* DEFAULT_WRAPPER_W_3W(Error_string) */
2570 DEFAULT_WRAPPER_W_6W(Exscan
)
2571 DEFAULT_WRAPPER_W_1W(File_c2f
)
2572 DEFAULT_WRAPPER_W_1W(File_f2c
)
2573 DEFAULT_WRAPPER_W_2W(File_call_errhandler
)
2574 DEFAULT_WRAPPER_W_2W(File_create_errhandler
)
2575 DEFAULT_WRAPPER_W_2W(File_set_errhandler
)
2576 DEFAULT_WRAPPER_W_2W(File_get_errhandler
)
2577 DEFAULT_WRAPPER_W_5W(File_open
)
2578 DEFAULT_WRAPPER_W_1W(File_close
)
2579 DEFAULT_WRAPPER_W_2W(File_delete
)
2580 DEFAULT_WRAPPER_W_2W(File_set_size
)
2581 DEFAULT_WRAPPER_W_2W(File_preallocate
)
2582 DEFAULT_WRAPPER_W_2W(File_get_size
)
2583 DEFAULT_WRAPPER_W_2W(File_get_group
)
2584 DEFAULT_WRAPPER_W_2W(File_get_amode
)
2585 DEFAULT_WRAPPER_W_2W(File_set_info
)
2586 DEFAULT_WRAPPER_W_2W(File_get_info
)
2587 DEFAULT_WRAPPER_W_6W(File_set_view
)
2588 DEFAULT_WRAPPER_W_5W(File_get_view
)
2589 DEFAULT_WRAPPER_W_6W(File_read_at
)
2590 DEFAULT_WRAPPER_W_6W(File_read_at_all
)
2591 DEFAULT_WRAPPER_W_6W(File_write_at
)
2592 DEFAULT_WRAPPER_W_6W(File_write_at_all
)
2593 DEFAULT_WRAPPER_W_6W(File_iread_at
)
2594 DEFAULT_WRAPPER_W_6W(File_iwrite_at
)
2595 DEFAULT_WRAPPER_W_5W(File_read
)
2596 DEFAULT_WRAPPER_W_5W(File_read_all
)
2597 DEFAULT_WRAPPER_W_5W(File_write
)
2598 DEFAULT_WRAPPER_W_5W(File_write_all
)
2599 DEFAULT_WRAPPER_W_5W(File_iread
)
2600 DEFAULT_WRAPPER_W_5W(File_iwrite
)
2601 DEFAULT_WRAPPER_W_3W(File_seek
)
2602 DEFAULT_WRAPPER_W_2W(File_get_position
)
2603 DEFAULT_WRAPPER_W_3W(File_get_byte_offset
)
2604 DEFAULT_WRAPPER_W_5W(File_read_shared
)
2605 DEFAULT_WRAPPER_W_5W(File_write_shared
)
2606 DEFAULT_WRAPPER_W_5W(File_iread_shared
)
2607 DEFAULT_WRAPPER_W_5W(File_iwrite_shared
)
2608 DEFAULT_WRAPPER_W_5W(File_read_ordered
)
2609 DEFAULT_WRAPPER_W_5W(File_write_ordered
)
2610 DEFAULT_WRAPPER_W_3W(File_seek_shared
)
2611 DEFAULT_WRAPPER_W_2W(File_get_position_shared
)
2612 DEFAULT_WRAPPER_W_5W(File_read_at_all_begin
)
2613 DEFAULT_WRAPPER_W_3W(File_read_at_all_end
)
2614 DEFAULT_WRAPPER_W_5W(File_write_at_all_begin
)
2615 DEFAULT_WRAPPER_W_3W(File_write_at_all_end
)
2616 DEFAULT_WRAPPER_W_4W(File_read_all_begin
)
2617 DEFAULT_WRAPPER_W_3W(File_read_all_end
)
2618 DEFAULT_WRAPPER_W_4W(File_write_all_begin
)
2619 DEFAULT_WRAPPER_W_3W(File_write_all_end
)
2620 DEFAULT_WRAPPER_W_4W(File_read_ordered_begin
)
2621 DEFAULT_WRAPPER_W_3W(File_read_ordered_end
)
2622 DEFAULT_WRAPPER_W_4W(File_write_ordered_begin
)
2623 DEFAULT_WRAPPER_W_3W(File_write_ordered_end
)
2624 DEFAULT_WRAPPER_W_3W(File_get_type_extent
)
2625 DEFAULT_WRAPPER_W_2W(File_set_atomicity
)
2626 DEFAULT_WRAPPER_W_2W(File_get_atomicity
)
2627 DEFAULT_WRAPPER_W_1W(File_sync
)
2628 /* DEFAULT_WRAPPER_W_0W(Finalize) */
2629 DEFAULT_WRAPPER_W_1W(Finalized
)
2630 DEFAULT_WRAPPER_W_1W(Free_mem
)
2631 /* DEFAULT_WRAPPER_W_8W(Gather) */
2632 DEFAULT_WRAPPER_W_9W(Gatherv
)
2633 DEFAULT_WRAPPER_W_2W(Get_address
)
2634 /* DEFAULT_WRAPPER_W_3W(Get_count) */
2635 DEFAULT_WRAPPER_W_3W(Get_elements
)
2636 DEFAULT_WRAPPER_W_8W(Get
)
2637 DEFAULT_WRAPPER_W_2W(Get_processor_name
)
2638 DEFAULT_WRAPPER_W_2W(Get_version
)
2639 DEFAULT_WRAPPER_W_6W(Graph_create
)
2640 DEFAULT_WRAPPER_W_5W(Graph_get
)
2641 DEFAULT_WRAPPER_W_5W(Graph_map
)
2642 DEFAULT_WRAPPER_W_3W(Graph_neighbors_count
)
2643 DEFAULT_WRAPPER_W_4W(Graph_neighbors
)
2644 DEFAULT_WRAPPER_W_3W(Graphdims_get
)
2645 DEFAULT_WRAPPER_W_1W(Grequest_complete
)
2646 DEFAULT_WRAPPER_W_5W(Grequest_start
)
2647 DEFAULT_WRAPPER_W_1W(Group_c2f
)
2648 DEFAULT_WRAPPER_W_3W(Group_compare
)
2649 DEFAULT_WRAPPER_W_3W(Group_difference
)
2650 DEFAULT_WRAPPER_W_4W(Group_excl
)
2651 DEFAULT_WRAPPER_W_1W(Group_f2c
)
2652 DEFAULT_WRAPPER_W_1W(Group_free
)
2653 DEFAULT_WRAPPER_W_4W(Group_incl
)
2654 DEFAULT_WRAPPER_W_3W(Group_intersection
)
2655 DEFAULT_WRAPPER_W_4W(Group_range_excl
)
2656 DEFAULT_WRAPPER_W_4W(Group_range_incl
)
2657 DEFAULT_WRAPPER_W_2W(Group_rank
)
2658 DEFAULT_WRAPPER_W_2W(Group_size
)
2659 DEFAULT_WRAPPER_W_5W(Group_translate_ranks
)
2660 DEFAULT_WRAPPER_W_3W(Group_union
)
2661 /* DEFAULT_WRAPPER_W_7W(Ibsend) */
2662 DEFAULT_WRAPPER_W_1W(Info_c2f
)
2663 DEFAULT_WRAPPER_W_1W(Info_create
)
2664 DEFAULT_WRAPPER_W_2W(Info_delete
)
2665 DEFAULT_WRAPPER_W_2W(Info_dup
)
2666 DEFAULT_WRAPPER_W_1W(Info_f2c
)
2667 DEFAULT_WRAPPER_W_1W(Info_free
)
2668 DEFAULT_WRAPPER_W_5W(Info_get
)
2669 DEFAULT_WRAPPER_W_2W(Info_get_nkeys
)
2670 DEFAULT_WRAPPER_W_3W(Info_get_nthkey
)
2671 DEFAULT_WRAPPER_W_4W(Info_get_valuelen
)
2672 DEFAULT_WRAPPER_W_3W(Info_set
)
2673 /* DEFAULT_WRAPPER_W_2W(Init) */
2674 /* DEFAULT_WRAPPER_W_1W(Initialized) */
2675 DEFAULT_WRAPPER_W_4W(Init_thread
)
2676 DEFAULT_WRAPPER_W_6W(Intercomm_create
)
2677 DEFAULT_WRAPPER_W_3W(Intercomm_merge
)
2678 /* DEFAULT_WRAPPER_W_5W(Iprobe) */
2679 /* DEFAULT_WRAPPER_W_7W(Irecv) */
2680 /* DEFAULT_WRAPPER_W_7W(Irsend) */
2681 /* DEFAULT_WRAPPER_W_7W(Isend) */
2682 /* DEFAULT_WRAPPER_W_7W(Issend) */
2683 DEFAULT_WRAPPER_W_1W(Is_thread_main
)
2684 DEFAULT_WRAPPER_W_4W(Keyval_create
)
2685 DEFAULT_WRAPPER_W_1W(Keyval_free
)
2686 DEFAULT_WRAPPER_W_3W(Lookup_name
)
2687 DEFAULT_WRAPPER_W_1W(Op_c2f
)
2688 /* DEFAULT_WRAPPER_W_3W(Op_create) */
2689 DEFAULT_WRAPPER_W_2W(Open_port
)
2690 DEFAULT_WRAPPER_W_1W(Op_f2c
)
2691 DEFAULT_WRAPPER_W_1W(Op_free
)
2692 DEFAULT_WRAPPER_W_7W(Pack_external
)
2693 DEFAULT_WRAPPER_W_4W(Pack_external_size
)
2694 /* DEFAULT_WRAPPER_W_7W(Pack) */
2695 DEFAULT_WRAPPER_W_4W(Pack_size
)
2696 /* int MPI_Pcontrol(const int level, ...) */
2697 /* DEFAULT_WRAPPER_W_4W(Probe) */
2698 DEFAULT_WRAPPER_W_3W(Publish_name
)
2699 DEFAULT_WRAPPER_W_8W(Put
)
2700 DEFAULT_WRAPPER_W_1W(Query_thread
)
2701 DEFAULT_WRAPPER_W_7W(Recv_init
)
2702 /* DEFAULT_WRAPPER_W_7W(Recv) */
2703 /* DEFAULT_WRAPPER_W_7W(Reduce) */
2704 DEFAULT_WRAPPER_W_6W(Reduce_scatter
)
2705 DEFAULT_WRAPPER_W_5W(Register_datarep
)
2706 DEFAULT_WRAPPER_W_1W(Request_c2f
)
2707 DEFAULT_WRAPPER_W_1W(Request_f2c
)
2708 DEFAULT_WRAPPER_W_1W(Request_free
)
2709 DEFAULT_WRAPPER_W_3W(Request_get_status
)
2710 /* DEFAULT_WRAPPER_W_6W(Rsend) */
2711 DEFAULT_WRAPPER_W_7W(Rsend_init
)
2712 DEFAULT_WRAPPER_W_6W(Scan
)
2713 /* DEFAULT_WRAPPER_W_8W(Scatter) */
2714 DEFAULT_WRAPPER_W_9W(Scatterv
)
2715 DEFAULT_WRAPPER_W_7W(Send_init
)
2716 /* DEFAULT_WRAPPER_W_6W(Send) */
2717 /* DEFAULT_WRAPPER_W_12W(Sendrecv) */
2718 DEFAULT_WRAPPER_W_9W(Sendrecv_replace
)
2719 DEFAULT_WRAPPER_W_7W(Ssend_init
)
2720 /* DEFAULT_WRAPPER_W_6W(Ssend) */
2721 DEFAULT_WRAPPER_W_1W(Start
)
2722 DEFAULT_WRAPPER_W_2W(Startall
)
2723 DEFAULT_WRAPPER_W_2W(Status_c2f
)
2724 DEFAULT_WRAPPER_W_2W(Status_f2c
)
2725 DEFAULT_WRAPPER_W_2W(Status_set_cancelled
)
2726 DEFAULT_WRAPPER_W_3W(Status_set_elements
)
2727 /* DEFAULT_WRAPPER_W_4W(Testall) */
2728 DEFAULT_WRAPPER_W_5W(Testany
)
2729 /* DEFAULT_WRAPPER_W_3W(Test) */
2730 DEFAULT_WRAPPER_W_2W(Test_cancelled
)
2731 DEFAULT_WRAPPER_W_5W(Testsome
)
2732 DEFAULT_WRAPPER_W_2W(Topo_test
)
2733 DEFAULT_WRAPPER_W_1W(Type_c2f
)
2734 /* DEFAULT_WRAPPER_W_1W(Type_commit) */
2735 DEFAULT_WRAPPER_W_3W(Type_contiguous
)
2736 DEFAULT_WRAPPER_W_10W(Type_create_darray
)
2737 DEFAULT_WRAPPER_W_3W(Type_create_f90_complex
)
2738 DEFAULT_WRAPPER_W_2W(Type_create_f90_integer
)
2739 DEFAULT_WRAPPER_W_3W(Type_create_f90_real
)
2740 DEFAULT_WRAPPER_W_5W(Type_create_hindexed
)
2741 DEFAULT_WRAPPER_W_5W(Type_create_hvector
)
2742 DEFAULT_WRAPPER_W_4W(Type_create_keyval
)
2743 DEFAULT_WRAPPER_W_5W(Type_create_indexed_block
)
2744 DEFAULT_WRAPPER_W_5W(Type_create_struct
)
2745 DEFAULT_WRAPPER_W_7W(Type_create_subarray
)
2746 DEFAULT_WRAPPER_W_4W(Type_create_resized
)
2747 DEFAULT_WRAPPER_W_2W(Type_delete_attr
)
2748 DEFAULT_WRAPPER_W_2W(Type_dup
)
2749 /* DEFAULT_WRAPPER_W_2W(Type_extent) */
2750 /* DEFAULT_WRAPPER_W_1W(Type_free) */
2751 DEFAULT_WRAPPER_W_1W(Type_free_keyval
)
2752 DEFAULT_WRAPPER_W_1W(Type_f2c
)
2753 DEFAULT_WRAPPER_W_4W(Type_get_attr
)
2754 /* DEFAULT_WRAPPER_W_7W(Type_get_contents) */
2755 /* DEFAULT_WRAPPER_W_5W(Type_get_envelope) */
2756 DEFAULT_WRAPPER_W_3W(Type_get_extent
)
2757 DEFAULT_WRAPPER_W_3W(Type_get_name
)
2758 DEFAULT_WRAPPER_W_3W(Type_get_true_extent
)
2759 DEFAULT_WRAPPER_W_5W(Type_hindexed
)
2760 DEFAULT_WRAPPER_W_5W(Type_hvector
)
2761 DEFAULT_WRAPPER_W_5W(Type_indexed
)
2762 DEFAULT_WRAPPER_W_2W(Type_lb
)
2763 DEFAULT_WRAPPER_W_3W(Type_match_size
)
2764 DEFAULT_WRAPPER_W_3W(Type_set_attr
)
2765 DEFAULT_WRAPPER_W_2W(Type_set_name
)
2766 DEFAULT_WRAPPER_W_2W(Type_size
)
2767 DEFAULT_WRAPPER_W_5W(Type_struct
)
2768 DEFAULT_WRAPPER_W_2W(Type_ub
)
2769 DEFAULT_WRAPPER_W_5W(Type_vector
)
2770 /* DEFAULT_WRAPPER_W_7W(Unpack) */
2771 DEFAULT_WRAPPER_W_3W(Unpublish_name
)
2772 DEFAULT_WRAPPER_W_7W(Unpack_external
)
2773 /* DEFAULT_WRAPPER_W_3W(Waitall) */
2774 /* DEFAULT_WRAPPER_W_4W(Waitany) */
2775 /* DEFAULT_WRAPPER_W_2W(Wait) */
2776 DEFAULT_WRAPPER_W_5W(Waitsome
)
2777 DEFAULT_WRAPPER_W_1W(Win_c2f
)
2778 DEFAULT_WRAPPER_W_2W(Win_call_errhandler
)
2779 DEFAULT_WRAPPER_W_1W(Win_complete
)
2780 DEFAULT_WRAPPER_W_6W(Win_create
)
2781 DEFAULT_WRAPPER_W_2W(Win_create_errhandler
)
2782 DEFAULT_WRAPPER_W_4W(Win_create_keyval
)
2783 DEFAULT_WRAPPER_W_2W(Win_delete_attr
)
2784 DEFAULT_WRAPPER_W_1W(Win_f2c
)
2785 DEFAULT_WRAPPER_W_2W(Win_fence
)
2786 DEFAULT_WRAPPER_W_1W(Win_free
)
2787 DEFAULT_WRAPPER_W_1W(Win_free_keyval
)
2788 DEFAULT_WRAPPER_W_4W(Win_get_attr
)
2789 DEFAULT_WRAPPER_W_2W(Win_get_errhandler
)
2790 DEFAULT_WRAPPER_W_2W(Win_get_group
)
2791 DEFAULT_WRAPPER_W_3W(Win_get_name
)
2792 DEFAULT_WRAPPER_W_4W(Win_lock
)
2793 DEFAULT_WRAPPER_W_3W(Win_post
)
2794 DEFAULT_WRAPPER_W_3W(Win_set_attr
)
2795 DEFAULT_WRAPPER_W_2W(Win_set_errhandler
)
2796 DEFAULT_WRAPPER_W_2W(Win_set_name
)
2797 DEFAULT_WRAPPER_W_3W(Win_start
)
2798 DEFAULT_WRAPPER_W_2W(Win_test
)
2799 DEFAULT_WRAPPER_W_2W(Win_unlock
)
2800 DEFAULT_WRAPPER_W_1W(Win_wait
)
2801 /* double MPI_Wtick(void) */
2802 /* double MPI_Wtime(void) */
2805 /*------------------------------------------------------------*/
2809 /*------------------------------------------------------------*/
2811 /*---------------------------------------------------------------*/
2812 /*--- end mpiwrap.c ---*/
2813 /*---------------------------------------------------------------*/