|
Packit Service |
c5cf8c |
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* (C) 2001 by Argonne National Laboratory.
|
|
Packit Service |
c5cf8c |
* See COPYRIGHT in top-level directory.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#include "mpiimpl.h"
|
|
Packit Service |
c5cf8c |
#include "mpii_bsend.h"
|
|
Packit Service |
c5cf8c |
#include "bsendutil.h"
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* Miscellaneous comments
|
|
Packit Service |
c5cf8c |
* By storing total_size along with "size available for messages", we
|
|
Packit Service |
c5cf8c |
* avoid any complexities associated with alignment, since we must
|
|
Packit Service |
c5cf8c |
* ensure that each KPIR_Bsend_data_t structure is properly aligned
|
|
Packit Service |
c5cf8c |
* (i.e., we can't simply do (sizeof(MPII_Bsend_data_t) + size) to get
|
|
Packit Service |
c5cf8c |
* total_size).
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* Function Summary
|
|
Packit Service |
c5cf8c |
* MPIR_Bsend_attach - Performs the work of MPI_Buffer_attach
|
|
Packit Service |
c5cf8c |
* MPIR_Bsend_detach - Performs the work of MPI_Buffer_detach
|
|
Packit Service |
c5cf8c |
* MPIR_Bsend_isend - Essentially performs an MPI_Ibsend. Returns
|
|
Packit Service |
c5cf8c |
* an MPIR_Request that is also stored internally in the
|
|
Packit Service |
c5cf8c |
* corresponding MPII_Bsend_data_t entry
|
|
Packit Service |
c5cf8c |
* MPIR_Bsend_free_segment - Free a buffer that is no longer needed,
|
|
Packit Service |
c5cf8c |
* merging with adjacent segments
|
|
Packit Service |
c5cf8c |
* MPIR_Bsend_check_active - Check for completion of any pending sends
|
|
Packit Service |
c5cf8c |
* for bsends (all bsends, both MPI_Ibsend and MPI_Bsend,
|
|
Packit Service |
c5cf8c |
* are internally converted into Isends on the data
|
|
Packit Service |
c5cf8c |
* in the Bsend buffer)
|
|
Packit Service |
c5cf8c |
* MPIR_Bsend_retry_pending - Routine for future use to handle the
|
|
Packit Service |
c5cf8c |
* case where an Isend cannot be initiated.
|
|
Packit Service |
c5cf8c |
* MPIR_Bsend_find_buffer - Find a buffer in the bsend buffer large
|
|
Packit Service |
c5cf8c |
* enough for the message. However, does not acquire that
|
|
Packit Service |
c5cf8c |
* buffer (see MPIR_Bsend_take_buffer)
|
|
Packit Service |
c5cf8c |
* MPIR_Bsend_take_buffer - Find and acquire a buffer for a message
|
|
Packit Service |
c5cf8c |
* MPIR_Bsend_finalize - Finalize handler when Bsend routines are used
|
|
Packit Service |
c5cf8c |
* MPIR_Bsend_dump - Debugging routine to print the contents of the control
|
|
Packit Service |
c5cf8c |
* information in the bsend buffer (the MPII_Bsend_data_t entries)
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#ifdef MPL_USE_DBG_LOGGING
|
|
Packit Service |
c5cf8c |
static void MPIR_Bsend_dump(void);
|
|
Packit Service |
c5cf8c |
#endif
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define BSENDDATA_HEADER_TRUE_SIZE (sizeof(MPII_Bsend_data_t) - sizeof(double))
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* BsendBuffer is the structure that describes the overall Bsend buffer */
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* We use separate buffer and origbuffer because we may need to align
|
|
Packit Service |
c5cf8c |
* the buffer (we *could* always memcopy the header to an aligned region,
|
|
Packit Service |
c5cf8c |
* but it is simpler to just align it internally. This does increase the
|
|
Packit Service |
c5cf8c |
* BSEND_OVERHEAD, but that is already relatively large. We could instead
|
|
Packit Service |
c5cf8c |
* make sure that the initial header was set at an aligned location (
|
|
Packit Service |
c5cf8c |
* taking advantage of the "alignpad"), but this would require more changes.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
static struct BsendBuffer {
|
|
Packit Service |
c5cf8c |
void *buffer; /* Pointer to the begining of the user-
|
|
Packit Service |
c5cf8c |
* provided buffer */
|
|
Packit Service |
c5cf8c |
size_t buffer_size; /* Size of the user-provided buffer */
|
|
Packit Service |
c5cf8c |
void *origbuffer; /* Pointer to the buffer provided by
|
|
Packit Service |
c5cf8c |
* the user */
|
|
Packit Service |
c5cf8c |
size_t origbuffer_size; /* Size of the buffer as provided
|
|
Packit Service |
c5cf8c |
* by the user */
|
|
Packit Service |
c5cf8c |
MPII_Bsend_data_t *avail; /* Pointer to the first available block
|
|
Packit Service |
c5cf8c |
* of space */
|
|
Packit Service |
c5cf8c |
MPII_Bsend_data_t *pending; /* Pointer to the first message that
|
|
Packit Service |
c5cf8c |
* could not be sent because of a
|
|
Packit Service |
c5cf8c |
* resource limit (e.g., no requests
|
|
Packit Service |
c5cf8c |
* available) */
|
|
Packit Service |
c5cf8c |
MPII_Bsend_data_t *active; /* Pointer to the first active (sending)
|
|
Packit Service |
c5cf8c |
* message */
|
|
Packit Service |
c5cf8c |
} BsendBuffer = {
|
|
Packit Service |
c5cf8c |
0, 0, 0, 0, 0, 0, 0};
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int initialized = 0; /* keep track of the first call to any
|
|
Packit Service |
c5cf8c |
* bsend routine */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Forward references */
|
|
Packit Service |
c5cf8c |
static void MPIR_Bsend_retry_pending(void);
|
|
Packit Service |
c5cf8c |
static int MPIR_Bsend_check_active(void);
|
|
Packit Service |
c5cf8c |
static MPII_Bsend_data_t *MPIR_Bsend_find_buffer(size_t);
|
|
Packit Service |
c5cf8c |
static void MPIR_Bsend_take_buffer(MPII_Bsend_data_t *, size_t);
|
|
Packit Service |
c5cf8c |
static int MPIR_Bsend_finalize(void *);
|
|
Packit Service |
c5cf8c |
static void MPIR_Bsend_free_segment(MPII_Bsend_data_t *);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* Attach a buffer. This checks for the error conditions and then
|
|
Packit Service |
c5cf8c |
* initialized the avail buffer.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPIR_Bsend_attach
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
int MPIR_Bsend_attach(void *buffer, int buffer_size)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
MPII_Bsend_data_t *p;
|
|
Packit Service |
c5cf8c |
size_t offset, align_sz;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#ifdef HAVE_ERROR_CHECKING
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
MPID_BEGIN_ERROR_CHECKS;
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
if (BsendBuffer.buffer) {
|
|
Packit Service |
c5cf8c |
return MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE,
|
|
Packit Service |
c5cf8c |
"MPIR_Bsend_attach", __LINE__, MPI_ERR_BUFFER,
|
|
Packit Service |
c5cf8c |
"**bufexists", 0);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (buffer_size < MPI_BSEND_OVERHEAD) {
|
|
Packit Service |
c5cf8c |
/* MPI_ERR_OTHER is another valid choice for this error,
|
|
Packit Service |
c5cf8c |
* but the Intel test wants MPI_ERR_BUFFER, and it seems
|
|
Packit Service |
c5cf8c |
* to violate the principle of least surprise to not use
|
|
Packit Service |
c5cf8c |
* MPI_ERR_BUFFER for errors with the Buffer */
|
|
Packit Service |
c5cf8c |
return MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE,
|
|
Packit Service |
c5cf8c |
"MPIR_Bsend_attach", __LINE__, MPI_ERR_BUFFER,
|
|
Packit Service |
c5cf8c |
"**bsendbufsmall",
|
|
Packit Service |
c5cf8c |
"**bsendbufsmall %d %d", buffer_size,
|
|
Packit Service |
c5cf8c |
MPI_BSEND_OVERHEAD);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
MPID_END_ERROR_CHECKS;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
#endif /* HAVE_ERROR_CHECKING */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (!initialized) {
|
|
Packit Service |
c5cf8c |
initialized = 1;
|
|
Packit Service |
c5cf8c |
MPIR_Add_finalize(MPIR_Bsend_finalize, (void *) 0, 10);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
BsendBuffer.origbuffer = buffer;
|
|
Packit Service |
c5cf8c |
BsendBuffer.origbuffer_size = buffer_size;
|
|
Packit Service |
c5cf8c |
BsendBuffer.buffer = buffer;
|
|
Packit Service |
c5cf8c |
BsendBuffer.buffer_size = buffer_size;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Make sure that the buffer that we use is aligned to align_sz. Some other
|
|
Packit Service |
c5cf8c |
* code assumes pointer-alignment, and some code assumes double alignment.
|
|
Packit Service |
c5cf8c |
* Further, GCC 4.5.1 generates bad code on 32-bit platforms when this is
|
|
Packit Service |
c5cf8c |
* only 4-byte aligned (see #1149). */
|
|
Packit Service |
c5cf8c |
align_sz = MPL_MAX(sizeof(void *), sizeof(double));
|
|
Packit Service |
c5cf8c |
offset = ((size_t) buffer) % align_sz;
|
|
Packit Service |
c5cf8c |
if (offset) {
|
|
Packit Service |
c5cf8c |
offset = align_sz - offset;
|
|
Packit Service |
c5cf8c |
buffer = (char *) buffer + offset;
|
|
Packit Service |
c5cf8c |
BsendBuffer.buffer = buffer;
|
|
Packit Service |
c5cf8c |
BsendBuffer.buffer_size -= offset;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
BsendBuffer.avail = buffer;
|
|
Packit Service |
c5cf8c |
BsendBuffer.pending = 0;
|
|
Packit Service |
c5cf8c |
BsendBuffer.active = 0;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Set the first block */
|
|
Packit Service |
c5cf8c |
p = (MPII_Bsend_data_t *) buffer;
|
|
Packit Service |
c5cf8c |
p->size = buffer_size - BSENDDATA_HEADER_TRUE_SIZE;
|
|
Packit Service |
c5cf8c |
p->total_size = buffer_size;
|
|
Packit Service |
c5cf8c |
p->next = p->prev = NULL;
|
|
Packit Service |
c5cf8c |
p->msg.msgbuf = (char *) p + BSENDDATA_HEADER_TRUE_SIZE;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* Detach a buffer. This routine must wait until any pending bsends
|
|
Packit Service |
c5cf8c |
* are complete. Note that MPI specifies the type of the returned "size"
|
|
Packit Service |
c5cf8c |
* argument as an "int" (the definition predates that of ssize_t as a
|
|
Packit Service |
c5cf8c |
* standard type).
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPIR_Bsend_detach
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
int MPIR_Bsend_detach(void *bufferp, int *size)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (BsendBuffer.pending) {
|
|
Packit Service |
c5cf8c |
/* FIXME: Process pending bsend requests in detach */
|
|
Packit Service |
c5cf8c |
return MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE,
|
|
Packit Service |
c5cf8c |
"MPIR_Bsend_detach", __LINE__, MPI_ERR_OTHER, "**bsendpending",
|
|
Packit Service |
c5cf8c |
0);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (BsendBuffer.active) {
|
|
Packit Service |
c5cf8c |
/* Loop through each active element and wait on it */
|
|
Packit Service |
c5cf8c |
MPII_Bsend_data_t *p = BsendBuffer.active;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
while (p) {
|
|
Packit Service |
c5cf8c |
MPI_Request r = p->request->handle;
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Wait(&r, MPI_STATUS_IGNORE);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
p = p->next;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Note that this works even when the buffer does not exist */
|
|
Packit Service |
c5cf8c |
*(void **) bufferp = BsendBuffer.origbuffer;
|
|
Packit Service |
c5cf8c |
/* This cast to int will work because the user must use an int to describe
|
|
Packit Service |
c5cf8c |
* the buffer size */
|
|
Packit Service |
c5cf8c |
*size = (int) BsendBuffer.origbuffer_size;
|
|
Packit Service |
c5cf8c |
BsendBuffer.origbuffer = NULL;
|
|
Packit Service |
c5cf8c |
BsendBuffer.origbuffer_size = 0;
|
|
Packit Service |
c5cf8c |
BsendBuffer.buffer = 0;
|
|
Packit Service |
c5cf8c |
BsendBuffer.buffer_size = 0;
|
|
Packit Service |
c5cf8c |
BsendBuffer.avail = 0;
|
|
Packit Service |
c5cf8c |
BsendBuffer.active = 0;
|
|
Packit Service |
c5cf8c |
BsendBuffer.pending = 0;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* Initiate an ibsend. We'll used this for Bsend as well.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPIR_Bsend_isend
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
int MPIR_Bsend_isend(const void *buf, int count, MPI_Datatype dtype,
|
|
Packit Service |
c5cf8c |
int dest, int tag, MPIR_Comm * comm_ptr,
|
|
Packit Service |
c5cf8c |
MPII_Bsend_kind_t kind, MPIR_Request ** request)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
MPII_Bsend_data_t *p;
|
|
Packit Service |
c5cf8c |
MPII_Bsend_msg_t *msg;
|
|
Packit Service |
c5cf8c |
MPI_Aint packsize;
|
|
Packit Service |
c5cf8c |
int pass;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Find a free segment and copy the data into it. If we could
|
|
Packit Service |
c5cf8c |
* have, we would already have used tBsend to send the message with
|
|
Packit Service |
c5cf8c |
* no copying.
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* We may want to decide here whether we need to pack at all
|
|
Packit Service |
c5cf8c |
* or if we can just use (a MPIR_Memcpy) of the buffer.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* We check the active buffer first. This helps avoid storage
|
|
Packit Service |
c5cf8c |
* fragmentation */
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Bsend_check_active();
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (dtype != MPI_PACKED)
|
|
Packit Service |
c5cf8c |
MPIR_Pack_size_impl(count, dtype, &packsize);
|
|
Packit Service |
c5cf8c |
else
|
|
Packit Service |
c5cf8c |
packsize = count;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG_D(MPIR_DBG_BSEND, TYPICAL, "looking for buffer of size " MPI_AINT_FMT_DEC_SPEC,
|
|
Packit Service |
c5cf8c |
packsize);
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* Use two passes. Each pass is the same; between the two passes,
|
|
Packit Service |
c5cf8c |
* attempt to complete any active requests, and start any pending
|
|
Packit Service |
c5cf8c |
* ones. If the message can be initiated in the first pass,
|
|
Packit Service |
c5cf8c |
* do not perform the second pass.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
for (pass = 0; pass < 2; pass++) {
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
p = MPIR_Bsend_find_buffer(packsize);
|
|
Packit Service |
c5cf8c |
if (p) {
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG_FMT(MPIR_DBG_BSEND, TYPICAL, (MPL_DBG_FDEST,
|
|
Packit Service |
c5cf8c |
"found buffer of size " MPI_AINT_FMT_DEC_SPEC
|
|
Packit Service |
c5cf8c |
" with address %p", packsize, p));
|
|
Packit Service |
c5cf8c |
/* Found a segment */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
msg = &p->msg;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Pack the data into the buffer */
|
|
Packit Service |
c5cf8c |
/* We may want to optimize for the special case of
|
|
Packit Service |
c5cf8c |
* either primative or contiguous types, and just
|
|
Packit Service |
c5cf8c |
* use MPIR_Memcpy and the provided datatype */
|
|
Packit Service |
c5cf8c |
msg->count = 0;
|
|
Packit Service |
c5cf8c |
if (dtype != MPI_PACKED) {
|
|
Packit Service |
c5cf8c |
mpi_errno =
|
|
Packit Service |
c5cf8c |
MPIR_Pack_impl(buf, count, dtype, p->msg.msgbuf, packsize, &p->msg.count);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
MPIR_Memcpy(p->msg.msgbuf, buf, count);
|
|
Packit Service |
c5cf8c |
p->msg.count = count;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
/* Try to send the message. We must use MPID_Isend
|
|
Packit Service |
c5cf8c |
* because this call must not block */
|
|
Packit Service |
c5cf8c |
mpi_errno = MPID_Isend(msg->msgbuf, msg->count, MPI_PACKED,
|
|
Packit Service |
c5cf8c |
dest, tag, comm_ptr, MPIR_CONTEXT_INTRA_PT2PT, &p->request);
|
|
Packit Service |
c5cf8c |
MPIR_ERR_CHKINTERNAL(mpi_errno, mpi_errno, "Bsend internal error: isend returned err");
|
|
Packit Service |
c5cf8c |
/* If the error is "request not available", we should
|
|
Packit Service |
c5cf8c |
* put this on the pending list. This will depend on
|
|
Packit Service |
c5cf8c |
* how we signal failure to send. */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (p->request) {
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG_FMT(MPIR_DBG_BSEND, TYPICAL,
|
|
Packit Service |
c5cf8c |
(MPL_DBG_FDEST, "saving request %p in %p", p->request, p));
|
|
Packit Service |
c5cf8c |
/* An optimization is to check to see if the
|
|
Packit Service |
c5cf8c |
* data has already been sent. The original code
|
|
Packit Service |
c5cf8c |
* to do this was commented out and probably did not match
|
|
Packit Service |
c5cf8c |
* the current request internals */
|
|
Packit Service |
c5cf8c |
MPIR_Bsend_take_buffer(p, p->msg.count);
|
|
Packit Service |
c5cf8c |
p->kind = kind;
|
|
Packit Service |
c5cf8c |
*request = p->request;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
/* If we found a buffer or we're in the seccond pass, then break.
|
|
Packit Service |
c5cf8c |
* Note that the test on phere is redundant, as the code breaks
|
|
Packit Service |
c5cf8c |
* out of the loop in the test above if a block p is found. */
|
|
Packit Service |
c5cf8c |
if (p || pass == 1)
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG(MPIR_DBG_BSEND, TYPICAL, "Could not find storage, checking active");
|
|
Packit Service |
c5cf8c |
/* Try to complete some pending bsends */
|
|
Packit Service |
c5cf8c |
MPIR_Bsend_check_active();
|
|
Packit Service |
c5cf8c |
/* Give priority to any pending operations */
|
|
Packit Service |
c5cf8c |
MPIR_Bsend_retry_pending();
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (!p) {
|
|
Packit Service |
c5cf8c |
/* Return error for no buffer space found */
|
|
Packit Service |
c5cf8c |
/* Generate a traceback of the allocated space, explaining why
|
|
Packit Service |
c5cf8c |
* packsize could not be found */
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG(MPIR_DBG_BSEND, TYPICAL, "Could not find space; dumping arena");
|
|
Packit Service |
c5cf8c |
MPL_DBG_STMT(MPIR_DBG_BSEND, TYPICAL, MPIR_Bsend_dump());
|
|
Packit Service |
c5cf8c |
MPIR_ERR_SETANDJUMP2(mpi_errno, MPI_ERR_BUFFER, "**bufbsend", "**bufbsend %d %d", packsize,
|
|
Packit Service |
c5cf8c |
BsendBuffer.buffer_size);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* The following routine looks up the segment used by request req
|
|
Packit Service |
c5cf8c |
* and frees it. The request is assumed to be completed. This routine
|
|
Packit Service |
c5cf8c |
* is called by only MPIR_Ibsend_free.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPIR_Bsend_free_seg
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
int MPIR_Bsend_free_req_seg(MPIR_Request * req)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_ERR_INTERN;
|
|
Packit Service |
c5cf8c |
MPII_Bsend_data_t *active = BsendBuffer.active;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG_P(MPIR_DBG_BSEND, TYPICAL, "Checking active starting at %p", active);
|
|
Packit Service |
c5cf8c |
while (active) {
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (active->request == req) {
|
|
Packit Service |
c5cf8c |
MPIR_Bsend_free_segment(active);
|
|
Packit Service |
c5cf8c |
mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
active = active->next;;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG_P(MPIR_DBG_BSEND, TYPICAL, "Next active is %p", active);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* The following routines are used to manage the allocation of bsend segments
|
|
Packit Service |
c5cf8c |
* in the user buffer. These routines handle, for example, merging segments
|
|
Packit Service |
c5cf8c |
* when an active segment that is adjacent to a free segment becomes free.
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Add block p to the free list. Merge into adjacent blocks. Used only
|
|
Packit Service |
c5cf8c |
within the check_active */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPIR_Bsend_free_segment
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
static void MPIR_Bsend_free_segment(MPII_Bsend_data_t * p)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
MPII_Bsend_data_t *prev = p->prev, *avail = BsendBuffer.avail, *avail_prev;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG_FMT(MPIR_DBG_BSEND, TYPICAL, (MPL_DBG_FDEST,
|
|
Packit Service |
c5cf8c |
"Freeing bsend segment at %p of size %llu, next at %p",
|
|
Packit Service |
c5cf8c |
p, (unsigned long long) p->size,
|
|
Packit Service |
c5cf8c |
((char *) p) + p->total_size));
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG_D(MPIR_DBG_BSEND, TYPICAL,
|
|
Packit Service |
c5cf8c |
"At the begining of free_segment with size %llu:",
|
|
Packit Service |
c5cf8c |
(unsigned long long) p->total_size);
|
|
Packit Service |
c5cf8c |
MPL_DBG_STMT(MPIR_DBG_BSEND, TYPICAL, MPIR_Bsend_dump());
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Remove the segment from the active list */
|
|
Packit Service |
c5cf8c |
if (prev) {
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG(MPIR_DBG_BSEND, TYPICAL, "free segment is within active list");
|
|
Packit Service |
c5cf8c |
prev->next = p->next;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
/* p was at the head of the active list */
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG(MPIR_DBG_BSEND, TYPICAL, "free segment is head of active list");
|
|
Packit Service |
c5cf8c |
BsendBuffer.active = p->next;
|
|
Packit Service |
c5cf8c |
/* The next test sets the prev pointer to null */
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (p->next) {
|
|
Packit Service |
c5cf8c |
p->next->prev = prev;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPL_DBG_STMT(MPIR_DBG_BSEND, VERBOSE, MPIR_Bsend_dump());
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Merge into the avail list */
|
|
Packit Service |
c5cf8c |
/* Find avail_prev, avail, such that p is between them.
|
|
Packit Service |
c5cf8c |
* either may be null if p is at either end of the list */
|
|
Packit Service |
c5cf8c |
avail_prev = 0;
|
|
Packit Service |
c5cf8c |
while (avail) {
|
|
Packit Service |
c5cf8c |
if (avail > p) {
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
avail_prev = avail;
|
|
Packit Service |
c5cf8c |
avail = avail->next;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Try to merge p with the next block */
|
|
Packit Service |
c5cf8c |
if (avail) {
|
|
Packit Service |
c5cf8c |
if ((char *) p + p->total_size == (char *) avail) {
|
|
Packit Service |
c5cf8c |
p->total_size += avail->total_size;
|
|
Packit Service |
c5cf8c |
p->size = p->total_size - BSENDDATA_HEADER_TRUE_SIZE;
|
|
Packit Service |
c5cf8c |
p->next = avail->next;
|
|
Packit Service |
c5cf8c |
if (avail->next)
|
|
Packit Service |
c5cf8c |
avail->next->prev = p;
|
|
Packit Service |
c5cf8c |
avail = 0;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
p->next = avail;
|
|
Packit Service |
c5cf8c |
avail->prev = p;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
p->next = 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
/* Try to merge p with the previous block */
|
|
Packit Service |
c5cf8c |
if (avail_prev) {
|
|
Packit Service |
c5cf8c |
if ((char *) avail_prev + avail_prev->total_size == (char *) p) {
|
|
Packit Service |
c5cf8c |
avail_prev->total_size += p->total_size;
|
|
Packit Service |
c5cf8c |
avail_prev->size = avail_prev->total_size - BSENDDATA_HEADER_TRUE_SIZE;
|
|
Packit Service |
c5cf8c |
avail_prev->next = p->next;
|
|
Packit Service |
c5cf8c |
if (p->next)
|
|
Packit Service |
c5cf8c |
p->next->prev = avail_prev;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
avail_prev->next = p;
|
|
Packit Service |
c5cf8c |
p->prev = avail_prev;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
/* p is the new head of the list */
|
|
Packit Service |
c5cf8c |
BsendBuffer.avail = p;
|
|
Packit Service |
c5cf8c |
p->prev = 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG(MPIR_DBG_BSEND, TYPICAL, "At the end of free_segment:");
|
|
Packit Service |
c5cf8c |
MPL_DBG_STMT(MPIR_DBG_BSEND, TYPICAL, MPIR_Bsend_dump());
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* The following routine tests for completion of active sends and
|
|
Packit Service |
c5cf8c |
* frees the related storage
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* To make it easier to identify the source of the request, we keep
|
|
Packit Service |
c5cf8c |
* track of the type of MPI routine (ibsend, bsend, or bsend_init/start)
|
|
Packit Service |
c5cf8c |
* that created the bsend entry.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPIR_Bsend_check_active
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
static int MPIR_Bsend_check_active(void)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
MPII_Bsend_data_t *active = BsendBuffer.active, *next_active;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG_P(MPIR_DBG_BSEND, TYPICAL, "Checking active starting at %p", active);
|
|
Packit Service |
c5cf8c |
while (active) {
|
|
Packit Service |
c5cf8c |
MPI_Request r = active->request->handle;
|
|
Packit Service |
c5cf8c |
int flag;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
next_active = active->next;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (active->kind == IBSEND) {
|
|
Packit Service |
c5cf8c |
/* We handle ibsend specially to allow for the user
|
|
Packit Service |
c5cf8c |
* to attempt and cancel the request. Also, to allow
|
|
Packit Service |
c5cf8c |
* for a cancel attempt (which must be attempted before
|
|
Packit Service |
c5cf8c |
* a successful test or wait), we only start
|
|
Packit Service |
c5cf8c |
* testing when the user has successfully released
|
|
Packit Service |
c5cf8c |
* the request (it is a grequest, the free call will do it) */
|
|
Packit Service |
c5cf8c |
flag = 0;
|
|
Packit Service |
c5cf8c |
/* XXX DJG FIXME-MT should we be checking this? */
|
|
Packit Service |
c5cf8c |
if (MPIR_Object_get_ref(active->request) == 1) {
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Test(&r, &flag, MPI_STATUS_IGNORE);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
/* We need to invoke the progress engine in case we
|
|
Packit Service |
c5cf8c |
* need to advance other, incomplete communication. */
|
|
Packit Service |
c5cf8c |
MPID_Progress_state progress_state;
|
|
Packit Service |
c5cf8c |
MPID_Progress_start(&progress_state);
|
|
Packit Service |
c5cf8c |
mpi_errno = MPID_Progress_test();
|
|
Packit Service |
c5cf8c |
MPID_Progress_end(&progress_state);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Test(&r, &flag, MPI_STATUS_IGNORE);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (flag) {
|
|
Packit Service |
c5cf8c |
/* We're done. Remove this segment */
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG_P(MPIR_DBG_BSEND, TYPICAL, "Removing segment %p", active);
|
|
Packit Service |
c5cf8c |
MPIR_Bsend_free_segment(active);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
active = next_active;
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG_P(MPIR_DBG_BSEND, TYPICAL, "Next active is %p", active);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* FIXME : For each pending item (that is, items that we couldn't even start
|
|
Packit Service |
c5cf8c |
* sending), try to get them going.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
static void MPIR_Bsend_retry_pending(void)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
MPII_Bsend_data_t *pending = BsendBuffer.pending, *next_pending;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
while (pending) {
|
|
Packit Service |
c5cf8c |
next_pending = pending->next;
|
|
Packit Service |
c5cf8c |
/* Retry sending this item */
|
|
Packit Service |
c5cf8c |
/* FIXME: Unimplemented retry of pending bsend operations */
|
|
Packit Service |
c5cf8c |
pending = next_pending;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* Find a slot in the avail buffer that can hold size bytes. Does *not*
|
|
Packit Service |
c5cf8c |
* remove the slot from the avail buffer (see MPIR_Bsend_take_buffer)
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
static MPII_Bsend_data_t *MPIR_Bsend_find_buffer(size_t size)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
MPII_Bsend_data_t *p = BsendBuffer.avail;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
while (p) {
|
|
Packit Service |
c5cf8c |
if (p->size >= size) {
|
|
Packit Service |
c5cf8c |
return p;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
p = p->next;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* This is the minimum number of bytes that a segment must be able to
|
|
Packit Service |
c5cf8c |
hold. */
|
|
Packit Service |
c5cf8c |
#define MIN_BUFFER_BLOCK 8
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* Carve off size bytes from buffer p and leave the remainder
|
|
Packit Service |
c5cf8c |
* on the avail list. Handle the head/tail cases.
|
|
Packit Service |
c5cf8c |
* If there isn't enough left of p, remove the entire segment from
|
|
Packit Service |
c5cf8c |
* the avail list.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
static void MPIR_Bsend_take_buffer(MPII_Bsend_data_t * p, size_t size)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
MPII_Bsend_data_t *prev;
|
|
Packit Service |
c5cf8c |
size_t alloc_size;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Compute the remaining size. This must include any padding
|
|
Packit Service |
c5cf8c |
* that must be added to make the new block properly aligned */
|
|
Packit Service |
c5cf8c |
alloc_size = size;
|
|
Packit Service |
c5cf8c |
if (alloc_size & 0x7)
|
|
Packit Service |
c5cf8c |
alloc_size += (8 - (alloc_size & 0x7));
|
|
Packit Service |
c5cf8c |
/* alloc_size is the amount of space (out of size) that we will
|
|
Packit Service |
c5cf8c |
* allocate for this buffer. */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG_FMT(MPIR_DBG_BSEND, TYPICAL, (MPL_DBG_FDEST,
|
|
Packit Service |
c5cf8c |
"Taking %lu bytes from a block with %llu bytes\n",
|
|
Packit Service |
c5cf8c |
alloc_size, (unsigned long long) p->total_size));
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Is there enough space left to create a new block? */
|
|
Packit Service |
c5cf8c |
if (alloc_size + BSENDDATA_HEADER_TRUE_SIZE + MIN_BUFFER_BLOCK <= p->size) {
|
|
Packit Service |
c5cf8c |
/* Yes, the available space (p->size) is large enough to
|
|
Packit Service |
c5cf8c |
* carve out a new block */
|
|
Packit Service |
c5cf8c |
MPII_Bsend_data_t *newp;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG_P(MPIR_DBG_BSEND, TYPICAL, "Breaking block into used and allocated at %p", p);
|
|
Packit Service |
c5cf8c |
newp = (MPII_Bsend_data_t *) ((char *) p + BSENDDATA_HEADER_TRUE_SIZE + alloc_size);
|
|
Packit Service |
c5cf8c |
newp->total_size = p->total_size - alloc_size - BSENDDATA_HEADER_TRUE_SIZE;
|
|
Packit Service |
c5cf8c |
newp->size = newp->total_size - BSENDDATA_HEADER_TRUE_SIZE;
|
|
Packit Service |
c5cf8c |
newp->msg.msgbuf = (char *) newp + BSENDDATA_HEADER_TRUE_SIZE;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Insert this new block after p (we'll remove p from the avail list
|
|
Packit Service |
c5cf8c |
* next) */
|
|
Packit Service |
c5cf8c |
newp->next = p->next;
|
|
Packit Service |
c5cf8c |
newp->prev = p;
|
|
Packit Service |
c5cf8c |
if (p->next) {
|
|
Packit Service |
c5cf8c |
p->next->prev = newp;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
p->next = newp;
|
|
Packit Service |
c5cf8c |
p->total_size = (char *) newp - (char *) p;
|
|
Packit Service |
c5cf8c |
p->size = p->total_size - BSENDDATA_HEADER_TRUE_SIZE;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG_FMT(MPIR_DBG_BSEND, TYPICAL, (MPL_DBG_FDEST,
|
|
Packit Service |
c5cf8c |
"broken blocks p (%llu) and new (%llu)\n",
|
|
Packit Service |
c5cf8c |
(unsigned long long) p->total_size,
|
|
Packit Service |
c5cf8c |
(unsigned long long) newp->total_size));
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Remove p from the avail list and add it to the active list */
|
|
Packit Service |
c5cf8c |
prev = p->prev;
|
|
Packit Service |
c5cf8c |
if (prev) {
|
|
Packit Service |
c5cf8c |
prev->next = p->next;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
BsendBuffer.avail = p->next;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (p->next) {
|
|
Packit Service |
c5cf8c |
p->next->prev = p->prev;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (BsendBuffer.active) {
|
|
Packit Service |
c5cf8c |
BsendBuffer.active->prev = p;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
p->next = BsendBuffer.active;
|
|
Packit Service |
c5cf8c |
p->prev = 0;
|
|
Packit Service |
c5cf8c |
BsendBuffer.active = p;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG_P(MPIR_DBG_BSEND, VERBOSE, "segment %p now head of active", p);
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG(MPIR_DBG_BSEND, TYPICAL, "At end of take buffer");
|
|
Packit Service |
c5cf8c |
MPL_DBG_STMT(MPIR_DBG_BSEND, TYPICAL, MPIR_Bsend_dump());
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int MPIR_Bsend_finalize(void *p ATTRIBUTE((unused)))
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
void *b;
|
|
Packit Service |
c5cf8c |
int s;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPL_UNREFERENCED_ARG(p);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (BsendBuffer.buffer) {
|
|
Packit Service |
c5cf8c |
/* Use detach to complete any communication */
|
|
Packit Service |
c5cf8c |
MPIR_Bsend_detach(&b, &s);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* These routines are defined only if debug logging is enabled
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
#ifdef MPL_USE_DBG_LOGGING
|
|
Packit Service |
c5cf8c |
static void MPIR_Bsend_dump(void)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
MPII_Bsend_data_t *a = BsendBuffer.avail;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG_D(MPIR_DBG_BSEND, TYPICAL, "Total size is %llu",
|
|
Packit Service |
c5cf8c |
(unsigned long long) BsendBuffer.buffer_size);
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG(MPIR_DBG_BSEND, TYPICAL, "Avail list is:");
|
|
Packit Service |
c5cf8c |
while (a) {
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG_FMT(MPIR_DBG_BSEND, TYPICAL, (MPL_DBG_FDEST, "[%p] totalsize = %llu(%llx)",
|
|
Packit Service |
c5cf8c |
a, (unsigned long long) a->total_size,
|
|
Packit Service |
c5cf8c |
(unsigned long long) a->total_size));
|
|
Packit Service |
c5cf8c |
if (a == a->next) {
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG(MPIR_DBG_BSEND, TYPICAL, "@@@Corrupt list; avail block points at itself");
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
a = a->next;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG(MPIR_DBG_BSEND, TYPICAL, "Active list is:");
|
|
Packit Service |
c5cf8c |
a = BsendBuffer.active;
|
|
Packit Service |
c5cf8c |
while (a) {
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG_FMT(MPIR_DBG_BSEND, TYPICAL, (MPL_DBG_FDEST, "[%p] totalsize = %llu(%llx)",
|
|
Packit Service |
c5cf8c |
a, (unsigned long long) a->total_size,
|
|
Packit Service |
c5cf8c |
(unsigned long long) a->total_size));
|
|
Packit Service |
c5cf8c |
if (a == a->next) {
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG(MPIR_DBG_BSEND, TYPICAL, "@@@Corrupt list; active block points at itself");
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
a = a->next;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG(MPIR_DBG_BSEND, TYPICAL, "end of list");
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
#endif
|