






















#include "bsp_lib_f77.h"








   
int   _bsp_sendlatency_usecs    = 1400;
int   _bsp_roundtrip_usecs      = 1000;
int   _bsp_slotsize_usecs       = 1400;
int   _bsp_noslots              = 1;
int   _bsp_nbuffers             = 2;
int   _bsp_buffer_size          = 16384;
int   _bsp_buffer_stalls        = 2;
int   _bsp_comm_fifo_size       = 1000;
int   _bsp_throttle_procs       = 0;
char *_bsp_compile_flags        = NULL;
char *_bsp_arch                 = "unknown";
char *_bsp_device               = "unknown";
char *_bsp_include_dir          = "/usr/include/";
int   _bsp_opt_fcombine_puts    = 1024;
int   _bsp_opt_fcombine_puts_max= 1024;
int   _bsp_opt_fcombine_puts_min= 1024;
int   _bsp_opt_flibrary_level   = 0;
char  _bsp_library_type         = 'O';
int   _bsp_do_stat              = 0;
int   _bsp_opt_contention_level = 1;
int   _bsp_check_syncs          = 0;
int   _bsp_do_cgprof            = 0;
int   _bsp_do_prof              = 0;
int   _bsp_checkpointing        = 0;
int   _bsp_processmigration     = 0;
int   _bsp_opt_bsmp_buffer_size = BSMP_INFINITE_BUFFERS;
char *_bsp_exec_file            = "a.out";











char _bsp_buffget_reference;









 
static struct {
  int    tag_size;
  int    tag_padding;
  int    payload_padding;
  int    isfrozen;
  int    current_buffer;
  char  *oldincoming_message_buffer[BSP_MAX_PROCS];
  char  *incoming_message_buffer[BSP_MAX_PROCS];
  int    incoming_message_buffer_size[BSP_MAX_PROCS];
  int    incoming_messages_size[BSP_MAX_PROCS];
#ifdef BSP_DRMA
  int    incoming_messages_size_safe[BSP_MAX_PROCS];
#endif
  int    outgoing_offset[BSP_MAX_PROCS];
  char  *next_message;
} _bsmp;






typedef struct _BSPfreelist {
  int                  size;
  char                *head;
  struct _BSPfreelist *tail;
} BSPfreelist;

BSPfreelist *_bsp_free_list=NULL, *_bsp_last_free_list=NULL,
                                  *_bsp_togo_free_list=NULL;










typedef struct {
  bsp_int32 reg_table_smash_nbytes;
  bsp_int32 offset;
} _BSPcombinfo;







char *_bspcombput_buffer;
static int    _bspcombput_region_size;
static int    _bspcombput_half_size;

/* Each of the ptr entries will actually be located at            */
/* the beginning of each processors region of the scratch buffer. */
typedef struct {
  int   queue_nbytes_to_go;
  int   queue_out_size_copy; /* shadow of the following to save indirections*/
  int  *queue_out_size;
  char *buffer_out;
  int  *queue_in_size;
  char *buffer_in;
} _BSPcomb_accounting;

static _BSPcomb_accounting _bspcombput[BSP_MAX_PROCS];



int   _bsp_lineno=0;
char *_bsp_filename="<null>";







#define bspcombputs_resetin(i)                              \
  do {                                                      \
    *_bspcombput[i].queue_in_size     =0;                   \
    _bspcombput[i].buffer_in                                \
      =(char*) (_bspcombput[i].queue_in_size  +             \
                (SIZEOF(_BSPcombinfo) / SIZEOF(int)));      \
  } while(0)

#define bspcombputs_resetout(i)                             \
  do {                                                      \
    _bspcombput[i].queue_out_size_copy=0;                   \
    _bspcombput[i].buffer_out                               \
      =(char*) (_bspcombput[i].queue_out_size +             \
                (SIZEOF(_BSPcombinfo) / SIZEOF(int)));      \
    _bspcombput[i].queue_nbytes_to_go                       \
      =_bspcombput_region_size-SIZEOF(_BSPcombinfo);        \
  } while(0)






#define bspcombputs_applicable(pid,gid,inbytes) \
  (((inbytes+(2*SIZEOF(_BSPcombinfo))) <        \
    (_bspcombput[pid].queue_nbytes_to_go)) &&   \
   (gid < 65536))          

#define bspcombputs_put(pid,src,dst_addr,offset,inbytes,cacheinbytes,cachenbytes,ptr) \
  do {                                                              \
    ptr = (_BSPcombinfo*) _bspcombput[pid].buffer_out;              \
    _bspcombput[pid].queue_out_size_copy++;                         \
    ptr->reg_table_smash_nbytes = dst_addr | (inbytes << 16);       \
    ptr->offset                 = offset;                           \
    if (inbytes!=cacheinbytes) {                                    \
      /* Make sure that the buffer is allocated in blocks modulo */ \
      /* BSPcombinfo size */                                        \
      cacheinbytes= inbytes;                                        \
      cachenbytes = MOD_POW2(inbytes,SIZEOF(_BSPcombinfo));         \
      if (cachenbytes)                                              \
        cachenbytes=inbytes+(2*SIZEOF(_BSPcombinfo))-cachenbytes;   \
      else                                                          \
        cachenbytes = inbytes + SIZEOF(_BSPcombinfo);               \
    }                                                               \
    FAST_MEMCPY(ptr+1,src,inbytes);                                 \
    _bspcombput[pid].buffer_out         += cachenbytes;             \
    _bspcombput[pid].queue_nbytes_to_go -= cachenbytes;             \
  } while(0)












