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

Revision 4890, 35.3 KB (checked in by buntinas, 5 months ago)

removed debugging code that shouldn't have been checked in

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            MPIU_Memcpy((void *)pbox->cell.pkt.mpich2.payload, header, header_sz);
579           
580            /* copy data */
581            last = segment_size;
582            MPID_Segment_pack(segment, *segment_first, &last, (char *)pbox->cell.pkt.mpich2.payload + sizeof(MPIDI_CH3_Pkt_t));
583            MPIU_Assert(last == segment_size);
584
585            OPA_write_barrier();
586            pbox->flag.value = 1;
587
588            *segment_first = last;
589
590            MPIU_DBG_MSG(CH3_CHANNEL, VERBOSE, "--> Sent fbox ");
591            MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, MPID_nem_dbg_dump_cell (&pbox->cell));
592
593            goto return_success;
594        }
595    }
596 usequeue_l:
597
598#endif /*USE_FASTBOX */
599       
600#ifdef PREFETCH_CELL
601    el = MPID_nem_prefetched_cell;
602
603    if (!el)
604    {
605        if (MPID_nem_queue_empty (MPID_nem_mem_region.my_freeQ))
606        {
607            DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues5));
608            goto return_again;
609        }
610       
611        MPID_nem_queue_dequeue (MPID_nem_mem_region.my_freeQ, &el);
612    }
613#else /*PREFETCH_CELL    */
614    if (MPID_nem_queue_empty (MPID_nem_mem_region.my_freeQ))
615    {
616        DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues5));
617        goto return_again;
618    }
619
620    MPID_nem_queue_dequeue (MPID_nem_mem_region.my_freeQ, &el);
621#endif /*PREFETCH_CELL */
622
623    /* copy header */
624    MPIU_Memcpy((void *)el->pkt.mpich2.payload, header, header_sz);
625   
626    /* copy data */
627    if (segment_size - *segment_first <= MPID_NEM_MPICH2_DATA_LEN - sizeof(MPIDI_CH3_Pkt_t))
628        last = segment_size;
629    else
630        last = *segment_first + MPID_NEM_MPICH2_DATA_LEN - sizeof(MPIDI_CH3_Pkt_t);
631   
632    MPID_Segment_pack(segment, *segment_first, &last, (char *)el->pkt.mpich2.payload + sizeof(MPIDI_CH3_Pkt_t));
633    datalen = sizeof(MPIDI_CH3_Pkt_t) + last - *segment_first;
634    *segment_first = last;
635   
636    el->pkt.mpich2.source  = my_rank;
637    el->pkt.mpich2.dest    = vc->lpid;
638    el->pkt.mpich2.datalen = datalen;
639    el->pkt.mpich2.seqno   = vc_ch->send_seqno++;
640#ifdef ENABLED_CHECKPOINTING
641    el->pkt.mpich2.type = MPID_NEM_PKT_MPICH2;
642#endif
643    MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, el->pkt.mpich2.type = MPID_NEM_PKT_MPICH2_HEAD);
644
645    MPIU_DBG_MSG (CH3_CHANNEL, VERBOSE, "--> Sent queue");
646    MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, MPID_nem_dbg_dump_cell (el));
647
648    MPID_nem_queue_enqueue (vc_ch->recv_queue, el);     
649
650#ifdef PREFETCH_CELL
651    if (!MPID_nem_queue_empty (MPID_nem_mem_region.my_freeQ))
652        MPID_nem_queue_dequeue (MPID_nem_mem_region.my_freeQ, &MPID_nem_prefetched_cell);
653    else
654        MPID_nem_prefetched_cell = 0;
655#endif /*PREFETCH_CELL */
656    DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues5));
657
658 return_success:
659    *again = 0;
660    goto fn_exit;
661 return_again:
662    *again = 1;
663    goto fn_exit;
664 fn_exit:
665    return;
666}
667
668/* similar to MPID_nem_mpich2_send_seg_header, except there is no
669   header to send.  This need not be the first packet of a message. */
670#undef FUNCNAME
671#define FUNCNAME MPID_nem_mpich2_send_seg
672#undef FCNAME
673#define FCNAME MPIDI_QUOTE(FUNCNAME)
674static inline void
675MPID_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)
676{
677    MPID_nem_cell_ptr_t el;
678    MPIDI_msg_sz_t datalen;   
679    int my_rank;
680    MPIDI_msg_sz_t last;
681    MPIDI_CH3I_VC *vc_ch = (MPIDI_CH3I_VC *)vc->channel_private;
682
683    MPIU_Assert(vc_ch->is_local); /* netmods will have their own implementation */
684   
685#ifdef ENABLED_CHECKPOINTING
686    if (MPID_nem_ckpt_sending_markers)
687    {
688        MPID_nem_ckpt_send_markers();
689        goto return_again;
690    }
691#endif
692   
693    DO_PAPI (PAPI_reset (PAPI_EventSet));
694
695    my_rank = MPID_nem_mem_region.rank;
696       
697#ifdef PREFETCH_CELL
698    el = MPID_nem_prefetched_cell;
699   
700    if (!el)
701    {
702        if (MPID_nem_queue_empty (MPID_nem_mem_region.my_freeQ))
703        {
704            DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues5));
705            goto return_again;
706        }
707       
708        MPID_nem_queue_dequeue (MPID_nem_mem_region.my_freeQ, &el);
709    }
710#else /*PREFETCH_CELL    */
711    if (MPID_nem_queue_empty (MPID_nem_mem_region.my_freeQ))
712    {
713        DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues5));
714        goto return_again;
715    }
716
717    MPID_nem_queue_dequeue (MPID_nem_mem_region.my_freeQ, &el);
718#endif /*PREFETCH_CELL */
719
720    /* copy data */
721    if (segment_size - *segment_first <= MPID_NEM_MPICH2_DATA_LEN)
722        last = segment_size;
723    else
724        last = *segment_first + MPID_NEM_MPICH2_DATA_LEN;
725   
726    MPID_Segment_pack(segment, *segment_first, &last, (char *)el->pkt.mpich2.payload);
727    datalen = last - *segment_first;
728    *segment_first = last;
729   
730    el->pkt.mpich2.source  = my_rank;
731    el->pkt.mpich2.dest    = vc->lpid;
732    el->pkt.mpich2.datalen = datalen;
733    el->pkt.mpich2.seqno   = vc_ch->send_seqno++;
734#ifdef ENABLED_CHECKPOINTING
735    el->pkt.mpich2.type = MPID_NEM_PKT_MPICH2;
736#endif
737    MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, el->pkt.mpich2.type = MPID_NEM_PKT_MPICH2_HEAD);
738
739    MPIU_DBG_MSG (CH3_CHANNEL, VERBOSE, "--> Sent queue");
740    MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, MPID_nem_dbg_dump_cell (el));
741
742    MPID_nem_queue_enqueue (vc_ch->recv_queue, el);     
743
744#ifdef PREFETCH_CELL
745    if (!MPID_nem_queue_empty (MPID_nem_mem_region.my_freeQ))
746        MPID_nem_queue_dequeue (MPID_nem_mem_region.my_freeQ, &MPID_nem_prefetched_cell);
747    else
748        MPID_nem_prefetched_cell = 0;
749#endif /*PREFETCH_CELL */
750    DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues5));
751
752    *again = 0;
753    goto fn_exit;
754 return_again:
755    *again = 1;
756    goto fn_exit;
757 fn_exit:
758    return;
759}
760
761/*
762  MPID_nem_mpich2_dequeue_fastbox (int local_rank)
763  decrements usage count on fastbox for process with local rank local_rank and
764  dequeues it from fbox queue if usage is 0.
765  This function is called whenever a receive for a process on this node is matched.
766  Fastboxes on fbox queue are polled regularly for incoming messages.
767*/
768#undef FUNCNAME
769#define FUNCNAME MPID_nem_mpich2_dequeue_fastbox
770#undef FCNAME
771#define FCNAME MPIDI_QUOTE(FUNCNAME)
772static inline void MPID_nem_mpich2_dequeue_fastbox(int local_rank)
773{
774    MPID_nem_fboxq_elem_t *el;
775
776    MPIU_Assert(local_rank < MPID_nem_mem_region.num_local);
777
778    el = &MPID_nem_fboxq_elem_list[local_rank];   
779    MPIU_Assert(el->fbox != NULL);
780
781    MPIU_Assert(el->usage);
782
783    --el->usage;
784    if (el->usage == 0)
785    {
786        if (el->prev == NULL)
787            MPID_nem_fboxq_head = el->next;
788        else
789            el->prev->next = el->next;
790
791        if (el->next == NULL)
792            MPID_nem_fboxq_tail = el->prev;
793        else
794            el->next->prev = el->prev;
795
796        if (el == MPID_nem_curr_fboxq_elem)
797        {
798            if (el->next == NULL)
799                MPID_nem_curr_fboxq_elem = MPID_nem_fboxq_head;
800            else
801                MPID_nem_curr_fboxq_elem = el->next;
802        }
803    }   
804}
805
806/*
807  MPID_nem_mpich2_enqueue_fastbox (int local_rank)
808  enqueues fastbox for process with local rank local_rank on fbox queue
809  This function is called whenever a receive is posted for a process on this node.
810  Fastboxes on fbox queue are polled regularly for incoming messages.
811*/
812#undef FUNCNAME
813#define FUNCNAME MPID_nem_mpich2_dequeue_fastbox
814#undef FCNAME
815#define FCNAME MPIDI_QUOTE(FUNCNAME)
816static inline void MPID_nem_mpich2_enqueue_fastbox(int local_rank)
817{
818    MPID_nem_fboxq_elem_t *el;
819
820    MPIU_Assert(local_rank < MPID_nem_mem_region.num_local);
821
822    el = &MPID_nem_fboxq_elem_list[local_rank];
823    MPIU_Assert(el->fbox != NULL);
824
825    if (el->usage)
826    {
827        ++el->usage;
828    }
829    else
830    {
831        el->usage = 1;
832        if (MPID_nem_fboxq_tail == NULL)
833        {
834            el->prev = NULL;
835            MPID_nem_curr_fboxq_elem = MPID_nem_fboxq_head = el;
836        }
837        else
838        {
839            el->prev = MPID_nem_fboxq_tail;
840            MPID_nem_fboxq_tail->next = el;
841        }
842           
843        el->next = NULL;
844        MPID_nem_fboxq_tail = el;
845    }
846}
847/*
848  MPID_nem_recv_seqno_matches (MPID_nem_queue_ptr_t qhead)
849  check whether the sequence number for the cell at the head of qhead is the one
850  expected from the sender of that cell
851  We only check these for processes in COMM_WORLD (i.e. the ones initially allocated)
852*/
853#undef FUNCNAME
854#define FUNCNAME MPID_nem_recv_seqno_matches
855#undef FCNAME
856#define FCNAME MPIDI_QUOTE(FUNCNAME)
857static inline int
858MPID_nem_recv_seqno_matches (MPID_nem_queue_ptr_t qhead)
859{
860    int source;
861    MPID_nem_cell_ptr_t cell = MPID_nem_queue_head(qhead);
862    source = cell->pkt.mpich2.source;
863   
864    return (cell->pkt.mpich2.seqno == MPID_nem_recv_seqno[source]);
865}
866
867/*
868  int MPID_nem_mpich2_test_recv (MPID_nem_cell_ptr_t *cell, int *in_fbox);
869
870  non-blocking receive
871  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
872  the cell must be released back to the subsystem with MPID_nem_mpich2_release_cell() once the packet has been copied out
873*/
874#undef FUNCNAME
875#define FUNCNAME MPID_nem_mpich2_test_recv
876#undef FCNAME
877#define FCNAME MPIDI_QUOTE(FUNCNAME)
878static inline int
879MPID_nem_mpich2_test_recv(MPID_nem_cell_ptr_t *cell, int *in_fbox, int in_blocking_progress)
880{
881    int mpi_errno = MPI_SUCCESS;
882   
883    DO_PAPI (PAPI_reset (PAPI_EventSet));
884
885#ifdef ENABLED_CHECKPOINTING
886    MPID_nem_ckpt_maybe_take_checkpoint();
887
888    if (MPID_nem_ckpt_message_log)
889    {
890        MPID_nem_ckpt_replay_message (cell);
891        MPIU_Assert ((*cell)->pkt.mpich2.seqno == MPID_nem_recv_seqno[(*cell)->pkt.mpich2.source]);
892        ++MPID_nem_recv_seqno[(*cell)->pkt.mpich2.source];
893        *in_fbox = 0;
894        goto fn_exit;
895    }
896#endif
897   
898#ifdef USE_FASTBOX
899    if (poll_fboxes(cell)) goto fbox_l;
900#endif/* USE_FASTBOX     */
901
902    if (MPID_nem_num_netmods)
903    {
904        mpi_errno = MPID_nem_network_poll(in_blocking_progress);
905        if (mpi_errno) MPIU_ERR_POP (mpi_errno);
906    }
907
908    if (MPID_nem_queue_empty (MPID_nem_mem_region.my_recvQ) || !MPID_nem_recv_seqno_matches (MPID_nem_mem_region.my_recvQ))
909    {
910#ifdef USE_FASTBOX
911        poll_all_fboxes (cell, goto fbox_l);
912#endif/* USE_FASTBOX     */
913        *cell = NULL;
914        goto fn_exit;
915    }
916   
917    MPID_nem_queue_dequeue (MPID_nem_mem_region.my_recvQ, cell);
918
919    ++MPID_nem_recv_seqno[(*cell)->pkt.mpich2.source];
920    *in_fbox = 0;
921
922 fn_exit:
923#ifdef ENABLED_CHECKPOINTING
924    if ((*cell)->pkt.header.type == MPID_NEM_PKT_CKPT)
925        MPID_nem_ckpt_got_marker (cell, in_fbox);
926    else if (MPID_nem_ckpt_logging_messages)
927        MPID_nem_ckpt_log_message (*cell);
928#endif
929    DO_PAPI (PAPI_accum_var (PAPI_EventSet, PAPI_vvalues6));
930   
931    MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, {
932        if (*cell)
933        {
934            MPIU_DBG_MSG_S (CH3_CHANNEL, VERBOSE, "<-- Recv %s", (*in_fbox) ? "fbox " : "queue");
935            MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, MPID_nem_dbg_dump_cell (*cell));
936        }
937    });
938
939 fn_fail:
940    return mpi_errno;
941
942 fbox_l:
943    *in_fbox = 1;
944    goto fn_exit;
945
946}
947
948/*
949  int MPID_nem_mpich2_test_recv_wait (MPID_nem_cell_ptr_t *cell, int *in_fbox, int timeout);
950
951  blocking receive with timeout
952  waits up to timeout iterations to receive a cell
953  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
954  the cell must be released back to the subsystem with MPID_nem_mpich2_release_cell() once the packet has been copied out
955*/
956#undef FUNCNAME
957#define FUNCNAME MPID_nem_mpich2_test_recv_wait
958#undef FCNAME
959#define FCNAME MPIDI_QUOTE(FUNCNAME)
960static inline int
961MPID_nem_mpich2_test_recv_wait (MPID_nem_cell_ptr_t *cell, int *in_fbox, int timeout)
962{
963    int mpi_errno = MPI_SUCCESS;
964   
965#ifdef USE_FASTBOX
966    if (poll_fboxes(cell)) goto fbox_l;
967#endif/* USE_FASTBOX     */
968
969    if (MPID_nem_num_netmods)
970    {
971        mpi_errno = MPID_nem_network_poll(TRUE /* blocking */);
972        if (mpi_errno) MPIU_ERR_POP (mpi_errno);
973    }
974
975    while ((--timeout > 0) && (MPID_nem_queue_empty (MPID_nem_mem_region.my_recvQ) || !MPID_nem_recv_seqno_matches (MPID_nem_mem_region.my_recvQ)))
976    {
977#ifdef USE_FASTBOX
978        poll_all_fboxes (cell, goto fbox_l);
979#endif/* USE_FASTBOX     */
980        *cell = NULL;
981        goto exit_l;
982    }
983   
984    MPID_nem_queue_dequeue (MPID_nem_mem_region.my_recvQ, cell);
985
986    ++MPID_nem_recv_seqno[(*cell)->pkt.mpich2.source];
987    *in_fbox = 0;
988 exit_l:
989   
990    MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, {
991            if (*cell)
992            {
993                MPIU_DBG_MSG_S (CH3_CHANNEL, VERBOSE, "<-- Recv %s", (*in_fbox) ? "fbox " : "queue");
994                MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, MPID_nem_dbg_dump_cell (*cell));
995            }
996        });
997
998 fn_fail:
999    return mpi_errno;
1000
1001 fbox_l:
1002    *in_fbox = 1;
1003    goto exit_l;
1004}
1005
1006/*
1007  int MPID_nem_mpich2_blocking_recv (MPID_nem_cell_ptr_t *cell, int *in_fbox);
1008
1009  blocking receive waits until there is something to receive, or then
1010  sets cell to the received cell. in_fbox is true iff the cell was
1011  found in a fbox the cell must be released back to the subsystem with
1012  MPID_nem_mpich2_release_cell() once the packet has been copied out
1013*/
1014#undef FUNCNAME
1015#define FUNCNAME MPID_nem_mpich2_blocking_recv
1016#undef FCNAME
1017#define FCNAME MPIDI_QUOTE(FUNCNAME)
1018static inline int
1019MPID_nem_mpich2_blocking_recv(MPID_nem_cell_ptr_t *cell, int *in_fbox)
1020{
1021    int mpi_errno = MPI_SUCCESS;
1022    unsigned completions = MPIDI_CH3I_progress_completion_count;
1023#ifndef ENABLE_NO_YIELD
1024    int pollcount = 0;
1025#endif
1026    DO_PAPI (PAPI_reset (PAPI_EventSet));
1027
1028#ifdef MPICH_IS_THREADED
1029    /* We should never enter this function in a multithreaded app */
1030#ifdef HAVE_RUNTIME_THREADCHECK
1031    MPIU_Assert(!MPIR_ThreadInfo.isThreaded);
1032#else
1033    MPIU_Assert(0);
1034#endif
1035#endif
1036
1037#ifdef ENABLED_CHECKPOINTING
1038    MPID_nem_ckpt_maybe_take_checkpoint();
1039
1040 top_l:
1041    if (MPID_nem_ckpt_message_log)
1042    {
1043        MPID_nem_ckpt_replay_message (cell);
1044        MPIU_Assert ((*cell)->pkt.mpich2.seqno == MPID_nem_recv_seqno[(*cell)->pkt.mpich2.source]);
1045        ++MPID_nem_recv_seqno[(*cell)->pkt.mpich2.source];
1046        *in_fbox = 0;
1047        return mpi_errno;
1048    }
1049#endif
1050   
1051   
1052#ifdef USE_FASTBOX
1053    if (poll_fboxes(cell)) goto fbox_l;
1054#endif /*USE_FASTBOX */
1055
1056    if (MPID_nem_num_netmods)
1057    {
1058        mpi_errno = MPID_nem_network_poll(TRUE /* blocking */);
1059        if (mpi_errno) MPIU_ERR_POP (mpi_errno);
1060    }
1061
1062    while (MPID_nem_queue_empty (MPID_nem_mem_region.my_recvQ) || !MPID_nem_recv_seqno_matches (MPID_nem_mem_region.my_recvQ))
1063    {
1064        DO_PAPI (PAPI_reset (PAPI_EventSet));
1065
1066#ifdef USE_FASTBOX     
1067        poll_all_fboxes (cell, goto fbox_l);
1068        if (poll_fboxes(cell)) goto fbox_l;
1069#endif /*USE_FASTBOX */
1070
1071        if (MPID_nem_num_netmods)
1072        {           
1073            mpi_errno = MPID_nem_network_poll(TRUE /* blocking */);
1074            if (mpi_errno) MPIU_ERR_POP (mpi_errno);
1075
1076            if (completions != MPIDI_CH3I_progress_completion_count || MPID_nem_local_lmt_pending || MPIDI_CH3I_active_send[CH3_NORMAL_QUEUE]
1077                || MPIDI_CH3I_SendQ_head(CH3_NORMAL_QUEUE))
1078            {
1079                *cell = NULL;
1080                *in_fbox = 0;
1081                goto exit_l;
1082            }
1083        }
1084#if !defined ENABLE_NO_YIELD
1085        if (pollcount >= MPID_NEM_POLLS_BEFORE_YIELD)
1086        {
1087            pollcount = 0;
1088            MPIDU_Yield();
1089        }
1090        ++pollcount;
1091#endif
1092    }
1093
1094    MPID_nem_queue_dequeue (MPID_nem_mem_region.my_recvQ, cell);
1095
1096    ++MPID_nem_recv_seqno[(*cell)->pkt.mpich2.source];
1097    *in_fbox = 0;
1098
1099 exit_l:   
1100
1101#ifdef ENABLED_CHECKPOINTING
1102    if (*cell)
1103    {
1104        if ((*cell)->pkt.header.type == MPID_NEM_PKT_CKPT)
1105        {
1106            MPID_nem_ckpt_got_marker (cell, in_fbox);
1107            goto top_l;
1108        }
1109        else if (MPID_nem_ckpt_logging_messages)
1110            MPID_nem_ckpt_log_message (*cell);
1111    }
1112#endif
1113
1114    DO_PAPI (PAPI_accum_var (PAPI_EventSet,PAPI_vvalues8));
1115   
1116    MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, {
1117            if (*cell)
1118            {
1119                MPIU_DBG_MSG_S (CH3_CHANNEL, VERBOSE, "<-- Recv %s", (*in_fbox) ? "fbox " : "queue");
1120                MPIU_DBG_STMT (CH3_CHANNEL, VERBOSE, MPID_nem_dbg_dump_cell(*cell));
1121            }
1122        });
1123
1124 fn_fail:
1125    return mpi_errno;
1126
1127 fbox_l:
1128    *in_fbox = 1;
1129    goto exit_l;
1130}
1131
1132/*
1133  int MPID_nem_mpich2_release_cell (MPID_nem_cell_ptr_t cell, MPIDI_VC_t *vc);
1134
1135  releases the cell back to the subsystem to be used for subsequent receives
1136*/
1137#undef FUNCNAME
1138#define FUNCNAME MPID_nem_mpich2_release_cell
1139#undef FCNAME
1140#define FCNAME MPIDI_QUOTE(FUNCNAME)
1141static inline int
1142MPID_nem_mpich2_release_cell (MPID_nem_cell_ptr_t cell, MPIDI_VC_t *vc)
1143{
1144    int mpi_errno = MPI_SUCCESS;
1145    MPIDI_CH3I_VC *vc_ch = (MPIDI_CH3I_VC *)vc->channel_private;
1146    DO_PAPI (PAPI_reset (PAPI_EventSet));
1147#ifdef ENABLED_CHECKPOINTING
1148    if (cell->pkt.header.type == MPID_NEM_PKT_CKPT_REPLAY)
1149    {
1150        if (!MPID_nem_ckpt_message_log)
1151            /* this is the last replayed message */
1152            MPID_nem_ckpt_free_msg_log();
1153        return mpi_errno;
1154    }
1155#endif
1156    MPID_nem_queue_enqueue (vc_ch->free_queue, cell);
1157    DO_PAPI (PAPI_accum_var (PAPI_EventSet,PAPI_vvalues9));
1158    return mpi_errno;
1159}
1160
1161#endif /*_MPID_NEM_INLINE_H*/
Note: See TracBrowser for help on using the browser.