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