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