Hi Open MPI developers, I found some bugs in Open MPI and attach a patch to fix them.
The bugs are: (1) MPI_SOURCE of MPI_Status for a null request must be MPI_ANY_SOURCE. 3.7.3 Communication Completion in MPI-3.0 (and also MPI-2.2) says an MPI_Status object returned by MPI_{Wait|Test}{|any|all} must be an empty status for a null request (MPI_REQUEST_NULL). And the MPI_SOURCE field of the empty status must be MPI_ANY_SOURCE. But MPI_Wait, MPI_Waitall, and MPI_Testall set MPI_PROC_NULL to the MPI_SOURCE field of such status object. This bug is caused by a use of an incorrect variable in ompi/mpi/c/wait.c (for MPI_Wait) and by an incorrect initialization of ompi_request_null in ompi/request/request.c (for MPI_Waitall and MPI_Testall). (2) MPI_Status for an inactive request must be an empty status. 3.7.3 Communication Completion in MPI-3.0 (and also MPI-2.2) says an MPI_Status object returned by MPI_{Wait|Test}{|any|all} must be an empty status for an inactive persistent request. But MPI_Wait, MPI_Waitall, and MPI_Testall return an old status (that was returned when the request was active) for an inactive persistent request. This bug is caused by not updating a req_status field of an inactive persistent request object in ompi/request/req_wait.c and ompi/request/req_test.c. (3) Possible BUS errors on sparc64 processors. r23554 fixed possible BUS errors on sparc64 processors. But the fix seems to be insufficient. We should use OMPI_STATUS_SET macro for all user-supplied MPI_Status objects. The attached patch is for Open MPI trunk and it also fixes some typos in comments. A program to reproduce bugs (1) and (2) is also attached. Regards, Takahiro Kawashima, MPI development team, Fujitsu
Index: ompi/request/request.c =================================================================== --- ompi/request/request.c (revision 27388) +++ ompi/request/request.c (working copy) @@ -13,6 +13,7 @@ * Copyright (c) 2006-2012 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2012 Oak Ridge National Labs. All rights reserved. + * Copyright (c) 2012 FUJITSU LIMITED. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -111,7 +112,7 @@ return OMPI_ERROR; } ompi_request_null.request.req_type = OMPI_REQUEST_NULL; - ompi_request_null.request.req_status.MPI_SOURCE = MPI_PROC_NULL; + ompi_request_null.request.req_status.MPI_SOURCE = MPI_ANY_SOURCE; ompi_request_null.request.req_status.MPI_TAG = MPI_ANY_TAG; ompi_request_null.request.req_status.MPI_ERROR = MPI_SUCCESS; ompi_request_null.request.req_status._ucount = 0; Index: ompi/request/req_wait.c =================================================================== --- ompi/request/req_wait.c (revision 27388) +++ ompi/request/req_wait.c (working copy) @@ -12,6 +12,7 @@ * Copyright (c) 2006-2008 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012 Oak Ridge National Labs. All rights reserved. + * Copyright (c) 2012 FUJITSU LIMITED. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -46,7 +47,7 @@ #endif /* return status. If it's a generalized request, we *have* to - invoke the query_fn, even if the user procided STATUS_IGNORE. + invoke the query_fn, even if the user provided STATUS_IGNORE. MPI-2:8.2. */ if (OMPI_REQUEST_GEN == req->req_type) { ompi_grequest_invoke_query(req, &req->req_status); @@ -60,11 +61,15 @@ status->_cancelled = req->req_status._cancelled; } if( req->req_persistent ) { + int error = req->req_status.MPI_ERROR; if( req->req_state == OMPI_REQUEST_INACTIVE ) { return OMPI_SUCCESS; } req->req_state = OMPI_REQUEST_INACTIVE; - return req->req_status.MPI_ERROR; + /* Next time MPI_Wait* or MPI_Test* is called, we must return + empty status. */ + OMPI_STATUS_SET(&req->req_status, &ompi_status_empty); + return error; } /* If there was an error, don't free the request -- just return @@ -188,6 +193,9 @@ rc = request->req_status.MPI_ERROR; if( request->req_persistent ) { request->req_state = OMPI_REQUEST_INACTIVE; + /* Next time MPI_Wait* or MPI_Test* is called, we must return + empty status. */ + OMPI_STATUS_SET(&request->req_status, &ompi_status_empty); } else if (MPI_SUCCESS == rc) { /* Only free the request if there is no error on it */ /* If there's an error while freeing the request, @@ -254,7 +262,7 @@ /* * confirm the status of the pending requests. We have to do it before * taking the condition or otherwise we can miss some requests completion (the - * one that happpens between our initial test and the aquisition of the lock). + * one that happens between our initial test and the acquisition of the lock). */ rptr = requests; for( completed = i = 0; i < count; i++ ) { @@ -360,6 +368,9 @@ if( request->req_persistent ) { request->req_state = OMPI_REQUEST_INACTIVE; + /* Next time MPI_Wait* or MPI_Test* is called, we must return + empty status. */ + OMPI_STATUS_SET(&request->req_status, &ompi_status_empty); } else { /* Only free the request if there is no error on it */ if (MPI_SUCCESS == request->req_status.MPI_ERROR) { @@ -409,6 +420,9 @@ } if( request->req_persistent ) { request->req_state = OMPI_REQUEST_INACTIVE; + /* Next time MPI_Wait* or MPI_Test* is called, we must return + empty status. */ + OMPI_STATUS_SET(&request->req_status, &ompi_status_empty); } else if (MPI_SUCCESS == rc) { /* Only free the request if there is no error on it */ int tmp = ompi_request_free(rptr); @@ -566,6 +580,9 @@ if( request->req_persistent ) { request->req_state = OMPI_REQUEST_INACTIVE; + /* Next time MPI_Wait* or MPI_Test* is called, we must return + empty status. */ + OMPI_STATUS_SET(&request->req_status, &ompi_status_empty); } else { /* Only free the request if there was no error */ if (MPI_SUCCESS == request->req_status.MPI_ERROR) { Index: ompi/request/req_test.c =================================================================== --- ompi/request/req_test.c (revision 27388) +++ ompi/request/req_test.c (working copy) @@ -12,6 +12,7 @@ * Copyright (c) 2006-2008 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012 Oak Ridge National Labs. All rights reserved. + * Copyright (c) 2012 FUJITSU LIMITED. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -68,8 +69,12 @@ status->MPI_ERROR = old_error; } if( request->req_persistent ) { + int error = request->req_status.MPI_ERROR; request->req_state = OMPI_REQUEST_INACTIVE; - return request->req_status.MPI_ERROR; + /* Next time MPI_Wait* or MPI_Test* is called, we must return + empty status. */ + OMPI_STATUS_SET(&request->req_status, &ompi_status_empty); + return error; } /* If there was an error, don't free the request -- just return the single error. */ @@ -145,8 +150,12 @@ } if( request->req_persistent ) { + int error = request->req_status.MPI_ERROR; request->req_state = OMPI_REQUEST_INACTIVE; - return OMPI_SUCCESS; + /* Next time MPI_Wait* or MPI_Test* is called, we must return + empty status. */ + OMPI_STATUS_SET(&request->req_status, &ompi_status_empty); + return error; } /* If there is an error on the request, don't free it */ if (MPI_SUCCESS != request->req_status.MPI_ERROR) { @@ -231,6 +240,9 @@ OMPI_STATUS_SET(&statuses[i], &request->req_status); if( request->req_persistent ) { request->req_state = OMPI_REQUEST_INACTIVE; + /* Next time MPI_Wait* or MPI_Test* is called, we must return + empty status. */ + OMPI_STATUS_SET(&request->req_status, &ompi_status_empty); continue; } /* MPI-2:4.5.1 says that we can return MPI_ERR_IN_STATUS @@ -260,6 +272,9 @@ } if( request->req_persistent ) { request->req_state = OMPI_REQUEST_INACTIVE; + /* Next time MPI_Wait* or MPI_Test* is called, we must return + empty status. */ + OMPI_STATUS_SET(&request->req_status, &ompi_status_empty); continue; } /* Only free the request if there was no error */ @@ -338,6 +353,9 @@ if( request->req_persistent ) { request->req_state = OMPI_REQUEST_INACTIVE; + /* Next time MPI_Wait* or MPI_Test* is called, we must return + empty status. */ + OMPI_STATUS_SET(&request->req_status, &ompi_status_empty); } else { /* Only free the request if there was no error */ if (MPI_SUCCESS == request->req_status.MPI_ERROR) { Index: ompi/mpi/c/wait.c =================================================================== --- ompi/mpi/c/wait.c (revision 27388) +++ ompi/mpi/c/wait.c (working copy) @@ -10,6 +10,7 @@ * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. * Copyright (c) 2006 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2012 FUJITSU LIMITED. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -54,7 +55,7 @@ if (MPI_REQUEST_NULL == *request) { if (MPI_STATUS_IGNORE != status) { - *status = ompi_request_empty.req_status; + OMPI_STATUS_SET(status, &ompi_status_empty); /* * Per MPI-1, the MPI_ERROR field is not defined for single-completion calls */ Index: ompi/mpi/c/waitany.c =================================================================== --- ompi/mpi/c/waitany.c (revision 27388) +++ ompi/mpi/c/waitany.c (working copy) @@ -13,6 +13,7 @@ * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012 Los Alamos National Security, LLC. All rights * reserved. + * Copyright (c) 2012 FUJITSU LIMITED. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -71,7 +72,7 @@ if (OPAL_UNLIKELY(0 == count)) { *indx = MPI_UNDEFINED; - *status = ompi_status_empty; + OMPI_STATUS_SET(status, &ompi_status_empty); return MPI_SUCCESS; } Index: ompi/mpi/c/testany.c =================================================================== --- ompi/mpi/c/testany.c (revision 27388) +++ ompi/mpi/c/testany.c (working copy) @@ -13,6 +13,7 @@ * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012 Los Alamos National Security, LLC. All rights * reserved. + * Copyright (c) 2012 FUJITSU LIMITED. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -72,7 +73,7 @@ if (OPAL_UNLIKELY(0 == count)) { *completed = true; *indx = MPI_UNDEFINED; - *status = ompi_status_empty; + OMPI_STATUS_SET(status, &ompi_status_empty); return MPI_SUCCESS; } Index: ompi/mpi/c/probe.c =================================================================== --- ompi/mpi/c/probe.c (revision 27388) +++ ompi/mpi/c/probe.c (working copy) @@ -9,6 +9,7 @@ * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. + * Copyright (c) 2012 FUJITSU LIMITED. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -62,7 +63,7 @@ if (MPI_PROC_NULL == source) { if (MPI_STATUS_IGNORE != status) { - *status = ompi_request_empty.req_status; + OMPI_STATUS_SET(status, &ompi_request_empty.req_status); /* * Per MPI-1, the MPI_ERROR field is not defined for single-completion calls */ Index: ompi/mpi/c/iprobe.c =================================================================== --- ompi/mpi/c/iprobe.c (revision 27388) +++ ompi/mpi/c/iprobe.c (working copy) @@ -9,6 +9,7 @@ * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. + * Copyright (c) 2012 FUJITSU LIMITED. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -62,7 +63,7 @@ if (MPI_PROC_NULL == source) { if (MPI_STATUS_IGNORE != status) { - *status = ompi_request_empty.req_status; + OMPI_STATUS_SET(status, &ompi_request_empty.req_status); /* * Per MPI-1, the MPI_ERROR field is not defined for single-completion calls */ Index: ompi/mpi/c/mprobe.c =================================================================== --- ompi/mpi/c/mprobe.c (revision 27388) +++ ompi/mpi/c/mprobe.c (working copy) @@ -2,6 +2,7 @@ * Copyright (c) 2011 Sandia National Laboratories. All rights reserved. * Copyright (c) 2012 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012 FUJITSU LIMITED. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -57,7 +58,7 @@ if (MPI_PROC_NULL == source) { if (MPI_STATUS_IGNORE != status) { - *status = ompi_request_empty.req_status; + OMPI_STATUS_SET(status, &ompi_request_empty.req_status); /* Per MPI-1, the MPI_ERROR field is not defined for single-completion calls */ MEMCHECKER( Index: ompi/mpi/c/improbe.c =================================================================== --- ompi/mpi/c/improbe.c (revision 27388) +++ ompi/mpi/c/improbe.c (working copy) @@ -2,6 +2,7 @@ * Copyright (c) 2011 Sandia National Laboratories. All rights reserved. * Copyright (c) 2012 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012 FUJITSU LIMITED. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -57,7 +58,7 @@ if (MPI_PROC_NULL == source) { if (MPI_STATUS_IGNORE != status) { - *status = ompi_request_empty.req_status; + OMPI_STATUS_SET(status, &ompi_request_empty.req_status); /* Per MPI-1, the MPI_ERROR field is not defined for single-completion calls */ MEMCHECKER( Index: ompi/mpi/c/request_get_status.c =================================================================== --- ompi/mpi/c/request_get_status.c (revision 27388) +++ ompi/mpi/c/request_get_status.c (working copy) @@ -10,6 +10,7 @@ * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. * Copyright (c) 2006-2010 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2012 FUJITSU LIMITED. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -71,7 +72,7 @@ if( (request == MPI_REQUEST_NULL) || (request->req_state == OMPI_REQUEST_INACTIVE) ) { *flag = true; if( MPI_STATUS_IGNORE != status ) { - *status = ompi_status_empty; + OMPI_STATUS_SET(status, &ompi_status_empty); } return MPI_SUCCESS; } @@ -84,7 +85,7 @@ ompi_grequest_invoke_query(request, &request->req_status); } if (MPI_STATUS_IGNORE != status) { - *status = request->req_status; + OMPI_STATUS_SET(status, &request->req_status); } return MPI_SUCCESS; } Index: ompi/mpi/c/recv.c =================================================================== --- ompi/mpi/c/recv.c (revision 27388) +++ ompi/mpi/c/recv.c (working copy) @@ -9,6 +9,7 @@ * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. + * Copyright (c) 2012 FUJITSU LIMITED. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -68,7 +69,7 @@ if (MPI_PROC_NULL == source) { if (MPI_STATUS_IGNORE != status) { - *status = ompi_request_empty.req_status; + OMPI_STATUS_SET(status, &ompi_request_empty.req_status); } return MPI_SUCCESS; } Index: ompi/mpi/c/mrecv.c =================================================================== --- ompi/mpi/c/mrecv.c (revision 27388) +++ ompi/mpi/c/mrecv.c (working copy) @@ -1,6 +1,7 @@ /* * Copyright (c) 2011 Sandia National Laboratories. All rights reserved. * Copyright (c) 2012 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2012 FUJITSU LIMITED. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -59,7 +60,7 @@ } if (&ompi_message_no_proc.message == *message) { - *status = ompi_request_empty.req_status; + OMPI_STATUS_SET(status, &ompi_request_empty.req_status); *message = MPI_MESSAGE_NULL; return MPI_SUCCESS; } Index: ompi/mpi/c/sendrecv.c =================================================================== --- ompi/mpi/c/sendrecv.c (revision 27388) +++ ompi/mpi/c/sendrecv.c (working copy) @@ -9,6 +9,7 @@ * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. + * Copyright (c) 2012 FUJITSU LIMITED. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -90,7 +91,7 @@ rc = ompi_request_wait(&req, status); } else { if (MPI_STATUS_IGNORE != status) { - *status = ompi_request_empty.req_status; + OMPI_STATUS_SET(status, &ompi_request_empty.req_status); } rc = MPI_SUCCESS; }
#include <stdio.h> #include <string.h> #include <mpi.h> static void check_status_empty(MPI_Status status) { int count; int cancelled; MPI_Get_count(&status, MPI_INT, &count); MPI_Test_cancelled(&status, &cancelled); printf("returned source: %2d, expected source: %2d, result: %s\n", status.MPI_SOURCE, MPI_ANY_SOURCE, status.MPI_SOURCE == MPI_ANY_SOURCE ? "OK" : "NG"); printf("returned tag: %2d, expected tag: %2d, result: %s\n", status.MPI_TAG, MPI_ANY_TAG, status.MPI_TAG == MPI_ANY_TAG ? "OK" : "NG"); #if 0 /* No need to check. See 3.2.5 Return Status in MPI-3.0. */ printf("returned error: %2d, expected error: %2d, result: %s\n", status.MPI_ERROR, MPI_SUCCESS, status.MPI_ERROR == MPI_SUCCESS ? "OK" : "NG"); #endif printf("returned count: %2d, expected count: %2d, result: %s\n", count, 0, count == 0 ? "OK" : "NG"); printf("returned cancelled: %2d, expected cancelled: %2d, result: %s\n", cancelled, 0, cancelled == 0 ? "OK" : "NG"); } static void check_status_procnull(MPI_Status status) { int count; int cancelled; MPI_Get_count(&status, MPI_INT, &count); MPI_Test_cancelled(&status, &cancelled); printf("returned source: %2d, expected source: %2d, result: %s\n", status.MPI_SOURCE, MPI_PROC_NULL, status.MPI_SOURCE == MPI_PROC_NULL ? "OK" : "NG"); printf("returned tag: %2d, expected tag: %2d, result: %s\n", status.MPI_TAG, MPI_ANY_TAG, status.MPI_TAG == MPI_ANY_TAG ? "OK" : "NG"); printf("returned count: %2d, expected count: %2d, result: %s\n", count, 0, count == 0 ? "OK" : "NG"); } static void check_status_cancelled(MPI_Status status, int expected) { int cancelled; MPI_Test_cancelled(&status, &cancelled); printf("returned cancelled: %2d, expected cancelled: %2d, result: %s\n", cancelled, expected, cancelled == expected ? "OK" : "NG"); } static void check_count(int count, int expected) { printf("returned count: %6d, expected count: %6d, result: %s\n", count, expected, count == expected ? "OK" : "NG"); } static void check_index(int index, int expected) { printf("returned index: %6d, expected index: %6d, result: %s\n", index, expected, index == expected ? "OK" : "NG"); } static void check_completed(int completed, int expected) { printf("returned completed: %2d, expected completed: %2d, result: %s\n", completed, expected, completed == expected ? "OK" : "NG"); } static void clear_variables(MPI_Status *status, int *count, int *index, int *completed) { memset(status, 0xF0, sizeof(*status)); memset(count, 0xF0, sizeof(*count)); memset(index, 0xF0, sizeof(*index)); memset(completed, 0xF0, sizeof(*completed)); } int main(int argc, char *argv[]) { int my_rank; int buf; int count; int index; int completed; MPI_Request request; MPI_Status status; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); /* Test of MPI_Wait */ switch (my_rank) { case 0: printf("MPI_Wait for null request\n"); /* make a null request */ MPI_Irecv(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Wait(&request, &status); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Wait(&request, &status); check_status_empty(status); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Wait for inactive persistent request after MPI_Wait\n"); /* make a inactive request */ MPI_Recv_init(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Start(&request); MPI_Wait(&request, &status); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Wait(&request, &status); check_status_empty(status); MPI_Request_free(&request); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Wait for inactive persistent request after MPI_Waitany\n"); /* make a inactive request */ MPI_Recv_init(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Start(&request); MPI_Waitany(1, &request, &index, &status); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Wait(&request, &status); check_status_empty(status); MPI_Request_free(&request); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Wait for inactive persistent request after MPI_Waitall\n"); /* make a inactive request */ MPI_Recv_init(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Start(&request); MPI_Waitall(1, &request, &status); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Wait(&request, &status); check_status_empty(status); MPI_Request_free(&request); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Wait for inactive persistent request after MPI_Waitsome\n"); /* make a inactive request */ MPI_Recv_init(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Start(&request); MPI_Waitsome(1, &request, &count, &index, &status); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Wait(&request, &status); check_status_empty(status); MPI_Request_free(&request); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Wait for inactive persistent request after MPI_Test\n"); /* make a inactive request */ MPI_Recv_init(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Start(&request); do { MPI_Test(&request, &completed, &status); } while (completed == 0); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Wait(&request, &status); check_status_empty(status); MPI_Request_free(&request); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Wait for inactive persistent request after MPI_Testany\n"); /* make a inactive request */ MPI_Recv_init(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Start(&request); do { MPI_Testany(1, &request, &index, &completed, &status); } while (completed == 0); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Wait(&request, &status); check_status_empty(status); MPI_Request_free(&request); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Wait for inactive persistent request after MPI_Testall\n"); /* make a inactive request */ MPI_Recv_init(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Start(&request); do { MPI_Testall(1, &request, &completed, &status); } while (completed == 0); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Wait(&request, &status); check_status_empty(status); MPI_Request_free(&request); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Wait for inactive persistent request after MPI_Testsome\n"); /* make a inactive request */ MPI_Recv_init(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Start(&request); do { MPI_Testsome(1, &request, &count, &index, &status); } while (count == 0); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Wait(&request, &status); check_status_empty(status); MPI_Request_free(&request); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Wait for MPI_PROC_NULL\n"); /* make a request for MPI_PROC_NULL */ MPI_Irecv(&buf, 1, MPI_INT, MPI_PROC_NULL, 0, MPI_COMM_WORLD, &request); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Wait(&request, &status); check_status_procnull(status); check_status_cancelled(status, 0); break; } /* Test of MPI_Waitany */ switch (my_rank) { case 0: printf("MPI_Waitany for no requests\n"); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Waitany(0, NULL, &index, &status); check_status_empty(status); check_index(index, MPI_UNDEFINED); break; } switch (my_rank) { case 0: printf("MPI_Waitany for null request\n"); /* make a null request */ MPI_Irecv(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Waitany(1, &request, &index, &status); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Waitany(1, &request, &index, &status); check_status_empty(status); check_index(index, MPI_UNDEFINED); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Waitany for inactive persistent request\n"); /* make a inactive request */ MPI_Recv_init(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Start(&request); MPI_Waitany(1, &request, &index, &status); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Waitany(1, &request, &index, &status); check_status_empty(status); check_index(index, MPI_UNDEFINED); MPI_Request_free(&request); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Waitany for MPI_PROC_NULL\n"); /* make a request for MPI_PROC_NULL */ MPI_Irecv(&buf, 1, MPI_INT, MPI_PROC_NULL, 0, MPI_COMM_WORLD, &request); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Waitany(1, &request, &index, &status); check_status_procnull(status); check_status_cancelled(status, 0); check_index(index, 0); break; } /* Test of MPI_Waitall */ switch (my_rank) { case 0: printf("MPI_Waitall for no requests\n"); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Waitall(0, NULL, NULL); break; } switch (my_rank) { case 0: printf("MPI_Waitall for null request\n"); /* make a null request */ MPI_Irecv(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Waitall(1, &request, &status); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Waitall(1, &request, &status); check_status_empty(status); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Waitall for inactive persistent request\n"); /* make a inactive request */ MPI_Recv_init(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Start(&request); MPI_Waitall(1, &request, &status); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Waitall(1, &request, &status); check_status_empty(status); MPI_Request_free(&request); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Waitall for MPI_PROC_NULL\n"); /* make a request for MPI_PROC_NULL */ MPI_Irecv(&buf, 1, MPI_INT, MPI_PROC_NULL, 0, MPI_COMM_WORLD, &request); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Waitall(1, &request, &status); check_status_procnull(status); check_status_cancelled(status, 0); break; } /* Test of MPI_Waitsome */ switch (my_rank) { case 0: printf("MPI_Waitsome for no requests\n"); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Waitsome(0, NULL, &count, NULL, NULL); check_count(count, MPI_UNDEFINED); break; } switch (my_rank) { case 0: printf("MPI_Waitsome for null request\n"); /* make a null request */ MPI_Irecv(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Waitsome(1, &request, &count, &index, &status); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Waitsome(1, &request, &count, &index, &status); check_count(count, MPI_UNDEFINED); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Waitsome for inactive persistent request\n"); /* make a inactive request */ MPI_Recv_init(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Start(&request); MPI_Waitsome(1, &request, &count, &index, &status); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Waitsome(1, &request, &count, &index, &status); check_count(count, MPI_UNDEFINED); MPI_Request_free(&request); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Waitsome for MPI_PROC_NULL\n"); /* make a request for MPI_PROC_NULL */ MPI_Irecv(&buf, 1, MPI_INT, MPI_PROC_NULL, 0, MPI_COMM_WORLD, &request); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Waitsome(1, &request, &count, &index, &status); check_status_procnull(status); check_status_cancelled(status, 0); check_index(index, 0); check_count(count, 1); break; } /* Test of MPI_Test */ switch (my_rank) { case 0: printf("MPI_Test for null request\n"); /* make a null request */ MPI_Irecv(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); do { MPI_Test(&request, &completed, &status); } while (completed == 0); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Test(&request, &completed, &status); check_status_empty(status); check_completed(completed, 1); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Test for inactive persistent request\n"); /* make a inactive request */ MPI_Recv_init(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Start(&request); do { MPI_Test(&request, &completed, &status); } while (completed == 0); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Test(&request, &completed, &status); check_status_empty(status); check_completed(completed, 1); MPI_Request_free(&request); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Test for MPI_PROC_NULL\n"); /* make a request for MPI_PROC_NULL */ MPI_Irecv(&buf, 1, MPI_INT, MPI_PROC_NULL, 0, MPI_COMM_WORLD, &request); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Test(&request, &completed, &status); check_status_procnull(status); check_status_cancelled(status, 0); check_completed(completed, 1); break; } /* Test of MPI_Testany */ switch (my_rank) { case 0: printf("MPI_Testany for no requests\n"); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Testany(0, NULL, &index, &completed, &status); check_status_empty(status); check_index(index, MPI_UNDEFINED); check_completed(completed, 1); break; } switch (my_rank) { case 0: printf("MPI_Testany for null request\n"); /* make a null request */ MPI_Irecv(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); do { MPI_Testany(1, &request, &index, &completed, &status); } while (completed == 0); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Testany(1, &request, &index, &completed, &status); check_status_empty(status); check_index(index, MPI_UNDEFINED); check_completed(completed, 1); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Testany for inactive persistent request\n"); /* make a inactive request */ MPI_Recv_init(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Start(&request); do { MPI_Testany(1, &request, &index, &completed, &status); } while (completed == 0); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Testany(1, &request, &index, &completed, &status); check_status_empty(status); check_index(index, MPI_UNDEFINED); check_completed(completed, 1); MPI_Request_free(&request); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Testany for MPI_PROC_NULL\n"); /* make a request for MPI_PROC_NULL */ MPI_Irecv(&buf, 1, MPI_INT, MPI_PROC_NULL, 0, MPI_COMM_WORLD, &request); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Testany(1, &request, &index, &completed, &status); check_status_procnull(status); check_status_cancelled(status, 0); check_index(index, 0); check_completed(completed, 1); break; } /* Test of MPI_Testall */ switch (my_rank) { case 0: printf("MPI_Testall for no requests\n"); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Testall(0, NULL, &completed, NULL); check_completed(completed, 1); break; } switch (my_rank) { case 0: printf("MPI_Testall for null request\n"); /* make a null request */ MPI_Irecv(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); do { MPI_Testall(1, &request, &completed, &status); } while (completed == 0); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Testall(1, &request, &completed, &status); check_status_empty(status); check_completed(completed, 1); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Testall for inactive persistent request\n"); /* make a inactive request */ MPI_Recv_init(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Start(&request); do { MPI_Testall(1, &request, &completed, &status); } while (completed == 0); MPI_Wait(&request, &status); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Testall(1, &request, &completed, &status); check_status_empty(status); check_completed(completed, 1); MPI_Request_free(&request); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Testall for MPI_PROC_NULL\n"); /* make a request for MPI_PROC_NULL */ MPI_Irecv(&buf, 1, MPI_INT, MPI_PROC_NULL, 0, MPI_COMM_WORLD, &request); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Testall(1, &request, &completed, &status); check_status_procnull(status); check_status_cancelled(status, 0); check_completed(completed, 1); break; } /* Test of MPI_Testsome */ switch (my_rank) { case 0: printf("MPI_Testsome for no requests\n"); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Testsome(0, NULL, &count, NULL, NULL); check_count(count, MPI_UNDEFINED); break; } switch (my_rank) { case 0: printf("MPI_Testsome for null request\n"); /* make a null request */ MPI_Irecv(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); do { MPI_Testsome(1, &request, &count, &index, &status); } while (count == 0); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Testsome(1, &request, &count, &index, &status); check_count(count, MPI_UNDEFINED); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Testsome for inactive persistent request\n"); /* make a inactive request */ MPI_Recv_init(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Start(&request); do { MPI_Testsome(1, &request, &count, &index, &status); } while (count == 0); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Testsome(1, &request, &count, &index, &status); check_count(count, MPI_UNDEFINED); MPI_Request_free(&request); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Testsome for MPI_PROC_NULL\n"); /* make a request for MPI_PROC_NULL */ MPI_Irecv(&buf, 1, MPI_INT, MPI_PROC_NULL, 0, MPI_COMM_WORLD, &request); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Testsome(1, &request, &count, &index, &status); check_status_procnull(status); check_status_cancelled(status, 0); check_index(index, 0); check_count(count, 1); break; } /* Test of MPI_Request_get_status */ switch (my_rank) { case 0: printf("MPI_Request_get_status for null request\n"); /* make a null request */ MPI_Irecv(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Wait(&request, &status); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Request_get_status(request, &completed, &status); check_status_empty(status); check_completed(completed, 1); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Request_get_status for inactive persistent request after MPI_Wait\n"); /* make a inactive request */ MPI_Recv_init(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Start(&request); MPI_Wait(&request, &status); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Request_get_status(request, &completed, &status); check_status_empty(status); check_completed(completed, 1); MPI_Request_free(&request); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Request_get_status for inactive persistent request after MPI_Waitany\n"); /* make a inactive request */ MPI_Recv_init(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Start(&request); MPI_Waitany(1, &request, &index, &status); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Request_get_status(request, &completed, &status); check_status_empty(status); check_completed(completed, 1); MPI_Request_free(&request); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Request_get_status for inactive persistent request after MPI_Waitall\n"); /* make a inactive request */ MPI_Recv_init(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Start(&request); MPI_Waitall(1, &request, &status); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Request_get_status(request, &completed, &status); check_status_empty(status); check_completed(completed, 1); MPI_Request_free(&request); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Request_get_status for inactive persistent request after MPI_Waitsome\n"); /* make a inactive request */ MPI_Recv_init(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Start(&request); MPI_Waitsome(1, &request, &count, &index, &status); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Request_get_status(request, &completed, &status); check_status_empty(status); check_completed(completed, 1); MPI_Request_free(&request); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Request_get_status for inactive persistent request after MPI_Test\n"); /* make a inactive request */ MPI_Recv_init(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Start(&request); do { MPI_Test(&request, &completed, &status); } while (completed == 0); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Request_get_status(request, &completed, &status); check_status_empty(status); check_completed(completed, 1); MPI_Request_free(&request); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Request_get_status for inactive persistent request after MPI_Testany\n"); /* make a inactive request */ MPI_Recv_init(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Start(&request); do { MPI_Testany(1, &request, &index, &completed, &status); } while (completed == 0); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Request_get_status(request, &completed, &status); check_status_empty(status); check_completed(completed, 1); MPI_Request_free(&request); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Request_get_status for inactive persistent request after MPI_Testall\n"); /* make a inactive request */ MPI_Recv_init(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Start(&request); do { MPI_Testall(1, &request, &completed, &status); } while (completed == 0); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Request_get_status(request, &completed, &status); check_status_empty(status); check_completed(completed, 1); MPI_Request_free(&request); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } switch (my_rank) { case 0: printf("MPI_Request_get_status for inactive persistent request after MPI_Testsome\n"); /* make a inactive request */ MPI_Recv_init(&buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Start(&request); do { MPI_Testsome(1, &request, &count, &index, &status); } while (count == 0); /* test */ clear_variables(&status, &count, &index, &completed); MPI_Request_get_status(request, &completed, &status); check_status_empty(status); check_completed(completed, 1); MPI_Request_free(&request); break; case 1: MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); break; } MPI_Finalize(); return 0; }
Copyright (c) 2012 FUJITSU LIMITED. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer listed in this license in the documentation and/or other materials provided with the distribution. * Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. The copyright holders provide no reassurances that the source code provided does not infringe any patent, copyright, or any other intellectual property rights of third parties. The copyright holders disclaim any liability to any recipient for claims brought against recipient by any third party for infringement of that parties intellectual property rights. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.