STATIC void bspcombputs_init() { 
  int i,offset;

  if (_bsp_nprocs==1) _bsp_opt_fcombine_puts=0;
  _bspcombput_region_size = _bsp_opt_fcombine_puts;

  if (_bsp_opt_fcombine_puts_max>0 &&
       ((_bspcombput_region_size*2*_bsp_nprocs*(_bsp_nprocs-1))>
        _bsp_opt_fcombine_puts_max)) {
    _bspcombput_region_size=_bsp_opt_fcombine_puts_max/
                            (2*_bsp_nprocs*(_bsp_nprocs-1));
    if (_bspcombput_region_size<_bsp_opt_fcombine_puts_min) {
      _bsp_opt_fcombine_puts=0;
      _bspcombput_region_size=0;
    }
  }
#ifdef DEBUG
  bsp_debug("{bspcombputs_init} %d K per process",
            _bspcombput_region_size/1024);
#endif
  if (_bspcombput_region_size>0) {
    _bspcombput_buffer=MALLOC((2*(_bsp_nprocs-1))*_bspcombput_region_size);
    if (_bspcombput_buffer==NULL)
      bsp_abort("{bspcombputs_init} unable to allocate %d bytes",
                _bspcombput_buffer);
  } else {
    _bspcombput_buffer=MALLOC(2*SIZEOF(_BSPcombinfo));
  }
  /* Make sure the regions we use as buffers are word addressable */
  _bspcombput_region_size -=_bspcombput_region_size%SIZEOF(_BSPcombinfo);
  _bspcombput_half_size    =_bspcombput_region_size*(_bsp_nprocs-1);
  
  bsp_push_reg_cpp(_bspcombput_buffer,
                   2*_bspcombput_half_size,
                   __LINE__,
                   "BSPlib's internal combine buffer.");

  if (_bsp_nprocs>BSP_MAX_PROCS) {
    bsp_debug("Turning off -fcombine-puts: only works for <%d processors",
              BSP_MAX_PROCS);
    _bsp_opt_fcombine_puts = 0;
  }

  for(i=0;i<_bsp_nprocs;i++) {
    if (i!=_bsp_pid) {
      offset = (i>=_bsp_pid)?1:0;
      _bspcombput[i].queue_out_size
        =(int*) (_bspcombput_buffer+
                 ((i-offset)*_bspcombput_region_size));
      _bspcombput[i].queue_in_size
        =(int*) (_bspcombput_buffer+_bspcombput_half_size+
                 ((i-offset)*_bspcombput_region_size));
      bspcombputs_resetin(i);
      bspcombputs_resetout(i);
    }
  }
}







STATIC void bspcombputs_flush() {
  int i;
  _BSPcombinfo *ptr;

  for (i=0;i<_bsp_nprocs;i++) {
    if ((_bspcombput[i].queue_out_size_copy==0) || (i==_bsp_pid)) {
#ifdef DEBUG
      bsp_debug("{bspcombputs} nothing going out to %d",i);
#endif
    } else if (_bspcombput[i].queue_out_size_copy==1) {
#ifdef DEBUG
      bsp_debug("{bspcombputs} only one thing going out to %d",i);
#endif
      /* Only one thing to send, so just send it */
      ptr= (_BSPcombinfo *) 
             (_bspcombput_buffer+SIZEOF(_BSPcombinfo)+
              ((i-((i>=_bsp_pid)?1:0))*_bspcombput_region_size));
      _bsp_put(COMM_SET_PUT(i),
               (_bspcombput_buffer+(2*SIZEOF(_BSPcombinfo))+
               ((i+((i>=_bsp_pid)?-1:0))*_bspcombput_region_size)),
               0xffff & ptr->reg_table_smash_nbytes,
               ptr->offset,
               ptr->reg_table_smash_nbytes >> 16);
#ifdef STATISTICS
      _bspstat.combput_fails++;
#endif
    } else {
      *(_bspcombput[i].queue_out_size)
        = _bspcombput[i].queue_out_size_copy;
#ifdef DEBUG
      bsp_debug("{bspcombputs} %d bytes from %d puts merged to proc %d",
                _bspcombput_region_size-_bspcombput[i].queue_nbytes_to_go,
                *(_bspcombput[i].queue_out_size),i);
#endif 
      _bsp_put(COMM_SET_PUT(i),
               (char*)_bspcombput_buffer+
                     ((i-((i>=_bsp_pid)?1:0))*_bspcombput_region_size),
               bsp_register_local_to_global(_bspcombput_buffer),
               _bspcombput_half_size+
               ((_bsp_pid-((_bsp_pid>=i)?1:0))*_bspcombput_region_size),
               _bspcombput_region_size-_bspcombput[i].queue_nbytes_to_go);
#ifdef STATISTICS
      _bspstat.combput_hits += *(_bspcombput[i].queue_out_size);
#endif
    }
  } 
} 






STATIC void bspcombputs_finalise() {
  int tmp,i,j, no_puts,smash,nbytes,addr_global_src;
  char *cached_reg_table_tgt, *buff_addr;
  _BSPcombinfo *infoptr;

  for (i=0;i<_bsp_nprocs;i++) {
    if (i!=_bsp_pid) {
      no_puts = *(_bspcombput[i].queue_in_size);
      if (no_puts>1) {
#ifdef DEBUG
        bsp_debug("{bspcombputs_finalise} dealing with %d puts from %d",
                  no_puts,i);
#endif
        buff_addr = _bspcombput[i].buffer_in;
        for (j=0;j<no_puts;j++) {
          infoptr         = (_BSPcombinfo*) buff_addr;
          buff_addr      += SIZEOF(_BSPcombinfo);
          smash           = infoptr->reg_table_smash_nbytes;
          nbytes          = smash >> 16; 
          addr_global_src = 0xffff & smash ;
#ifdef DEBUG
          bsp_debug("{bspcombputs_finalise} %d put(%x+%d,%d)=%d\n",
                    j,bsp_register_global_to_local(addr_global_src,_bsp_pid),
                    infoptr->offset,nbytes,*((int*) buff_addr));
#endif
#ifdef SANITY_CHECK
          if (bsp_register_nbytes(addr_global_src,_bsp_pid)- 
              infoptr->offset < nbytes)
            bsp_error_reg_small(i,addr_global_src,nbytes,infoptr->offset);
#endif
          FAST_MEMCPY(((char*)bsp_register_global_to_local(addr_global_src,_bsp_pid))+
                      infoptr->offset,
                      buff_addr,nbytes);

          if (tmp= (MOD_POW2(nbytes,SIZEOF(_BSPcombinfo)))) {
            buff_addr += nbytes + SIZEOF(_BSPcombinfo)-tmp;
          } else {
            buff_addr += nbytes;
          }       
        }
        if (no_puts>0) bspcombputs_resetin(i);  
      }
      if (_bspcombput[i].queue_out_size_copy>0)
        bspcombputs_resetout(i);
    }
  } 
}







