1 /* -*- Mode: C; c-basic-offset:4 ; -*- */
2 /*
3  *  (C) 2001 by Argonne National Laboratory.
4  *      See COPYRIGHT in top-level directory.
5  */
6 
7 #include "mpidimpl.h"
8 
9 int (*MPIDI_Anysource_iprobe_fn)(int tag, MPID_Comm * comm, int context_offset, int *flag,
10                                  MPI_Status * status) = NULL;
11 
12 #undef FUNCNAME
13 #define FUNCNAME MPID_Iprobe
14 #undef FCNAME
15 #define FCNAME MPIDI_QUOTE(FUNCNAME)
MPID_Iprobe(int source,int tag,MPID_Comm * comm,int context_offset,int * flag,MPI_Status * status)16 int MPID_Iprobe(int source, int tag, MPID_Comm *comm, int context_offset,
17 		int *flag, MPI_Status *status)
18 {
19     const int context = comm->recvcontext_id + context_offset;
20     int found = 0;
21     int mpi_errno = MPI_SUCCESS;
22     MPIDI_STATE_DECL(MPID_STATE_MPID_IPROBE);
23 
24     MPIDI_FUNC_ENTER(MPID_STATE_MPID_IPROBE);
25 
26     if (source == MPI_PROC_NULL)
27     {
28 	MPIR_Status_set_procnull(status);
29 	/* We set the flag to true because an MPI_Recv with this rank will
30 	   return immediately */
31 	*flag = TRUE;
32 	goto fn_exit;
33     }
34 
35 #ifdef ENABLE_COMM_OVERRIDES
36     if (MPIDI_Anysource_iprobe_fn) {
37         if (source == MPI_ANY_SOURCE) {
38             /* if it's anysource, check shm, then check the network.
39                If still not found, call progress, and check again. */
40 
41             /* check shm*/
42             MPIU_THREAD_CS_ENTER(MSGQUEUE,);
43             found = MPIDI_CH3U_Recvq_FU(source, tag, context, status);
44             MPIU_THREAD_CS_EXIT(MSGQUEUE,);
45             if (!found) {
46                 /* not found, check network */
47                 mpi_errno = MPIDI_Anysource_iprobe_fn(tag, comm, context_offset, &found, status);
48                 if (mpi_errno) MPIU_ERR_POP(mpi_errno);
49                 if (!found) {
50                     /* still not found, make some progress*/
51                     mpi_errno = MPIDI_CH3_Progress_poke();
52                     if (mpi_errno) MPIU_ERR_POP(mpi_errno);
53                     /* check shm again */
54                     MPIU_THREAD_CS_ENTER(MSGQUEUE,);
55                     found = MPIDI_CH3U_Recvq_FU(source, tag, context, status);
56                     MPIU_THREAD_CS_EXIT(MSGQUEUE,);
57                     if (!found) {
58                         /* check network again */
59                         mpi_errno = MPIDI_Anysource_iprobe_fn(tag, comm, context_offset, &found, status);
60                         if (mpi_errno) MPIU_ERR_POP(mpi_errno);
61                     }
62                 }
63             }
64             *flag = found;
65             goto fn_exit;
66         } else {
67             /* it's not anysource, check if the netmod has overridden it */
68             MPIDI_VC_t * vc;
69             MPIDI_Comm_get_vc_set_active(comm, source, &vc);
70             if (vc->comm_ops && vc->comm_ops->iprobe) {
71                 mpi_errno = vc->comm_ops->iprobe(vc, source, tag, comm, context_offset, &found, status);
72                 if (mpi_errno) MPIU_ERR_POP(mpi_errno);
73                 *flag = found;
74                 goto fn_exit;
75             }
76             /* fall-through to shm case */
77         }
78     }
79 #endif
80 
81     /* FIXME: The routine CH3U_Recvq_FU is used only by the probe functions;
82        it should atomically return the flag and status rather than create
83        a request.  Note that in some cases it will be possible to
84        atomically query the unexpected receive list (which is what the
85        probe routines are for). */
86     MPIU_THREAD_CS_ENTER(MSGQUEUE,);
87     found = MPIDI_CH3U_Recvq_FU( source, tag, context, status );
88     MPIU_THREAD_CS_EXIT(MSGQUEUE,);
89     if (!found) {
90 	/* Always try to advance progress before returning failure
91 	   from the iprobe test.  */
92 	/* FIXME: It would be helpful to know if the Progress_poke
93 	   operation causes any change in state; we could then avoid
94 	   a second test of the receive queue if we knew that nothing
95 	   had changed */
96 	mpi_errno = MPID_Progress_poke();
97 	MPIU_THREAD_CS_ENTER(MSGQUEUE,);
98 	found = MPIDI_CH3U_Recvq_FU( source, tag, context, status );
99 	MPIU_THREAD_CS_EXIT(MSGQUEUE,);
100     }
101 
102     *flag = found;
103 
104  fn_exit:
105     MPIDI_FUNC_EXIT(MPID_STATE_MPID_IPROBE);
106     return mpi_errno;
107  fn_fail:
108     goto fn_exit;
109 }
110