1 /*
2 * Copyright (C) by Argonne National Laboratory
3 * See COPYRIGHT in top-level directory
4 */
5
6 #include "mpidimpl.h"
7
8 /* FIXME: Consider using function pointers for invoking persistent requests;
9 if we made those part of the public request structure, the top-level routine
10 could implement startall unless the device wanted to study the requests
11 and reorder them */
12
13 /* FIXME: Where is the memory registration call in the init routines,
14 in case the channel wishes to take special action (such as pinning for DMA)
15 the memory? This was part of the design. */
16
17 /* This macro initializes all of the fields in a persistent request */
18 #define MPIDI_Request_create_psreq(sreq_, mpi_errno_, FAIL_) \
19 { \
20 (sreq_) = MPIR_Request_create(MPIR_REQUEST_KIND__PREQUEST_SEND); \
21 if ((sreq_) == NULL) \
22 { \
23 MPL_DBG_MSG(MPIDI_CH3_DBG_OTHER,VERBOSE,"send request allocation failed");\
24 (mpi_errno_) = MPIR_ERR_MEMALLOCFAILED; \
25 FAIL_; \
26 } \
27 \
28 MPIR_Object_set_ref((sreq_), 1); \
29 MPIR_cc_set(&(sreq_)->cc, 0); \
30 (sreq_)->comm = comm; \
31 MPIR_Comm_add_ref(comm); \
32 (sreq_)->dev.match.parts.rank = rank; \
33 (sreq_)->dev.match.parts.tag = tag; \
34 (sreq_)->dev.match.parts.context_id = comm->context_id + context_offset; \
35 (sreq_)->dev.user_buf = (void *) buf; \
36 (sreq_)->dev.user_count = count; \
37 (sreq_)->dev.datatype = datatype; \
38 (sreq_)->u.persist.real_request = NULL; \
39 }
40
41
42 /*
43 * MPID_Startall()
44 */
MPID_Startall(int count,MPIR_Request * requests[])45 int MPID_Startall(int count, MPIR_Request * requests[])
46 {
47 int i;
48 int rc;
49 int mpi_errno = MPI_SUCCESS;
50 MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPID_STARTALL);
51
52 MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPID_STARTALL);
53
54 for (i = 0; i < count; i++)
55 {
56 MPIR_Request * const preq = requests[i];
57
58 /* continue if the source/dest is MPI_PROC_NULL */
59 if (preq->dev.match.parts.rank == MPI_PROC_NULL)
60 continue;
61
62 /* FIXME: The odd 7th arg (match.context_id - comm->context_id)
63 is probably to get the context offset. Do we really need the
64 context offset? Is there any case where the offset isn't zero? */
65 switch (MPIDI_Request_get_type(preq))
66 {
67 case MPIDI_REQUEST_TYPE_RECV:
68 {
69 rc = MPID_Irecv(preq->dev.user_buf, preq->dev.user_count, preq->dev.datatype, preq->dev.match.parts.rank,
70 preq->dev.match.parts.tag, preq->comm, preq->dev.match.parts.context_id - preq->comm->recvcontext_id,
71 &preq->u.persist.real_request);
72 break;
73 }
74
75 case MPIDI_REQUEST_TYPE_SEND:
76 {
77 rc = MPID_Isend(preq->dev.user_buf, preq->dev.user_count, preq->dev.datatype, preq->dev.match.parts.rank,
78 preq->dev.match.parts.tag, preq->comm, preq->dev.match.parts.context_id - preq->comm->context_id,
79 &preq->u.persist.real_request);
80 break;
81 }
82
83 case MPIDI_REQUEST_TYPE_RSEND:
84 {
85 rc = MPID_Irsend(preq->dev.user_buf, preq->dev.user_count, preq->dev.datatype, preq->dev.match.parts.rank,
86 preq->dev.match.parts.tag, preq->comm, preq->dev.match.parts.context_id - preq->comm->context_id,
87 &preq->u.persist.real_request);
88 break;
89 }
90
91 case MPIDI_REQUEST_TYPE_SSEND:
92 {
93 rc = MPID_Issend(preq->dev.user_buf, preq->dev.user_count, preq->dev.datatype, preq->dev.match.parts.rank,
94 preq->dev.match.parts.tag, preq->comm, preq->dev.match.parts.context_id - preq->comm->context_id,
95 &preq->u.persist.real_request);
96 break;
97 }
98
99 case MPIDI_REQUEST_TYPE_BSEND:
100 {
101 rc = MPIR_Bsend_isend(preq->dev.user_buf, preq->dev.user_count,
102 preq->dev.datatype, preq->dev.match.parts.rank,
103 preq->dev.match.parts.tag, preq->comm,
104 &preq->u.persist.real_request);
105 if (rc == MPI_SUCCESS) {
106 preq->status.MPI_ERROR = MPI_SUCCESS;
107 preq->cc_ptr = &preq->cc;
108 /* bsend is local-complete */
109 MPIR_cc_set(preq->cc_ptr, 0);
110 goto fn_exit;
111 }
112 break;
113 }
114
115 default:
116 {
117 /* --BEGIN ERROR HANDLING-- */
118 rc = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_FATAL, __func__, __LINE__, MPI_ERR_INTERN, "**ch3|badreqtype",
119 "**ch3|badreqtype %d", MPIDI_Request_get_type(preq));
120 /* --END ERROR HANDLING-- */
121 }
122 }
123
124 if (rc == MPI_SUCCESS)
125 {
126 preq->status.MPI_ERROR = MPI_SUCCESS;
127 preq->cc_ptr = &preq->u.persist.real_request->cc;
128 }
129 /* --BEGIN ERROR HANDLING-- */
130 else
131 {
132 /* If a failure occurs attempting to start the request, then we
133 assume that partner request was not created, and stuff
134 the error code in the persistent request. The wait and test
135 routines will look at the error code in the persistent
136 request if a partner request is not present. */
137 preq->u.persist.real_request = NULL;
138 preq->status.MPI_ERROR = rc;
139 preq->cc_ptr = &preq->cc;
140 MPIR_cc_set(&preq->cc, 0);
141 }
142 /* --END ERROR HANDLING-- */
143 }
144
145 fn_exit:
146 MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPID_STARTALL);
147 return mpi_errno;
148 }
149
150 /* FIXME:
151 Move the routines that initialize the persistent requests into this file,
152 since startall must be used with all of them */
153
154 /*
155 * MPID_Send_init()
156 */
MPID_Send_init(const void * buf,int count,MPI_Datatype datatype,int rank,int tag,MPIR_Comm * comm,int context_offset,MPIR_Request ** request)157 int MPID_Send_init(const void * buf, int count, MPI_Datatype datatype, int rank, int tag, MPIR_Comm * comm, int context_offset,
158 MPIR_Request ** request)
159 {
160 MPIR_Request * sreq;
161 int mpi_errno = MPI_SUCCESS;
162 MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPID_SEND_INIT);
163
164 MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPID_SEND_INIT);
165
166 MPIDI_Request_create_psreq(sreq, mpi_errno, goto fn_exit);
167 MPIDI_Request_set_type(sreq, MPIDI_REQUEST_TYPE_SEND);
168 if (!HANDLE_IS_BUILTIN(datatype))
169 {
170 MPIR_Datatype_get_ptr(datatype, sreq->dev.datatype_ptr);
171 MPIR_Datatype_ptr_add_ref(sreq->dev.datatype_ptr);
172 }
173 *request = sreq;
174
175 fn_exit:
176 MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPID_SEND_INIT);
177 return mpi_errno;
178 }
179
180 /*
181 * MPID_Ssend_init()
182 */
MPID_Ssend_init(const void * buf,int count,MPI_Datatype datatype,int rank,int tag,MPIR_Comm * comm,int context_offset,MPIR_Request ** request)183 int MPID_Ssend_init(const void * buf, int count, MPI_Datatype datatype, int rank, int tag, MPIR_Comm * comm, int context_offset,
184 MPIR_Request ** request)
185 {
186 MPIR_Request * sreq;
187 int mpi_errno = MPI_SUCCESS;
188 MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPID_SSEND_INIT);
189
190 MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPID_SSEND_INIT);
191
192 MPIDI_Request_create_psreq(sreq, mpi_errno, goto fn_exit);
193 MPIDI_Request_set_type(sreq, MPIDI_REQUEST_TYPE_SSEND);
194 if (!HANDLE_IS_BUILTIN(datatype))
195 {
196 MPIR_Datatype_get_ptr(datatype, sreq->dev.datatype_ptr);
197 MPIR_Datatype_ptr_add_ref(sreq->dev.datatype_ptr);
198 }
199 *request = sreq;
200
201 fn_exit:
202 MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPID_SSEND_INIT);
203 return mpi_errno;
204 }
205
206 /*
207 * MPID_Rsend_init()
208 */
MPID_Rsend_init(const void * buf,int count,MPI_Datatype datatype,int rank,int tag,MPIR_Comm * comm,int context_offset,MPIR_Request ** request)209 int MPID_Rsend_init(const void * buf, int count, MPI_Datatype datatype, int rank, int tag, MPIR_Comm * comm, int context_offset,
210 MPIR_Request ** request)
211 {
212 MPIR_Request * sreq;
213 int mpi_errno = MPI_SUCCESS;
214 MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPID_RSEND_INIT);
215
216 MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPID_RSEND_INIT);
217
218 MPIDI_Request_create_psreq(sreq, mpi_errno, goto fn_exit);
219 MPIDI_Request_set_type(sreq, MPIDI_REQUEST_TYPE_RSEND);
220 if (!HANDLE_IS_BUILTIN(datatype))
221 {
222 MPIR_Datatype_get_ptr(datatype, sreq->dev.datatype_ptr);
223 MPIR_Datatype_ptr_add_ref(sreq->dev.datatype_ptr);
224 }
225 *request = sreq;
226
227 fn_exit:
228 MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPID_RSEND_INIT);
229 return mpi_errno;
230 }
231
232 /*
233 * MPID_Bsend_init()
234 */
MPID_Bsend_init(const void * buf,int count,MPI_Datatype datatype,int rank,int tag,MPIR_Comm * comm,int context_offset,MPIR_Request ** request)235 int MPID_Bsend_init(const void * buf, int count, MPI_Datatype datatype, int rank, int tag, MPIR_Comm * comm, int context_offset,
236 MPIR_Request ** request)
237 {
238 MPIR_Request * sreq;
239 int mpi_errno = MPI_SUCCESS;
240 MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPID_BSEND_INIT);
241
242 MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPID_BSEND_INIT);
243
244 MPIDI_Request_create_psreq(sreq, mpi_errno, goto fn_exit);
245 MPIDI_Request_set_type(sreq, MPIDI_REQUEST_TYPE_BSEND);
246 if (!HANDLE_IS_BUILTIN(datatype))
247 {
248 MPIR_Datatype_get_ptr(datatype, sreq->dev.datatype_ptr);
249 MPIR_Datatype_ptr_add_ref(sreq->dev.datatype_ptr);
250 }
251 *request = sreq;
252
253 fn_exit:
254 MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPID_BSEND_INIT);
255 return mpi_errno;
256 }
257
258 /*
259 * FIXME: The ch3 implmentation of the persistent routines should
260 * be very simple and use common code as much as possible. All
261 * persistent routine should be in the same file, along with
262 * startall. Consider using function pointers to specify the
263 * start functions, as if these were generalized requests,
264 * rather than having MPID_Startall look at the request type.
265 */
266 /*
267 * MPID_Recv_init()
268 */
MPID_Recv_init(void * buf,int count,MPI_Datatype datatype,int rank,int tag,MPIR_Comm * comm,int context_offset,MPIR_Request ** request)269 int MPID_Recv_init(void * buf, int count, MPI_Datatype datatype, int rank, int tag, MPIR_Comm * comm, int context_offset,
270 MPIR_Request ** request)
271 {
272 MPIR_Request * rreq;
273 int mpi_errno = MPI_SUCCESS;
274 MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPID_RECV_INIT);
275
276 MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPID_RECV_INIT);
277
278 rreq = MPIR_Request_create(MPIR_REQUEST_KIND__PREQUEST_RECV);
279 if (rreq == NULL)
280 {
281 /* --BEGIN ERROR HANDLING-- */
282 mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_FATAL, __func__, __LINE__, MPI_ERR_OTHER, "**nomemreq", 0);
283 /* --END ERROR HANDLING-- */
284 goto fn_exit;
285 }
286
287 MPIR_Object_set_ref(rreq, 1);
288 rreq->comm = comm;
289 MPIR_cc_set(&rreq->cc, 0);
290 MPIR_Comm_add_ref(comm);
291 rreq->dev.match.parts.rank = rank;
292 rreq->dev.match.parts.tag = tag;
293 rreq->dev.match.parts.context_id = comm->recvcontext_id + context_offset;
294 rreq->dev.user_buf = (void *) buf;
295 rreq->dev.user_count = count;
296 rreq->dev.datatype = datatype;
297 rreq->u.persist.real_request = NULL;
298 MPIDI_Request_set_type(rreq, MPIDI_REQUEST_TYPE_RECV);
299 if (!HANDLE_IS_BUILTIN(datatype))
300 {
301 MPIR_Datatype_get_ptr(datatype, rreq->dev.datatype_ptr);
302 MPIR_Datatype_ptr_add_ref(rreq->dev.datatype_ptr);
303 }
304 *request = rreq;
305
306 fn_exit:
307 MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPID_RECV_INIT);
308 return mpi_errno;
309 }
310