1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
4 * (C) 2001 by Argonne National Laboratory.
5 * See COPYRIGHT in top-level directory.
8 #include "mpitestconf.h"
10 #include "smpi_cocci.h"
11 #if defined(HAVE_STDIO_H) || defined(STDC_HEADERS)
14 #if defined(HAVE_STDLIB_H) || defined(STDC_HEADERS)
17 #if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
23 /* The following two includes permit the collection of resource usage
26 #ifdef HAVE_SYS_TIME_H
29 #ifdef HAVE_SYS_RESOURCE_H
30 #include <sys/resource.h>
36 * Utility routines for writing MPI tests.
38 * We check the return codes on all MPI routines (other than INIT)
39 * to allow the program that uses these routines to select MPI_ERRORS_RETURN
40 * as the error handler. We do *not* set MPI_ERRORS_RETURN because
41 * the code that makes use of these routines may not check return
46 static void MTestRMACleanup( void );
47 static void MTestResourceSummary( FILE * );
49 /* Here is where we could put the includes and definitions to enable
52 SMPI_VARINIT_GLOBAL_AND_SET(dbgflag, int, 0); /* Flag used for debugging */
53 SMPI_VARINIT_GLOBAL_AND_SET(wrank, int, -1); /* World rank */
54 SMPI_VARINIT_GLOBAL_AND_SET(verbose, int, 0); /* Message level (0 is none) */
55 SMPI_VARINIT_GLOBAL_AND_SET(returnWithVal, int, 0); /* Allow programs to return
56 with a non-zero if there was an error (may
57 cause problems with some runtime systems) */
58 SMPI_VARINIT_GLOBAL_AND_SET(usageOutput, int, 0); /* */
60 /* Provide backward portability to MPI 1 */
65 #define MPI_THREAD_SINGLE 0
69 * Initialize and Finalize MTest
73 Initialize MTest, initializing MPI if necessary.
75 Environment Variables:
76 + MPITEST_DEBUG - If set (to any value), turns on debugging output
77 . MPITEST_THREADLEVEL_DEFAULT - If set, use as the default "provided"
78 level of thread support. Applies to
79 MTest_Init but not MTest_Init_thread.
80 - MPITEST_VERBOSE - If set to a numeric value, turns on that level of
81 verbose output. This is used by the routine 'MTestPrintfMsg'
84 void MTest_Init_thread( int *argc, char ***argv, int required, int *provided )
89 MPI_Initialized( &flag );
91 /* Permit an MPI that claims only MPI 1 but includes the
92 MPI_Init_thread routine (e.g., IBM MPI) */
93 #if MPI_VERSION >= 2 || defined(HAVE_MPI_INIT_THREAD)
94 MPI_Init_thread( argc, argv, required, provided );
96 MPI_Init( argc, argv );
100 /* Check for debugging control */
101 if (getenv( "MPITEST_DEBUG" )) {
102 SMPI_VARGET_GLOBAL(dbgflag) = 1;
103 MPI_Comm_rank( MPI_COMM_WORLD, &SMPI_VARGET_GLOBAL(wrank) );
106 /* Check for verbose control */
107 envval = getenv( "MPITEST_VERBOSE" );
110 long val = strtol( envval, &s, 0 );
112 /* This is the error case for strtol */
113 fprintf( stderr, "Warning: %s not valid for MPITEST_VERBOSE\n",
119 SMPI_VARGET_GLOBAL(verbose) = val;
122 fprintf( stderr, "Warning: %s not valid for MPITEST_VERBOSE\n",
128 /* Check for option to return success/failure in the return value of main */
129 envval = getenv( "MPITEST_RETURN_WITH_CODE" );
131 if (strcmp( envval, "yes" ) == 0 ||
132 strcmp( envval, "YES" ) == 0 ||
133 strcmp( envval, "true" ) == 0 ||
134 strcmp( envval, "TRUE" ) == 0) {
135 SMPI_VARGET_GLOBAL(returnWithVal) = 1;
137 else if (strcmp( envval, "no" ) == 0 ||
138 strcmp( envval, "NO" ) == 0 ||
139 strcmp( envval, "false" ) == 0 ||
140 strcmp( envval, "FALSE" ) == 0) {
141 SMPI_VARGET_GLOBAL(returnWithVal) = 0;
145 "Warning: %s not valid for MPITEST_RETURN_WITH_CODE\n",
151 /* Print rusage data if set */
152 if (getenv( "MPITEST_RUSAGE" )) {
153 SMPI_VARGET_GLOBAL(usageOutput) = 1;
157 * Initialize the tests, using an MPI-1 style init. Supports
158 * MTEST_THREADLEVEL_DEFAULT to test with user-specified thread level
160 void MTest_Init( int *argc, char ***argv )
163 #if MPI_VERSION >= 2 || defined(HAVE_MPI_INIT_THREAD)
167 threadLevel = MPI_THREAD_SINGLE;
168 str = getenv( "MTEST_THREADLEVEL_DEFAULT" );
169 if (!str) str = getenv( "MPITEST_THREADLEVEL_DEFAULT" );
171 if (strcmp(str,"MULTIPLE") == 0 || strcmp(str,"multiple") == 0) {
172 threadLevel = MPI_THREAD_MULTIPLE;
174 else if (strcmp(str,"SERIALIZED") == 0 ||
175 strcmp(str,"serialized") == 0) {
176 threadLevel = MPI_THREAD_SERIALIZED;
178 else if (strcmp(str,"FUNNELED") == 0 || strcmp(str,"funneled") == 0) {
179 threadLevel = MPI_THREAD_FUNNELED;
181 else if (strcmp(str,"SINGLE") == 0 || strcmp(str,"single") == 0) {
182 threadLevel = MPI_THREAD_SINGLE;
185 fprintf( stderr, "Unrecognized thread level %s\n", str );
186 /* Use exit since MPI_Init/Init_thread has not been called. */
190 MTest_Init_thread( argc, argv, threadLevel, &provided );
192 /* If the MPI_VERSION is 1, there is no MPI_THREAD_xxx defined */
193 MTest_Init_thread( argc, argv, 0, &provided );
198 Finalize MTest. errs is the number of errors on the calling process;
199 this routine will write the total number of errors over all of MPI_COMM_WORLD
200 to the process with rank zero, or " No Errors".
201 It does *not* finalize MPI.
203 void MTest_Finalize( int errs )
205 int rank, toterrs, merr;
207 merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
208 if (merr) MTestPrintError( merr );
210 merr = MPI_Reduce( &errs, &toterrs, 1, MPI_INT, MPI_SUM,
212 if (merr) MTestPrintError( merr );
215 printf( " Found %d errors\n", toterrs );
218 printf( " No Errors\n" );
223 if (SMPI_VARGET_GLOBAL(usageOutput))
224 MTestResourceSummary( stdout );
227 /* Clean up any persistent objects that we allocated */
230 /* ------------------------------------------------------------------------ */
231 /* This routine may be used instead of "return 0;" at the end of main;
232 it allows the program to use the return value to signal success or failure.
234 int MTestReturnValue( int errors )
236 if (SMPI_VARGET_GLOBAL(returnWithVal)) return errors ? 1 : 0;
239 /* ------------------------------------------------------------------------ */
242 * Miscellaneous utilities, particularly to eliminate OS dependencies
244 * MTestSleep( seconds )
246 #ifdef HAVE_WINDOWS_H
248 void MTestSleep( int sec )
254 void MTestSleep( int sec )
263 * Eventually, this could read a description of a file. For now, we hard
266 * Each kind of datatype has the following functions:
267 * MTestTypeXXXInit - Initialize a send buffer for that type
268 * MTestTypeXXXInitRecv - Initialize a receive buffer for that type
269 * MTestTypeXXXFree - Free any buffers associate with that type
270 * MTestTypeXXXCheckbuf - Check that the buffer contains the expected data
271 * These routines work with (nearly) any datatype that is of type XXX,
272 * allowing the test codes to create a variety of contiguous, vector, and
273 * indexed types, then test them by calling these routines.
275 * Available types (for the XXX) are
276 * Contig - Simple contiguous buffers
277 * Vector - Simple strided "vector" type
278 * Indexed - Indexed datatype. Only for a count of 1 instance of the
281 SMPI_VARINIT_GLOBAL_AND_SET(datatype_index, int, 0);
283 /* ------------------------------------------------------------------------ */
284 /* Datatype routines for contiguous datatypes */
285 /* ------------------------------------------------------------------------ */
287 * Setup contiguous buffers of n copies of a datatype.
289 static void *MTestTypeContigInit( MTestDatatype *mtype )
294 if (mtype->count > 0) {
297 merr = MPI_Type_extent( mtype->datatype, &size );
298 if (merr) MTestPrintError( merr );
299 totsize = size * mtype->count;
301 mtype->buf = (void *) malloc( totsize );
303 p = (signed char *)(mtype->buf);
305 /* Error - out of memory */
306 MTestError( "Out of memory in type buffer init" );
308 for (i=0; i<totsize; i++) {
309 p[i] = 0xff ^ (i & 0xff);
322 * Setup contiguous buffers of n copies of a datatype. Initialize for
323 * reception (e.g., set initial data to detect failure)
325 static void *MTestTypeContigInitRecv( MTestDatatype *mtype )
330 if (mtype->count > 0) {
333 merr = MPI_Type_extent( mtype->datatype, &size );
334 if (merr) MTestPrintError( merr );
335 totsize = size * mtype->count;
337 mtype->buf = (void *) malloc( totsize );
339 p = (signed char *)(mtype->buf);
341 /* Error - out of memory */
342 MTestError( "Out of memory in type buffer init" );
344 for (i=0; i<totsize; i++) {
356 static void *MTestTypeContigFree( MTestDatatype *mtype )
364 static int MTestTypeContigCheckbuf( MTestDatatype *mtype )
367 unsigned char expected;
368 int i, totsize, err = 0, merr;
371 p = (unsigned char *)mtype->buf;
373 merr = MPI_Type_extent( mtype->datatype, &size );
374 if (merr) MTestPrintError( merr );
375 totsize = size * mtype->count;
376 for (i=0; i<totsize; i++) {
377 expected = (0xff ^ (i & 0xff));
378 if (p[i] != expected) {
380 if (mtype->printErrors && err < 10) {
381 printf( "Data expected = %x but got p[%d] = %x\n",
391 /* ------------------------------------------------------------------------ */
392 /* Datatype routines for vector datatypes */
393 /* ------------------------------------------------------------------------ */
395 static void *MTestTypeVectorInit( MTestDatatype *mtype )
400 if (mtype->count > 0) {
402 int i, j, k, nc, totsize;
404 merr = MPI_Type_extent( mtype->datatype, &size );
405 if (merr) MTestPrintError( merr );
406 totsize = mtype->count * size;
408 mtype->buf = (void *) malloc( totsize );
410 p = (unsigned char *)(mtype->buf);
412 /* Error - out of memory */
413 MTestError( "Out of memory in type buffer init" );
416 /* First, set to -1 */
417 for (i=0; i<totsize; i++) p[i] = 0xff;
419 /* Now, set the actual elements to the successive values.
420 To do this, we need to run 3 loops */
422 /* count is usually one for a vector type */
423 for (k=0; k<mtype->count; k++) {
424 /* For each element (block) */
425 for (i=0; i<mtype->nelm; i++) {
427 for (j=0; j<mtype->blksize; j++) {
428 p[j] = (0xff ^ (nc & 0xff));
441 static void *MTestTypeVectorFree( MTestDatatype *mtype )
450 /* ------------------------------------------------------------------------ */
451 /* Datatype routines for indexed block datatypes */
452 /* ------------------------------------------------------------------------ */
455 * Setup a buffer for one copy of an indexed datatype.
457 static void *MTestTypeIndexedInit( MTestDatatype *mtype )
462 if (mtype->count > 1) {
463 MTestError( "This datatype is supported only for a single count" );
465 if (mtype->count == 1) {
469 /* Allocate the send/recv buffer */
470 merr = MPI_Type_extent( mtype->datatype, &totsize );
471 if (merr) MTestPrintError( merr );
473 mtype->buf = (void *) malloc( totsize );
475 p = (signed char *)(mtype->buf);
477 MTestError( "Out of memory in type buffer init\n" );
479 /* Initialize the elements */
480 /* First, set to -1 */
481 for (i=0; i<totsize; i++) p[i] = 0xff;
483 /* Now, set the actual elements to the successive values.
484 We require that the base type is a contiguous type */
486 for (i=0; i<mtype->nelm; i++) {
488 /* Compute the offset: */
489 offset = mtype->displs[i] * mtype->basesize;
490 /* For each element in the block */
491 for (b=0; b<mtype->index[i]; b++) {
492 for (j=0; j<mtype->basesize; j++) {
493 p[offset+j] = 0xff ^ (k++ & 0xff);
495 offset += mtype->basesize;
510 * Setup indexed buffers for 1 copy of a datatype. Initialize for
511 * reception (e.g., set initial data to detect failure)
513 static void *MTestTypeIndexedInitRecv( MTestDatatype *mtype )
518 if (mtype->count > 1) {
519 MTestError( "This datatype is supported only for a single count" );
521 if (mtype->count == 1) {
524 merr = MPI_Type_extent( mtype->datatype, &totsize );
525 if (merr) MTestPrintError( merr );
527 mtype->buf = (void *) malloc( totsize );
529 p = (signed char *)(mtype->buf);
531 /* Error - out of memory */
532 MTestError( "Out of memory in type buffer init\n" );
534 for (i=0; i<totsize; i++) {
548 static void *MTestTypeIndexedFree( MTestDatatype *mtype )
552 free( mtype->displs );
553 free( mtype->index );
561 static int MTestTypeIndexedCheckbuf( MTestDatatype *mtype )
564 unsigned char expected;
565 int i, err = 0, merr;
568 p = (unsigned char *)mtype->buf;
571 merr = MPI_Type_extent( mtype->datatype, &totsize );
572 if (merr) MTestPrintError( merr );
575 for (i=0; i<mtype->nelm; i++) {
577 /* Compute the offset: */
578 offset = mtype->displs[i] * mtype->basesize;
579 for (b=0; b<mtype->index[i]; b++) {
580 for (j=0; j<mtype->basesize; j++) {
581 expected = (0xff ^ (k & 0xff));
582 if (p[offset+j] != expected) {
584 if (mtype->printErrors && err < 10) {
585 printf( "Data expected = %x but got p[%d,%d] = %x\n",
586 expected, i,j, p[offset+j] );
592 offset += mtype->basesize;
600 /* ------------------------------------------------------------------------ */
601 /* Routines to select a datatype and associated buffer create/fill/check */
603 /* ------------------------------------------------------------------------ */
606 Create a range of datatypes with a given count elements.
607 This uses a selection of types, rather than an exhaustive collection.
608 It allocates both send and receive types so that they can have the same
609 type signature (collection of basic types) but different type maps (layouts
612 int MTestGetDatatypes( MTestDatatype *sendtype, MTestDatatype *recvtype,
618 sendtype->InitBuf = 0;
619 sendtype->FreeBuf = 0;
620 sendtype->CheckBuf = 0;
621 sendtype->datatype = 0;
622 sendtype->isBasic = 0;
623 sendtype->printErrors = 0;
624 recvtype->InitBuf = 0;
625 recvtype->FreeBuf = 0;
627 recvtype->CheckBuf = 0;
628 recvtype->datatype = 0;
629 recvtype->isBasic = 0;
630 recvtype->printErrors = 0;
635 /* Set the defaults for the message lengths */
636 sendtype->count = count;
637 recvtype->count = count;
638 /* Use datatype_index to choose a datatype to use. If at the end of the
640 switch (SMPI_VARGET_GLOBAL(datatype_index)) {
642 sendtype->datatype = MPI_INT;
643 sendtype->isBasic = 1;
644 recvtype->datatype = MPI_INT;
645 recvtype->isBasic = 1;
648 sendtype->datatype = MPI_DOUBLE;
649 sendtype->isBasic = 1;
650 recvtype->datatype = MPI_DOUBLE;
651 recvtype->isBasic = 1;
654 sendtype->datatype = MPI_FLOAT_INT;
655 sendtype->isBasic = 1;
656 recvtype->datatype = MPI_FLOAT_INT;
657 recvtype->isBasic = 1;
660 merr = MPI_Type_dup( MPI_INT, &sendtype->datatype );
661 if (merr) MTestPrintError( merr );
662 merr = MPI_Type_set_name( sendtype->datatype,
663 (char*)"dup of MPI_INT" );
664 if (merr) MTestPrintError( merr );
665 merr = MPI_Type_dup( MPI_INT, &recvtype->datatype );
666 if (merr) MTestPrintError( merr );
667 merr = MPI_Type_set_name( recvtype->datatype,
668 (char*)"dup of MPI_INT" );
669 if (merr) MTestPrintError( merr );
670 /* dup'ed types are already committed if the original type
671 was committed (MPI-2, section 8.8) */
674 /* vector send type and contiguous receive type */
675 /* These sizes are in bytes (see the VectorInit code) */
676 sendtype->stride = 3 * sizeof(int);
677 sendtype->blksize = sizeof(int);
678 sendtype->nelm = recvtype->count;
680 merr = MPI_Type_vector( recvtype->count, 1, 3, MPI_INT,
681 &sendtype->datatype );
682 if (merr) MTestPrintError( merr );
683 merr = MPI_Type_commit( &sendtype->datatype );
684 if (merr) MTestPrintError( merr );
685 merr = MPI_Type_set_name( sendtype->datatype,
686 (char*)"int-vector" );
687 if (merr) MTestPrintError( merr );
689 recvtype->datatype = MPI_INT;
690 recvtype->isBasic = 1;
691 sendtype->InitBuf = MTestTypeVectorInit;
692 recvtype->InitBuf = MTestTypeContigInitRecv;
693 sendtype->FreeBuf = MTestTypeVectorFree;
694 recvtype->FreeBuf = MTestTypeContigFree;
695 sendtype->CheckBuf = 0;
696 recvtype->CheckBuf = MTestTypeContigCheckbuf;
700 /* Indexed send using many small blocks and contig receive */
701 sendtype->blksize = sizeof(int);
702 sendtype->nelm = recvtype->count;
703 sendtype->basesize = sizeof(int);
704 sendtype->displs = (int *)malloc( sendtype->nelm * sizeof(int) );
705 sendtype->index = (int *)malloc( sendtype->nelm * sizeof(int) );
706 if (!sendtype->displs || !sendtype->index) {
707 MTestError( "Out of memory in type init\n" );
709 /* Make the sizes larger (4 ints) to help push the total
710 size to over 256k in some cases, as the MPICH code as of
711 10/1/06 used large internal buffers for packing non-contiguous
713 for (i=0; i<sendtype->nelm; i++) {
714 sendtype->index[i] = 4;
715 sendtype->displs[i] = 5*i;
717 merr = MPI_Type_indexed( sendtype->nelm,
718 sendtype->index, sendtype->displs,
719 MPI_INT, &sendtype->datatype );
720 if (merr) MTestPrintError( merr );
721 merr = MPI_Type_commit( &sendtype->datatype );
722 if (merr) MTestPrintError( merr );
723 merr = MPI_Type_set_name( sendtype->datatype,
724 (char*)"int-indexed(4-int)" );
725 if (merr) MTestPrintError( merr );
727 sendtype->InitBuf = MTestTypeIndexedInit;
728 sendtype->FreeBuf = MTestTypeIndexedFree;
729 sendtype->CheckBuf = 0;
731 recvtype->datatype = MPI_INT;
732 recvtype->isBasic = 1;
733 recvtype->count = count * 4;
734 recvtype->InitBuf = MTestTypeContigInitRecv;
735 recvtype->FreeBuf = MTestTypeContigFree;
736 recvtype->CheckBuf = MTestTypeContigCheckbuf;
740 /* Indexed send using 2 large blocks and contig receive */
741 sendtype->blksize = sizeof(int);
743 sendtype->basesize = sizeof(int);
744 sendtype->displs = (int *)malloc( sendtype->nelm * sizeof(int) );
745 sendtype->index = (int *)malloc( sendtype->nelm * sizeof(int) );
746 if (!sendtype->displs || !sendtype->index) {
747 MTestError( "Out of memory in type init\n" );
749 /* index -> block size */
750 sendtype->index[0] = (recvtype->count + 1) / 2;
751 sendtype->displs[0] = 0;
752 sendtype->index[1] = recvtype->count - sendtype->index[0];
753 sendtype->displs[1] = sendtype->index[0] + 1;
754 /* There is a deliberate gap here */
756 merr = MPI_Type_indexed( sendtype->nelm,
757 sendtype->index, sendtype->displs,
758 MPI_INT, &sendtype->datatype );
759 if (merr) MTestPrintError( merr );
760 merr = MPI_Type_commit( &sendtype->datatype );
761 if (merr) MTestPrintError( merr );
762 merr = MPI_Type_set_name( sendtype->datatype,
763 (char*)"int-indexed(2 blocks)" );
764 if (merr) MTestPrintError( merr );
766 sendtype->InitBuf = MTestTypeIndexedInit;
767 sendtype->FreeBuf = MTestTypeIndexedFree;
768 sendtype->CheckBuf = 0;
770 recvtype->datatype = MPI_INT;
771 recvtype->isBasic = 1;
772 recvtype->count = sendtype->index[0] + sendtype->index[1];
773 recvtype->InitBuf = MTestTypeContigInitRecv;
774 recvtype->FreeBuf = MTestTypeContigFree;
775 recvtype->CheckBuf = MTestTypeContigCheckbuf;
779 /* Indexed receive using many small blocks and contig send */
780 recvtype->blksize = sizeof(int);
781 recvtype->nelm = recvtype->count;
782 recvtype->basesize = sizeof(int);
783 recvtype->displs = (int *)malloc( recvtype->nelm * sizeof(int) );
784 recvtype->index = (int *)malloc( recvtype->nelm * sizeof(int) );
785 if (!recvtype->displs || !recvtype->index) {
786 MTestError( "Out of memory in type recv init\n" );
788 /* Make the sizes larger (4 ints) to help push the total
789 size to over 256k in some cases, as the MPICH code as of
790 10/1/06 used large internal buffers for packing non-contiguous
792 /* Note that there are gaps in the indexed type */
793 for (i=0; i<recvtype->nelm; i++) {
794 recvtype->index[i] = 4;
795 recvtype->displs[i] = 5*i;
797 merr = MPI_Type_indexed( recvtype->nelm,
798 recvtype->index, recvtype->displs,
799 MPI_INT, &recvtype->datatype );
800 if (merr) MTestPrintError( merr );
801 merr = MPI_Type_commit( &recvtype->datatype );
802 if (merr) MTestPrintError( merr );
803 merr = MPI_Type_set_name( recvtype->datatype,
804 (char*)"recv-int-indexed(4-int)" );
805 if (merr) MTestPrintError( merr );
807 recvtype->InitBuf = MTestTypeIndexedInitRecv;
808 recvtype->FreeBuf = MTestTypeIndexedFree;
809 recvtype->CheckBuf = MTestTypeIndexedCheckbuf;
811 sendtype->datatype = MPI_INT;
812 sendtype->isBasic = 1;
813 sendtype->count = count * 4;
814 sendtype->InitBuf = MTestTypeContigInit;
815 sendtype->FreeBuf = MTestTypeContigFree;
816 sendtype->CheckBuf = 0;
819 /* Less commonly used but still simple types */
821 sendtype->datatype = MPI_SHORT;
822 sendtype->isBasic = 1;
823 recvtype->datatype = MPI_SHORT;
824 recvtype->isBasic = 1;
827 sendtype->datatype = MPI_LONG;
828 sendtype->isBasic = 1;
829 recvtype->datatype = MPI_LONG;
830 recvtype->isBasic = 1;
833 sendtype->datatype = MPI_CHAR;
834 sendtype->isBasic = 1;
835 recvtype->datatype = MPI_CHAR;
836 recvtype->isBasic = 1;
839 sendtype->datatype = MPI_UINT64_T;
840 sendtype->isBasic = 1;
841 recvtype->datatype = MPI_UINT64_T;
842 recvtype->isBasic = 1;
845 sendtype->datatype = MPI_FLOAT;
846 sendtype->isBasic = 1;
847 recvtype->datatype = MPI_FLOAT;
848 recvtype->isBasic = 1;
851 #ifndef USE_STRICT_MPI
852 /* MPI_BYTE may only be used with MPI_BYTE in strict MPI */
854 sendtype->datatype = MPI_INT;
855 sendtype->isBasic = 1;
856 recvtype->datatype = MPI_BYTE;
857 recvtype->isBasic = 1;
858 recvtype->count *= sizeof(int);
862 SMPI_VARGET_GLOBAL(datatype_index) = -1;
865 if (!sendtype->InitBuf) {
866 sendtype->InitBuf = MTestTypeContigInit;
867 recvtype->InitBuf = MTestTypeContigInitRecv;
868 sendtype->FreeBuf = MTestTypeContigFree;
869 recvtype->FreeBuf = MTestTypeContigFree;
870 sendtype->CheckBuf = MTestTypeContigCheckbuf;
871 recvtype->CheckBuf = MTestTypeContigCheckbuf;
873 SMPI_VARGET_GLOBAL(datatype_index)++;
875 if (SMPI_VARGET_GLOBAL(dbgflag) && SMPI_VARGET_GLOBAL(datatype_index) > 0) {
877 fprintf( stderr, "%d: sendtype is %s\n", SMPI_VARGET_GLOBAL(wrank), MTestGetDatatypeName( sendtype ) );
878 merr = MPI_Type_size( sendtype->datatype, &typesize );
879 if (merr) MTestPrintError( merr );
880 fprintf( stderr, "%d: sendtype size = %d\n", SMPI_VARGET_GLOBAL(wrank), typesize );
881 fprintf( stderr, "%d: recvtype is %s\n", SMPI_VARGET_GLOBAL(wrank), MTestGetDatatypeName( recvtype ) );
882 merr = MPI_Type_size( recvtype->datatype, &typesize );
883 if (merr) MTestPrintError( merr );
884 fprintf( stderr, "%d: recvtype size = %d\n", SMPI_VARGET_GLOBAL(wrank), typesize );
888 else if (SMPI_VARGET_GLOBAL(verbose) && SMPI_VARGET_GLOBAL(datatype_index) > 0) {
889 printf( "Get new datatypes: send = %s, recv = %s\n",
890 MTestGetDatatypeName( sendtype ),
891 MTestGetDatatypeName( recvtype ) );
895 return SMPI_VARGET_GLOBAL(datatype_index);
898 /* Reset the datatype index (start from the initial data type.
899 Note: This routine is rarely needed; MTestGetDatatypes automatically
900 starts over after the last available datatype is used.
902 void MTestResetDatatypes( void )
904 SMPI_VARGET_GLOBAL(datatype_index) = 0;
906 /* Return the index of the current datatype. This is rarely needed and
907 is provided mostly to enable debugging of the MTest package itself */
908 int MTestGetDatatypeIndex( void )
910 return SMPI_VARGET_GLOBAL(datatype_index);
913 /* Free the storage associated with a datatype */
914 void MTestFreeDatatype( MTestDatatype *mtype )
917 /* Invoke a datatype-specific free function to handle
918 both the datatype and the send/receive buffers */
919 if (mtype->FreeBuf) {
920 (mtype->FreeBuf)( mtype );
922 /* Free the datatype itself if it was created */
923 if (!mtype->isBasic) {
924 merr = MPI_Type_free( &mtype->datatype );
925 if (merr) MTestPrintError( merr );
929 /* Check that a message was received correctly. Returns the number of
930 errors detected. Status may be NULL or MPI_STATUS_IGNORE */
931 int MTestCheckRecv( MPI_Status *status, MTestDatatype *recvtype )
936 if (status && status != MPI_STATUS_IGNORE) {
937 merr = MPI_Get_count( status, recvtype->datatype, &count );
938 if (merr) MTestPrintError( merr );
940 /* Check count against expected count */
941 if (count != recvtype->count) {
946 /* Check received data */
947 if (!errs && recvtype->CheckBuf( recvtype )) {
953 /* This next routine uses a circular buffer of static name arrays just to
954 simplify the use of the routine */
955 const char *MTestGetDatatypeName( MTestDatatype *dtype )
957 typedef char name_type[4][MPI_MAX_OBJECT_NAME];
958 SMPI_VARINIT_STATIC(name, name_type);
959 SMPI_VARINIT_STATIC_AND_SET(sp, int, 0);
962 if (SMPI_VARGET_STATIC(sp) >= 4) SMPI_VARGET_STATIC(sp) = 0;
963 merr = MPI_Type_get_name( dtype->datatype, SMPI_VARGET_STATIC(name)[SMPI_VARGET_STATIC(sp)], &rlen );
964 if (merr) MTestPrintError( merr );
965 return (const char *)SMPI_VARGET_STATIC(name)[SMPI_VARGET_STATIC(sp)++];
967 /* ----------------------------------------------------------------------- */
970 * Create communicators. Use separate routines for inter and intra
971 * communicators (there is a routine to give both)
972 * Note that the routines may return MPI_COMM_NULL, so code should test for
973 * that return value as well.
976 SMPI_VARINIT_GLOBAL_AND_SET(interCommIdx, int, 0);
977 SMPI_VARINIT_GLOBAL_AND_SET(intraCommIdx, int, 0);
978 SMPI_VARINIT_GLOBAL_AND_SET(intraCommName, const char *, 0);
979 SMPI_VARINIT_GLOBAL_AND_SET(interCommName, const char *, 0);
982 * Get an intracommunicator with at least min_size members. If "allowSmaller"
983 * is true, allow the communicator to be smaller than MPI_COMM_WORLD and
984 * for this routine to return MPI_COMM_NULL for some values. Returns 0 if
985 * no more communicators are available.
987 int MTestGetIntracommGeneral( MPI_Comm *comm, int min_size, int allowSmaller )
989 int size, rank, merr;
993 /* The while loop allows us to skip communicators that are too small.
994 MPI_COMM_NULL is always considered large enough */
997 SMPI_VARGET_GLOBAL(intraCommName) = "";
998 switch (SMPI_VARGET_GLOBAL(intraCommIdx)) {
1000 *comm = MPI_COMM_WORLD;
1002 SMPI_VARGET_GLOBAL(intraCommName) = "MPI_COMM_WORLD";
1006 merr = MPI_Comm_dup(MPI_COMM_WORLD, comm );
1007 if (merr) MTestPrintError( merr );
1008 SMPI_VARGET_GLOBAL(intraCommName) = "Dup of MPI_COMM_WORLD";
1012 merr = MPI_Comm_size( MPI_COMM_WORLD, &size );
1013 if (merr) MTestPrintError( merr );
1014 merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
1015 if (merr) MTestPrintError( merr );
1016 merr = MPI_Comm_split( MPI_COMM_WORLD, 0, size-rank, comm );
1017 if (merr) MTestPrintError( merr );
1018 SMPI_VARGET_GLOBAL(intraCommName) = "Rank reverse of MPI_COMM_WORLD";
1021 /* subset of world, with reversed ranks */
1022 merr = MPI_Comm_size( MPI_COMM_WORLD, &size );
1023 if (merr) MTestPrintError( merr );
1024 merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
1025 if (merr) MTestPrintError( merr );
1026 merr = MPI_Comm_split( MPI_COMM_WORLD, ((rank < size/2) ? 1 : MPI_UNDEFINED),
1028 if (merr) MTestPrintError( merr );
1029 SMPI_VARGET_GLOBAL(intraCommName) = "Rank reverse of half of MPI_COMM_WORLD";
1032 *comm = MPI_COMM_SELF;
1034 SMPI_VARGET_GLOBAL(intraCommName) = "MPI_COMM_SELF";
1037 /* These next cases are communicators that include some
1038 but not all of the processes */
1045 merr = MPI_Comm_size( MPI_COMM_WORLD, &size );
1046 if (merr) MTestPrintError( merr );
1047 newsize = size - (SMPI_VARGET_GLOBAL(intraCommIdx) - 4);
1049 if (allowSmaller && newsize >= min_size) {
1050 merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
1051 if (merr) MTestPrintError( merr );
1052 merr = MPI_Comm_split( MPI_COMM_WORLD, rank < newsize, rank,
1054 if (merr) MTestPrintError( merr );
1055 if (rank >= newsize) {
1056 merr = MPI_Comm_free( comm );
1057 if (merr) MTestPrintError( merr );
1058 *comm = MPI_COMM_NULL;
1061 SMPI_VARGET_GLOBAL(intraCommName) = "Split of WORLD";
1065 /* Act like default */
1066 *comm = MPI_COMM_NULL;
1067 SMPI_VARGET_GLOBAL(intraCommIdx) = -1;
1072 /* Other ideas: dup of self, cart comm, graph comm */
1074 *comm = MPI_COMM_NULL;
1075 SMPI_VARGET_GLOBAL(intraCommIdx) = -1;
1079 if (*comm != MPI_COMM_NULL) {
1080 merr = MPI_Comm_size( *comm, &size );
1081 if (merr) MTestPrintError( merr );
1082 if (size >= min_size)
1086 SMPI_VARGET_GLOBAL(intraCommName) = "MPI_COMM_NULL";
1091 /* we are only done if all processes are done */
1092 MPI_Allreduce(&done2, &done, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD);
1094 /* Advance the comm index whether we are done or not, otherwise we could
1095 * spin forever trying to allocate a too-small communicator over and
1097 SMPI_VARGET_GLOBAL(intraCommIdx)++;
1099 if (!done && !isBasic && *comm != MPI_COMM_NULL) {
1100 /* avoid leaking communicators */
1101 merr = MPI_Comm_free(comm);
1102 if (merr) MTestPrintError(merr);
1106 return SMPI_VARGET_GLOBAL(intraCommIdx);
1110 * Get an intracommunicator with at least min_size members.
1112 int MTestGetIntracomm( MPI_Comm *comm, int min_size )
1114 return MTestGetIntracommGeneral( comm, min_size, 0 );
1117 /* Return the name of an intra communicator */
1118 const char *MTestGetIntracommName( void )
1120 return SMPI_VARGET_GLOBAL(intraCommName);
1124 * Return an intercomm; set isLeftGroup to 1 if the calling process is
1125 * a member of the "left" group.
1127 int MTestGetIntercomm( MPI_Comm *comm, int *isLeftGroup, int min_size )
1129 int size, rank, remsize, merr;
1131 MPI_Comm mcomm = MPI_COMM_NULL;
1132 MPI_Comm mcomm2 = MPI_COMM_NULL;
1135 /* The while loop allows us to skip communicators that are too small.
1136 MPI_COMM_NULL is always considered large enough. The size is
1137 the sum of the sizes of the local and remote groups */
1139 *comm = MPI_COMM_NULL;
1141 SMPI_VARGET_GLOBAL(interCommName) = "MPI_COMM_NULL";
1143 switch (SMPI_VARGET_GLOBAL(interCommIdx)) {
1145 /* Split comm world in half */
1146 merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
1147 if (merr) MTestPrintError( merr );
1148 merr = MPI_Comm_size( MPI_COMM_WORLD, &size );
1149 if (merr) MTestPrintError( merr );
1151 merr = MPI_Comm_split( MPI_COMM_WORLD, (rank < size/2), rank,
1153 if (merr) MTestPrintError( merr );
1157 else if (rank == size/2) {
1161 /* Remote leader is signficant only for the processes
1162 designated local leaders */
1165 *isLeftGroup = rank < size/2;
1166 merr = MPI_Intercomm_create( mcomm, 0, MPI_COMM_WORLD, rleader,
1168 if (merr) MTestPrintError( merr );
1169 SMPI_VARGET_GLOBAL(interCommName) = "Intercomm by splitting MPI_COMM_WORLD";
1172 *comm = MPI_COMM_NULL;
1175 /* Split comm world in to 1 and the rest */
1176 merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
1177 if (merr) MTestPrintError( merr );
1178 merr = MPI_Comm_size( MPI_COMM_WORLD, &size );
1179 if (merr) MTestPrintError( merr );
1181 merr = MPI_Comm_split( MPI_COMM_WORLD, rank == 0, rank,
1183 if (merr) MTestPrintError( merr );
1187 else if (rank == 1) {
1191 /* Remote leader is signficant only for the processes
1192 designated local leaders */
1195 *isLeftGroup = rank == 0;
1196 merr = MPI_Intercomm_create( mcomm, 0, MPI_COMM_WORLD,
1197 rleader, 12346, comm );
1198 if (merr) MTestPrintError( merr );
1199 SMPI_VARGET_GLOBAL(interCommName) = "Intercomm by splitting MPI_COMM_WORLD into 1, rest";
1202 *comm = MPI_COMM_NULL;
1206 /* Split comm world in to 2 and the rest */
1207 merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
1208 if (merr) MTestPrintError( merr );
1209 merr = MPI_Comm_size( MPI_COMM_WORLD, &size );
1210 if (merr) MTestPrintError( merr );
1212 merr = MPI_Comm_split( MPI_COMM_WORLD, rank < 2, rank,
1214 if (merr) MTestPrintError( merr );
1218 else if (rank == 2) {
1222 /* Remote leader is signficant only for the processes
1223 designated local leaders */
1226 *isLeftGroup = rank < 2;
1227 merr = MPI_Intercomm_create( mcomm, 0, MPI_COMM_WORLD,
1228 rleader, 12347, comm );
1229 if (merr) MTestPrintError( merr );
1230 SMPI_VARGET_GLOBAL(interCommName) = "Intercomm by splitting MPI_COMM_WORLD into 2, rest";
1233 *comm = MPI_COMM_NULL;
1237 /* Split comm world in half, then dup */
1238 merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
1239 if (merr) MTestPrintError( merr );
1240 merr = MPI_Comm_size( MPI_COMM_WORLD, &size );
1241 if (merr) MTestPrintError( merr );
1243 merr = MPI_Comm_split( MPI_COMM_WORLD, (rank < size/2), rank,
1245 if (merr) MTestPrintError( merr );
1249 else if (rank == size/2) {
1253 /* Remote leader is signficant only for the processes
1254 designated local leaders */
1257 *isLeftGroup = rank < size/2;
1258 merr = MPI_Intercomm_create( mcomm, 0, MPI_COMM_WORLD, rleader,
1260 if (merr) MTestPrintError( merr );
1261 /* avoid leaking after assignment below */
1262 merr = MPI_Comm_free( &mcomm );
1263 if (merr) MTestPrintError( merr );
1265 /* now dup, some bugs only occur for dup's of intercomms */
1267 merr = MPI_Comm_dup(mcomm, comm);
1268 if (merr) MTestPrintError( merr );
1269 SMPI_VARGET_GLOBAL(interCommName) = "Intercomm by splitting MPI_COMM_WORLD then dup'ing";
1272 *comm = MPI_COMM_NULL;
1276 /* Split comm world in half, form intercomm, then split that intercomm */
1277 merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
1278 if (merr) MTestPrintError( merr );
1279 merr = MPI_Comm_size( MPI_COMM_WORLD, &size );
1280 if (merr) MTestPrintError( merr );
1282 merr = MPI_Comm_split( MPI_COMM_WORLD, (rank < size/2), rank,
1284 if (merr) MTestPrintError( merr );
1288 else if (rank == size/2) {
1292 /* Remote leader is signficant only for the processes
1293 designated local leaders */
1296 *isLeftGroup = rank < size/2;
1297 merr = MPI_Intercomm_create( mcomm, 0, MPI_COMM_WORLD, rleader,
1299 if (merr) MTestPrintError( merr );
1300 /* avoid leaking after assignment below */
1301 merr = MPI_Comm_free( &mcomm );
1302 if (merr) MTestPrintError( merr );
1304 /* now split, some bugs only occur for splits of intercomms */
1306 rank = MPI_Comm_rank(mcomm, &rank);
1307 if (merr) MTestPrintError( merr );
1308 /* this split is effectively a dup but tests the split code paths */
1309 merr = MPI_Comm_split(mcomm, 0, rank, comm);
1310 if (merr) MTestPrintError( merr );
1311 SMPI_VARGET_GLOBAL(interCommName) = "Intercomm by splitting MPI_COMM_WORLD then then splitting again";
1314 *comm = MPI_COMM_NULL;
1318 /* split comm world in half discarding rank 0 on the "left"
1319 * communicator, then form them into an intercommunicator */
1320 merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
1321 if (merr) MTestPrintError( merr );
1322 merr = MPI_Comm_size( MPI_COMM_WORLD, &size );
1323 if (merr) MTestPrintError( merr );
1325 int color = (rank < size/2 ? 0 : 1);
1327 color = MPI_UNDEFINED;
1329 merr = MPI_Comm_split( MPI_COMM_WORLD, color, rank, &mcomm );
1330 if (merr) MTestPrintError( merr );
1335 else if (rank == (size/2)) {
1339 /* Remote leader is signficant only for the processes
1340 designated local leaders */
1343 *isLeftGroup = rank < size/2;
1344 if (rank != 0) { /* 0's mcomm is MPI_COMM_NULL */
1345 merr = MPI_Intercomm_create( mcomm, 0, MPI_COMM_WORLD, rleader, 12345, comm );
1346 if (merr) MTestPrintError( merr );
1348 SMPI_VARGET_GLOBAL(interCommName) = "Intercomm by splitting MPI_COMM_WORLD (discarding rank 0 in the left group) then MPI_Intercomm_create'ing";
1351 *comm = MPI_COMM_NULL;
1356 /* Split comm world in half then form them into an
1357 * intercommunicator. Then discard rank 0 from each group of the
1358 * intercomm via MPI_Comm_create. */
1359 merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
1360 if (merr) MTestPrintError( merr );
1361 merr = MPI_Comm_size( MPI_COMM_WORLD, &size );
1362 if (merr) MTestPrintError( merr );
1364 MPI_Group oldgroup, newgroup;
1366 int color = (rank < size/2 ? 0 : 1);
1368 merr = MPI_Comm_split( MPI_COMM_WORLD, color, rank, &mcomm );
1369 if (merr) MTestPrintError( merr );
1374 else if (rank == (size/2)) {
1378 /* Remote leader is signficant only for the processes
1379 designated local leaders */
1382 *isLeftGroup = rank < size/2;
1383 merr = MPI_Intercomm_create( mcomm, 0, MPI_COMM_WORLD, rleader, 12345, &mcomm2 );
1384 if (merr) MTestPrintError( merr );
1386 /* We have an intercomm between the two halves of comm world. Now create
1387 * a new intercomm that removes rank 0 on each side. */
1388 merr = MPI_Comm_group(mcomm2, &oldgroup);
1389 if (merr) MTestPrintError( merr );
1391 merr = MPI_Group_excl(oldgroup, 1, ranks, &newgroup);
1392 if (merr) MTestPrintError( merr );
1393 merr = MPI_Comm_create(mcomm2, newgroup, comm);
1394 if (merr) MTestPrintError( merr );
1396 merr = MPI_Group_free(&oldgroup);
1397 if (merr) MTestPrintError( merr );
1398 merr = MPI_Group_free(&newgroup);
1399 if (merr) MTestPrintError( merr );
1401 SMPI_VARGET_GLOBAL(interCommName) = "Intercomm by splitting MPI_COMM_WORLD then discarding 0 ranks with MPI_Comm_create";
1404 *comm = MPI_COMM_NULL;
1409 *comm = MPI_COMM_NULL;
1410 SMPI_VARGET_GLOBAL(interCommIdx) = -1;
1414 if (*comm != MPI_COMM_NULL) {
1415 merr = MPI_Comm_size( *comm, &size );
1416 if (merr) MTestPrintError( merr );
1417 merr = MPI_Comm_remote_size( *comm, &remsize );
1418 if (merr) MTestPrintError( merr );
1419 if (size + remsize >= min_size) done = 1;
1422 SMPI_VARGET_GLOBAL(interCommName) = "MPI_COMM_NULL";
1426 /* we are only done if all processes are done */
1427 MPI_Allreduce(MPI_IN_PLACE, &done, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD);
1429 /* Advance the comm index whether we are done or not, otherwise we could
1430 * spin forever trying to allocate a too-small communicator over and
1432 SMPI_VARGET_GLOBAL(interCommIdx)++;
1434 if (!done && *comm != MPI_COMM_NULL) {
1435 /* avoid leaking communicators */
1436 merr = MPI_Comm_free(comm);
1437 if (merr) MTestPrintError(merr);
1440 /* cleanup for common temp objects */
1441 if (mcomm != MPI_COMM_NULL) {
1442 merr = MPI_Comm_free(&mcomm);
1443 if (merr) MTestPrintError( merr );
1445 if (mcomm2 != MPI_COMM_NULL) {
1446 merr = MPI_Comm_free(&mcomm2);
1447 if (merr) MTestPrintError( merr );
1451 return SMPI_VARGET_GLOBAL(interCommIdx);
1453 /* Return the name of an intercommunicator */
1454 const char *MTestGetIntercommName( void )
1456 return SMPI_VARGET_GLOBAL(interCommName);
1459 /* Get a communicator of a given minimum size. Both intra and inter
1460 communicators are provided */
1461 int MTestGetComm( MPI_Comm *comm, int min_size )
1464 SMPI_VARINIT_STATIC_AND_SET(getinter, int, 0);
1466 if (!SMPI_VARGET_STATIC(getinter)) {
1467 idx = MTestGetIntracomm( comm, min_size );
1469 SMPI_VARGET_STATIC(getinter) = 1;
1472 if (SMPI_VARGET_STATIC(getinter)) {
1474 idx = MTestGetIntercomm( comm, &isLeft, min_size );
1476 SMPI_VARGET_STATIC(getinter) = 0;
1483 /* Free a communicator. It may be called with a predefined communicator
1485 void MTestFreeComm( MPI_Comm *comm )
1488 if (*comm != MPI_COMM_WORLD &&
1489 *comm != MPI_COMM_SELF &&
1490 *comm != MPI_COMM_NULL) {
1491 merr = MPI_Comm_free( comm );
1492 if (merr) MTestPrintError( merr );
1496 /* ------------------------------------------------------------------------ */
1497 void MTestPrintError( int errcode )
1500 char string[MPI_MAX_ERROR_STRING];
1502 MPI_Error_class( errcode, &errclass );
1503 MPI_Error_string( errcode, string, &slen );
1504 printf( "Error class %d (%s)\n", errclass, string );
1507 void MTestPrintErrorMsg( const char msg[], int errcode )
1510 char string[MPI_MAX_ERROR_STRING];
1512 MPI_Error_class( errcode, &errclass );
1513 MPI_Error_string( errcode, string, &slen );
1514 printf( "%s: Error class %d (%s)\n", msg, errclass, string );
1517 /* ------------------------------------------------------------------------ */
1519 If verbose output is selected and the level is at least that of the
1520 value of the verbose flag, then perform printf( format, ... );
1522 void MTestPrintfMsg( int level, const char format[], ... )
1526 if (SMPI_VARGET_GLOBAL(verbose) && level >= SMPI_VARGET_GLOBAL(verbose)) {
1527 va_start(list,format);
1528 vprintf( format, list );
1533 /* Fatal error. Report and exit */
1534 void MTestError( const char *msg )
1536 fprintf( stderr, "%s\n", msg );
1538 MPI_Abort( MPI_COMM_WORLD, 1 );
1541 /* ------------------------------------------------------------------------ */
1542 static void MTestResourceSummary( FILE *fp )
1544 #ifdef HAVE_GETRUSAGE
1546 SMPI_VARINIT_STATIC_AND_SET(pfThreshold, int, -2);
1548 if (getrusage( RUSAGE_SELF, &ru ) == 0) {
1549 /* There is an option to generate output only when a resource
1550 exceeds a threshold. To date, only page faults supported. */
1551 if (SMPI_VARGET_STATIC(pfThreshold) == -2) {
1552 char *p = getenv("MPITEST_RUSAGE_PF");
1553 SMPI_VARGET_STATIC(pfThreshold) = -1;
1555 SMPI_VARGET_STATIC(pfThreshold) = strtol( p, 0, 0 );
1558 if (SMPI_VARGET_STATIC(pfThreshold) > 0) {
1559 doOutput = ru.ru_minflt > SMPI_VARGET_STATIC(pfThreshold);
1562 /* Cast values to long in case some system has defined them
1563 as another integer type */
1564 fprintf( fp, "RUSAGE: max resident set = %ldKB\n",
1565 (long)ru.ru_maxrss );
1566 fprintf( fp, "RUSAGE: page faults = %ld : %ld\n",
1567 (long)ru.ru_minflt, (long)ru.ru_majflt );
1568 /* Not every Unix provides useful information for the xxrss fields */
1569 fprintf( fp, "RUSAGE: memory in text/data/stack = %ld : %ld : %ld\n",
1570 (long)ru.ru_ixrss, (long)ru.ru_idrss, (long)ru.ru_isrss );
1571 fprintf( fp, "RUSAGE: I/O in and out = %ld : %ld\n",
1572 (long)ru.ru_inblock, (long)ru.ru_oublock );
1573 fprintf( fp, "RUSAGE: context switch = %ld : %ld\n",
1574 (long)ru.ru_nvcsw, (long)ru.ru_nivcsw );
1578 fprintf( fp, "RUSAGE: return error %d\n", errno );
1582 /* ------------------------------------------------------------------------ */
1583 #ifdef HAVE_MPI_WIN_CREATE
1585 * Create MPI Windows
1587 SMPI_VARINIT_GLOBAL_AND_SET(win_index, int, 0);
1588 SMPI_VARINIT_GLOBAL(winName, const char *);
1589 /* Use an attribute to remember the type of memory allocation (static,
1590 malloc, or MPI_Alloc_mem) */
1591 SMPI_VARINIT_GLOBAL_AND_SET(mem_keyval, int, MPI_KEYVAL_INVALID);
1592 int MTestGetWin( MPI_Win *win, int mustBePassive )
1594 typedef char actbuf_type[1024];
1595 SMPI_VARINIT_STATIC(actbuf, actbuf_type);
1596 SMPI_VARINIT_STATIC(pasbuf, char *);
1601 if (SMPI_VARGET_GLOBAL(mem_keyval) == MPI_KEYVAL_INVALID) {
1602 /* Create the keyval */
1603 merr = MPI_Win_create_keyval( MPI_WIN_NULL_COPY_FN,
1604 MPI_WIN_NULL_DELETE_FN,
1605 &SMPI_VARGET_GLOBAL(mem_keyval), 0 );
1606 if (merr) MTestPrintError( merr );
1610 switch (SMPI_VARGET_GLOBAL(win_index)) {
1612 /* Active target window */
1613 merr = MPI_Win_create( SMPI_VARGET_STATIC(actbuf), 1024, 1, MPI_INFO_NULL, MPI_COMM_WORLD,
1615 if (merr) MTestPrintError( merr );
1616 SMPI_VARGET_GLOBAL(winName) = "active-window";
1617 merr = MPI_Win_set_attr( *win, SMPI_VARGET_GLOBAL(mem_keyval), (void *)0 );
1618 if (merr) MTestPrintError( merr );
1621 /* Passive target window */
1622 merr = MPI_Alloc_mem( 1024, MPI_INFO_NULL, &SMPI_VARGET_STATIC(pasbuf) );
1623 if (merr) MTestPrintError( merr );
1624 merr = MPI_Win_create( SMPI_VARGET_STATIC(pasbuf), 1024, 1, MPI_INFO_NULL, MPI_COMM_WORLD,
1626 if (merr) MTestPrintError( merr );
1627 SMPI_VARGET_GLOBAL(winName) = "passive-window";
1628 merr = MPI_Win_set_attr( *win, SMPI_VARGET_GLOBAL(mem_keyval), (void *)2 );
1629 if (merr) MTestPrintError( merr );
1632 /* Active target; all windows different sizes */
1633 merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
1634 if (merr) MTestPrintError( merr );
1637 buf = (char *)malloc( n );
1640 merr = MPI_Win_create( buf, n, 1, MPI_INFO_NULL, MPI_COMM_WORLD,
1642 if (merr) MTestPrintError( merr );
1643 SMPI_VARGET_GLOBAL(winName) = "active-all-different-win";
1644 merr = MPI_Win_set_attr( *win, SMPI_VARGET_GLOBAL(mem_keyval), (void *)1 );
1645 if (merr) MTestPrintError( merr );
1648 /* Active target, no locks set */
1649 merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
1650 if (merr) MTestPrintError( merr );
1653 buf = (char *)malloc( n );
1656 merr = MPI_Info_create( &info );
1657 if (merr) MTestPrintError( merr );
1658 merr = MPI_Info_set( info, (char*)"nolocks", (char*)"true" );
1659 if (merr) MTestPrintError( merr );
1660 merr = MPI_Win_create( buf, n, 1, info, MPI_COMM_WORLD, win );
1661 if (merr) MTestPrintError( merr );
1662 merr = MPI_Info_free( &info );
1663 if (merr) MTestPrintError( merr );
1664 SMPI_VARGET_GLOBAL(winName) = "active-nolocks-all-different-win";
1665 merr = MPI_Win_set_attr( *win, SMPI_VARGET_GLOBAL(mem_keyval), (void *)1 );
1666 if (merr) MTestPrintError( merr );
1669 SMPI_VARGET_GLOBAL(win_index) = -1;
1671 SMPI_VARGET_GLOBAL(win_index)++;
1672 return SMPI_VARGET_GLOBAL(win_index);
1674 /* Return a pointer to the name associated with a window object */
1675 const char *MTestGetWinName( void )
1677 return SMPI_VARGET_GLOBAL(winName);
1679 /* Free the storage associated with a window object */
1680 void MTestFreeWin( MPI_Win *win )
1685 merr = MPI_Win_get_attr( *win, MPI_WIN_BASE, &addr, &flag );
1686 if (merr) MTestPrintError( merr );
1688 MTestError( "Could not get WIN_BASE from window" );
1692 merr = MPI_Win_get_attr( *win, SMPI_VARGET_GLOBAL(mem_keyval), &val, &flag );
1693 if (merr) MTestPrintError( merr );
1695 if (val == (void *)1) {
1698 else if (val == (void *)2) {
1699 merr = MPI_Free_mem( addr );
1700 if (merr) MTestPrintError( merr );
1702 /* if val == (void *)0, then static data that must not be freed */
1705 merr = MPI_Win_free(win);
1706 if (merr) MTestPrintError( merr );
1708 static void MTestRMACleanup( void )
1710 if (SMPI_VARGET_GLOBAL(mem_keyval) != MPI_KEYVAL_INVALID) {
1711 MPI_Win_free_keyval( &SMPI_VARGET_GLOBAL(mem_keyval) );
1715 static void MTestRMACleanup( void ) {}