1 /*
2  * Copyright (C) by Argonne National Laboratory
3  *     See COPYRIGHT in top-level directory
4  */
5 
6 #include "mpidimpl.h"
7 
MPID_Imrecv(void * buf,int count,MPI_Datatype datatype,MPIR_Request * message,MPIR_Request ** rreqp)8 int MPID_Imrecv(void *buf, int count, MPI_Datatype datatype,
9                 MPIR_Request *message, MPIR_Request **rreqp)
10 {
11     int mpi_errno = MPI_SUCCESS;
12     MPIR_Request *rreq;
13     MPIR_Comm *comm;
14     MPIDI_VC_t *vc = NULL;
15 
16     /* message==NULL is equivalent to MPI_MESSAGE_NO_PROC being passed at the
17      * upper level */
18     if (message == NULL)
19     {
20         *rreqp = MPIR_Request_create_null_recv();
21         goto fn_exit;
22     }
23 
24     MPIR_Assert(message != NULL);
25     MPIR_Assert(message->kind == MPIR_REQUEST_KIND__MPROBE);
26 
27     /* promote the request object to be a "real" recv request */
28     message->kind = MPIR_REQUEST_KIND__RECV;
29 
30     *rreqp = rreq = message;
31 
32     comm = rreq->comm;
33 
34     /* the following code was adapted from FDU_or_AEP and MPID_Irecv */
35     /* comm was already added at FDU (mprobe) time */
36     rreq->dev.user_buf = buf;
37     rreq->dev.user_count = count;
38     rreq->dev.datatype = datatype;
39 
40 #ifdef ENABLE_COMM_OVERRIDES
41     MPIDI_Comm_get_vc(comm, rreq->status.MPI_SOURCE, &vc);
42     if (vc->comm_ops && vc->comm_ops->imrecv) {
43         MPID_THREAD_CS_ENTER(POBJ, vc->pobj_mutex);
44         vc->comm_ops->imrecv(vc, rreq);
45         MPID_THREAD_CS_EXIT(POBJ, vc->pobj_mutex);
46         goto fn_exit;
47     }
48 #endif
49 
50     if (MPIDI_Request_get_msg_type(rreq) == MPIDI_REQUEST_EAGER_MSG)
51     {
52         int recv_pending;
53 
54         /* This is an eager message */
55         MPL_DBG_MSG(MPIDI_CH3_DBG_OTHER,VERBOSE,"eager message in the request");
56 
57         /* If this is an eager synchronous message, then we need to send an
58            acknowledgement back to the sender. */
59         if (MPIDI_Request_get_sync_send_flag(rreq))
60         {
61             MPIDI_Comm_get_vc_set_active(comm, rreq->dev.match.parts.rank, &vc);
62             mpi_errno = MPIDI_CH3_EagerSyncAck(vc, rreq);
63             MPIR_ERR_CHECK(mpi_errno);
64         }
65 
66         /* the request was found in the unexpected queue, so it has a
67            recv_pending_count of at least 1 */
68         MPIDI_Request_decr_pending(rreq);
69         MPIDI_Request_check_pending(rreq, &recv_pending);
70 
71         if (MPIR_Request_is_complete(rreq)) {
72             /* is it ever possible to have (cc==0 && recv_pending>0) ? */
73             MPIR_Assert(!recv_pending);
74 
75             /* All of the data has arrived, we need to copy the data and
76                then free the buffer. */
77             if (rreq->dev.recv_data_sz > 0)
78             {
79                 MPIDI_CH3U_Request_unpack_uebuf(rreq);
80                 MPL_free(rreq->dev.tmpbuf);
81             }
82 
83             mpi_errno = rreq->status.MPI_ERROR;
84             MPIR_ERR_CHECK(mpi_errno);
85             goto fn_exit;
86         }
87         else
88         {
89             /* there should never be outstanding completion events for an unexpected
90              * recv without also having a "pending recv" */
91             MPIR_Assert(recv_pending);
92             /* The data is still being transfered across the net.  We'll
93                leave it to the progress engine to handle once the
94                entire message has arrived. */
95             if (!HANDLE_IS_BUILTIN(datatype))
96             {
97                 MPIR_Datatype_get_ptr(datatype, rreq->dev.datatype_ptr);
98                 MPIR_Datatype_ptr_add_ref(rreq->dev.datatype_ptr);
99             }
100 
101         }
102     }
103     else if (MPIDI_Request_get_msg_type(rreq) == MPIDI_REQUEST_RNDV_MSG)
104     {
105         MPIDI_Comm_get_vc_set_active(comm, rreq->dev.match.parts.rank, &vc);
106 
107         mpi_errno = vc->rndvRecv_fn(vc, rreq);
108         MPIR_ERR_CHECK(mpi_errno);
109         if (!HANDLE_IS_BUILTIN(datatype))
110         {
111             MPIR_Datatype_get_ptr(datatype, rreq->dev.datatype_ptr);
112             MPIR_Datatype_ptr_add_ref(rreq->dev.datatype_ptr);
113         }
114     }
115     else if (MPIDI_Request_get_msg_type(rreq) == MPIDI_REQUEST_SELF_MSG)
116     {
117         mpi_errno = MPIDI_CH3_RecvFromSelf(rreq, buf, count, datatype);
118         MPIR_ERR_CHECK(mpi_errno);
119     }
120     else
121     {
122         /* --BEGIN ERROR HANDLING-- */
123 #ifdef HAVE_ERROR_CHECKING
124         int msg_type = MPIDI_Request_get_msg_type(rreq);
125 #endif
126         MPIR_Request_free(rreq);
127         rreq = NULL;
128         MPIR_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_INTERN, "**ch3|badmsgtype",
129                              "**ch3|badmsgtype %d", msg_type);
130         /* --END ERROR HANDLING-- */
131     }
132 
133 fn_exit:
134     return mpi_errno;
135 fn_fail:
136     MPIR_Request_free(rreq);
137     rreq = NULL;
138     goto fn_exit;
139 }
140 
141