int bsp_pid() {
  return (_bsp_pid);
}

int bsp_nprocs() {
  char *env_nprocs;
  int i;

  if (_bsp_nprocs>0) return (_bsp_nprocs);
  else {

    env_nprocs = getenv("BSP_PROCS");
    if (env_nprocs!=NULL) {
      i = atoi(env_nprocs);
      if ((i<=0) || (i>BSP_MAX_PROCS)) 
        return (BSP_MAX_PROCS);
      else 
        return i;
    } else {
      return (BSP_MAX_PROCS);
    }
  }
    
}












#define deallocateFreeList()                             \
  do {                                                   \
    BSPfreelist *freelistptr;                            \
    while (_bsp_togo_free_list) {                        \
      freelistptr = _bsp_togo_free_list;                 \
      _bsp_togo_free_list = _bsp_togo_free_list->tail;   \
      free(freelistptr->head);                           \
      free(freelistptr);                                 \
   }                                                     \
   _bsp_togo_free_list = _bsp_last_free_list;            \
   _bsp_last_free_list = _bsp_free_list;                 \
   _bsp_free_list      = NULL;                           \
 } while(0)







#define BSP_MALLOC(ptr,newsize,str) do { 			\
   BSPfreelist *freelistptr;					\
   if (_bsp_togo_free_list) {				        \
     if (newsize == _bsp_togo_free_list->size) {                \
       ptr = (char *) (_bsp_togo_free_list->head);		\
     } else {                                                   \
       free(_bsp_togo_free_list->head); 			\
       ptr = (char *) MALLOC(newsize);			     	\
       if (ptr==NULL)						\
          bsp_abort("%s: line %d of \"%s\"\n"	     		\
                    "\tFailed to malloc %d bytes",str,   	\
	            _bsp_lineno,_bsp_filename,newsize);      	\
       _bsp_togo_free_list->size = newsize;			\
       _bsp_togo_free_list->head = ptr;				\
     }              						\
     freelistptr         = _bsp_togo_free_list;			\
     _bsp_togo_free_list = _bsp_togo_free_list->tail;		\
     freelistptr->tail   = _bsp_free_list;			\
     _bsp_free_list      = freelistptr;				\
   } else {							\
     ptr = (char *) MALLOC(SIZEOF(BSPfreelist));		\
     if (ptr==NULL) 						\
        bsp_abort("%s: line %d of \"%s\"\n"	     		\
                  "\tFailed to malloc free list", str,		\
                  _bsp_lineno,_bsp_filename);      		\
     ((BSPfreelist *) ptr)->tail= _bsp_free_list;		\
     ((BSPfreelist *) ptr)->size= newsize;			\
     _bsp_free_list = (BSPfreelist *) ptr;			\
     ptr = (char *) MALLOC(newsize);				\
     if	(ptr==NULL)						\
        bsp_abort("%s: line %d of \"%s\"\n"	     		\
                    "\tFailed to malloc %d bytes",str,   	\
	            _bsp_lineno,_bsp_filename,newsize);      	\
     _bsp_free_list->head = ptr;				\
   }								\
  } while (0)







#undef bsp_init
void bsp_init(void (*startproc)(void),int argc,char **argv) {
#if defined(CHECKPOINTING_DEV) && defined(CHECKPOINTING_ARCH)
  cpr_depth++;
#endif
  bsp_init_cpp(startproc,argc,argv,0,"unknown");
}







#undef bsp_sync
void bsp_sync() {
  bsp_sync_cpp(0,"unprofiled");
}






#undef bsp_put
void bsp_put(int pid, const void *src, void *dst, int offset, int nbytes) {
  bsp_put_cpp(pid,src,dst,offset,nbytes,0,"unprofiled");
}

void bsp_put_cpp(int pid, const void *src, void *dst, int offset, int nbytes,
                 int lineno,const char *filename){
  static int    cacheinbytes=0,cachenbytes=0;
  int           gid;
  char         *dst_plus_offset, *copy;
  _BSPcombinfo *ptr;

  
#if defined(PROFILE) || !defined(TURBO)
  _bsp_lineno   = lineno;
  _bsp_filename = (char*) filename;
#endif
#ifdef SANITY_CHECK
  if (pid < 0 || pid >= _bsp_nprocs) 
    bsp_abort("{bsp_put}: line %d  of \"%s\"\n"
              "\tprocess %d is trying to put into non-existant processor %d.",
              _bsp_lineno,_bsp_filename,_bsp_pid,pid);

  if (src==NULL && nbytes>0)
    bsp_abort("{bsp_put}: line %d of \"%s\"\n"
              "\tSrc address is NULL while nbytes is %d",
              _bsp_lineno,_bsp_filename,nbytes);
#endif

  if (nbytes<=0) {
    /* do nothing */
  } else {
    gid=bsp_register_local_to_global(dst);
    if ((nbytes < MAX_FCOMBINE_MESSAGE_SIZE)   &&
        bspcombputs_applicable(pid,gid,nbytes) &&
        (pid!=_bsp_pid)) {

      bspcombputs_put(pid,src,gid,offset,nbytes,cacheinbytes,cachenbytes,ptr);
    } else {
      BSP_MALLOC(copy,nbytes,"{bsp_put_cpp}");
      MEMCPY(copy,src,nbytes);
      _bsp_put(COMM_SET_PUT(pid),copy,gid,offset,nbytes);
    }
  }
}









