From efbf926308f287dd0edcff8794a346b85aac39e2 Mon Sep 17 00:00:00 2001 From: KAWASHIMA Takahiro Date: Thu, 8 Dec 2016 21:42:05 +0900 Subject: [PATCH] ompi/request: Fix a persistent request creation bug According to the MPI-3.1 p.52 and p.53 (cited below), a request created by `MPI_*_INIT` but not yet started by `MPI_START` or `MPI_STARTALL` is inactive therefore `MPI_WAIT` or its friends must return immediately if such a request is passed. The current implementation hangs in `MPI_WAIT` and its friends in such case because a persistent request is initialized as `req_complete = REQUEST_PENDING`. This commit fixes the initialization. Also, this commit fixes internal requests used in `MPI_PROBE` and `MPI_IPROBE` which was marked wrongly as persistent. MPI-3.1 p.52: We shall use the following terminology: A null handle is a handle with value MPI_REQUEST_NULL. A persistent request and the handle to it are inactive if the request is not associated with any ongoing communication (see Section 3.9). A handle is active if it is neither null nor inactive. An empty status is a status which is set to return tag = MPI_ANY_TAG, source = MPI_ANY_SOURCE, error = MPI_SUCCESS, and is also internally configured so that calls to MPI_GET_COUNT, MPI_GET_ELEMENTS, and MPI_GET_ELEMENTS_X return count = 0 and MPI_TEST_CANCELLED returns false. We set a status variable to empty when the value returned by it is not significant. Status is set in this way so as to prevent errors due to accesses of stale information. MPI-3.1 p.53: One is allowed to call MPI_WAIT with a null or inactive request argument. In this case the operation returns immediately with empty status. Signed-off-by: KAWASHIMA Takahiro (back-ported from commit 6510800c1642a9b459dadb2720ae57df9fbea934) --- ompi/mca/pml/ob1/pml_ob1_iprobe.c | 4 ++-- ompi/request/request.h | 15 ++++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/ompi/mca/pml/ob1/pml_ob1_iprobe.c b/ompi/mca/pml/ob1/pml_ob1_iprobe.c index 4a952f462dc..914474c6668 100644 --- a/ompi/mca/pml/ob1/pml_ob1_iprobe.c +++ b/ompi/mca/pml/ob1/pml_ob1_iprobe.c @@ -36,7 +36,7 @@ int mca_pml_ob1_iprobe(int src, recvreq.req_recv.req_base.req_ompi.req_type = OMPI_REQUEST_PML; recvreq.req_recv.req_base.req_type = MCA_PML_REQUEST_IPROBE; - MCA_PML_OB1_RECV_REQUEST_INIT(&recvreq, NULL, 0, &ompi_mpi_char.dt, src, tag, comm, true); + MCA_PML_OB1_RECV_REQUEST_INIT(&recvreq, NULL, 0, &ompi_mpi_char.dt, src, tag, comm, false); MCA_PML_OB1_RECV_REQUEST_START(&recvreq); if( REQUEST_COMPLETE( &(recvreq.req_recv.req_base.req_ompi)) ) { @@ -66,7 +66,7 @@ int mca_pml_ob1_probe(int src, recvreq.req_recv.req_base.req_ompi.req_type = OMPI_REQUEST_PML; recvreq.req_recv.req_base.req_type = MCA_PML_REQUEST_PROBE; - MCA_PML_OB1_RECV_REQUEST_INIT(&recvreq, NULL, 0, &ompi_mpi_char.dt, src, tag, comm, true); + MCA_PML_OB1_RECV_REQUEST_INIT(&recvreq, NULL, 0, &ompi_mpi_char.dt, src, tag, comm, false); MCA_PML_OB1_RECV_REQUEST_START(&recvreq); ompi_request_wait_completion(&recvreq.req_recv.req_base.req_ompi); diff --git a/ompi/request/request.h b/ompi/request/request.h index e94fa11c75c..aaac0df912b 100644 --- a/ompi/request/request.h +++ b/ompi/request/request.h @@ -142,13 +142,14 @@ typedef struct ompi_predefined_request_t ompi_predefined_request_t; * performance path (since requests may be re-used, it is possible * that we will have to initialize a request multiple times). */ -#define OMPI_REQUEST_INIT(request, persistent) \ - do { \ - (request)->req_complete = REQUEST_PENDING; \ - (request)->req_state = OMPI_REQUEST_INACTIVE; \ - (request)->req_persistent = (persistent); \ - (request)->req_complete_cb = NULL; \ - (request)->req_complete_cb_data = NULL; \ +#define OMPI_REQUEST_INIT(request, persistent) \ + do { \ + (request)->req_complete = \ + (persistent) ? REQUEST_COMPLETED : REQUEST_PENDING; \ + (request)->req_state = OMPI_REQUEST_INACTIVE; \ + (request)->req_persistent = (persistent); \ + (request)->req_complete_cb = NULL; \ + (request)->req_complete_cb_data = NULL; \ } while (0);