-:    0:Source:/home/MPI/testing/mpich2/mpich2/src/mpid/ch3/src/ch3u_request.c
        -:    0:Graph:ch3u_request.gcno
        -:    0:Data:ch3u_request.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:/* This file contains two types of routines associated with requests: 
        -:   10: * Routines to allocate and free requests
        -:   11: * Routines to manage iovs on requests 
        -:   12: *
        -:   13: * Note that there are a number of macros that also manage requests defined
        -:   14: * in mpidimpl.h ; these are intended to optimize request creation for
        -:   15: * specific types of requests.  See the comments in mpidimpl.h for more
        -:   16: * details.
        -:   17: */
        -:   18:
        -:   19:/* Routines and data structures for request allocation and deallocation */
        -:   20:#ifndef MPID_REQUEST_PREALLOC
        -:   21:#define MPID_REQUEST_PREALLOC 8
        -:   22:#endif
        -:   23:
        -:   24:MPID_Request MPID_Request_direct[MPID_REQUEST_PREALLOC] = {{0}};
        -:   25:MPIU_Object_alloc_t MPID_Request_mem = {
        -:   26:    0, 0, 0, 0, MPID_REQUEST, sizeof(MPID_Request), MPID_Request_direct,
        -:   27:    MPID_REQUEST_PREALLOC };
        -:   28:
        -:   29:/* See the comments above about request creation.  Some routines will
        -:   30:   use macros in mpidimpl.h *instead* of this routine */
        -:   31:#undef FUNCNAME
        -:   32:#define FUNCNAME MPID_Request_create
        -:   33:#undef FCNAME
        -:   34:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:   35:MPID_Request * MPID_Request_create(void)
   580657:   36:{
        -:   37:    MPID_Request * req;
        -:   38:    MPIDI_STATE_DECL(MPID_STATE_MPID_REQUEST_CREATE);
        -:   39:
        -:   40:    MPIDI_FUNC_ENTER(MPID_STATE_MPID_REQUEST_CREATE);
        -:   41:    
   580657:   42:    req = MPIU_Handle_obj_alloc(&MPID_Request_mem);
   580657:   43:    if (req != NULL)
        -:   44:    {
        -:   45:	MPIU_DBG_MSG_P(CH3_CHANNEL,VERBOSE,
        -:   46:		       "allocated request, handle=0x%08x", req->handle);
        -:   47:#ifdef MPICH_DBG_OUTPUT
        -:   48:	/*MPIU_Assert(HANDLE_GET_MPI_KIND(req->handle) == MPID_REQUEST);*/
        -:   49:	if (HANDLE_GET_MPI_KIND(req->handle) != MPID_REQUEST)
        -:   50:	{
        -:   51:	    int mpi_errno;
        -:   52:	    mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_FATAL, 
        -:   53:		       FCNAME, __LINE__, MPI_ERR_OTHER, 
        -:   54:		       "**invalid_handle", "**invalid_handle %d", req->handle);
        -:   55:	    MPID_Abort(MPIR_Process.comm_world, mpi_errno, -1, NULL);
        -:   56:	}
        -:   57:#endif
        -:   58:	/* FIXME: This makes request creation expensive.  We need to trim
        -:   59:	   this to the basics, with additional setup for special-purpose 
        -:   60:	   requests (think base class and inheritance).  For example, do we 
        -:   61:	   *really* want to set the kind to UNDEFINED? And should the RMA 
        -:   62:	   values be set only for RMA requests? */
   580657:   63:	MPIU_Object_set_ref(req, 1);
   580657:   64:	req->kind		   = MPID_REQUEST_UNDEFINED;
   580657:   65:	req->cc			   = 1;
   580657:   66:	req->cc_ptr		   = &req->cc;
        -:   67:	/* FIXME: status fields meaningful only for receive, and even then
        -:   68:	   should not need to be set. */
   580657:   69:	req->status.MPI_SOURCE	   = MPI_UNDEFINED;
   580657:   70:	req->status.MPI_TAG	   = MPI_UNDEFINED;
   580657:   71:	req->status.MPI_ERROR	   = MPI_SUCCESS;
   580657:   72:	req->status.count	   = 0;
   580657:   73:	req->status.cancelled	   = FALSE;
   580657:   74:	req->comm		   = NULL;
   580657:   75:	req->dev.datatype_ptr	   = NULL;
   580657:   76:	req->dev.segment_ptr	   = NULL;
        -:   77:	/* Masks and flags for channel device state in an MPID_Request */
   580657:   78:	req->dev.state		   = 0;
   580657:   79:	req->dev.cancel_pending	   = FALSE;
        -:   80:	/* FIXME: RMA ops shouldn't need to be set except when creating a
        -:   81:	   request for RMA operations */
   580657:   82:	req->dev.target_win_handle = MPI_WIN_NULL;
   580657:   83:	req->dev.source_win_handle = MPI_WIN_NULL;
   580657:   84:	req->dev.single_op_opt	   = 0;
   580657:   85:	req->dev.lock_queue_entry  = NULL;
   580657:   86:	req->dev.dtype_info	   = NULL;
   580657:   87:	req->dev.dataloop	   = NULL;
   580657:   88:	req->dev.iov_offset        = 0;
        -:   89:#if 0
        -:   90:	req->dev.rdma_iov_count	   = 0;
        -:   91:	req->dev.rdma_iov_offset   = 0;
        -:   92:#endif
        -:   93:#ifdef MPIDI_CH3_REQUEST_INIT
        -:   94:	MPIDI_CH3_REQUEST_INIT(req);
        -:   95:#endif
        -:   96:    }
        -:   97:    else
        -:   98:    {
        -:   99:	/* FIXME: This fails to fail if debugging is turned off */
        -:  100:	MPIU_DBG_MSG(CH3_CHANNEL,TYPICAL,"unable to allocate a request");
        -:  101:    }
        -:  102:    
        -:  103:    MPIDI_FUNC_EXIT(MPID_STATE_MPID_REQUEST_CREATE);
   580657:  104:    return req;
        -:  105:}
        -:  106:
        -:  107:/* FIXME: We need a lighter-weight version of this to avoid all of the
        -:  108:   extra checks.  One posibility would be a single, no special case (no 
        -:  109:   comm, datatype, or srbuf to check) and a more general (check everything)
        -:  110:   version.  */
        -:  111:#undef FUNCNAME
        -:  112:#define FUNCNAME MPIDI_CH3_Request_destroy
        -:  113:#undef FCNAME
        -:  114:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  115:void MPIDI_CH3_Request_destroy(MPID_Request * req)
 20967117:  116:{
        -:  117:    MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3_REQUEST_DESTROY);
        -:  118:    
        -:  119:    MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3_REQUEST_DESTROY);
        -:  120:    MPIU_DBG_MSG_P(CH3_CHANNEL,VERBOSE,
        -:  121:		   "freeing request, handle=0x%08x", req->handle);
        -:  122:    
        -:  123:#ifdef MPICH_DBG_OUTPUT
        -:  124:    /*MPIU_Assert(HANDLE_GET_MPI_KIND(req->handle) == MPID_REQUEST);*/
        -:  125:    if (HANDLE_GET_MPI_KIND(req->handle) != MPID_REQUEST)
        -:  126:    {
        -:  127:	int mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_FATAL, 
        -:  128:                      FCNAME, __LINE__, MPI_ERR_OTHER, 
        -:  129:                      "**invalid_handle", "**invalid_handle %d", req->handle);
        -:  130:	MPID_Abort(MPIR_Process.comm_world, mpi_errno, -1, NULL);
        -:  131:    }
        -:  132:    /* XXX DJG FIXME should we be checking this? */
        -:  133:    /*MPIU_Assert(req->ref_count == 0);*/
        -:  134:    if (req->ref_count != 0)
        -:  135:    {
        -:  136:	int mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_FATAL,
        -:  137:                       FCNAME, __LINE__, MPI_ERR_OTHER, 
        -:  138:              "**invalid_refcount", "**invalid_refcount %d", req->ref_count);
        -:  139:	MPID_Abort(MPIR_Process.comm_world, mpi_errno, -1, NULL);
        -:  140:    }
        -:  141:#endif
        -:  142:
        -:  143:    /* FIXME: We need a better way to handle these so that we
        -:  144:       do not always need to initialize these fields and check them
        -:  145:       when we destroy a request */
        -:  146:    /* FIXME: We need a way to call these routines ONLY when the 
        -:  147:       related ref count has become zero. */
 20967117:  148:    if (req->comm != NULL) {
 20387127:  149:	MPIR_Comm_release(req->comm, 0);
        -:  150:    }
        -:  151:
 20967117:  152:    if (req->dev.datatype_ptr != NULL) {
   448917:  153:	MPID_Datatype_release(req->dev.datatype_ptr);
        -:  154:    }
        -:  155:
 20967117:  156:    if (req->dev.segment_ptr != NULL) {
   520991:  157:	MPID_Segment_free(req->dev.segment_ptr);
        -:  158:    }
        -:  159:
 20967117:  160:    if (MPIDI_Request_get_srbuf_flag(req)) {
   251345:  161:	MPIDI_CH3U_SRBuf_free(req);
        -:  162:    }
        -:  163:
 20967117:  164:    MPIU_Handle_obj_free(&MPID_Request_mem, req);
        -:  165:    
        -:  166:    MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_CH3_REQUEST_DESTROY);
 20967117:  167:}
        -:  168:
        -:  169:
        -:  170:/* ------------------------------------------------------------------------- */
        -:  171:/* Here are the routines to manipulate the iovs in the requests              */
        -:  172:/* ------------------------------------------------------------------------- */
        -:  173:
        -:  174:
        -:  175:
        -:  176:/*
        -:  177: * MPIDI_CH3U_Request_load_send_iov()
        -:  178: *
        -:  179: * Fill the provided IOV with the next (or remaining) portion of data described
        -:  180: * by the segment contained in the request structure.
        -:  181: * If the density of IOV is not sufficient, pack the data into a send/receive 
        -:  182: * buffer and point the IOV at the buffer.
        -:  183: *
        -:  184: * Expects sreq->dev.OnFinal to be initialized (even if it's NULL).
        -:  185: */
        -:  186:#undef FUNCNAME
        -:  187:#define FUNCNAME MPIDI_CH3U_Request_load_send_iov
        -:  188:#undef FCNAME
        -:  189:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  190:int MPIDI_CH3U_Request_load_send_iov(MPID_Request * const sreq, 
        -:  191:				     MPID_IOV * const iov, int * const iov_n)
   388925:  192:{
        -:  193:    MPI_Aint last;
   388925:  194:    int mpi_errno = MPI_SUCCESS;
        -:  195:    MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3U_REQUEST_LOAD_SEND_IOV);
        -:  196:
        -:  197:    MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3U_REQUEST_LOAD_SEND_IOV);
   388925:  198:    MPIU_Assert(sreq->dev.segment_ptr != NULL);
   388925:  199:    last = sreq->dev.segment_size;
        -:  200:    MPIU_DBG_MSG_FMT(CH3_CHANNEL,VERBOSE,(MPIU_DBG_FDEST,
        -:  201:     "pre-pv: first=" MPIDI_MSG_SZ_FMT ", last=" MPIDI_MSG_SZ_FMT ", iov_n=%d",
        -:  202:		      sreq->dev.segment_first, last, *iov_n));
   388925:  203:    MPIU_Assert(sreq->dev.segment_first < last);
   388925:  204:    MPIU_Assert(last > 0);
   388925:  205:    MPIU_Assert(*iov_n > 0 && *iov_n <= MPID_IOV_LIMIT);
   388925:  206:    MPID_Segment_pack_vector(sreq->dev.segment_ptr, sreq->dev.segment_first, 
        -:  207:			     &last, iov, iov_n);
        -:  208:    MPIU_DBG_MSG_FMT(CH3_CHANNEL,VERBOSE,(MPIU_DBG_FDEST,
        -:  209:    "post-pv: first=" MPIDI_MSG_SZ_FMT ", last=" MPIDI_MSG_SZ_FMT ", iov_n=%d",
        -:  210:		      sreq->dev.segment_first, last, *iov_n));
   388925:  211:    MPIU_Assert(*iov_n > 0 && *iov_n <= MPID_IOV_LIMIT);
        -:  212:    
   388925:  213:    if (last == sreq->dev.segment_size)
        -:  214:    {
        -:  215:	MPIU_DBG_MSG(CH3_CHANNEL,VERBOSE,"remaining data loaded into IOV");
   214759:  216:	sreq->dev.OnDataAvail = sreq->dev.OnFinal;
        -:  217:    }
   174166:  218:    else if ((last - sreq->dev.segment_first) / *iov_n >= MPIDI_IOV_DENSITY_MIN)
        -:  219:    {
        -:  220:	MPIU_DBG_MSG(CH3_CHANNEL,VERBOSE,"more data loaded into IOV");
        2:  221:	sreq->dev.segment_first = last;
        2:  222:	sreq->dev.OnDataAvail = MPIDI_CH3_ReqHandler_SendReloadIOV;
        -:  223:    }
        -:  224:    else
        -:  225:    {
        -:  226:	MPIDI_msg_sz_t data_sz;
        -:  227:	int i, iov_data_copied;
        -:  228:	
        -:  229:	MPIU_DBG_MSG(CH3_CHANNEL,VERBOSE,"low density.  using SRBuf.");
        -:  230:	    
   174164:  231:	data_sz = sreq->dev.segment_size - sreq->dev.segment_first;
   174164:  232:	if (!MPIDI_Request_get_srbuf_flag(sreq))
        -:  233:	{
   173966:  234:	    MPIDI_CH3U_SRBuf_alloc(sreq, data_sz);
        -:  235:	    /* --BEGIN ERROR HANDLING-- */
   173966:  236:	    if (sreq->dev.tmpbuf_sz == 0)
        -:  237:	    {
        -:  238:		MPIU_DBG_MSG(CH3_CHANNEL,TYPICAL,"SRBuf allocation failure");
    #####:  239:		mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_FATAL, 
        -:  240:                                FCNAME, __LINE__, MPI_ERR_OTHER, "**nomem", 0);
    #####:  241:		sreq->status.MPI_ERROR = mpi_errno;
    #####:  242:		goto fn_exit;
        -:  243:	    }
        -:  244:	    /* --END ERROR HANDLING-- */
        -:  245:	}
        -:  246:
   174164:  247:	iov_data_copied = 0;
  2786822:  248:	for (i = 0; i < *iov_n; i++) {
  2612658:  249:	    MPIU_Memcpy((char*) sreq->dev.tmpbuf + iov_data_copied, 
        -:  250:		   iov[i].MPID_IOV_BUF, iov[i].MPID_IOV_LEN);
  2612658:  251:	    iov_data_copied += iov[i].MPID_IOV_LEN;
        -:  252:	}
   174164:  253:	sreq->dev.segment_first = last;
        -:  254:
   174164:  255:	last = (data_sz <= sreq->dev.tmpbuf_sz - iov_data_copied) ? 
        -:  256:	    sreq->dev.segment_size :
        -:  257:	    sreq->dev.segment_first + sreq->dev.tmpbuf_sz - iov_data_copied;
        -:  258:	MPIU_DBG_MSG_FMT(CH3_CHANNEL,VERBOSE,(MPIU_DBG_FDEST,
        -:  259:               "pre-pack: first=" MPIDI_MSG_SZ_FMT ", last=" MPIDI_MSG_SZ_FMT,
        -:  260:			  sreq->dev.segment_first, last));
   174164:  261:	MPID_Segment_pack(sreq->dev.segment_ptr, sreq->dev.segment_first, 
        -:  262:			  &last, (char*) sreq->dev.tmpbuf + iov_data_copied);
        -:  263:	MPIU_DBG_MSG_FMT(CH3_CHANNEL,VERBOSE,(MPIU_DBG_FDEST,
        -:  264:              "post-pack: first=" MPIDI_MSG_SZ_FMT ", last=" MPIDI_MSG_SZ_FMT,
        -:  265:			   sreq->dev.segment_first, last));
   174164:  266:	iov[0].MPID_IOV_BUF = (MPID_IOV_BUF_CAST)sreq->dev.tmpbuf;
   174164:  267:	iov[0].MPID_IOV_LEN = last - sreq->dev.segment_first + iov_data_copied;
   174164:  268:	*iov_n = 1;
   174164:  269:	if (last == sreq->dev.segment_size)
        -:  270:	{
        -:  271:	    MPIU_DBG_MSG(CH3_CHANNEL,VERBOSE,"remaining data packed into SRBuf");
   173966:  272:	    sreq->dev.OnDataAvail = sreq->dev.OnFinal;
        -:  273:	}
        -:  274:	else 
        -:  275:	{
        -:  276:	    MPIU_DBG_MSG(CH3_CHANNEL,VERBOSE,"more data packed into SRBuf");
      198:  277:	    sreq->dev.segment_first = last;
      198:  278:	    sreq->dev.OnDataAvail = MPIDI_CH3_ReqHandler_SendReloadIOV;
        -:  279:	}
        -:  280:    }
        -:  281:    
   388925:  282:  fn_exit:
        -:  283:    MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_CH3U_REQUEST_LOAD_SEND_IOV);
   388925:  284:    return mpi_errno;
        -:  285:}
        -:  286:
        -:  287:/*
        -:  288: * MPIDI_CH3U_Request_load_recv_iov()
        -:  289: *
        -:  290: * Fill the request's IOV with the next (or remaining) portion of data 
        -:  291: * described by the segment (also contained in the request
        -:  292: * structure).  If the density of IOV is not sufficient, allocate a 
        -:  293: * send/receive buffer and point the IOV at the buffer.
        -:  294: */
        -:  295:#undef FUNCNAME
        -:  296:#define FUNCNAME MPIDI_CH3U_Request_load_recv_iov
        -:  297:#undef FCNAME
        -:  298:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  299:int MPIDI_CH3U_Request_load_recv_iov(MPID_Request * const rreq)
   209843:  300:{
        -:  301:    MPI_Aint last;
   209843:  302:    int mpi_errno = MPI_SUCCESS;
        -:  303:    MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3U_REQUEST_LOAD_RECV_IOV);
        -:  304:
        -:  305:    MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3U_REQUEST_LOAD_RECV_IOV);
   209843:  306:    if (rreq->dev.segment_first < rreq->dev.segment_size)
        -:  307:    {
        -:  308:	/* still reading data that needs to go into the user buffer */
        -:  309:	
   209830:  310:	if (MPIDI_Request_get_srbuf_flag(rreq))
        -:  311:	{
        -:  312:	    MPIDI_msg_sz_t data_sz;
        -:  313:	    MPIDI_msg_sz_t tmpbuf_sz;
        -:  314:
        -:  315:	    /* Once a SRBuf is in use, we continue to use it since a small 
        -:  316:	       amount of data may already be present at the beginning
        -:  317:	       of the buffer.  This data is left over from the previous unpack,
        -:  318:	       most like a result of alignment issues.  NOTE: we
        -:  319:	       could force the use of the SRBuf only 
        -:  320:	       when (rreq->dev.tmpbuf_off > 0)... */
        -:  321:	    
    77579:  322:	    data_sz = rreq->dev.segment_size - rreq->dev.segment_first - 
        -:  323:		rreq->dev.tmpbuf_off;
    77579:  324:	    MPIU_Assert(data_sz > 0);
    77579:  325:	    tmpbuf_sz = rreq->dev.tmpbuf_sz - rreq->dev.tmpbuf_off;
    77579:  326:	    if (data_sz > tmpbuf_sz)
        -:  327:	    {
      213:  328:		data_sz = tmpbuf_sz;
        -:  329:	    }
    77579:  330:	    rreq->dev.iov[0].MPID_IOV_BUF = 
        -:  331:		(MPID_IOV_BUF_CAST)((char *) rreq->dev.tmpbuf + 
        -:  332:				    rreq->dev.tmpbuf_off);
    77579:  333:	    rreq->dev.iov[0].MPID_IOV_LEN = data_sz;
    77579:  334:            rreq->dev.iov_offset = 0;
    77579:  335:	    rreq->dev.iov_count = 1;
    77579:  336:	    MPIU_Assert(rreq->dev.segment_first + data_sz + 
        -:  337:			rreq->dev.tmpbuf_off <= rreq->dev.recv_data_sz);
    77579:  338:	    if (rreq->dev.segment_first + data_sz + rreq->dev.tmpbuf_off == 
        -:  339:		rreq->dev.recv_data_sz)
        -:  340:	    {
        -:  341:		MPIU_DBG_MSG(CH3_CHANNEL,VERBOSE,
        -:  342:		  "updating rreq to read the remaining data into the SRBuf");
    77366:  343:		rreq->dev.OnDataAvail = MPIDI_CH3_ReqHandler_UnpackSRBufComplete;
        -:  344:	    }
        -:  345:	    else
        -:  346:	    {
        -:  347:		MPIU_DBG_MSG(CH3_CHANNEL,VERBOSE,
        -:  348:		       "updating rreq to read more data into the SRBuf");
      213:  349:		rreq->dev.OnDataAvail = MPIDI_CH3_ReqHandler_UnpackSRBufReloadIOV;
        -:  350:	    }
        -:  351:	    goto fn_exit;
        -:  352:	}
        -:  353:	
   132251:  354:	last = rreq->dev.segment_size;
   132251:  355:	rreq->dev.iov_count = MPID_IOV_LIMIT;
   132251:  356:	rreq->dev.iov_offset = 0;
        -:  357:	MPIU_DBG_MSG_FMT(CH3_CHANNEL,VERBOSE,(MPIU_DBG_FDEST,
        -:  358:   "pre-upv: first=" MPIDI_MSG_SZ_FMT ", last=" MPIDI_MSG_SZ_FMT ", iov_n=%d",
        -:  359:			  rreq->dev.segment_first, last, rreq->dev.iov_count));
   132251:  360:	MPIU_Assert(rreq->dev.segment_first < last);
   132251:  361:	MPIU_Assert(last > 0);
   132251:  362:	MPID_Segment_unpack_vector(rreq->dev.segment_ptr, 
        -:  363:				   rreq->dev.segment_first,
        -:  364:				   &last, &rreq->dev.iov[0], &rreq->dev.iov_count);
        -:  365:	MPIU_DBG_MSG_FMT(CH3_CHANNEL,VERBOSE,(MPIU_DBG_FDEST,
        -:  366:   "post-upv: first=" MPIDI_MSG_SZ_FMT ", last=" MPIDI_MSG_SZ_FMT ", iov_n=%d, iov_offset=%d",
        -:  367:			  rreq->dev.segment_first, last, rreq->dev.iov_count, rreq->dev.iov_offset));
   132251:  368:	MPIU_Assert(rreq->dev.iov_count >= 0 && rreq->dev.iov_count <= 
        -:  369:		    MPID_IOV_LIMIT);
        -:  370:
        -:  371:	/* --BEGIN ERROR HANDLING-- */
   132251:  372:	if (rreq->dev.iov_count == 0)
        -:  373:	{
        -:  374:	    /* If the data can't be unpacked, the we have a mis-match between
        -:  375:	       the datatype and the amount of data received.  Adjust
        -:  376:	       the segment info so that the remaining data is received and 
        -:  377:	       thrown away. */
        1:  378:	    rreq->status.MPI_ERROR = MPIR_Err_create_code(MPI_SUCCESS, 
        -:  379:		       MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_TYPE,
        -:  380:		       "**dtypemismatch", 0);
        1:  381:	    rreq->status.count = (int)rreq->dev.segment_first;
        1:  382:	    rreq->dev.segment_size = rreq->dev.segment_first;
        1:  383:	    mpi_errno = MPIDI_CH3U_Request_load_recv_iov(rreq);
        1:  384:	    goto fn_exit;
        -:  385:	}
        -:  386:        else
        -:  387:        {
   132250:  388:            MPIU_Assert(rreq->dev.iov_offset < rreq->dev.iov_count);
        -:  389:        }
        -:  390:	/* --END ERROR HANDLING-- */
        -:  391:
   132250:  392:	if (last == rreq->dev.recv_data_sz)
        -:  393:	{
        -:  394:	    MPIU_DBG_MSG(CH3_CHANNEL,VERBOSE,
        -:  395:     "updating rreq to read the remaining data directly into the user buffer");
        -:  396:	    /* Eventually, use OnFinal for this instead */
    54871:  397:	    rreq->dev.OnDataAvail = 0;
        -:  398:	}
    77392:  399:	else if (last == rreq->dev.segment_size || 
        -:  400:		 (last - rreq->dev.segment_first) / rreq->dev.iov_count >= MPIDI_IOV_DENSITY_MIN)
        -:  401:	{
        -:  402:	    MPIU_DBG_MSG(CH3_CHANNEL,VERBOSE,
        -:  403:	     "updating rreq to read more data directly into the user buffer");
       13:  404:	    rreq->dev.segment_first = last;
       13:  405:	    rreq->dev.OnDataAvail = MPIDI_CH3_ReqHandler_ReloadIOV;
        -:  406:	}
        -:  407:	else
        -:  408:	{
        -:  409:	    /* Too little data would have been received using an IOV.  
        -:  410:	       We will start receiving data into a SRBuf and unpacking it
        -:  411:	       later. */
    77366:  412:	    MPIU_Assert(MPIDI_Request_get_srbuf_flag(rreq) == FALSE);
        -:  413:	    
    77366:  414:	    MPIDI_CH3U_SRBuf_alloc(rreq, 
        -:  415:			    rreq->dev.segment_size - rreq->dev.segment_first);
    77366:  416:	    rreq->dev.tmpbuf_off = 0;
        -:  417:	    /* --BEGIN ERROR HANDLING-- */
    77366:  418:	    if (rreq->dev.tmpbuf_sz == 0)
        -:  419:	    {
        -:  420:		/* FIXME - we should drain the data off the pipe here, but we 
        -:  421:		   don't have a buffer to drain it into.  should this be
        -:  422:		   a fatal error? */
        -:  423:		MPIU_DBG_MSG(CH3_CHANNEL,VERBOSE,"SRBuf allocation failure");
    #####:  424:		mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_FATAL, 
        -:  425:			      FCNAME, __LINE__, MPI_ERR_OTHER, "**nomem", 0);
    #####:  426:		rreq->status.MPI_ERROR = mpi_errno;
    #####:  427:		goto fn_exit;
        -:  428:	    }
        -:  429:	    /* --END ERROR HANDLING-- */
        -:  430:
        -:  431:	    /* fill in the IOV using a recursive call */
    77366:  432:	    mpi_errno = MPIDI_CH3U_Request_load_recv_iov(rreq);
        -:  433:	}
        -:  434:    }
        -:  435:    else
        -:  436:    {
        -:  437:	/* receive and toss any extra data that does not fit in the user's 
        -:  438:	   buffer */
        -:  439:	MPIDI_msg_sz_t data_sz;
        -:  440:
       13:  441:	data_sz = rreq->dev.recv_data_sz - rreq->dev.segment_first;
       13:  442:	if (!MPIDI_Request_get_srbuf_flag(rreq))
        -:  443:	{
       13:  444:	    MPIDI_CH3U_SRBuf_alloc(rreq, data_sz);
        -:  445:	    /* --BEGIN ERROR HANDLING-- */
       13:  446:	    if (rreq->dev.tmpbuf_sz == 0)
        -:  447:	    {
        -:  448:		MPIU_DBG_MSG(CH3_CHANNEL,TYPICAL,"SRBuf allocation failure");
    #####:  449:		mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_FATAL, 
        -:  450:			       FCNAME, __LINE__, MPI_ERR_OTHER, "**nomem", 0);
    #####:  451:		rreq->status.MPI_ERROR = mpi_errno;
    #####:  452:		goto fn_exit;
        -:  453:	    }
        -:  454:	    /* --END ERROR HANDLING-- */
        -:  455:	}
        -:  456:
       13:  457:	if (data_sz <= rreq->dev.tmpbuf_sz)
        -:  458:	{
        -:  459:	    MPIU_DBG_MSG(CH3_CHANNEL,VERBOSE,
        -:  460:	    "updating rreq to read overflow data into the SRBuf and complete");
       13:  461:	    rreq->dev.iov[0].MPID_IOV_LEN = data_sz;
       13:  462:	    MPIU_Assert(MPIDI_Request_get_type(rreq) == MPIDI_REQUEST_TYPE_RECV);
        -:  463:	    /* Eventually, use OnFinal for this instead */
       13:  464:	    rreq->dev.OnDataAvail = 0;
        -:  465:	}
        -:  466:	else
        -:  467:	{
        -:  468:	    MPIU_DBG_MSG(CH3_CHANNEL,VERBOSE,
        -:  469:	  "updating rreq to read overflow data into the SRBuf and reload IOV");
    #####:  470:	    rreq->dev.iov[0].MPID_IOV_LEN = rreq->dev.tmpbuf_sz;
    #####:  471:	    rreq->dev.segment_first += rreq->dev.tmpbuf_sz;
    #####:  472:	    rreq->dev.OnDataAvail = MPIDI_CH3_ReqHandler_ReloadIOV;
        -:  473:	}
        -:  474:	
       13:  475:	rreq->dev.iov[0].MPID_IOV_BUF = (MPID_IOV_BUF_CAST)rreq->dev.tmpbuf;
       13:  476:	rreq->dev.iov_count = 1;
        -:  477:    }
        -:  478:    
   209843:  479:  fn_exit:
        -:  480:    MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_CH3U_REQUEST_LOAD_RECV_IOV);
   209843:  481:    return mpi_errno;
        -:  482:}
        -:  483:
        -:  484:/*
        -:  485: * MPIDI_CH3U_Request_unpack_srbuf
        -:  486: *
        -:  487: * Unpack data from a send/receive buffer into the user buffer.
        -:  488: */
        -:  489:#undef FUNCNAME
        -:  490:#define FUNCNAME MPIDI_CH3U_Request_unpack_srbuf
        -:  491:#undef FCNAME
        -:  492:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  493:int MPIDI_CH3U_Request_unpack_srbuf(MPID_Request * rreq)
    77579:  494:{
        -:  495:    MPI_Aint last;
        -:  496:    int tmpbuf_last;
    77579:  497:    int mpi_errno = MPI_SUCCESS;
        -:  498:    MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3U_REQUEST_UNPACK_SRBUF);
        -:  499:    
        -:  500:    MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3U_REQUEST_UNPACK_SRBUF);
        -:  501:
    77579:  502:    tmpbuf_last = (int)(rreq->dev.segment_first + rreq->dev.tmpbuf_sz);
    77579:  503:    if (rreq->dev.segment_size < tmpbuf_last)
        -:  504:    {
    77202:  505:	tmpbuf_last = (int)rreq->dev.segment_size;
        -:  506:    }
    77579:  507:    last = tmpbuf_last;
    77579:  508:    MPID_Segment_unpack(rreq->dev.segment_ptr, rreq->dev.segment_first, 
        -:  509:			&last, rreq->dev.tmpbuf);
    77579:  510:    if (last == 0 || last == rreq->dev.segment_first)
        -:  511:    {
        -:  512:	/* --BEGIN ERROR HANDLING-- */
        -:  513:	/* If no data can be unpacked, then we have a datatype processing 
        -:  514:	   problem.  Adjust the segment info so that the remaining
        -:  515:	   data is received and thrown away. */
    #####:  516:	rreq->status.count = (int)rreq->dev.segment_first;
    #####:  517:	rreq->dev.segment_size = rreq->dev.segment_first;
    #####:  518:	rreq->dev.segment_first += tmpbuf_last;
    #####:  519:	rreq->status.MPI_ERROR = MPIR_Err_create_code(MPI_SUCCESS, 
        -:  520:		       MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_TYPE,
        -:  521:		       "**dtypemismatch", 0);
        -:  522:	/* --END ERROR HANDLING-- */
        -:  523:    }
    77579:  524:    else if (tmpbuf_last == rreq->dev.segment_size)
        -:  525:    {
        -:  526:	/* --BEGIN ERROR HANDLING-- */
    77366:  527:	if (last != tmpbuf_last)
        -:  528:	{
        -:  529:	    /* received data was not entirely consumed by unpack() because too
        -:  530:	       few bytes remained to fill the next basic datatype.
        -:  531:	       Note: the segment_first field is set to segment_last so that if
        -:  532:	       this is a truncated message, extra data will be read
        -:  533:	       off the pipe. */
    #####:  534:	    rreq->status.count = (int)last;
    #####:  535:	    rreq->dev.segment_size = last;
    #####:  536:	    rreq->dev.segment_first = tmpbuf_last;
    #####:  537:	    rreq->status.MPI_ERROR = MPIR_Err_create_code(MPI_SUCCESS, 
        -:  538:		  MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_TYPE,
        -:  539:							  "**dtypemismatch", 0);
        -:  540:	}
        -:  541:	/* --END ERROR HANDLING-- */
        -:  542:    }
        -:  543:    else
        -:  544:    {
      213:  545:	rreq->dev.tmpbuf_off = (int)(tmpbuf_last - last);
      213:  546:	if (rreq->dev.tmpbuf_off > 0)
        -:  547:	{
        -:  548:	    /* move any remaining data to the beginning of the buffer.  
        -:  549:	       Note: memmove() is used since the data regions could
        -:  550:               overlap. */
    #####:  551:	    memmove(rreq->dev.tmpbuf, (char *) rreq->dev.tmpbuf + 
        -:  552:		    (last - rreq->dev.segment_first), rreq->dev.tmpbuf_off);
        -:  553:	}
      213:  554:	rreq->dev.segment_first = last;
        -:  555:    }
        -:  556:
        -:  557:    MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_CH3U_REQUEST_UNPACK_SRBUF);
    77579:  558:    return mpi_errno;
        -:  559:}
        -:  560:
        -:  561:/*
        -:  562: * MPIDI_CH3U_Request_unpack_uebuf
        -:  563: *
        -:  564: * Copy/unpack data from an "unexpected eager buffer" into the user buffer.
        -:  565: */
        -:  566:#undef FUNCNAME
        -:  567:#define FUNCNAME MPIDI_CH3U_Request_unpack_uebuf
        -:  568:#undef FCNAME
        -:  569:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  570:int MPIDI_CH3U_Request_unpack_uebuf(MPID_Request * rreq)
  1119858:  571:{
        -:  572:    int dt_contig;
        -:  573:    MPI_Aint dt_true_lb;
        -:  574:    MPIDI_msg_sz_t userbuf_sz;
        -:  575:    MPID_Datatype * dt_ptr;
        -:  576:    MPIDI_msg_sz_t unpack_sz;
  1119858:  577:    int mpi_errno = MPI_SUCCESS;
        -:  578:    MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3U_REQUEST_UNPACK_UEBUF);
        -:  579:    MPIDI_STATE_DECL(MPID_STATE_MEMCPY);
        -:  580:
        -:  581:    MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3U_REQUEST_UNPACK_UEBUF);
        -:  582:
  1119858:  583:    MPIDI_Datatype_get_info(rreq->dev.user_count, rreq->dev.datatype, 
        -:  584:			    dt_contig, userbuf_sz, dt_ptr, dt_true_lb);
        -:  585:    
  1119858:  586:    if (rreq->dev.recv_data_sz <= userbuf_sz)
        -:  587:    {
  1119857:  588:	unpack_sz = rreq->dev.recv_data_sz;
        -:  589:    }
        -:  590:    else
        -:  591:    {
        -:  592:	/* --BEGIN ERROR HANDLING-- */
        -:  593:	MPIU_DBG_MSG_FMT(CH3_CHANNEL,VERBOSE,(MPIU_DBG_FDEST,
        -:  594:      "receive buffer overflow; message truncated, msg_sz=" MPIDI_MSG_SZ_FMT 
        -:  595:	      ", buf_sz=" MPIDI_MSG_SZ_FMT, 
        -:  596:                rreq->dev.recv_data_sz, userbuf_sz));
        1:  597:	unpack_sz = userbuf_sz;
        1:  598:	rreq->status.count = (int)userbuf_sz;
        1:  599:	rreq->status.MPI_ERROR = MPIR_Err_create_code(MPI_SUCCESS, 
        -:  600:		 MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_TRUNCATE,
        -:  601:		 "**truncate", "**truncate %d %d", 
        -:  602:                 rreq->dev.recv_data_sz, userbuf_sz);
        -:  603:	/* --END ERROR HANDLING-- */
        -:  604:    }
        -:  605:
  1119858:  606:    if (unpack_sz > 0)
        -:  607:    {
  1119858:  608:	if (dt_contig)
        -:  609:	{
        -:  610:	    /* TODO - check that amount of data is consistent with datatype.  
        -:  611:	       In other words, if we were to use Segment_unpack()
        -:  612:	       would last = unpack?  If not we should return an error 
        -:  613:	       (unless configured with --enable-fast) */
        -:  614:	    MPIDI_FUNC_ENTER(MPID_STATE_MEMCPY);
  1119325:  615:	    MPIU_Memcpy((char *)rreq->dev.user_buf + dt_true_lb, rreq->dev.tmpbuf,
        -:  616:		   unpack_sz);
        -:  617:	    MPIDI_FUNC_EXIT(MPID_STATE_MEMCPY);
        -:  618:	}
        -:  619:	else
        -:  620:	{
        -:  621:	    MPID_Segment seg;
        -:  622:	    MPI_Aint last;
        -:  623:
      533:  624:	    MPID_Segment_init(rreq->dev.user_buf, rreq->dev.user_count, 
        -:  625:			      rreq->dev.datatype, &seg, 0);
      533:  626:	    last = unpack_sz;
      533:  627:	    MPID_Segment_unpack(&seg, 0, &last, rreq->dev.tmpbuf);
      533:  628:	    if (last != unpack_sz)
        -:  629:	    {
        -:  630:		/* --BEGIN ERROR HANDLING-- */
        -:  631:		/* received data was not entirely consumed by unpack() 
        -:  632:		   because too few bytes remained to fill the next basic
        -:  633:		   datatype */
    #####:  634:		rreq->status.count = (int)last;
    #####:  635:		rreq->status.MPI_ERROR = MPIR_Err_create_code(MPI_SUCCESS, 
        -:  636:                         MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_TYPE,
        -:  637:			 "**dtypemismatch", 0);
        -:  638:		/* --END ERROR HANDLING-- */
        -:  639:	    }
        -:  640:	}
        -:  641:    }
        -:  642:
        -:  643:    MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_CH3U_REQUEST_UNPACK_UEBUF);
  1119858:  644:    return mpi_errno;
        -:  645:}
        -:  646:
        -:  647:/* 
        -:  648: * Export the function to set a request as completed for use by
        -:  649: * the generalized request functions in mpich2/src/pt2pt/greq_complete.c
        -:  650: */
        -:  651:void MPID_Request_set_completed( MPID_Request *req )
   532445:  652:{
   532445:  653:    MPID_REQUEST_SET_COMPLETED(req);
   532445:  654:}