#undef bsp_hpput
void bsp_hpput(int pid, const void *src, void *dst, int offset, int nbytes){
  bsp_hpput_cpp(pid,src,dst,offset,nbytes,0,"unprofiled");
}

void bsp_hpput_cpp(int pid, const void *src, void *dst, int offset, int nbytes,
                   int lineno,const char *filename){
  static int    cacheinbytes=0,cachenbytes=0;
  int           gid;
  char         *dst_plus_offset;
  _BSPcombinfo *ptr;
  extern bsp_registration **_bsp_reg_global;
  
#if defined(PROFILE) || !defined(TURBO)
  _bsp_lineno   = lineno;
  _bsp_filename = (char*)filename;
#endif
#ifdef SANITY_CHECK
  if (pid < 0 || pid >= _bsp_nprocs)
    bsp_abort("{bsp_hpput}: line %d  of \"%s\"\n"
              "\tprocess %d is trying to put into no-existant processor %d.",
              _bsp_lineno,_bsp_filename,_bsp_pid,pid);

  if (src==NULL && nbytes>0)
    bsp_abort("{bsp_hpput}: line %d of \"%s\"\n"
              "\tSrc address is NULL while nbytes is %d",
              _bsp_lineno,_bsp_filename,nbytes);
#endif

  if (nbytes<=0) {
    /* do nothing */
  } else if (pid == _bsp_pid) {
    dst_plus_offset = (char*) dst + offset;
    if (dst_plus_offset != (char*)src)
      FAST_MEMCPY(dst_plus_offset,src,nbytes);
 
  } else {
    gid=bsp_register_local_to_global(dst);
    if (nbytes < MAX_FCOMBINE_MESSAGE_SIZE &&
        bspcombputs_applicable(pid,gid,nbytes)) {
      bspcombputs_put(pid,src,gid,offset,nbytes,cacheinbytes,cachenbytes,ptr);
    } else {
#if !defined(BSP_DRMA) || defined(PROFILE)
      _bsp_put(COMM_SET_PUT(pid),src,gid,offset,nbytes);
#else
      if (CONTENTION_REMOVAL_SOME()) 
        drma_put(pid,
                 src,
                 ((char*) bsp_register_global_to_local(gid,pid))+offset,
                 nbytes);
      else
        _bsp_put(COMM_SET_PUT(pid),src,gid,offset,nbytes);
#endif
    }
  }
}







#undef bsp_get
void bsp_get(int pid,const void *src,int offset,void *dst,int nbytes) {
#if defined(PROFILE) || !defined(TURBO)
  _bsp_lineno   = 0;
  _bsp_filename = (char*) "unprofiled";
#endif
#ifdef SANITY_CHECK
  if (dst==NULL && nbytes>0)
    bsp_abort("{bsp_get}: line %d of \"%s\"\n"
              "\tDestination address is NULL while nbytes is %d",
              _bsp_lineno,_bsp_filename,nbytes);
#endif
  if (nbytes<=0) {
    /* do nothing */
  } else
    _bsp_get(COMM_SET_GET(pid),src,offset,dst,nbytes);
}

void bsp_get_cpp(int pid,const void *src,int offset,void *dst,int nbytes,
                 int lineno, const char* filename) {
#if defined(PROFILE) || !defined(TURBO)
  _bsp_lineno   = lineno;
  _bsp_filename = (char*) filename;
#endif
#ifdef SANITY_CHECK
  if (dst==NULL && nbytes>0)
    bsp_abort("{bsp_get}: line %d of \"%s\"\n"
              "\tDestination address is NULL while nbytes is %d",
              _bsp_lineno,_bsp_filename,nbytes);
#endif
  if (nbytes<=0) {
    /* do nothing */
  } else
    _bsp_get(COMM_SET_GET(pid),src,offset,dst,nbytes);
}






#undef bsp_hpget
void bsp_hpget(int pid,const void *src,int offset,void *dst,int nbytes) {
#if defined(PROFILE) || !defined(TURBO)
  _bsp_lineno   = 0;
  _bsp_filename = (char*) "unprofiled";
#endif
#ifdef SANITY_CHECK
  if (dst==NULL && nbytes>0)
    bsp_abort("{bsp_hpget}: line %d of \"%s\"\n"
              "\tDestination address is NULL while nbytes is %d",
              _bsp_lineno,_bsp_filename,nbytes);
#endif
  if (nbytes<=0) {
    /* do nothing */
  } else
    _bsp_get(COMM_SET_HPGET(pid),src,offset,dst,nbytes);
}

#undef bsp_hpget
void bsp_hpget_cpp(int pid,const void *src,int offset,void *dst,int nbytes,
                   int lineno, const char* filename) {
#if defined(PROFILE) || !defined(TURBO)
  _bsp_lineno   = lineno;
  _bsp_filename = (char*) filename;
#endif
#ifdef SANITY_CHECK
  if (dst==NULL && nbytes>0)
    bsp_abort("{bsp_hpget}: line %d of \"%s\"\n"
              "\tDestination address is NULL while nbytes is %d",
              _bsp_lineno,_bsp_filename,nbytes);
#endif
  if (nbytes<=0) {
    /* do nothing */
  } else {
#if !defined(BSP_DRMA) || defined(PROFILE)
    _bsp_get(COMM_SET_HPGET(pid),src,offset,dst,nbytes);
#else
    if (CONTENTION_REMOVAL_SOME()) 
      drma_get(pid,
               ((char*) 
                bsp_register_global_to_local(
                  bsp_register_local_to_global(src), 
                  pid))+offset,
               dst,
               nbytes);
    else
      _bsp_get(COMM_SET_HPGET(pid),src,offset,dst,nbytes);
#endif
  }
}



















