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 int 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)
MPIR_Bsend_attach(void * buffer,int buffer_size)93 int MPIR_Bsend_attach( void *buffer, int buffer_size )
94 {
95 MPIR_Bsend_data_t *p;
96 size_t offset, align_sz;
97
98 # ifdef HAVE_ERROR_CHECKING
99 {
100 MPID_BEGIN_ERROR_CHECKS;
101 {
102 if (BsendBuffer.buffer) {
103 return MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE,
104 "MPIR_Bsend_attach", __LINE__, MPI_ERR_BUFFER,
105 "**bufexists", 0 );
106 }
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
122 if (!initialized) {
123 initialized = 1;
124 MPIR_Add_finalize( MPIR_Bsend_finalize, (void *)0, 10 );
125 }
126
127 BsendBuffer.origbuffer = buffer;
128 BsendBuffer.origbuffer_size = buffer_size;
129 BsendBuffer.buffer = buffer;
130 BsendBuffer.buffer_size = buffer_size;
131
132 /* Make sure that the buffer that we use is aligned to align_sz. Some other
133 code assumes pointer-alignment, and some code assumes double alignment.
134 Further, GCC 4.5.1 generates bad code on 32-bit platforms when this is
135 only 4-byte aligned (see #1149). */
136 align_sz = MPIR_MAX(sizeof(void *), sizeof(double));
137 offset = ((size_t)buffer) % align_sz;
138 if (offset) {
139 offset = align_sz - offset;
140 buffer = (char *)buffer + offset;
141 BsendBuffer.buffer = buffer;
142 BsendBuffer.buffer_size -= offset;
143 }
144 BsendBuffer.avail = buffer;
145 BsendBuffer.pending = 0;
146 BsendBuffer.active = 0;
147
148 /* Set the first block */
149 p = (MPIR_Bsend_data_t *)buffer;
150 p->size = buffer_size - BSENDDATA_HEADER_TRUE_SIZE;
151 p->total_size = buffer_size;
152 p->next = p->prev = NULL;
153 p->msg.msgbuf = (char *)p + BSENDDATA_HEADER_TRUE_SIZE;
154
155 return MPI_SUCCESS;
156 }
157
158 /*
159 * Detach a buffer. This routine must wait until any pending bsends
160 * are complete.
161 */
162 #undef FUNCNAME
163 #define FUNCNAME MPIR_Bsend_detach
164 #undef FCNAME
165 #define FCNAME MPIDI_QUOTE(FUNCNAME)
MPIR_Bsend_detach(void * bufferp,int * size)166 int MPIR_Bsend_detach( void *bufferp, int *size )
167 {
168 if (BsendBuffer.pending) {
169 /* FIXME: Process pending bsend requests in detach */
170 return MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE,
171 "MPIR_Bsend_detach", __LINE__, MPI_ERR_OTHER, "**bsendpending", 0 );
172 }
173 if (BsendBuffer.active) {
174 /* Loop through each active element and wait on it */
175 MPIR_Bsend_data_t *p = BsendBuffer.active;
176
177 while (p) {
178 MPI_Request r = p->request->handle;
179 MPIR_Wait_impl( &r, MPI_STATUS_IGNORE );
180 p = p->next;
181 }
182 }
183
184 /* Note that this works even when the buffer does not exist */
185 *(void **) bufferp = BsendBuffer.origbuffer;
186 *size = BsendBuffer.origbuffer_size;
187 BsendBuffer.origbuffer = NULL;
188 BsendBuffer.origbuffer_size = 0;
189 BsendBuffer.buffer = 0;
190 BsendBuffer.buffer_size = 0;
191 BsendBuffer.avail = 0;
192 BsendBuffer.active = 0;
193 BsendBuffer.pending = 0;
194
195 return MPI_SUCCESS;
196 }
197
198 /*
199 * Initiate an ibsend. We'll used this for Bsend as well.
200 */
201 #undef FUNCNAME
202 #define FUNCNAME MPIR_Bsend_isend
203 #undef FCNAME
204 #define FCNAME MPIDI_QUOTE(FUNCNAME)
MPIR_Bsend_isend(const void * buf,int count,MPI_Datatype dtype,int dest,int tag,MPID_Comm * comm_ptr,MPIR_Bsend_kind_t kind,MPID_Request ** request)205 int MPIR_Bsend_isend(const void *buf, int count, MPI_Datatype dtype,
206 int dest, int tag, MPID_Comm *comm_ptr,
207 MPIR_Bsend_kind_t kind, MPID_Request **request )
208 {
209 int mpi_errno = MPI_SUCCESS;
210 MPIR_Bsend_data_t *p;
211 MPIR_Bsend_msg_t *msg;
212 int packsize, pass;
213
214 /* Find a free segment and copy the data into it. If we could
215 have, we would already have used tBsend to send the message with
216 no copying.
217
218 We may want to decide here whether we need to pack at all
219 or if we can just use (a MPIU_Memcpy) of the buffer.
220 */
221
222
223 /* We check the active buffer first. This helps avoid storage
224 fragmentation */
225 mpi_errno = MPIR_Bsend_check_active();
226 if (mpi_errno) MPIU_ERR_POP(mpi_errno);
227
228 if (dtype != MPI_PACKED)
229 MPIR_Pack_size_impl( count, dtype, &packsize );
230 else
231 packsize = count;
232
233 MPIU_DBG_MSG_D(BSEND,TYPICAL,"looking for buffer of size %d", packsize);
234 /*
235 * Use two passes. Each pass is the same; between the two passes,
236 * attempt to complete any active requests, and start any pending
237 * ones. If the message can be initiated in the first pass,
238 * do not perform the second pass.
239 */
240 for (pass = 0; pass < 2; pass++) {
241
242 p = MPIR_Bsend_find_buffer( packsize );
243 if (p) {
244 MPIU_DBG_MSG_FMT(BSEND,TYPICAL,(MPIU_DBG_FDEST,
245 "found buffer of size %d with address %p",packsize,p));
246 /* Found a segment */
247
248 msg = &p->msg;
249
250 /* Pack the data into the buffer */
251 /* We may want to optimize for the special case of
252 either primative or contiguous types, and just
253 use MPIU_Memcpy and the provided datatype */
254 msg->count = 0;
255 if (dtype != MPI_PACKED)
256 {
257 mpi_errno = MPIR_Pack_impl( buf, count, dtype, p->msg.msgbuf, packsize, &p->msg.count);
258 if (mpi_errno) MPIU_ERR_POP(mpi_errno);
259 }
260 else
261 {
262 MPIU_Memcpy(p->msg.msgbuf, buf, count);
263 p->msg.count = count;
264 }
265 /* Try to send the message. We must use MPID_Isend
266 because this call must not block */
267 mpi_errno = MPID_Isend(msg->msgbuf, msg->count, MPI_PACKED,
268 dest, tag, comm_ptr,
269 MPID_CONTEXT_INTRA_PT2PT, &p->request );
270 MPIU_ERR_CHKINTERNAL(mpi_errno, mpi_errno, "Bsend internal error: isend returned err");
271 /* If the error is "request not available", we should
272 put this on the pending list. This will depend on
273 how we signal failure to send. */
274
275 if (p->request) {
276 MPIU_DBG_MSG_FMT(BSEND,TYPICAL,
277 (MPIU_DBG_FDEST,"saving request %p in %p",p->request,p));
278 /* An optimization is to check to see if the
279 data has already been sent. The original code
280 to do this was commented out and probably did not match
281 the current request internals */
282 MPIR_Bsend_take_buffer( p, p->msg.count );
283 p->kind = kind;
284 *request = p->request;
285 }
286 break;
287 }
288 /* If we found a buffer or we're in the seccond pass, then break.
289 Note that the test on phere is redundant, as the code breaks
290 out of the loop in the test above if a block p is found. */
291 if (p || pass == 1) break;
292 MPIU_DBG_MSG(BSEND,TYPICAL,"Could not find storage, checking active");
293 /* Try to complete some pending bsends */
294 MPIR_Bsend_check_active( );
295 /* Give priority to any pending operations */
296 MPIR_Bsend_retry_pending( );
297 }
298
299 if (!p) {
300 /* Return error for no buffer space found */
301 /* Generate a traceback of the allocated space, explaining why
302 packsize could not be found */
303 MPIU_DBG_MSG(BSEND,TYPICAL,"Could not find space; dumping arena" );
304 MPIU_DBG_STMT(BSEND,TYPICAL,MPIR_Bsend_dump());
305 MPIU_ERR_SETANDJUMP2(mpi_errno, MPI_ERR_BUFFER, "**bufbsend", "**bufbsend %d %d", packsize, BsendBuffer.buffer_size);
306 }
307
308 fn_exit:
309 return mpi_errno;
310 fn_fail:
311 goto fn_exit;
312 }
313
314 /*
315 * The following routines are used to manage the allocation of bsend segments
316 * in the user buffer. These routines handle, for example, merging segments
317 * when an active segment that is adjacent to a free segment becomes free.
318 *
319 */
320
321 /* Add block p to the free list. Merge into adjacent blocks. Used only
322 within the check_active */
323
324 #undef FUNCNAME
325 #define FUNCNAME MPIR_Bsend_free_segment
326 #undef FCNAME
327 #define FCNAME MPIDI_QUOTE(FUNCNAME)
MPIR_Bsend_free_segment(MPIR_Bsend_data_t * p)328 static void MPIR_Bsend_free_segment( MPIR_Bsend_data_t *p )
329 {
330 MPIR_Bsend_data_t *prev = p->prev, *avail = BsendBuffer.avail, *avail_prev;
331
332 MPIU_DBG_MSG_FMT(BSEND,TYPICAL,(MPIU_DBG_FDEST,
333 "Freeing bsend segment at %p of size %d, next at %p",
334 p,p->size, ((char *)p)+p->total_size));
335
336 MPIU_DBG_MSG_D(BSEND,TYPICAL,
337 "At the begining of free_segment with size %d:", p->total_size );
338 MPIU_DBG_STMT(BSEND,TYPICAL,MPIR_Bsend_dump());
339
340 /* Remove the segment from the active list */
341 if (prev) {
342 MPIU_DBG_MSG(BSEND,TYPICAL,"free segment is within active list");
343 prev->next = p->next;
344 }
345 else {
346 /* p was at the head of the active list */
347 MPIU_DBG_MSG(BSEND,TYPICAL,"free segment is head of active list");
348 BsendBuffer.active = p->next;
349 /* The next test sets the prev pointer to null */
350 }
351 if (p->next) {
352 p->next->prev = prev;
353 }
354
355 MPIU_DBG_STMT(BSEND,VERBOSE,MPIR_Bsend_dump());
356
357 /* Merge into the avail list */
358 /* Find avail_prev, avail, such that p is between them.
359 either may be null if p is at either end of the list */
360 avail_prev = 0;
361 while (avail) {
362 if (avail > p) {
363 break;
364 }
365 avail_prev = avail;
366 avail = avail->next;
367 }
368
369 /* Try to merge p with the next block */
370 if (avail) {
371 if ((char *)p + p->total_size == (char *)avail) {
372 p->total_size += avail->total_size;
373 p->size = p->total_size - BSENDDATA_HEADER_TRUE_SIZE;
374 p->next = avail->next;
375 if (avail->next) avail->next->prev = p;
376 avail = 0;
377 }
378 else {
379 p->next = avail;
380 avail->prev = p;
381 }
382 }
383 else {
384 p->next = 0;
385 }
386 /* Try to merge p with the previous block */
387 if (avail_prev) {
388 if ((char *)avail_prev + avail_prev->total_size == (char *)p) {
389 avail_prev->total_size += p->total_size;
390 avail_prev->size = avail_prev->total_size - BSENDDATA_HEADER_TRUE_SIZE;
391 avail_prev->next = p->next;
392 if (p->next) p->next->prev = avail_prev;
393 }
394 else {
395 avail_prev->next = p;
396 p->prev = avail_prev;
397 }
398 }
399 else {
400 /* p is the new head of the list */
401 BsendBuffer.avail = p;
402 p->prev = 0;
403 }
404
405 MPIU_DBG_MSG(BSEND,TYPICAL,"At the end of free_segment:" );
406 MPIU_DBG_STMT(BSEND,TYPICAL,MPIR_Bsend_dump());
407 }
408
409 /*
410 * The following routine tests for completion of active sends and
411 * frees the related storage
412 *
413 * To make it easier to identify the source of the request, we keep
414 * track of the type of MPI routine (ibsend, bsend, or bsend_init/start)
415 * that created the bsend entry.
416 */
417 #undef FUNCNAME
418 #define FUNCNAME MPIR_Bsend_check_active
419 #undef FCNAME
420 #define FCNAME MPIDI_QUOTE(FUNCNAME)
MPIR_Bsend_check_active(void)421 static int MPIR_Bsend_check_active( void )
422 {
423 int mpi_errno = MPI_SUCCESS;
424 MPIR_Bsend_data_t *active = BsendBuffer.active, *next_active;
425
426 MPIU_DBG_MSG_P(BSEND,TYPICAL,"Checking active starting at %p", active);
427 while (active) {
428 MPI_Request r = active->request->handle;
429 int flag;
430
431 next_active = active->next;
432
433 if (active->kind == IBSEND) {
434 /* We handle ibsend specially to allow for the user
435 to attempt and cancel the request. Also, to allow
436 for a cancel attempt (which must be attempted before
437 a successful test or wait), we only start
438 testing when the user has successfully released
439 the request (it is a grequest, the free call will do it) */
440 flag = 0;
441 /* XXX DJG FIXME-MT should we be checking this? */
442 if (MPIU_Object_get_ref(active->request) == 1) {
443 mpi_errno = MPIR_Test_impl(&r, &flag, MPI_STATUS_IGNORE );
444 if (mpi_errno) MPIU_ERR_POP(mpi_errno);
445 } else {
446 /* We need to invoke the progress engine in case we
447 need to advance other, incomplete communication. */
448 MPID_Progress_state progress_state;
449 MPID_Progress_start(&progress_state);
450 mpi_errno = MPID_Progress_test( );
451 MPID_Progress_end(&progress_state);
452 if (mpi_errno) MPIU_ERR_POP(mpi_errno);
453 }
454 } else {
455 mpi_errno = MPIR_Test_impl( &r, &flag, MPI_STATUS_IGNORE );
456 if (mpi_errno) MPIU_ERR_POP(mpi_errno);
457 }
458 if (flag) {
459 /* We're done. Remove this segment */
460 MPIU_DBG_MSG_P(BSEND,TYPICAL,"Removing segment %p", active);
461 MPIR_Bsend_free_segment( active );
462 }
463 active = next_active;
464 MPIU_DBG_MSG_P(BSEND,TYPICAL,"Next active is %p",active);
465 }
466
467 fn_exit:
468 return mpi_errno;
469 fn_fail:
470 goto fn_exit;
471 }
472
473 /*
474 * FIXME : For each pending item (that is, items that we couldn't even start
475 * sending), try to get them going.
476 */
MPIR_Bsend_retry_pending(void)477 static void MPIR_Bsend_retry_pending( void )
478 {
479 MPIR_Bsend_data_t *pending = BsendBuffer.pending, *next_pending;
480
481 while (pending) {
482 next_pending = pending->next;
483 /* Retry sending this item */
484 /* FIXME: Unimplemented retry of pending bsend operations */
485 pending = next_pending;
486 }
487 }
488
489 /*
490 * Find a slot in the avail buffer that can hold size bytes. Does *not*
491 * remove the slot from the avail buffer (see MPIR_Bsend_take_buffer)
492 */
MPIR_Bsend_find_buffer(int size)493 static MPIR_Bsend_data_t *MPIR_Bsend_find_buffer( int size )
494 {
495 MPIR_Bsend_data_t *p = BsendBuffer.avail;
496
497 while (p) {
498 if (p->size >= size) {
499 return p;
500 }
501 p = p->next;
502 }
503 return 0;
504 }
505
506 /* This is the minimum number of bytes that a segment must be able to
507 hold. */
508 #define MIN_BUFFER_BLOCK 8
509 /*
510 * Carve off size bytes from buffer p and leave the remainder
511 * on the avail list. Handle the head/tail cases.
512 * If there isn't enough left of p, remove the entire segment from
513 * the avail list.
514 */
MPIR_Bsend_take_buffer(MPIR_Bsend_data_t * p,int size)515 static void MPIR_Bsend_take_buffer( MPIR_Bsend_data_t *p, int size )
516 {
517 MPIR_Bsend_data_t *prev;
518 int alloc_size;
519
520 /* Compute the remaining size. This must include any padding
521 that must be added to make the new block properly aligned */
522 alloc_size = size;
523 if (alloc_size & 0x7)
524 alloc_size += (8 - (alloc_size & 0x7));
525 /* alloc_size is the amount of space (out of size) that we will
526 allocate for this buffer. */
527
528 MPIU_DBG_MSG_FMT(BSEND,TYPICAL,(MPIU_DBG_FDEST,
529 "Taking %d bytes from a block with %d bytes\n",
530 alloc_size, p->total_size ));
531
532 /* Is there enough space left to create a new block? */
533 if (alloc_size + (int)BSENDDATA_HEADER_TRUE_SIZE + MIN_BUFFER_BLOCK <= p->size) {
534 /* Yes, the available space (p->size) is large enough to
535 carve out a new block */
536 MPIR_Bsend_data_t *newp;
537
538 MPIU_DBG_MSG_P(BSEND,TYPICAL,"Breaking block into used and allocated at %p", p );
539 newp = (MPIR_Bsend_data_t *)( (char *)p + BSENDDATA_HEADER_TRUE_SIZE +
540 alloc_size );
541 newp->total_size = p->total_size - alloc_size -
542 BSENDDATA_HEADER_TRUE_SIZE;
543 newp->size = newp->total_size - BSENDDATA_HEADER_TRUE_SIZE;
544 newp->msg.msgbuf = (char *)newp + BSENDDATA_HEADER_TRUE_SIZE;
545
546 /* Insert this new block after p (we'll remove p from the avail list
547 next) */
548 newp->next = p->next;
549 newp->prev = p;
550 if (p->next) {
551 p->next->prev = newp;
552 }
553 p->next = newp;
554 p->total_size = (char *)newp - (char*)p;
555 p->size = p->total_size - BSENDDATA_HEADER_TRUE_SIZE;
556
557 MPIU_DBG_MSG_FMT(BSEND,TYPICAL,(MPIU_DBG_FDEST,
558 "broken blocks p (%d) and new (%d)\n",
559 p->total_size, newp->total_size ));
560 }
561
562 /* Remove p from the avail list and add it to the active list */
563 prev = p->prev;
564 if (prev) {
565 prev->next = p->next;
566 }
567 else {
568 BsendBuffer.avail = p->next;
569 }
570
571 if (p->next) {
572 p->next->prev = p->prev;
573 }
574
575 if (BsendBuffer.active) {
576 BsendBuffer.active->prev = p;
577 }
578 p->next = BsendBuffer.active;
579 p->prev = 0;
580 BsendBuffer.active = p;
581
582 MPIU_DBG_MSG_P(BSEND,VERBOSE,"segment %p now head of active",p);
583 MPIU_DBG_MSG(BSEND,TYPICAL,"At end of take buffer" );
584 MPIU_DBG_STMT(BSEND,TYPICAL,MPIR_Bsend_dump());
585 }
586
MPIR_Bsend_finalize(void * p ATTRIBUTE ((unused)))587 static int MPIR_Bsend_finalize( void *p ATTRIBUTE((unused)) )
588 {
589 void *b;
590 int s;
591
592 MPIU_UNREFERENCED_ARG(p);
593
594 if (BsendBuffer.buffer) {
595 /* Use detach to complete any communication */
596 MPIR_Bsend_detach( &b, &s );
597 }
598 return 0;
599 }
600
601 /*
602 * These routines are defined only if debug logging is enabled
603 */
604 #ifdef USE_DBG_LOGGING
MPIR_Bsend_dump(void)605 static void MPIR_Bsend_dump( void )
606 {
607 MPIR_Bsend_data_t *a = BsendBuffer.avail;
608
609 MPIU_DBG_MSG_D(BSEND,TYPICAL,"Total size is %d",BsendBuffer.buffer_size );
610 MPIU_DBG_MSG(BSEND,TYPICAL,"Avail list is:" );
611 while (a) {
612 MPIU_DBG_MSG_FMT(BSEND,TYPICAL,(MPIU_DBG_FDEST,
613 "[%p] totalsize = %d(%x)", a, a->total_size,
614 a->total_size ));
615 if (a == a->next) {
616 MPIU_DBG_MSG(BSEND,TYPICAL,
617 "@@@Corrupt list; avail block points at itself" );
618 break;
619 }
620 a = a->next;
621 }
622
623 MPIU_DBG_MSG(BSEND,TYPICAL,"Active list is:" );
624 a = BsendBuffer.active;
625 while (a) {
626 MPIU_DBG_MSG_FMT(BSEND,TYPICAL,(MPIU_DBG_FDEST,
627 "[%p] totalsize = %d(%x)", a, a->total_size,
628 a->total_size ));
629 if (a == a->next) {
630 MPIU_DBG_MSG(BSEND,TYPICAL,
631 "@@@Corrupt list; active block points at itself" );
632 break;
633 }
634 a = a->next;
635 }
636 MPIU_DBG_MSG(BSEND,TYPICAL,"end of list" );
637 }
638 #endif
639