1 /*
2 * Copyright (C) by Argonne National Laboratory
3 * See COPYRIGHT in top-level directory
4 */
5
6 #include "mpidimpl.h"
7 #include "mpidrma.h"
8
MPIDI_CH3U_Handle_send_req(MPIDI_VC_t * vc,MPIR_Request * sreq,int * complete)9 int MPIDI_CH3U_Handle_send_req(MPIDI_VC_t * vc, MPIR_Request * sreq, int *complete)
10 {
11 int mpi_errno = MPI_SUCCESS;
12 int (*reqFn) (MPIDI_VC_t *, MPIR_Request *, int *);
13 MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPIDI_CH3U_HANDLE_SEND_REQ);
14
15 MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPIDI_CH3U_HANDLE_SEND_REQ);
16
17 /* Use the associated function rather than switching on the old ca field */
18 /* Routines can call the attached function directly */
19 reqFn = sreq->dev.OnDataAvail;
20 if (!reqFn) {
21 MPIR_Assert(MPIDI_Request_get_type(sreq) != MPIDI_REQUEST_TYPE_GET_RESP);
22 mpi_errno = MPID_Request_complete(sreq);
23 *complete = 1;
24 }
25 else {
26 mpi_errno = reqFn(vc, sreq, complete);
27 }
28 MPIR_ERR_CHECK(mpi_errno);
29
30 fn_exit:
31 MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPIDI_CH3U_HANDLE_SEND_REQ);
32 return mpi_errno;
33 fn_fail:
34 goto fn_exit;
35 }
36
37 /* ----------------------------------------------------------------------- */
38 /* Here are the functions that implement the actions that are taken when
39 * data is available for a send request (or other completion operations)
40 * These include "send" requests that are part of the RMA implementation.
41 */
42 /* ----------------------------------------------------------------------- */
43
MPIDI_CH3_ReqHandler_GetSendComplete(MPIDI_VC_t * vc ATTRIBUTE ((unused)),MPIR_Request * sreq,int * complete)44 int MPIDI_CH3_ReqHandler_GetSendComplete(MPIDI_VC_t * vc ATTRIBUTE((unused)),
45 MPIR_Request * sreq, int *complete)
46 {
47 int mpi_errno = MPI_SUCCESS;
48 MPIR_Win *win_ptr;
49 int pkt_flags = sreq->dev.pkt_flags;
50
51 /* NOTE: It is possible that this request is already completed before
52 * entering this handler. This happens when this req handler is called
53 * within the same req handler on the same request.
54 * Consider this case: req is queued up in SHM queue with ref count of 2:
55 * one is for completing the request and another is for dequeueing from
56 * the queue. The first called req handler on this request completed
57 * this request and decrement ref counter to 1. Request is still in the
58 * queue. Within this handler, we call the req handler on the same request
59 * for the second time (for example when making progress on SHM queue),
60 * and the second called handler also tries to complete this request,
61 * which leads to wrong execution.
62 * Here we check if req is already completed to prevent processing the
63 * same request twice. */
64 if (MPIR_Request_is_complete(sreq)) {
65 *complete = FALSE;
66 goto fn_exit;
67 }
68
69 MPIR_Win_get_ptr(sreq->dev.target_win_handle, win_ptr);
70
71 /* here we decrement the Active Target counter to guarantee the GET-like
72 * operation are completed when counter reaches zero. */
73 win_ptr->at_completion_counter--;
74 MPIR_Assert(win_ptr->at_completion_counter >= 0);
75
76 /* mark data transfer as complete and decrement CC */
77 mpi_errno = MPID_Request_complete(sreq);
78 MPIR_ERR_CHECK(mpi_errno);
79
80 /* NOTE: finish_op_on_target() must be called after we complete this request,
81 * because inside finish_op_on_target() we may call this request handler
82 * on the same request again (in release_lock()). Marking this request as
83 * completed will prevent us from processing the same request twice. */
84 mpi_errno = finish_op_on_target(win_ptr, vc, TRUE /* has response data */ ,
85 pkt_flags, MPI_WIN_NULL);
86 MPIR_ERR_CHECK(mpi_errno);
87
88 *complete = TRUE;
89
90 fn_exit:
91 return mpi_errno;
92 fn_fail:
93 goto fn_exit;
94 }
95
MPIDI_CH3_ReqHandler_GaccumSendComplete(MPIDI_VC_t * vc,MPIR_Request * rreq,int * complete)96 int MPIDI_CH3_ReqHandler_GaccumSendComplete(MPIDI_VC_t * vc, MPIR_Request * rreq, int *complete)
97 {
98 int mpi_errno = MPI_SUCCESS;
99 MPIR_Win *win_ptr;
100 int pkt_flags = rreq->dev.pkt_flags;
101 MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPIDI_CH3_REQHANDLER_GACCUMSENDCOMPLETE);
102
103 MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPIDI_CH3_REQHANDLER_GACCUMSENDCOMPLETE);
104
105 /* NOTE: It is possible that this request is already completed before
106 * entering this handler. This happens when this req handler is called
107 * within the same req handler on the same request.
108 * Consider this case: req is queued up in SHM queue with ref count of 2:
109 * one is for completing the request and another is for dequeueing from
110 * the queue. The first called req handler on this request completed
111 * this request and decrement ref counter to 1. Request is still in the
112 * queue. Within this handler, we call the req handler on the same request
113 * for the second time (for example when making progress on SHM queue),
114 * and the second called handler also tries to complete this request,
115 * which leads to wrong execution.
116 * Here we check if req is already completed to prevent processing the
117 * same request twice. */
118 if (MPIR_Request_is_complete(rreq)) {
119 *complete = FALSE;
120 goto fn_exit;
121 }
122
123 /* This function is triggered when sending back process of GACC/FOP/CAS
124 * is finished. Only GACC used user_buf. FOP and CAS can fit all data
125 * in response packet. */
126 MPL_free(rreq->dev.user_buf);
127
128 MPIR_Win_get_ptr(rreq->dev.target_win_handle, win_ptr);
129
130 /* here we decrement the Active Target counter to guarantee the GET-like
131 * operation are completed when counter reaches zero. */
132 win_ptr->at_completion_counter--;
133 MPIR_Assert(win_ptr->at_completion_counter >= 0);
134
135 mpi_errno = MPID_Request_complete(rreq);
136 MPIR_ERR_CHECK(mpi_errno);
137
138 /* NOTE: finish_op_on_target() must be called after we complete this request,
139 * because inside finish_op_on_target() we may call this request handler
140 * on the same request again (in release_lock()). Marking this request as
141 * completed will prevent us from processing the same request twice. */
142 mpi_errno = finish_op_on_target(win_ptr, vc, TRUE /* has response data */ ,
143 pkt_flags, MPI_WIN_NULL);
144 MPIR_ERR_CHECK(mpi_errno);
145
146 *complete = TRUE;
147
148 fn_exit:
149 MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPIDI_CH3_REQHANDLER_GACCUMSENDCOMPLETE);
150 return mpi_errno;
151
152 fn_fail:
153 goto fn_exit;
154 }
155
156
MPIDI_CH3_ReqHandler_CASSendComplete(MPIDI_VC_t * vc,MPIR_Request * rreq,int * complete)157 int MPIDI_CH3_ReqHandler_CASSendComplete(MPIDI_VC_t * vc, MPIR_Request * rreq, int *complete)
158 {
159 int mpi_errno = MPI_SUCCESS;
160 MPIR_Win *win_ptr;
161 int pkt_flags = rreq->dev.pkt_flags;
162 MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPIDI_CH3_REQHANDLER_CASSENDCOMPLETE);
163
164 MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPIDI_CH3_REQHANDLER_CASSENDCOMPLETE);
165
166 /* NOTE: It is possible that this request is already completed before
167 * entering this handler. This happens when this req handler is called
168 * within the same req handler on the same request.
169 * Consider this case: req is queued up in SHM queue with ref count of 2:
170 * one is for completing the request and another is for dequeueing from
171 * the queue. The first called req handler on this request completed
172 * this request and decrement ref counter to 1. Request is still in the
173 * queue. Within this handler, we call the req handler on the same request
174 * for the second time (for example when making progress on SHM queue),
175 * and the second called handler also tries to complete this request,
176 * which leads to wrong execution.
177 * Here we check if req is already completed to prevent processing the
178 * same request twice. */
179 if (MPIR_Request_is_complete(rreq)) {
180 *complete = FALSE;
181 goto fn_exit;
182 }
183
184 /* This function is triggered when sending back process of GACC/FOP/CAS
185 * is finished. Only GACC used user_buf. FOP and CAS can fit all data
186 * in response packet. */
187 MPL_free(rreq->dev.user_buf);
188
189 MPIR_Win_get_ptr(rreq->dev.target_win_handle, win_ptr);
190
191 /* here we decrement the Active Target counter to guarantee the GET-like
192 * operation are completed when counter reaches zero. */
193 win_ptr->at_completion_counter--;
194 MPIR_Assert(win_ptr->at_completion_counter >= 0);
195
196 mpi_errno = MPID_Request_complete(rreq);
197 MPIR_ERR_CHECK(mpi_errno);
198
199 /* NOTE: finish_op_on_target() must be called after we complete this request,
200 * because inside finish_op_on_target() we may call this request handler
201 * on the same request again (in release_lock()). Marking this request as
202 * completed will prevent us from processing the same request twice. */
203 mpi_errno = finish_op_on_target(win_ptr, vc, TRUE /* has response data */ ,
204 pkt_flags, MPI_WIN_NULL);
205 MPIR_ERR_CHECK(mpi_errno);
206
207 *complete = TRUE;
208
209 fn_exit:
210 MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPIDI_CH3_REQHANDLER_CASSENDCOMPLETE);
211 return mpi_errno;
212
213 fn_fail:
214 goto fn_exit;
215 }
216
MPIDI_CH3_ReqHandler_FOPSendComplete(MPIDI_VC_t * vc,MPIR_Request * rreq,int * complete)217 int MPIDI_CH3_ReqHandler_FOPSendComplete(MPIDI_VC_t * vc, MPIR_Request * rreq, int *complete)
218 {
219 int mpi_errno = MPI_SUCCESS;
220 MPIR_Win *win_ptr;
221 int pkt_flags = rreq->dev.pkt_flags;
222 MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPIDI_CH3_REQHANDLER_FOPSENDCOMPLETE);
223
224 MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPIDI_CH3_REQHANDLER_FOPSENDCOMPLETE);
225
226 /* NOTE: It is possible that this request is already completed before
227 * entering this handler. This happens when this req handler is called
228 * within the same req handler on the same request.
229 * Consider this case: req is queued up in SHM queue with ref count of 2:
230 * one is for completing the request and another is for dequeueing from
231 * the queue. The first called req handler on this request completed
232 * this request and decrement ref counter to 1. Request is still in the
233 * queue. Within this handler, we call the req handler on the same request
234 * for the second time (for example when making progress on SHM queue),
235 * and the second called handler also tries to complete this request,
236 * which leads to wrong execution.
237 * Here we check if req is already completed to prevent processing the
238 * same request twice. */
239 if (MPIR_Request_is_complete(rreq)) {
240 *complete = FALSE;
241 goto fn_exit;
242 }
243
244 /* This function is triggered when sending back process of GACC/FOP/CAS
245 * is finished. Only GACC used user_buf. FOP and CAS can fit all data
246 * in response packet. */
247 MPL_free(rreq->dev.user_buf);
248
249 MPIR_Win_get_ptr(rreq->dev.target_win_handle, win_ptr);
250
251 /* here we decrement the Active Target counter to guarantee the GET-like
252 * operation are completed when counter reaches zero. */
253 win_ptr->at_completion_counter--;
254 MPIR_Assert(win_ptr->at_completion_counter >= 0);
255
256 mpi_errno = MPID_Request_complete(rreq);
257 MPIR_ERR_CHECK(mpi_errno);
258
259 /* NOTE: finish_op_on_target() must be called after we complete this request,
260 * because inside finish_op_on_target() we may call this request handler
261 * on the same request again (in release_lock()). Marking this request as
262 * completed will prevent us from processing the same request twice. */
263 mpi_errno = finish_op_on_target(win_ptr, vc, TRUE /* has response data */ ,
264 pkt_flags, MPI_WIN_NULL);
265 MPIR_ERR_CHECK(mpi_errno);
266
267 *complete = TRUE;
268
269 fn_exit:
270 MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPIDI_CH3_REQHANDLER_FOPSENDCOMPLETE);
271 return mpi_errno;
272
273 fn_fail:
274 goto fn_exit;
275 }
276
277
MPIDI_CH3_ReqHandler_SendReloadIOV(MPIDI_VC_t * vc ATTRIBUTE ((unused)),MPIR_Request * sreq,int * complete)278 int MPIDI_CH3_ReqHandler_SendReloadIOV(MPIDI_VC_t * vc ATTRIBUTE((unused)), MPIR_Request * sreq,
279 int *complete)
280 {
281 int mpi_errno;
282
283 /* setting the iov_offset to 0 here is critical, since it is intentionally
284 * not set in the _load_send_iov function */
285 sreq->dev.iov_offset = 0;
286 sreq->dev.iov_count = MPL_IOV_LIMIT;
287 mpi_errno = MPIDI_CH3U_Request_load_send_iov(sreq, sreq->dev.iov, &sreq->dev.iov_count);
288 if (mpi_errno != MPI_SUCCESS) {
289 MPIR_ERR_SETFATALANDJUMP(mpi_errno, MPI_ERR_OTHER, "**ch3|loadsendiov");
290 }
291
292 *complete = FALSE;
293
294 fn_fail:
295 return mpi_errno;
296 }
297