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