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