1 /*
2 * Copyright (C) by Argonne National Laboratory
3 * See COPYRIGHT in top-level directory
4 */
5
6 #include "mpidimpl.h"
7
8 /*
9 * MPID_Send()
10 */
MPID_Send(const void * buf,MPI_Aint count,MPI_Datatype datatype,int rank,int tag,MPIR_Comm * comm,int context_offset,MPIR_Request ** request)11 int MPID_Send(const void * buf, MPI_Aint count, MPI_Datatype datatype, int rank,
12 int tag, MPIR_Comm * comm, int context_offset,
13 MPIR_Request ** request)
14 {
15 intptr_t data_sz;
16 int dt_contig;
17 MPI_Aint dt_true_lb;
18 MPIR_Datatype* dt_ptr;
19 MPIR_Request * sreq = NULL;
20 MPIDI_VC_t * vc;
21 #if defined(MPID_USE_SEQUENCE_NUMBERS)
22 MPID_Seqnum_t seqnum;
23 #endif
24 int eager_threshold = -1;
25 int mpi_errno = MPI_SUCCESS;
26 MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPID_SEND);
27
28 MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPID_SEND);
29
30 MPL_DBG_MSG_FMT(MPIDI_CH3_DBG_OTHER,VERBOSE,(MPL_DBG_FDEST,
31 "rank=%d, tag=%d, context=%d",
32 rank, tag, comm->context_id + context_offset));
33
34 /* Check to make sure the communicator hasn't already been revoked */
35 if (comm->revoked &&
36 MPIR_AGREE_TAG != MPIR_TAG_MASK_ERROR_BITS(tag & ~MPIR_TAG_COLL_BIT) &&
37 MPIR_SHRINK_TAG != MPIR_TAG_MASK_ERROR_BITS(tag & ~MPIR_TAG_COLL_BIT)) {
38 MPIR_ERR_SETANDJUMP(mpi_errno,MPIX_ERR_REVOKED,"**revoked");
39 }
40
41 if (rank == comm->rank && comm->comm_kind != MPIR_COMM_KIND__INTERCOMM)
42 {
43 mpi_errno = MPIDI_Isend_self(buf, count, datatype, rank, tag, comm,
44 context_offset, MPIDI_REQUEST_TYPE_SEND,
45 &sreq);
46
47 /* In the single threaded case, sending to yourself will cause
48 deadlock. Note that in the runtime-thread case, this check
49 will not be made (long-term FIXME) */
50 # ifndef MPICH_IS_THREADED
51 {
52 if (sreq != NULL && MPIR_cc_get(sreq->cc) != 0) {
53 MPIR_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER,
54 "**dev|selfsenddeadlock");
55 }
56 }
57 # endif
58 if (mpi_errno != MPI_SUCCESS) { MPIR_ERR_POP(mpi_errno); }
59 goto fn_exit;
60 }
61
62 MPIDI_Comm_get_vc_set_active(comm, rank, &vc);
63 MPIR_ERR_CHKANDJUMP1(vc->state == MPIDI_VC_STATE_MORIBUND, mpi_errno, MPIX_ERR_PROC_FAILED, "**comm_fail", "**comm_fail %d", rank);
64
65 #ifdef ENABLE_COMM_OVERRIDES
66 if (vc->comm_ops && vc->comm_ops->send)
67 {
68 mpi_errno = vc->comm_ops->send( vc, buf, count, datatype, rank, tag, comm, context_offset, &sreq);
69 goto fn_exit;
70 }
71 #endif
72
73 MPIDI_Datatype_get_info(count, datatype, dt_contig, data_sz, dt_ptr,
74 dt_true_lb);
75
76
77 if (data_sz == 0)
78 {
79 MPIDI_CH3_Pkt_t upkt;
80 MPIDI_CH3_Pkt_eager_send_t * const eager_pkt = &upkt.eager_send;
81
82 MPL_DBG_MSG(MPIDI_CH3_DBG_OTHER,VERBOSE,"sending zero length message");
83 MPIDI_Pkt_init(eager_pkt, MPIDI_CH3_PKT_EAGER_SEND);
84 eager_pkt->match.parts.rank = comm->rank;
85 eager_pkt->match.parts.tag = tag;
86 eager_pkt->match.parts.context_id = comm->context_id + context_offset;
87 eager_pkt->sender_req_id = MPI_REQUEST_NULL;
88 eager_pkt->data_sz = 0;
89
90 MPIDI_VC_FAI_send_seqnum(vc, seqnum);
91 MPIDI_Pkt_set_seqnum(eager_pkt, seqnum);
92
93 MPID_THREAD_CS_ENTER(POBJ, vc->pobj_mutex);
94 mpi_errno = MPIDI_CH3_iStartMsg(vc, eager_pkt, sizeof(*eager_pkt), &sreq);
95 MPID_THREAD_CS_EXIT(POBJ, vc->pobj_mutex);
96 /* --BEGIN ERROR HANDLING-- */
97 if (mpi_errno != MPI_SUCCESS)
98 {
99 MPIR_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER,"**ch3|eagermsg");
100 }
101 /* --END ERROR HANDLING-- */
102 if (sreq != NULL)
103 {
104 MPIDI_Request_set_seqnum(sreq, seqnum);
105 MPIDI_Request_set_type(sreq, MPIDI_REQUEST_TYPE_SEND);
106 /* sreq->comm = comm;
107 MPIR_Comm_add_ref(comm); -- not necessary for blocking functions */
108 }
109
110 goto fn_exit;
111 }
112
113 MPIDI_CH3_GET_EAGER_THRESHOLD(&eager_threshold, comm, vc);
114
115 /* FIXME: flow control: limit number of outstanding eager messages
116 containing data and need to be buffered by the receiver */
117 #ifdef USE_EAGER_SHORT
118 if (dt_contig && data_sz <= MPIDI_EAGER_SHORT_SIZE) {
119 mpi_errno = MPIDI_CH3_EagerContigShortSend( &sreq,
120 MPIDI_CH3_PKT_EAGERSHORT_SEND,
121 (char *)buf + dt_true_lb,
122 data_sz, rank, tag, comm,
123 context_offset );
124 }
125 else
126 #endif
127
128 if (data_sz + sizeof(MPIDI_CH3_Pkt_eager_send_t) <= eager_threshold)
129 {
130 if (dt_contig)
131 {
132 mpi_errno = MPIDI_CH3_EagerContigSend( &sreq,
133 MPIDI_CH3_PKT_EAGER_SEND,
134 (char *)buf + dt_true_lb,
135 data_sz, rank, tag, comm,
136 context_offset );
137 }
138 else
139 {
140 MPIDI_Request_create_sreq(sreq, mpi_errno, goto fn_exit);
141 MPIDI_Request_set_type(sreq, MPIDI_REQUEST_TYPE_SEND);
142 mpi_errno = MPIDI_CH3_EagerNoncontigSend( &sreq,
143 MPIDI_CH3_PKT_EAGER_SEND,
144 buf, count, datatype,
145 rank, tag,
146 comm, context_offset );
147 }
148 }
149 else
150 {
151 MPIDI_Request_create_sreq(sreq, mpi_errno, goto fn_exit);
152 MPIDI_Request_set_type(sreq, MPIDI_REQUEST_TYPE_SEND);
153 mpi_errno = vc->rndvSend_fn( &sreq, buf, count, datatype, dt_contig,
154 data_sz, dt_true_lb, rank, tag, comm,
155 context_offset );
156 /* Note that we don't increase the ref count on the datatype
157 because this is a blocking call, and the calling routine
158 must wait until sreq completes */
159 }
160
161 fn_fail:
162 fn_exit:
163 *request = sreq;
164
165 MPL_DBG_STMT(MPIDI_CH3_DBG_OTHER,VERBOSE,
166 {
167 if (mpi_errno == MPI_SUCCESS) {
168 if (sreq) {
169 MPL_DBG_MSG_P(MPIDI_CH3_DBG_OTHER,VERBOSE,
170 "request allocated, handle=0x%08x", sreq->handle);
171 }
172 else
173 {
174 MPL_DBG_MSG(MPIDI_CH3_DBG_OTHER,VERBOSE,
175 "operation complete, no requests allocated");
176 }
177 }
178 }
179 );
180
181 MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPID_SEND);
182 return mpi_errno;
183 }
184
MPID_Send_coll(const void * buf,MPI_Aint count,MPI_Datatype datatype,int rank,int tag,MPIR_Comm * comm,int context_offset,MPIR_Request ** request,MPIR_Errflag_t * errflag)185 int MPID_Send_coll(const void *buf, MPI_Aint count, MPI_Datatype datatype, int rank, int tag,
186 MPIR_Comm * comm, int context_offset, MPIR_Request ** request,
187 MPIR_Errflag_t * errflag)
188 {
189 int mpi_errno = MPI_SUCCESS;
190
191 MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPID_SEND_COLL);
192 MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPID_SEND_COLL);
193
194 switch (*errflag) {
195 case MPIR_ERR_NONE:
196 break;
197 case MPIR_ERR_PROC_FAILED:
198 MPIR_TAG_SET_PROC_FAILURE_BIT(tag);
199 break;
200 default:
201 MPIR_TAG_SET_ERROR_BIT(tag);
202 }
203
204 mpi_errno = MPID_Send(buf, count, datatype, rank, tag, comm, context_offset, request);
205
206 MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPID_SEND_COLL);
207
208 return mpi_errno;
209 }
210