📄 bsendutil.c
字号:
} MPIR_Nest_decr(); if (!p) { /* Return error for no buffer space found */ /* Generate a traceback of the allocated space, explaining why packsize could not be found */ MPIU_DBG_MSG(BSEND,TYPICAL,"Could not find space; dumping arena" ); MPIU_DBG_STMT(BSEND,TYPICAL,MPIR_Bsend_dump()); return MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, "MPIR_Bsend_isend", __LINE__, MPI_ERR_BUFFER, "**bufbsend", "**bufbsend %d %d", packsize, BsendBuffer.buffer_size ); } else { return MPI_SUCCESS; }}/* * The following routines are used to manage the allocation of bsend segments * in the user buffer. These routines handle, for example, merging segments * when an active segment that is adjacent to a free segment becomes free. * *//* Add block p to the free list. Merge into adjacent blocks. Used only within the check_active *//* begin:nested */static void MPIR_Bsend_free_segment( BsendData_t *p ){ BsendData_t *prev = p->prev, *avail = BsendBuffer.avail, *avail_prev; MPIU_DBG_MSG_FMT(BSEND,TYPICAL,(MPIU_DBG_FDEST, "Freeing bsend segment at %p of size %d, next at %p", p,p->size, ((char *)p)+p->total_size)); MPIU_DBG_MSG_D(BSEND,TYPICAL, "At the begining of free_segment with size %d:", p->total_size ); MPIU_DBG_STMT(BSEND,TYPICAL,MPIR_Bsend_dump()); /* Remove the segment from the active list */ if (prev) { MPIU_DBG_MSG(BSEND,TYPICAL,"free segment is within active list"); prev->next = p->next; } else { /* p was at the head of the active list */ MPIU_DBG_MSG(BSEND,TYPICAL,"free segment is head of active list"); BsendBuffer.active = p->next; /* The next test sets the prev pointer to null */ } if (p->next) { p->next->prev = prev; } MPIU_DBG_STMT(BSEND,VERBOSE,MPIR_Bsend_dump()); /* Merge into the avail list */ /* Find avail_prev, avail, such that p is between them. either may be null if p is at either end of the list */ avail_prev = 0; while (avail) { if (avail > p) { break; } avail_prev = avail; avail = avail->next; } /* Try to merge p with the next block */ if (avail) { if ((char *)p + p->total_size == (char *)avail) { p->total_size += avail->total_size; p->size = p->total_size - BSENDDATA_HEADER_TRUE_SIZE; p->next = avail->next; if (avail->next) avail->next->prev = p; avail = 0; } else { p->next = avail; avail->prev = p; } } else { p->next = 0; } /* Try to merge p with the previous block */ if (avail_prev) { if ((char *)avail_prev + avail_prev->total_size == (char *)p) { avail_prev->total_size += p->total_size; avail_prev->size = avail_prev->total_size - BSENDDATA_HEADER_TRUE_SIZE; avail_prev->next = p->next; if (p->next) p->next->prev = avail_prev; } else { avail_prev->next = p; p->prev = avail_prev; } } else { /* p is the new head of the list */ BsendBuffer.avail = p; p->prev = 0; } MPIU_DBG_MSG(BSEND,TYPICAL,"At the end of free_segment:" ); MPIU_DBG_STMT(BSEND,TYPICAL,MPIR_Bsend_dump());}/* end:nested *//* * The following routine tests for completion of active sends and * frees the related storage * * To make it easier to identify the source of the request, we keep * track of the type of MPI routine (ibsend, bsend, or bsend_init/start) * that created the bsend entry. */static void MPIR_Bsend_check_active( void ){ BsendData_t *active = BsendBuffer.active, *next_active; MPIU_DBG_MSG_P(BSEND,TYPICAL,"Checking active starting at %p", active); while (active) { MPI_Request r = active->request->handle; int flag; next_active = active->next; if (active->kind == IBSEND) { /* We handle ibsend specially to allow for the user to attempt and cancel the request. Also, to allow for a cancel attempt (which must be attempted before a successful test or wait), we only start testing when the user has successfully released the request (it is a grequest, the free call will do it) */ flag = 0; if (active->request->ref_count == 1) { NMPI_Test(&r, &flag, MPI_STATUS_IGNORE ); } else { /* We need to invoke the progress engine in case we need to advance other, incomplete communication. */ MPID_Progress_state progress_state; MPID_Progress_start(&progress_state); MPID_Progress_test( ); MPID_Progress_end(&progress_state); } } else { NMPI_Test( &r, &flag, MPI_STATUS_IGNORE ); } if (flag) { /* We're done. Remove this segment */ MPIU_DBG_MSG_P(BSEND,TYPICAL,"Removing segment %p", active); MPIR_Bsend_free_segment( active ); } active = next_active; MPIU_DBG_MSG_P(BSEND,TYPICAL,"Next active is %p",active); }}/* * FIXME : For each pending item (that is, items that we couldn't even start sending), * try to get them going. */static void MPIR_Bsend_retry_pending( void ){ BsendData_t *pending = BsendBuffer.pending, *next_pending; while (pending) { next_pending = pending->next; /* Retry sending this item */ /* FIXME */ pending = next_pending; }}/* * Find a slot in the avail buffer that can hold size bytes. Does *not* * remove the slot from the avail buffer (see MPIR_Bsend_take_buffer) */static BsendData_t *MPIR_Bsend_find_buffer( int size ){ BsendData_t *p = BsendBuffer.avail; while (p) { if (p->size >= size) { return p; } p = p->next; } return 0;}/* This is the minimum number of bytes that a segment must be able to hold. */#define MIN_BUFFER_BLOCK 8/* * Carve off size bytes from buffer p and leave the remainder * on the avail list. Handle the head/tail cases. * If there isn't enough left of p, remove the entire segment from * the avail list. */static void MPIR_Bsend_take_buffer( BsendData_t *p, int size ){ BsendData_t *prev; int alloc_size; /* Compute the remaining size. This must include any padding that must be added to make the new block properly aligned */ alloc_size = size; if (alloc_size & 0x7) alloc_size += (8 - (alloc_size & 0x7)); /* alloc_size is the amount of space (out of size) that we will allocate for this buffer. */ MPIU_DBG_MSG_FMT(BSEND,TYPICAL,(MPIU_DBG_FDEST, "Taking %d bytes from a block with %d bytes\n", alloc_size, p->total_size )); /* Is there enough space left to create a new block? */ if (alloc_size + (int)BSENDDATA_HEADER_TRUE_SIZE + MIN_BUFFER_BLOCK <= p->size) { /* Yes, the available space (p->size) is large enough to carve out a new block */ BsendData_t *newp; MPIU_DBG_MSG_P(BSEND,TYPICAL,"Breaking block into used and allocated at %p", p ); newp = (BsendData_t *)( (char *)p + BSENDDATA_HEADER_TRUE_SIZE + alloc_size ); newp->total_size = p->total_size - alloc_size - BSENDDATA_HEADER_TRUE_SIZE; newp->size = newp->total_size - BSENDDATA_HEADER_TRUE_SIZE; newp->msg.msgbuf = (char *)newp + BSENDDATA_HEADER_TRUE_SIZE; /* Insert this new block after p (we'll remove p from the avail list next) */ newp->next = p->next; newp->prev = p; if (p->next) { p->next->prev = newp; } p->next = newp; p->total_size = (char *)newp - (char*)p; p->size = p->total_size - BSENDDATA_HEADER_TRUE_SIZE; MPIU_DBG_MSG_FMT(BSEND,TYPICAL,(MPIU_DBG_FDEST, "broken blocks p (%d) and new (%d)\n", p->total_size, newp->total_size )); } /* Remove p from the avail list and add it to the active list */ prev = p->prev; if (prev) { prev->next = p->next; } else { BsendBuffer.avail = p->next; } if (p->next) { p->next->prev = p->prev; } if (BsendBuffer.active) { BsendBuffer.active->prev = p; } p->next = BsendBuffer.active; p->prev = 0; BsendBuffer.active = p; MPIU_DBG_MSG_P(BSEND,VERBOSE,"segment %p now head of active",p); MPIU_DBG_MSG(BSEND,TYPICAL,"At end of take buffer" ); MPIU_DBG_STMT(BSEND,TYPICAL,MPIR_Bsend_dump());}/* Ignore p */static int MPIR_Bsend_finalize( void *p ){ void *b; int s; MPIU_UNREFERENCED_ARG(p); if (BsendBuffer.buffer) { /* Use detach to complete any communication */ MPIR_Bsend_detach( &b, &s ); } return 0;}/* * These routines are defined only if debug logging is enabled */#ifdef USE_DBG_LOGGINGstatic void MPIR_Bsend_dump( void ){ BsendData_t *a = BsendBuffer.avail; MPIU_DBG_MSG_D(BSEND,TYPICAL,"Total size is %d",BsendBuffer.buffer_size ); MPIU_DBG_MSG(BSEND,TYPICAL,"Avail list is:" ); while (a) { MPIU_DBG_MSG_FMT(BSEND,TYPICAL,(MPIU_DBG_FDEST, "[%p] totalsize = %d(%x)", a, a->total_size, a->total_size )); if (a == a->next) { MPIU_DBG_MSG(BSEND,TYPICAL, "@@@Corrupt list; avail block points at itself" ); break; } a = a->next; } MPIU_DBG_MSG(BSEND,TYPICAL,"Active list is:" ); a = BsendBuffer.active; while (a) { MPIU_DBG_MSG_FMT(BSEND,TYPICAL,(MPIU_DBG_FDEST, "[%p] totalsize = %d(%x)", a, a->total_size, a->total_size )); if (a == a->next) { MPIU_DBG_MSG(BSEND,TYPICAL, "@@@Corrupt list; active block points at itself" ); break; } a = a->next; } MPIU_DBG_MSG(BSEND,TYPICAL,"end of list" );}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -