-:    0:Source:/home/MPI/testing/mpich2/mpich2/src/mpi/pt2pt/bsendutil.c
        -:    0:Graph:bsendutil.gcno
        -:    0:Data:bsendutil.gcda
        -:    0:Runs:856
        -:    0:Programs:280
        -:    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 "mpiimpl.h"
        -:    8:#include "mpibsend.h"
        -:    9:#include "bsendutil.h"
        -:   10:
        -:   11:/*
        -:   12: * Miscellaneous comments
        -:   13: * By storing total_size along with "size available for messages", we
        -:   14: * avoid any complexities associated with alignment, since we must
        -:   15: * ensure that each KPIR_Bsend_data_t structure is properly aligned
        -:   16: * (i.e., we can't simply do (sizeof(MPIR_Bsend_data_t) + size) to get
        -:   17: * total_size).
        -:   18: *
        -:   19: * Function Summary
        -:   20: *   MPIR_Bsend_attach - Performs the work of MPI_Buffer_attach
        -:   21: *   MPIR_Bsend_detach - Performs the work of MPI_Buffer_detach
        -:   22: *   MPIR_Bsend_isend  - Essentially performs an MPI_Ibsend.  Returns
        -:   23: *                an MPID_Request that is also stored internally in the
        -:   24: *                corresponding MPIR_Bsend_data_t entry
        -:   25: *   MPIR_Bsend_free_segment - Free a buffer that is no longer needed,
        -:   26: *                merging with adjacent segments
        -:   27: *   MPIR_Bsend_check_active - Check for completion of any pending sends
        -:   28: *                for bsends (all bsends, both MPI_Ibsend and MPI_Bsend,
        -:   29: *                are internally converted into Isends on the data
        -:   30: *                in the Bsend buffer)
        -:   31: *   MPIR_Bsend_retry_pending - Routine for future use to handle the
        -:   32: *                case where an Isend cannot be initiated.
        -:   33: *   MPIR_Bsend_find_buffer - Find a buffer in the bsend buffer large 
        -:   34: *                enough for the message.  However, does not acquire that
        -:   35: *                buffer (see MPIR_Bsend_take_buffer)
        -:   36: *   MPIR_Bsend_take_buffer - Find and acquire a buffer for a message
        -:   37: *   MPIR_Bsend_finalize - Finalize handler when Bsend routines are used 
        -:   38: *   MPIR_Bsend_dump - Debugging routine to print the contents of the control
        -:   39: *                information in the bsend buffer (the MPIR_Bsend_data_t entries)
        -:   40: */
        -:   41:
        -:   42:#ifdef USE_DBG_LOGGING
        -:   43:static void MPIR_Bsend_dump( void );
        -:   44:#endif
        -:   45:
        -:   46:#define BSENDDATA_HEADER_TRUE_SIZE (sizeof(MPIR_Bsend_data_t) - sizeof(double))
        -:   47:
        -:   48:/* BsendBuffer is the structure that describes the overall Bsend buffer */
        -:   49:/* 
        -:   50: * We use separate buffer and origbuffer because we may need to align
        -:   51: * the buffer (we *could* always memcopy the header to an aligned region,
        -:   52: * but it is simpler to just align it internally.  This does increase the
        -:   53: * BSEND_OVERHEAD, but that is already relatively large.  We could instead
        -:   54: * make sure that the initial header was set at an aligned location (
        -:   55: * taking advantage of the "alignpad"), but this would require more changes.
        -:   56: */
        -:   57:static struct BsendBuffer {
        -:   58:    void               *buffer;        /* Pointer to the begining of the user-
        -:   59:					  provided buffer */
        -:   60:    int                buffer_size;    /* Size of the user-provided buffer */
        -:   61:    void               *origbuffer;    /* Pointer to the buffer provided by
        -:   62:					  the user */
        -:   63:    int                origbuffer_size; /* Size of the buffer as provided 
        -:   64:					    by the user */
        -:   65:    MPIR_Bsend_data_t  *avail;         /* Pointer to the first available block
        -:   66:					  of space */
        -:   67:    MPIR_Bsend_data_t  *pending;       /* Pointer to the first message that
        -:   68:					  could not be sent because of a 
        -:   69:					  resource limit (e.g., no requests
        -:   70:					  available) */
        -:   71:    MPIR_Bsend_data_t  *active;        /* Pointer to the first active (sending)
        -:   72:					  message */
        -:   73:} BsendBuffer = { 0, 0, 0, 0, 0, 0, 0 };
        -:   74:
        -:   75:static int initialized = 0;   /* keep track of the first call to any
        -:   76:				 bsend routine */
        -:   77:
        -:   78:/* Forward references */
        -:   79:static void MPIR_Bsend_retry_pending( void );
        -:   80:static void MPIR_Bsend_check_active ( void );
        -:   81:static MPIR_Bsend_data_t *MPIR_Bsend_find_buffer( int );
        -:   82:static void MPIR_Bsend_take_buffer( MPIR_Bsend_data_t *, int );
        -:   83:static int MPIR_Bsend_finalize( void * );
        -:   84:
        -:   85:/*
        -:   86: * Attach a buffer.  This checks for the error conditions and then
        -:   87: * initialized the avail buffer.
        -:   88: */    
        -:   89:#undef FUNCNAME
        -:   90:#define FUNCNAME MPIR_Bsend_attach
        -:   91:#undef FCNAME
        -:   92:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:   93:int MPIR_Bsend_attach( void *buffer, int buffer_size )
    45987:   94:{
        -:   95:    MPIR_Bsend_data_t *p;
        -:   96:    long        offset;
        -:   97:
        -:   98:#   ifdef HAVE_ERROR_CHECKING
        -:   99:    {
        -:  100:        MPID_BEGIN_ERROR_CHECKS;
        -:  101:        {
    45987:  102:	    if (BsendBuffer.buffer) {
        2:  103:		return MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE,
        -:  104:                         "MPIR_Bsend_attach", __LINE__, MPI_ERR_BUFFER, 
        -:  105:					     "**bufexists", 0 );
        -:  106:	    }
    45985:  107:	    if (buffer_size < MPI_BSEND_OVERHEAD) {
        -:  108:		/* MPI_ERR_OTHER is another valid choice for this error,
        -:  109:		 but the Intel test wants MPI_ERR_BUFFER, and it seems
        -:  110:		 to violate the principle of least surprise to not use
        -:  111:		 MPI_ERR_BUFFER for errors with the Buffer */
    #####:  112:		return MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE,
        -:  113:		    "MPIR_Bsend_attach", __LINE__, MPI_ERR_BUFFER, 
        -:  114:		    "**bsendbufsmall", 
        -:  115:                    "**bsendbufsmall %d %d", buffer_size, MPI_BSEND_OVERHEAD );
        -:  116:	    }
        -:  117:	}
        -:  118:	MPID_END_ERROR_CHECKS;
        -:  119:    }
        -:  120:#   endif /* HAVE_ERROR_CHECKING */
        -:  121:
    45985:  122:    if (!initialized) {
      168:  123:	initialized = 1;
      168:  124:	MPIR_Add_finalize( MPIR_Bsend_finalize, (void *)0, 10 );
        -:  125:    }
        -:  126:
    45985:  127:    BsendBuffer.origbuffer	= buffer;
    45985:  128:    BsendBuffer.origbuffer_size	= buffer_size;
    45985:  129:    BsendBuffer.buffer		= buffer;
    45985:  130:    BsendBuffer.buffer_size	= buffer_size;
    45985:  131:    offset = ((long)buffer) % sizeof(void *);
    45985:  132:    if (offset) {
        -:  133:	/* Make sure that the buffer that we use is aligned for pointers,
        -:  134:	   because the code assumes that */
       10:  135:	offset = sizeof(void *) - offset;
       10:  136:	buffer = (char *)buffer + offset;
       10:  137:	BsendBuffer.buffer      = buffer;
       10:  138:	BsendBuffer.buffer_size -= offset;
        -:  139:    }
    45985:  140:    BsendBuffer.avail		= buffer;
    45985:  141:    BsendBuffer.pending		= 0;
    45985:  142:    BsendBuffer.active		= 0;
        -:  143:
        -:  144:    /* Set the first block */
    45985:  145:    p		  = (MPIR_Bsend_data_t *)buffer;
    45985:  146:    p->size	  = buffer_size - BSENDDATA_HEADER_TRUE_SIZE;
    45985:  147:    p->total_size = buffer_size;
    45985:  148:    p->next	  = p->prev = 0;
    45985:  149:    p->msg.msgbuf = (char *)p + BSENDDATA_HEADER_TRUE_SIZE;
        -:  150:
    45985:  151:    return MPI_SUCCESS;
        -:  152:}
        -:  153:
        -:  154:/* 
        -:  155: * Detach a buffer.  This routine must wait until any pending bsends 
        -:  156: * are complete.
        -:  157: */
        -:  158:#undef FUNCNAME
        -:  159:#define FUNCNAME MPIR_Bsend_detach
        -:  160:#undef FCNAME
        -:  161:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  162:int MPIR_Bsend_detach( void *bufferp, int *size )
    45995:  163:{
    45995:  164:    if (BsendBuffer.pending) {
        -:  165:	/* FIXME: This is the wrong error text (notimpl) */
    #####:  166:	return MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, 
        -:  167:             "MPIR_Bsend_detach", __LINE__, MPI_ERR_OTHER, "**notimpl", 0 );
        -:  168:    }
    45995:  169:    if (BsendBuffer.active) {
        -:  170:	/* Loop through each active element and wait on it */
    45897:  171:	MPIR_Bsend_data_t *p = BsendBuffer.active;
    45897:  172:	MPIU_THREADPRIV_DECL;
        -:  173:	
    45897:  174:	MPIU_THREADPRIV_GET;
        -:  175:
    45897:  176:	MPIR_Nest_incr();
   154658:  177:	while (p) {
    62864:  178:	    MPI_Request r = p->request->handle;
    62864:  179:	    NMPI_Wait( &r, MPI_STATUS_IGNORE );
    62864:  180:	    p = p->next;
        -:  181:	}
    45897:  182:	MPIR_Nest_decr();
        -:  183:    }
        -:  184:
        -:  185:/* Note that this works even when the buffer does not exist */
    45995:  186:    *(void **) bufferp  = BsendBuffer.origbuffer;
    45995:  187:    *size = BsendBuffer.origbuffer_size;
    45995:  188:    BsendBuffer.origbuffer = NULL;
    45995:  189:    BsendBuffer.origbuffer_size = 0;
    45995:  190:    BsendBuffer.buffer  = 0;
    45995:  191:    BsendBuffer.buffer_size  = 0;
    45995:  192:    BsendBuffer.avail   = 0;
    45995:  193:    BsendBuffer.active  = 0;
    45995:  194:    BsendBuffer.pending = 0;
        -:  195:
    45995:  196:    return MPI_SUCCESS;
        -:  197:}
        -:  198:
        -:  199:/*
        -:  200: * Initiate an ibsend.  We'll used this for Bsend as well.
        -:  201: */
        -:  202:#undef FUNCNAME
        -:  203:#define FUNCNAME MPIR_Bsend_isend
        -:  204:#undef FCNAME
        -:  205:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  206:int MPIR_Bsend_isend( void *buf, int count, MPI_Datatype dtype, 
        -:  207:		      int dest, int tag, MPID_Comm *comm_ptr, 
        -:  208:		      MPIR_Bsend_kind_t kind, MPID_Request **request )
   193584:  209:{
        -:  210:    MPIR_Bsend_data_t *p;
        -:  211:    MPIR_Bsend_msg_t *msg;
        -:  212:    int packsize, mpi_errno, pass;
   193584:  213:    MPIU_THREADPRIV_DECL;
        -:  214:
        -:  215:    /* Find a free segment and copy the data into it.  If we could 
        -:  216:       have, we would already have used tBsend to send the message with
        -:  217:       no copying.
        -:  218:
        -:  219:       We may want to decide here whether we need to pack at all 
        -:  220:       or if we can just use (a MPIU_Memcpy) of the buffer.
        -:  221:    */
        -:  222:
   193584:  223:    MPIU_THREADPRIV_GET;
   193584:  224:    MPIR_Nest_incr();
        -:  225:
        -:  226:    /* We check the active buffer first.  This helps avoid storage 
        -:  227:       fragmentation */
   193584:  228:    MPIR_Bsend_check_active();
        -:  229:
   193584:  230:    if (dtype != MPI_PACKED)
        -:  231:    {
   193584:  232:        (void)NMPI_Pack_size( count, dtype, comm_ptr->handle, &packsize );
        -:  233:    }
        -:  234:    else
        -:  235:    {
    #####:  236:        packsize = count;
        -:  237:    }
        -:  238:
        -:  239:    MPIU_DBG_MSG_D(BSEND,TYPICAL,"looking for buffer of size %d", packsize);
        -:  240:    /*
        -:  241:     * Use two passes.  Each pass is the same; between the two passes,
        -:  242:     * attempt to complete any active requests, and start any pending
        -:  243:     * ones.  If the message can be initiated in the first pass,
        -:  244:     * do not perform the second pass.
        -:  245:     */
   199401:  246:    for (pass = 0; pass < 2; pass++) {
        -:  247:	
   199401:  248:	p = MPIR_Bsend_find_buffer( packsize );
   199401:  249:	if (p) {
        -:  250:	    MPIU_DBG_MSG_FMT(BSEND,TYPICAL,(MPIU_DBG_FDEST,
        -:  251:                     "found buffer of size %d with address %p",packsize,p));
        -:  252:	    /* Found a segment */
        -:  253:
   187778:  254:	    msg = &p->msg;
        -:  255:	    
        -:  256:	    /* Pack the data into the buffer */
        -:  257:	    /* We may want to optimize for the special case of
        -:  258:	       either primative or contiguous types, and just
        -:  259:	       use MPIU_Memcpy and the provided datatype */
   187778:  260:	    msg->count = 0;
   187778:  261:            if (dtype != MPI_PACKED)
        -:  262:            {
   187778:  263:                (void)NMPI_Pack( buf, count, dtype, p->msg.msgbuf, packsize, 
        -:  264:                                 &p->msg.count, comm_ptr->handle );
        -:  265:            }
        -:  266:            else
        -:  267:            {
    #####:  268:                MPIU_Memcpy(p->msg.msgbuf, buf, count);
    #####:  269:                p->msg.count = count;
        -:  270:            }
        -:  271:	    /* Try to send the message.  We must use MPID_Isend
        -:  272:	       because this call must not block */
   187778:  273:	    mpi_errno = MPID_Isend(msg->msgbuf, msg->count, MPI_PACKED, 
        -:  274:				   dest, tag, comm_ptr,
        -:  275:				   MPID_CONTEXT_INTRA_PT2PT, &p->request );
   187778:  276:	    if (p->request) {
        -:  277:		MPIU_DBG_MSG_FMT(BSEND,TYPICAL,
        -:  278:		    (MPIU_DBG_FDEST,"saving request %p in %p",p->request,p));
        -:  279:		/* An optimization is to check to see if the 
        -:  280:		   data has already been sent.  The original code
        -:  281:		   to do this was commented out and probably did not match
        -:  282:		   the current request internals */
   187778:  283:		MPIR_Bsend_take_buffer( p, p->msg.count );
   187778:  284:		p->kind  = kind;
   187778:  285:		*request = p->request;
        -:  286:	    }
        -:  287:	    else {
        -:  288:		/* --BEGIN ERROR HANDLING-- */
    #####:  289:		if (mpi_errno) {
    #####:  290:		    MPIU_Internal_error_printf ("Bsend internal error: isend returned err = %d", mpi_errno );
        -:  291:		}
        -:  292:		/* --END ERROR HANDLING-- */
        -:  293:		/* If the error is "request not available", we should 
        -:  294:		   put this on the pending list.  This will depend on
        -:  295:		   how we signal failure to send. */
        -:  296:	    }
        -:  297:	    break;
        -:  298:	}
        -:  299:	/* If we found a buffer or we're in the seccond pass, then break.
        -:  300:	    Note that the test on phere is redundant, as the code breaks 
        -:  301:	    out of the loop in the test above if a block p is found. */
    11623:  302:	if (p || pass == 1) break;
        -:  303:	MPIU_DBG_MSG(BSEND,TYPICAL,"Could not find storage, checking active");
        -:  304:	/* Try to complete some pending bsends */
     5817:  305:	MPIR_Bsend_check_active( );
        -:  306:	/* Give priority to any pending operations */
     5817:  307:	MPIR_Bsend_retry_pending( );
        -:  308:    }
   193584:  309:    MPIR_Nest_decr();
        -:  310:    
   193584:  311:    if (!p) {
        -:  312:	/* Return error for no buffer space found */
        -:  313:	/* Generate a traceback of the allocated space, explaining why
        -:  314:	   packsize could not be found */
        -:  315:	MPIU_DBG_MSG(BSEND,TYPICAL,"Could not find space; dumping arena" );
        -:  316:	MPIU_DBG_STMT(BSEND,TYPICAL,MPIR_Bsend_dump());
        -:  317:
     5806:  318:	return MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, "MPIR_Bsend_isend", __LINE__, MPI_ERR_BUFFER, "**bufbsend", 
        -:  319:				     "**bufbsend %d %d", packsize, 
        -:  320:				     BsendBuffer.buffer_size );
        -:  321:    }
        -:  322:    else {
   187778:  323:	return MPI_SUCCESS;
        -:  324:    }
        -:  325:}
        -:  326:
        -:  327:/*
        -:  328: * The following routines are used to manage the allocation of bsend segments
        -:  329: * in the user buffer.  These routines handle, for example, merging segments
        -:  330: * when an active segment that is adjacent to a free segment becomes free.
        -:  331: *
        -:  332: */
        -:  333:
        -:  334:/* Add block p to the free list. Merge into adjacent blocks.  Used only 
        -:  335:   within the check_active */
        -:  336:/* begin:nested */
        -:  337:#undef FUNCNAME
        -:  338:#define FUNCNAME MPIR_Bsend_free_segment
        -:  339:#undef FCNAME
        -:  340:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  341:static void MPIR_Bsend_free_segment( MPIR_Bsend_data_t *p )
   124914:  342:{
   124914:  343:    MPIR_Bsend_data_t *prev = p->prev, *avail = BsendBuffer.avail, *avail_prev;
        -:  344:
        -:  345:    MPIU_DBG_MSG_FMT(BSEND,TYPICAL,(MPIU_DBG_FDEST,
        -:  346:                 "Freeing bsend segment at %p of size %d, next at %p",
        -:  347:		 p,p->size, ((char *)p)+p->total_size));
        -:  348:
        -:  349:    MPIU_DBG_MSG_D(BSEND,TYPICAL,
        -:  350:	     "At the begining of free_segment with size %d:", p->total_size );
        -:  351:    MPIU_DBG_STMT(BSEND,TYPICAL,MPIR_Bsend_dump());
        -:  352:
        -:  353:    /* Remove the segment from the active list */
   124914:  354:    if (prev) {
        -:  355:	MPIU_DBG_MSG(BSEND,TYPICAL,"free segment is within active list");
       54:  356:	prev->next = p->next;
        -:  357:    }
        -:  358:    else {
        -:  359:	/* p was at the head of the active list */
        -:  360:	MPIU_DBG_MSG(BSEND,TYPICAL,"free segment is head of active list");
   124860:  361:	BsendBuffer.active = p->next;
        -:  362:	/* The next test sets the prev pointer to null */
        -:  363:    }
   124914:  364:    if (p->next) {
    36500:  365:	p->next->prev = prev;
        -:  366:    }
        -:  367:
        -:  368:    MPIU_DBG_STMT(BSEND,VERBOSE,MPIR_Bsend_dump());
        -:  369:
        -:  370:    /* Merge into the avail list */
        -:  371:    /* Find avail_prev, avail, such that p is between them.
        -:  372:       either may be null if p is at either end of the list */
   124914:  373:    avail_prev = 0;
   249843:  374:    while (avail) {
   124317:  375:	if (avail > p) {
   124302:  376:	    break;
        -:  377:	}
       15:  378:	avail_prev = avail;
       15:  379:	avail      = avail->next;
        -:  380:    }
        -:  381:
        -:  382:    /* Try to merge p with the next block */
   124914:  383:    if (avail) {
   124302:  384:	if ((char *)p + p->total_size == (char *)avail) {
   124273:  385:	    p->total_size += avail->total_size;
   124273:  386:	    p->size       = p->total_size - BSENDDATA_HEADER_TRUE_SIZE;
   124273:  387:	    p->next = avail->next;
   124273:  388:	    if (avail->next) avail->next->prev = p;
   124273:  389:	    avail = 0;
        -:  390:	}
        -:  391:	else {
       29:  392:	    p->next = avail;
       29:  393:	    avail->prev = p;
        -:  394:	}
        -:  395:    }
        -:  396:    else {
      612:  397:	p->next = 0;
        -:  398:    }
        -:  399:    /* Try to merge p with the previous block */
   124914:  400:    if (avail_prev) {
       15:  401:	if ((char *)avail_prev + avail_prev->total_size == (char *)p) {
        7:  402:	    avail_prev->total_size += p->total_size;
        7:  403:	    avail_prev->size       = avail_prev->total_size - BSENDDATA_HEADER_TRUE_SIZE;
        7:  404:	    avail_prev->next = p->next;
        7:  405:	    if (p->next) p->next->prev = avail_prev;
        -:  406:	}
        -:  407:	else {
        8:  408:	    avail_prev->next = p;
        8:  409:	    p->prev          = avail_prev;
        -:  410:	}
        -:  411:    }
        -:  412:    else {
        -:  413:	/* p is the new head of the list */
   124899:  414:	BsendBuffer.avail = p;
   124899:  415:	p->prev           = 0;
        -:  416:    }
        -:  417:
        -:  418:    MPIU_DBG_MSG(BSEND,TYPICAL,"At the end of free_segment:" );
        -:  419:    MPIU_DBG_STMT(BSEND,TYPICAL,MPIR_Bsend_dump());
   124914:  420:}
        -:  421:/* end:nested */
        -:  422:/* 
        -:  423: * The following routine tests for completion of active sends and 
        -:  424: * frees the related storage
        -:  425: *
        -:  426: * To make it easier to identify the source of the request, we keep
        -:  427: * track of the type of MPI routine (ibsend, bsend, or bsend_init/start)
        -:  428: * that created the bsend entry.
        -:  429: */
        -:  430:#undef FUNCNAME
        -:  431:#define FUNCNAME MPIR_Bsend_check_active
        -:  432:#undef FCNAME
        -:  433:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  434:static void MPIR_Bsend_check_active( void )
   199401:  435:{
   199401:  436:    MPIR_Bsend_data_t *active = BsendBuffer.active, *next_active;
        -:  437:
        -:  438:    MPIU_DBG_MSG_P(BSEND,TYPICAL,"Checking active starting at %p", active);
   603992:  439:    while (active) {
   205190:  440:	MPI_Request r = active->request->handle;
        -:  441:	int         flag;
        -:  442:	
   205190:  443:	next_active = active->next;
        -:  444:
   205190:  445:	if (active->kind == IBSEND) {
        -:  446:	    /* We handle ibsend specially to allow for the user
        -:  447:	       to attempt and cancel the request. Also, to allow
        -:  448:	       for a cancel attempt (which must be attempted before
        -:  449:	       a successful test or wait), we only start
        -:  450:	       testing when the user has successfully released
        -:  451:	       the request (it is a grequest, the free call will do it) */
   126198:  452:	    flag = 0;
        -:  453:            /* XXX DJG FIXME-MT should we be checking this? */
   126198:  454:	    if (MPIU_Object_get_ref(active->request) == 1) {
    71197:  455:		NMPI_Test(&r, &flag, MPI_STATUS_IGNORE );
        -:  456:	    }
        -:  457:	    else {
        -:  458:		/* We need to invoke the progress engine in case we 
        -:  459:		 need to advance other, incomplete communication.  */
        -:  460:		MPID_Progress_state progress_state;
    55001:  461:		MPID_Progress_start(&progress_state);
    55001:  462:		MPID_Progress_test( );
        -:  463:		MPID_Progress_end(&progress_state);
        -:  464:	    }
        -:  465:	}
        -:  466:	else {
    78992:  467:	    NMPI_Test( &r, &flag, MPI_STATUS_IGNORE );
        -:  468:	}
   205190:  469:	if (flag) {
        -:  470:	    /* We're done.  Remove this segment */
        -:  471:	    MPIU_DBG_MSG_P(BSEND,TYPICAL,"Removing segment %p", active);
   124914:  472:	    MPIR_Bsend_free_segment( active );
        -:  473:	}
   205190:  474:	active = next_active;
        -:  475:	MPIU_DBG_MSG_P(BSEND,TYPICAL,"Next active is %p",active);
        -:  476:    }
   199401:  477:}
        -:  478:
        -:  479:/* 
        -:  480: * FIXME : For each pending item (that is, items that we couldn't even start sending),
        -:  481: * try to get them going.  
        -:  482: */
        -:  483:static void MPIR_Bsend_retry_pending( void )
     5817:  484:{
     5817:  485:    MPIR_Bsend_data_t *pending = BsendBuffer.pending, *next_pending;
        -:  486:
    11634:  487:    while (pending) {
    #####:  488:	next_pending = pending->next;
        -:  489:	/* Retry sending this item */
        -:  490:	/* FIXME */
    #####:  491:	pending = next_pending;
        -:  492:    }
     5817:  493:}
        -:  494:
        -:  495:/* 
        -:  496: * Find a slot in the avail buffer that can hold size bytes.  Does *not*
        -:  497: * remove the slot from the avail buffer (see MPIR_Bsend_take_buffer) 
        -:  498: */
        -:  499:static MPIR_Bsend_data_t *MPIR_Bsend_find_buffer( int size )
   199401:  500:{
   199401:  501:    MPIR_Bsend_data_t *p = BsendBuffer.avail;
        -:  502:
   398814:  503:    while (p) {
   187790:  504:	if (p->size >= size) { 
   187778:  505:	    return p;
        -:  506:	}
       12:  507:	p = p->next;
        -:  508:    }
    11623:  509:    return 0;
        -:  510:}
        -:  511:
        -:  512:/* This is the minimum number of bytes that a segment must be able to
        -:  513:   hold. */
        -:  514:#define MIN_BUFFER_BLOCK 8
        -:  515:/*
        -:  516: * Carve off size bytes from buffer p and leave the remainder
        -:  517: * on the avail list.  Handle the head/tail cases. 
        -:  518: * If there isn't enough left of p, remove the entire segment from
        -:  519: * the avail list.
        -:  520: */
        -:  521:static void MPIR_Bsend_take_buffer( MPIR_Bsend_data_t *p, int size  )
   187778:  522:{
        -:  523:    MPIR_Bsend_data_t *prev;
        -:  524:    int         alloc_size;
        -:  525:
        -:  526:    /* Compute the remaining size.  This must include any padding 
        -:  527:       that must be added to make the new block properly aligned */
   187778:  528:    alloc_size = size;
   187778:  529:    if (alloc_size & 0x7) 
    20891:  530:	alloc_size += (8 - (alloc_size & 0x7));
        -:  531:    /* alloc_size is the amount of space (out of size) that we will 
        -:  532:       allocate for this buffer. */
        -:  533:
        -:  534:    MPIU_DBG_MSG_FMT(BSEND,TYPICAL,(MPIU_DBG_FDEST,
        -:  535:			    "Taking %d bytes from a block with %d bytes\n", 
        -:  536:				    alloc_size, p->total_size ));
        -:  537:
        -:  538:    /* Is there enough space left to create a new block? */
   187778:  539:    if (alloc_size + (int)BSENDDATA_HEADER_TRUE_SIZE + MIN_BUFFER_BLOCK <= p->size) {
        -:  540:	/* Yes, the available space (p->size) is large enough to 
        -:  541:	   carve out a new block */
        -:  542:	MPIR_Bsend_data_t *newp;
        -:  543:	
        -:  544:	MPIU_DBG_MSG_P(BSEND,TYPICAL,"Breaking block into used and allocated at %p", p );
   186541:  545:	newp = (MPIR_Bsend_data_t *)( (char *)p + BSENDDATA_HEADER_TRUE_SIZE + 
        -:  546:				alloc_size );
   186541:  547:	newp->total_size = p->total_size - alloc_size - 
        -:  548:	    BSENDDATA_HEADER_TRUE_SIZE;
   186541:  549:	newp->size = newp->total_size - BSENDDATA_HEADER_TRUE_SIZE;
   186541:  550:	newp->msg.msgbuf = (char *)newp + BSENDDATA_HEADER_TRUE_SIZE;
        -:  551:
        -:  552:	/* Insert this new block after p (we'll remove p from the avail list
        -:  553:	   next) */
   186541:  554:	newp->next = p->next;
   186541:  555:	newp->prev = p;
   186541:  556:	if (p->next) {
        5:  557:	    p->next->prev = newp;
        -:  558:	}
   186541:  559:	p->next       = newp;
   186541:  560:	p->total_size = (char *)newp - (char*)p;
   186541:  561:	p->size       = p->total_size - BSENDDATA_HEADER_TRUE_SIZE;
        -:  562:
        -:  563:	MPIU_DBG_MSG_FMT(BSEND,TYPICAL,(MPIU_DBG_FDEST,
        -:  564:		   "broken blocks p (%d) and new (%d)\n",
        -:  565:		    p->total_size, newp->total_size ));
        -:  566:    }
        -:  567:
        -:  568:    /* Remove p from the avail list and add it to the active list */
   187778:  569:    prev = p->prev;
   187778:  570:    if (prev) {
    #####:  571:	prev->next = p->next;
        -:  572:    }
        -:  573:    else {
   187778:  574:	BsendBuffer.avail = p->next;
        -:  575:    }
        -:  576:
   187778:  577:    if (p->next) {
   186563:  578:	p->next->prev = p->prev;
        -:  579:    }
        -:  580:	
   187778:  581:    if (BsendBuffer.active) {
    53496:  582:	BsendBuffer.active->prev = p;
        -:  583:    }
   187778:  584:    p->next	       = BsendBuffer.active;
   187778:  585:    p->prev	       = 0;
   187778:  586:    BsendBuffer.active = p;
        -:  587:
        -:  588:    MPIU_DBG_MSG_P(BSEND,VERBOSE,"segment %p now head of active",p); 
        -:  589:    MPIU_DBG_MSG(BSEND,TYPICAL,"At end of take buffer" );
        -:  590:    MPIU_DBG_STMT(BSEND,TYPICAL,MPIR_Bsend_dump());
   187778:  591:}
        -:  592:
        -:  593:static int MPIR_Bsend_finalize( void *p ATTRIBUTE((unused)) )
      168:  594:{
        -:  595:    void *b;
        -:  596:    int  s;
        -:  597:
        -:  598:    MPIU_UNREFERENCED_ARG(p);
        -:  599:
      168:  600:    if (BsendBuffer.buffer) {
        -:  601:	/* Use detach to complete any communication */
        4:  602:	MPIR_Bsend_detach( &b, &s );
        -:  603:    }
      168:  604:    return 0;
        -:  605:}
        -:  606:
        -:  607:/* 
        -:  608: * These routines are defined only if debug logging is enabled
        -:  609: */
        -:  610:#ifdef USE_DBG_LOGGING
        -:  611:static void MPIR_Bsend_dump( void )
        -:  612:{
        -:  613:    MPIR_Bsend_data_t *a = BsendBuffer.avail;
        -:  614:
        -:  615:    MPIU_DBG_MSG_D(BSEND,TYPICAL,"Total size is %d",BsendBuffer.buffer_size );
        -:  616:    MPIU_DBG_MSG(BSEND,TYPICAL,"Avail list is:" );
        -:  617:    while (a) {
        -:  618:	MPIU_DBG_MSG_FMT(BSEND,TYPICAL,(MPIU_DBG_FDEST,
        -:  619:				"[%p] totalsize = %d(%x)", a, a->total_size, 
        -:  620:					a->total_size ));
        -:  621:	if (a == a->next) {
        -:  622:	    MPIU_DBG_MSG(BSEND,TYPICAL,
        -:  623:			 "@@@Corrupt list; avail block points at itself" );
        -:  624:	    break;
        -:  625:	}
        -:  626:	a = a->next;
        -:  627:    }
        -:  628:    
        -:  629:    MPIU_DBG_MSG(BSEND,TYPICAL,"Active list is:" );
        -:  630:    a = BsendBuffer.active;
        -:  631:    while (a) {
        -:  632:	MPIU_DBG_MSG_FMT(BSEND,TYPICAL,(MPIU_DBG_FDEST,
        -:  633:				"[%p] totalsize = %d(%x)", a, a->total_size, 
        -:  634:					a->total_size ));
        -:  635:	if (a == a->next) {
        -:  636:	    MPIU_DBG_MSG(BSEND,TYPICAL,
        -:  637:			 "@@@Corrupt list; active block points at itself" );
        -:  638:	    break;
        -:  639:	}
        -:  640:	a = a->next;
        -:  641:    }
        -:  642:    MPIU_DBG_MSG(BSEND,TYPICAL,"end of list" );
        -:  643:}
        -:  644:#endif