STATIC void bsmp_init() {
  bsp_registration *ptr;
  int i=0,size;
  _bsmp.tag_size       = 0;
  _bsmp.tag_padding    = BSMP_PADDING_SIZE - SIZEOF(int);
  _bsmp.payload_padding= 0;
  size = (_bsp_opt_bsmp_buffer_size<BSMP_MIN_BUFFER_SIZE)?
           BSMP_MIN_BUFFER_SIZE:_bsp_opt_bsmp_buffer_size;
  for(i=0;i<_bsp_nprocs;i++) {
    _bsmp.incoming_message_buffer[i]=MALLOC(size);
    _bsmp.oldincoming_message_buffer[i]
      =_bsmp.incoming_message_buffer[i];

    if (_bsmp.incoming_message_buffer[i]==NULL) 
      bsp_abort("{bsmp_init}: unable to allocate message buffer");
    bsp_push_reg_cpp(_bsmp.incoming_message_buffer[i],
                     size,
                     __LINE__,
                     "BSPlibs internal BSMP buffer. "
                     "Use -finfinite-bsmp-buffers");
    _bsmp.incoming_message_buffer_size[i]=size;
    _bsmp.incoming_messages_size[i]      =0;
#ifdef BSP_DRMA
    _bsmp.incoming_messages_size_safe[i] =0;
    bsp_register_changetostatics(_bsmp.incoming_message_buffer[i],i);
#endif
    _bsmp.outgoing_offset[i]             =0;
  }
}











STATIC void bsmp_enlargebuffers() {
  int i;

  for(i=0;i<_bsp_nprocs;i++) {
#ifdef DEBUG
    bsp_debug("System buffer %d=%d bytes [incoming=%d]",i,
              _bsmp.incoming_message_buffer_size[i],
              _bsmp.incoming_messages_size[i]);
#endif
    if (_bsmp.incoming_message_buffer_size[i]<
        _bsmp.incoming_messages_size[i]) {
#ifdef DEBUG
      bsp_debug("{bspmp_enlargebuffers} buffer %d from %d to %d bytes",
                i,_bsmp.incoming_message_buffer_size[i],
                _bsmp.incoming_messages_size[i]);
#endif
      _bsmp.incoming_message_buffer_size[i]
        = _bsmp.incoming_messages_size[i];

      _bsmp.oldincoming_message_buffer[i] 
        = _bsmp.incoming_message_buffer[i];

      _bsmp.incoming_message_buffer[i]
        = MALLOC(_bsmp.incoming_message_buffer_size[i]);

#ifdef SANITY_CHECK
      if (_bsmp.incoming_message_buffer[i]==NULL)
        bsp_abort("{bsp_sync} at line %d of \"%s\"\n"
                  "\tunable to enlarge BSMP buffer to %d bytes",
                  _bsp_lineno, _bsp_filename,
                  _bsmp.incoming_message_buffer_size[i]);
#endif  
      /* old must not equal new. Therefore free _after_ malloc */ 
      free(_bsmp.oldincoming_message_buffer[i]);
          
    }
  }
}



#ifdef TURBO
#ifdef BSP_DRMA
#define bsmp_resetincoming()                                \
  do {                                                      \
    int i;                                                  \
    for(i=0;i<_bsp_nprocs;i++) {                            \
      _bsmp.outgoing_offset[i]=0;                           \
      _bsmp.incoming_messages_size_safe[i]=0;               \
    }                                                       \
    _bsmp.current_buffer=0;                                 \
    _bsmp.next_message  =_bsmp.incoming_message_buffer[0];  \
    _bsmp.isfrozen=0;                                       \
  } while(0)
#else
#define bsmp_resetincoming()                                \
  do {                                                      \
    int i;                                                  \
    for(i=0;i<_bsp_nprocs;i++) _bsmp.outgoing_offset[i]=0;  \
    _bsmp.current_buffer=0;                                 \
    _bsmp.next_message  =_bsmp.incoming_message_buffer[0];  \
    _bsmp.isfrozen=0;                                       \
  } while(0)
#endif
#else
STATIC void bsmp_resetincoming() {
  int i;
  for(i=0;i<_bsp_nprocs;i++) {
    _bsmp.outgoing_offset[i]=0;
#ifdef BSP_DRMA
    _bsmp.incoming_messages_size_safe[i]=0;
#endif
  }
  _bsmp.current_buffer=0;  
  _bsmp.next_message  =_bsmp.incoming_message_buffer[0];
  
  _bsmp.isfrozen=0;
#ifdef SANITY_CHECK
  if (!_bsp_constant(_bsmp.tag_size))
    bsp_abort("{bsp_set_tagsize} line %d  of \"%s\"\n"
              "The tag size is not the same on all processors",
	      _bsp_lineno,_bsp_filename);
#endif
#ifdef DEBUG
  bsp_debug("{bsp_freeze_tag_size} %d bytes (+%d,%d padding)",
            _bsmp.tag_size,_bsmp.tag_padding,_bsmp.payload_padding);
#endif
}
#endif









