Reorganized pgms directory.
authorMilind Bhandarkar <milind@cs.uiuc.edu>
Sat, 7 Aug 1999 22:26:46 +0000 (22:26 +0000)
committerMilind Bhandarkar <milind@cs.uiuc.edu>
Sat, 7 Aug 1999 22:26:46 +0000 (22:26 +0000)
24 files changed:
examples/converse/pingpong/Makefile [new file with mode: 0644]
examples/converse/pingpong/pingpong.C [new file with mode: 0644]
src/conv-ccs/ccs-client.c [new file with mode: 0644]
src/conv-ccs/ccs-client.h [new file with mode: 0644]
tests/converse/megacon/Makefile [new file with mode: 0644]
tests/converse/megacon/README [new file with mode: 0644]
tests/converse/megacon/bigmsg.c [new file with mode: 0644]
tests/converse/megacon/blkinhand.c [new file with mode: 0644]
tests/converse/megacon/broadc.c [new file with mode: 0644]
tests/converse/megacon/deadlock.c [new file with mode: 0644]
tests/converse/megacon/fibobj.c [new file with mode: 0644]
tests/converse/megacon/fibthr.c [new file with mode: 0644]
tests/converse/megacon/future.c [new file with mode: 0644]
tests/converse/megacon/megacon.c [new file with mode: 0644]
tests/converse/megacon/multicast.c [new file with mode: 0644]
tests/converse/megacon/multisend.c [new file with mode: 0644]
tests/converse/megacon/nodenum.c [new file with mode: 0644]
tests/converse/megacon/posixth.c [new file with mode: 0644]
tests/converse/megacon/priotest.c [new file with mode: 0644]
tests/converse/megacon/ring.c [new file with mode: 0644]
tests/converse/megacon/ringsimple.c [new file with mode: 0644]
tests/converse/megacon/specmsg.c [new file with mode: 0644]
tests/converse/megacon/vars.c [new file with mode: 0644]
tests/converse/megacon/vecsend.c [new file with mode: 0644]

