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