1 /* -*- Mode: C; c-basic-offset:4 ; -*- */
2 /*
3 *
4 * (C) 2001 by Argonne National Laboratory.
5 * See COPYRIGHT in top-level directory.
6 */
7
8 #include "mpiimpl.h"
9 #include "datatype.h"
10
11 #define COPY_BUFFER_SZ 16384
12
13 /* These functions are used in the implementation of collective
14 operations. They are wrappers around MPID send/recv functions. They do
15 sends/receives by setting the context offset to
16 MPID_CONTEXT_INTRA_COLL or MPID_CONTEXT_INTER_COLL. */
17
18 #undef FUNCNAME
19 #define FUNCNAME MPIC_Probe
20 #undef FCNAME
21 #define FCNAME MPIU_QUOTE(FUNCNAME)
MPIC_Probe(int source,int tag,MPI_Comm comm,MPI_Status * status)22 int MPIC_Probe(int source, int tag, MPI_Comm comm, MPI_Status *status)
23 {
24 int mpi_errno = MPI_SUCCESS;
25 int context_id;
26 MPID_Comm *comm_ptr;
27
28 MPID_Comm_get_ptr( comm, comm_ptr );
29
30 context_id = (comm_ptr->comm_kind == MPID_INTRACOMM) ?
31 MPID_CONTEXT_INTRA_COLL : MPID_CONTEXT_INTER_COLL;
32
33 mpi_errno = MPID_Probe(source, tag, comm_ptr, context_id, status);
34 if (mpi_errno != MPI_SUCCESS) goto fn_fail;
35
36 fn_exit:
37 return mpi_errno;
38 fn_fail:
39 goto fn_exit;
40 }
41
42
43 #undef FUNCNAME
44 #define FUNCNAME MPIC_Send
45 #undef FCNAME
46 #define FCNAME "MPIC_Send"
MPIC_Send(const void * buf,int count,MPI_Datatype datatype,int dest,int tag,MPI_Comm comm)47 int MPIC_Send(const void *buf, int count, MPI_Datatype datatype, int dest, int tag,
48 MPI_Comm comm)
49 {
50 int mpi_errno, context_id;
51 MPID_Request *request_ptr=NULL;
52 MPID_Comm *comm_ptr=NULL;
53 MPIDI_STATE_DECL(MPID_STATE_MPIC_SEND);
54
55 MPIDI_PT2PT_FUNC_ENTER_FRONT(MPID_STATE_MPIC_SEND);
56
57 MPID_Comm_get_ptr( comm, comm_ptr );
58 context_id = (comm_ptr->comm_kind == MPID_INTRACOMM) ?
59 MPID_CONTEXT_INTRA_COLL : MPID_CONTEXT_INTER_COLL;
60
61 mpi_errno = MPID_Send(buf, count, datatype, dest, tag, comm_ptr,
62 context_id, &request_ptr);
63 if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
64 if (request_ptr) {
65 mpi_errno = MPIC_Wait(request_ptr);
66 if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
67 MPID_Request_release(request_ptr);
68 }
69 fn_exit:
70 MPIDI_PT2PT_FUNC_EXIT(MPID_STATE_MPIC_SEND);
71 return mpi_errno;
72 fn_fail:
73 /* --BEGIN ERROR HANDLING-- */
74 if (request_ptr) {
75 MPID_Request_release(request_ptr);
76 }
77 goto fn_exit;
78 /* --END ERROR HANDLING-- */
79 }
80
81 #undef FUNCNAME
82 #define FUNCNAME MPIC_Recv
83 #undef FCNAME
84 #define FCNAME "MPIC_Recv"
MPIC_Recv(void * buf,int count,MPI_Datatype datatype,int source,int tag,MPI_Comm comm,MPI_Status * status)85 int MPIC_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag,
86 MPI_Comm comm, MPI_Status *status)
87 {
88 int mpi_errno, context_id;
89 MPID_Request *request_ptr=NULL;
90 MPID_Comm *comm_ptr = NULL;
91 MPIDI_STATE_DECL(MPID_STATE_MPIC_RECV);
92
93 MPIDI_PT2PT_FUNC_ENTER_BACK(MPID_STATE_MPIC_RECV);
94
95 MPID_Comm_get_ptr( comm, comm_ptr );
96 context_id = (comm_ptr->comm_kind == MPID_INTRACOMM) ?
97 MPID_CONTEXT_INTRA_COLL : MPID_CONTEXT_INTER_COLL;
98
99 mpi_errno = MPID_Recv(buf, count, datatype, source, tag, comm_ptr,
100 context_id, status, &request_ptr);
101 if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
102 if (request_ptr) {
103 mpi_errno = MPIC_Wait(request_ptr);
104 if (mpi_errno == MPI_SUCCESS) {
105 if (status != MPI_STATUS_IGNORE) {
106 *status = request_ptr->status;
107 }
108 mpi_errno = request_ptr->status.MPI_ERROR;
109 }
110 else { MPIU_ERR_POP(mpi_errno); }
111
112 MPID_Request_release(request_ptr);
113 }
114 fn_exit:
115 MPIDI_PT2PT_FUNC_EXIT_BACK(MPID_STATE_MPIC_RECV);
116 return mpi_errno;
117 fn_fail:
118 /* --BEGIN ERROR HANDLING-- */
119 if (request_ptr) {
120 MPID_Request_release(request_ptr);
121 }
122 goto fn_exit;
123 /* --END ERROR HANDLING-- */
124 }
125
126 #undef FUNCNAME
127 #define FUNCNAME MPIC_Ssend
128 #undef FCNAME
129 #define FCNAME "MPIC_Ssend"
MPIC_Ssend(const void * buf,int count,MPI_Datatype datatype,int dest,int tag,MPI_Comm comm)130 int MPIC_Ssend(const void *buf, int count, MPI_Datatype datatype, int dest, int tag,
131 MPI_Comm comm)
132 {
133 int mpi_errno, context_id;
134 MPID_Request *request_ptr=NULL;
135 MPID_Comm *comm_ptr=NULL;
136 MPIDI_STATE_DECL(MPID_STATE_MPIC_SSEND);
137
138 MPIDI_PT2PT_FUNC_ENTER_FRONT(MPID_STATE_MPIC_SSEND);
139
140 MPID_Comm_get_ptr( comm, comm_ptr );
141 context_id = (comm_ptr->comm_kind == MPID_INTRACOMM) ?
142 MPID_CONTEXT_INTRA_COLL : MPID_CONTEXT_INTER_COLL;
143
144 mpi_errno = MPID_Ssend(buf, count, datatype, dest, tag, comm_ptr,
145 context_id, &request_ptr);
146 if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
147 if (request_ptr) {
148 mpi_errno = MPIC_Wait(request_ptr);
149 if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
150 MPID_Request_release(request_ptr);
151 }
152 fn_exit:
153 MPIDI_PT2PT_FUNC_EXIT(MPID_STATE_MPIC_SSEND);
154 return mpi_errno;
155 fn_fail:
156 /* --BEGIN ERROR HANDLING-- */
157 if (request_ptr) {
158 MPID_Request_release(request_ptr);
159 }
160 goto fn_exit;
161 /* --END ERROR HANDLING-- */
162 }
163
164 #undef FUNCNAME
165 #define FUNCNAME MPIC_Sendrecv
166 #undef FCNAME
167 #define FCNAME "MPIC_Sendrecv"
MPIC_Sendrecv(const void * sendbuf,int sendcount,MPI_Datatype sendtype,int dest,int sendtag,void * recvbuf,int recvcount,MPI_Datatype recvtype,int source,int recvtag,MPI_Comm comm,MPI_Status * status)168 int MPIC_Sendrecv(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
169 int dest, int sendtag, void *recvbuf, int recvcount,
170 MPI_Datatype recvtype, int source, int recvtag,
171 MPI_Comm comm, MPI_Status *status)
172 {
173 MPID_Request *recv_req_ptr=NULL, *send_req_ptr=NULL;
174 int mpi_errno, context_id;
175 MPID_Comm *comm_ptr = NULL;
176 MPIDI_STATE_DECL(MPID_STATE_MPIC_SENDRECV);
177
178 MPIDI_PT2PT_FUNC_ENTER_BOTH(MPID_STATE_MPIC_SENDRECV);
179
180 MPID_Comm_get_ptr( comm, comm_ptr );
181 context_id = (comm_ptr->comm_kind == MPID_INTRACOMM) ?
182 MPID_CONTEXT_INTRA_COLL : MPID_CONTEXT_INTER_COLL;
183
184 mpi_errno = MPID_Irecv(recvbuf, recvcount, recvtype, source, recvtag,
185 comm_ptr, context_id, &recv_req_ptr);
186 if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
187 mpi_errno = MPID_Isend(sendbuf, sendcount, sendtype, dest, sendtag,
188 comm_ptr, context_id, &send_req_ptr);
189 if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
190
191 mpi_errno = MPIC_Wait(send_req_ptr);
192 if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
193
194 mpi_errno = MPIC_Wait(recv_req_ptr);
195 if (mpi_errno) { MPIU_ERR_POPFATAL(mpi_errno); }
196 if (status != MPI_STATUS_IGNORE)
197 *status = recv_req_ptr->status;
198 mpi_errno = recv_req_ptr->status.MPI_ERROR;
199
200 MPID_Request_release(send_req_ptr);
201 MPID_Request_release(recv_req_ptr);
202 fn_fail:
203 /* --BEGIN ERROR HANDLING-- */
204 MPIDI_PT2PT_FUNC_EXIT_BOTH(MPID_STATE_MPIC_SENDRECV);
205 return mpi_errno;
206 /* --END ERROR HANDLING-- */
207 }
208
209 /* NOTE: for regular collectives (as opposed to irregular collectives) calling
210 * this function repeatedly will almost always be slower than performing the
211 * equivalent inline because of the overhead of the repeated malloc/free */
212 #undef FUNCNAME
213 #define FUNCNAME MPIC_Sendrecv_replace
214 #undef FCNAME
215 #define FCNAME MPIU_QUOTE(FUNCNAME)
MPIC_Sendrecv_replace(void * buf,int count,MPI_Datatype datatype,int dest,int sendtag,int source,int recvtag,MPI_Comm comm,MPI_Status * status)216 int MPIC_Sendrecv_replace(void *buf, int count, MPI_Datatype datatype,
217 int dest, int sendtag,
218 int source, int recvtag,
219 MPI_Comm comm, MPI_Status *status)
220 {
221 int mpi_errno = MPI_SUCCESS;
222 MPIR_Context_id_t context_id_offset;
223 MPID_Request *sreq;
224 MPID_Request *rreq;
225 void *tmpbuf = NULL;
226 int tmpbuf_size = 0;
227 int tmpbuf_count = 0;
228 MPID_Comm *comm_ptr;
229 MPIU_CHKLMEM_DECL(1);
230 MPIDI_STATE_DECL(MPID_STATE_MPIC_SENDRECV_REPLACE);
231 #ifdef MPID_LOG_ARROWS
232 /* The logging macros log sendcount and recvcount */
233 int sendcount = count, recvcount = count;
234 #endif
235
236 MPIDI_PT2PT_FUNC_ENTER_BOTH(MPID_STATE_MPIC_SENDRECV_REPLACE);
237
238 MPID_Comm_get_ptr( comm, comm_ptr );
239 context_id_offset = (comm_ptr->comm_kind == MPID_INTRACOMM) ?
240 MPID_CONTEXT_INTRA_COLL : MPID_CONTEXT_INTER_COLL;
241
242 if (count > 0 && dest != MPI_PROC_NULL)
243 {
244 MPIR_Pack_size_impl(count, datatype, &tmpbuf_size);
245 MPIU_CHKLMEM_MALLOC(tmpbuf, void *, tmpbuf_size, mpi_errno, "temporary send buffer");
246
247 mpi_errno = MPIR_Pack_impl(buf, count, datatype, tmpbuf, tmpbuf_size, &tmpbuf_count);
248 if (mpi_errno) MPIU_ERR_POP(mpi_errno);
249 }
250
251 mpi_errno = MPID_Irecv(buf, count, datatype, source, recvtag,
252 comm_ptr, context_id_offset, &rreq);
253 if (mpi_errno) MPIU_ERR_POP(mpi_errno);
254
255 mpi_errno = MPID_Isend(tmpbuf, tmpbuf_count, MPI_PACKED, dest,
256 sendtag, comm_ptr, context_id_offset,
257 &sreq);
258 if (mpi_errno != MPI_SUCCESS)
259 {
260 /* --BEGIN ERROR HANDLING-- */
261 /* FIXME: should we cancel the pending (possibly completed) receive request or wait for it to complete? */
262 MPID_Request_release(rreq);
263 MPIU_ERR_POP(mpi_errno);
264 /* --END ERROR HANDLING-- */
265 }
266
267 if (!MPID_Request_is_complete(sreq) || !MPID_Request_is_complete(rreq))
268 {
269 MPID_Progress_state progress_state;
270
271 MPID_Progress_start(&progress_state);
272 while (!MPID_Request_is_complete(sreq) || !MPID_Request_is_complete(rreq))
273 {
274 mpi_errno = MPID_Progress_wait(&progress_state);
275 if (mpi_errno != MPI_SUCCESS)
276 {
277 /* --BEGIN ERROR HANDLING-- */
278 MPID_Progress_end(&progress_state);
279 MPIU_ERR_POP(mpi_errno);
280 /* --END ERROR HANDLING-- */
281 }
282 }
283 MPID_Progress_end(&progress_state);
284 }
285
286 if (status != MPI_STATUS_IGNORE) {
287 *status = rreq->status;
288 }
289
290 if (mpi_errno == MPI_SUCCESS) {
291 mpi_errno = rreq->status.MPI_ERROR;
292
293 if (mpi_errno == MPI_SUCCESS) {
294 mpi_errno = sreq->status.MPI_ERROR;
295 }
296 }
297
298 MPID_Request_release(sreq);
299 MPID_Request_release(rreq);
300
301 if (mpi_errno) MPIU_ERR_POP(mpi_errno);
302
303 fn_exit:
304 MPIU_CHKLMEM_FREEALL();
305 MPIDI_PT2PT_FUNC_EXIT_BOTH(MPID_STATE_MPIC_SENDRECV_REPLACE);
306 return mpi_errno;
307 fn_fail:
308 goto fn_exit;
309 }
310
311 #undef FUNCNAME
312 #define FUNCNAME MPIR_Localcopy
313 #undef FCNAME
314 #define FCNAME "MPIR_Localcopy"
MPIR_Localcopy(const void * sendbuf,int sendcount,MPI_Datatype sendtype,void * recvbuf,int recvcount,MPI_Datatype recvtype)315 int MPIR_Localcopy(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
316 void *recvbuf, int recvcount, MPI_Datatype recvtype)
317 {
318 int mpi_errno = MPI_SUCCESS;
319 int sendtype_iscontig, recvtype_iscontig;
320 MPI_Aint sendsize, recvsize, sdata_sz, rdata_sz, copy_sz;
321 MPI_Aint true_extent, sendtype_true_lb, recvtype_true_lb;
322 MPIU_CHKLMEM_DECL(1);
323 MPID_MPI_STATE_DECL(MPID_STATE_MPIR_LOCALCOPY);
324
325 MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_LOCALCOPY);
326
327 MPIR_Datatype_iscontig(sendtype, &sendtype_iscontig);
328 MPIR_Datatype_iscontig(recvtype, &recvtype_iscontig);
329
330 MPID_Datatype_get_size_macro(sendtype, sendsize);
331 MPID_Datatype_get_size_macro(recvtype, recvsize);
332 sdata_sz = sendsize * sendcount;
333 rdata_sz = recvsize * recvcount;
334
335 if (!sdata_sz || !rdata_sz)
336 goto fn_exit;
337
338 if (sdata_sz > rdata_sz)
339 {
340 MPIU_ERR_SET2(mpi_errno, MPI_ERR_TRUNCATE, "**truncate", "**truncate %d %d", sdata_sz, rdata_sz);
341 copy_sz = rdata_sz;
342 }
343 else
344 {
345 copy_sz = sdata_sz;
346 }
347
348 MPIR_Type_get_true_extent_impl(sendtype, &sendtype_true_lb, &true_extent);
349 MPIR_Type_get_true_extent_impl(recvtype, &recvtype_true_lb, &true_extent);
350
351 if (sendtype_iscontig && recvtype_iscontig)
352 {
353 #if defined(HAVE_ERROR_CHECKING)
354 MPIU_ERR_CHKMEMCPYANDJUMP(mpi_errno,
355 ((char *)recvbuf + recvtype_true_lb),
356 ((char *)sendbuf + sendtype_true_lb),
357 copy_sz);
358 #endif
359 MPIU_Memcpy(((char *) recvbuf + recvtype_true_lb),
360 ((char *) sendbuf + sendtype_true_lb),
361 copy_sz);
362 }
363 else if (sendtype_iscontig)
364 {
365 MPID_Segment seg;
366 MPI_Aint last;
367
368 MPID_Segment_init(recvbuf, recvcount, recvtype, &seg, 0);
369 last = copy_sz;
370 MPID_Segment_unpack(&seg, 0, &last, (char*)sendbuf + sendtype_true_lb);
371 MPIU_ERR_CHKANDJUMP(last != copy_sz, mpi_errno, MPI_ERR_TYPE, "**dtypemismatch");
372 }
373 else if (recvtype_iscontig)
374 {
375 MPID_Segment seg;
376 MPI_Aint last;
377
378 MPID_Segment_init(sendbuf, sendcount, sendtype, &seg, 0);
379 last = copy_sz;
380 MPID_Segment_pack(&seg, 0, &last, (char*)recvbuf + recvtype_true_lb);
381 MPIU_ERR_CHKANDJUMP(last != copy_sz, mpi_errno, MPI_ERR_TYPE, "**dtypemismatch");
382 }
383 else
384 {
385 char * buf;
386 MPIDI_msg_sz_t buf_off;
387 MPID_Segment sseg;
388 MPIDI_msg_sz_t sfirst;
389 MPID_Segment rseg;
390 MPIDI_msg_sz_t rfirst;
391
392 MPIU_CHKLMEM_MALLOC(buf, char *, COPY_BUFFER_SZ, mpi_errno, "buf");
393
394 MPID_Segment_init(sendbuf, sendcount, sendtype, &sseg, 0);
395 MPID_Segment_init(recvbuf, recvcount, recvtype, &rseg, 0);
396
397 sfirst = 0;
398 rfirst = 0;
399 buf_off = 0;
400
401 while (1)
402 {
403 MPI_Aint last;
404 char * buf_end;
405
406 if (copy_sz - sfirst > COPY_BUFFER_SZ - buf_off)
407 {
408 last = sfirst + (COPY_BUFFER_SZ - buf_off);
409 }
410 else
411 {
412 last = copy_sz;
413 }
414
415 MPID_Segment_pack(&sseg, sfirst, &last, buf + buf_off);
416 MPIU_Assert(last > sfirst);
417
418 buf_end = buf + buf_off + (last - sfirst);
419 sfirst = last;
420
421 MPID_Segment_unpack(&rseg, rfirst, &last, buf);
422 MPIU_Assert(last > rfirst);
423
424 rfirst = last;
425
426 if (rfirst == copy_sz)
427 {
428 /* successful completion */
429 break;
430 }
431
432 /* if the send side finished, but the recv side couldn't unpack it, there's a datatype mismatch */
433 MPIU_ERR_CHKANDJUMP(sfirst == copy_sz, mpi_errno, MPI_ERR_TYPE, "**dtypemismatch");
434
435 /* if not all data was unpacked, copy it to the front of the buffer for next time */
436 buf_off = sfirst - rfirst;
437 if (buf_off > 0)
438 {
439 memmove(buf, buf_end - buf_off, buf_off);
440 }
441 }
442 }
443
444
445 fn_exit:
446 MPIU_CHKLMEM_FREEALL();
447 MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_LOCALCOPY);
448 return mpi_errno;
449
450 fn_fail:
451 goto fn_exit;
452 }
453
454
455 #undef FUNCNAME
456 #define FUNCNAME MPIC_Isend
457 #undef FCNAME
458 #define FCNAME "MPIC_Isend"
MPIC_Isend(const void * buf,int count,MPI_Datatype datatype,int dest,int tag,MPI_Comm comm,MPI_Request * request)459 int MPIC_Isend(const void *buf, int count, MPI_Datatype datatype, int dest, int tag,
460 MPI_Comm comm, MPI_Request *request)
461 {
462 int mpi_errno, context_id;
463 MPID_Request *request_ptr=NULL;
464 MPID_Comm *comm_ptr=NULL;
465 MPIDI_STATE_DECL(MPID_STATE_MPIC_ISEND);
466
467 MPIDI_PT2PT_FUNC_ENTER_FRONT(MPID_STATE_MPIC_ISEND);
468
469 MPID_Comm_get_ptr( comm, comm_ptr );
470 context_id = (comm_ptr->comm_kind == MPID_INTRACOMM) ?
471 MPID_CONTEXT_INTRA_COLL : MPID_CONTEXT_INTER_COLL;
472
473 mpi_errno = MPID_Isend(buf, count, datatype, dest, tag, comm_ptr,
474 context_id, &request_ptr);
475 if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
476
477 *request = request_ptr->handle;
478
479 fn_fail:
480 /* --BEGIN ERROR HANDLING-- */
481 MPIDI_PT2PT_FUNC_EXIT(MPID_STATE_MPIC_ISEND);
482 return mpi_errno;
483 /* --END ERROR HANDLING-- */
484 }
485
486
487 #undef FUNCNAME
488 #define FUNCNAME MPIC_Irecv
489 #undef FCNAME
490 #define FCNAME "MPIC_Irecv"
MPIC_Irecv(void * buf,int count,MPI_Datatype datatype,int source,int tag,MPI_Comm comm,MPI_Request * request)491 int MPIC_Irecv(void *buf, int count, MPI_Datatype datatype, int
492 source, int tag, MPI_Comm comm, MPI_Request *request)
493 {
494 int mpi_errno, context_id;
495 MPID_Request *request_ptr=NULL;
496 MPID_Comm *comm_ptr = NULL;
497 MPIDI_STATE_DECL(MPID_STATE_MPIC_IRECV);
498
499 MPIDI_PT2PT_FUNC_ENTER_BACK(MPID_STATE_MPIC_IRECV);
500
501 MPID_Comm_get_ptr( comm, comm_ptr );
502 context_id = (comm_ptr->comm_kind == MPID_INTRACOMM) ?
503 MPID_CONTEXT_INTRA_COLL : MPID_CONTEXT_INTER_COLL;
504
505 mpi_errno = MPID_Irecv(buf, count, datatype, source, tag, comm_ptr,
506 context_id, &request_ptr);
507 if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
508
509 *request = request_ptr->handle;
510
511 fn_fail:
512 /* --BEGIN ERROR HANDLING-- */
513 MPIDI_PT2PT_FUNC_EXIT_BACK(MPID_STATE_MPIC_IRECV);
514 return mpi_errno;
515 /* --END ERROR HANDLING-- */
516 }
517
518 /* FIXME: For the brief-global and finer-grain control, we must ensure that
519 the global lock is *not* held when this routine is called. (unless we change
520 progress_start/end to grab the lock, in which case we must *still* make
521 sure that the lock is not held when this routine is called). */
522 #undef FUNCNAME
523 #define FUNCNAME MPIC_Wait
524 #undef FCNAME
525 #define FCNAME "MPIC_Wait"
MPIC_Wait(MPID_Request * request_ptr)526 int MPIC_Wait(MPID_Request * request_ptr)
527 {
528 int mpi_errno = MPI_SUCCESS;
529 MPIDI_STATE_DECL(MPID_STATE_MPIC_WAIT);
530
531 MPIDI_PT2PT_FUNC_ENTER(MPID_STATE_MPIC_WAIT);
532 if (!MPID_Request_is_complete(request_ptr))
533 {
534 MPID_Progress_state progress_state;
535
536 MPID_Progress_start(&progress_state);
537 while (!MPID_Request_is_complete(request_ptr))
538 {
539 mpi_errno = MPID_Progress_wait(&progress_state);
540 if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
541 }
542 MPID_Progress_end(&progress_state);
543 }
544
545 fn_fail:
546 /* --BEGIN ERROR HANDLING-- */
547 MPIDI_PT2PT_FUNC_EXIT(MPID_STATE_MPIC_WAIT);
548 return mpi_errno;
549 /* --END ERROR HANDLING-- */
550 }
551
552
553 /* Fault-tolerance versions. When a process fails, collectives will
554 still complete, however the result may be invalid. Processes
555 directly communicating with the failed process can detect the
556 failure, however another mechanism is needed to commuinicate the
557 failure to other processes receiving the invalid data. To do this
558 we introduce the _ft versions of the MPIC_ helper functions. These
559 functions take a pointer to an error flag. When this is set to
560 TRUE, the send functions will communicate the failure to the
561 receiver. If a function detects a failure, either by getting a
562 failure in the communication operation, or by receiving an error
563 indicator from a remote process, it sets the error flag to TRUE.
564
565 In this implementation, we indicate an error to a remote process by
566 sending an empty message instead of the requested buffer. When a
567 process receives an empty message, it knows to set the error flag.
568 We count on the fact that collectives that exchange data (as
569 opposed to barrier) will never send an empty message. The barrier
570 collective will not communicate failure information this way, but
571 this is OK since there is no data that can be received corrupted. */
572
573 #undef FUNCNAME
574 #define FUNCNAME MPIC_Send_ft
575 #undef FCNAME
576 #define FCNAME MPIU_QUOTE(FUNCNAME)
MPIC_Send_ft(const void * buf,int count,MPI_Datatype datatype,int dest,int tag,MPI_Comm comm,int * errflag)577 int MPIC_Send_ft(const void *buf, int count, MPI_Datatype datatype, int dest, int tag,
578 MPI_Comm comm, int *errflag)
579 {
580 int mpi_errno = MPI_SUCCESS;
581 MPIDI_STATE_DECL(MPID_STATE_MPIC_SEND_FT);
582
583 MPIDI_FUNC_ENTER(MPID_STATE_MPIC_SEND_FT);
584
585 MPIU_DBG_MSG_S(PT2PT, TYPICAL, "IN: errflag = %s", *errflag?"TRUE":"FALSE");
586
587 if (*errflag && MPIR_PARAM_ENABLE_COLL_FT_RET)
588 mpi_errno = MPIC_Send(buf, count, datatype, dest, MPIR_ERROR_TAG, comm);
589 else
590 mpi_errno = MPIC_Send(buf, count, datatype, dest, tag, comm);
591
592 fn_exit:
593 MPIDI_FUNC_EXIT(MPID_STATE_MPIC_SEND_FT);
594 return mpi_errno;
595 fn_fail:
596 goto fn_exit;
597 }
598
599 #undef FUNCNAME
600 #define FUNCNAME MPIC_Recv_ft
601 #undef FCNAME
602 #define FCNAME MPIU_QUOTE(FUNCNAME)
MPIC_Recv_ft(void * buf,int count,MPI_Datatype datatype,int source,int tag,MPI_Comm comm,MPI_Status * status,int * errflag)603 int MPIC_Recv_ft(void *buf, int count, MPI_Datatype datatype, int source, int tag,
604 MPI_Comm comm, MPI_Status *status, int *errflag)
605 {
606 int mpi_errno = MPI_SUCCESS;
607 MPI_Status mystatus;
608 MPIDI_STATE_DECL(MPID_STATE_MPIC_RECV_FT);
609
610 MPIDI_FUNC_ENTER(MPID_STATE_MPIC_RECV_FT);
611
612 MPIU_DBG_MSG_S(PT2PT, TYPICAL, "IN: errflag = %s", *errflag?"TRUE":"FALSE");
613
614 if (!MPIR_PARAM_ENABLE_COLL_FT_RET) {
615 mpi_errno = MPIC_Recv(buf, count, datatype, source, tag, comm, status);
616 goto fn_exit;
617 }
618
619 if (status == MPI_STATUS_IGNORE)
620 status = &mystatus;
621
622 mpi_errno = MPIC_Recv(buf, count, datatype, source, MPI_ANY_TAG, comm, status);
623 if (mpi_errno) MPIU_ERR_POP(mpi_errno);
624
625 if (*errflag)
626 goto fn_exit;
627
628 if (source != MPI_PROC_NULL) {
629 if (status->MPI_TAG == MPIR_ERROR_TAG)
630 *errflag = TRUE;
631 else {
632 MPIU_Assert(status->MPI_TAG == tag);
633 }
634 }
635
636 fn_exit:
637 MPIU_DBG_MSG_S(PT2PT, TYPICAL, "OUT: errflag = %s", *errflag?"TRUE":"FALSE");
638 MPIDI_FUNC_EXIT(MPID_STATE_MPIC_RECV_FT);
639 return mpi_errno;
640 fn_fail:
641 goto fn_exit;
642 }
643
644 #undef FUNCNAME
645 #define FUNCNAME MPIC_Ssend_ft
646 #undef FCNAME
647 #define FCNAME MPIU_QUOTE(FUNCNAME)
MPIC_Ssend_ft(const void * buf,int count,MPI_Datatype datatype,int dest,int tag,MPI_Comm comm,int * errflag)648 int MPIC_Ssend_ft(const void *buf, int count, MPI_Datatype datatype, int dest, int tag,
649 MPI_Comm comm, int *errflag)
650 {
651 int mpi_errno = MPI_SUCCESS;
652 MPIDI_STATE_DECL(MPID_STATE_MPIC_SSEND_FT);
653
654 MPIDI_FUNC_ENTER(MPID_STATE_MPIC_SSEND_FT);
655
656 MPIU_DBG_MSG_S(PT2PT, TYPICAL, "IN: errflag = %s", *errflag?"TRUE":"FALSE");
657
658 if (*errflag && MPIR_PARAM_ENABLE_COLL_FT_RET)
659 mpi_errno = MPIC_Ssend(buf, count, datatype, dest, MPIR_ERROR_TAG, comm);
660 else
661 mpi_errno = MPIC_Ssend(buf, count, datatype, dest, tag, comm);
662
663 fn_exit:
664 MPIDI_FUNC_EXIT(MPID_STATE_MPIC_SSEND_FT);
665 return mpi_errno;
666 fn_fail:
667 goto fn_exit;
668 }
669
670 #undef FUNCNAME
671 #define FUNCNAME MPIC_Sendrecv_ft
672 #undef FCNAME
673 #define FCNAME MPIU_QUOTE(FUNCNAME)
MPIC_Sendrecv_ft(const void * sendbuf,int sendcount,MPI_Datatype sendtype,int dest,int sendtag,void * recvbuf,int recvcount,MPI_Datatype recvtype,int source,int recvtag,MPI_Comm comm,MPI_Status * status,int * errflag)674 int MPIC_Sendrecv_ft(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
675 int dest, int sendtag, void *recvbuf, int recvcount,
676 MPI_Datatype recvtype, int source, int recvtag,
677 MPI_Comm comm, MPI_Status *status, int *errflag)
678 {
679 int mpi_errno = MPI_SUCCESS;
680 MPI_Status mystatus;
681 MPIDI_STATE_DECL(MPID_STATE_MPIC_SENDRECV_FT);
682
683 MPIDI_FUNC_ENTER(MPID_STATE_MPIC_SENDRECV_FT);
684
685 MPIU_DBG_MSG_S(PT2PT, TYPICAL, "IN: errflag = %s", *errflag?"TRUE":"FALSE");
686
687 if (!MPIR_PARAM_ENABLE_COLL_FT_RET) {
688 mpi_errno = MPIC_Sendrecv(sendbuf, sendcount, sendtype, dest, sendtag,
689 recvbuf, recvcount, recvtype, source, recvtag,
690 comm, status);
691 goto fn_exit;
692 }
693
694 if (status == MPI_STATUS_IGNORE)
695 status = &mystatus;
696
697 if (*errflag) {
698 mpi_errno = MPIC_Sendrecv(sendbuf, sendcount, sendtype, dest, MPIR_ERROR_TAG,
699 recvbuf, recvcount, recvtype, source, MPI_ANY_TAG,
700 comm, status);
701 goto fn_exit;
702 }
703
704 mpi_errno = MPIC_Sendrecv(sendbuf, sendcount, sendtype, dest, sendtag,
705 recvbuf, recvcount, recvtype, source, MPI_ANY_TAG,
706 comm, status);
707 if (mpi_errno) MPIU_ERR_POP(mpi_errno);
708
709 if (source != MPI_PROC_NULL) {
710 if (status->MPI_TAG == MPIR_ERROR_TAG)
711 *errflag = TRUE;
712 else {
713 MPIU_Assert(status->MPI_TAG == recvtag);
714 }
715 }
716
717 fn_exit:
718 MPIU_DBG_MSG_S(PT2PT, TYPICAL, "OUT: errflag = %s", *errflag?"TRUE":"FALSE");
719
720 MPIDI_FUNC_EXIT(MPID_STATE_MPIC_SENDRECV_FT);
721 return mpi_errno;
722 fn_fail:
723 goto fn_exit;
724 }
725
726 #undef FUNCNAME
727 #define FUNCNAME MPIC_Sendrecv_replace_ft
728 #undef FCNAME
729 #define FCNAME MPIU_QUOTE(FUNCNAME)
MPIC_Sendrecv_replace_ft(void * buf,int count,MPI_Datatype datatype,int dest,int sendtag,int source,int recvtag,MPI_Comm comm,MPI_Status * status,int * errflag)730 int MPIC_Sendrecv_replace_ft(void *buf, int count, MPI_Datatype datatype,
731 int dest, int sendtag,
732 int source, int recvtag,
733 MPI_Comm comm, MPI_Status *status, int *errflag)
734 {
735 int mpi_errno = MPI_SUCCESS;
736 MPI_Status mystatus;
737 MPIDI_STATE_DECL(MPID_STATE_MPIC_SENDRECV_REPLACE_FT);
738
739 MPIDI_FUNC_ENTER(MPID_STATE_MPIC_SENDRECV_REPLACE_FT);
740
741 MPIU_DBG_MSG_S(PT2PT, TYPICAL, "IN: errflag = %s", *errflag?"TRUE":"FALSE");
742
743 if (!MPIR_PARAM_ENABLE_COLL_FT_RET) {
744 mpi_errno = MPIC_Sendrecv_replace(buf, count, datatype,
745 dest, sendtag,
746 source, recvtag,
747 comm, status);
748 goto fn_exit;
749 }
750
751 if (status == MPI_STATUS_IGNORE)
752 status = &mystatus;
753
754 if (*errflag) {
755 mpi_errno = MPIC_Sendrecv_replace(buf, count, datatype,
756 dest, MPIR_ERROR_TAG,
757 source, MPI_ANY_TAG,
758 comm, status);
759 goto fn_exit;
760 }
761
762 mpi_errno = MPIC_Sendrecv_replace(buf, count, datatype,
763 dest, sendtag,
764 source, MPI_ANY_TAG,
765 comm, status);
766 if (mpi_errno) MPIU_ERR_POP(mpi_errno);
767
768 if (source != MPI_PROC_NULL) {
769 if (status->MPI_TAG == MPIR_ERROR_TAG)
770 *errflag = TRUE;
771 else {
772 MPIU_Assert(status->MPI_TAG == recvtag);
773 }
774 }
775
776 fn_exit:
777 MPIU_DBG_MSG_S(PT2PT, TYPICAL, "OUT: errflag = %s", *errflag?"TRUE":"FALSE");
778 MPIDI_FUNC_EXIT(MPID_STATE_MPIC_SENDRECV_REPLACE_FT);
779 return mpi_errno;
780 fn_fail:
781 goto fn_exit;
782 }
783
784 #undef FUNCNAME
785 #define FUNCNAME MPIC_Isend_ft
786 #undef FCNAME
787 #define FCNAME MPIU_QUOTE(FUNCNAME)
MPIC_Isend_ft(const void * buf,int count,MPI_Datatype datatype,int dest,int tag,MPI_Comm comm,MPI_Request * request,int * errflag)788 int MPIC_Isend_ft(const void *buf, int count, MPI_Datatype datatype, int dest, int tag,
789 MPI_Comm comm, MPI_Request *request, int *errflag)
790 {
791 int mpi_errno = MPI_SUCCESS;
792 MPIDI_STATE_DECL(MPID_STATE_MPIC_ISEND_FT);
793
794 MPIDI_FUNC_ENTER(MPID_STATE_MPIC_ISEND_FT);
795
796 MPIU_DBG_MSG_S(PT2PT, TYPICAL, "IN: errflag = %s", *errflag?"TRUE":"FALSE");
797
798 if (*errflag && MPIR_PARAM_ENABLE_COLL_FT_RET)
799 mpi_errno = MPIC_Isend(buf, count, datatype, dest, MPIR_ERROR_TAG, comm, request);
800 else
801 mpi_errno = MPIC_Isend(buf, count, datatype, dest, tag, comm, request);
802
803 fn_exit:
804 MPIDI_FUNC_EXIT(MPID_STATE_MPIC_ISEND_FT);
805 return mpi_errno;
806 fn_fail:
807 goto fn_exit;
808 }
809
810 #undef FUNCNAME
811 #define FUNCNAME MPIC_Irecv_ft
812 #undef FCNAME
813 #define FCNAME MPIU_QUOTE(FUNCNAME)
MPIC_Irecv_ft(void * buf,int count,MPI_Datatype datatype,int source,int tag,MPI_Comm comm,MPI_Request * request)814 int MPIC_Irecv_ft(void *buf, int count, MPI_Datatype datatype, int source,
815 int tag, MPI_Comm comm, MPI_Request *request)
816 {
817 int mpi_errno = MPI_SUCCESS;
818 MPIDI_STATE_DECL(MPID_STATE_MPIC_IRECV_FT);
819
820 MPIDI_FUNC_ENTER(MPID_STATE_MPIC_IRECV_FT);
821
822 if (MPIR_PARAM_ENABLE_COLL_FT_RET)
823 mpi_errno = MPIC_Irecv(buf, count, datatype, source, MPI_ANY_TAG, comm, request);
824 else
825 mpi_errno = MPIC_Irecv(buf, count, datatype, source, tag, comm, request);
826
827 fn_exit:
828 MPIDI_FUNC_EXIT(MPID_STATE_MPIC_IRECV_FT);
829 return mpi_errno;
830 fn_fail:
831 goto fn_exit;
832 }
833
834
835 #undef FUNCNAME
836 #define FUNCNAME MPIC_Waitall_ft
837 #undef FCNAME
838 #define FCNAME MPIU_QUOTE(FUNCNAME)
MPIC_Waitall_ft(int numreq,MPI_Request requests[],MPI_Status statuses[],int * errflag)839 int MPIC_Waitall_ft(int numreq, MPI_Request requests[], MPI_Status statuses[], int *errflag)
840 {
841 int mpi_errno = MPI_SUCCESS;
842 int i;
843 MPIDI_STATE_DECL(MPID_STATE_MPIC_WAITALL_FT);
844
845 MPIDI_FUNC_ENTER(MPID_STATE_MPIC_WAITALL_FT);
846
847 MPIU_Assert(statuses != MPI_STATUSES_IGNORE);
848
849 MPIU_DBG_MSG_S(PT2PT, TYPICAL, "IN: errflag = %s", *errflag?"TRUE":"FALSE");
850
851 /* The MPI_TAG field is not set for send oeprations, so if we want
852 to check for MPIR_ERROR_TAG below, we should initialize all tag
853 fields here. */
854 for (i = 0; i < numreq; ++i)
855 statuses[i].MPI_TAG = 0;
856
857 mpi_errno = MPIR_Waitall_impl(numreq, requests, statuses);
858 if (mpi_errno) MPIU_ERR_POP(mpi_errno);
859
860 if (*errflag || !MPIR_PARAM_ENABLE_COLL_FT_RET)
861 goto fn_exit;
862
863 for (i = 0; i < numreq; ++i) {
864 if (statuses[i].MPI_TAG == MPIR_ERROR_TAG) {
865 *errflag = TRUE;
866 break;
867 }
868 }
869
870 fn_exit:
871 MPIU_DBG_MSG_S(PT2PT, TYPICAL, "OUT: errflag = %s", *errflag?"TRUE":"FALSE");
872 MPIDI_FUNC_EXIT(MPID_STATE_MPIC_WAITALL_FT);
873 return mpi_errno;
874 fn_fail:
875 goto fn_exit;
876 }
877