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