STATIC void bsmp_reregisterbuffers() {
  int i;
  for(i=0;i<_bsp_nprocs;i++) {
    if (_bsmp.oldincoming_message_buffer[i] !=
        _bsmp.incoming_message_buffer[i]) {
      bsp_changeregister((const void*)_bsmp.oldincoming_message_buffer[i],
                         (const void*)_bsmp.incoming_message_buffer[i],
                                      _bsmp.incoming_message_buffer_size[i],
                         i);
      _bsmp.oldincoming_message_buffer[i]
        = _bsmp.incoming_message_buffer[i];
    }
  }
}






void bsp_set_tagsize_cpp(int *tag_bytes,int lineno, const char *filename) {
  int temp;

#if defined(PROFILE) || !defined(TURBO)
  _bsp_lineno   = lineno;
  _bsp_filename = (char*) filename;
#endif
#ifdef SANITY_CHECK
  if (_bsmp.isfrozen)
    bsp_abort("{bsp_set_tag_size} line %d of \"%s\"\n"
              "\tTag must be set before first message is sent\n",
              _bsp_lineno,_bsp_filename);
#endif
  temp           = _bsmp.tag_size;
  _bsmp.tag_size = *tag_bytes;
  *tag_bytes     = temp;
  /* header = size of payload + tag + padding */
  if (_bsmp.tag_size>=BSMP_PADDING_SIZE) {
    temp = SIZEOF(int) % BSMP_PADDING_SIZE;
    _bsmp.tag_padding = (temp)?(BSMP_PADDING_SIZE-temp):0;
  }

  temp = (SIZEOF(int)+_bsmp.tag_size+_bsmp.tag_padding)%BSMP_PADDING_SIZE;
  _bsmp.payload_padding=(temp)?(BSMP_PADDING_SIZE-temp):0;
}

#undef bsp_set_tag_size
void bsp_set_tag_size(int *tag_bytes) {
  bsp_set_tagsize_cpp(tag_bytes,0,"unprofiled");
}

#undef bsp_set_tagsize
void bsp_set_tagsize(int *tag_bytes) {
  bsp_set_tagsize_cpp(tag_bytes,0,"unprofiled");
}









#undef bsp_send
void bsp_send(int pid,const void *tag, const void *payload,int payload_bytes){
  bsp_send_cpp(pid,tag,payload,payload_bytes,0,"unprofiled");
}


 
void bsp_send_cpp(int pid,const void *tag, const void *payload, 
                  int payload_bytes,int lineno,const char *filename) {
  int temp,messg_size, *ptr;
  char  *copy;

#if defined(PROFILE) || !defined(TURBO)
  _bsp_lineno   = lineno;
  _bsp_filename = (char*) filename;
#endif
#ifdef SANITY_CHECK
  if (pid < 0 || pid >= _bsp_nprocs) 
    bsp_abort("{bsp_send}: line %d  of \"%s\"\n"
              "\tprocess %d is trying to send to non-existant processor %d.",
              _bsp_lineno,_bsp_filename,_bsp_pid,pid);
  if (_bsmp.tag_size>0 && tag==NULL)
    bsp_abort("{bsp_send} line %d of \"%s\"\n"
              "\tTag is NULL when the tag size is %d",
              _bsp_lineno,_bsp_filename,_bsmp.tag_size);

  if (payload_bytes>0 && payload==NULL)
     bsp_abort("{bsp_send} line %d of \"%s\"\n"
              "\tPayload is NULL when the tag size is %d",
              _bsp_lineno,_bsp_filename,_bsmp.tag_size);
#endif
  _bsmp.isfrozen = 1;
  messg_size  = SIZEOF(int)+_bsmp.tag_padding + _bsmp.tag_size +
                _bsmp.payload_padding + payload_bytes;
  
  BSP_MALLOC(copy,messg_size,"{bsp_send}"); 
  *((int*) copy)= payload_bytes;
#ifdef DEBUG
  bsp_debug("{bsp_send} to %d tag=%d payload=%d(%d) "
            "message=%d offset=%d bytes",
            pid,_bsmp.tag_size,payload_bytes,*((int*) copy),
            messg_size,_bsmp.outgoing_offset[pid]);
#endif
  
  if (_bsmp.tag_size>0) 
    MEMCPY((((char*) copy)+SIZEOF(int)+_bsmp.tag_padding),tag,_bsmp.tag_size);

  if (payload_bytes>0)
    MEMCPY(((char*) copy)+SIZEOF(int)+_bsmp.tag_padding+
                          _bsmp.tag_size+_bsmp.payload_padding,
           payload,payload_bytes);
  
  if (temp=(MOD_POW2(messg_size,BSMP_PADDING_SIZE)))
    messg_size += BSMP_PADDING_SIZE - temp;
  _bsp_put(COMM_SET_SEND(pid),
           copy,
           bsp_register_local_to_global(
              _bsmp.incoming_message_buffer[_bsp_pid]),
           _bsmp.outgoing_offset[pid],
           messg_size);
  _bsmp.outgoing_offset[pid]  +=messg_size;
}






#undef bsp_get_tag
void bsp_get_tag(int *status, void *tag) {
  bsp_get_tag_cpp(status,tag,0,"unprofiled");
}

void bsp_get_tag_cpp(int *status, void *tag,int lineno, const char* filename) {

#ifdef SANITY_CHECK
  if (status==NULL)
    bsp_abort("{bsp_get_tag}: line %d of \"%s\"\n"
              "\tThe status address is NULL.",lineno,filename);
#endif
  *status=-1;
  while(_bsmp.current_buffer<_bsp_nprocs) {
#ifdef DEBUG
    bsp_debug("{bsp_get_tag} buffer %d has %d bytes left",
              _bsmp.current_buffer,
              _bsmp.incoming_messages_size[_bsmp.current_buffer]);
#endif
    if (_bsmp.incoming_messages_size[_bsmp.current_buffer]<=0) 
      _bsmp.next_message=_bsmp.incoming_message_buffer[++_bsmp.current_buffer];
    else {
      *status = *((int*) _bsmp.next_message);
      if (_bsmp.tag_size > 0) {
#ifdef SANITY_CHECK
        if (tag==NULL) 
        bsp_abort("{bsp_get_tag}: line %d of \"%s\"\n"
                  "\tThe tag address is NULL.",lineno,filename);
#endif
        MEMCPY(tag,
               ((char*)_bsmp.next_message)+SIZEOF(int)+_bsmp.tag_padding,
               _bsmp.tag_size);
      }
      break;
    }  
  }
}






