root/mpich2/trunk/src/mpid/ch3/channels/nemesis/nemesis/include/mpid_nem_inline.h @ 4888

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

squashed more warnings

Line 
1/* -*- Mode: C; c-basic-offset:4 ; -*- */
2/*
3 *  (C) 2006 by Argonne National Laboratory.
4 *      See COPYRIGHT in top-level directory.
5 */
6
7#ifndef _MPID_NEM_INLINE_H
8#define _MPID_NEM_INLINE_H
9
10#define MPID_NEM_POLLS_BEFORE_YIELD 1000
11#define MPID_NEM_THREAD_POLLS_BEFORE_YIELD 1
12
13#include "my_papi_defs.h"
14#include "mpiiov.h"
15
16extern int MPID_nem_lmt_shm_pending;
17extern MPID_nem_cell_ptr_t MPID_nem_prefetched_cell;
18
19static inline int MPID_nem_mpich2_send_header (void* buf, int size, MPIDI_VC_t *vc, int *again);
20static inline int MPID_nem_mpich2_sendv (MPID_IOV **iov, int *n_iov, MPIDI_VC_t *vc, int *again);
21static inline void MPID_nem_mpich2_dequeue_fastbox (int local_rank);
22static inline void MPID_nem_mpich2_enqueue_fastbox (int local_rank);
23static inline int MPID_nem_mpich2_sendv_header (MPID_IOV **iov, int *n_iov, MPIDI_VC_t *vc, int *again);
24static inline int MPID_nem_recv_seqno_matches (MPID_nem_queue_ptr_t qhead);
25static inline int MPID_nem_mpich2_test_recv (MPID_nem_cell_ptr_t *cell, int *in_fbox, int in_blocking_progress);
26static inline int MPID_nem_mpich2_blocking_recv (MPID_nem_cell_ptr_t *cell, int *in_fbox);
27static inline int MPID_nem_mpich2_test_recv_wait (MPID_nem_cell_ptr_t *cell, int *in_fbox, int timeout);
28static inline int MPID_nem_mpich2_release_cell (MPID_nem_cell_ptr_t cell, MPIDI_VC_t *vc);
29static inline void MPID_nem_mpich2_send_seg_header (MPID_Segment *segment, MPIDI_msg_sz_t *segment_first,
30                                                           MPIDI_msg_sz_t segment_size, void *header, MPIDI_msg_sz_t header_sz,
31                                                           MPIDI_VC_t *vc, int *again);
32static inline void MPID_nem_mpich2_send_seg (MPID_Segment *segment, MPIDI_msg_sz_t *segment_first, MPIDI_msg_sz_t segment_size,
33                                                    MPIDI_VC_t *vc, int *again);
34
35
36/* MPID_nem_mpich2_send_header (void* buf, int size, MPIDI_VC_t *vc)
37   same as above, but sends MPICH2 32 byte header */
38#undef FUNCNAME
39#define FUNCNAME MPID_nem_mpich2_send_header
40#undef FCNAME
41#define FCNAME MPIDI_QUOTE(FUNCNAME)
42static inline int
43MPID_nem_mpich2_send_header (void* buf, int size, MPIDI_VC_t *vc, int *again)
44{
45    int mpi_errno = MPI_SUCCESS;
46    MPID_nem_cell_ptr_t el;
47    int my_rank;
48    MPIDI_CH3I_VC *vc_ch = (MPIDI_CH3I_VC *)vc->channel_private;
49
50#ifdef ENABLED_CHECKPOINTING
51    if (MPID_nem_ckpt_sending_markers)
52    {
53        MPID_nem_ckpt_send_markers();
54        goto return_again;
55    }
56#endif
57   
58    /*DO_PAPI (PAPI_reset (PAPI_EventSet)); */
59
60    MPIU_Assert (size == sizeof(MPIDI_CH3_Pkt_t));
61
62    my_rank = MPID_nem_mem_region.rank;
63
64#ifdef USE_FASTBOX
65    if (vc_ch->is_local)
66    {
67        MPID_nem_fbox_mpich2_t *pbox = vc_ch->fbox_out;
68        int count = 10;
69        uint32_t *payload_32 = (uint32_t *)pbox->cell.pkt.mpich2.payload;
70        uint32_t *buf_32 = (uint32_t *)buf;
71
72        if (MPID_nem_islocked ((MPID_nem_fbox_common_ptr_t)pbox, 0, count))
73            goto usequeue_l;
74        {
75            pbox->cell.pkt.mpich2.source  = MPID_nem_mem_region.local_rank;
76            pbox->cell.pkt.mpich2.datalen = size;
77            pbox->cell.pkt.mpich2.seqno   = vc_ch->send_seqno++;
78
79#ifdef ENABLED_CHECKPOINTING
80            pbox->cell.pkt.mpich2.datalen = size;
81            pbox->cell.pkt.mpich2.type = MPID_NEM_PKT_MPICH2;
82#endif /* ENABLED_CHECKPOINTING */
83            MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, pbox->cell.pkt.mpich2.type = MPID_NEM_PKT_MPICH2_HEAD);
84
85            payload_32[0] = buf_32[0];
86            payload_32[1] = buf_32[1];
87            payload_32[2] = buf_32[2];
88            payload_32[3] = buf_32[3];
89            payload_32[4] = buf_32[4];
90            payload_32[5] = buf_32[5];
91            payload_32[6] = buf_32[6];
92            payload_32[7] = buf_32[7];
93            if (sizeof(MPIDI_CH3_Pkt_t) == 40) /* This conditional should be optimized out */
94            {
95                payload_32[8] = buf_32[8];
96                payload_32[9] = buf_32[9];
97            }
98
99            OPA_write_barrier();
100            pbox->flag.value = 1;
101
102            MPIU_DBG_MSG (CH3_CHANNEL, VERBOSE, "--> Sent fbox ");
103            MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, MPID_nem_dbg_dump_cell (&pbox->cell));
104
105            goto return_success;
106        }
107    }
108 usequeue_l:
109#endif /*USE_FASTBOX */
110
111#ifdef PREFETCH_CELL
112    DO_PAPI (PAPI_reset (PAPI_EventSet));
113    el = MPID_nem_prefetched_cell;
114
115    if (!el)
116    {
117        if (MPID_nem_queue_empty (MPID_nem_mem_region.my_freeQ))
118            goto return_again;
119       
120        MPID_nem_queue_dequeue (MPID_nem_mem_region.my_freeQ, &el);
121    }
122    DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues14));
123#else /* PREFETCH_CELL */
124    DO_PAPI (PAPI_reset (PAPI_EventSet));
125    if (MPID_nem_queue_empty (MPID_nem_mem_region.my_freeQ))
126    {
127        goto return_again;
128    }
129    DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues14));
130
131    DO_PAPI (PAPI_reset (PAPI_EventSet));
132    MPID_nem_queue_dequeue (MPID_nem_mem_region.my_freeQ , &el);
133    DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues10));
134#endif /* PREFETCH_CELL */
135
136    DO_PAPI (PAPI_reset (PAPI_EventSet));
137    el->pkt.mpich2.source  = my_rank;
138    el->pkt.mpich2.dest    = vc->lpid;
139    el->pkt.mpich2.datalen = size;
140    el->pkt.mpich2.seqno   = vc_ch->send_seqno++;
141#ifdef ENABLED_CHECKPOINTING
142    el->pkt.mpich2.type = MPID_NEM_PKT_MPICH2;
143#endif
144    MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, el->pkt.mpich2.type = MPID_NEM_PKT_MPICH2_HEAD);
145   
146#if 1
147    ((uint32_t *)(el->pkt.mpich2.payload))[0] = ((uint32_t *)buf)[0];
148    ((uint32_t *)(el->pkt.mpich2.payload))[1] = ((uint32_t *)buf)[1];
149    ((uint32_t *)(el->pkt.mpich2.payload))[2] = ((uint32_t *)buf)[2];
150    ((uint32_t *)(el->pkt.mpich2.payload))[3] = ((uint32_t *)buf)[3];
151    ((uint32_t *)(el->pkt.mpich2.payload))[4] = ((uint32_t *)buf)[4];
152    ((uint32_t *)(el->pkt.mpich2.payload))[5] = ((uint32_t *)buf)[5];
153    ((uint32_t *)(el->pkt.mpich2.payload))[6] = ((uint32_t *)buf)[6];
154    ((uint32_t *)(el->pkt.mpich2.payload))[7] = ((uint32_t *)buf)[7];
155    if (sizeof(MPIDI_CH3_Pkt_t) == 40) /* This conditional should be optimized out */
156    {
157        ((uint32_t *)(el->pkt.mpich2.payload))[8] = ((uint32_t *)buf)[8];
158        ((uint32_t *)(el->pkt.mpich2.payload))[9] = ((uint32_t *)buf)[9];
159    }
160#else /*1 */
161    MPIU_Memcpy (el->pkt.mpich2.payload, buf, size);
162#endif /*1 */
163    DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues11));
164
165    MPIU_DBG_MSG (CH3_CHANNEL, VERBOSE, "--> Sent queue");
166    MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, MPID_nem_dbg_dump_cell (el));
167
168    DO_PAPI (PAPI_reset (PAPI_EventSet));
169    if (vc_ch->is_local)
170    {
171        MPID_nem_queue_enqueue (vc_ch->recv_queue, el);
172        /*MPID_nem_rel_dump_queue( vc_ch->recv_queue ); */
173    }
174    else
175    {
176        mpi_errno = MPID_nem_netmod_func->send (vc, el, size);
177        if (mpi_errno) MPIU_ERR_POP (mpi_errno);
178    }
179    DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues12));
180    DO_PAPI (PAPI_reset (PAPI_EventSet));   
181
182#ifdef PREFETCH_CELL
183    DO_PAPI (PAPI_reset (PAPI_EventSet));
184    if (!MPID_nem_queue_empty (MPID_nem_mem_region.my_freeQ))
185        MPID_nem_queue_dequeue (MPID_nem_mem_region.my_freeQ, &MPID_nem_prefetched_cell);
186    else
187        MPID_nem_prefetched_cell = 0;
188    DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues10));
189#endif /*PREFETCH_CELL */
190
191    /*DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues14)); */
192
193 return_success:
194    *again = 0;
195    goto fn_exit;
196 return_again:
197    *again = 1;
198    goto fn_exit;
199 fn_exit:
200    return mpi_errno;
201 fn_fail:
202    goto fn_exit;
203}
204
205
206/*
207  int MPID_nem_mpich2_sendv (struct iovec **iov, int *n_iov, MPIDI_VC_t *vc);
208
209  sends iov to vc
210  Non-blocking
211  if iov specifies more than MPID_NEM_MPICH2_DATA_LEN of data, the iov will be truncated, so that after MPID_nem_mpich2_sendv returns,
212  iov will describe unsent data
213  sets again to 1 if it can't get a free cell, 0 otherwise
214*/
215#undef FUNCNAME
216#define FUNCNAME MPID_nem_mpich2_sendv
217#undef FCNAME
218#define FCNAME MPIDI_QUOTE(FUNCNAME)
219static inline int
220MPID_nem_mpich2_sendv (MPID_IOV **iov, int *n_iov, MPIDI_VC_t *vc, int *again)
221{
222    int mpi_errno = MPI_SUCCESS;
223    MPID_nem_cell_ptr_t el;
224    char *cell_buf;
225    MPIDI_msg_sz_t payload_len;   
226    int my_rank;
227    MPIDI_CH3I_VC *vc_ch = (MPIDI_CH3I_VC *)vc->channel_private;
228    MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_MPICH2_SENDV);
229
230    MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_MPICH2_SENDV);
231
232    MPIU_Assert (*n_iov > 0 && (*iov)->MPID_IOV_LEN > 0);
233   
234#ifdef ENABLED_CHECKPOINTING
235    if (MPID_nem_ckpt_sending_markers)
236    {
237        MPID_nem_ckpt_send_markers();
238        goto return_again;
239    }
240#endif
241   
242    DO_PAPI (PAPI_reset (PAPI_EventSet));
243
244    my_rank = MPID_nem_mem_region.rank;
245       
246#ifdef PREFETCH_CELL
247    el = MPID_nem_prefetched_cell;
248   
249    if (!el)
250    {
251        if (MPID_nem_queue_empty (MPID_nem_mem_region.my_freeQ))
252        {
253            DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues5));
254            goto return_again;
255        }
256       
257        MPID_nem_queue_dequeue (MPID_nem_mem_region.my_freeQ, &el);
258    }
259#else /*PREFETCH_CELL     */
260    if (MPID_nem_queue_empty (MPID_nem_mem_region.my_freeQ))
261    {
262        DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues5));
263        goto return_again;
264    }
265
266    MPID_nem_queue_dequeue (MPID_nem_mem_region.my_freeQ , &el);
267#endif /*PREFETCH_CELL     */
268
269    payload_len = MPID_NEM_MPICH2_DATA_LEN;
270    cell_buf    = (char *) el->pkt.mpich2.payload; /* cast away volatile */
271   
272    while (*n_iov && payload_len >= (*iov)->MPID_IOV_LEN)
273    {
274        int _iov_len = (*iov)->MPID_IOV_LEN;
275        MPIU_Memcpy (cell_buf, (*iov)->MPID_IOV_BUF, _iov_len);
276        payload_len -= _iov_len;
277        cell_buf += _iov_len;
278        --(*n_iov);
279        ++(*iov);
280    }
281   
282    if (*n_iov && payload_len > 0)
283    {
284        MPIU_Memcpy (cell_buf, (*iov)->MPID_IOV_BUF, payload_len);
285        (*iov)->MPID_IOV_BUF = (char *)(*iov)->MPID_IOV_BUF + payload_len;
286        (*iov)->MPID_IOV_LEN -= payload_len;
287        payload_len = 0;
288    }
289
290    el->pkt.mpich2.source  = my_rank;
291    el->pkt.mpich2.dest    = vc->lpid;
292    el->pkt.mpich2.datalen = MPID_NEM_MPICH2_DATA_LEN - payload_len;
293    el->pkt.mpich2.seqno   = vc_ch->send_seqno++;
294#ifdef ENABLED_CHECKPOINTING
295    el->pkt.mpich2.type = MPID_NEM_PKT_MPICH2;
296#endif
297    MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, el->pkt.mpich2.type = MPID_NEM_PKT_MPICH2);
298
299    MPIU_DBG_MSG (CH3_CHANNEL, VERBOSE, "--> Sent queue");
300    MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, MPID_nem_dbg_dump_cell (el));
301
302    if(vc_ch->is_local)
303    {
304        MPID_nem_queue_enqueue (vc_ch->recv_queue, el);
305        /*MPID_nem_rel_dump_queue( vc_ch->recv_queue ); */
306    }
307    else
308    {
309        mpi_errno = MPID_nem_netmod_func->send (vc, el, MPID_NEM_MPICH2_DATA_LEN - payload_len);
310        if (mpi_errno) MPIU_ERR_POP (mpi_errno);
311    }
312
313#ifdef PREFETCH_CELL
314    if (!MPID_nem_queue_empty (MPID_nem_mem_region.my_freeQ))
315        MPID_nem_queue_dequeue (MPID_nem_mem_region.my_freeQ, &MPID_nem_prefetched_cell);
316    else
317        MPID_nem_prefetched_cell = 0;
318#endif /*PREFETCH_CELL */
319    DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues5));
320
321    *again = 0;
322    goto fn_exit;
323 return_again:
324    *again = 1;
325    goto fn_exit;
326 fn_exit:
327    MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_MPICH2_SENDV);
328    return mpi_errno;
329 fn_fail:
330    goto fn_exit;
331}
332
333/* MPID_nem_mpich2_sendv_header (struct iovec **iov, int *n_iov, int dest)
334   same as above but first iov element is an MPICH2 32 byte header */
335#undef FUNCNAME
336#define FUNCNAME MPID_nem_mpich2_sendv_header
337#undef FCNAME
338#define FCNAME MPIDI_QUOTE(FUNCNAME)
339static inline int
340MPID_nem_mpich2_sendv_header (MPID_IOV **iov, int *n_iov, MPIDI_VC_t *vc, int *again)
341{
342    int mpi_errno = MPI_SUCCESS;
343    MPID_nem_cell_ptr_t el;
344    char *cell_buf;
345    MPIDI_msg_sz_t payload_len;   
346    int my_rank;
347    MPIDI_CH3I_VC *vc_ch = (MPIDI_CH3I_VC *)vc->channel_private;
348    MPIDI_STATE_DECL(MPID_STATE_MPID_NEM_MPICH2_SENDV_HEADER);
349   
350    MPIDI_FUNC_ENTER(MPID_STATE_MPID_NEM_MPICH2_SENDV_HEADER);
351
352#ifdef ENABLED_CHECKPOINTING
353    if (MPID_nem_ckpt_sending_markers)
354    {
355        MPID_nem_ckpt_send_markers();
356        goto return_again;
357    }
358#endif
359   
360    DO_PAPI (PAPI_reset (PAPI_EventSet));
361    MPIU_Assert (*n_iov > 0 && (*iov)->MPID_IOV_LEN == sizeof(MPIDI_CH3_Pkt_t));
362
363    my_rank = MPID_nem_mem_region.rank;
364
365#ifdef USE_FASTBOX
366    if (vc_ch->is_local && (*n_iov == 2 && (*iov)[1].MPID_IOV_LEN + sizeof(MPIDI_CH3_Pkt_t) <= MPID_NEM_FBOX_DATALEN))
367    {
368        MPID_nem_fbox_mpich2_t *pbox = vc_ch->fbox_out;
369        int count = 10;
370        uint32_t *payload_32 = (uint32_t *)(pbox->cell.pkt.mpich2.payload ) ;
371        uint32_t *buf_32 = (uint32_t *)(*iov)->MPID_IOV_BUF;
372
373        if (MPID_nem_islocked ((MPID_nem_fbox_common_ptr_t)pbox, 0, count))
374            goto usequeue_l;
375        {
376            pbox->cell.pkt.mpich2.source  = MPID_nem_mem_region.local_rank;
377            pbox->cell.pkt.mpich2.datalen = (*iov)[1].MPID_IOV_LEN + sizeof(MPIDI_CH3_Pkt_t);
378            pbox->cell.pkt.mpich2.seqno   = vc_ch->send_seqno++;
379#ifdef ENABLED_CHECKPOINTING
380            pbox->cell.pkt.mpich2.datalen = (*iov)[1].MPID_IOV_LEN + sizeof(MPIDI_CH3_Pkt_t);
381            pbox->cell.pkt.mpich2.type = MPID_NEM_PKT_MPICH2;
382#endif
383            MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, pbox->cell.pkt.mpich2.type = MPID_NEM_PKT_MPICH2_HEAD);
384
385            payload_32[0] = buf_32[0];
386            payload_32[1] = buf_32[1];
387            payload_32[2] = buf_32[2];
388            payload_32[3] = buf_32[3];
389            payload_32[4] = buf_32[4];
390            payload_32[5] = buf_32[5];
391            payload_32[6] = buf_32[6];
392            payload_32[7] = buf_32[7];
393            if (sizeof(MPIDI_CH3_Pkt_t) == 40) /* This conditional should be optimized out */
394            {
395                payload_32[8] = buf_32[8];
396                payload_32[9] = buf_32[9];
397            }
398            MPIU_Memcpy ((char *)pbox->cell.pkt.mpich2.payload +sizeof(MPIDI_CH3_Pkt_t), (*iov)[1].MPID_IOV_BUF, (*iov)[1].MPID_IOV_LEN);
399            OPA_write_barrier();
400            pbox->flag.value = 1;
401            *n_iov = 0;
402
403            MPIU_DBG_MSG (CH3_CHANNEL, VERBOSE, "--> Sent fbox ");
404            MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, MPID_nem_dbg_dump_cell (&pbox->cell));
405
406            goto return_success;
407        }
408    }
409 usequeue_l:
410
411#endif /*USE_FASTBOX */
412       
413#ifdef PREFETCH_CELL
414    el = MPID_nem_prefetched_cell;
415
416    if (!el)
417    {
418        if (MPID_nem_queue_empty (MPID_nem_mem_region.my_freeQ))
419        {
420            DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues5));
421            goto return_again;
422        }
423       
424        MPID_nem_queue_dequeue (MPID_nem_mem_region.my_freeQ, &el);
425    }
426#else /*PREFETCH_CELL    */
427    if (MPID_nem_queue_empty (MPID_nem_mem_region.my_freeQ))
428    {
429        DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues5));
430        goto return_again;
431    }
432
433    MPID_nem_queue_dequeue (MPID_nem_mem_region.my_freeQ, &el);
434#endif /*PREFETCH_CELL */
435
436    ((uint32_t *)(el->pkt.mpich2.payload))[0] = ((uint32_t *)(*iov)->MPID_IOV_BUF)[0];
437    ((uint32_t *)(el->pkt.mpich2.payload))[1] = ((uint32_t *)(*iov)->MPID_IOV_BUF)[1];
438    ((uint32_t *)(el->pkt.mpich2.payload))[2] = ((uint32_t *)(*iov)->MPID_IOV_BUF)[2];
439    ((uint32_t *)(el->pkt.mpich2.payload))[3] = ((uint32_t *)(*iov)->MPID_IOV_BUF)[3];
440    ((uint32_t *)(el->pkt.mpich2.payload))[4] = ((uint32_t *)(*iov)->MPID_IOV_BUF)[4];
441    ((uint32_t *)(el->pkt.mpich2.payload))[5] = ((uint32_t *)(*iov)->MPID_IOV_BUF)[5];
442    ((uint32_t *)(el->pkt.mpich2.payload))[6] = ((uint32_t *)(*iov)->MPID_IOV_BUF)[6];
443    ((uint32_t *)(el->pkt.mpich2.payload))[7] = ((uint32_t *)(*iov)->MPID_IOV_BUF)[7];
444    if (sizeof(MPIDI_CH3_Pkt_t) == 40) /* This conditional should be optimized out */
445    {
446        ((uint32_t *)(el->pkt.mpich2.payload))[8] = ((uint32_t *)(*iov)->MPID_IOV_BUF)[8];
447        ((uint32_t *)(el->pkt.mpich2.payload))[9] = ((uint32_t *)(*iov)->MPID_IOV_BUF)[9];
448    }
449
450    cell_buf = (char *)(el->pkt.mpich2.payload) + sizeof(MPIDI_CH3_Pkt_t);
451    ++(*iov);
452    --(*n_iov);
453
454    payload_len = MPID_NEM_MPICH2_DATA_LEN - sizeof(MPIDI_CH3_Pkt_t);
455    while (*n_iov && payload_len >= (*iov)->MPID_IOV_LEN)
456    {
457        int _iov_len = (*iov)->MPID_IOV_LEN;
458        MPIU_Memcpy (cell_buf, (*iov)->MPID_IOV_BUF, _iov_len);
459        payload_len -= _iov_len;
460        cell_buf += _iov_len;
461        --(*n_iov);
462        ++(*iov);
463    }
464   
465    if (*n_iov && payload_len > 0)
466    {
467        MPIU_Memcpy (cell_buf, (*iov)->MPID_IOV_BUF, payload_len);
468        (*iov)->MPID_IOV_BUF = (char *)(*iov)->MPID_IOV_BUF + payload_len;
469        (*iov)->MPID_IOV_LEN -= payload_len;
470        payload_len = 0;
471    }
472
473    el->pkt.mpich2.source  = my_rank;
474    el->pkt.mpich2.dest    = vc->lpid;
475    el->pkt.mpich2.datalen = MPID_NEM_MPICH2_DATA_LEN - payload_len;
476    el->pkt.mpich2.seqno   = vc_ch->send_seqno++;
477#ifdef ENABLED_CHECKPOINTING
478    el->pkt.mpich2.type = MPID_NEM_PKT_MPICH2;
479#endif
480    MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, el->pkt.mpich2.type = MPID_NEM_PKT_MPICH2_HEAD);
481
482    MPIU_DBG_MSG (CH3_CHANNEL, VERBOSE, "--> Sent queue");
483    MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, MPID_nem_dbg_dump_cell (el));
484
485    if (vc_ch->is_local)
486    {   
487        MPID_nem_queue_enqueue (vc_ch->recv_queue, el); 
488        /*MPID_nem_rel_dump_queue( vc_ch->recv_queue ); */
489    }
490    else
491    {
492        mpi_errno = MPID_nem_netmod_func->send (vc, el, MPID_NEM_MPICH2_DATA_LEN - payload_len);
493        if (mpi_errno) MPIU_ERR_POP (mpi_errno);
494    }
495
496#ifdef PREFETCH_CELL
497    if (!MPID_nem_queue_empty (MPID_nem_mem_region.my_freeQ))
498        MPID_nem_queue_dequeue (MPID_nem_mem_region.my_freeQ, &MPID_nem_prefetched_cell);
499    else
500        MPID_nem_prefetched_cell = 0;
501#endif /*PREFETCH_CELL */
502    DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues5));
503
504 return_success:
505    *again = 0;
506    goto fn_exit;
507 return_again:
508    *again = 1;
509    goto fn_exit;
510 fn_exit:
511    MPIDI_FUNC_EXIT(MPID_STATE_MPID_NEM_MPICH2_SENDV_HEADER);
512    return mpi_errno;
513 fn_fail:
514    goto fn_exit;
515}
516
517/* send the header and data described by the segment in one cell.  If
518   there is no cell available, *again is set to 1.  If all of the data
519   cannot be sent, *segment_first is set to the index of the first
520   unsent byte.
521   Pre condition:  This must be the first packet of a message (i.e.,
522                       *segment first == 0)
523                   The destination process is local
524   Post conditions:  the header has been sent iff *again == 0
525                     if there is data to send (segment_size > 0) then
526                         (the header has been sent iff any data has
527                         been sent (i.e., *segment_first > 0) )
528                     i.e.: we will never send only the header
529*/
530#undef FUNCNAME
531#define FUNCNAME MPID_nem_mpich2_send_seg_header
532#undef FCNAME
533#define FCNAME MPIDI_QUOTE(FUNCNAME)
534static inline void
535MPID_nem_mpich2_send_seg_header (MPID_Segment *segment, MPIDI_msg_sz_t *segment_first, MPIDI_msg_sz_t segment_size,
536                                 void *header, MPIDI_msg_sz_t header_sz, MPIDI_VC_t *vc, int *again)
537{
538    MPID_nem_cell_ptr_t el;
539    MPIDI_msg_sz_t datalen;
540    int my_rank;
541    MPIDI_msg_sz_t last;
542    MPIDI_CH3I_VC *vc_ch = (MPIDI_CH3I_VC *)vc->channel_private;
543
544    MPIU_Assert(vc_ch->is_local); /* netmods will have their own implementation */
545    MPIU_Assert(header_sz <= sizeof(MPIDI_CH3_Pkt_t));
546    MPIU_Assert(*segment_first == 0); /* this routine is only called for new messages */
547   
548#ifdef ENABLED_CHECKPOINTING
549    if (MPID_nem_ckpt_sending_markers)
550    {
551        MPID_nem_ckpt_send_markers();
552        goto return_again;
553    }
554#endif
555   
556    DO_PAPI (PAPI_reset (PAPI_EventSet));
557
558    my_rank = MPID_nem_mem_region.rank;
559
560#ifdef USE_FASTBOX
561    if (sizeof(MPIDI_CH3_Pkt_t) + segment_size <= MPID_NEM_FBOX_DATALEN)
562    {
563        MPID_nem_fbox_mpich2_t *pbox = vc_ch->fbox_out;
564        int count = 10;
565
566        if (MPID_nem_islocked ((MPID_nem_fbox_common_ptr_t)pbox, 0, count))
567            goto usequeue_l;
568        {
569            pbox->cell.pkt.mpich2.source  = MPID_nem_mem_region.local_rank;
570            pbox->cell.pkt.mpich2.datalen = sizeof(MPIDI_CH3_Pkt_t) + segment_size;
571            pbox->cell.pkt.mpich2.seqno   = vc_ch->send_seqno++;
572#ifdef ENABLED_CHECKPOINTING
573            pbox->cell.pkt.mpich2.type = MPID_NEM_PKT_MPICH2;
574#endif
575            MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, pbox->cell.pkt.mpich2.type = MPID_NEM_PKT_MPICH2_HEAD);
576
577            /* copy header */
578            {
579                void * p = (void *)pbox->cell.pkt.mpich2.payload;
580                MPIU_Memcpy(p, header, header_sz);
581            /* MPIU_Memcpy((void *)pbox->cell.pkt.mpich2.payload, header, header_sz); */
582            }
583           
584            /* copy data */
585            last = segment_size;
586            MPID_Segment_pack(segment, *segment_first, &last, (char *)pbox->cell.pkt.mpich2.payload + sizeof(MPIDI_CH3_Pkt_t));
587            MPIU_Assert(last == segment_size);
588
589            OPA_write_barrier();
590            pbox->flag.value = 1;
591
592            *segment_first = last;
593
594            MPIU_DBG_MSG(CH3_CHANNEL, VERBOSE, "--> Sent fbox ");
595            MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, MPID_nem_dbg_dump_cell (&pbox->cell));
596
597            goto return_success;
598        }
599    }
600 usequeue_l:
601
602#endif /*USE_FASTBOX */
603       
604#ifdef PREFETCH_CELL
605    el = MPID_nem_prefetched_cell;
606
607    if (!el)
608    {
609        if (MPID_nem_queue_empty (MPID_nem_mem_region.my_freeQ))
610        {
611            DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues5));
612            goto return_again;
613        }
614       
615        MPID_nem_queue_dequeue (MPID_nem_mem_region.my_freeQ, &el);
616    }
617#else /*PREFETCH_CELL    */
618    if (MPID_nem_queue_empty (MPID_nem_mem_region.my_freeQ))
619    {
620        DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues5));
621        goto return_again;
622    }
623
624    MPID_nem_queue_dequeue (MPID_nem_mem_region.my_freeQ, &el);
625#endif /*PREFETCH_CELL */
626
627    /* copy header */
628    MPIU_Memcpy((void *)el->pkt.mpich2.payload, header, header_sz);
629   
630    /* copy data */
631    if (segment_size - *segment_first <= MPID_NEM_MPICH2_DATA_LEN - sizeof(MPIDI_CH3_Pkt_t))
632        last = segment_size;
633    else
634        last = *segment_first + MPID_NEM_MPICH2_DATA_LEN - sizeof(MPIDI_CH3_Pkt_t);
635   
636    MPID_Segment_pack(segment, *segment_first, &last, (char *)el->pkt.mpich2.payload + sizeof(MPIDI_CH3_Pkt_t));
637    datalen = sizeof(MPIDI_CH3_Pkt_t) + last - *segment_first;
638    *segment_first = last;
639   
640    el->pkt.mpich2.source  = my_rank;
641    el->pkt.mpich2.dest    = vc->lpid;
642    el->pkt.mpich2.datalen = datalen;
643    el->pkt.mpich2.seqno   = vc_ch->send_seqno++;
644#ifdef ENABLED_CHECKPOINTING
645    el->pkt.mpich2.type = MPID_NEM_PKT_MPICH2;
646#endif
647    MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, el->pkt.mpich2.type = MPID_NEM_PKT_MPICH2_HEAD);
648
649    MPIU_DBG_MSG (CH3_CHANNEL, VERBOSE, "--> Sent queue");
650    MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, MPID_nem_dbg_dump_cell (el));
651
652    MPID_nem_queue_enqueue (vc_ch->recv_queue, el);     
653
654#ifdef PREFETCH_CELL
655    if (!MPID_nem_queue_empty (MPID_nem_mem_region.my_freeQ))
656        MPID_nem_queue_dequeue (MPID_nem_mem_region.my_freeQ, &MPID_nem_prefetched_cell);
657    else
658        MPID_nem_prefetched_cell = 0;
659#endif /*PREFETCH_CELL */
660    DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues5));
661
662 return_success:
663    *again = 0;
664    goto fn_exit;
665 return_again:
666    *again = 1;
667    goto fn_exit;
668 fn_exit:
669    return;
670}
671
672/* similar to MPID_nem_mpich2_send_seg_header, except there is no
673   header to send.  This need not be the first packet of a message. */
674#undef FUNCNAME
675#define FUNCNAME MPID_nem_mpich2_send_seg
676#undef FCNAME
677#define FCNAME MPIDI_QUOTE(FUNCNAME)
678static inline void
679MPID_nem_mpich2_send_seg (MPID_Segment *segment, MPIDI_msg_sz_t *segment_first, MPIDI_msg_sz_t segment_size, MPIDI_VC_t *vc, int *again)
680{
681    MPID_nem_cell_ptr_t el;
682    MPIDI_msg_sz_t datalen;   
683    int my_rank;
684    MPIDI_msg_sz_t last;
685    MPIDI_CH3I_VC *vc_ch = (MPIDI_CH3I_VC *)vc->channel_private;
686
687    MPIU_Assert(vc_ch->is_local); /* netmods will have their own implementation */
688   
689#ifdef ENABLED_CHECKPOINTING
690    if (MPID_nem_ckpt_sending_markers)
691    {
692        MPID_nem_ckpt_send_markers();
693        goto return_again;
694    }
695#endif
696   
697    DO_PAPI (PAPI_reset (PAPI_EventSet));
698
699    my_rank = MPID_nem_mem_region.rank;
700       
701#ifdef PREFETCH_CELL
702    el = MPID_nem_prefetched_cell;
703   
704    if (!el)
705    {
706        if (MPID_nem_queue_empty (MPID_nem_mem_region.my_freeQ))
707        {
708            DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues5));
709            goto return_again;
710        }
711       
712        MPID_nem_queue_dequeue (MPID_nem_mem_region.my_freeQ, &el);
713    }
714#else /*PREFETCH_CELL    */
715    if (MPID_nem_queue_empty (MPID_nem_mem_region.my_freeQ))
716    {
717        DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues5));
718        goto return_again;
719    }
720
721    MPID_nem_queue_dequeue (MPID_nem_mem_region.my_freeQ, &el);
722#endif /*PREFETCH_CELL */
723
724    /* copy data */
725    if (segment_size - *segment_first <= MPID_NEM_MPICH2_DATA_LEN)
726        last = segment_size;
727    else
728        last = *segment_first + MPID_NEM_MPICH2_DATA_LEN;
729   
730    MPID_Segment_pack(segment, *segment_first, &last, (char *)el->pkt.mpich2.payload);
731    datalen = last - *segment_first;
732    *segment_first = last;
733   
734    el->pkt.mpich2.source  = my_rank;
735    el->pkt.mpich2.dest    = vc->lpid;
736    el->pkt.mpich2.datalen = datalen;
737    el->pkt.mpich2.seqno   = vc_ch->send_seqno++;
738#ifdef ENABLED_CHECKPOINTING
739    el->pkt.mpich2.type = MPID_NEM_PKT_MPICH2;
740#endif
741    MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, el->pkt.mpich2.type = MPID_NEM_PKT_MPICH2_HEAD);
742
743    MPIU_DBG_MSG (CH3_CHANNEL, VERBOSE, "--> Sent queue");
744    MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, MPID_nem_dbg_dump_cell (el));
745
746    MPID_nem_queue_enqueue (vc_ch->recv_queue, el);     
747
748#ifdef PREFETCH_CELL
749    if (!MPID_nem_queue_empty (MPID_nem_mem_region.my_freeQ))
750        MPID_nem_queue_dequeue (MPID_nem_mem_region.my_freeQ, &MPID_nem_prefetched_cell);
751    else
752        MPID_nem_prefetched_cell = 0;
753#endif /*PREFETCH_CELL */
754    DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues5));
755
756    *again = 0;
757    goto fn_exit;
758 return_again:
759    *again = 1;
760    goto fn_exit;
761 fn_exit:
762    return;
763}
764
765/*
766  MPID_nem_mpich2_dequeue_fastbox (int local_rank)
767  decrements usage count on fastbox for process with local rank local_rank and
768  dequeues it from fbox queue if usage is 0.
769  This function is called whenever a receive for a process on this node is matched.
770  Fastboxes on fbox queue are polled regularly for incoming messages.
771*/
772#undef FUNCNAME
773#define FUNCNAME MPID_nem_mpich2_dequeue_fastbox
774#undef FCNAME
775#define FCNAME MPIDI_QUOTE(FUNCNAME)
776static inline void MPID_nem_mpich2_dequeue_fastbox(int local_rank)
777{
778    MPID_nem_fboxq_elem_t *el;
779
780    MPIU_Assert(local_rank < MPID_nem_mem_region.num_local);
781
782    el = &MPID_nem_fboxq_elem_list[local_rank];   
783    MPIU_Assert(el->fbox != NULL);
784
785    MPIU_Assert(el->usage);
786
787    --el->usage;
788    if (el->usage == 0)
789    {
790        if (el->prev == NULL)
791            MPID_nem_fboxq_head = el->next;
792        else
793            el->prev->next = el->next;
794
795        if (el->next == NULL)
796            MPID_nem_fboxq_tail = el->prev;
797        else
798            el->next->prev = el->prev;
799
800        if (el == MPID_nem_curr_fboxq_elem)
801        {
802            if (el->next == NULL)
803                MPID_nem_curr_fboxq_elem = MPID_nem_fboxq_head;
804            else
805                MPID_nem_curr_fboxq_elem = el->next;
806        }
807    }   
808}
809
810/*
811  MPID_nem_mpich2_enqueue_fastbox (int local_rank)
812  enqueues fastbox for process with local rank local_rank on fbox queue
813  This function is called whenever a receive is posted for a process on this node.
814  Fastboxes on fbox queue are polled regularly for incoming messages.
815*/
816#undef FUNCNAME
817#define FUNCNAME MPID_nem_mpich2_dequeue_fastbox
818#undef FCNAME
819#define FCNAME MPIDI_QUOTE(FUNCNAME)
820static inline void MPID_nem_mpich2_enqueue_fastbox(int local_rank)
821{
822    MPID_nem_fboxq_elem_t *el;
823
824    MPIU_Assert(local_rank < MPID_nem_mem_region.num_local);
825
826    el = &MPID_nem_fboxq_elem_list[local_rank];
827    MPIU_Assert(el->fbox != NULL);
828
829    if (el->usage)
830    {
831        ++el->usage;
832    }
833    else
834    {
835        el->usage = 1;
836        if (MPID_nem_fboxq_tail == NULL)
837        {
838            el->prev = NULL;
839            MPID_nem_curr_fboxq_elem = MPID_nem_fboxq_head = el;
840        }
841        else
842        {
843            el->prev = MPID_nem_fboxq_tail;
844            MPID_nem_fboxq_tail->next = el;
845        }
846           
847        el->next = NULL;
848        MPID_nem_fboxq_tail = el;
849    }
850}
851/*
852  MPID_nem_recv_seqno_matches (MPID_nem_queue_ptr_t qhead)
853  check whether the sequence number for the cell at the head of qhead is the one
854  expected from the sender of that cell
855  We only check these for processes in COMM_WORLD (i.e. the ones initially allocated)
856*/
857#undef FUNCNAME
858#define FUNCNAME MPID_nem_recv_seqno_matches
859#undef FCNAME
860#define FCNAME MPIDI_QUOTE(FUNCNAME)
861static inline int
862MPID_nem_recv_seqno_matches (MPID_nem_queue_ptr_t qhead)
863{
864    int source;
865    MPID_nem_cell_ptr_t cell = MPID_nem_queue_head(qhead);
866    source = cell->pkt.mpich2.source;
867   
868    return (cell->pkt.mpich2.seqno == MPID_nem_recv_seqno[source]);
869}
870
871/*
872  int MPID_nem_mpich2_test_recv (MPID_nem_cell_ptr_t *cell, int *in_fbox);
873
874  non-blocking receive
875  sets cell to the received cell, or NULL if there is nothing to receive. in_fbox is true iff the cell was found in a fbox
876  the cell must be released back to the subsystem with MPID_nem_mpich2_release_cell() once the packet has been copied out
877*/
878#undef FUNCNAME
879#define FUNCNAME MPID_nem_mpich2_test_recv
880#undef FCNAME
881#define FCNAME MPIDI_QUOTE(FUNCNAME)
882static inline int
883MPID_nem_mpich2_test_recv(MPID_nem_cell_ptr_t *cell, int *in_fbox, int in_blocking_progress)
884{
885    int mpi_errno = MPI_SUCCESS;
886   
887    DO_PAPI (PAPI_reset (PAPI_EventSet));
888
889#ifdef ENABLED_CHECKPOINTING
890    MPID_nem_ckpt_maybe_take_checkpoint();
891
892    if (MPID_nem_ckpt_message_log)
893    {
894        MPID_nem_ckpt_replay_message (cell);
895        MPIU_Assert ((*cell)->pkt.mpich2.seqno == MPID_nem_recv_seqno[(*cell)->pkt.mpich2.source]);
896        ++MPID_nem_recv_seqno[(*cell)->pkt.mpich2.source];
897        *in_fbox = 0;
898        goto fn_exit;
899    }
900#endif
901   
902#ifdef USE_FASTBOX
903    if (poll_fboxes(cell)) goto fbox_l;
904#endif/* USE_FASTBOX     */
905
906    if (MPID_nem_num_netmods)
907    {
908        mpi_errno = MPID_nem_network_poll(in_blocking_progress);
909        if (mpi_errno) MPIU_ERR_POP (mpi_errno);
910    }
911
912    if (MPID_nem_queue_empty (MPID_nem_mem_region.my_recvQ) || !MPID_nem_recv_seqno_matches (MPID_nem_mem_region.my_recvQ))
913    {
914#ifdef USE_FASTBOX
915        poll_all_fboxes (cell, goto fbox_l);
916#endif/* USE_FASTBOX     */
917        *cell = NULL;
918        goto fn_exit;
919    }
920   
921    MPID_nem_queue_dequeue (MPID_nem_mem_region.my_recvQ, cell);
922
923    ++MPID_nem_recv_seqno[(*cell)->pkt.mpich2.source];
924    *in_fbox = 0;
925
926 fn_exit:
927#ifdef ENABLED_CHECKPOINTING
928    if ((*cell)->pkt.header.type == MPID_NEM_PKT_CKPT)
929        MPID_nem_ckpt_got_marker (cell, in_fbox);
930    else if (MPID_nem_ckpt_logging_messages)
931        MPID_nem_ckpt_log_message (*cell);
932#endif
933    DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues6));
934   
935    MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, {
936        if (*cell)
937        {
938            MPIU_DBG_MSG_S (CH3_CHANNEL, VERBOSE, "<-- Recv %s", (*in_fbox) ? "fbox " : "queue");
939            MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, MPID_nem_dbg_dump_cell (*cell));
940        }
941    });
942
943 fn_fail:
944    return mpi_errno;
945
946 fbox_l:
947    *in_fbox = 1;
948    goto fn_exit;
949
950}
951
952/*
953  int MPID_nem_mpich2_test_recv_wait (MPID_nem_cell_ptr_t *cell, int *in_fbox, int timeout);
954
955  blocking receive with timeout
956  waits up to timeout iterations to receive a cell
957  sets cell to the received cell, or NULL if there is nothing to receive. in_fbox is true iff the cell was found in a fbox
958  the cell must be released back to the subsystem with MPID_nem_mpich2_release_cell() once the packet has been copied out
959*/
960#undef FUNCNAME
961#define FUNCNAME MPID_nem_mpich2_test_recv_wait
962#undef FCNAME
963#define FCNAME MPIDI_QUOTE(FUNCNAME)
964static inline int
965MPID_nem_mpich2_test_recv_wait (MPID_nem_cell_ptr_t *cell, int *in_fbox, int timeout)
966{
967    int mpi_errno = MPI_SUCCESS;
968   
969#ifdef USE_FASTBOX
970    if (poll_fboxes(cell)) goto fbox_l;
971#endif/* USE_FASTBOX     */
972
973    if (MPID_nem_num_netmods)
974    {
975        mpi_errno = MPID_nem_network_poll(TRUE /* blocking */);
976        if (mpi_errno) MPIU_ERR_POP (mpi_errno);
977    }
978
979    while ((--timeout > 0) && (MPID_nem_queue_empty (MPID_nem_mem_region.my_recvQ) || !MPID_nem_recv_seqno_matches (MPID_nem_mem_region.my_recvQ)))
980    {
981#ifdef USE_FASTBOX
982        poll_all_fboxes (cell, goto fbox_l);
983#endif/* USE_FASTBOX     */
984        *cell = NULL;
985        goto exit_l;
986    }
987   
988    MPID_nem_queue_dequeue (MPID_nem_mem_region.my_recvQ, cell);
989
990    ++MPID_nem_recv_seqno[(*cell)->pkt.mpich2.source];
991    *in_fbox = 0;
992 exit_l:
993   
994    MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, {
995            if (*cell)
996            {
997                MPIU_DBG_MSG_S (CH3_CHANNEL, VERBOSE, "<-- Recv %s", (*in_fbox) ? "fbox " : "queue");
998                MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, MPID_nem_dbg_dump_cell (*cell));
999            }
1000        });
1001
1002 fn_fail:
1003    return mpi_errno;
1004
1005 fbox_l:
1006    *in_fbox = 1;
1007    goto exit_l;
1008}
1009
1010/*
1011  int MPID_nem_mpich2_blocking_recv (MPID_nem_cell_ptr_t *cell, int *in_fbox);
1012
1013  blocking receive waits until there is something to receive, or then
1014  sets cell to the received cell. in_fbox is true iff the cell was
1015  found in a fbox the cell must be released back to the subsystem with
1016  MPID_nem_mpich2_release_cell() once the packet has been copied out
1017*/
1018#undef FUNCNAME
1019#define FUNCNAME MPID_nem_mpich2_blocking_recv
1020#undef FCNAME
1021#define FCNAME MPIDI_QUOTE(FUNCNAME)
1022static inline int
1023MPID_nem_mpich2_blocking_recv(MPID_nem_cell_ptr_t *cell, int *in_fbox)
1024{
1025    int mpi_errno = MPI_SUCCESS;
1026    unsigned completions = MPIDI_CH3I_progress_completion_count;
1027#ifndef ENABLE_NO_YIELD
1028    int pollcount = 0;
1029#endif
1030    DO_PAPI (PAPI_reset (PAPI_EventSet));
1031
1032#ifdef MPICH_IS_THREADED
1033    /* We should never enter this function in a multithreaded app */
1034#ifdef HAVE_RUNTIME_THREADCHECK
1035    MPIU_Assert(!MPIR_ThreadInfo.isThreaded);
1036#else
1037    MPIU_Assert(0);
1038#endif
1039#endif
1040
1041#ifdef ENABLED_CHECKPOINTING
1042    MPID_nem_ckpt_maybe_take_checkpoint();
1043
1044 top_l:
1045    if (MPID_nem_ckpt_message_log)
1046    {
1047        MPID_nem_ckpt_replay_message (cell);
1048        MPIU_Assert ((*cell)->pkt.mpich2.seqno == MPID_nem_recv_seqno[(*cell)->pkt.mpich2.source]);
1049        ++MPID_nem_recv_seqno[(*cell)->pkt.mpich2.source];
1050        *in_fbox = 0;
1051        return mpi_errno;
1052    }
1053#endif
1054   
1055   
1056#ifdef USE_FASTBOX
1057    if (poll_fboxes(cell)) goto fbox_l;
1058#endif /*USE_FASTBOX */
1059
1060    if (MPID_nem_num_netmods)
1061    {
1062        mpi_errno = MPID_nem_network_poll(TRUE /* blocking */);
1063        if (mpi_errno) MPIU_ERR_POP (mpi_errno);
1064    }
1065
1066    while (MPID_nem_queue_empty (MPID_nem_mem_region.my_recvQ) || !MPID_nem_recv_seqno_matches (MPID_nem_mem_region.my_recvQ))
1067    {
1068        DO_PAPI (PAPI_reset (PAPI_EventSet));
1069
1070#ifdef USE_FASTBOX     
1071        poll_all_fboxes (cell, goto fbox_l);
1072        if (poll_fboxes(cell)) goto fbox_l;
1073#endif /*USE_FASTBOX */
1074
1075        if (MPID_nem_num_netmods)
1076        {           
1077            mpi_errno = MPID_nem_network_poll(TRUE /* blocking */);
1078            if (mpi_errno) MPIU_ERR_POP (mpi_errno);
1079
1080            if (completions != MPIDI_CH3I_progress_completion_count || MPID_nem_local_lmt_pending || MPIDI_CH3I_active_send[CH3_NORMAL_QUEUE]
1081                || MPIDI_CH3I_SendQ_head(CH3_NORMAL_QUEUE))
1082            {
1083                *cell = NULL;
1084                *in_fbox = 0;
1085                goto exit_l;
1086            }
1087        }
1088#if !defined ENABLE_NO_YIELD
1089        if (pollcount >= MPID_NEM_POLLS_BEFORE_YIELD)
1090        {
1091            pollcount = 0;
1092            MPIDU_Yield();
1093        }
1094        ++pollcount;
1095#endif
1096    }
1097
1098    MPID_nem_queue_dequeue (MPID_nem_mem_region.my_recvQ, cell);
1099
1100    ++MPID_nem_recv_seqno[(*cell)->pkt.mpich2.source];
1101    *in_fbox = 0;
1102
1103 exit_l:   
1104
1105#ifdef ENABLED_CHECKPOINTING
1106    if (*cell)
1107    {
1108        if ((*cell)->pkt.header.type == MPID_NEM_PKT_CKPT)
1109        {
1110            MPID_nem_ckpt_got_marker (cell, in_fbox);
1111            goto top_l;
1112        }
1113        else if (MPID_nem_ckpt_logging_messages)
1114            MPID_nem_ckpt_log_message (*cell);
1115    }
1116#endif
1117
1118    DO_PAPI (PAPI_accum_var (PAPI_EventSet,PAPI_vvalues8));
1119   
1120    MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, {
1121            if (*cell)
1122            {
1123                MPIU_DBG_MSG_S (CH3_CHANNEL, VERBOSE, "<-- Recv %s", (*in_fbox) ? "fbox " : "queue");
1124                MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, MPID_nem_dbg_dump_cell(*cell));
1125            }
1126        });
1127
1128 fn_fail:
1129    return mpi_errno;
1130
1131 fbox_l:
1132    *in_fbox = 1;
1133    goto exit_l;
1134}
1135
1136/*
1137  int MPID_nem_mpich2_release_cell (MPID_nem_cell_ptr_t cell, MPIDI_VC_t *vc);
1138
1139  releases the cell back to the subsystem to be used for subsequent receives
1140*/
1141#undef FUNCNAME
1142#define FUNCNAME MPID_nem_mpich2_release_cell
1143#undef FCNAME
1144#define FCNAME MPIDI_QUOTE(FUNCNAME)
1145static inline int
1146MPID_nem_mpich2_release_cell (MPID_nem_cell_ptr_t cell, MPIDI_VC_t *vc)
1147{
1148    int mpi_errno = MPI_SUCCESS;
1149    MPIDI_CH3I_VC *vc_ch = (MPIDI_CH3I_VC *)vc->channel_private;
1150    DO_PAPI (PAPI_reset (PAPI_EventSet));
1151#ifdef ENABLED_CHECKPOINTING
1152    if (cell->pkt.header.type == MPID_NEM_PKT_CKPT_REPLAY)
1153    {
1154        if (!MPID_nem_ckpt_message_log)
1155            /* this is the last replayed message */
1156            MPID_nem_ckpt_free_msg_log();
1157        return mpi_errno;
1158    }
1159#endif
1160    MPID_nem_queue_enqueue (vc_ch->free_queue, cell);
1161    DO_PAPI (PAPI_accum_var (PAPI_EventSet,PAPI_vvalues9));
1162    return mpi_errno;
1163}
1164
1165#endif /*_MPID_NEM_INLINE_H*/
Note: See TracBrowser for help on using the browser.