#include "BSprivate.h"
/* ******************************************************************* */
/* Routines for building, manipulating, and using the compiled message */
/* passing routines. */
/* ******************************************************************* */
/*+ BMcomp_init - Initialize a compiled message structure.
Input Parameters:
. base_type - The base number for message types in this structure.
See BMmsg.h for more information on base_type.
Returns:
pointer to the compiled message structure
+*/
BMcomp_msg *BMcomp_init(int base_type)
{
BMcomp_msg *ph_ptr;
MY_MALLOCN(ph_ptr,(BMcomp_msg *),sizeof(BMcomp_msg),1);
ph_ptr->num_phases = 0;
ph_ptr->num_msgs = 0;
ph_ptr->base_type = base_type;
ph_ptr->phase_list = NULL;
return(ph_ptr);
}
/*+ BMfree_comp_msg - Free a compiled message structure.
Input Parameters:
. comp_msg - Pointer to compiled message structure to free
Returns: void
+*/
void BMfree_comp_msg(BMcomp_msg *comp_msg)
{
BMphase *phase_ptr;
BMmsg *msg_ptr;
while (comp_msg->phase_list != NULL) {
/* free a phase */
phase_ptr = comp_msg->phase_list;
comp_msg->phase_list = comp_msg->phase_list->next;
while (phase_ptr->msg_list != NULL) {
/* free a msg */
msg_ptr = phase_ptr->msg_list;
phase_ptr->msg_list = phase_ptr->msg_list->next;
BMfree_user_data(msg_ptr); CHKERR(0);
BMfree_setup_data(msg_ptr); CHKERR(0);
if (msg_ptr->msg != NULL) {
MY_FREE(msg_ptr->msg);
}
MY_FREE(msg_ptr);
}
MY_FREE(phase_ptr);
}
MY_FREE(comp_msg);
}
/*+ BMget_phase - Get a pointer to a particular message phase.
Input Parameters:
. comp_msg - The compiled message structure
. phase_num - the phase number point to find
Returns:
pointer to the phase list or NULL if not found
+*/
BMphase *BMget_phase(BMcomp_msg *comp_msg, int phase_num)
{
BMphase *phase_ptr;
phase_ptr = comp_msg->phase_list;
while (phase_ptr != NULL) {
if (phase_ptr->phase == phase_num) {
return(phase_ptr);
}
phase_ptr = phase_ptr->next;
}
return(phase_ptr);
}
/*+ BMadd_msg - Insert a message into the structure.
Input Parameters:
. comp_msg - The compiled message structure
. phase_num - a pointer to the message
. procinfo - information about the processor number, etc.
Returns:
void
+*/
void BMadd_msg(BMcomp_msg *comp_msg, BMmsg *msg_ptr, BSprocinfo *procinfo)
{
BMphase *phase_ptr, *prev;
int found;
BMmsg *cur_msg;
/* do we need to generate a msg number? */
if (msg_ptr->msg_type < 0) {
if (comp_msg->num_msgs >= MAX_NUM_MSGS) {
MY_SETERRC(MSG_ERROR,"Too many messages in comp_msg\n");
}
msg_ptr->msg_type = comp_msg->base_type + comp_msg->num_msgs +
procinfo->my_id*MAX_NUM_MSGS;
}
comp_msg->num_msgs++;
/* find the phase, if possible */
phase_ptr = comp_msg->phase_list;
prev = phase_ptr;
found = FALSE;
while (phase_ptr != NULL) {
if (phase_ptr->phase == msg_ptr->phase) {
/* put the msg at the end of the list */
cur_msg = phase_ptr->end_msg_list;
phase_ptr->end_msg_list = msg_ptr;
cur_msg->next = msg_ptr;
msg_ptr->next = NULL;
found = TRUE;
break;
}
if (phase_ptr->phase > msg_ptr->phase) break;
prev = phase_ptr;
phase_ptr = phase_ptr->next;
}
/* did not find phase, must create it */
if (!found) {
comp_msg->num_phases++;
if (phase_ptr == comp_msg->phase_list) {
MY_MALLOC(comp_msg->phase_list,(BMphase *),sizeof(BMphase),1);
comp_msg->phase_list->phase = msg_ptr->phase;
comp_msg->phase_list->msg_list = msg_ptr;
comp_msg->phase_list->end_msg_list = msg_ptr;
comp_msg->phase_list->cur_msg = NULL;
comp_msg->phase_list->cur_list_ptr = NULL;
comp_msg->phase_list->cur_recv_msg = NULL;
comp_msg->phase_list->async_list = NULL;
msg_ptr->next = NULL;
comp_msg->phase_list->next = prev;
} else {
MY_MALLOC(phase_ptr,(BMphase *),sizeof(BMphase),1);
phase_ptr->phase = msg_ptr->phase;
phase_ptr->msg_list = msg_ptr;
phase_ptr->end_msg_list = msg_ptr;
phase_ptr->next = prev->next;
phase_ptr->cur_msg = NULL;
phase_ptr->cur_list_ptr = NULL;
phase_ptr->async_list = NULL;
phase_ptr->cur_recv_msg = NULL;
prev->next = phase_ptr;
msg_ptr->next = NULL;
}
}
}
/*+ BMcreate_msg - Create a message
Input Parameters:
. phase - the message phase number
. msg_type - the message type
. msg_data_type - the data type of the message (see tools)
. proc - the processor to send to/from
Returns:
pointer to the new message data structure
+*/
BMmsg *BMcreate_msg(int phase, int msg_type, MPI_Datatype msg_data_type,
int proc)
{
BMmsg *msg;
MY_MALLOCN(msg,(BMmsg *),sizeof(BMmsg),1);
msg->phase = phase;
msg->msg_type = msg_type;
msg->msg_data_type = msg_data_type;
msg->status = COMPLETED;
msg->proc = proc;
msg->msg = NULL;
BMinit_user(&(msg->user_data)); CHKERRN(0);
BMinit_user(&(msg->setup_data)); CHKERRN(0);
return(msg);
}
/*+ BMget_msg_size - Return the size of a message (in number of elements)
Input Parameters:
. msg - pointer to a message
Returns:
the message size in number of elements
+*/
int BMget_msg_size(BMmsg *msg)
{
return(msg->size);
}
/*+ BMset_msg_size - Set the size of a message (in number of elements)
Input Parameters:
. msg - pointer to a message
. size - the message size (in number of elements)
Returns:
void
+*/
void BMset_msg_size(BMmsg *msg, int size)
{
msg->size = size;
}
/*+ BMinit_user - Initialize the user data structure
Input Parameters:
. user_data - pointer to the user_data structure
Returns:
void
+*/
void BMinit_user(BMuser_data *user_data)
{
user_data->data = NULL;
user_data->length = 0;
user_data->free_data = NULL;
}
/*+ BMfree_user - Free the user data structure
Input Parameters:
. user_data - pointer to the user_data structure
Returns:
void
+*/
void BMfree_user(BMuser_data *user_data)
{
if (user_data->free_data != NULL) {
(*user_data->free_data)(user_data->data); CHKERR(0);
}
user_data->data = NULL;
user_data->length = 0;
user_data->free_data = NULL;
}
/*+ BMfree_user_data - Free the user's data (from the message structure)
Input Parameters:
. msg - pointer to the message
Returns:
void
+*/
void BMfree_user_data(BMmsg *msg)
{
BMfree_user(&(msg->user_data)); CHKERR(0);
}
/*+ BMfree_setup_data - Free the user's setup data (from the message structure)
Input Parameters:
. msg - pointer to the message
Returns:
void
+*/
void BMfree_setup_data(BMmsg *msg)
{
BMfree_user(&(msg->setup_data)); CHKERR(0);
}
/*+ BMset_user - Set the user data structure
Input Parameters:
. user_data - pointer to the user data structure
. data - pointer to the user's data
. length - the length of the user data
. fcn - the function to free the user data
Returns:
void
+*/
void BMset_user(BMuser_data *user_data, int *data, int length, void (*fcn)(int *))
{
user_data->data = data;
user_data->length = length;
user_data->free_data = fcn;
}
/*+ BMset_user_data - Set the user data structure (in a message)
Input Parameters:
. msg - pointer to the message
. data - pointer to the user's data
. length - the length of the user data
. fcn - the function to free the user data
Returns:
void
+*/
void BMset_user_data(BMmsg *msg, int *data, int length, void (*fcn)(int *))
{
BMset_user(&(msg->user_data),data,length,fcn); CHKERR(0);
}
/*+ BMset_setup_data - Set the user's setup data structure (in a message)
Input Parameters:
. msg - pointer to the message
. data - pointer to the user's data
. length - the length of the user data
. fcn - the function to free the user data
Returns:
void
+*/
void BMset_setup_data(BMmsg *msg, int *data, int length, void (*fcn)(int *))
{
BMset_user(&(msg->setup_data),data,length,fcn); CHKERR(0);
}
/*+ BMget_user - Return the user's data and it's length
Input Parameters:
. msg - pointer to a message
Output Parameters:
. length - pointer to the length of the message
Returns:
pointer to the user data
+*/
int *BMget_user(BMmsg *msg, int *length)
{
(*length) = msg->user_data.length;
return(msg->user_data.data);
}
/*+ BMget_setup - Return the user's setup data and it's length
Input Parameters:
. msg - pointer to a message
Output Parameters:
. length - pointer to the length of the message
Returns:
pointer to the user data
+*/
int *BMget_setup(BMmsg *msg, int *length)
{
(*length) = msg->setup_data.length;
return(msg->setup_data.data);
}
/*+ BMset_msg_ptr - Give the message structure a pointer to the space
allocated for the message data.
Input Parameters:
. msg - pointer to a message
. msg_ptr - pointer to the space for the message
Returns:
void
+*/
void BMset_msg_ptr(BMmsg *msg, void *msg_ptr)
{
msg->msg = msg_ptr;
}
/*+ BMget_msg_ptr - Get the pointer to the message data.
Input Parameters:
. msg - pointer to a message
Returns:
pointer to the message data
+*/
void *BMget_msg_ptr(BMmsg *msg)
{
return(msg->msg);
}
/*+ BMnext_msg - Get the next message in this phase
Input Parameters:
. phase_ptr - pointer to the phase
. msg_ptr - pointer to a message
Returns:
pointer to the next message (NULL if none)
+*/
BMmsg *BMnext_msg(BMphase *phase_ptr, BMmsg *msg_ptr)
{
if (phase_ptr == NULL) return(NULL);
if (msg_ptr == NULL) {
msg_ptr = phase_ptr->msg_list;
} else {
msg_ptr = msg_ptr->next;
}
return(msg_ptr);
}
/*+ BMalloc_msg - Pre-allocate messages for the compiled message structure
Input Parameters:
. comp_msg - pointer to the compiled message structure
+*/
void BMalloc_msg(BMcomp_msg *comp_msg)
{
BMphase *phase_ptr;
BMmsg *msg_ptr;
int type_size;
for (phase_ptr=comp_msg->phase_list;phase_ptr != NULL;
phase_ptr=phase_ptr->next) {
for (msg_ptr=phase_ptr->msg_list;msg_ptr!=NULL;msg_ptr=msg_ptr->next) {
if (msg_ptr->msg == NULL) {
MPI_Type_size(msg_ptr->msg_data_type,(MPI_Aint *)&type_size);
MY_MALLOC(msg_ptr->msg,(char *),
type_size*msg_ptr->size,1);
}
}
}
}
/*+ BMfix_send - Decide what must be sent when
Input Parameters:
. msg_type - message type for the use of BMfix_send
. comp_msg_type - base type for the compiled message structure
. comp_msg_data_type - message data type for the compiled message structure
. (see tools)
. comp_msg - pointer to the compiled message structure
. phase_ptr - pointer to the phase to work on
. free_fcn - pointer to function to free user data
. procinfo - the usual processor information
Returns:
the number of messages to be sent
+*/
int BMfix_send(int msg_type, int comp_msg_type, MPI_Datatype comp_msg_data_type,
BMcomp_msg *comp_msg, BMphase *phase_ptr, void (*free_fcn)(int *),
BSprocinfo *procinfo)
{
BMmsg *msg_ptr;
int size, from, msg_len;
int i, source_len, *t_msg;
int *addr, *source;
BSmsg_list *msg_list;
int num_to_recv, num_recved;
int *tot_num_msg, *tot_num_msg2, *iwork, *tot_len;
int **msg, **cur_msg_ptr;
int cur_size;
int *int_msg;
int consumed;
int np;
MPI_Status mpi_status;
void *in_msg;
msg_list = NULL;
/* sync up to avoid problems */
GSYNC(procinfo->procset);
np = procinfo->nprocs;
MY_MALLOCN(tot_num_msg,(int *),sizeof(int)*np,0);
MY_MALLOCN(tot_num_msg2,(int *),sizeof(int)*np,0);
MY_MALLOCN(tot_len,(int *),sizeof(int)*np,1);
MY_MALLOCN(msg,(int **),sizeof(int *)*np,3);
MY_MALLOCN(cur_msg_ptr,(int **),sizeof(int *)*np,3);
MY_MALLOCN(iwork,(int *),sizeof(int)*np,2);
for (i=0;i<np;i++) {
tot_num_msg[i] = 0;
tot_num_msg2[i] = 0;
tot_len[i] = 0;
msg[i] = NULL;
}
if (phase_ptr != NULL) {
for (msg_ptr=phase_ptr->msg_list;msg_ptr!=NULL;msg_ptr=msg_ptr->next) {
source = BMget_setup(msg_ptr,&source_len); CHKERRN(0);
msg_len = source_len + 3;
tot_num_msg[msg_ptr->proc]++;
tot_num_msg2[msg_ptr->proc]++;
tot_len[msg_ptr->proc] += msg_len;
}
}
GISUM(tot_num_msg2,np,iwork,procinfo->procset);
num_to_recv = tot_num_msg2[procinfo->my_id];
MY_FREE(iwork);
MY_FREE(tot_num_msg2);
/* tell the people who you want stuff from, that you want it */
if (phase_ptr != NULL) {
for (msg_ptr=phase_ptr->msg_list;msg_ptr!=NULL;msg_ptr=msg_ptr->next) {
source = BMget_setup(msg_ptr,&source_len); CHKERRN(0);
msg_len = source_len + 3;
if (msg[msg_ptr->proc] == NULL) {
MY_MALLOCN(t_msg,(int *),tot_len[msg_ptr->proc]*sizeof(int),5);
msg[msg_ptr->proc] = t_msg;
cur_msg_ptr[msg_ptr->proc] = t_msg;
} else {
t_msg = cur_msg_ptr[msg_ptr->proc];
}
cur_msg_ptr[msg_ptr->proc] += msg_len;
t_msg[0] = msg_ptr->phase;
t_msg[1] = msg_ptr->msg_type;
t_msg[2] = msg_len;
for (i=0;i<source_len;i++) {
t_msg[3+i] = source[i];
}
tot_num_msg[msg_ptr->proc]--;
if (tot_num_msg[msg_ptr->proc] == 0) {
MY_SEND_SYNC(msg_list,msg_type,msg[msg_ptr->proc],
tot_len[msg_ptr->proc],(msg_ptr->proc),MPI_INT,procinfo);
MY_FREE(msg[msg_ptr->proc]);
}
}
}
MY_FREE(tot_num_msg);
MY_FREE(tot_len);
MY_FREE(msg);
MY_FREE(cur_msg_ptr);
/* now wait for msgs from people */
num_recved = 0;
while (num_recved < num_to_recv) {
/* receive a message */
RECVSYNCUNSZN(msg_type,in_msg,size,MPI_INT,procinfo,mpi_status);
CHKERRN(0);
from = mpi_status.MPI_SOURCE;
CHECK_SEND_LIST(msg_list);
int_msg = (int *)in_msg;
consumed = 0;
while (consumed < size) {
cur_size = int_msg[2];
/* if no message number, then create one */
if (int_msg[1] < 0) {
int_msg[1] = num_recved + comp_msg_type;
}
msg_ptr = BMcreate_msg(int_msg[0],int_msg[1],comp_msg_data_type,
from); CHKERRN(0);
BMadd_msg(comp_msg,msg_ptr,procinfo); CHKERRN(0);
/* copy user data from message */
MY_MALLOCN(addr,(int *),(cur_size-3)*sizeof(int),6);
for (i=0;i<cur_size-3;i++) {
addr[i] = int_msg[i+3];
}
BMset_user_data(msg_ptr,addr,cur_size-3,free_fcn);
CHKERRN(0);
consumed += cur_size;
int_msg += cur_size;
num_recved++;
}
MSGFREERECV(in_msg);CHKERRN(0);
}
FINISH_SEND_LIST(msg_list);
/* return the number of messages that were created */
return(num_recved);
}
/*+ BMinit_comp_msg - Post receives for all messages in this structure
Input Parameters:
. comp_msg - pointer to the message structure
. procinfo - the usual processor information
Returns:
void
+*/
void BMinit_comp_msg(BMcomp_msg *comp_msg, BSprocinfo *procinfo)
{
BMphase *phase_ptr;
BMmsg *msg_ptr;
for (phase_ptr=comp_msg->phase_list;phase_ptr!=NULL;
phase_ptr=phase_ptr->next) {
for (msg_ptr=phase_ptr->msg_list;msg_ptr!=NULL;msg_ptr=msg_ptr->next) {
msg_ptr->status = NOT_COMPLETED;
if (msg_ptr->msg != NULL) {
RECVASYNCNOMEMFORCE(msg_ptr->msg_type,msg_ptr->msg,
msg_ptr->size,msg_ptr->msg_data_type,
msg_ptr->recv_id,procinfo); CHKERR(0);
}
}
}
GSYNC(procinfo->procset);
}
/*+ BMfinish_comp_msg - Clean up after using message structure
Input Parameters:
. comp_msg - pointer to the message structure
. procinfo - the usual processor information
Returns:
void
+*/
void BMfinish_comp_msg(BMcomp_msg *comp_msg, BSprocinfo *procinfo)
{
BMphase *phase_ptr;
BMmsg *msg_ptr;
for (phase_ptr=comp_msg->phase_list;phase_ptr!=NULL;
phase_ptr=phase_ptr->next) {
for (msg_ptr=phase_ptr->msg_list;msg_ptr!=NULL;msg_ptr=msg_ptr->next) {
if ((msg_ptr->msg != NULL) && (msg_ptr->status != COMPLETED)) {
SENDWAITNOMEM(msg_ptr->msg_type,msg_ptr->msg,msg_ptr->size,
msg_ptr->proc,msg_ptr->msg_data_type,msg_ptr->send_id);
CHKERR(0);
msg_ptr->status = COMPLETED;
}
}
}
}
/*+ BMsendf_msg - Send a message as a "forced" message
Input Parameters:
. msg - pointer to a message
. procinfo - information about the processor number, etc.
Returns:
void
+*/
void BMsendf_msg(BMmsg *msg, BSprocinfo *procinfo)
{
SENDASYNCNOMEMFORCE(msg->msg_type,msg->msg,msg->size,msg->proc,
msg->msg_data_type,msg->send_id,procinfo);
msg->status = NOT_COMPLETED;
CHKERR(0);
}
/*+ BMcheck_on_async_block(phase_ptr)
Input Parameters:
. phase_ptr -- pointer to the current phase
Returns:
void
+*/
void BMcheck_on_async_block(BMphase *phase_ptr)
{
if (phase_ptr != NULL) {
MCHECK_SEND_LIST(phase_ptr->async_list);
}
}
/*+ BMfinish_on_async_block(phase_ptr)
Input Parameters:
. phase_ptr -- pointer to the current phase
Returns:
void
+*/
void BMfinish_on_async_block(BMphase *phase_ptr)
{
if (phase_ptr != NULL) {
MFINISH_SEND_LIST(phase_ptr->async_list);
}
}
#define TRUE_MSG_LEN(msg_len) \
(((int)((msg_len+sizeof(int))/sizeof(FLOAT)))*sizeof(FLOAT))
/*+ BMsend_block_msg - Send a message and try to group with others
Input Parameters:
. phase_ptr -- pointer to the current phase
. msg - pointer to a message
. procinfo - information about the processor number, etc.
Returns:
void
+*/
void BMsend_block_msg(BMphase *phase_ptr, BMmsg *msg, BSprocinfo *procinfo)
{
int *int_msg;
char *char_msg, *ochar_msg;
BSmsg_list *msg_list_node;
int i;
int *tint1;
/* this really shouldn't happen */
if (phase_ptr == NULL) return;
/* this means we should send off the pending message, if it exists */
if (msg == NULL) {
if (phase_ptr->cur_msg != NULL) {
msg_list_node = phase_ptr->cur_msg;
phase_ptr->cur_msg = NULL;
msg_list_node->next = phase_ptr->async_list;
phase_ptr->async_list = msg_list_node;
SENDASYNCNOMEM(msg_list_node->msg_type,msg_list_node->msg_buf,
msg_list_node->msg_len,msg_list_node->msg_to,
msg_list_node->msg_data_type,msg_list_node->msg_id,procinfo);
CHKERR(0);
}
return;
}
/* check to see if any of the messages have been sent */
MCHECK_SEND_LIST(phase_ptr->async_list);
if (phase_ptr->cur_msg != NULL) {
msg_list_node = phase_ptr->cur_msg;
/* check to see if the destination of the message in cur_msg is the */
/* same as the message to be sent, if not, then clear cur_msg */
/* same thing if there isn't enough room for the message */
if ((msg->proc != msg_list_node->msg_to) ||
(msg->size+sizeof(FLOAT)+TRUE_MSG_LEN(msg_list_node->msg_len) >
PREFER_MAX_MSG_SIZE)) {
msg_list_node = phase_ptr->cur_msg;
phase_ptr->cur_msg = NULL;
msg_list_node->next = phase_ptr->async_list;
phase_ptr->async_list = msg_list_node;
SENDASYNCNOMEM(msg_list_node->msg_type,msg_list_node->msg_buf,
msg_list_node->msg_len,msg_list_node->msg_to,
msg_list_node->msg_data_type,msg_list_node->msg_id,procinfo);
CHKERR(0);
/* fall through... */
} else {
/* we have enough room put it here and return */
/* find my place in the message */
char_msg = &(msg_list_node->msg_buf[msg_list_node->msg_len]);
msg_list_node->msg_len += (TRUE_MSG_LEN(msg->size) + sizeof(FLOAT));
tint1 = (int *) msg_list_node->msg_buf;
(*tint1)++;
int_msg = (int *) char_msg;
int_msg[0] = msg->size;
char_msg += sizeof(FLOAT);
ochar_msg = (char *)msg->msg;
for (i=0;i<msg->size;i++) {
char_msg[i] = ochar_msg[i];
}
return;
}
}
/* the type of the block message is the type of the 1st message */
/* extra data in each message */
/* 1 int -- the number of messages in the block */
/* 1 int per sub message -- the type of a single message */
/* 1 int per sub message -- the length of a single message */
if (phase_ptr->cur_msg == NULL) {
if (TRUE_MSG_LEN(msg->size)+sizeof(FLOAT)*2 <= PREFER_MAX_MSG_SIZE) {
MY_MALLOC(msg_list_node,(BSmsg_list *),sizeof(BSmsg_list),1);
phase_ptr->cur_msg = msg_list_node;
msg_list_node->msg_type = msg->msg_type;
msg_list_node->msg_len = TRUE_MSG_LEN(msg->size)+2*sizeof(FLOAT);
msg_list_node->msg_to = msg->proc;
msg_list_node->msg_data_type = msg->msg_data_type;
MY_MALLOC(msg_list_node->msg_buf,(char *),PREFER_MAX_MSG_SIZE,1);
char_msg = (char *) msg_list_node->msg_buf;
int_msg = (int *) char_msg;
int_msg[0] = 1;
char_msg += sizeof(FLOAT);
int_msg = (int *) char_msg;
int_msg[0] = msg->size;
char_msg += sizeof(FLOAT);
ochar_msg = (char *)msg->msg;
for (i=0;i<msg->size;i++) {
char_msg[i] = ochar_msg[i];
}
} else {
MY_MALLOC(msg_list_node,(BSmsg_list *),sizeof(BSmsg_list),1);
msg_list_node->next = phase_ptr->async_list;
phase_ptr->async_list = msg_list_node;
msg_list_node->msg_type = msg->msg_type;
msg_list_node->msg_len = TRUE_MSG_LEN(msg->size) + sizeof(FLOAT)*2;
msg_list_node->msg_to = msg->proc;
msg_list_node->msg_data_type = msg->msg_data_type;
MY_MALLOC(msg_list_node->msg_buf,(char *),msg_list_node->msg_len,1);
char_msg = (char *) msg_list_node->msg_buf;
int_msg = (int *) char_msg;
int_msg[0] = 1;
char_msg += sizeof(FLOAT);
int_msg = (int *) char_msg;
int_msg[0] = msg->size;
char_msg += sizeof(FLOAT);
ochar_msg = (char *)msg->msg;
for (i=0;i<msg->size;i++) {
char_msg[i] = ochar_msg[i];
}
SENDASYNCNOMEM(msg_list_node->msg_type,msg_list_node->msg_buf,
msg_list_node->msg_len,msg_list_node->msg_to,
msg_list_node->msg_data_type,msg_list_node->msg_id,procinfo);
CHKERR(0);
}
}
}
/*+ BMrecv_block_msg - Receive any unreceived blocked message in this phase
Input Parameters:
. phase_ptr - pointer to the phase
. procinfo - information about the processor number, etc.
Returns:
pointer to the message (NULL if no more messages)
+*/
BMmsg *BMrecv_block_msg(BMphase *phase_ptr, BSprocinfo *procinfo)
{
BMmsg *msg_ptr, *tmsg_ptr;
int i;
int *int_msg;
char *char_msg;
int num_msg;
MPI_Status mpi_status;
if (phase_ptr == NULL) return(NULL);
if (phase_ptr->cur_list_ptr == NULL) {
phase_ptr->cur_list_ptr = phase_ptr->msg_list;
} else {
phase_ptr->cur_list_ptr = phase_ptr->cur_list_ptr->next;
}
msg_ptr = phase_ptr->cur_list_ptr;
if (msg_ptr == NULL) {
return(NULL);
} else {
if (msg_ptr->status == NOT_COMPLETED) {
/* this means we *really* have to receive it */
/* first, free up the current received message */
BMfree_block_msg(phase_ptr);
RECVSYNCUNSZN(msg_ptr->msg_type,phase_ptr->cur_recv_msg,
msg_ptr->size,msg_ptr->msg_data_type,procinfo,mpi_status);
CHKERRN(0);
/* now break up the message */
char_msg = (char *)phase_ptr->cur_recv_msg;
int_msg = (int *) char_msg;
tmsg_ptr = msg_ptr;
num_msg = int_msg[0];
char_msg += sizeof(FLOAT);
for (i=0;i<num_msg;i++) {
int_msg = (int *) char_msg;
tmsg_ptr->size = int_msg[0];
char_msg += sizeof(FLOAT);
tmsg_ptr->msg = char_msg;
tmsg_ptr->status = COMPLETED;
tmsg_ptr = tmsg_ptr->next;
char_msg += TRUE_MSG_LEN(int_msg[0]);
}
return(msg_ptr);
} else {
/* we just have to return with it */
return(msg_ptr);
}
}
}
/*+ BMrecv_msg - Receive any unreceived message in this phase
Input Parameters:
. phase_ptr - pointer to the phase
Returns:
pointer to the message (NULL if no more messages)
+*/
BMmsg *BMrecv_msg(BMphase *phase_ptr)
{
BMmsg *msg_ptr;
int waiting;
int finished;
MPI_Status mpi_status;
if (phase_ptr == NULL) return(NULL);
waiting = TRUE;
while (waiting) {
waiting = FALSE;
for (msg_ptr=phase_ptr->msg_list;msg_ptr!=NULL;msg_ptr=msg_ptr->next) {
if (msg_ptr->status == NOT_COMPLETED) {
if (msg_ptr->msg != NULL) {
MPI_Test(&(msg_ptr->recv_id),&finished,&mpi_status);
if (finished) {
msg_ptr->alloced = FALSE;
msg_ptr->status = COMPLETED;
return(msg_ptr);
} else {
waiting = TRUE;
}
} else {
printf("Major error in BMrecv_msg\n");
}
}
}
}
return(NULL);
}
/*+ BMfree_block_msg - Free the current blocked message, if any
Input Parameters:
. phase_ptr - pointer to the current phase
Returns:
void
+*/
void BMfree_block_msg(BMphase *phase_ptr)
{
if (phase_ptr != NULL) {
if (phase_ptr->cur_recv_msg != NULL) {
MSGFREERECV(phase_ptr->cur_recv_msg); CHKERR(0);
phase_ptr->cur_recv_msg = NULL;
}
}
}
/*+ BMfree_msg - Free a received message
Input Parameters:
. msg_ptr - pointer to a message
Returns:
void
+*/
void BMfree_msg(BMmsg *msg_ptr)
{
if (msg_ptr->alloced) {
if (msg_ptr->msg != NULL) {
MSGFREERECV(msg_ptr->msg); CHKERR(0);
}
msg_ptr->msg = NULL;
msg_ptr->alloced = FALSE;
}
}
syntax highlighted by Code2HTML, v. 0.9.1