#undef bsp_qsize
void bsp_qsize(int *packets,int *accum_size) {
  bsp_qsize_cpp(packets,accum_size,0,"unprofiled");
}

void bsp_qsize_cpp(int *packets, int *accum_size,
                       int lineno, const char* filename) {
  int i,payload_size,messg_size,no_messg=0;
  int buffsize,buffno;
  char *ptr;

#ifdef SANITY_CHECK
  if (packets==NULL)
    bsp_abort("{bsp_qsize}: line %d of \"%s\"\n"
              "\tThe pointer to the number of packets is NULL.",
              lineno,filename);

  if (accum_size==NULL)
    bsp_abort("{bsp_qsize}: line %d of \"%s\"\n"
              "\tThe pointer to the accumulated size of the packets is NULL.",
              lineno,filename);
#endif
  ptr        = _bsmp.next_message;
  buffno     = _bsmp.current_buffer;
  *accum_size= 0;
  buffsize   = _bsmp.incoming_messages_size[buffno];
  while (buffno<_bsp_nprocs) {
    if (buffsize<=0) {
      ptr      =_bsmp.incoming_message_buffer[++buffno];
      buffsize =_bsmp.incoming_messages_size[buffno];
    } else {
      payload_size = *((int*) ptr);
      *accum_size += payload_size;
      messg_size   = SIZEOF(int)    + _bsmp.tag_padding +
                     _bsmp.tag_size + _bsmp.payload_padding;
      if (i=(MOD_POW2(payload_size,BSMP_PADDING_SIZE)))
        messg_size += payload_size + BSMP_PADDING_SIZE - i;
      else 
        messg_size += payload_size; 
      ptr      += messg_size;
      buffsize -= messg_size;
      no_messg++;
#ifdef DEBUG
      bsp_debug("{bsp_qsize} clearing buffer %d. "
                "%d bytes to go %d messages seen (%d bytes payload)",
                buffno,buffsize,no_messg,*accum_size);
#endif
    }
  }
#ifdef DEBUG
  bsp_debug("{bsp_qsize} %d messages. %d bytes",
            no_messg,*accum_size);
#endif
  *packets=no_messg;
}






#undef bsp_move
void bsp_move(void *payload, int reception_nbytes) {
  bsp_move_cpp(payload,reception_nbytes,0,"unprofiled");
}

void bsp_move_cpp(void *payload, int reception_nbytes,
                  int lineno, const char* filename) {
  int i,total_size, payload_size;

  while(_bsmp.current_buffer<_bsp_nprocs) {
    if (_bsmp.incoming_messages_size[_bsmp.current_buffer]==0) {
      _bsmp.next_message=_bsmp.incoming_message_buffer[++_bsmp.current_buffer];
#ifdef SANITY_CHECK
    } else if (_bsmp.incoming_messages_size[_bsmp.current_buffer]<0) {
      bsp_abort("{bsp_move} line %d of \"%s\"\n"
                "Severe error with bsmp buffer offsets");
#endif
    } else {
      payload_size = *((int*) _bsmp.next_message);
      total_size   = SIZEOF(int) + _bsmp.tag_padding + _bsmp.tag_size + 
                     _bsmp.payload_padding;

      if (reception_nbytes>0) {
#ifdef SANITY_CHECK
        if (payload==NULL)
          bsp_abort("{bsp_move}: line %d of \"%s\"\n"
                    "\tThe payload address is NULL whilst trying to "
                    "to copy %d bytes",
		    lineno,filename,payload_size);
#endif
        MEMCPY(payload,
               _bsmp.next_message+total_size,
               (payload_size>reception_nbytes)?reception_nbytes:payload_size);
      }

      if (i=(MOD_POW2(payload_size,BSMP_PADDING_SIZE)))
        total_size += payload_size + BSMP_PADDING_SIZE - i;
      else 
        total_size += payload_size;

#ifdef DEBUG
      bsp_debug("{bsp_move} removing %d from system. Offset=%d",
                total_size,_bsmp.next_message-
                _bsmp.incoming_message_buffer[_bsmp.current_buffer]);
#endif
      _bsmp.incoming_messages_size[_bsmp.current_buffer]
        -= total_size;
      _bsmp.next_message+=total_size;
      break;
    }  
  }
}







#undef bsp_hpmove
int bsp_hpmove(void **tag_ptr_buf, void **payload_ptr_buf) {
  return (bsp_hpmove_cpp(tag_ptr_buf,payload_ptr_buf,0,"unprofiled"));
}

