1 /*
2 * Copyright (C) by Argonne National Laboratory
3 * See COPYRIGHT in top-level directory
4 */
5
6 #include "mpidimpl.h"
7
MPID_Irecv(void * buf,MPI_Aint count,MPI_Datatype datatype,int rank,int tag,MPIR_Comm * comm,int context_offset,MPIR_Request ** request)8 int MPID_Irecv(void * buf, MPI_Aint count, MPI_Datatype datatype, int rank, int tag,
9 MPIR_Comm * comm, int context_offset,
10 MPIR_Request ** request)
11 {
12 MPIR_Request * rreq = NULL;
13 int found;
14 int mpi_errno = MPI_SUCCESS;
15 MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPID_IRECV);
16
17 MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPID_IRECV);
18
19 MPL_DBG_MSG_FMT(MPIDI_CH3_DBG_OTHER,VERBOSE,(MPL_DBG_FDEST,
20 "rank=%d, tag=%d, context=%d",
21 rank, tag, comm->recvcontext_id + context_offset));
22
23 /* Check to make sure the communicator hasn't already been revoked */
24 if (comm->revoked &&
25 MPIR_AGREE_TAG != MPIR_TAG_MASK_ERROR_BITS(tag & ~MPIR_TAG_COLL_BIT) &&
26 MPIR_SHRINK_TAG != MPIR_TAG_MASK_ERROR_BITS(tag & ~MPIR_TAG_COLL_BIT)) {
27 MPL_DBG_MSG(MPIDI_CH3_DBG_OTHER,VERBOSE,"Comm has been revoked. Returning from MPID_IRECV.");
28 MPIR_ERR_SETANDJUMP(mpi_errno,MPIX_ERR_REVOKED,"**revoked");
29 }
30
31 MPID_THREAD_CS_ENTER(POBJ, MPIR_THREAD_POBJ_MSGQ_MUTEX);
32 rreq = MPIDI_CH3U_Recvq_FDU_or_AEP(rank, tag,
33 comm->recvcontext_id + context_offset,
34 comm, buf, count, datatype, &found);
35 if (rreq == NULL)
36 {
37 MPID_THREAD_CS_EXIT(POBJ, MPIR_THREAD_POBJ_MSGQ_MUTEX);
38 MPIR_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER,"**nomemreq");
39 }
40
41 if (found)
42 {
43 MPIDI_VC_t * vc;
44
45 /* Message was found in the unexepected queue */
46 MPL_DBG_MSG(MPIDI_CH3_DBG_OTHER,VERBOSE,"request found in unexpected queue");
47
48 /* Release the message queue - we've removed this request from
49 the queue already */
50 MPID_THREAD_CS_EXIT(POBJ, MPIR_THREAD_POBJ_MSGQ_MUTEX);
51
52 if (MPIDI_Request_get_msg_type(rreq) == MPIDI_REQUEST_EAGER_MSG)
53 {
54 int recv_pending;
55
56 /* This is an eager message */
57 MPL_DBG_MSG(MPIDI_CH3_DBG_OTHER,VERBOSE,"eager message in the request");
58
59 /* If this is a eager synchronous message, then we need to send an
60 acknowledgement back to the sender. */
61 if (MPIDI_Request_get_sync_send_flag(rreq))
62 {
63 MPIDI_Comm_get_vc_set_active(comm, rreq->dev.match.parts.rank, &vc);
64 mpi_errno = MPIDI_CH3_EagerSyncAck( vc, rreq );
65 MPIR_ERR_CHECK(mpi_errno);
66 }
67
68 /* the request was found in the unexpected queue, so it has a
69 recv_pending_count of at least 1 */
70 MPIDI_Request_decr_pending(rreq);
71 MPIDI_Request_check_pending(rreq, &recv_pending);
72
73 if (MPIR_Request_is_complete(rreq)) {
74 /* is it ever possible to have (cc==0 && recv_pending>0) ? */
75 MPIR_Assert(!recv_pending);
76
77 /* All of the data has arrived, we need to copy the data and
78 then free the buffer. */
79 if (rreq->dev.recv_data_sz > 0)
80 {
81 MPIDI_CH3U_Request_unpack_uebuf(rreq);
82 MPL_free(rreq->dev.tmpbuf);
83 }
84
85 mpi_errno = rreq->status.MPI_ERROR;
86 goto fn_exit;
87 }
88 else
89 {
90 /* there should never be outstanding completion events for an unexpected
91 * recv without also having a "pending recv" */
92 MPIR_Assert(recv_pending);
93 /* The data is still being transfered across the net. We'll
94 leave it to the progress engine to handle once the
95 entire message has arrived. */
96 if (!HANDLE_IS_BUILTIN(datatype))
97 {
98 MPIR_Datatype_get_ptr(datatype, rreq->dev.datatype_ptr);
99 MPIR_Datatype_ptr_add_ref(rreq->dev.datatype_ptr);
100 }
101
102 }
103 }
104 else if (MPIDI_Request_get_msg_type(rreq) == MPIDI_REQUEST_RNDV_MSG)
105 {
106 MPIDI_Comm_get_vc_set_active(comm, rreq->dev.match.parts.rank, &vc);
107
108 mpi_errno = vc->rndvRecv_fn( vc, rreq );
109 if (mpi_errno) MPIR_ERR_POP( mpi_errno );
110 if (!HANDLE_IS_BUILTIN(datatype))
111 {
112 MPIR_Datatype_get_ptr(datatype, rreq->dev.datatype_ptr);
113 MPIR_Datatype_ptr_add_ref(rreq->dev.datatype_ptr);
114 }
115 }
116 else if (MPIDI_Request_get_msg_type(rreq) == MPIDI_REQUEST_SELF_MSG)
117 {
118 mpi_errno = MPIDI_CH3_RecvFromSelf( rreq, buf, count, datatype );
119 MPIR_ERR_CHECK(mpi_errno);
120 }
121 else
122 {
123 /* --BEGIN ERROR HANDLING-- */
124 #ifdef HAVE_ERROR_CHECKING
125 int msg_type = MPIDI_Request_get_msg_type(rreq);
126 #endif
127 MPIR_Request_free(rreq);
128 rreq = NULL;
129 MPIR_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_INTERN, "**ch3|badmsgtype",
130 "**ch3|badmsgtype %d", msg_type);
131 /* --END ERROR HANDLING-- */
132 }
133 }
134 else
135 {
136 /* Message has yet to arrived. The request has been placed on the
137 list of posted receive requests and populated with
138 information supplied in the arguments. */
139 MPL_DBG_MSG(MPIDI_CH3_DBG_OTHER,VERBOSE,"request allocated in posted queue");
140
141 if (!HANDLE_IS_BUILTIN(datatype))
142 {
143 MPIR_Datatype_get_ptr(datatype, rreq->dev.datatype_ptr);
144 MPIR_Datatype_ptr_add_ref(rreq->dev.datatype_ptr);
145 }
146
147 rreq->dev.recv_pending_count = 1;
148
149 /* We must wait until here to exit the msgqueue critical section
150 on this request (we needed to set the recv_pending_count
151 and the datatype pointer) */
152 MPID_THREAD_CS_EXIT(POBJ, MPIR_THREAD_POBJ_MSGQ_MUTEX);
153 }
154
155 fn_exit:
156 *request = rreq;
157 MPL_DBG_MSG_P(MPIDI_CH3_DBG_OTHER,VERBOSE,"request allocated, handle=0x%08x",
158 rreq->handle);
159 MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPID_IRECV);
160 return mpi_errno;
161
162 fn_fail:
163 MPL_DBG_MSG_D(MPIDI_CH3_DBG_OTHER,VERBOSE,"IRECV errno: 0x%08x", mpi_errno);
164 MPL_DBG_MSG_D(MPIDI_CH3_DBG_OTHER,VERBOSE,"(class: %d)", MPIR_ERR_GET_CLASS(mpi_errno));
165 goto fn_exit;
166 }
167