/*****************************************************************************
 * $Source: /expand6/cvsroot/charm/src/Common/ck-core/msgalloc.C,v $
 * $Author: milind $
 * $Date: 2000/03/02 11:36:08 $
 * $Revision: 2.4 $
 *****************************************************************************/

#include "ck.h"

extern "C"
void *CkAllocSysMsg(void)
{
  return CpvAccess(_msgPool)->get();
}

extern "C"
void CkFreeSysMsg(void *m)
{
  CpvAccess(_msgPool)->put(m);
}

extern "C"
void* CkAllocMsg(int msgIdx, int msgBytes, int prioBits)
{
  register envelope *env = _allocEnv(ForChareMsg, msgBytes, prioBits);
  env->setQueueing(_defaultQueueing);
  env->setMsgIdx(msgIdx);
  return EnvToUsr(env);
}

extern "C"
void* CkAllocBuffer(void *msg, int bufsize)
{
  bufsize = ALIGN(bufsize);
  register envelope *env = UsrToEnv(msg);
  register envelope *packbuf = _allocEnv(env->getMsgtype(), bufsize, 
                                         env->getPriobits());
  register int size = packbuf->getTotalsize();
  memcpy(packbuf, env, sizeof(envelope));
  packbuf->setTotalsize(size);
  packbuf->setPacked(!env->isPacked());
  memcpy(packbuf->getPrioPtr(), env->getPrioPtr(), packbuf->getPrioBytes());
  return EnvToUsr(packbuf);;
}

extern "C"
void  CkFreeMsg(void *msg)
{
  CmiFree(UsrToEnv(msg));
}

// cannot simply copy all fields because srcMsg could be varsize msg

extern "C"
void* CkCopyMsg(void **pMsg)
{
  register void *srcMsg = *pMsg;
  register envelope *env = UsrToEnv(srcMsg);
  register unsigned char msgidx = env->getMsgIdx();
  if(!env->isPacked() && _msgTable[msgidx]->pack) {
    srcMsg = _msgTable[msgidx]->pack(srcMsg);
    UsrToEnv(srcMsg)->setPacked(1);
  }
  register int size = UsrToEnv(srcMsg)->getTotalsize();
  register envelope *newenv = (envelope *) CmiAlloc(size);
  memcpy(newenv, UsrToEnv(srcMsg), size);
  if(UsrToEnv(srcMsg)->isPacked() && _msgTable[msgidx]->unpack) {
    srcMsg = _msgTable[msgidx]->unpack(srcMsg);
    UsrToEnv(srcMsg)->setPacked(0);
  }
  *pMsg = srcMsg;
  if(newenv->isPacked() && _msgTable[msgidx]->unpack) {
    srcMsg = _msgTable[msgidx]->unpack(EnvToUsr(newenv));
    UsrToEnv(srcMsg)->setPacked(0);
  } else srcMsg = EnvToUsr(newenv);

  return srcMsg;
}

extern "C"
void  CkSetQueueing(void *msg, int strategy)
{
  UsrToEnv(msg)->setQueueing((unsigned char) strategy);
}


extern "C"
void* CkPriorityPtr(void *msg)
{
  return UsrToEnv(msg)->getPrioPtr();
}

// This cannot be in the header file because for loop cannot be expanded
// inline by the stupid HP C++ compiler.

MsgPool::MsgPool() 
{ 
  for(int i=0;i<MAXMSGS;i++)
    msgs[i] = _alloc();
  num = MAXMSGS;
}
