root/mpich2/trunk/src/mpid/ch3/src/ch3u_eager.c @ 4888

Revision 4888, 27.7 KB (checked in by buntinas, 5 months ago)

squashed more warnings

Line 
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/*
10 * Send an eager message.  To optimize for the important, short contiguous
11 * message case, there are separate routines for the contig and non-contig
12 * datatype cases.
13 */
14
15#undef FUNCNAME
16#define FUNCNAME MPIDI_CH3_SendNoncontig_iov
17#undef FCNAME
18#define FCNAME MPIDI_QUOTE(FUNCNAME)
19/* MPIDI_CH3_SendNoncontig_iov - Sends a message by loading an
20   IOV and calling iSendv.  The caller must initialize
21   sreq->dev.segment as well as segment_first and segment_size. */
22int MPIDI_CH3_SendNoncontig_iov( MPIDI_VC_t *vc, MPID_Request *sreq,
23                                 void *header, MPIDI_msg_sz_t hdr_sz )
24{
25    int mpi_errno = MPI_SUCCESS;
26    int iov_n;
27    MPID_IOV iov[MPID_IOV_LIMIT];
28    MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3_SENDNONCONTIG_IOV);
29
30    MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3_SENDNONCONTIG_IOV);
31
32    iov[0].MPID_IOV_BUF = header;
33    iov[0].MPID_IOV_LEN = hdr_sz;
34
35    iov_n = MPID_IOV_LIMIT - 1;
36
37    mpi_errno = MPIDI_CH3U_Request_load_send_iov(sreq, &iov[1], &iov_n);
38    if (mpi_errno == MPI_SUCCESS)
39    {
40        iov_n += 1;
41       
42        /* Note this routine is invoked withing a CH3 critical section */
43        /* MPIU_THREAD_CS_ENTER(CH3COMM,vc); */
44        mpi_errno = MPIU_CALL(MPIDI_CH3,iSendv(vc, sreq, iov, iov_n));
45        /* MPIU_THREAD_CS_EXIT(CH3COMM,vc); */
46        /* --BEGIN ERROR HANDLING-- */
47        if (mpi_errno != MPI_SUCCESS)
48        {
49            MPIU_Object_set_ref(sreq, 0);
50            MPIDI_CH3_Request_destroy(sreq);
51            mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_FATAL, 
52                         FCNAME, __LINE__, MPI_ERR_OTHER, "**ch3|eagermsg", 0);
53            goto fn_fail;
54        }
55        /* --END ERROR HANDLING-- */
56
57        /* Note that in the non-blocking case, we need to add a ref to the
58           datatypes */
59    }
60    else
61    {
62        /* --BEGIN ERROR HANDLING-- */
63        MPIU_Object_set_ref(sreq, 0);
64        MPIDI_CH3_Request_destroy(sreq);
65        mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, 
66                    FCNAME, __LINE__, MPI_ERR_OTHER, "**ch3|loadsendiov", 0);
67        goto fn_fail;
68        /* --END ERROR HANDLING-- */
69    }
70
71
72 fn_exit:
73    MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_CH3_SENDNONCONTIG_IOV);
74    return mpi_errno;
75 fn_fail:
76    goto fn_exit;
77}
78
79/* This function will allocate a segment.  That segment must be freed when
80   it is no longer needed */
81#undef FUNCNAME
82#define FUNCNAME MPIDI_EagerNoncontigSend
83#undef FCNAME
84#define FCNAME MPIDI_QUOTE(FUNCNAME)
85/* MPIDI_CH3_EagerNoncontigSend - Eagerly send noncontiguous data */
86int MPIDI_CH3_EagerNoncontigSend( MPID_Request **sreq_p, 
87                                  MPIDI_CH3_Pkt_type_t reqtype, 
88                                  const void * buf, int count, 
89                                  MPI_Datatype datatype, MPIDI_msg_sz_t data_sz,
90                                  int rank, 
91                                  int tag, MPID_Comm * comm, 
92                                  int context_offset )
93{
94    int mpi_errno = MPI_SUCCESS;
95    MPIDI_VC_t * vc;
96    MPID_Request *sreq = *sreq_p;
97    MPIDI_CH3_Pkt_t upkt;
98    MPIDI_CH3_Pkt_eager_send_t * const eager_pkt = &upkt.eager_send;
99   
100    MPIU_DBG_MSG_FMT(CH3_OTHER,VERBOSE,(MPIU_DBG_FDEST,
101                     "sending non-contiguous eager message, data_sz=" MPIDI_MSG_SZ_FMT,
102                                        data_sz));
103    sreq->dev.OnDataAvail = 0;
104    sreq->dev.OnFinal = 0;
105
106    MPIDI_Pkt_init(eager_pkt, reqtype);
107    eager_pkt->match.parts.rank = comm->rank;
108    eager_pkt->match.parts.tag  = tag;
109    eager_pkt->match.parts.context_id   = comm->context_id + context_offset;
110    eager_pkt->sender_req_id    = MPI_REQUEST_NULL;
111    eager_pkt->data_sz          = data_sz;
112   
113    MPIDI_Comm_get_vc_set_active(comm, rank, &vc);
114
115    MPIDI_VC_FAI_send_seqnum(vc, seqnum);
116    MPIDI_Pkt_set_seqnum(eager_pkt, seqnum);
117    MPIDI_Request_set_seqnum(sreq, seqnum);
118
119    MPIU_DBG_MSGPKT(vc,tag,eager_pkt->match.parts.context_id,rank,data_sz,
120                    "Eager");
121           
122    sreq->dev.segment_ptr = MPID_Segment_alloc( );
123    MPIU_ERR_CHKANDJUMP1((sreq->dev.segment_ptr == NULL), mpi_errno, MPI_ERR_OTHER, "**nomem", "**nomem %s", "MPID_Segment_alloc");
124
125    MPID_Segment_init(buf, count, datatype, sreq->dev.segment_ptr, 0);
126    sreq->dev.segment_first = 0;
127    sreq->dev.segment_size = data_sz;
128           
129    MPIU_THREAD_CS_ENTER(CH3COMM,vc);
130    mpi_errno = vc->sendNoncontig_fn(vc, sreq, eager_pkt, 
131                                     sizeof(MPIDI_CH3_Pkt_eager_send_t));
132    MPIU_THREAD_CS_EXIT(CH3COMM,vc);
133    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
134
135 fn_exit:
136    return mpi_errno;
137 fn_fail:
138    *sreq_p = NULL;
139    goto fn_exit;
140}
141
142/* Send a contiguous eager message.  We'll want to optimize (and possibly
143   inline) this.
144
145   Make sure that buf is at the beginning of the data to send;
146   adjust by adding dt_true_lb if necessary
147*/
148#undef FUNCNAME
149#define FUNCNAME MPIDI_EagerContigSend
150#undef FCNAME
151#define FCNAME MPIDI_QUOTE(FUNCNAME)
152int MPIDI_CH3_EagerContigSend( MPID_Request **sreq_p, 
153                               MPIDI_CH3_Pkt_type_t reqtype, 
154                               const void * buf, MPIDI_msg_sz_t data_sz, int rank, 
155                               int tag, MPID_Comm * comm, int context_offset )
156{
157    int mpi_errno = MPI_SUCCESS;
158    MPIDI_VC_t * vc;
159    MPIDI_CH3_Pkt_t upkt;
160    MPIDI_CH3_Pkt_eager_send_t * const eager_pkt = &upkt.eager_send;
161    MPID_Request *sreq = *sreq_p;
162    MPID_IOV iov[2];
163   
164    MPIDI_Pkt_init(eager_pkt, reqtype);
165    eager_pkt->match.parts.rank = comm->rank;
166    eager_pkt->match.parts.tag  = tag;
167    eager_pkt->match.parts.context_id   = comm->context_id + context_offset;
168    eager_pkt->sender_req_id    = MPI_REQUEST_NULL;
169    eager_pkt->data_sz          = data_sz;
170   
171    iov[0].MPID_IOV_BUF = (MPID_IOV_BUF_CAST)eager_pkt;
172    iov[0].MPID_IOV_LEN = sizeof(*eager_pkt);
173   
174    MPIU_DBG_MSG_FMT(CH3_OTHER,VERBOSE,(MPIU_DBG_FDEST,
175               "sending contiguous eager message, data_sz=" MPIDI_MSG_SZ_FMT,
176                                        data_sz));
177           
178    iov[1].MPID_IOV_BUF = (MPID_IOV_BUF_CAST) buf;
179    iov[1].MPID_IOV_LEN = data_sz;
180   
181    MPIDI_Comm_get_vc_set_active(comm, rank, &vc);
182    MPIDI_VC_FAI_send_seqnum(vc, seqnum);
183    MPIDI_Pkt_set_seqnum(eager_pkt, seqnum);
184   
185    MPIU_DBG_MSGPKT(vc,tag,eager_pkt->match.parts.context_id,rank,data_sz,"EagerContig");
186    MPIU_THREAD_CS_ENTER(CH3COMM,vc);
187    mpi_errno = MPIU_CALL(MPIDI_CH3,iStartMsgv(vc, iov, 2, sreq_p));
188    MPIU_THREAD_CS_EXIT(CH3COMM,vc);
189    if (mpi_errno != MPI_SUCCESS) {
190        MPIU_ERR_SETFATALANDJUMP(mpi_errno,MPI_ERR_OTHER,"**ch3|eagermsg");
191    }
192
193    sreq = *sreq_p;
194    if (sreq != NULL)
195    {
196        MPIDI_Request_set_seqnum(sreq, seqnum);
197        MPIDI_Request_set_type(sreq, MPIDI_REQUEST_TYPE_SEND);
198    }
199
200 fn_fail:
201    return mpi_errno;
202}
203
204#ifdef USE_EAGER_SHORT
205/* Send a short contiguous eager message.  We'll want to optimize (and possibly
206   inline) this
207
208   Make sure that buf is at the beginning of the data to send;
209   adjust by adding dt_true_lb if necessary
210
211   We may need a nonblocking (cancellable) version of this, which will
212   have a smaller payload.
213*/
214#undef FUNCNAME
215#define FUNCNAME MPIDI_EagerContigShortSend
216#undef FCNAME
217#define FCNAME MPIDI_QUOTE(FUNCNAME)
218int MPIDI_CH3_EagerContigShortSend( MPID_Request **sreq_p, 
219                                    MPIDI_CH3_Pkt_type_t reqtype, 
220                                    const void * buf, MPIDI_msg_sz_t data_sz, int rank, 
221                                    int tag, MPID_Comm * comm, 
222                                    int context_offset )
223{
224    int mpi_errno = MPI_SUCCESS;
225    MPIDI_VC_t * vc;
226    MPIDI_CH3_Pkt_t upkt;
227    MPIDI_CH3_Pkt_eagershort_send_t * const eagershort_pkt = 
228        &upkt.eagershort_send;
229    MPID_Request *sreq = *sreq_p;
230   
231    /*    printf( "Sending short eager\n"); fflush(stdout); */
232    MPIDI_Pkt_init(eagershort_pkt, reqtype);
233    eagershort_pkt->match.parts.rank         = comm->rank;
234    eagershort_pkt->match.parts.tag          = tag;
235    eagershort_pkt->match.parts.context_id = comm->context_id + context_offset;
236    eagershort_pkt->data_sz          = data_sz;
237   
238    MPIU_DBG_MSG_FMT(CH3_OTHER,VERBOSE,(MPIU_DBG_FDEST,
239       "sending contiguous short eager message, data_sz=" MPIDI_MSG_SZ_FMT,
240                                        data_sz));
241           
242    MPIDI_Comm_get_vc_set_active(comm, rank, &vc);
243    MPIDI_VC_FAI_send_seqnum(vc, seqnum);
244    MPIDI_Pkt_set_seqnum(eagershort_pkt, seqnum);
245
246    /* Copy the payload. We could optimize this if data_sz & 0x3 == 0
247       (copy (data_sz >> 2) ints, inline that since data size is
248       currently limited to 4 ints */
249    {
250        unsigned char * restrict p = 
251            (unsigned char *)eagershort_pkt->data;
252        unsigned char const * restrict bufp = (unsigned char *)buf;
253        int i;
254        for (i=0; i<data_sz; i++) {
255            *p++ = *bufp++;
256        }
257    }
258
259    MPIU_DBG_MSGPKT(vc,tag,eagershort_pkt->match.parts.context_id,rank,data_sz,
260                    "EagerShort");
261    MPIU_THREAD_CS_ENTER(CH3COMM,vc);
262    mpi_errno = MPIU_CALL(MPIDI_CH3,iStartMsg(vc, eagershort_pkt, 
263                                      sizeof(*eagershort_pkt), sreq_p ));
264    MPIU_THREAD_CS_EXIT(CH3COMM,vc);
265    if (mpi_errno != MPI_SUCCESS) {
266        MPIU_ERR_SETFATALANDJUMP(mpi_errno,MPI_ERR_OTHER,"**ch3|eagermsg");
267    }
268    sreq = *sreq_p;
269    if (sreq != NULL) {
270        /*printf( "Surprise, did not complete send of eagershort (starting connection?)\n" );
271          fflush(stdout); */
272        MPIDI_Request_set_seqnum(sreq, seqnum);
273        MPIDI_Request_set_type(sreq, MPIDI_REQUEST_TYPE_SEND);
274    }
275
276 fn_fail:   
277    return mpi_errno;
278}
279
280/* This is the matching handler for the EagerShort message defined above */
281
282#undef FUNCNAME
283#define FUNCNAME MPIDI_CH3_PktHandler_EagerShortSend
284#undef FCNAME
285#define FCNAME MPIDI_QUOTE(FUNCNAME)
286int MPIDI_CH3_PktHandler_EagerShortSend( MPIDI_VC_t *vc, MPIDI_CH3_Pkt_t *pkt, 
287                                         MPIDI_msg_sz_t *buflen, MPID_Request **rreqp )
288{
289    MPIDI_CH3_Pkt_eagershort_send_t * eagershort_pkt = &pkt->eagershort_send;
290    MPID_Request * rreq;
291    int found;
292    int mpi_errno = MPI_SUCCESS;
293
294    /* printf( "Receiving short eager!\n" ); fflush(stdout); */
295    MPIU_DBG_MSG_FMT(CH3_OTHER,VERBOSE,(MPIU_DBG_FDEST,
296        "received eagershort send pkt, rank=%d, tag=%d, context=%d",
297        eagershort_pkt->match.parts.rank, 
298        eagershort_pkt->match.parts.tag, 
299        eagershort_pkt->match.parts.context_id));
300           
301    MPIU_DBG_MSGPKT(vc,eagershort_pkt->match.parts.tag,
302                    eagershort_pkt->match.parts.context_id,
303                    eagershort_pkt->match.parts.rank,eagershort_pkt->data_sz,
304                    "ReceivedEagerShort");
305    rreq = MPIDI_CH3U_Recvq_FDP_or_AEU(&eagershort_pkt->match, &found);
306    MPIU_ERR_CHKANDJUMP1(!rreq, mpi_errno,MPI_ERR_OTHER, "**nomemreq", "**nomemuereq %d", MPIDI_CH3U_Recvq_count_unexp());
307
308    (rreq)->status.MPI_SOURCE = (eagershort_pkt)->match.parts.rank;
309    (rreq)->status.MPI_TAG    = (eagershort_pkt)->match.parts.tag;
310    (rreq)->status.count      = (eagershort_pkt)->data_sz;
311    (rreq)->dev.recv_data_sz  = (eagershort_pkt)->data_sz;
312    MPIDI_Request_set_seqnum((rreq), (eagershort_pkt)->seqnum);
313    /* FIXME: Why do we set the message type? */
314    MPIDI_Request_set_msg_type((rreq), MPIDI_REQUEST_EAGER_MSG);
315    /* The request is still complete (in the sense of
316       having all data) */
317    MPIDI_CH3U_Request_complete(rreq);
318
319    /* This packed completes the reception of the indicated data.
320       The packet handler returns null for a request that requires
321       no further communication */
322    *rreqp = NULL;
323    *buflen = sizeof(MPIDI_CH3_Pkt_t);
324
325    /* Extract the data from the packet */
326    /* Note that if the data size if zero, we're already done */
327    if (rreq->dev.recv_data_sz > 0) {
328        if (found) {
329            int            dt_contig;
330            MPI_Aint       dt_true_lb;
331            MPIDI_msg_sz_t userbuf_sz;
332            MPID_Datatype *dt_ptr;
333            MPIDI_msg_sz_t data_sz;
334
335            /* Make sure that we handle the general (non-contiguous)
336               datatypes correctly while optimizing for the
337               special case */
338            MPIDI_Datatype_get_info(rreq->dev.user_count, rreq->dev.datatype, 
339                                    dt_contig, userbuf_sz, dt_ptr, dt_true_lb);
340               
341            if (rreq->dev.recv_data_sz <= userbuf_sz) {
342                data_sz = rreq->dev.recv_data_sz;
343            }
344            else {
345                MPIU_DBG_MSG_FMT(CH3_OTHER,VERBOSE,(MPIU_DBG_FDEST,
346                    "receive buffer too small; message truncated, msg_sz=" 
347                                          MPIDI_MSG_SZ_FMT ", userbuf_sz="
348                                          MPIDI_MSG_SZ_FMT,
349                                 rreq->dev.recv_data_sz, userbuf_sz));
350                rreq->status.MPI_ERROR = MPIR_Err_create_code(MPI_SUCCESS, 
351                     MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_TRUNCATE,
352                     "**truncate", "**truncate %d %d %d %d", 
353                     rreq->status.MPI_SOURCE, rreq->status.MPI_TAG, 
354                     rreq->dev.recv_data_sz, userbuf_sz );
355                rreq->status.count = userbuf_sz;
356                data_sz = userbuf_sz;
357            }
358
359            if (dt_contig && data_sz == rreq->dev.recv_data_sz) {
360                /* user buffer is contiguous and large enough to store the
361                   entire message.  We can just copy the code */
362
363                /* Copy the payload. We could optimize this
364                   if data_sz & 0x3 == 0
365                   (copy (data_sz >> 2) ints, inline that since data size is
366                   currently limited to 4 ints */
367                {
368                    unsigned char const * restrict p = 
369                        (unsigned char *)eagershort_pkt->data;
370                    unsigned char * restrict bufp = 
371                        (unsigned char *)(char*)(rreq->dev.user_buf) + 
372                        dt_true_lb;
373                    int i;
374                    for (i=0; i<data_sz; i++) {
375                        *bufp++ = *p++;
376                    }
377                }
378                /* FIXME: We want to set the OnDataAvail to the appropriate
379                   function, which depends on whether this is an RMA
380                   request or a pt-to-pt request. */
381                rreq->dev.OnDataAvail = 0;
382                /* The recv_pending_count must be one here (!) because of
383                   the way the pending count is queried.  We may want
384                   to fix this, but it will require a sweep of the code */
385            }
386            else {
387                MPIDI_msg_sz_t recv_data_sz, last;
388                /* user buffer is not contiguous.  Use the segment
389                   code to unpack it, handling various errors and
390                   exceptional cases */
391                /* FIXME: The MPICH2 tests do not exercise this branch */
392                /* printf( "Surprise!\n" ); fflush(stdout);*/
393                rreq->dev.segment_ptr = MPID_Segment_alloc( );
394                MPIU_ERR_CHKANDJUMP1((rreq->dev.segment_ptr == NULL), mpi_errno, MPI_ERR_OTHER, "**nomem", "**nomem %s", "MPID_Segment_alloc");
395
396                MPID_Segment_init(rreq->dev.user_buf, rreq->dev.user_count, 
397                                  rreq->dev.datatype, rreq->dev.segment_ptr, 0);
398
399                recv_data_sz = rreq->dev.recv_data_sz;
400                last    = recv_data_sz;
401                MPID_Segment_unpack( rreq->dev.segment_ptr, 0, 
402                                     &last, eagershort_pkt->data );
403                if (last != recv_data_sz) {
404                    /* --BEGIN ERROR HANDLING-- */
405                    /* There are two cases:  a datatype mismatch (could
406                       not consume all data) or a too-short buffer. We
407                       need to distinguish between these two types. */
408                    rreq->status.count = (int)last;
409                    if (rreq->dev.recv_data_sz <= userbuf_sz) {
410                        MPIU_ERR_SETSIMPLE(rreq->status.MPI_ERROR,MPI_ERR_TYPE,
411                                           "**dtypemismatch");
412                    }
413                    /* --END ERROR HANDLING-- */
414                }
415                rreq->dev.OnDataAvail = 0;
416            }
417        }
418        else {
419            MPIDI_msg_sz_t recv_data_sz;
420            /* This is easy; copy the data into a temporary buffer.
421               To begin with, we use the same temporary location as
422               is used in receiving eager unexpected data.
423             */
424            /* FIXME: When eagershort is enabled, provide a preallocated
425               space for short messages (which is used even if eager short
426               is not used), since we don't want to have a separate check
427               to figure out which buffer we're using (or perhaps we should
428               have a free-buffer-pointer, which can be null if it isn't
429               a buffer that we've allocated). */
430            /* printf( "Allocating into tmp\n" ); fflush(stdout); */
431            recv_data_sz = rreq->dev.recv_data_sz;
432            rreq->dev.tmpbuf = MPIU_Malloc(recv_data_sz);
433            if (!rreq->dev.tmpbuf) {
434                MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER,"**nomem");
435            }
436            rreq->dev.tmpbuf_sz = recv_data_sz;
437            /* Copy the payload. We could optimize this if recv_data_sz & 0x3 == 0
438               (copy (recv_data_sz >> 2) ints, inline that since data size is
439               currently limited to 4 ints */
440            {
441                unsigned char const * restrict p = 
442                    (unsigned char *)eagershort_pkt->data;
443                unsigned char * restrict bufp = 
444                    (unsigned char *)rreq->dev.tmpbuf;
445                int i;
446                for (i=0; i<recv_data_sz; i++) {
447                    *bufp++ = *p++;
448                }
449            }
450            /* printf( "Unexpected eager short\n" ); fflush(stdout); */
451            /* These next two indicate that once matched, there is
452               one more step (the unpack into the user buffer) to perform. */
453            rreq->dev.OnDataAvail = MPIDI_CH3_ReqHandler_UnpackUEBufComplete;
454            rreq->dev.recv_pending_count = 1;
455        }
456
457        if (mpi_errno != MPI_SUCCESS) {
458            MPIU_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_OTHER, "**ch3|postrecv",
459                     "**ch3|postrecv %s", "MPIDI_CH3_PKT_EAGERSHORT_SEND");
460        }
461    }
462
463    /* The semantics of the packet handlers is that a returned request
464       means that additional actions are required on the request */
465    /* We also signal completion (without this, the progress engine
466       may fail to return from a Progress_wait; the probe-unexp test
467       failed without this Progress_signal_completion call) */
468    MPIDI_CH3_Progress_signal_completion();
469
470 fn_fail:
471    return mpi_errno;
472}
473
474#endif
475
476/* Send a contiguous eager message that can be cancelled (e.g.,
477   a nonblocking eager send).  We'll want to optimize (and possibly
478   inline) this
479
480   Make sure that buf is at the beginning of the data to send;
481   adjust by adding dt_true_lb if necessary
482*/
483#undef FUNCNAME
484#define FUNCNAME MPIDI_EagerContigIsend
485#undef FCNAME
486#define FCNAME MPIDI_QUOTE(FUNCNAME)
487int MPIDI_CH3_EagerContigIsend( MPID_Request **sreq_p, 
488                                MPIDI_CH3_Pkt_type_t reqtype, 
489                                const void * buf, MPIDI_msg_sz_t data_sz, int rank, 
490                                int tag, MPID_Comm * comm, int context_offset )
491{
492    int mpi_errno = MPI_SUCCESS;
493    MPIDI_VC_t * vc;
494    MPIDI_CH3_Pkt_t upkt;
495    MPIDI_CH3_Pkt_eager_send_t * const eager_pkt = &upkt.eager_send;
496    MPID_Request *sreq = *sreq_p;
497    MPID_IOV iov[MPID_IOV_LIMIT];
498
499    MPIU_DBG_MSG_FMT(CH3_OTHER,VERBOSE,(MPIU_DBG_FDEST,
500               "sending contiguous eager message, data_sz=" MPIDI_MSG_SZ_FMT,
501                                        data_sz));
502           
503    sreq->dev.OnDataAvail = 0;
504   
505    MPIDI_Pkt_init(eager_pkt, reqtype);
506    eager_pkt->match.parts.rank = comm->rank;
507    eager_pkt->match.parts.tag  = tag;
508    eager_pkt->match.parts.context_id   = comm->context_id + context_offset;
509    eager_pkt->sender_req_id    = sreq->handle;
510    eager_pkt->data_sz          = data_sz;
511   
512    iov[0].MPID_IOV_BUF = (MPID_IOV_BUF_CAST)eager_pkt;
513    iov[0].MPID_IOV_LEN = sizeof(*eager_pkt);
514   
515    iov[1].MPID_IOV_BUF = (MPID_IOV_BUF_CAST) buf;
516    iov[1].MPID_IOV_LEN = data_sz;
517   
518    MPIDI_Comm_get_vc_set_active(comm, rank, &vc);
519    MPIDI_VC_FAI_send_seqnum(vc, seqnum);
520    MPIDI_Pkt_set_seqnum(eager_pkt, seqnum);
521    MPIDI_Request_set_seqnum(sreq, seqnum);
522   
523    MPIU_DBG_MSGPKT(vc,tag,eager_pkt->match.parts.context_id,rank,data_sz,"EagerIsend");
524    MPIU_THREAD_CS_ENTER(CH3COMM,vc);
525    mpi_errno = MPIU_CALL(MPIDI_CH3,iSendv(vc, sreq, iov, 2 ));
526    MPIU_THREAD_CS_EXIT(CH3COMM,vc);
527    /* --BEGIN ERROR HANDLING-- */
528    if (mpi_errno != MPI_SUCCESS)
529    {
530        MPIU_Object_set_ref(sreq, 0);
531        MPIDI_CH3_Request_destroy(sreq);
532        *sreq_p = NULL;
533        mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_FATAL, FCNAME, 
534                            __LINE__, MPI_ERR_OTHER, "**ch3|eagermsg", 0);
535        goto fn_exit;
536    }
537    /* --END ERROR HANDLING-- */
538   
539 fn_exit:
540    return mpi_errno;
541}
542
543/*
544 * Here are the routines that are called by the progress engine to handle
545 * the various rendezvous message requests (cancel of sends is in
546 * mpid_cancel_send.c).
547 */   
548
549#define set_request_info(rreq_, pkt_, msg_type_)                \
550{                                                               \
551    (rreq_)->status.MPI_SOURCE = (pkt_)->match.parts.rank;      \
552    (rreq_)->status.MPI_TAG = (pkt_)->match.parts.tag;          \
553    (rreq_)->status.count = (pkt_)->data_sz;                    \
554    (rreq_)->dev.sender_req_id = (pkt_)->sender_req_id;         \
555    (rreq_)->dev.recv_data_sz = (pkt_)->data_sz;                \
556    MPIDI_Request_set_seqnum((rreq_), (pkt_)->seqnum);          \
557    MPIDI_Request_set_msg_type((rreq_), (msg_type_));           \
558}
559
560/* FIXME: This is not optimized for short messages, which
561   should have the data in the same packet when the data is
562   particularly short (e.g., one 8 byte long word) */
563#undef FUNCNAME
564#define FUNCNAME MPIDI_CH3_PktHandler_EagerSend
565#undef FCNAME
566#define FCNAME MPIDI_QUOTE(FUNCNAME)
567int MPIDI_CH3_PktHandler_EagerSend( MPIDI_VC_t *vc, MPIDI_CH3_Pkt_t *pkt, 
568                                    MPIDI_msg_sz_t *buflen, MPID_Request **rreqp )
569{
570    MPIDI_CH3_Pkt_eager_send_t * eager_pkt = &pkt->eager_send;
571    MPID_Request * rreq;
572    int found;
573    int complete;
574    char *data_buf;
575    MPIDI_msg_sz_t data_len;
576    int mpi_errno = MPI_SUCCESS;
577   
578    MPIU_DBG_MSG_FMT(CH3_OTHER,VERBOSE,(MPIU_DBG_FDEST,
579        "received eager send pkt, sreq=0x%08x, rank=%d, tag=%d, context=%d",
580        eager_pkt->sender_req_id, eager_pkt->match.parts.rank, 
581        eager_pkt->match.parts.tag, eager_pkt->match.parts.context_id));
582    MPIU_DBG_MSGPKT(vc,eager_pkt->match.parts.tag,
583                    eager_pkt->match.parts.context_id,
584                    eager_pkt->match.parts.rank,eager_pkt->data_sz,
585                    "ReceivedEager");
586           
587    rreq = MPIDI_CH3U_Recvq_FDP_or_AEU(&eager_pkt->match, &found);
588    MPIU_ERR_CHKANDJUMP1(!rreq, mpi_errno,MPI_ERR_OTHER, "**nomemreq", "**nomemuereq %d", MPIDI_CH3U_Recvq_count_unexp());
589   
590    set_request_info(rreq, eager_pkt, MPIDI_REQUEST_EAGER_MSG);
591   
592    data_len = ((*buflen - sizeof(MPIDI_CH3_Pkt_t) >= rreq->dev.recv_data_sz)
593                ? rreq->dev.recv_data_sz : *buflen - sizeof(MPIDI_CH3_Pkt_t));
594    data_buf = (char *)pkt + sizeof(MPIDI_CH3_Pkt_t);
595   
596    if (rreq->dev.recv_data_sz == 0) {
597        /* return the number of bytes processed in this function */
598        *buflen = sizeof(MPIDI_CH3_Pkt_t);
599        MPIDI_CH3U_Request_complete(rreq);
600        *rreqp = NULL;
601    }
602    else {
603        if (found) {
604            mpi_errno = MPIDI_CH3U_Receive_data_found( rreq, data_buf,
605                                                       &data_len, &complete );
606        }
607        else {
608            mpi_errno = MPIDI_CH3U_Receive_data_unexpected( rreq, data_buf,
609                                                            &data_len, &complete );
610        }
611
612        if (mpi_errno != MPI_SUCCESS) {
613            MPIU_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_OTHER, "**ch3|postrecv",
614                             "**ch3|postrecv %s", "MPIDI_CH3_PKT_EAGER_SEND");
615        }
616
617        /* return the number of bytes processed in this function */
618        *buflen = sizeof(MPIDI_CH3_Pkt_t) + data_len;
619
620        if (complete) 
621        {
622            MPIDI_CH3U_Request_complete(rreq);
623            *rreqp = NULL;
624        }
625        else
626        {
627            *rreqp = rreq;
628        }
629    }
630
631 fn_fail:
632    return mpi_errno;
633}
634
635
636#undef FUNCNAME
637#define FUNCNAME MPIDI_CH3_PktHandler_ReadySend
638#undef FCNAME
639#define FCNAME MPIDI_QUOTE(FUNCNAME)
640int MPIDI_CH3_PktHandler_ReadySend( MPIDI_VC_t *vc, MPIDI_CH3_Pkt_t *pkt,
641                                    MPIDI_msg_sz_t *buflen, MPID_Request **rreqp )
642{
643    MPIDI_CH3_Pkt_ready_send_t * ready_pkt = &pkt->ready_send;
644    MPID_Request * rreq;
645    int found;
646    int complete;
647    char *data_buf;
648    MPIDI_msg_sz_t data_len;
649    int mpi_errno = MPI_SUCCESS;
650   
651    MPIU_DBG_MSG_FMT(CH3_OTHER,VERBOSE,(MPIU_DBG_FDEST,
652        "received ready send pkt, sreq=0x%08x, rank=%d, tag=%d, context=%d",
653                        ready_pkt->sender_req_id, 
654                        ready_pkt->match.parts.rank, 
655                        ready_pkt->match.parts.tag, 
656                        ready_pkt->match.parts.context_id));
657    MPIU_DBG_MSGPKT(vc,ready_pkt->match.parts.tag,
658                    ready_pkt->match.parts.context_id,
659                    ready_pkt->match.parts.rank,ready_pkt->data_sz,
660                    "ReceivedReady");
661           
662    rreq = MPIDI_CH3U_Recvq_FDP_or_AEU(&ready_pkt->match, &found);
663    MPIU_ERR_CHKANDJUMP1(!rreq, mpi_errno,MPI_ERR_OTHER, "**nomemreq", "**nomemuereq %d", MPIDI_CH3U_Recvq_count_unexp());
664   
665    set_request_info(rreq, ready_pkt, MPIDI_REQUEST_EAGER_MSG);
666   
667    data_len = ((*buflen - sizeof(MPIDI_CH3_Pkt_t) >= rreq->dev.recv_data_sz)
668                ? rreq->dev.recv_data_sz : *buflen - sizeof(MPIDI_CH3_Pkt_t));
669    data_buf = (char *)pkt + sizeof(MPIDI_CH3_Pkt_t);
670   
671    if (found) {
672        if (rreq->dev.recv_data_sz == 0) {
673            /* return the number of bytes processed in this function */
674            *buflen = sizeof(MPIDI_CH3_Pkt_t) + data_len;;
675            MPIDI_CH3U_Request_complete(rreq);
676            *rreqp = NULL;
677        }
678        else {
679            mpi_errno = MPIDI_CH3U_Receive_data_found(rreq, data_buf, &data_len,
680                                                      &complete);
681            if (mpi_errno != MPI_SUCCESS) {
682                MPIU_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_OTHER, 
683                                     "**ch3|postrecv",
684                                     "**ch3|postrecv %s", 
685                                     "MPIDI_CH3_PKT_READY_SEND");
686            }
687
688            /* return the number of bytes processed in this function */
689            *buflen = sizeof(MPIDI_CH3_Pkt_t) + data_len;
690
691            if (complete) 
692            {
693                MPIDI_CH3U_Request_complete(rreq);
694                *rreqp = NULL;
695            }
696            else
697            {
698                *rreqp = rreq;
699            }
700        }
701    }
702    else
703    {
704        /* FIXME: an error packet should be sent back to the sender
705           indicating that the ready-send failed.  On the send
706           side, the error handler for the communicator can be invoked
707           even if the ready-send request has already
708           completed. */
709       
710        /* We need to consume any outstanding associated data and
711           mark the request with an error. */
712       
713        rreq->status.MPI_ERROR = MPIR_Err_create_code(MPI_SUCCESS, 
714                                      MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, 
715                                      MPI_ERR_OTHER, "**rsendnomatch", 
716                                      "**rsendnomatch %d %d", 
717                                      ready_pkt->match.parts.rank,
718                                      ready_pkt->match.parts.tag);
719        rreq->status.count = 0;
720        if (rreq->dev.recv_data_sz > 0)
721        {
722            /* force read of extra data */
723            *rreqp = rreq;
724            rreq->dev.segment_first = 0;
725            rreq->dev.segment_size = 0;
726            mpi_errno = MPIDI_CH3U_Request_load_recv_iov(rreq);
727            if (mpi_errno != MPI_SUCCESS) {
728                MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER,
729                                    "**ch3|loadrecviov");
730            }
731        }
732        else
733        {
734            /* mark data transfer as complete and decrement CC */
735            MPIDI_CH3U_Request_complete(rreq);
736            *rreqp = NULL;
737        }
738        /* we didn't process anything but the header in this case */
739        *buflen = sizeof(MPIDI_CH3_Pkt_t);
740    }
741 fn_fail:
742    return mpi_errno;
743}
744
745
746/*
747 * Define the routines that can print out the cancel packets if
748 * debugging is enabled.
749 */
750#ifdef MPICH_DBG_OUTPUT
751int MPIDI_CH3_PktPrint_EagerSend( FILE *fp, MPIDI_CH3_Pkt_t *pkt )
752{
753    MPIU_DBG_PRINTF((" type ......... EAGER_SEND\n"));
754    MPIU_DBG_PRINTF((" sender_reqid . 0x%08X\n", pkt->eager_send.sender_req_id));
755    MPIU_DBG_PRINTF((" context_id ... %d\n", pkt->eager_send.match.parts.context_id));
756    MPIU_DBG_PRINTF((" tag .......... %d\n", pkt->eager_send.match.parts.tag));
757    MPIU_DBG_PRINTF((" rank ......... %d\n", pkt->eager_send.match.parts.rank));
758    MPIU_DBG_PRINTF((" data_sz ...... %d\n", pkt->eager_send.data_sz));
759#ifdef MPID_USE_SEQUENCE_NUMBERS
760    MPIU_DBG_PRINTF((" seqnum ....... %d\n", pkt->eager_send.seqnum));
761#endif
762}
763
764#if defined(USE_EAGER_SHORT)
765int MPIDI_CH3_PktPrint_EagerShortSend( FILE *fp, MPIDI_CH3_Pkt_t *pkt )
766{
767    int datalen;
768    unsigned char *p = (unsigned char *)pkt->eagershort_send.data;
769    MPIU_DBG_PRINTF((" type ......... EAGERSHORT_SEND\n"));
770    MPIU_DBG_PRINTF((" context_id ... %d\n", pkt->eagershort_send.match.parts.context_id));
771    MPIU_DBG_PRINTF((" tag .......... %d\n", pkt->eagershort_send.match.parts.tag));
772    MPIU_DBG_PRINTF((" rank ......... %d\n", pkt->eagershort_send.match.parts.rank));
773    MPIU_DBG_PRINTF((" data_sz ...... %d\n", pkt->eagershort_send.data_sz));
774#ifdef MPID_USE_SEQUENCE_NUMBERS
775    MPIU_DBG_PRINTF((" seqnum ....... %d\n", pkt->eagershort_send.seqnum));
776#endif
777    datalen = pkt->eagershort_send.data_sz;
778    if (datalen > 0) {
779        char databytes[64+1];
780        int i;
781        if (datalen > 32) datalen = 32;
782        for (i=0; i<datalen; i++) {
783            MPIU_Snprintf( &databytes[2*i], 64 - 2*i, "%2x", p[i] );
784        }
785        MPIU_DBG_PRINTF((" data ......... %s\n", databytes));
786    }
787}
788#endif /* defined(USE_EAGER_SHORT) */
789
790int MPIDI_CH3_PktPrint_ReadySend( FILE *fp, MPIDI_CH3_Pkt_t *pkt )
791{
792    MPIU_DBG_PRINTF((" type ......... READY_SEND\n"));
793    MPIU_DBG_PRINTF((" sender_reqid . 0x%08X\n", pkt->ready_send.sender_req_id));
794    MPIU_DBG_PRINTF((" context_id ... %d\n", pkt->ready_send.match.parts.context_id));
795    MPIU_DBG_PRINTF((" tag .......... %d\n", pkt->ready_send.match.parts.tag));
796    MPIU_DBG_PRINTF((" rank ......... %d\n", pkt->ready_send.match.parts.rank));
797    MPIU_DBG_PRINTF((" data_sz ...... %d\n", pkt->ready_send.data_sz));
798#ifdef MPID_USE_SEQUENCE_NUMBERS
799    MPIU_DBG_PRINTF((" seqnum ....... %d\n", pkt->ready_send.seqnum));
800#endif
801}
802
803#endif /* MPICH_DBG_OUTPUT */
Note: See TracBrowser for help on using the browser.