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