-:    0:Source:/home/MPI/testing/mpich2/mpich2/src/mpid/ch3/src/ch3u_handle_recv_pkt.c
        -:    0:Graph:ch3u_handle_recv_pkt.gcno
        -:    0:Data:ch3u_handle_recv_pkt.gcda
        -:    0:Runs:3459
        -:    0:Programs:899
        -:    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: * This file contains the dispatch routine called by the ch3 progress 
        -:   11: * engine to process messages.  
        -:   12: *
        -:   13: * This file is in transistion
        -:   14: *
        -:   15: * Where possible, the routines that create and send all packets of
        -:   16: * a particular type are in the same file that contains the implementation 
        -:   17: * of the handlers for that packet type (for example, the CancelSend 
        -:   18: * packets are created and processed by routines in ch3/src/mpid_cancel_send.c)
        -:   19: * This makes is easier to replace or modify functionality within 
        -:   20: * the ch3 device.
        -:   21: */
        -:   22:
        -:   23:#define set_request_info(rreq_, pkt_, msg_type_)		\
        -:   24:{								\
        -:   25:    (rreq_)->status.MPI_SOURCE = (pkt_)->match.parts.rank;	\
        -:   26:    (rreq_)->status.MPI_TAG = (pkt_)->match.parts.tag;		\
        -:   27:    (rreq_)->status.count = (pkt_)->data_sz;			\
        -:   28:    (rreq_)->dev.sender_req_id = (pkt_)->sender_req_id;		\
        -:   29:    (rreq_)->dev.recv_data_sz = (pkt_)->data_sz;		\
        -:   30:    MPIDI_Request_set_seqnum((rreq_), (pkt_)->seqnum);		\
        -:   31:    MPIDI_Request_set_msg_type((rreq_), (msg_type_));		\
        -:   32:}
        -:   33:
        -:   34:
        -:   35:/*
        -:   36: * MPIDI_CH3U_Handle_recv_pkt()
        -:   37: *
        -:   38: * NOTE: Multiple threads may NOT simultaneously call this routine with the 
        -:   39: * same VC.  This constraint eliminates the need to
        -:   40: * lock the VC.  If simultaneous upcalls are a possible, the calling routine 
        -:   41: * for serializing the calls.
        -:   42: */
        -:   43:
        -:   44:/* This code and definition is used to allow us to provide a routine
        -:   45:   that handles packets that are received out-of-order.  However, we 
        -:   46:   currently do not support that in the CH3 device. */
        -:   47:#define MPIDI_CH3U_Handle_ordered_recv_pkt MPIDI_CH3U_Handle_recv_pkt 
        -:   48:
        -:   49:#undef FUNCNAME
        -:   50:#define FUNCNAME MPIDI_CH3U_Handle_ordered_recv_pkt
        -:   51:#undef FCNAME
        -:   52:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:   53:int MPIDI_CH3U_Handle_ordered_recv_pkt(MPIDI_VC_t * vc, MPIDI_CH3_Pkt_t * pkt, 
        -:   54:				       MPIDI_msg_sz_t *buflen, MPID_Request ** rreqp)
    #####:   55:{
    #####:   56:    int mpi_errno = MPI_SUCCESS;
        -:   57:    static MPIDI_CH3_PktHandler_Fcn *pktArray[MPIDI_CH3_PKT_END_CH3+1];
        -:   58:    static int needsInit = 1;
        -:   59:    MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3U_HANDLE_ORDERED_RECV_PKT);
        -:   60:
        -:   61:    MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3U_HANDLE_ORDERED_RECV_PKT);
        -:   62:
        -:   63:    MPIU_DBG_STMT(CH3_OTHER,VERBOSE,MPIDI_DBG_Print_packet(pkt));
        -:   64:
        -:   65:    /* FIXME: We can turn this into something like
        -:   66:
        -:   67:       MPIU_Assert(pkt->type <= MAX_PACKET_TYPE);
        -:   68:       mpi_errno = MPIDI_CH3_ProgressFunctions[pkt->type](vc,pkt,rreqp);
        -:   69:       
        -:   70:       in the progress engine itself.  Then this routine is not necessary.
        -:   71:    */
        -:   72:
    #####:   73:    if (needsInit) {
    #####:   74:	MPIDI_CH3_PktHandler_Init( pktArray, MPIDI_CH3_PKT_END_CH3 );
    #####:   75:	needsInit = 0;
        -:   76:    }
        -:   77:    /* Packet type is an enum and hence >= 0 */
    #####:   78:    MPIU_Assert(pkt->type <= MPIDI_CH3_PKT_END_CH3);
    #####:   79:    mpi_errno = pktArray[pkt->type](vc, pkt, buflen, rreqp);
        -:   80:
        -:   81:    MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_CH3U_HANDLE_ORDERED_RECV_PKT);
    #####:   82:    return mpi_errno;
        -:   83:}
        -:   84:
        -:   85:/* 
        -:   86: * This function is used to receive data from the receive buffer to
        -:   87: * the user buffer.  If all data for this message has not been
        -:   88: * received, the request is set up to receive the next data to arrive.
        -:   89: * In turn, this request is attached to a virtual connection.
        -:   90: *
        -:   91: * buflen is an I/O parameter.  The length of the received data is
        -:   92: * passed in.  The function returns the number of bytes actually
        -:   93: * processed by this function.
        -:   94: *
        -:   95: * complete is an OUTPUT variable.  It is set to TRUE iff all of the
        -:   96: * data for the request has been received.  This function does not
        -:   97: * actually complete the request.
        -:   98: */
        -:   99:#undef FUNCNAME
        -:  100:#define FUNCNAME MPIDI_CH3U_Receive_data_found
        -:  101:#undef FCNAME
        -:  102:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  103:int MPIDI_CH3U_Receive_data_found(MPID_Request *rreq, char *buf, MPIDI_msg_sz_t *buflen, int *complete)
  8549121:  104:{
        -:  105:    int dt_contig;
        -:  106:    MPI_Aint dt_true_lb;
        -:  107:    MPIDI_msg_sz_t userbuf_sz;
  8549121:  108:    MPID_Datatype * dt_ptr = NULL;
        -:  109:    MPIDI_msg_sz_t data_sz;
  8549121:  110:    int mpi_errno = MPI_SUCCESS;
        -:  111:    MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3U_RECEIVE_DATA_FOUND);
        -:  112:
        -:  113:    MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3U_RECEIVE_DATA_FOUND);
        -:  114:
        -:  115:    MPIU_DBG_MSG(CH3_OTHER,VERBOSE,"posted request found");
        -:  116:	
  8549121:  117:    MPIDI_Datatype_get_info(rreq->dev.user_count, rreq->dev.datatype, 
        -:  118:			    dt_contig, userbuf_sz, dt_ptr, dt_true_lb);
        -:  119:		
  8549121:  120:    if (rreq->dev.recv_data_sz <= userbuf_sz) {
  8549109:  121:	data_sz = rreq->dev.recv_data_sz;
        -:  122:    }
        -:  123:    else {
        -:  124:	MPIU_DBG_MSG_FMT(CH3_OTHER,VERBOSE,(MPIU_DBG_FDEST,
        -:  125:               "receive buffer too small; message truncated, msg_sz=" MPIDI_MSG_SZ_FMT ", userbuf_sz="
        -:  126:					    MPIDI_MSG_SZ_FMT,
        -:  127:				 rreq->dev.recv_data_sz, userbuf_sz));
       12:  128:	rreq->status.MPI_ERROR = MPIR_Err_create_code(MPI_SUCCESS, 
        -:  129:                     MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_TRUNCATE,
        -:  130:		     "**truncate", "**truncate %d %d %d %d", 
        -:  131:		     rreq->status.MPI_SOURCE, rreq->status.MPI_TAG, 
        -:  132:		     rreq->dev.recv_data_sz, userbuf_sz );
       12:  133:	rreq->status.count = userbuf_sz;
       12:  134:	data_sz = userbuf_sz;
        -:  135:    }
        -:  136:
 16967631:  137:    if (dt_contig && data_sz == rreq->dev.recv_data_sz)
        -:  138:    {
        -:  139:	/* user buffer is contiguous and large enough to store the
        -:  140:	   entire message.  However, we haven't yet *read* the data 
        -:  141:	   (this code describes how to read the data into the destination) */
        -:  142:
        -:  143:        /* if all of the data has already been received, unpack it
        -:  144:           now, otherwise build an iov and let the channel unpack */
  8418510:  145:        if (*buflen >= data_sz)
        -:  146:        {
        -:  147:            MPIU_DBG_MSG(CH3_OTHER,VERBOSE,"Copying contiguous data to user buffer");
        -:  148:            /* copy data out of the receive buffer */
    #####:  149:            MPIU_Memcpy((char*)(rreq->dev.user_buf) + dt_true_lb, buf, data_sz);
    #####:  150:            *buflen = data_sz;
    #####:  151:            *complete = TRUE;
        -:  152:        }
        -:  153:        else
        -:  154:        {
        -:  155:            MPIU_DBG_MSG(CH3_OTHER,VERBOSE,"IOV loaded for contiguous read");
        -:  156:            
  8418510:  157:            rreq->dev.iov[0].MPID_IOV_BUF = 
        -:  158:                (MPID_IOV_BUF_CAST)((char*)(rreq->dev.user_buf) + dt_true_lb);
  8418510:  159:            rreq->dev.iov[0].MPID_IOV_LEN = data_sz;
  8418510:  160:            rreq->dev.iov_count = 1;
  8418510:  161:            *buflen = 0;
  8418510:  162:            *complete = FALSE;
        -:  163:        }
        -:  164:        
        -:  165:	/* FIXME: We want to set the OnDataAvail to the appropriate 
        -:  166:	   function, which depends on whether this is an RMA 
        -:  167:	   request or a pt-to-pt request. */
  8418510:  168:	rreq->dev.OnDataAvail = 0;
        -:  169:    }
        -:  170:    else {
        -:  171:	/* user buffer is not contiguous or is too small to hold
        -:  172:	   the entire message */
        -:  173:        
   130611:  174:	rreq->dev.segment_ptr = MPID_Segment_alloc( );
   130611:  175:        MPIU_ERR_CHKANDJUMP1((rreq->dev.segment_ptr == NULL), mpi_errno, MPI_ERR_OTHER, "**nomem", "**nomem %s", "MPID_Segment_alloc");
        -:  176:
   130611:  177: 	MPID_Segment_init(rreq->dev.user_buf, rreq->dev.user_count, 
        -:  178:			  rreq->dev.datatype, rreq->dev.segment_ptr, 0);
   130611:  179:	rreq->dev.segment_first = 0;
   130611:  180:	rreq->dev.segment_size  = data_sz;
        -:  181:
        -:  182:        /* if all of the data has already been received, and the
        -:  183:           message is not truncated, unpack it now, otherwise build an
        -:  184:           iov and let the channel unpack */
   130611:  185:        if (data_sz == rreq->dev.recv_data_sz && *buflen >= data_sz)
        -:  186:        {
        -:  187:            MPIDI_msg_sz_t last;
        -:  188:            MPIU_DBG_MSG(CH3_OTHER,VERBOSE,"Copying noncontiguous data to user buffer");
    #####:  189:            last = data_sz;
    #####:  190:            MPID_Segment_unpack(rreq->dev.segment_ptr, rreq->dev.segment_first, 
        -:  191:				&last, buf);
        -:  192:            /* --BEGIN ERROR HANDLING-- */
    #####:  193:            if (last != data_sz)
        -:  194:            {
        -:  195:                /* If the data can't be unpacked, the we have a
        -:  196:                   mismatch between the datatype and the amount of
        -:  197:                   data received.  Throw away received data. */
    #####:  198:                MPIU_ERR_SET(rreq->status.MPI_ERROR, MPI_ERR_TYPE, "**dtypemismatch");
    #####:  199:                rreq->status.count = (int)rreq->dev.segment_first;
    #####:  200:                *buflen = data_sz;
    #####:  201:                *complete = TRUE;
        -:  202:		/* FIXME: Set OnDataAvail to 0?  If not, why not? */
    #####:  203:                goto fn_exit;
        -:  204:            }
        -:  205:            /* --END ERROR HANDLING-- */
    #####:  206:            *buflen = data_sz;
    #####:  207:            rreq->dev.OnDataAvail = 0;
    #####:  208:            *complete = TRUE;
        -:  209:        }
        -:  210:        else
        -:  211:        {   
        -:  212:            MPIU_DBG_MSG(CH3_OTHER,VERBOSE,"IOV loaded for non-contiguous read");
        -:  213:
   130611:  214:            mpi_errno = MPIDI_CH3U_Request_load_recv_iov(rreq);
   130611:  215:            if (mpi_errno != MPI_SUCCESS) {
    #####:  216:                MPIU_ERR_SETFATALANDJUMP(mpi_errno,MPI_ERR_OTHER,
        -:  217:                                         "**ch3|loadrecviov");
        -:  218:            }
   130611:  219:            *buflen = 0;
   130611:  220:            *complete = FALSE;
        -:  221:        }
        -:  222:    }
        -:  223:
  8549121:  224: fn_exit:
        -:  225:    MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_CH3U_RECEIVE_DATA_FOUND);
  8549121:  226:    return mpi_errno;
        -:  227:fn_fail:
        -:  228:    goto fn_exit;
        -:  229:}
        -:  230:
        -:  231:#undef FUNCNAME
        -:  232:#define FUNCNAME MPIDI_CH3U_Receive_data_unexpected
        -:  233:#undef FCNAME
        -:  234:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  235:int MPIDI_CH3U_Receive_data_unexpected(MPID_Request * rreq, char *buf, MPIDI_msg_sz_t *buflen, int *complete)
   983889:  236:{
   983889:  237:    int mpi_errno = MPI_SUCCESS;
        -:  238:    MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3U_RECEIVE_DATA_UNEXPECTED);
        -:  239:
        -:  240:    MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3U_RECEIVE_DATA_UNEXPECTED);
        -:  241:
        -:  242:    /* FIXME: to improve performance, allocate temporary buffer from a 
        -:  243:       specialized buffer pool. */
        -:  244:    /* FIXME: to avoid memory exhaustion, integrate buffer pool management
        -:  245:       with flow control */
        -:  246:    MPIU_DBG_MSG(CH3_OTHER,VERBOSE,"unexpected request allocated");
        -:  247:    
   983889:  248:    rreq->dev.tmpbuf = MPIU_Malloc(rreq->dev.recv_data_sz);
   983889:  249:    if (!rreq->dev.tmpbuf) {
    #####:  250:	MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER,"**nomem");
        -:  251:    }
   983889:  252:    rreq->dev.tmpbuf_sz = rreq->dev.recv_data_sz;
        -:  253:    
        -:  254:    /* if all of the data has already been received, copy it
        -:  255:       now, otherwise build an iov and let the channel copy it */
   983889:  256:    if (rreq->dev.recv_data_sz <= *buflen)
        -:  257:    {
    #####:  258:        MPIU_Memcpy(rreq->dev.tmpbuf, buf, rreq->dev.recv_data_sz);
    #####:  259:        *buflen = rreq->dev.recv_data_sz;
    #####:  260:        rreq->dev.recv_pending_count = 1;
    #####:  261:        *complete = TRUE;
        -:  262:    }
        -:  263:    else
        -:  264:    {
   983889:  265:        rreq->dev.iov[0].MPID_IOV_BUF = (MPID_IOV_BUF_CAST)((char *)rreq->dev.tmpbuf);
   983889:  266:        rreq->dev.iov[0].MPID_IOV_LEN = rreq->dev.recv_data_sz;
   983889:  267:        rreq->dev.iov_count = 1;
   983889:  268:        rreq->dev.recv_pending_count = 2;
   983889:  269:        *buflen = 0;
   983889:  270:        *complete = FALSE;
        -:  271:    }
        -:  272:
   983889:  273:    rreq->dev.OnDataAvail = MPIDI_CH3_ReqHandler_UnpackUEBufComplete;
        -:  274:
   983889:  275: fn_fail:
        -:  276:    MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_CH3U_RECEIVE_DATA_UNEXPECTED);
   983889:  277:    return mpi_errno;
        -:  278:}
        -:  279:
        -:  280:/* 
        -:  281: * This function is used to post a receive operation on a request for the 
        -:  282: * next data to arrive.  In turn, this request is attached to a virtual
        -:  283: * connection.
        -:  284: */
        -:  285:#undef FUNCNAME
        -:  286:#define FUNCNAME MPIDI_CH3U_Post_data_receive_found
        -:  287:#undef FCNAME
        -:  288:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  289:int MPIDI_CH3U_Post_data_receive_found(MPID_Request * rreq)
    #####:  290:{
    #####:  291:    int mpi_errno = MPI_SUCCESS;	
        -:  292:    int dt_contig;
        -:  293:    MPI_Aint dt_true_lb;
        -:  294:    MPIDI_msg_sz_t userbuf_sz;
    #####:  295:    MPID_Datatype * dt_ptr = NULL;
        -:  296:    MPIDI_msg_sz_t data_sz;
        -:  297:    MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3U_POST_DATA_RECEIVE_FOUND);
        -:  298:
        -:  299:    MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3U_POST_DATA_RECEIVE_FOUND);
        -:  300:
        -:  301:    MPIU_DBG_MSG(CH3_OTHER,VERBOSE,"posted request found");
        -:  302:	
    #####:  303:    MPIDI_Datatype_get_info(rreq->dev.user_count, rreq->dev.datatype, 
        -:  304:			    dt_contig, userbuf_sz, dt_ptr, dt_true_lb);
        -:  305:		
    #####:  306:    if (rreq->dev.recv_data_sz <= userbuf_sz) {
    #####:  307:	data_sz = rreq->dev.recv_data_sz;
        -:  308:    }
        -:  309:    else {
        -:  310:	MPIU_DBG_MSG_FMT(CH3_OTHER,VERBOSE,(MPIU_DBG_FDEST,
        -:  311:               "receive buffer too small; message truncated, msg_sz=" MPIDI_MSG_SZ_FMT ", userbuf_sz="
        -:  312:					    MPIDI_MSG_SZ_FMT,
        -:  313:				 rreq->dev.recv_data_sz, userbuf_sz));
    #####:  314:	rreq->status.MPI_ERROR = MPIR_Err_create_code(MPI_SUCCESS, 
        -:  315:                     MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_TRUNCATE,
        -:  316:		     "**truncate", "**truncate %d %d %d %d", 
        -:  317:		     rreq->status.MPI_SOURCE, rreq->status.MPI_TAG, 
        -:  318:		     rreq->dev.recv_data_sz, userbuf_sz );
    #####:  319:	rreq->status.count = userbuf_sz;
    #####:  320:	data_sz = userbuf_sz;
        -:  321:    }
        -:  322:
    #####:  323:    if (dt_contig && data_sz == rreq->dev.recv_data_sz)
        -:  324:    {
        -:  325:	/* user buffer is contiguous and large enough to store the
        -:  326:	   entire message.  However, we haven't yet *read* the data 
        -:  327:	   (this code describes how to read the data into the destination) */
        -:  328:	MPIU_DBG_MSG(CH3_OTHER,VERBOSE,"IOV loaded for contiguous read");
    #####:  329:	rreq->dev.iov[0].MPID_IOV_BUF = 
        -:  330:	    (MPID_IOV_BUF_CAST)((char*)(rreq->dev.user_buf) + dt_true_lb);
    #####:  331:	rreq->dev.iov[0].MPID_IOV_LEN = data_sz;
    #####:  332:	rreq->dev.iov_count = 1;
        -:  333:	/* FIXME: We want to set the OnDataAvail to the appropriate 
        -:  334:	   function, which depends on whether this is an RMA 
        -:  335:	   request or a pt-to-pt request. */
    #####:  336:	rreq->dev.OnDataAvail = 0;
        -:  337:    }
        -:  338:    else {
        -:  339:	/* user buffer is not contiguous or is too small to hold
        -:  340:	   the entire message */
        -:  341:	MPIU_DBG_MSG(CH3_OTHER,VERBOSE,"IOV loaded for non-contiguous read");
    #####:  342:	rreq->dev.segment_ptr = MPID_Segment_alloc( );
    #####:  343:        MPIU_ERR_CHKANDJUMP1((rreq->dev.segment_ptr == NULL), mpi_errno, MPI_ERR_OTHER, "**nomem", "**nomem %s", "MPID_Segment_alloc");
    #####:  344:	MPID_Segment_init(rreq->dev.user_buf, rreq->dev.user_count, 
        -:  345:			  rreq->dev.datatype, rreq->dev.segment_ptr, 0);
    #####:  346:	rreq->dev.segment_first = 0;
    #####:  347:	rreq->dev.segment_size = data_sz;
    #####:  348:	mpi_errno = MPIDI_CH3U_Request_load_recv_iov(rreq);
    #####:  349:	if (mpi_errno != MPI_SUCCESS) {
    #####:  350:	    MPIU_ERR_SETFATALANDJUMP(mpi_errno,MPI_ERR_OTHER,
        -:  351:				     "**ch3|loadrecviov");
        -:  352:	}
        -:  353:    }
        -:  354:
    #####:  355: fn_exit:
        -:  356:    MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_CH3U_POST_DATA_RECEIVE_FOUND);
    #####:  357:    return mpi_errno;
        -:  358: fn_fail:
        -:  359:    goto fn_exit;
        -:  360:}
        -:  361:
        -:  362:#undef FUNCNAME
        -:  363:#define FUNCNAME MPIDI_CH3U_Post_data_receive_unexpected
        -:  364:#undef FCNAME
        -:  365:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  366:int MPIDI_CH3U_Post_data_receive_unexpected(MPID_Request * rreq)
    #####:  367:{
    #####:  368:    int mpi_errno = MPI_SUCCESS;
        -:  369:    MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3U_POST_DATA_RECEIVE_UNEXPECTED);
        -:  370:
        -:  371:    MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3U_POST_DATA_RECEIVE_UNEXPECTED);
        -:  372:
        -:  373:    /* FIXME: to improve performance, allocate temporary buffer from a 
        -:  374:       specialized buffer pool. */
        -:  375:    /* FIXME: to avoid memory exhaustion, integrate buffer pool management
        -:  376:       with flow control */
        -:  377:    MPIU_DBG_MSG(CH3_OTHER,VERBOSE,"unexpected request allocated");
        -:  378:    
    #####:  379:    rreq->dev.tmpbuf = MPIU_Malloc(rreq->dev.recv_data_sz);
    #####:  380:    if (!rreq->dev.tmpbuf) {
    #####:  381:	MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER,"**nomem");
        -:  382:    }
    #####:  383:    rreq->dev.tmpbuf_sz = rreq->dev.recv_data_sz;
        -:  384:    
    #####:  385:    rreq->dev.iov[0].MPID_IOV_BUF = (MPID_IOV_BUF_CAST)rreq->dev.tmpbuf;
    #####:  386:    rreq->dev.iov[0].MPID_IOV_LEN = rreq->dev.recv_data_sz;
    #####:  387:    rreq->dev.iov_count = 1;
    #####:  388:    rreq->dev.OnDataAvail = MPIDI_CH3_ReqHandler_UnpackUEBufComplete;
    #####:  389:    rreq->dev.recv_pending_count = 2;
        -:  390:
    #####:  391: fn_fail:
        -:  392:    MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_CH3U_POST_DATA_RECEIVE_UNEXPECTED);
    #####:  393:    return mpi_errno;
        -:  394:}
        -:  395:
        -:  396:
        -:  397:/* Check if requested lock can be granted. If it can, set 
        -:  398:   win_ptr->current_lock_type to the new lock type and return 1. Else return 0.
        -:  399:
        -:  400:   FIXME: MT: This function must be atomic because two threads could be trying 
        -:  401:   to do the same thing, e.g., the main thread in MPI_Win_lock(source=target) 
        -:  402:   and another thread in the progress engine.
        -:  403: */
        -:  404:#undef FUNCNAME
        -:  405:#define FUNCNAME MPIDI_CH3I_Try_acquire_win_lock
        -:  406:#undef FCNAME
        -:  407:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  408:int MPIDI_CH3I_Try_acquire_win_lock(MPID_Win *win_ptr, int requested_lock)
     1569:  409:{
        -:  410:    int existing_lock;
        -:  411:    MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3I_TRY_ACQUIRE_WIN_LOCK);
        -:  412:    
        -:  413:    MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3I_TRY_ACQUIRE_WIN_LOCK);
        -:  414:
     1569:  415:    existing_lock = win_ptr->current_lock_type;
        -:  416:
        -:  417:    /* Locking Rules:
        -:  418:       
        -:  419:    Requested          Existing             Action
        -:  420:    --------           --------             ------
        -:  421:    Shared             Exclusive            Queue it
        -:  422:    Shared             NoLock/Shared        Grant it
        -:  423:    Exclusive          NoLock               Grant it
        -:  424:    Exclusive          Exclusive/Shared     Queue it
        -:  425:    */
        -:  426:
     1569:  427:    if ( ( (requested_lock == MPI_LOCK_SHARED) && 
        -:  428:           ((existing_lock == MPID_LOCK_NONE) ||
        -:  429:            (existing_lock == MPI_LOCK_SHARED) ) )
        -:  430:         || 
        -:  431:         ( (requested_lock == MPI_LOCK_EXCLUSIVE) &&
        -:  432:           (existing_lock == MPID_LOCK_NONE) ) ) {
        -:  433:
        -:  434:        /* grant lock.  set new lock type on window */
     1095:  435:        win_ptr->current_lock_type = requested_lock;
        -:  436:
        -:  437:        /* if shared lock, incr. ref. count */
     1095:  438:        if (requested_lock == MPI_LOCK_SHARED)
      405:  439:            win_ptr->shared_lock_ref_cnt++;
        -:  440:
        -:  441:	MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_CH3I_TRY_ACQUIRE_WIN_LOCK);
     1095:  442:        return 1;
        -:  443:    }
        -:  444:    else {
        -:  445:        /* do not grant lock */
        -:  446:	MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_CH3I_TRY_ACQUIRE_WIN_LOCK);
      474:  447:        return 0;
        -:  448:    }
        -:  449:}
        -:  450:
        -:  451:
        -:  452:
        -:  453:/* ------------------------------------------------------------------------ */
        -:  454:/* Here are the functions that implement the packet actions.  They'll be moved
        -:  455: * to more modular places where it will be easier to replace subsets of the
        -:  456: * in order to experiement with alternative data transfer methods, such as
        -:  457: * sending some data with a rendezvous request or including data within
        -:  458: * an eager message.                                                        
        -:  459: *
        -:  460: * The convention for the names of routines that handle packets is
        -:  461: *   MPIDI_CH3_PktHandler_<type>( MPIDI_VC_t *vc, MPIDI_CH3_Pkt_t *pkt )
        -:  462: * as in
        -:  463: *   MPIDI_CH3_PktHandler_EagerSend
        -:  464: *
        -:  465: * Each packet type also has a routine that understands how to print that
        -:  466: * packet type, this routine is
        -:  467: *   MPIDI_CH3_PktPrint_<type>( FILE *, MPIDI_CH3_Pkt_t * )
        -:  468: *                                                                          */
        -:  469:/* ------------------------------------------------------------------------ */
        -:  470:
        -:  471:
        -:  472:/* FIXME: we still need to implement flow control.  As a reminder, 
        -:  473:   we don't mark these parameters as unused, because a full implementation
        -:  474:   of this routine will need to make use of all 4 parameters */
        -:  475:#undef FUNCNAME
        -:  476:#define FUNCNAME MPIDI_CH3_PktHandler_FlowCntlUpdate
        -:  477:#undef FCNAME
        -:  478:int MPIDI_CH3_PktHandler_FlowCntlUpdate( MPIDI_VC_t *vc, MPIDI_CH3_Pkt_t *pkt,
        -:  479:					 MPIDI_msg_sz_t *buflen, MPID_Request **rreqp)
    #####:  480:{
    #####:  481:    *buflen = sizeof(MPIDI_CH3_Pkt_t);
    #####:  482:    return MPI_SUCCESS;
        -:  483:}
        -:  484:
        -:  485:/* This is a dummy handler*/
        -:  486:#undef FUNCNAME
        -:  487:#define FUNCNAME MPIDI_CH3_PktHandler_EndCH3
        -:  488:#undef FCNAME
        -:  489:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  490:int MPIDI_CH3_PktHandler_EndCH3( MPIDI_VC_t *vc ATTRIBUTE((unused)), 
        -:  491:				 MPIDI_CH3_Pkt_t *pkt ATTRIBUTE((unused)),
        -:  492:				 MPIDI_msg_sz_t *buflen ATTRIBUTE((unused)), 
        -:  493:				 MPID_Request **rreqp ATTRIBUTE((unused)) )
    #####:  494:{
        -:  495:    MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3_PKTHANDLER_ENDCH3);
        -:  496:    
        -:  497:    MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3_PKTHANDLER_ENDCH3);
        -:  498:
        -:  499:    MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_CH3_PKTHANDLER_ENDCH3);
        -:  500:
    #####:  501:    return MPI_SUCCESS;
        -:  502:}
        -:  503:
        -:  504:
        -:  505:/* ------------------------------------------------------------------------- */
        -:  506:/* This routine may be called within a channel to initialize an 
        -:  507:   array of packet handler functions, indexed by packet type.
        -:  508:
        -:  509:   This function initializes an array so that the array may be private 
        -:  510:   to the file that contains the progress function, if this is 
        -:  511:   appropriate (this allows the compiler to reduce the cost in 
        -:  512:   accessing the elements of the array in some cases).
        -:  513:*/
        -:  514:#undef FUNCNAME
        -:  515:#define FUNCNAME MPIDI_CH3_PktHandler_Init
        -:  516:#undef FCNAME
        -:  517:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  518:int MPIDI_CH3_PktHandler_Init( MPIDI_CH3_PktHandler_Fcn *pktArray[], 
        -:  519:			       int arraySize  )
     3459:  520:{
     3459:  521:    int mpi_errno = MPI_SUCCESS;
        -:  522:    MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3_PKTHANDLER_INIT);
        -:  523:    
        -:  524:    MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3_PKTHANDLER_INIT);
        -:  525:
        -:  526:    /* Check that the array is large enough */
     3459:  527:    if (arraySize < MPIDI_CH3_PKT_END_CH3) {
    #####:  528:	MPIU_ERR_SETFATALANDJUMP(mpi_errno,MPI_ERR_INTERN,
        -:  529:				 "**ch3|pktarraytoosmall");
        -:  530:    }
     3459:  531:    pktArray[MPIDI_CH3_PKT_EAGER_SEND] = 
        -:  532:	MPIDI_CH3_PktHandler_EagerSend;
        -:  533:#ifdef USE_EAGER_SHORT
     3459:  534:    pktArray[MPIDI_CH3_PKT_EAGERSHORT_SEND] = 
        -:  535:	MPIDI_CH3_PktHandler_EagerShortSend;
        -:  536:#endif
     3459:  537:    pktArray[MPIDI_CH3_PKT_READY_SEND] = 
        -:  538:	MPIDI_CH3_PktHandler_ReadySend;
     3459:  539:    pktArray[MPIDI_CH3_PKT_EAGER_SYNC_SEND] = 
        -:  540:	MPIDI_CH3_PktHandler_EagerSyncSend;
     3459:  541:    pktArray[MPIDI_CH3_PKT_EAGER_SYNC_ACK] = 
        -:  542:	MPIDI_CH3_PktHandler_EagerSyncAck;
     3459:  543:    pktArray[MPIDI_CH3_PKT_RNDV_REQ_TO_SEND] =
        -:  544:	MPIDI_CH3_PktHandler_RndvReqToSend;
     3459:  545:    pktArray[MPIDI_CH3_PKT_RNDV_CLR_TO_SEND] = 
        -:  546:	MPIDI_CH3_PktHandler_RndvClrToSend;
     3459:  547:    pktArray[MPIDI_CH3_PKT_RNDV_SEND] = 
        -:  548:	MPIDI_CH3_PktHandler_RndvSend;
     3459:  549:    pktArray[MPIDI_CH3_PKT_CANCEL_SEND_REQ] = 
        -:  550:	MPIDI_CH3_PktHandler_CancelSendReq;
     3459:  551:    pktArray[MPIDI_CH3_PKT_CANCEL_SEND_RESP] = 
        -:  552:	MPIDI_CH3_PktHandler_CancelSendResp;
        -:  553:
        -:  554:    /* Connection Management */
     3459:  555:    pktArray[MPIDI_CH3_PKT_CLOSE] =
        -:  556:	MPIDI_CH3_PktHandler_Close;
        -:  557:
        -:  558:    /* Provision for flow control */
     3459:  559:    pktArray[MPIDI_CH3_PKT_FLOW_CNTL_UPDATE] = 0;
        -:  560:
        -:  561:
        -:  562:    /* Default RMA operations */
        -:  563:    /* FIXME: This should be initialized by a separate, RMA routine.
        -:  564:       That would allow different RMA implementations.
        -:  565:       We could even do lazy initialization (make this part of win_create) */
     3459:  566:    pktArray[MPIDI_CH3_PKT_PUT] = 
        -:  567:	MPIDI_CH3_PktHandler_Put;
     3459:  568:    pktArray[MPIDI_CH3_PKT_ACCUMULATE] = 
        -:  569:	MPIDI_CH3_PktHandler_Accumulate;
     3459:  570:    pktArray[MPIDI_CH3_PKT_GET] = 
        -:  571:	MPIDI_CH3_PktHandler_Get;
     3459:  572:    pktArray[MPIDI_CH3_PKT_GET_RESP] = 
        -:  573:	MPIDI_CH3_PktHandler_GetResp;
     3459:  574:    pktArray[MPIDI_CH3_PKT_LOCK] =
        -:  575:	MPIDI_CH3_PktHandler_Lock;
     3459:  576:    pktArray[MPIDI_CH3_PKT_LOCK_GRANTED] =
        -:  577:	MPIDI_CH3_PktHandler_LockGranted;
     3459:  578:    pktArray[MPIDI_CH3_PKT_PT_RMA_DONE] = 
        -:  579:	MPIDI_CH3_PktHandler_PtRMADone;
     3459:  580:    pktArray[MPIDI_CH3_PKT_LOCK_PUT_UNLOCK] = 
        -:  581:	MPIDI_CH3_PktHandler_LockPutUnlock;
     3459:  582:    pktArray[MPIDI_CH3_PKT_LOCK_ACCUM_UNLOCK] =
        -:  583:	MPIDI_CH3_PktHandler_LockAccumUnlock;
     3459:  584:    pktArray[MPIDI_CH3_PKT_LOCK_GET_UNLOCK] = 
        -:  585:	MPIDI_CH3_PktHandler_LockGetUnlock;
        -:  586:    /* End of default RMA operations */
        -:  587:
     3459:  588: fn_fail:
        -:  589:    MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_CH3_PKTHANDLER_INIT);
     3459:  590:    return mpi_errno;
        -:  591:}
        -:  592: