#include "converse.h"
#include <alloca.h>
#include <stdlib.h>

#define NITER 1000000

CpvDeclare(int, exitHandlerIdx);
static int stacksize;

void ExitHandler(void *msg)
{
  CsdExitScheduler();
}

static char endmsg[CmiMsgHeaderSizeBytes];
static double starttime, endtime;
char *buf;

void Yielder(void *arg)
{
  register int i;
  buf = (char *) alloca(stacksize);
  for(i=0;i<stacksize;i++)
    buf[i] = 0;
  starttime = CmiTimer();
  for(i=0;i<NITER;i++) {
    // CmiPrintf("yielding %d\n", i);
    CthYield();
  }
  endtime = CmiTimer();
  CmiPrintf("Context Switching Overhead : %lf microseconds\n", 
            (endtime-starttime)*1.e6/NITER);
  CmiSetHandler(endmsg, CpvAccess(exitHandlerIdx));
  CmiSyncSend(CmiMyPe(), CmiMsgHeaderSizeBytes, endmsg);
}

void test_init(int argc, char **argv)
{
  stacksize = atoi(argv[1]);
  CmiPrintf("Stacksize = %u\n", stacksize);
  CpvInitialize(int, exitHandlerIdx);
  CpvAccess(exitHandlerIdx) = CmiRegisterHandler((CmiHandler)ExitHandler);
  CthThread yielder = CthCreate((CthVoidFn)Yielder, 0, 2*stacksize);
  CthAwaken(yielder);
}

int main(int argc, char **argv)
{
  ConverseInit(argc, argv, test_init, 0, 0);
}