int bsp_hpmove_cpp(void **tag_ptr_buf, void **payload_ptr_buf,
                   int lineno, const char* filename) {
  int i,total_size, payload_size, tag_size;

#ifdef SANITY_CHECK
  if (tag_ptr_buf==NULL)
    bsp_abort("{bsp_hpmove}: line %d of \"%s\"\n"
              "\tThe pointer to the tag address is NULL.",
		    lineno,filename);
  if (payload_ptr_buf==NULL)
    bsp_abort("{bsp_hpmove}: line %d of \"%s\"\n"
              "\tThe pointer to the payload address is NULL.",
		    lineno,filename);
#endif
  payload_size=-1;
  while(_bsmp.current_buffer<_bsp_nprocs) {
#ifdef DEBUG
    bsp_debug("{bsp_hpmove} buffer %d has %d bytes left",
              _bsmp.current_buffer,
              _bsmp.incoming_messages_size[_bsmp.current_buffer]);
#endif
   if (_bsmp.incoming_messages_size[_bsmp.current_buffer]<=0) 
      _bsmp.next_message=_bsmp.incoming_message_buffer[++_bsmp.current_buffer];
    else {
      payload_size = *((int*) _bsmp.next_message);
      total_size   = SIZEOF(int) + _bsmp.tag_padding + 
                     _bsmp.tag_size+_bsmp.payload_padding;

#ifdef DEBUG
      bsp_debug("{bsp_hpmove} tag=%d payload=%d -%d + %d bytes [%d bytes all total]",
                 _bsmp.tag_size,payload_size,
                 *(((int*) _bsmp.next_message)-1),
                 *(((int*) _bsmp.next_message)+1),
                 _bsmp.incoming_messages_size[_bsmp.current_buffer]);
#endif
      *tag_ptr_buf    = (void*) ((char*)_bsmp.next_message+SIZEOF(int)+
                                _bsmp.tag_padding);
      *payload_ptr_buf= (void*) (((char*)_bsmp.next_message)+total_size);
      
      if (i=(MOD_POW2(payload_size,BSMP_PADDING_SIZE)))
        total_size += payload_size+ BSMP_PADDING_SIZE - i;
      else
        total_size += payload_size;
      _bsmp.incoming_messages_size[_bsmp.current_buffer] -= total_size;
      _bsmp.next_message+=total_size;
      break;
    }  
  }
  return(payload_size);
}










void process_globals_init() {
   bsp_register_init();
   bspcombputs_init();  
   bsp_pushregister(&_bsp_buffget_reference,1073741824);
   bsmp_init();        
#ifdef STATISTICS
   if (_bsp_do_stat) bspstat_create();
   bspstat_init();
#endif
#ifdef PROFILE
   bspprof_create();
   bspprof_init();
#endif
}





void bsplib_routines_init() {
   bspparams_init(); /* From level 1 library */
   bsp_bcast_init();
   bsp_scan_init();
   bsp_fold_init();
   bsp_fold_funs_init();
   bsp_f77_init();
}











void bsp_fix_argv(int *ref_argc, char ***ref_argv) {
#ifdef MPASS_NEEDS_HOST_PROGRAM
  mpass_argv_fromhost(ref_argc, ref_argv);
#endif
}










STATIC void bsp_check_setup_before_init() {
  if (strcmp(_bsp_arch,BSP_ARCH)!=0)
    bsp_abort("{bsp_begin}\n"
              "\tYour program was compiled for a \"%s\", yet it was\n"
              "\tlinked against a library that was compiled for \"%s\".\n",
              _bsp_arch,BSP_ARCH);

  if (getenv("BSP_MACHINE") && (strcmp(BSP_ARCH,getenv("BSP_MACHINE"))!=0))
    bsp_abort("{bsp_begin}\n"
              "\tYour program is trying to run on a \"%s\", yet it was\n"
              "\tlinked against a library that was compiled for \"%s\".\n",
              getenv("BSP_MACHINE"),BSP_ARCH);

  if (strcmp(_bsp_device,BSP_DEVICE)!=0)
    bsp_abort("{bsp_begin}\n"
              "\tYour program was compiled to run over \"%s\", yet it was\n"
              "\tlinked against a library that was compiled for \"%s\".\n",
              _bsp_device,BSP_DEVICE);

  if (getenv("BSP_DEVICE") && (strcmp(BSP_DEVICE,getenv("BSP_DEVICE"))!=0))
    bsp_abort("{bsp_begin}\n"
              "\tYour program is trying to run over \"%s\", yet it was\n"
              "\tlinked against a library that was compiled for \"%s\".\n",
              getenv("BSP_DEVICE"),BSP_DEVICE);
}



STATIC void bsp_check_setup_after_init() {
   if (SIZEOF(double) != 8)
     bsp_abort("{MEMCPY} SIZEOF(double)=%d and not 8",
       SIZEOF(double));

   if (_bsp_buffer_size % 4 != 0)
      bsp_abort("{_bsp_buffer_size=%d} has to be divisable by 4.",
                _bsp_buffer_size);

   if ((SIZEOF(_BSPcombinfo)!=8) && (SIZEOF(_BSPcombinfo)!=16))
     bsp_abort("MOD_POW2 not going to work for SIZEOF(_BSPcombinfo)");

   if (CEILING_DIV(_bsp_nprocs*_bsp_nprocs,8*SIZEOF(int))  > _bsp_buffer_size)
     bsp_abort("log total exchange -fbspbuffer %d too small. Relink program",
               _bsp_buffer_size);    
       
   if (BSP_MAX_PROCS < 0)
      bsp_abort("{BSP_MAX_PROCS=%d} has to be positive",_bsp_buffer_size);

   if (_bsp_buffer_size < (BSP_MAX_PROCS*SIZEOF(int)))
      bsp_abort("{_bsp_buffer_size=%d}: is too small. "
             "It is required to be at least %d bytes for the\n"
             "internal workings of the library.\n"
             "Recompile your code with the -bspbuffer option",
             _bsp_buffer_size,(BSP_MAX_PROCS*SIZEOF(int)));
   if (_bsp_comm_fifo_size < 1)
      bsp_abort("{_bsp_comm_fifo_size} has to be greater than 1");

   if (MAX_FCOMBINE_MESSAGE_SIZE>65536)
     bsp_abort("{MAX_FCOMBINE_MESSAGE_SIZE} has to be less than 65536 "
               "because of bit manipulations");

   if (_bsp_nbuffers<=0)
     bsp_abort("{_bsp_nbuffers} has to be greater than zero (set to %d)",
               _bsp_nbuffers);
}


