📄 bsendutil.c
字号:
"**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; DEBUG1(printf("Freeing bsend segment at %x of size %d, next at %x\n", p,p->size, ((char *)p)+p->total_size));#ifdef PRINT_ARENA printf( "At the begining of free_segment with size %d:\n", p->total_size ); MPIR_Bsend_dump();#endif /* Remove the segment from the free list */ if (prev) { DEBUG(printf("free segment is within active list\n")); prev->next = p->next; } else { /* p was at the head of the active list */ DEBUG(printf("free segment is head of active list\n")); BsendBuffer.active = p->next; /* The next test sets the prev pointer to null */ } if (p->next) { p->next->prev = prev; }#ifdef PRINT_AVAIL_LIST { BsendData_t *a = BsendBuffer.avail; printf( "Avail list is:\n" ); while (a) { printf( "[%x] totalsize = %d(%x)\n", a, a->total_size, a->total_size ); a = a->next; } }#endif /* 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 = p->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; }#ifdef PRINT_ARENA printf( "At the end of free_segment:\n" ); MPIR_Bsend_dump();#endif }/* 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; DEBUG(printf("Checking active starting at %x\n", active )); while (active) { MPI_Request r = active->request->handle; int flag; next_active = active->next; NMPI_Test( &r, &flag, MPI_STATUS_IGNORE ); if (flag) { /* We're done. Remove this segment */ DEBUG(printf("Removing segment %x\n", active )); MPIR_Bsend_free_segment( active ); } active = next_active; DEBUG(printf("Next active is %x\n",active)); }}/* * For each pending item (that is, items that we couldn't even start sending), * try to get them going. FIXME */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. */#ifdef PRINT_ARENA printf( "Taking %d bytes from a block with %d bytes\n", alloc_size, p->total_size );#endif /* Is there enough space left to create a new block? */ if (alloc_size + 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; DEBUG(printf("Breaking block into used and allocated at %x\n", 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;#ifdef PRINT_ARENA printf( "broken blocks p (%d) and new (%d)\n", p->total_size, newp->total_size ); fflush(stdout);#endif } /* 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;#ifdef PRINT_ARENA printf( "At end of take buffer\n" ); MPIR_Bsend_dump();#endif DEBUG(printf("segment %x now head of active\n", p ));}/* Ignore p */static int MPIR_Bsend_finalize( void *p ){ void *b; int s; if (BsendBuffer.buffer) { /* Use detach to complete any communication */ MPIR_Bsend_detach( &b, &s ); } return 0;}#ifdef PRINT_ARENAvoid MPIR_Bsend_dump( void ){ BsendData_t *a = BsendBuffer.avail; printf( "Total size is %d\n", BsendBuffer.buffer_size ); printf( "Avail list is:\n" ); while (a) { printf( "[%x] totalsize = %d(%x)\n", a, a->total_size, a->total_size ); if (a == a->next) { printf( "@@@Corrupt list; avail block points at itself\n" ); break; } a = a->next; } printf( "Active list is:\n" ); a = BsendBuffer.active; while (a) { printf( "[%x] totalsize = %d(%x)\n", a, a->total_size, a->total_size ); if (a == a->next) { printf( "@@@Corrupt list; active block points at itself\n" ); break; } a = a->next; } printf( "end of list\n" ); fflush( stdout );}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -