/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ /* * * (C) 2003 by Argonne National Laboratory. * See COPYRIGHT in top-level directory. */ #include "mpi.h" #include #include #include "mpitest.h" #include "mpithreadtest.h" /* static char MTEST_Descrip[] = "Threaded Send-Recv"; */ /* The buffer size needs to be large enough to cause the rndv protocol to be used. If the MPI provider doesn't use a rndv protocol then the size doesn't matter. */ #define MSG_SIZE 1024*1024 /* Keep track of whether the send succeeded. The values are: -1 (unset), 0 (failure), 1 (ok). The unset value allows us to avoid a possible race caused by reading the value before the send thread sets it. */ static volatile int sendok = -1; MTEST_THREAD_RETURN_TYPE send_thread(void *p); MTEST_THREAD_RETURN_TYPE send_thread(void *p) { int err; char *buffer; int length; int rank; buffer = malloc(sizeof(char) * MSG_SIZE); MTEST_VG_MEM_INIT(buffer, MSG_SIZE * sizeof(char)); if (buffer == NULL) { printf("malloc failed to allocate %d bytes for the send buffer.\n", MSG_SIZE); fflush(stdout); sendok = 0; return (MTEST_THREAD_RETURN_TYPE) - 1; } MPI_Comm_rank(MPI_COMM_WORLD, &rank); /* To improve reporting of problems about operations, we * change the error handler to errors return */ MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_RETURN); err = MPI_Send(buffer, MSG_SIZE, MPI_CHAR, rank == 0 ? 1 : 0, 0, MPI_COMM_WORLD); if (err) { MPI_Error_string(err, buffer, &length); printf("MPI_Send of %d bytes from %d to %d failed, error: %s\n", MSG_SIZE, rank, rank == 0 ? 1 : 0, buffer); fflush(stdout); sendok = 0; } else { sendok = 1; } free(buffer); return (MTEST_THREAD_RETURN_TYPE) (long) err; } int main(int argc, char *argv[]) { int err, errs = 0; int rank, size; int provided; char *buffer; int length; MPI_Status status; err = MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided); if (err != MPI_SUCCESS) { MPI_Abort(MPI_COMM_WORLD, 1); } MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); if (provided != MPI_THREAD_MULTIPLE) { if (rank == 0) { printf ("MPI_Init_thread must return MPI_THREAD_MULTIPLE in order for this test to run.\n"); fflush(stdout); } MPI_Finalize(); return -1; } if (size > 2) { printf("please run with exactly two processes.\n"); MPI_Finalize(); return -1; } MTest_Start_thread(send_thread, NULL); /* give the send thread time to start up and begin sending the message */ MTestSleep(3); buffer = malloc(sizeof(char) * MSG_SIZE); MTEST_VG_MEM_INIT(buffer, MSG_SIZE * sizeof(char)); if (buffer == NULL) { printf("malloc failed to allocate %d bytes for the recv buffer.\n", MSG_SIZE); fflush(stdout); MPI_Abort(MPI_COMM_WORLD, -1); } /* To improve reporting of problems about operations, we * change the error handler to errors return */ MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_RETURN); err = MPI_Recv(buffer, MSG_SIZE, MPI_CHAR, rank == 0 ? 1 : 0, 0, MPI_COMM_WORLD, &status); if (err) { errs++; MPI_Error_string(err, buffer, &length); printf("MPI_Recv of %d bytes from %d to %d failed, error: %s\n", MSG_SIZE, rank, rank == 0 ? 1 : 0, buffer); fflush(stdout); } /* Loop until the send flag is set */ while (sendok == -1); if (!sendok) { errs++; } MTest_Join_threads(); free(buffer); MTest_Finalize(errs); MPI_Finalize(); return 0; }