diff --git a/examples/converse/pingpong/Makefile b/examples/converse/pingpong/Makefile
new file mode 100644 (file)
index 0000000..d094092
--- /dev/null
@@ -0,0 +1,6 @@
+CHARM=../..
+
+pingpong: pingpong.C
+       $(CHARM)/bin/charmc -language converse++ -O -o pingpong pingpong.C
+
+
diff --git a/examples/converse/pingpong/pingpong.C b/examples/converse/pingpong/pingpong.C
new file mode 100644 (file)
index 0000000..803e1bd
--- /dev/null
@@ -0,0 +1,129 @@
+#include <stdlib.h>
+#include <converse.h>
+
+/* extern "C" int CmiGrabBuffer();*/
+
+enum {nCycles = 1 << 8 };
+enum { maxMsgSize = 1 << 13 };
+
+CpvDeclare(int,msgSize);
+CpvDeclare(int,cycleNum);
+CpvDeclare(int,sizeNum);
+CpvDeclare(int,exitHandler);
+CpvDeclare(int,node0Handler);
+CpvDeclare(int,node1Handler);
+CpvDeclare(double,startTime);
+CpvDeclare(double,endTime);
+CpvDeclare(double,startCTime);
+CpvDeclare(double,endCTime);
+
+void startRing()
+{
+  CmiPrintf("PE %d startRing\n",CmiMyPe());
+  CpvAccess(cycleNum) = 0;
+  CpvAccess(msgSize) = 100 * CpvAccess(sizeNum) + CmiMsgHeaderSizeBytes;
+  CmiPrintf("PE %d startRing allocating %d bytes, header=%d bytes\n",
+           CmiMyPe(),CpvAccess(msgSize),CmiMsgHeaderSizeBytes);
+  CmiPrintf(
+  "       cycles       bytes         Total(ms)     One-way (us/msg)\n"
+  );
+  char *msg = (char *)CmiAlloc(CpvAccess(msgSize));
+  *((int *)(msg+CmiMsgHeaderSizeBytes)) = CpvAccess(msgSize);
+  CmiPrintf("PE %d startRing starting clock\n",CmiMyPe());
+  CpvAccess(startTime) = CmiWallTimer();
+  CpvAccess(startCTime) = CmiTimer();
+  CmiSetHandler(msg,CpvAccess(node0Handler));
+  CmiSyncSendAndFree(0, CpvAccess(msgSize), msg);
+}
+
+void ringFinished(char *msg)
+{
+  CmiPrintf("PE %d ringFinished\n",CmiMyPe());
+  CmiFree(msg);
+  CpvAccess(endTime) = CmiWallTimer();
+  CpvAccess(endCTime) = CmiTimer();
+  CmiPrintf("WALL: %4d \t%8d \t%8.4g \t%8.4g\n",
+           nCycles, CpvAccess(msgSize)-CmiMsgHeaderSizeBytes,
+           (CpvAccess(endTime)-CpvAccess(startTime))*1e3,
+           1e6*(CpvAccess(endTime)-CpvAccess(startTime))/(2.*nCycles)
+  );
+  CmiPrintf(" CPU: %4d \t%8d \t%8.4g \t%8.4g\n",
+           nCycles,CpvAccess(msgSize)-CmiMsgHeaderSizeBytes,
+           (CpvAccess(endCTime)-CpvAccess(startCTime))*1e3, 
+           1e6*(CpvAccess(endCTime)-CpvAccess(startCTime))/(2.*nCycles)
+    );
+  CpvAccess(sizeNum)++;
+  if (CpvAccess(msgSize) < maxMsgSize)
+    startRing();
+  else 
+  {
+    void *sendmsg = CmiAlloc(CmiMsgHeaderSizeBytes);
+    CmiSetHandler(sendmsg,CpvAccess(exitHandler));
+    CmiSyncBroadcastAllAndFree(CmiMsgHeaderSizeBytes,sendmsg);
+  }
+}
+
+CmiHandler exitHandlerFunc(char *msg)
+{
+  CmiFree(msg);
+  CsdExitScheduler();
+  return 0;
+}
+
+CmiHandler node0HandlerFunc(char *msg)
+{
+  CmiGrabBuffer((void **)&msg);
+  //  CmiPrintf("PE %d node0Handler\n",CmiMyPe());
+  CpvAccess(cycleNum)++;
+
+  if (CpvAccess(cycleNum) == nCycles)
+    ringFinished(msg);
+  else
+  {
+    CmiSetHandler(msg,CpvAccess(node1Handler));
+    CmiSyncSendAndFree(1,CpvAccess(msgSize),msg);
+  }
+  return 0;
+}
+
+CmiHandler node1HandlerFunc(char *msg)
+{
+  CmiGrabBuffer((void **)&msg);
+  // CmiPrintf("PE %d node1Handler\n",CmiMyPe());
+  CpvAccess(msgSize) = *((int *)(msg+CmiMsgHeaderSizeBytes));
+  CmiSetHandler(msg,CpvAccess(node0Handler));
+  CmiSyncSendAndFree(0,CpvAccess(msgSize),msg);
+  return 0;
+}
+
+CmiStartFn mymain()
+{
+  CmiPrintf("PE %d of %d starting\n",CmiMyPe(),CmiNumPes());
+
+  CpvInitialize(int,msgSize);
+  CpvInitialize(int,cycleNum);
+  CpvInitialize(int,sizeNum);
+  CpvAccess(sizeNum) = 1;
+
+  CpvInitialize(int,exitHandler);
+  CpvAccess(exitHandler) = CmiRegisterHandler((CmiHandler) exitHandlerFunc);
+  CpvInitialize(int,node0Handler);
+  CpvAccess(node0Handler) = CmiRegisterHandler((CmiHandler) node0HandlerFunc);
+  CpvInitialize(int,node1Handler);
+  CpvAccess(node1Handler) = CmiRegisterHandler((CmiHandler) node1HandlerFunc);
+
+  CpvInitialize(double,startTime);
+  CpvInitialize(double,endTime);
+  CpvInitialize(double,startCTime);
+  CpvInitialize(double,endCTime);
+
+  if (CmiMyPe() == 0)
+    startRing();
+
+  return 0;
+}
+
+main(int argc,char *argv[])
+{
+  ConverseInit(argc,argv,(CmiStartFn)mymain,0,0);
+}
diff --git a/src/conv-ccs/ccs-client.c b/src/conv-ccs/ccs-client.c
new file mode 100644 (file)
index 0000000..1bf9c0d
--- /dev/null
@@ -0,0 +1,302 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include "ccs.h"
+#include <stdio.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <errno.h>
+
+
+static void zap_newline(char *s)
+{
+  char *p;
+  p = s + strlen(s)-1;
+  if (*p == '\n') *p = '\0';
+}
+
+/*
+ * return IP address for hostname. If hostname=0, return self IP
+ */
+static unsigned int skt_ip(char *hostname)
+{
+  unsigned int ip;
+  struct hostent *hostent;
+  if(strcmp(hostname, "") == 0)
+    hostent = gethostent();
+  else {
+    hostent = gethostbyname(hostname);
+  }
+  if (hostent == 0) return 0x7f000001;
+  ip = htonl(*((int *)(hostent->h_addr_list[0])));
+
+  /*Debugging*/
+  printf("hostname = %s, IP address = %u\n", hostname, ip);
+
+  return ip;
+}
+
+static void jsleep(int sec, int usec)
+{
+  int ntimes,i;
+  struct timeval tm;
+
+  ntimes = sec*200 + usec/5000;
+  for(i=0;i<ntimes;i++) {
+    tm.tv_sec = 0;
+    tm.tv_usec = 5000;
+    while(1) {
+      if (select(0,NULL,NULL,NULL,&tm)==0) break;
+      if ((errno!=EBADF)&&(errno!=EINTR)) return;
+    }
+  }
+}
+
+/*
+ * Create a socket connected to <ip> at port <port>
+ */
+static int skt_connect(ip, port, seconds)
+unsigned int ip; int port; int seconds;
+{
+  struct sockaddr_in remote; short sport=port;
+  int fd, ok, len, retry, begin;
+    
+  /* create an address structure for the server */
+  memset(&remote, 0, sizeof(remote));
+  remote.sin_family = AF_INET;
+  remote.sin_port = htons(sport);
+  remote.sin_addr.s_addr = htonl(ip);
+    
+  begin = time(0); ok= -1;
+  while (time(0)-begin < seconds) {
+  sock:
+    fd = socket(AF_INET, SOCK_STREAM, 0);
+    if ((fd<0)&&((errno==EINTR)||(errno==EBADF))) goto sock;
+    if (fd < 0) { perror("socket 3"); exit(1); }
+    
+  conn:
+    ok = connect(fd, (struct sockaddr *)&(remote), sizeof(remote));
+    if (ok>=0) break;
+    close(fd);
+    switch (errno) {
+    case EINTR: case EBADF: case EALREADY: break;
+    case ECONNREFUSED: jsleep(1,0); break;
+    case EADDRINUSE: jsleep(1,0); break;
+    case EADDRNOTAVAIL: jsleep(5,0); break;
+    default: return -1;
+    }
+  }
+  if (ok<0) return -1;
+  return fd;
+}
+
+/*
+ * Create a server socket
+ */
+static void skt_server(CcsServer *svr)
+{
+  int fd= -1;
+  int ok, len;
+  struct sockaddr_in addr;
+  char hostname[100];
+  fd = socket(PF_INET, SOCK_STREAM, 0);
+  if (fd < 0) { perror("socket"); exit(1); }
+  memset(&addr, 0, sizeof(addr));
+  addr.sin_family = AF_INET;
+  ok = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
+  if (ok < 0) { perror("bind"); exit(1); }
+  ok = listen(fd,5);
+  if (ok < 0) { perror("listen"); exit(1); }
+  len = sizeof(addr);
+  ok = getsockname(fd, (struct sockaddr *)&addr, &len);
+  if (ok < 0) { perror("getsockname"); exit(1); }
+
+  if (gethostname(hostname, 99) < 0) strcpy(hostname, "");
+  
+  /*Debugging*/
+  printf("hostname = %s, %d\n", hostname, strlen(hostname));
+
+  svr->myFd = fd;
+  svr->myIP = skt_ip(hostname);
+  svr->myPort = ntohs(addr.sin_port);
+}
+
+static int skt_accept(CcsServer *svr)
+{
+  int i, fd, ok;
+  struct sockaddr_in remote;
+  i = sizeof(remote);
+ acc:
+  fd = accept(svr->myFd, (struct sockaddr *)&remote, &i);
+  if ((fd<0)&&(errno==EINTR)) goto acc;
+  if ((fd<0)&&(errno==EMFILE)) goto acc;
+  if ((fd<0)&&(errno==EPROTO)) goto acc;
+  if (fd<0) { perror("accept"); exit(1); }
+  return fd;
+}
+
+static char *skipstuff(char *line)
+{
+  while (*line != ' ') line++;
+  return line;
+}
+
+static char *skipblanks(char *line)
+{
+  while (*line == ' ') line++;
+  return line;
+}
+
+static void parseInfo(CcsServer *svr, char *line)
+{
+  char ans[32];
+  int num, i;
+  line = skipblanks(line);
+  sscanf(line, "%s", ans);
+  line = skipstuff(line); line = skipblanks(line);
+  sscanf(line, "%d", &(svr->numNodes));
+  line = skipstuff(line); line = skipblanks(line);
+  svr->numProcs = (int *) malloc(svr->numNodes * sizeof(int));
+  svr->nodeIPs = (int *) malloc(svr->numNodes * sizeof(int));
+  svr->nodePorts = (int *) malloc(svr->numNodes * sizeof(int));
+  svr->numPes = 0;
+  for(i=0;i<svr->numNodes;i++) {
+    sscanf(line, "%d", &(svr->numProcs[i]));
+    line = skipstuff(line); line= skipblanks(line);
+    svr->numPes += svr->numProcs[i];
+  }
+  for(i=0;i<svr->numNodes;i++) {
+    sscanf(line, "%d", &(svr->nodeIPs[i]));
+    line = skipstuff(line); line= skipblanks(line);
+  }
+  for(i=0;i<svr->numNodes;i++) {
+    sscanf(line, "%d", &(svr->nodePorts[i]));
+    line = skipstuff(line); line= skipblanks(line);
+  }
+}
+
+static void printSvr(CcsServer *svr)
+{
+  int i;
+  printf("hostIP: %d\n", svr->hostIP);
+  printf("hostPort: %d\n", svr->hostPort);
+  printf("myIP: %d\n", svr->myIP);
+  printf("myPort: %d\n", svr->myPort);
+  printf("myFd: %d\n", svr->myFd);
+  printf("numNodes: %d\n", svr->numNodes);
+  printf("numPes: %d\n", svr->numPes);
+  for(i=0;i<svr->numNodes;i++) {
+    printf("Node[%d] has %d processors at IP=%d, port=%d\n",
+            i, svr->numProcs[i], svr->nodeIPs[i], svr->nodePorts[i]);
+  }
+}
+
+/**
+ * Converse Client-Server Module: Client Side
+ */
+int CcsConnect(CcsServer *svr, char *host, int port)
+{
+  int fd;
+  char ans[32];
+  char line[1024];
+  FILE *f;
+  strcpy(svr->hostAddr, host);
+  svr->hostPort = port;
+  svr->hostIP = skt_ip(host);
+  skt_server(svr);
+  fd = skt_connect(svr->hostIP, svr->hostPort, 120);
+  if(fd == (-1)) {
+    fprintf(stderr, "Cannot connect to server\n");
+    exit(1);
+  }
+  write(fd, "getinfo ", strlen("getinfo "));
+  sprintf(ans, "%d %d\n", svr->myIP, svr->myPort);
+  write(fd, ans, strlen(ans));
+  close(fd);
+  fd = skt_accept(svr);
+  f = fdopen(fd, "r+");
+  line[0] = 0;
+  fgets(line, 1023, f);
+  fclose(f);
+  close(fd);
+  zap_newline(line);
+  parseInfo(svr, line);
+}
+
+int CcsNumNodes(CcsServer *svr)
+{
+  return svr->numNodes;
+}
+
+int CcsNumPes(CcsServer *svr)
+{
+  return svr->numPes;
+}
+
+int CcsNodeFirst(CcsServer *svr, int node)
+{
+  int retval=0,i;
+  for(i=0;i<node;i++) {
+    retval += svr->numProcs[node];
+  }
+  return retval;
+}
+
+int CcsNodeSize(CcsServer *svr,int node)
+{
+  return svr->numProcs[node];
+}
+
+int CcsSendRequest(CcsServer *svr, char *hdlrID, int pe, uint size, void *msg)
+{
+  int startpe=0, endpe=0, i;
+  int fd;
+  char line[1024];
+  for(i=0;i<svr->numNodes;i++) {
+    endpe += svr->numProcs[i];
+    if(pe >= startpe && pe < endpe)
+      break;
+    startpe = endpe;
+  }
+  pe -= startpe;
+  fd = skt_connect(svr->nodeIPs[i], svr->nodePorts[i], 120);
+  sprintf(line, "req %d %d %d %d %s\n", pe, size, svr->myIP, svr->myPort, 
+                                        hdlrID);
+  write(fd, line, strlen(line));
+  write(fd, msg, size);
+  close(fd);
+}
+
+int CcsRecvResponse(CcsServer *svr, uint maxsize, void *recvBuffer)
+{
+  char line[1024], ans[16];
+  int size, fd;
+  FILE *f;
+  fd = skt_accept(svr);
+  f = fdopen(fd, "r+");
+  line[0] = 0;
+  fgets(line, 1023, f);
+  zap_newline(line);
+  sscanf(line, "%s%d", ans, &size);
+  fread(recvBuffer, 1, size, f);
+  fclose(f); close(fd);
+}
+
+int CcsProbe(CcsServer *svr)
+{
+  fprintf(stderr, "CcsProbe not implemented.\n");
+  exit(1);
+}
+
+int CcsResponseHandler(CcsServer *svr, CcsHandlerFn fn)
+{
+  svr->callback = fn;
+  fprintf(stderr, "CcsResponseHandler not implemented.\n");
+  exit(1);
+}
+
+int CcsFinalize(CcsServer *svr)
+{
+  close(svr->myFd);
+}
diff --git a/src/conv-ccs/ccs-client.h b/src/conv-ccs/ccs-client.h
new file mode 100644 (file)
index 0000000..7c492b3
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+ * Converse Client-Server Module: Client Side
+ */
+
+#ifndef _CCS_H_
+#define _CCS_H_
+
+typedef int (*CcsHandlerFn)(int, void *);
+
+typedef struct CcsServer {
+  char hostAddr[128];
+  unsigned int hostIP;
+  unsigned int hostPort;
+  unsigned int myIP;
+  unsigned int myPort;
+  int myFd;
+  int numNodes;
+  int numPes;
+  int *numProcs;
+  int *nodeIPs;
+  int *nodePorts;
+  CcsHandlerFn callback;
+} CcsServer;
+
+int CcsConnect(CcsServer *svr, char *host, int port);
+int CcsNumNodes(CcsServer *svr);
+int CcsNumPes(CcsServer *svr);
+int CcsNodeFirst(CcsServer *svr, int node);
+int CcsNodeSize(CcsServer *svr,int node);
+int CcsSendRequest(CcsServer *svr, char *hdlrID, int pe, unsigned int size, void *msg);
+int CcsRecvResponse(CcsServer *svr, unsigned int maxsize, void *recvBuffer);
+int CcsProbe(CcsServer *svr);
+int CcsResponseHandler(CcsServer *svr, CcsHandlerFn fn);
+int CcsFinalize(CcsServer *svr);
+
+#endif
diff --git a/tests/converse/megacon/Makefile b/tests/converse/megacon/Makefile
new file mode 100644 (file)
index 0000000..a2c588e
--- /dev/null
@@ -0,0 +1,82 @@
+OPTS=-g
+CHARMC=../../bin/charmc $(OPTS)
+
+OBJS=blkinhand.o megacon.o ringsimple.o ring.o fibobj.o fibthr.o broadc.o priotest.o deadlock.o vars.o nodenum.o specmsg.o bigmsg.o vecsend.o posixth.o future.o multicast.o multisend.o
+
+pgm: $(OBJS) link
+
+link:
+       $(CHARMC) -o pgm $(OBJS) -language converse++
+
+megacon.o: megacon.c
+       $(CHARMC) -gen-cpm megacon.c
+       $(CHARMC) megacon.c
+
+blkinhand.o: blkinhand.c
+       $(CHARMC) -gen-cpm blkinhand.c
+       $(CHARMC) blkinhand.c
+
+ring.o: ring.c
+       $(CHARMC) -gen-cpm ring.c
+       $(CHARMC) ring.c
+
+ringsimple.o: ringsimple.c
+       $(CHARMC) ringsimple.c
+
+vecsend.o: vecsend.c
+       $(CHARMC) -gen-cpm vecsend.c
+       $(CHARMC) vecsend.c
+
+multicast.o: multicast.c
+       $(CHARMC) multicast.c
+
+fibobj.o: fibobj.c
+       $(CHARMC) -gen-cpm fibobj.c
+       $(CHARMC) fibobj.c
+
+fibthr.o: fibthr.c
+       $(CHARMC) -gen-cpm fibthr.c
+       $(CHARMC) fibthr.c
+
+broadc.o: broadc.c
+       $(CHARMC) broadc.c
+
+priotest.o: priotest.c
+       $(CHARMC) -gen-cpm priotest.c
+       $(CHARMC) priotest.c
+
+deadlock.o: deadlock.c
+       $(CHARMC) deadlock.c
+
+vars.o: vars.c
+       $(CHARMC) -gen-cpm vars.c
+       $(CHARMC) vars.c
+
+nodenum.o: nodenum.c
+       $(CHARMC) -gen-cpm nodenum.c
+       $(CHARMC) nodenum.c
+
+future.o: future.c
+       $(CHARMC) -gen-cpm future.c
+       $(CHARMC) future.c
+
+specmsg.o: specmsg.c
+       $(CHARMC) -gen-cpm specmsg.c
+       $(CHARMC) specmsg.c
+
+bigmsg.o: bigmsg.c
+       $(CHARMC) -gen-cpm bigmsg.c
+       $(CHARMC) bigmsg.c
+
+posixth.o: posixth.c
+       $(CHARMC) -gen-cpm posixth.c
+       $(CHARMC) posixth.c
+
+multisend.o: multisend.c
+       $(CHARMC) multisend.c
+
+clean:
+       rm -f core *.cpm.h
+       rm -f TAGS *.o
+       rm -f pgm
+       rm -f conv-host
diff --git a/tests/converse/megacon/README b/tests/converse/megacon/README
new file mode 100644 (file)
index 0000000..a6e024c
--- /dev/null
@@ -0,0 +1,71 @@
+
+When running the megacon test, you can skip a test by typing a
+negative-sign and the test's name on the command line.  For example,
+
+  % conv-host pgm +p4 -timer -specmsg
+
+would run all the tests except the timer and specmsg tests.
+
+The megacon test currently contains these modules.
+
+  bigmsg - sends a 1-meg message in a ring around the processors.
+  fibobj - computes fib(12) using a charm-like programming style.
+  fibthr - computes fib(12) using threads and thread-sync mechanisms.
+  priotest - enqueues many messages, makes sure they come out in right order.
+  timer - verifies that the CmiTimer is comparable to unix time function.
+  broadc - checks CmiSyncBroadcastAll, CmiSyncBroadcastAllAndFree.
+  ring - a ring that uses all the CPM packing and unpacking mechanisms.
+  vars - checks privacy of Ctv, Cpv, checks sharing of Csv.
+  deadlock - PE's 0 and 1 try to cram 50000 messages down each other's throats.
+  specmsg - verifies that CmiDeliverSpecificMsg works.
+  nodenum - checks that CmiMyRank and Csv vars are consistent.
+
+The major weaknesses in the tests above:
+
+  priotest - only tests integer priorities.
+  timer - assumes that CmiTimer is a real-time timer.
+  broadc - doesn't test Async broadcasts
+  ring - doesn't use the CPM type-declaration mechanisms.
+  nodenum - needs to test CmiNodeBarrier as well.
+
+These things need to be tested, but aren't tested at all:
+
+  - memory leakage.
+  - the message manager.
+
+Here are the rules for adding tests:
+
+  1. Each test has a function called testname_moduleinit, which is called
+     early on.  Use this to initialize Cpv variables and such.  Each test
+     also has a function called testname_init, which is used to trigger
+     the test into action.
+
+  2. A failed test may print an error message, but a successful test
+     must not print anything at all.  Successful tests must verify their
+     own functioning.  When the test is sure it has succeeded, it must
+     call the function Cpm_megacon_ack(CpmSend(0)) to acknowledge its
+     success to the main module.
+
+  3. The main module contains a table of tests.  Each entry in the table
+     has the following fields:
+
+       - test name,
+       - name of the init function,
+       - name of the moduleinit function,
+       - a flag if the test should be tested reentrantly,
+       - a count indicating how many acks the test will produce.
+
+     If the test is marked reentrant, the main module will attempt to run
+     several copies of the test at the same time.  The ack count indicates
+     how many times the test will call Cpm_megacon_ack on a successful
+     completion: 0 means as many times as there are processors.
+
+The megacon test will run
+
+       1. each test, one at a time,
+       2. each reentrant test, in a group of 5 at a time,
+       3. all the tests at the same time.
+
+If all this succeeds, megacon will declare the system OK.
+
+- Josh
diff --git a/tests/converse/megacon/bigmsg.c b/tests/converse/megacon/bigmsg.c
new file mode 100644 (file)
index 0000000..d0d2ad5
--- /dev/null
@@ -0,0 +1,47 @@
+#include <stdio.h>
+#include <time.h>
+#include <converse.h>
+
+CpvDeclare(int, bigmsg_index);
+
+#define CmiMsgHeaderSizeInts \
+    ((CmiMsgHeaderSizeBytes+sizeof(int)-1)/sizeof(int))
+
+void Cpm_megacon_ack();
+
+void bigmsg_handler(int *msg)
+{
+  int i, next;
+  if (CmiMyPe()==0) {
+    for (i=CmiMsgHeaderSizeInts; i<250000; i++) {
+      if (msg[i] != i) {
+       CmiPrintf("Failure in bigmsg test, data corrupted.\n");
+       exit(1);
+      }
+    }
+    Cpm_megacon_ack(CpmSend(0));
+  } else {
+    next = (CmiMyPe()+1) % CmiNumPes();
+    CmiSyncSend(next, 250000*sizeof(int), msg);
+  }
+}
+
+void bigmsg_init()
+{
+  int i, *msg;
+  if (CmiNumPes()<2) {
+    CmiPrintf("note: bigmsg requires at least 2 processors, skipping test.\n");
+    Cpm_megacon_ack(CpmSend(0));
+  } else {
+    msg = CmiAlloc(250000 * sizeof(int));
+    for (i=CmiMsgHeaderSizeInts; i<250000; i++) msg[i] = i;
+    CmiSetHandler(msg, CpvAccess(bigmsg_index));
+    CmiSyncSendAndFree(1, 250000 * sizeof(int), msg);
+  }
+}
+
+void bigmsg_moduleinit()
+{
+  CpvInitialize(int, bigmsg_index);
+  CpvAccess(bigmsg_index) = CmiRegisterHandler(bigmsg_handler);
+}
diff --git a/tests/converse/megacon/blkinhand.c b/tests/converse/megacon/blkinhand.c
new file mode 100644 (file)
index 0000000..83474c3
--- /dev/null
@@ -0,0 +1,76 @@
+#include <stdio.h>
+#include <converse.h>
+void Cpm_megacon_ack();
+
+/* an accumulator datatype, which can have one pending thread */
+
+typedef struct accum
+{
+  int total; int countdown;
+  CthThread pending;
+}
+*accum;
+
+CpmDeclareSimple(accum);
+#define CpmPack_accum(x)
+#define CpmUnpack_accum(x)
+
+#include "blkinhand.cpm.h"
+
+int blk_randpe()
+{
+  return ((rand()&0x7FFFFFFF)>>11) % CmiNumPes();
+}
+
+/* a function to add a number to an accumulator */
+
+CpmInvokable blk_accum_add(accum a, int val)
+{
+  a->total += val;
+  a->countdown --;
+  if ((a->countdown==0)&&(a->pending))
+    CthAwaken(a->pending);
+}
+
+/* The fib function: calculate fib of N, then add it to the specified accum */
+
+CpmInvokable blk_fibthr(int n, int pe, accum resp)
+{
+  int result;
+  if (n<2) result = n;
+  else {
+    struct accum acc;
+    acc.total = 0; acc.countdown = 2; acc.pending = CthSelf();
+    Cpm_blk_fibthr(CpmSend(blk_randpe()), n-1, CmiMyPe(), &acc);
+    Cpm_blk_fibthr(CpmSend(blk_randpe()), n-2, CmiMyPe(), &acc);
+    CthSuspend();
+    result = acc.total;
+  }
+  Cpm_blk_accum_add(CpmSend(pe), resp, result);
+}
+
+/* The top-level function */
+
+CpmInvokable blk_fibtop(int n)
+{
+  struct accum acc;
+  acc.total = 0; acc.countdown = 1; acc.pending = CthSelf();
+  Cpm_blk_fibthr(CpmSend(blk_randpe()), n, CmiMyPe(), &acc);
+  CthSuspend();
+  if (acc.total != 21) {
+    CmiPrintf("blkinhand failed. %08x\n", CthSelf());
+    CmiPrintf("Failure in blk_fibtop\n");
+    exit(1);
+  }
+  Cpm_megacon_ack(CpmSend(0));
+}
+
+void blkinhand_init()
+{
+  Cpm_blk_fibtop(CpmSend(0), 8);
+}
+
+void blkinhand_moduleinit()
+{
+  CpmInitializeThisModule();
+}
diff --git a/tests/converse/megacon/broadc.c b/tests/converse/megacon/broadc.c
new file mode 100644 (file)
index 0000000..5c656da
--- /dev/null
@@ -0,0 +1,85 @@
+#include <stdio.h>
+#include <converse.h>
+
+void Cpm_megacon_ack();
+
+typedef struct bchare
+{
+  int totalsent;
+  int totalreplies;
+}
+*bchare;
+
+typedef struct mesg
+{
+  char head[CmiMsgHeaderSizeBytes];
+  int reply_pe;
+  bchare reply_ptr;
+  int magic;
+}
+*mesg;
+
+CpvDeclare(int, broadc_recv_idx);
+CpvDeclare(int, broadc_reply_idx);
+
+void broadc_recv(mesg m)
+{
+  if (m->magic != 0x12345678) {
+    CmiPrintf("broadc failed.\n");
+    exit(1);
+  }
+  CmiSetHandler(m, CpvAccess(broadc_reply_idx));
+  CmiSyncSend(m->reply_pe, sizeof(struct mesg), m);
+}
+
+void broadc_start_cycle(bchare c)
+{
+  struct mesg m; struct mesg *mp; CmiCommHandle h;
+  switch (c->totalsent) {
+  case 0:
+    CmiSetHandler(&m, CpvAccess(broadc_recv_idx));
+    m.reply_ptr = c; m.reply_pe = CmiMyPe(); m.magic = 0x12345678;
+    CmiSyncBroadcastAll(sizeof(struct mesg),&m);
+    c->totalsent++;
+    break;
+  case 1:
+  case 2:
+    mp = (mesg)CmiAlloc(sizeof(struct mesg));
+    CmiSetHandler(mp, CpvAccess(broadc_recv_idx));
+    mp->reply_ptr = c; mp->reply_pe = CmiMyPe(); mp->magic = 0x12345678;
+    CmiSyncBroadcastAllAndFree(sizeof(struct mesg),mp);
+    c->totalsent++;
+    break;
+  case 3:
+    free(c);
+    Cpm_megacon_ack(CpmSend(0));
+  }
+}
+
+void broadc_reply(mesg m)
+{
+  bchare c;
+  if (m->magic != 0x12345678) {
+    CmiPrintf("broadc failed.\n");
+    exit(1);
+  }
+  c = m->reply_ptr;
+  c->totalreplies++;
+  if ((c->totalreplies % CmiNumPes())==0) broadc_start_cycle(c);
+}
+
+void broadc_init(void)
+{
+  bchare c = (bchare)malloc(sizeof(struct bchare));
+  c->totalsent = 0;
+  c->totalreplies = 0;
+  broadc_start_cycle(c);
+}
+
+void broadc_moduleinit()
+{
+  CpvInitialize(int, broadc_recv_idx);
+  CpvInitialize(int, broadc_reply_idx);
+  CpvAccess(broadc_recv_idx) = CmiRegisterHandler(broadc_recv);
+  CpvAccess(broadc_reply_idx) = CmiRegisterHandler(broadc_reply);
+}
diff --git a/tests/converse/megacon/deadlock.c b/tests/converse/megacon/deadlock.c
new file mode 100644 (file)
index 0000000..46861b5
--- /dev/null
@@ -0,0 +1,151 @@
+#include <stdio.h>
+#include <converse.h>
+
+typedef struct incmsg
+{
+  char head[CmiMsgHeaderSizeBytes];
+  int n;
+}
+*incmsg;
+
+CpvDeclare(int, deadlock_inc_idx);
+CpvDeclare(int, deadlock_cram_idx);
+CpvDeclare(int, deadlock_count);
+
+void Cpm_megacon_ack();
+
+void deadlock_inc(incmsg m)
+{
+  CpvAccess(deadlock_count) += m->n;
+  if (CpvAccess(deadlock_count)==0) {
+    Cpm_megacon_ack(CpmSend(0));
+  }
+}
+
+void deadlock_cram(char *msg)
+{
+  struct incmsg m;
+  int count = 0;
+  CmiSetHandler(&m, CpvAccess(deadlock_inc_idx));
+  m.n = 1;
+  while (count<50000) {
+    CmiSyncSend(1-CmiMyPe(), sizeof(m), &m);
+    count++;
+  } 
+  m.n = -count;
+  CmiSyncSend(1-CmiMyPe(), sizeof(m), &m);
+}
+
+void deadlock_init()
+{
+  char msg[CmiMsgHeaderSizeBytes];
+  if (CmiNumPes()<2) {
+    CmiPrintf("warning: need 2 processors for deadlock-test, skipping.\n");
+    Cpm_megacon_ack(CpmSend(0));
+    Cpm_megacon_ack(CpmSend(0));
+  } else {
+    CmiSetHandler(msg, CpvAccess(deadlock_cram_idx));
+    CmiSyncSend(0, sizeof(msg), msg);
+    CmiSyncSend(1, sizeof(msg), msg);
+  }
+}
+
+#if CMK_DEBUG_MODE
+
+static const char* _fCramHeaderStr = "DeadLock Cram Header";
+static const char* _fCramContentStr = "DeadLock Cram Message";
+static const char* _fIncHeaderStr = "DeadLock Inc Header";
+static const char* _fIncContentStr = "DeadLock Inc Message";
+
+static char* fCramHeader(char *msg){
+  char *temp;
+
+  temp = (char *)malloc(strlen(_fCramHeaderStr) + 1);
+  strcpy(temp, _fCramHeaderStr);
+  return(temp);
+}
+
+static char* fCramContent(char *msg){
+  char *temp;
+  
+  temp = (char *)malloc(strlen(_fCramContentStr) + 1);
+  strcpy(temp, _fCramContentStr);
+  return(temp);
+}
+
+static char* fIncHeader(char *msg){
+  char *temp;
+
+  temp = (char *)malloc(strlen(_fIncHeaderStr) + 1);
+  strcpy(temp, _fIncHeaderStr);
+  return(temp);
+}
+
+static char* fIncContent(char *msg){
+  char *temp;
+  
+  temp = (char *)malloc(strlen(_fIncContentStr) + 1 + 5);
+  sprintf(temp, "%s:%d", _fIncContentStr, ((incmsg)msg)->n);
+  return(temp);
+}
+
+char* makeIncSymbolTableInfo()
+{
+  int i, chareIndex;
+  int size;
+  char *returnInfo;
+  char temp[10];
+  
+  size = 200;
+  returnInfo = (char *)malloc(size * sizeof(char));
+  strcpy(returnInfo, "");
+  strcat(returnInfo, "Converse Handler : deadlock_inc");
+  strcat(returnInfo, "#");
+  
+  return(returnInfo);
+}
+
+int getInd(char *msg)
+{
+  return 0;
+}
+
+char* makeCramSymbolTableInfo()
+{
+  int i, chareIndex;
+  int size;
+  char *returnInfo;
+  char temp[10];
+  
+  size = 200;
+  returnInfo = (char *)malloc(size * sizeof(char));
+  strcpy(returnInfo, "");
+  strcat(returnInfo, "Converse Handler : deadlock_cram");
+  strcat(returnInfo, "#");
+  
+  return(returnInfo);
+}
+
+#endif
+
+void deadlock_moduleinit()
+{
+  CpvInitialize(int, deadlock_inc_idx);
+  CpvInitialize(int, deadlock_cram_idx);
+  CpvInitialize(int, deadlock_count);
+  CpvAccess(deadlock_inc_idx) = CmiRegisterHandler(deadlock_inc);
+  CpvAccess(deadlock_cram_idx) = CmiRegisterHandler(deadlock_cram);
+#if CMK_DEBUG_MODE
+  handlerArrayRegister(CpvAccess(deadlock_inc_idx), fIncHeader, fIncContent);
+  handlerArrayRegister(CpvAccess(deadlock_cram_idx),fCramHeader, fCramContent);
+  
+  symbolTableFnArrayRegister(CpvAccess(deadlock_inc_idx), 1,
+                            makeIncSymbolTableInfo,
+                            getInd);
+  symbolTableFnArrayRegister(CpvAccess(deadlock_cram_idx), 1,
+                            makeCramSymbolTableInfo,
+                            getInd);
+  
+#endif
+  CpvAccess(deadlock_count) = 0;
+}
diff --git a/tests/converse/megacon/fibobj.c b/tests/converse/megacon/fibobj.c
new file mode 100644 (file)
index 0000000..b1ac0d2
--- /dev/null
@@ -0,0 +1,87 @@
+#include <stdio.h>
+#include <converse.h>
+
+/*
+ *  Input:    10   11   12   13   14   15   16   17   18   19   20
+ *  Output:   55   89  144  233  377  610  987 1597 2584 4181 6765
+ */
+
+#define FIB_INPUT 17
+#define FIB_OUTPUT 1597
+
+void Cpm_megacon_ack();
+
+typedef struct fibobj_chare
+{
+  int ppe;
+  struct fibobj_chare *ppos;
+  int count, total;
+}
+*fibobj_chare;
+
+/* We can declare this a simple type, as long as valid pointers */
+/* don't leave the address space */
+
+CpmDeclareSimple(fibobj_chare);
+
+void CpmPack_fibobj_chare(fibobj_chare v)
+{
+  return;
+}
+
+void CpmUnpack_fibobj_chare(fibobj_chare v)
+{
+  return;
+}
+
+#include "fibobj.cpm.h"
+
+CpmDestination CpmLDB()
+{
+  int pe = ((rand()&0x7FFFFFFF)>>8) % CmiNumPes();
+  return CpmSend(pe);
+}
+
+CpmInvokable fibobj_result(int n, fibobj_chare cpos)
+{
+  fibobj_chare c = cpos;
+  c->total += n; c->count ++;
+  if (c->count == 2) {
+    if (c->ppe >= 0)
+      Cpm_fibobj_result(CpmSend(c->ppe), c->total, c->ppos);
+    else {
+      if (c->total != FIB_OUTPUT) {
+       CmiPrintf("Fib: results incorrect.\n");
+       exit(1);
+      }
+      Cpm_megacon_ack(CpmSend(0));
+    }
+    free(c);
+  }
+}
+
+CpmInvokable fibobj_calc(int n, int ppe, fibobj_chare ppos)
+{
+  if (n<2) Cpm_fibobj_result(CpmSend(ppe), n, ppos);
+  else {
+    fibobj_chare c = (fibobj_chare)malloc(sizeof(struct fibobj_chare));
+    c->ppe = ppe, c->ppos = ppos; c->count=c->total=0;
+    Cpm_fibobj_calc(CpmLDB(), n-1, CmiMyPe(), c);
+    Cpm_fibobj_calc(CpmLDB(), n-2, CmiMyPe(), c);
+  }
+}
+
+void fibobj_init()
+{
+  fibobj_chare c = (fibobj_chare)malloc(sizeof(struct fibobj_chare));
+  c->ppe = -1, c->ppos = (fibobj_chare)FIB_INPUT; c->total=0; c->count=1;
+  Cpm_fibobj_calc(CpmLDB(), FIB_INPUT, CmiMyPe(), c);
+}
+
+void fibobj_moduleinit()
+{
+  CpmInitializeThisModule();
+}
+
+
+
diff --git a/tests/converse/megacon/fibthr.c b/tests/converse/megacon/fibthr.c
new file mode 100644 (file)
index 0000000..28e17d0
--- /dev/null
@@ -0,0 +1,75 @@
+#include <stdio.h>
+#include <converse.h>
+void Cpm_megacon_ack();
+
+/* an accumulator datatype, which can have one pending thread */
+
+typedef struct accum
+{
+  int total; int countdown;
+  CthThread pending;
+}
+*accum;
+
+CpmDeclareSimple(accum);
+#define CpmPack_accum(x)
+#define CpmUnpack_accum(x)
+
+#include "fibthr.cpm.h"
+
+int randpe()
+{
+  return ((rand()&0x7FFFFFFF)>>11) % CmiNumPes();
+}
+
+/* a function to add a number to an accumulator */
+
+CpmInvokable accum_add(accum a, int val)
+{
+  a->total += val;
+  a->countdown --;
+  if ((a->countdown==0)&&(a->pending))
+    CthAwaken(a->pending);
+}
+
+/* The fib function: calculate fib of N, then add it to the specified accum */
+
+CpmInvokable fibthr(int n, int pe, accum resp)
+{
+  int result;
+  if (n<2) result = n;
+  else {
+    struct accum acc;
+    acc.total = 0; acc.countdown = 2; acc.pending = CthSelf();
+    Cpm_fibthr(CpmMakeThreadSize(randpe(),0), n-1, CmiMyPe(), &acc);
+    Cpm_fibthr(CpmMakeThreadSize(randpe(),0), n-2, CmiMyPe(), &acc);
+    CthSuspend();
+    result = acc.total;
+  }
+  Cpm_accum_add(CpmSend(pe), resp, result);
+}
+
+/* The top-level function */
+
+CpmInvokable fibtop(int n)
+{
+  struct accum acc;
+  acc.total = 0; acc.countdown = 1; acc.pending = CthSelf();
+  Cpm_fibthr(CpmMakeThreadSize(randpe(),0), n, CmiMyPe(), &acc);
+  CthSuspend();
+  if (acc.total != 144) {
+    CmiPrintf("Failure in fibtop\n");
+    exit(1);
+  }
+  Cpm_megacon_ack(CpmSend(0));
+}
+
+void fibthr_init()
+{
+  Cpm_fibtop(CpmMakeThreadSize(0,0), 12);
+}
+
+void fibthr_moduleinit()
+{
+  CpmInitializeThisModule();
+}
diff --git a/tests/converse/megacon/future.c b/tests/converse/megacon/future.c
new file mode 100644 (file)
index 0000000..2a66dee
--- /dev/null
@@ -0,0 +1,49 @@
+#include <stdio.h>
+#include <converse.h>
+#include "future.cpm.h"
+
+void Cpm_megacon_ack();
+
+void future_fail()
+{
+  CmiPrintf("data corrupted in future test.\n");
+  exit(1);
+}
+
+CpmInvokable future_sendback(Cfuture f)
+{
+  int i = CmiMyPe();
+  CfutureSet(f, &i, sizeof(int));
+}
+
+void future_wait(Cfuture *futures)
+{
+  int i; int *val;
+  for (i=0; i<CmiNumPes(); i++) {
+    val = (int*)CfutureWait(futures[i]);
+    if (*val != i) future_fail();
+    CfutureDestroy(futures[i]);
+  }
+  Cpm_megacon_ack(CpmSend(0));
+  CthFree(CthSelf());
+  CthSuspend();
+}
+
+void future_init(void)
+{
+  int i; CthThread t;
+  Cfuture *futures;
+  futures=(Cfuture *)malloc(CmiNumPes()*sizeof(Cfuture));
+  for (i=0; i<CmiNumPes(); i++) {
+    futures[i] = CfutureCreate();
+    Cpm_future_sendback(CpmSend(i), futures[i]);
+  }
+  t = CthCreate((CthVoidFn)future_wait, (void *)futures, 0);
+  CthSetStrategyDefault(t);
+  CthAwaken(t);
+}
+
+void future_moduleinit()
+{
+  CpmInitializeThisModule();
+}
diff --git a/tests/converse/megacon/megacon.c b/tests/converse/megacon/megacon.c
new file mode 100644 (file)
index 0000000..b0d75cd
--- /dev/null
@@ -0,0 +1,245 @@
+ /**************************************************************************
+ * DESCRIPTION:
+ *
+ * To add a test to megacon, you have to:
+ *
+ *   1. write a testname_moduleinit function that initializes the module.
+ *   2. write a testname_init function that starts the test.
+ *   3. declare the testname_init function inside this module.
+ *   4. extend the tests[] table in this module to include the new test.
+ *
+ **************************************************************************/
+
+#include <stdio.h>
+#include <converse.h>
+#include "megacon.cpm.h"
+
+/******************************************************************************
+ *
+ * Test Configuration Section
+ *
+ *****************************************************************************/
+
+void blkinhand_init(void);
+void posixth_init(void);
+void future_init(void);
+void bigmsg_init(void);
+void vecsend_init(void);
+void nodenum_init(void);
+void specmsg_init(void);
+void vars_init(void);
+void priotest_init(void);
+void ringsimple_init(void);
+void ring_init(void);
+void fibobj_init(void);
+void fibthr_init(void);
+void broadc_init(void);
+void multicast_init(void);
+void deadlock_init(void);
+void multisend_init(void);
+
+void blkinhand_moduleinit(void);
+void posixth_moduleinit(void);
+void future_moduleinit(void);
+void bigmsg_moduleinit(void);
+void vecsend_moduleinit(void);
+void nodenum_moduleinit(void);
+void specmsg_moduleinit(void);
+void vars_moduleinit(void);
+void priotest_moduleinit(void);
+void ringsimple_moduleinit(void);
+void ring_moduleinit(void);
+void fibobj_moduleinit(void);
+void fibthr_moduleinit(void);
+void broadc_moduleinit(void);
+void multicast_moduleinit(void);
+void deadlock_moduleinit(void);
+void multisend_moduleinit(void);
+
+struct testinfo
+{
+  char *name;
+  void (*initiator)(void);
+  void (*initializer)(void);
+  int  reentrant;
+  int  numacks;
+}
+tests[] = {
+  { "blkinhand", blkinhand_init, blkinhand_moduleinit,  1,  1 },
+  { "posixth",   posixth_init,   posixth_moduleinit,    0,  1 },
+  { "future",    future_init,    future_moduleinit,     1,  1 },
+  { "bigmsg",    bigmsg_init,    bigmsg_moduleinit,     1,  1 },
+  { "vecsend",   vecsend_init,   vecsend_moduleinit,    0,  1 },
+  { "nodenum",   nodenum_init,   nodenum_moduleinit,    0,  1 },
+  { "specmsg",   specmsg_init,   specmsg_moduleinit,    0,  0 },
+  { "vars",      vars_init,      vars_moduleinit,       0,  1 },
+  { "priotest",  priotest_init,  priotest_moduleinit,   1,  0 },
+  { "ringsimple",ringsimple_init,ringsimple_moduleinit, 0, 10 },
+  { "ring",      ring_init,      ring_moduleinit,       1,  1 },
+  { "fibobj",    fibobj_init,    fibobj_moduleinit,     1,  1 },
+  { "fibthr",    fibthr_init,    fibthr_moduleinit,     1,  1 },
+  { "broadc",    broadc_init,    broadc_moduleinit,     1,  1 },
+  { "multicast", multicast_init, multicast_moduleinit,  1,  1 },
+  { "deadlock",  deadlock_init,  deadlock_moduleinit,   0,  2 },
+  { "multisend", multisend_init, multisend_moduleinit,  0,  1 },
+  { 0,0,0,0 },
+};
+
+/******************************************************************************
+ *
+ * Central Control Section
+ *
+ *****************************************************************************/
+
+CpvDeclare(int, test_bank_size);
+CpvDeclare(int, test_negate_skip);
+CpvDeclare(char **, tests_to_skip);
+CpvDeclare(int, num_tests_to_skip);
+CpvDeclare(double, test_start_time);
+CpvDeclare(int, next_test_index);
+CpvDeclare(int, next_test_number);
+CpvDeclare(int, acks_expected);
+CpvDeclare(int, acks_received);
+
+/* The megacon shutdown sequence is to idle for a while, then exit.  */
+/* the idling period makes it possible to detect extra runaway msgs. */
+
+CpmInvokable megacon_stop()
+{
+  CsdExitScheduler();
+}
+
+CpmInvokable megacon_shutdown(int n)
+{
+  if (n==0) {
+    CmiPrintf("exiting.\n");
+    Cpm_megacon_stop(CpmSend(CpmALL));
+  } else {
+    Cpm_megacon_shutdown(CpmEnqueueIFIFO(0, 1), n-1);
+  }
+}
+
+int megacon_skip(char *test)
+{
+  int i;
+  int num_skip = CpvAccess(num_tests_to_skip);
+  char **skip;
+  skip = CpvAccess(tests_to_skip);
+  for (i=0; i<num_skip; i++) {
+    if ((skip[i][0]=='-')&&(strcmp(skip[i]+1, test)==0))
+      return 1 - CpvAccess(test_negate_skip);
+  }
+  return CpvAccess(test_negate_skip);
+}
+
+void megacon_next()
+{
+  int i, pos, idx, num, bank, numacks;
+
+  bank = CpvAccess(test_bank_size);
+  num = CpvAccess(next_test_number);
+nextidx:
+  idx = CpvAccess(next_test_index);
+  if (idx < bank) {
+    numacks = tests[idx].numacks;
+    if (megacon_skip(tests[idx].name)) {
+      CpvAccess(next_test_index)++;
+      goto nextidx;
+    }
+    CpvAccess(acks_expected) = numacks ? numacks : CmiNumPes();
+    CpvAccess(acks_received) = 0;
+    CpvAccess(test_start_time) = CmiWallTimer();
+    CmiPrintf("test %d: initiated [%s]\n", num, tests[idx].name);
+    (tests[idx].initiator)();
+    return; 
+  }
+  if (idx < (2*bank)) {
+    pos = idx - bank;
+    numacks = tests[pos].numacks;
+    if ((tests[pos].reentrant == 0)||(megacon_skip(tests[pos].name))||
+       CpvAccess(test_negate_skip)) {
+      CpvAccess(next_test_index)++;
+      goto nextidx;
+    }
+    CpvAccess(acks_expected) = 5 * (numacks ? numacks : CmiNumPes());
+    CpvAccess(acks_received) = 0;
+    CpvAccess(test_start_time) = CmiWallTimer();
+    CmiPrintf("test %d: initiated [multi %s]\n", num, tests[pos].name);
+    for (i=0; i<5; i++) (tests[pos].initiator)();
+    return;
+  }
+  if (idx== (2*bank)) {
+    CpvAccess(acks_expected) = 0;
+    CpvAccess(acks_received) = 0;
+    CpvAccess(test_start_time) = CmiWallTimer();
+    CmiPrintf("test %d: initiated [all-at-once]\n", num);
+    for (i=0; i<bank; i++) {
+      numacks = tests[i].numacks;
+      if (!megacon_skip(tests[i].name)) {
+       CpvAccess(acks_expected) += (numacks ? numacks : CmiNumPes());
+       (tests[i].initiator)();
+      }
+    }
+    return;
+  }
+  if (idx== ((2*bank)+1)) {
+    CmiPrintf("All tests completed, verifying quiescence...\n");
+    Cpm_megacon_shutdown(CpmSend(0), 50000);
+    return;
+  }
+  CmiPrintf("System should have been quiescent, but it wasnt.\n");
+  exit(1);
+}
+
+CpmInvokable megacon_ack()
+{
+  CpvAccess(acks_received)++;
+  if (CpvAccess(acks_received) == CpvAccess(acks_expected)) {
+    CmiPrintf("test %d: completed (%1.2f sec)\n",
+             CpvAccess(next_test_number),
+             CmiWallTimer() - CpvAccess(test_start_time));
+    CpvAccess(next_test_number)++;
+    CpvAccess(next_test_index)++;
+    megacon_next();
+  }
+}
+
+void megacon_init(int argc, char **argv)
+{
+  int numtests, i;
+  CpmModuleInit();
+  CfutureModuleInit();
+  CpthreadModuleInit();
+  CpmInitializeThisModule();
+  for (i=0; (tests[i].initializer); i++)
+    (tests[i].initializer)();
+  CpvInitialize(int, test_bank_size);
+  CpvInitialize(int, test_negate_skip);
+  CpvInitialize(double, test_start_time);
+  CpvInitialize(int, num_tests_to_skip);
+  CpvInitialize(char **, tests_to_skip);
+  CpvInitialize(int, next_test_index);
+  CpvInitialize(int, next_test_number);
+  CpvInitialize(int, acks_expected);
+  CpvInitialize(int, acks_received);
+  for (numtests=0; tests[numtests].name; numtests++);
+  CpvAccess(test_bank_size) = numtests;
+  CpvAccess(next_test_index) = 0;
+  CpvAccess(next_test_number) = 0;
+  CpvAccess(test_negate_skip)=0;
+  for (i=1; i<argc; i++)
+    if (strcmp(argv[i],"-only")==0)
+      CpvAccess(test_negate_skip)=1;
+  CpvAccess(num_tests_to_skip) = argc;
+  if(CpvAccess(test_negate_skip)) {
+    CpvAccess(num_tests_to_skip)--;
+  }
+  CpvAccess(tests_to_skip) = argv;
+  if (CmiMyPe()==0)
+    megacon_next();
+}
+
+int main(int argc, char **argv)
+{
+  ConverseInit(argc,argv,megacon_init,0,0);
+}
diff --git a/tests/converse/megacon/multicast.c b/tests/converse/megacon/multicast.c
new file mode 100644 (file)
index 0000000..509eda3
--- /dev/null
@@ -0,0 +1,105 @@
+#include <stdio.h>
+#include <converse.h>
+
+void Cpm_megacon_ack();
+
+typedef struct bchare
+{
+  CmiGroup grp;
+  int totalsent;
+  int totalreplies;
+}
+*bchare;
+
+typedef struct mesg
+{
+  char head[CmiMsgHeaderSizeBytes];
+  int reply_pe;
+  bchare reply_ptr;
+  int magic;
+}
+*mesg;
+
+CpvDeclare(int, multicast_recv_idx);
+CpvDeclare(int, multicast_reply_idx);
+
+void multicast_recv(mesg m)
+{
+  if (m->magic != 0x12345678) {
+    CmiPrintf("multicast failed.\n");
+    exit(1);
+  }
+  CmiSetHandler(m, CpvAccess(multicast_reply_idx));
+  CmiSyncSend(m->reply_pe, sizeof(struct mesg), m);
+}
+
+void multicast_start_cycle(bchare c)
+{
+  struct mesg m; struct mesg *mp; CmiCommHandle h;
+  switch (c->totalsent) {
+  case 0:
+    CmiSetHandler(&m, CpvAccess(multicast_recv_idx));
+    m.reply_ptr = c; m.reply_pe = CmiMyPe(); m.magic = 0x12345678;
+    CmiSyncMulticast(c->grp, sizeof(struct mesg),&m);
+    c->totalsent++;
+    break;
+  case 1:
+  case 2:
+    mp = (mesg)CmiAlloc(sizeof(struct mesg));
+    CmiSetHandler(mp, CpvAccess(multicast_recv_idx));
+    mp->reply_ptr = c; mp->reply_pe = CmiMyPe();mp->magic = 0x12345678;
+    CmiSyncMulticastAndFree(c->grp, sizeof(struct mesg), mp);
+    c->totalsent++;
+    break;
+  case 3:
+    free(c);
+    Cpm_megacon_ack(CpmSend(0));
+  }
+}
+
+void multicast_reply(mesg m)
+{
+  bchare c;
+  if (m->magic != 0x12345678) {
+    CmiPrintf("multicast failed.\n");
+    exit(1);
+  }
+  c = m->reply_ptr;
+  c->totalreplies++;
+  if ((c->totalreplies % CmiNumPes())==0) multicast_start_cycle(c);
+}
+
+CmiGroup multicast_all()
+{
+  int i, *pes, npes; CmiGroup grp;
+  npes = CmiNumPes();
+  pes = (int*)malloc(npes*sizeof(int));
+  for (i=0; i<npes; i++) pes[i] = i;
+  grp = CmiEstablishGroup(CmiNumPes(), pes);
+  free(pes);
+  return grp;
+}
+
+void multicast_init(void)
+{
+  bchare c;
+  c = (bchare)malloc(sizeof(struct bchare));
+  c->grp = multicast_all();
+  c->totalsent = 0;
+  c->totalreplies = 0;
+  multicast_start_cycle(c);
+}
+
+void multicast_moduleinit()
+{
+  CpvInitialize(int, multicast_recv_idx);
+  CpvInitialize(int, multicast_reply_idx);
+  CpvAccess(multicast_recv_idx) = CmiRegisterHandler(multicast_recv);
+  CpvAccess(multicast_reply_idx) = CmiRegisterHandler(multicast_reply);
+}
+
+
+
+
+
+
diff --git a/tests/converse/megacon/multisend.c b/tests/converse/megacon/multisend.c
new file mode 100644 (file)
index 0000000..badd77e
--- /dev/null
@@ -0,0 +1,135 @@
+#include <stdio.h>
+#include <converse.h>
+
+void Cpm_megacon_ack();
+
+typedef struct
+{
+  char core[CmiMsgHeaderSizeBytes]; 
+  int hdlrnum;
+  double data[10];
+} multisendmsg;
+
+CpvDeclare(int, multisend_first_index);
+CpvDeclare(int, multisend_second_index);
+CpvDeclare(int, multisend_third_index);
+CpvDeclare(int, multisend_recv_index);
+
+CpvDeclare(int, multisend_replies);
+
+void multisend_fail()
+{
+  CmiPrintf("data corrupted in multisend.\n");
+  exit(1);
+}
+
+void multisend_first_handler(multisendmsg *msg)
+{
+  int i;
+
+  if(msg->hdlrnum != 1)
+    multisend_fail();
+  for(i=0;i<10;i++) {
+    if(msg->data[i] != (double) (i+1))
+      multisend_fail();
+  }
+  CmiGrabBuffer((void **) &msg);
+  CmiSetHandler(msg, CpvAccess(multisend_recv_index));
+  CmiSyncSendAndFree(0, sizeof(multisendmsg), msg);
+}
+
+void multisend_second_handler(multisendmsg *msg)
+{
+  int i;
+
+  if(msg->hdlrnum != 2)
+    multisend_fail();
+  for(i=0;i<10;i++) {
+    if(msg->data[i] != (double) (i+2))
+      multisend_fail();
+  }
+  CmiGrabBuffer((void **) &msg);
+  CmiSetHandler(msg, CpvAccess(multisend_recv_index));
+  CmiSyncSendAndFree(0, sizeof(multisendmsg), msg);
+}
+
+void multisend_third_handler(multisendmsg *msg)
+{
+  int i;
+
+  if(msg->hdlrnum != 3)
+    multisend_fail();
+  for(i=0;i<10;i++) {
+    if(msg->data[i] != (double) (i+3))
+      multisend_fail();
+  }
+  CmiSetHandler(msg, CpvAccess(multisend_recv_index));
+  CmiSyncSend(0, sizeof(multisendmsg), msg);
+}
+
+void multisend_recv_handler(multisendmsg *msg)
+{
+  int i;
+
+  CpvAccess(multisend_replies)++;
+  for(i=0;i<10;i++) {
+    if(msg->data[i] != (double) (i+msg->hdlrnum))
+      multisend_fail();
+  }
+  if(CpvAccess(multisend_replies)==3)
+    Cpm_megacon_ack(CpmSend(0));
+}
+
+void multisend_init(void)
+{
+  multisendmsg first, third;
+  multisendmsg *second;
+  int sizes[3];
+  char *msgs[3];
+  int i;
+
+  if(CmiNumPes() < 2) {
+    CmiPrintf("Multisend requires at least 2 processors. skipping...\n");
+    Cpm_megacon_ack(CpmSend(0));
+  } else {
+    second = (multisendmsg *) CmiAlloc(sizeof(multisendmsg));
+    first.hdlrnum = 1;
+    second->hdlrnum = 2;
+    third.hdlrnum = 3;
+    for(i=0;i<10;i++) {
+      first.data[i] = (double) (i+1);
+      second->data[i] = (double) (i+2);
+      third.data[i] = (double) (i+3);
+    }
+    CmiSetHandler(&first, CpvAccess(multisend_first_index));
+    CmiSetHandler(second, CpvAccess(multisend_second_index));
+    CmiSetHandler(&third, CpvAccess(multisend_third_index));
+    sizes[0] = sizes[1] = sizes[2] = sizeof(multisendmsg);
+    msgs[0] = (char *) &first; 
+    msgs[1] = (char *) second; 
+    msgs[2] = (char *) &third;
+    CmiMultipleSend(1, 3, sizes, msgs);
+    CmiFree(second);
+  }
+  CpvAccess(multisend_replies) = 0;
+}
+
+void multisend_moduleinit()
+{
+  CpvInitialize(int, multisend_first_index);
+  CpvInitialize(int, multisend_second_index);
+  CpvInitialize(int, multisend_third_index);
+  CpvInitialize(int, multisend_recv_index);
+  CpvInitialize(int, multisend_replies);
+  CpvAccess(multisend_first_index) = 
+    CmiRegisterHandler(multisend_first_handler);
+  CpvAccess(multisend_second_index) = 
+    CmiRegisterHandler(multisend_second_handler);
+  CpvAccess(multisend_third_index) = 
+    CmiRegisterHandler(multisend_third_handler);
+  CpvAccess(multisend_recv_index) = 
+    CmiRegisterHandler(multisend_recv_handler);
+}
+
+
+
diff --git a/tests/converse/megacon/nodenum.c b/tests/converse/megacon/nodenum.c
new file mode 100644 (file)
index 0000000..a6857fb
--- /dev/null
@@ -0,0 +1,102 @@
+#include <stdio.h>
+#include <converse.h>
+
+typedef struct node_info
+{
+  int pe;
+  int rank;
+  int host;
+}
+*node_info;
+
+typedef struct nodenum_chare
+{
+  int countdown; CthThread pending;
+  struct node_info info[64];
+}
+*nodenum_chare;
+
+CpmDeclareSimple(nodenum_chare);
+#define CpmPack_nodenum_chare(x) (0)
+#define CpmUnpack_nodenum_chare(x) (0)
+CsvDeclare(int, myhost);
+
+void Cpm_megacon_ack();
+
+#include "nodenum.cpm.h"
+
+CpmInvokable nodenum_ack(nodenum_chare c)
+{
+  c->countdown--;
+  if ((c->countdown==0)&&(c->pending))
+    CthAwaken(c->pending);
+}
+
+CpmInvokable nodenum_reply(nodenum_chare c, int pe, int rank, int host)
+{
+  c->info[pe].pe   = pe; 
+  c->info[pe].rank = rank;
+  c->info[pe].host = host;
+  nodenum_ack(c);
+}
+
+CpmInvokable nodenum_initialize_myhost(nodenum_chare c)
+{
+  if (CmiMyRank()==0) CsvAccess(myhost) = CmiMyPe();
+  Cpm_nodenum_reply(CpmSend(0), c, 0, 0, 0);
+}
+
+CpmInvokable nodenum_collect_info(nodenum_chare c)
+{
+  if ((CmiMyRank()==0) && (CsvAccess(myhost)!=CmiMyPe())) {
+    CmiPrintf("failure in nodenum-test #1234\n");
+    exit(1);
+  }
+  Cpm_nodenum_reply(CpmSend(0),c,CmiMyPe(),CmiMyRank(),CsvAccess(myhost));
+}
+
+CpmInvokable nodenum_control()
+{
+  struct nodenum_chare c;
+  int i, npe; node_info curr, prev;
+  npe = CmiNumPes();
+
+  /* gather the processor/rank/host table */
+  Cpm_nodenum_initialize_myhost(CpmSend(CpmALL), &c);
+  c.countdown = CmiNumPes(); c.pending = CthSelf(); CthSuspend();
+  Cpm_nodenum_collect_info(CpmSend(CpmALL), &c);
+  c.countdown = CmiNumPes(); c.pending = CthSelf(); CthSuspend();
+  
+  /* check that the processor/host/rank table contains reasonable values */
+  if ((c.info[0].host != 0)||(c.info[0].rank != 0)||(c.info[0].pe != 0))
+    goto badnum;
+  for (i=1; i<npe; i++) {
+    curr = &(c.info[i]);
+    prev = &(c.info[i-1]);
+    if (curr->host == prev->host) {
+      if (curr->rank != prev->rank + 1)        goto badnum;
+    } else {
+      if (curr->host != curr->pe) goto badnum;
+      if (curr->rank != 0) goto badnum;
+    }
+  }
+  
+  Cpm_megacon_ack(CpmSend(0));
+  return;
+badnum:
+  CmiPrintf("nodenum: error in processor node/rank numbering system.\n");
+  exit(1);
+}
+
+void nodenum_init()
+{
+  if (CmiNumPes() > 64) {
+    CmiPrintf("skipping nodenum test (code only works on 64 PE's or less)\n");
+    Cpm_megacon_ack(CpmSend(0));
+  } else Cpm_nodenum_control(CpmMakeThread(0));
+}
+
+void nodenum_moduleinit()
+{
+  CpmInitializeThisModule();
+}
diff --git a/tests/converse/megacon/posixth.c b/tests/converse/megacon/posixth.c
new file mode 100644 (file)
index 0000000..29765bd
--- /dev/null
@@ -0,0 +1,169 @@
+#define SUPPRESS_PTHREADS
+#include <stdio.h>
+#include <converse.h>
+#include <cpthreads.h>
+#include "posixth.cpm.h"
+
+void Cpm_megacon_ack();
+
+CpvStaticDeclare(Cpthread_attr_t,  joinable);
+CpvStaticDeclare(Cpthread_attr_t,  detached);
+
+CpvStaticDeclare(Cpthread_mutexattr_t, mutexattrs);
+CpvStaticDeclare(Cpthread_condattr_t,  condattrs);
+
+CpvStaticDeclare(Cpthread_mutex_t, total_mutex);
+CpvStaticDeclare(int,              total);
+CpvStaticDeclare(Cpthread_mutex_t, leaves_mutex);
+CpvStaticDeclare(int,              leaves);
+CpvStaticDeclare(Cpthread_mutex_t, fibs_mutex);
+CpvStaticDeclare(int,              fibs);
+
+CpvStaticDeclare(Cpthread_cond_t,  donecond);
+
+static void posixth_fail()
+{
+  CmiError("error detected in posix threads.\n");
+  exit(1);
+}
+
+static void errck(int code)
+{
+  if (code != 0) posixth_fail();
+}
+
+void posixth_add(Cpthread_mutex_t *mutex, int *var, int val)
+{
+  int n;
+  Cpthread_mutex_lock(mutex);
+  n = *var;
+  if (rand()&1) CthYield();
+  *var = n + val;
+  Cpthread_mutex_unlock(mutex);
+}
+
+void *posixth_fib(void *np)
+{
+  Cpthread_t t1, t2; void *r1, *r2; int total;
+  int n = (size_t)np;
+  if (n<2) {
+    if (rand()&1) CthYield();
+    posixth_add(&CpvAccess(leaves_mutex), &CpvAccess(leaves), 1);
+    return (void*)n;
+  }
+  if (rand()&1) CthYield();
+  errck(Cpthread_create(&t1, &CpvAccess(joinable), posixth_fib, (void*)(n-1)));
+  if (rand()&1) CthYield();
+  errck(Cpthread_create(&t2, &CpvAccess(joinable), posixth_fib, (void*)(n-2)));
+  if (rand()&1) CthYield();
+  errck(Cpthread_join(t1, &r1));
+  if (rand()&1) CthYield();
+  errck(Cpthread_join(t2, &r2));
+  if (rand()&1) CthYield();
+  total = ((size_t)r1) + ((size_t)r2);
+  return (void*)total;
+}
+
+void *posixth_top(void *x)
+{
+  Cpthread_t t; void *result; int n;
+  if (rand()&1) CthYield();
+  errck(Cpthread_create(&t, &CpvAccess(joinable), posixth_fib, (void*)6));
+  if (rand()&1) CthYield();
+  errck(Cpthread_join(t, &result));
+  if (rand()&1) CthYield();
+  if ((size_t)result != 8) posixth_fail();
+  if (rand()&1) CthYield();
+  posixth_add(&CpvAccess(total_mutex), &CpvAccess(total), (size_t)result);
+  if (rand()&1) CthYield();
+  posixth_add(&CpvAccess(fibs_mutex), &CpvAccess(fibs), -1);
+  if (rand()&1) CthYield();
+  if (CpvAccess(fibs)==0)
+    errck(Cpthread_cond_signal(&CpvAccess(donecond)));
+  if (rand()&1) CthYield();
+}
+
+void posixth_main(int argc, char **argv)
+{
+  Cpthread_mutex_t dummymutex; int i; Cpthread_t t;
+
+  if (rand()&1) CthYield();
+  errck(Cpthread_attr_init(&CpvAccess(joinable)));
+  if (rand()&1) CthYield();
+  errck(Cpthread_attr_setdetachstate(&CpvAccess(joinable),CPTHREAD_CREATE_JOINABLE));
+  if (rand()&1) CthYield();
+  errck(Cpthread_attr_init(&CpvAccess(detached)));
+  if (rand()&1) CthYield();
+  errck(Cpthread_attr_setdetachstate(&CpvAccess(detached),CPTHREAD_CREATE_DETACHED));
+  if (rand()&1) CthYield();
+  errck(Cpthread_mutexattr_init(&CpvAccess(mutexattrs)));
+  if (rand()&1) CthYield();
+  errck(Cpthread_condattr_init(&CpvAccess(condattrs)));
+  if (rand()&1) CthYield();
+  errck(Cpthread_mutex_init(&CpvAccess(total_mutex), &CpvAccess(mutexattrs)));
+  if (rand()&1) CthYield();
+  errck(Cpthread_mutex_init(&CpvAccess(leaves_mutex), &CpvAccess(mutexattrs)));
+  if (rand()&1) CthYield();
+  errck(Cpthread_mutex_init(&CpvAccess(fibs_mutex), &CpvAccess(mutexattrs)));
+  if (rand()&1) CthYield();
+  errck(Cpthread_cond_init(&CpvAccess(donecond), &CpvAccess(condattrs)));
+  if (rand()&1) CthYield();
+  CpvAccess(total) = 0;
+  CpvAccess(fibs) = 20;
+  CpvAccess(leaves) = 0;
+
+  for (i=0; i<20; i++) {
+    if (rand()&1) CthYield();
+    Cpthread_create(&t, &CpvAccess(detached), posixth_top, 0);
+  }
+
+  if (rand()&1) CthYield();
+  errck(Cpthread_mutex_init(&dummymutex, &CpvAccess(mutexattrs)));
+  if (rand()&1) CthYield();
+  errck(Cpthread_mutex_lock(&dummymutex));
+  if (rand()&1) CthYield();
+  errck(Cpthread_cond_wait(&CpvAccess(donecond), &dummymutex));
+  if (rand()&1) CthYield();
+  errck(Cpthread_mutex_unlock(&dummymutex));
+  if (rand()&1) CthYield();
+  errck(Cpthread_mutex_destroy(&dummymutex));
+  if (rand()&1) CthYield();
+  
+  if (CpvAccess(total)!=160) posixth_fail();
+  if (CpvAccess(leaves)!=260) posixth_fail();
+  
+  if (rand()&1) CthYield();
+  errck(Cpthread_mutex_destroy(&CpvAccess(total_mutex)));
+  if (rand()&1) CthYield();
+  errck(Cpthread_mutex_destroy(&CpvAccess(leaves_mutex)));
+  if (rand()&1) CthYield();
+  errck(Cpthread_mutex_destroy(&CpvAccess(fibs_mutex)));
+  if (rand()&1) CthYield();
+  errck(Cpthread_cond_destroy(&CpvAccess(donecond)));
+  if (rand()&1) CthYield();
+  
+  Cpm_megacon_ack(CpmSend(0));
+}
+
+void posixth_init(void)
+{
+  Cpthread_start_main(posixth_main, 0, 0);
+}
+
+void posixth_moduleinit()
+{
+  CpmInitializeThisModule();
+
+  CpvInitialize(Cpthread_attr_t, joinable);
+  CpvInitialize(Cpthread_attr_t, detached);
+  CpvInitialize(Cpthread_mutexattr_t, mutexattrs);
+  CpvInitialize(Cpthread_condattr_t,  condattrs);
+  CpvInitialize(Cpthread_mutex_t, total_mutex);
+  CpvInitialize(int,              total);
+  CpvInitialize(Cpthread_mutex_t, leaves_mutex);
+  CpvInitialize(int,              leaves);
+  CpvInitialize(Cpthread_mutex_t, fibs_mutex);
+  CpvInitialize(int,              fibs);
+  CpvInitialize(Cpthread_cond_t,  donecond);
+  
+}
diff --git a/tests/converse/megacon/priotest.c b/tests/converse/megacon/priotest.c
new file mode 100644 (file)
index 0000000..8f9db1c
--- /dev/null
@@ -0,0 +1,55 @@
+#include <stdio.h>
+#include <converse.h>
+
+void Cpm_megacon_ack();
+
+typedef struct priotest_chare
+{
+  int numreceived;
+  int totalexpected;
+}
+*priotest_chare;
+CpmDeclareSimple(priotest_chare);
+#define CpmPack_priotest_chare(p) (0)
+#define CpmUnpack_priotest_chare(p) (0)
+
+#include "priotest.cpm.h"
+
+CpmInvokable priotest_bink(priotest_chare c, int n)
+{
+  if (n != c->numreceived) {
+    CmiError("priotest: message received in wrong order.\n");
+    exit(1);
+  }
+  c->numreceived++;
+  if (c->numreceived == c->totalexpected) {
+    CmiFree(c);
+    Cpm_megacon_ack(CpmSend(0));
+  }
+}
+
+CpmInvokable priotest_send()
+{
+  int me = CmiMyPe();
+  priotest_chare c = (priotest_chare)CmiAlloc(sizeof(struct priotest_chare));
+  c->numreceived = 0;
+  c->totalexpected = 8;
+  Cpm_priotest_bink(CpmEnqueueIFIFO(me, 1), c, 1);
+  Cpm_priotest_bink(CpmEnqueueIFIFO(me, 5), c, 5);
+  Cpm_priotest_bink(CpmEnqueueIFIFO(me, 2), c, 2);
+  Cpm_priotest_bink(CpmEnqueueIFIFO(me, 4), c, 4);
+  Cpm_priotest_bink(CpmEnqueueIFIFO(me, 3), c, 3);
+  Cpm_priotest_bink(CpmEnqueueIFIFO(me, 6), c, 6);
+  Cpm_priotest_bink(CpmEnqueueIFIFO(me, 0), c, 0);
+  Cpm_priotest_bink(CpmEnqueueIFIFO(me, 7), c, 7);
+}
+
+void priotest_init()
+{
+  Cpm_priotest_send(CpmSend(CpmALL));
+}
+
+void priotest_moduleinit()
+{
+  CpmInitializeThisModule();
+}
diff --git a/tests/converse/megacon/ring.c b/tests/converse/megacon/ring.c
new file mode 100644 (file)
index 0000000..957a8fa
--- /dev/null
@@ -0,0 +1,40 @@
+#include <stdio.h>
+#include <converse.h>
+#include <sys/types.h>
+#include "ring.cpm.h"
+
+void Cpm_megacon_ack();
+
+void ring_fail()
+{
+  CmiPrintf("data corrupted in ring_hop.\n");
+  exit(1);
+}
+
+CpmInvokable ring_hop(int steps, CpmStr t1, CpmDim t2, CpmStr *t3)
+{
+  int thispe = CmiMyPe();
+  int nextpe = (thispe+1) % CmiNumPes();
+  if (strcmp(t1,"Howdy, Dude.")) ring_fail();
+  if (t2 != 4) ring_fail();
+  if (strcmp(t3[0],"this")) ring_fail();
+  if (strcmp(t3[1],"is")) ring_fail();
+  if (strcmp(t3[2],"a")) ring_fail();
+  if (strcmp(t3[3],"test")) ring_fail();
+  if (steps) {
+    Cpm_ring_hop(CpmSend(nextpe), steps-1, t1, t2, t3);
+  } else {
+    Cpm_megacon_ack(CpmSend(0));
+  }
+}
+
+void ring_init(void)
+{
+  char *data[4] = { "this", "is", "a", "test" };
+  Cpm_ring_hop(CpmSend(0), 1000, "Howdy, Dude.", 4, data);
+}
+
+void ring_moduleinit()
+{
+  CpmInitializeThisModule();
+}
diff --git a/tests/converse/megacon/ringsimple.c b/tests/converse/megacon/ringsimple.c
new file mode 100644 (file)
index 0000000..bd26476
--- /dev/null
@@ -0,0 +1,56 @@
+#include <stdio.h>
+#include <converse.h>
+
+void Cpm_megacon_ack();
+
+typedef struct
+{
+  char core[CmiMsgHeaderSizeBytes]; 
+  int hops, ringno;
+  int data[10];
+} ringmsg;
+
+CpvDeclare(int, ringsimple_hop_index);
+
+void ringsimple_fail()
+{
+  CmiPrintf("data corrupted in ringsimple_hop.\n");
+  exit(1);
+}
+
+void ringsimple_hop(ringmsg *msg)
+{
+  int thispe = CmiMyPe();
+  int nextpe = (thispe+1) % CmiNumPes();
+  int i;
+  CmiGrabBuffer((void **)&msg);
+  for (i=0; i<10; i++)
+    if (msg->data[i] != i) ringsimple_fail();
+  if (msg->hops) {
+    msg->hops--;
+    CmiSyncSendAndFree(nextpe, sizeof(ringmsg), msg);
+  } else {
+    Cpm_megacon_ack(CpmSend(0));
+  }
+}
+
+void ringsimple_init(void)
+{
+  int i; ringmsg msg;
+  for (i=0; i<10; i++) msg.data[i] = i;
+  msg.hops = 1000;
+  CmiSetHandler(&msg, CpvAccess(ringsimple_hop_index));
+  for (i=0; i<10; i++) {
+    msg.ringno = i;
+    CmiSyncSend(0, sizeof(ringmsg), &msg);
+  }
+}
+
+void ringsimple_moduleinit()
+{
+  CpvInitialize(int, ringsimple_hop_index);
+  CpvAccess(ringsimple_hop_index) = CmiRegisterHandler((CmiHandler)ringsimple_hop);
+}
+
+
+
diff --git a/tests/converse/megacon/specmsg.c b/tests/converse/megacon/specmsg.c
new file mode 100644 (file)
index 0000000..4b992bd
--- /dev/null
@@ -0,0 +1,83 @@
+#include <stdio.h>
+#include <converse.h>
+
+typedef struct specmsg_chare
+{
+  int next;
+}
+*specmsg_chare;
+
+CpmDeclareSimple(specmsg_chare);
+#define CpmPack_specmsg_chare(x) (0)
+#define CpmUnpack_specmsg_chare(x) (0)
+
+#include "specmsg.cpm.h"
+
+void Cpm_megacon_ack();
+
+void specmsg_fail()
+{
+  CmiError("specmsg: CmiDeliverSpecificMsg failed.\n");
+  exit(1);
+}
+
+CpmInvokable specmsg_step1(specmsg_chare c)
+{
+  if (c->next != 1) specmsg_fail();
+  c->next++;
+}
+
+CpmInvokable specmsg_step2(specmsg_chare c)
+{
+  if (c->next != 2) specmsg_fail();
+  c->next++;
+}
+
+CpmInvokable specmsg_step3(specmsg_chare c)
+{
+  if (c->next != 3) specmsg_fail();
+  c->next++;
+}
+
+CpmInvokable specmsg_step4(specmsg_chare c)
+{
+  if (c->next != 4) specmsg_fail();
+  c->next++;
+}
+
+CpmInvokable specmsg_begin()
+{
+  int i; struct specmsg_chare c;
+  Cpm_specmsg_request(CpmSend(0), CmiMyPe(), &c);
+  if (CmiMyPe()==0)
+    for (i=0; i<CmiNumPes(); i++)
+      CmiDeliverSpecificMsg(CpvAccess(CpmIndex_specmsg_request));
+  c.next = 1;
+  CmiDeliverSpecificMsg(CpvAccess(CpmIndex_specmsg_step1));
+  CmiDeliverSpecificMsg(CpvAccess(CpmIndex_specmsg_step2));
+  CmiDeliverSpecificMsg(CpvAccess(CpmIndex_specmsg_step3));
+  CmiDeliverSpecificMsg(CpvAccess(CpmIndex_specmsg_step4));
+  Cpm_megacon_ack(CpmSend(0));
+}
+
+CpmInvokable specmsg_request(int pe, specmsg_chare c)
+{
+  Cpm_specmsg_step3(CpmSend(pe), c);
+  Cpm_specmsg_step2(CpmSend(pe), c); 
+  Cpm_specmsg_step4(CpmSend(pe), c);
+  Cpm_specmsg_step1(CpmSend(pe), c);
+}
+
+void specmsg_init()
+{
+  int pe;
+  for (pe=1; pe<CmiNumPes(); pe++)
+    Cpm_specmsg_begin(CpmSend(pe));
+  specmsg_begin();
+}
+
+void specmsg_moduleinit()
+{
+  CpmInitializeThisModule();
+}
+
diff --git a/tests/converse/megacon/vars.c b/tests/converse/megacon/vars.c
new file mode 100644 (file)
index 0000000..af47341
--- /dev/null
@@ -0,0 +1,102 @@
+#include <stdio.h>
+#include <converse.h>
+
+void Cpm_megacon_ack();
+
+typedef struct vars_chare
+{
+  int countdown;
+  CthThread pending;
+}
+*vars_chare;
+
+CpmDeclareSimple(vars_chare);
+#define CpmPack_vars_chare(x) (0)
+#define CpmUnpack_vars_chare(x) (0)
+
+#include "vars.cpm.h"
+
+CtvDeclare(int, ctv1);
+CpvDeclare(int, cpv1);
+CsvDeclare(int, csv1);
+
+CpmInvokable vars_ack(vars_chare c)
+{
+  c->countdown--;
+  if ((c->countdown==0)&&(c->pending))
+    CthAwaken(c->pending);
+}
+
+void vars_check_ctv_privacy(vars_chare c)
+{
+  int me = (size_t)CthSelf();
+  CtvAccess(ctv1) = me;
+  vars_ack(c);
+  CthSuspend();
+  if (CtvAccess(ctv1) != me) {
+    CmiPrintf("ctv privacy test failed.\n");
+    exit(1);
+  }
+  vars_ack(c);
+  CthFree(CthSelf());
+  CthSuspend();
+}
+
+CpmInvokable vars_set_cpv_and_csv(vars_chare c)
+{
+  CpvAccess(cpv1) = CmiMyPe();
+  if (CmiMyRank() == 0)
+    CsvAccess(csv1) = 0x12345678;
+  Cpm_vars_ack(CpmSend(0), c);
+}
+
+CpmInvokable vars_check_cpv_and_csv(vars_chare c)
+{
+  if (CpvAccess(cpv1) != CmiMyPe()) {
+    CmiPrintf("cpv privacy test failed.\n");
+    exit(1);
+  }
+  if (CsvAccess(csv1) != 0x12345678) {
+    CmiPrintf("csv sharing test failed.\n");
+    exit(1);
+  }
+  Cpm_vars_ack(CpmSend(0), c);
+}
+
+CpmInvokable vars_control()
+{
+  struct vars_chare c; CthThread t1,t2;
+
+  t1 = CthCreate(vars_check_ctv_privacy, (void *)&c, 0);
+  t2 = CthCreate(vars_check_ctv_privacy, (void *)&c, 0);
+  CthSetStrategyDefault(t1);
+  CthSetStrategyDefault(t2);
+
+  CthAwaken(t1); CthAwaken(t2);
+  c.countdown = 2; c.pending = CthSelf(); CthSuspend();
+  
+  CthAwaken(t1); CthAwaken(t2);
+  c.countdown = 2; c.pending = CthSelf(); CthSuspend();
+  
+  Cpm_vars_set_cpv_and_csv(CpmSend(CpmALL), &c);
+  c.countdown = CmiNumPes(); c.pending = CthSelf(); CthSuspend();
+  
+  Cpm_vars_check_cpv_and_csv(CpmSend(CpmALL), &c);
+  c.countdown = CmiNumPes(); c.pending = CthSelf(); CthSuspend();
+  
+  Cpm_megacon_ack(CpmSend(0));
+}
+
+void vars_init()
+{
+  Cpm_vars_control(CpmMakeThreadSize(0,0));
+}
+
+void vars_moduleinit()
+{
+  CpmInitializeThisModule();
+  CtvInitialize(int, ctv1);
+  CpvInitialize(int, cpv1);
+  CsvInitialize(int, csv1);
+}
+
diff --git a/tests/converse/megacon/vecsend.c b/tests/converse/megacon/vecsend.c
new file mode 100644 (file)
index 0000000..fbedd7d
--- /dev/null
@@ -0,0 +1,63 @@
+#include <stdio.h>
+#include <time.h>
+#include <converse.h>
+
+CpvDeclare(int, vecsend_index);
+
+#define CmiMsgHeaderSizeInts \
+    ((CmiMsgHeaderSizeBytes+sizeof(int)-1)/sizeof(int))
+
+void Cpm_megacon_ack();
+
+void vecsend_handler(int *msg)
+{
+  int i, next;
+  int sizes[1];
+  char *msgs[1];
+
+  if (CmiMyPe()==0) {
+    for (i=CmiMsgHeaderSizeInts; i<3600; i++) {
+      if (msg[i] != i) {
+       CmiPrintf("Failure in vecsend test, data corrupted.\n");
+       exit(1);
+      }
+    }
+    Cpm_megacon_ack(CpmSend(0));
+  } else {
+    next = (CmiMyPe()+1) % CmiNumPes();
+    sizes[0] = 3600*sizeof(int);
+    msgs[0] = (char *)msg;
+    CmiSyncVectorSend(next, 1, sizes, msgs);
+    CmiGrabBuffer((void **)&msg);
+    CmiFree(msg);
+  }
+}
+
+void vecsend_init()
+{
+  int i, *msg;
+  int *sizes;
+  int **msgs;
+  if (CmiNumPes()<2) {
+    CmiPrintf("note: vecsend requires at least 2 processors, skipping test.\n");
+    Cpm_megacon_ack(CpmSend(0));
+  } else {
+       sizes = (int *) CmiAlloc(4*sizeof(int));
+    msgs = (int **) CmiAlloc(4*sizeof(int *));
+    sizes[0] = 1000; sizes[1] = 500; sizes[2] = 2000; sizes[3] = 100;
+    for(i=0;i<4;i++) msgs[i] = CmiAlloc(sizes[i]*sizeof(int));
+    for(i=0;i<4;i++) sizes[i] *= sizeof(int);
+    for (i=CmiMsgHeaderSizeInts; i<1000; i++) msgs[0][i] = i;
+    for (i=0; i<500; i++) msgs[1][i] = i+1000;
+    for (i=0; i<2000; i++) msgs[2][i] = i+1500;
+    for (i=0; i<100; i++) msgs[3][i] = i+3500;
+    CmiSetHandler(msgs[0], CpvAccess(vecsend_index));
+    CmiSyncVectorSendAndFree(1, 4, sizes, (char **) msgs);
+  }
+}
+
+void vecsend_moduleinit()
+{
+  CpvInitialize(int, vecsend_index);
+  CpvAccess(vecsend_index) = CmiRegisterHandler(vecsend_handler);
+}