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