First check-in for the work on extractin common codes from MPI, LAPI and DCMF layer...
authorChao Mei <chaomei2@illinois.edu>
Fri, 13 May 2011 23:10:21 +0000 (18:10 -0500)
committerChao Mei <chaomei2@illinois.edu>
Fri, 13 May 2011 23:10:21 +0000 (18:10 -0500)
src/arch/bluegenep/machine.c
src/arch/lapi/machine.c
src/arch/mpi/conv-common.h
src/arch/mpi/machine.c
src/arch/util/machine-common.c [new file with mode: 0644]

index 156cda9fdd65a2c741e8469b196b10ec60084b87..bb2ddfe186c9c0c81b4ed671da2d6e32064c39e8 100644 (file)
@@ -1,67 +1,28 @@
-
 #include <stdio.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <math.h>
 #include <string.h>
-#include "machine.h"
+#include <malloc.h>
+#include <assert.h>
+
 #include "converse.h"
+#include "machine.h"
 #include "pcqueue.h"
-#include "assert.h"
-#include "malloc.h"
 
 #include <bpcore/ppc450_inlines.h>
-
 #include "dcmf.h"
 #include "dcmf_multisend.h"
 
-char *ALIGN_16(char *p) {
-    return((char *)((((unsigned long)p)+0xf)&0xfffffff0));
-}
-
-#define PROGRESS_PERIOD 1024
-
-//There are two roles of comm thread:
-// 1. polling other cores' bcast msg queue
-// 2. bcast msg is handled only by comm thd
-#define BCASTMSG_ONLY_TO_COMMTHD 1
+/* =======Beginning of Definitions of Performance-Specific Macros =======*/
+/* =======End of Definitions of Performance-Specific Macros =======*/
 
-//only one bcast queue for comm thread to handle, but
-//may be accessed by system threads such as the handler
-//for receiving messages
-static PCQueue broadcast_q;                 //queue to send broadcast messages
-#if CMK_NODE_QUEUE_AVAILABLE
-CsvDeclare(PCQueue, node_bcastq);
-CsvDeclare(CmiNodeLock, node_bcastLock);
-#endif
+/* =======Beginning of Definitions of Msg Header Specific Macros =======*/
+/* =======End of Definitions of Msg Header Specific Macros =======*/
 
-/*
-    To reduce the buffer used in broadcast and distribute the load from
-  broadcasting node, define CMK_BROADCAST_SPANNING_TREE enforce the use of
-  spanning tree broadcast algorithm.
-    This will use the fourth short in message as an indicator of spanning tree
-  root.
-*/
-#define CMK_BROADCAST_SPANNING_TREE    1
-/* FIXME: HYPERCUBE in SMP will not work*/
-#define CMK_BROADCAST_HYPERCUBE        0
-
-#define BROADCAST_SPANNING_FACTOR     4
-
-//The root of the message infers the type of the message
-// 1. root is 0, then it is a normal point-to-point message
-// 2. root is larger than 0 (>=1), then it is a broadcast message across all processors (cores)
-// 3. root is less than 0 (<=-1), then it is a broadcast message across all nodes
-#define CMI_BROADCAST_ROOT(msg)          ((CmiMsgHeaderBasic *)msg)->root
-#define CMI_IS_BCAST_ON_CORES(msg) (CMI_BROADCAST_ROOT(msg) > 0)
-#define CMI_IS_BCAST_ON_NODES(msg) (CMI_BROADCAST_ROOT(msg) < 0)
-#define CMI_GET_CYCLE(msg)               ((CmiMsgHeaderBasic *)msg)->root
-
-#define CMI_DEST_RANK(msg)               ((CmiMsgHeaderBasic *)msg)->rank
+/* =====Beginning of Definitions of Message-Corruption Related Macros=====*/
 #define CMI_MAGIC(msg)                   ((CmiMsgHeaderBasic *)msg)->magic
-
-/* FIXME: need a random number that everyone agrees ! */
 #define CHARM_MAGIC_NUMBER               126
 
 #if CMK_ERROR_CHECKING
@@ -78,8 +39,11 @@ extern unsigned char computeCheckSum(unsigned char *data, int len);
         if (checksum_flag)      \
           if (computeCheckSum((unsigned char*)msg, len) != 0)  { \
             printf("\n\n------------------------------\n\nReceiver %d size %d:", CmiMyPe(), len); \
+           { \
+           int count; \
             for(count = 0; count < len; count++) { \
                 printf("%2x", msg[count]);                 \
+            } \
             }                                             \
             printf("------------------------------\n\n"); \
             CmiAbort("Fatal error: checksum doesn't agree!\n"); \
@@ -88,31 +52,10 @@ extern unsigned char computeCheckSum(unsigned char *data, int len);
 #define CMI_SET_CHECKSUM(msg, len)
 #define CMI_CHECK_CHECKSUM(msg, len)
 #endif
-
-#define CMI_SET_BROADCAST_ROOT(msg, root)  CMI_BROADCAST_ROOT(msg) = (root);
-
-#if CMK_BROADCAST_HYPERCUBE
-#  define CMI_SET_CYCLE(msg, cycle)  CMI_GET_CYCLE(msg) = (cycle);
-#else
-#  define CMI_SET_CYCLE(msg, cycle)
-#endif
-
-int               _Cmi_numpes;
-int               _Cmi_mynode;    /* Which address space am I */
-int               _Cmi_mynodesize;/* Number of processors in my address space */
-int               _Cmi_numnodes;  /* Total number of address spaces */
-int                Cmi_nodestart; /* First processor in this address space */
-CpvDeclare(void*, CmiLocalQueue);
-
-
-#if CMK_NODE_QUEUE_AVAILABLE
-#define SMP_NODEMESSAGE   (0xFB) // rank of the node message when node queue
-// is available
-#define NODE_BROADCAST_OTHERS (-1)
-#define NODE_BROADCAST_ALL    (-2)
-#endif
+/* =====End of Definitions of Message-Corruption Related Macros=====*/
 
 
+/* =====Beginning of Declarations of Machine Specific Variables===== */
 typedef struct ProcState {
     /* PCQueue      sendMsgBuf; */      /* per processor message sending queue */
     CmiNodeLock  recvLock;              /* for cs->recv */
@@ -121,148 +64,73 @@ typedef struct ProcState {
 
 static ProcState  *procState;
 
-#if CMK_SMP && !CMK_MULTICORE
-static volatile int commThdExit = 0;
-static CmiNodeLock commThdExitLock = 0;
-#endif
-
-void ConverseRunPE(int everReturn);
-static void CommunicationServer(int sleepTime);
-static void CommunicationServerThread(int sleepTime);
-
-//So far we dont define any comm threads
-int Cmi_commthread = 0;
-
-#include "machine-smp.c"
-CsvDeclare(CmiNodeState, NodeState);
-#include "immediate.c"
-
-void AdvanceCommunications();
-
-
-#if !CMK_SMP
-/************ non SMP **************/
-static struct CmiStateStruct Cmi_state;
-int _Cmi_mype;
-int _Cmi_myrank;
-
-void CmiMemLock(void) {}
-void CmiMemUnlock(void) {}
+volatile int msgQueueLen;
+volatile int outstanding_recvs;
 
-#define CmiGetState() (&Cmi_state)
-#define CmiGetStateN(n) (&Cmi_state)
+DCMF_Protocol_t  cmi_dcmf_short_registration __attribute__((__aligned__(16)));
+DCMF_Protocol_t  cmi_dcmf_eager_registration __attribute__((__aligned__(16)));
+DCMF_Protocol_t  cmi_dcmf_rzv_registration   __attribute__((__aligned__(16)));
+DCMF_Protocol_t  cmi_dcmf_multicast_registration   __attribute__((__aligned__(16)));
 
-//void CmiYield(void) { sleep(0); }
 
-static void CmiStartThreads(char **argv) {
-    CmiStateInit(Cmi_nodestart, 0, &Cmi_state);
-    _Cmi_mype = Cmi_nodestart;
-    _Cmi_myrank = 0;
-}
-#endif  /* !CMK_SMP */
+typedef struct msg_list {
+    char              * msg;
+//    int                 size;
+//    int                 destpe;
+    int               * pelist;
+//    DCMF_Callback_t     cb;
+//    DCQuad              info __attribute__((__aligned__(16)));
+    DCMF_Request_t      send __attribute__((__aligned__(16)));
+} SMSG_LIST __attribute__((__aligned__(16)));
 
-//int received_immediate;
-//int received_broadcast;
+#define MAX_NUM_SMSGS   64
+CpvDeclare(PCQueue, smsg_list_q);
+static SMSG_LIST * smsg_allocate();
+static void smsg_free (SMSG_LIST *smsg);
 
-/*Add a message to this processor's receive queue, pe is a rank */
-void CmiPushPE(int pe,void *msg) {
-    CmiState cs = CmiGetStateN(pe);
-    MACHSTATE2(3,"Pushing message into rank %d's queue %p{",pe, cs->recv);
-#if CMK_IMMEDIATE_MSG
-    if (CmiIsImmediate(msg)) {
-        /**(CmiUInt2 *)msg = pe;*/
-        //received_immediate = 1;
-        //printf("PushPE: N[%d]P[%d]R[%d] received an imm msg with hdl: %p\n", CmiMyNode(), CmiMyPe(), CmiMyRank(), CmiGetHandler(msg));
-        //CMI_DEST_RANK(msg) = pe;
-        CmiPushImmediateMsg(msg);
-        return;
-    }
-#endif
+/* =====End of Declarations of Machine Specific Variables===== */
 
-    PCQueuePush(cs->recv,(char *)msg);
-    //printf("%d: PCQueue length = %d, msg = %x\n", CmiMyPe(), PCQueueLength(cs->recv), msg);
 
-    CmiIdleLock_addMessage(&cs->idle);
-    MACHSTATE1(3,"} Pushing message into rank %d's queue done",pe);
+/* =====Beginning of Declarations of Machine Specific Functions===== */
+/* Utility functions */
+char *ALIGN_16(char *p) {
+    return((char *)((((unsigned long)p)+0xf)&0xfffffff0));
 }
 
-#if CMK_NODE_QUEUE_AVAILABLE
-/*Add a message to this processor's receive queue */
-static void CmiPushNode(void *msg) {
-    MACHSTATE(3,"Pushing message into NodeRecv queue");
-#if CMK_IMMEDIATE_MSG
-    if (CmiIsImmediate(msg)) {
-        //printf("PushNode: N[%d]P[%d]R[%d] received an imm msg with hdl: %p\n", CmiMyNode(), CmiMyPe(), CmiMyRank(), CmiGetHandler(msg));
-        //CMI_DEST_RANK(msg) = 0;
-        CmiPushImmediateMsg(msg);
-        return;
-    }
-#endif
-    CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
-    PCQueuePush(CsvAccess(NodeState).NodeRecv,msg);
-    CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
-    {
-        CmiState cs=CmiGetStateN(0);
-        CmiIdleLock_addMessage(&cs->idle);
-    }
+void mysleep (int cycles) { /* approximate sleep command */
+    unsigned long long start = DCMF_Timebase();
+    unsigned long long end = start + cycles;
+    while (start < end)
+        start = DCMF_Timebase();
+    return;
 }
-#endif /* CMK_NODE_QUEUE_AVAILABLE */
-
-volatile int msgQueueLen;
-volatile int outstanding_recvs;
-
-static int Cmi_dim;     /* hypercube dim of network */
-
-static char     **Cmi_argv;
-static char     **Cmi_argvcopy;
-static CmiStartFn Cmi_startfn;   /* The start function */
-static int        Cmi_usrsched;  /* Continue after start function finishes? */
-
-extern void ConverseCommonInit(char **argv);
-extern void ConverseCommonExit(void);
-extern void CthInit(char **argv);
-
 static void SendMsgsUntil(int);
 
-
-void SendSpanningChildren(int size, char *msg);
-#if CMK_NODE_QUEUE_AVAILABLE
-void SendSpanningChildrenNode(int size, char *msg);
-#endif
-void SendHypercube(int size, char *msg);
-
-DCMF_Protocol_t  cmi_dcmf_short_registration __attribute__((__aligned__(16)));
-DCMF_Protocol_t  cmi_dcmf_eager_registration __attribute__((__aligned__(16)));
-DCMF_Protocol_t  cmi_dcmf_rzv_registration   __attribute__((__aligned__(16)));
-DCMF_Protocol_t  cmi_dcmf_multicast_registration   __attribute__((__aligned__(16)));
-
-
+/* ######Begining of Machine-specific RDMA related functions###### */
 #define BGP_USE_AM_DIRECT 1
-//#define BGP_USE_RDMA_DIRECT 1
-//#define CMI_DIRECT_DEBUG 1
-#ifdef BGP_USE_AM_DIRECT
-
+/* #define BGP_USE_RDMA_DIRECT 1 */
+/* #define CMI_DIRECT_DEBUG 1 */
+#if BGP_USE_AM_DIRECT
 
 DCMF_Protocol_t  cmi_dcmf_direct_registration __attribute__((__aligned__(16)));
 /** The receive side of a put implemented in DCMF_Send */
 
-
 typedef struct {
     void *recverBuf;
-  void (*callbackFnPtr)(void *);
+    void (*callbackFnPtr)(void *);
     void *callbackData;
     DCMF_Request_t *DCMF_rq_t;
 } dcmfDirectMsgHeader;
 
 /* nothing for us to do here */
 #if (DCMF_VERSION_MAJOR >= 2)
-void direct_send_done_cb(void*nothing, DCMF_Error_t *err) 
-#else 
-  void direct_send_done_cb(void*nothing) 
+void direct_send_done_cb(void*nothing, DCMF_Error_t *err)
+#else
+void direct_send_done_cb(void*nothing)
 #endif
 {
 #if CMI_DIRECT_DEBUG
-  CmiPrintf("[%d] RDMA send_done_cb\n", CmiMyPe());
+    CmiPrintf("[%d] RDMA send_done_cb\n", CmiMyPe());
 #endif
 }
 
@@ -309,36 +177,29 @@ DCMF_Request_t * direct_first_pkt_recv_done (void              * clientdata,
     *buffer=msgHead->recverBuf;
     return msgHead->DCMF_rq_t;
 }
-
-
-#endif
+#endif /* end of #if BGP_USE_AM_DIRECT */
 
 #ifdef BGP_USE_RDMA_DIRECT
 static struct DCMF_Callback_t dcmf_rdma_cb_ack;
 
-
 DCMF_Protocol_t  cmi_dcmf_direct_put_registration __attribute__((__aligned__(16)));
-
 DCMF_Protocol_t  cmi_dcmf_direct_get_registration __attribute__((__aligned__(16)));
-
 DCMF_Protocol_t  cmi_dcmf_direct_rdma_registration __attribute__((__aligned__(16)));
 /** The receive side of a DCMF_Put notification implemented in DCMF_Send */
 
 typedef struct {
-  void (*callbackFnPtr)(void *);
+    void (*callbackFnPtr)(void *);
     void *callbackData;
 } dcmfDirectRDMAMsgHeader;
 
-
-
 #if (DCMF_VERSION_MAJOR >= 2)
-void direct_send_rdma_done_cb(void*nothing, DCMF_Error_t *err) 
-#else 
-  void direct_send_rdma_done_cb(void*nothing) 
+void direct_send_rdma_done_cb(void*nothing, DCMF_Error_t *err)
+#else
+void direct_send_rdma_done_cb(void*nothing)
 #endif
 {
 #if CMI_DIRECT_DEBUG
-  CmiPrintf("[%d] RDMA send_rdma_done_cb result %d\n", CmiMyPe());
+    CmiPrintf("[%d] RDMA send_rdma_done_cb result %d\n", CmiMyPe());
 #endif
 
 
@@ -347,11 +208,11 @@ void direct_send_rdma_done_cb(void*nothing, DCMF_Error_t *err)
 DCMF_Callback_t  directcb;
 
 void     direct_short_rdma_pkt_recv (void             * clientdata,
-                                const DCQuad     * info,
-                                unsigned           count,
-                                unsigned           senderrank,
-                                const char       * buffer,
-                                const unsigned     sndlen) {
+                                     const DCQuad     * info,
+                                     unsigned           count,
+                                     unsigned           senderrank,
+                                     const char       * buffer,
+                                     const unsigned     sndlen) {
 #if CMI_DIRECT_DEBUG
     CmiPrintf("[%d] RDMA direct_short_rdma_pkt_recv\n", CmiMyPe());
 #endif
@@ -359,7 +220,6 @@ void     direct_short_rdma_pkt_recv (void             * clientdata,
     (*(msgHead->callbackFnPtr))(msgHead->callbackData);
 }
 
-
 #if (DCMF_VERSION_MAJOR >= 2)
 typedef void (*cbhdlr) (void *, DCMF_Error_t *);
 #else
@@ -374,33 +234,100 @@ DCMF_Request_t * direct_first_rdma_pkt_recv_done (void              * clientdata
         unsigned          * rcvlen,
         char             ** buffer,
         DCMF_Callback_t   * cb
-                                            ) {
+                                                 ) {
     CmiAbort("direct_first_rdma_pkt_recv should not be called");
 }
+#endif /* end of #if BGP_USE_RDMA_DIRECT */
+/* ######End of Machine-specific RDMA related functions###### */
+
 
+/* ### Beginning of Communication-Op Related Functions ### */
+/* The machine-specific send-related function */
+#if (DCMF_VERSION_MAJOR >= 2)
+static void send_done(void *data, DCMF_Error_t *err);
+static void send_multi_done(void *data, DCMF_Error_t *err);
+#else
+static void send_done(void *data);
+static void send_multi_done(void *data);
+#endif
+static CmiCommHandle MachineSpecificSendForDCMF(int destNode, int size, char *msg, int mode);
+#define CmiMachineSpecificSendFunc MachineSpecificSendForDCMF
 
+/* The machine-specific recv-related function (on the receiver side) */
+#if (DCMF_VERSION_MAJOR >= 2)
+static void recv_done(void *clientdata, DCMF_Error_t * err);
+#else
+static void recv_done(void *clientdata);
 #endif
+DCMF_Request_t * first_multi_pkt_recv_done (const DCQuad      * info,
+        unsigned            count,
+        unsigned            senderrank,
+        const unsigned      sndlen,
+        unsigned            connid,
+        void              * clientdata,
+        unsigned          * rcvlen,
+        char             ** buffer,
+        unsigned          * pw,
+        DCMF_Callback_t   * cb
+                                           );
+DCMF_Request_t * first_pkt_recv_done (void              * clientdata,
+                                      const DCQuad      * info,
+                                      unsigned            count,
+                                      unsigned            senderrank,
+                                      const unsigned      sndlen,
+                                      unsigned          * rcvlen,
+                                      char             ** buffer,
+                                      DCMF_Callback_t   * cb
+                                     );
 
+/* ### End of Communication-Op Related Functions ### */
 
-typedef struct msg_list {
-    char              * msg;
-    int                 size;
-    int                 destpe;
-    int               * pelist;
-    DCMF_Callback_t     cb;
-    DCQuad              info __attribute__((__aligned__(16)));
-    DCMF_Request_t      send __attribute__((__aligned__(16)));
-} SMSG_LIST __attribute__((__aligned__(16)));
+/* ### Beginning of Machine-startup Related Functions ### */
+static void MachineInitForDCMF(int argc, char **argv, int *numNodes, int *myNodeID);
+#define MachineSpecificInit MachineInitForDCMF
 
-#define MAX_NUM_SMSGS   64
-CpvDeclare(PCQueue, smsg_list_q);
+static void MachinePreCommonInitForDCMF(int everReturn);
+static void MachinePostCommonInitForDCMF(int everReturn);
+#define MachineSpecificPreCommonInit MachinePreCommonInitForDCMF
+#define MachineSpecificPostCommonInit MachinePostCommonInitForDCMF
+/* ### End of Machine-startup Related Functions ### */
+
+/* ### Beginning of Machine-running Related Functions ### */
+static void AdvanceCommunicationForDCMF();
+#define MachineSpecificAdvanceCommunication AdvanceCommunicationForDCMF
+
+static void DrainResourcesForDCMF();
+#define MachineSpecificDrainResources AdvanceCommunicationForDCMF
+
+static void MachineExitForDCMF();
+#define MachineSpecificExit AdvanceCommunicationForDCMF
 
+/* ### End of Machine-running Related Functions ### */
+
+/* ### Beginning of Idle-state Related Functions ### */
+
+/* ### End of Idle-state Related Functions ### */
+
+/* =====End of Declarations of Machine Specific Functions===== */
+
+/**
+ *  Macros that overwrites the common codes, such as
+ *  CMK_SMP_NO_COMMTHD, NETWORK_PROGRESS_PERIOD_DEFAULT,
+ *  USE_COMMON_SYNC_P2P, CMK_HAS_SIZE_IN_MSGHDR,
+ *  CMK_OFFLOAD_BCAST_PROCESS etc.
+ */
+#define CMK_OFFLOAD_BCAST_PROCESS 1
+#include "machine-common.c"
+
+/*######Beginning of functions related with Communication-Op functions ######*/
+
+/* Utility functions */
 static inline SMSG_LIST * smsg_allocate() {
     SMSG_LIST *smsg = (SMSG_LIST *)PCQueuePop(CpvAccess(smsg_list_q));
     if (smsg != NULL)
         return smsg;
 
-    void * buf = malloc(sizeof(SMSG_LIST)); 
+    void * buf = malloc(sizeof(SMSG_LIST));
     assert(buf!=NULL);
     assert (((unsigned)buf & 0x0f) == 0);
 
@@ -415,123 +342,198 @@ static inline void smsg_free (SMSG_LIST *smsg) {
         free (smsg);
 }
 
-typedef struct {
-    int sleepMs; /*Milliseconds to sleep while idle*/
-    int nIdles; /*Number of times we've been idle in a row*/
-    CmiState cs; /*Machine state*/
-} CmiIdleState;
-
-static CmiIdleState *CmiNotifyGetState(void) {
-    CmiIdleState *s=(CmiIdleState *)CmiAlloc(sizeof(CmiIdleState));
-    s->sleepMs=0;
-    s->nIdles=0;
-    s->cs=CmiGetState();
-    return s;
-}
+static void SendMsgsUntil(int targetm) {
+    while (msgQueueLen>targetm) {
+#if CMK_SMP
+        DCMF_CriticalSection_enter (0);
+#endif
+
+        while (DCMF_Messager_advance()>0);
 
+#if CMK_SMP
+        DCMF_CriticalSection_exit (0);
+#endif
+    }
+}
 
+/* Send functions */
+/* The callback on sender side */
 #if (DCMF_VERSION_MAJOR >= 2)
-static void send_done(void *data, DCMF_Error_t *err) 
-#else 
-static void send_done(void *data) 
+static void send_done(void *data, DCMF_Error_t *err)
+#else
+static void send_done(void *data)
 #endif
 /* send done callback: sets the smsg entry to done */
 {
     SMSG_LIST *msg_tmp = (SMSG_LIST *)(data);
     CmiFree(msg_tmp->msg);
-    //free(data);
     smsg_free (msg_tmp);
-
     msgQueueLen--;
 }
 
 #if (DCMF_VERSION_MAJOR >= 2)
-static void send_multi_done(void *data, DCMF_Error_t *err) 
-#else 
-static void send_multi_done(void *data) 
+static void send_multi_done(void *data, DCMF_Error_t *err)
+#else
+static void send_multi_done(void *data)
 #endif
 /* send done callback: sets the smsg entry to done */
 {
     SMSG_LIST *msg_tmp = (SMSG_LIST *)(data);
     CmiFree(msg_tmp->msg);
     free(msg_tmp->pelist);
-
     smsg_free(msg_tmp);
-
     msgQueueLen--;
 }
 
+/* The machine specific send function */
+static CmiCommHandle MachineSpecificSendForDCMF(int destNode, int size, char *msg, int mode) {
+    SMSG_LIST *msg_tmp = smsg_allocate(); //(SMSG_LIST *) malloc(sizeof(SMSG_LIST));
+    //msg_tmp->destpe = destNode;
+    //msg_tmp->size = size;
+    msg_tmp->msg = msg;
+
+    DCMF_Callback_t cb;
+    DCQuad info;
+
+    cb.function = send_done;
+    cb.clientdata = msg_tmp;
+
+
+#if CMK_ERROR_CHECKING
+    CMI_MAGIC(msg) = CHARM_MAGIC_NUMBER;
+    CMI_SET_CHECKSUM(msg, size);
+#endif
+    CMI_MSG_SIZE(msg) = size;
+
+    //msg_tmp->cb.function = send_done;
+    //msg_tmp->cb.clientdata   =   msg_tmp;
+
+    DCMF_Protocol_t *protocol = NULL;
+
+    if (size < 224)
+        protocol = &cmi_dcmf_short_registration;
+    else if (size < 2048)
+        protocol = &cmi_dcmf_eager_registration;
+    else
+        protocol = &cmi_dcmf_rzv_registration;
+
+#if CMK_SMP
+    DCMF_CriticalSection_enter (0);
+#endif
+
+    msgQueueLen ++;
+    /*
+     * Original one:
+     *     DCMF_Send (protocol, &msg_tmp->send, msg_tmp->cb,
+                   DCMF_MATCH_CONSISTENCY, msg_tmp->destpe,
+                   msg_tmp->size, msg_tmp->msg, &msg_tmp->info, 1);
+           Ref:http://dcmf.anl-external.org/docs/mpi:dcmfd/group__SEND.html
+     */
+    DCMF_Send (protocol, &msg_tmp->send, cb, DCMF_MATCH_CONSISTENCY,
+               destNode, size, msg, &info, 0);
+
+#if CMK_SMP
+    DCMF_CriticalSection_exit (0);
+#endif
+
+    return 0;
+}
+
+#define MAX_MULTICAST 128
+DCMF_Opcode_t  CmiOpcodeList [MAX_MULTICAST];
+
+void  machineMulticast(int npes, int *pelist, int size, char* msg) {
+    CQdCreate(CpvAccess(cQdState), npes);
+
+    CmiAssert (npes < MAX_MULTICAST);
+
+#if CMK_ERROR_CHECKING
+    CMI_MAGIC(msg) = CHARM_MAGIC_NUMBER;
+    CMI_SET_CHECKSUM(msg, size);
+#endif
+
+    CMI_MSG_SIZE(msg) = size;
+    CMI_SET_BROADCAST_ROOT(msg,0);
+
+    SMSG_LIST *msg_tmp = smsg_allocate(); //(SMSG_LIST *) malloc(sizeof(SMSG_LIST));
+
+    //msg_tmp->destpe    = -1;      //multicast operation
+    //msg_tmp->size      = size * npes; //keep track of #bytes outstanding
+    msg_tmp->msg       = msg;
+    msg_tmp->pelist    = pelist;
+
+    DCMF_Multicast_t  mcast_info __attribute__((__aligned__(16)));
+    DCQuad info;
+
+    mcast_info.registration   = & cmi_dcmf_multicast_registration;
+    mcast_info.request        = & msg_tmp->send;
+    mcast_info.cb_done.function    =   send_multi_done;
+    mcast_info.cb_done.clientdata  =   msg_tmp;
+    mcast_info.consistency    =   DCMF_MATCH_CONSISTENCY;
+    mcast_info.connection_id  =   CmiMyPe();
+    mcast_info.bytes          =   size;
+    mcast_info.src            =   msg;
+    mcast_info.nranks         =   npes;
+    mcast_info.ranks          =   (unsigned *)pelist;
+    mcast_info.opcodes        =   CmiOpcodeList;   //static list of MAX_MULTICAST entires with 0 in them
+    mcast_info.flags          =   0;
+    mcast_info.msginfo        =   &info;
+    //mcast_info.count          =   1;
+    mcast_info.count          =   0;
+
+#if CMK_SMP
+    DCMF_CriticalSection_enter (0);
+#endif
+    msgQueueLen++;
+    DCMF_Multicast (&mcast_info);
+
+#if CMK_SMP
+    DCMF_CriticalSection_exit (0);
+#endif
+}
 
+/* Recv functions */
+/* The callback on the recv side */
 #if (DCMF_VERSION_MAJOR >= 2)
-static void recv_done(void *clientdata, DCMF_Error_t * err) 
-#else 
-static void recv_done(void *clientdata) 
+static void recv_done(void *clientdata, DCMF_Error_t * err)
+#else
+static void recv_done(void *clientdata)
 #endif
 /* recv done callback: push the recved msg to recv queue */
 {
 
     char *msg = (char *) clientdata;
-    int sndlen = ((CmiMsgHeaderBasic *) msg)->size;
 
     /*printf ("NODE[%d] Recv message done with msg rank %d\n", CmiMyNode(), CMI_DEST_RANK(msg));*/
-
-    /* then we do what PumpMsgs used to do:
-     * push msg to recv queue */
-    int count=0;
+    MACHSTATE3(2,"[%d] recv_done begin with msg %p size=%d { ", CmiMyNode(), msg, CMI_MSG_SIZE(msg));
+#if CMK_ERROR_CHECKING
+    int sndlen = CMI_MSG_SIZE(msg);
     CMI_CHECK_CHECKSUM(msg, sndlen);
     if (CMI_MAGIC(msg) != CHARM_MAGIC_NUMBER) { /* received a non-charm msg */
         CmiAbort("Charm++ Warning: Non Charm++ Message Received. \n");
         return;
     }
-
-#if CMK_BROADCAST_SPANNING_TREE | CMK_BROADCAST_HYPERCUBE
-    if (CMI_IS_BCAST_ON_CORES(msg) ) {
-        int pe = CMI_DEST_RANK(msg);
-
-        //printf ("%d: Receiving bcast message from %d with %d bytes for %d\n", CmiMyPe(), CMI_BROADCAST_ROOT(msg), sndlen, pe);
-
-        char *copymsg;
-        copymsg = (char *)CmiAlloc(sndlen);
-        CmiMemcpy(copymsg,msg,sndlen);
-        //received_broadcast = 1;
-        PCQueuePush(broadcast_q, copymsg);     
-    }
 #endif
 
-#if CMK_NODE_QUEUE_AVAILABLE
-#if CMK_BROADCAST_SPANNING_TREE
-    if (CMI_IS_BCAST_ON_NODES(msg)) {
-        //printf ("%d: Receiving node bcast message from %d with %d bytes for %d\n", CmiMyPe(), CMI_BROADCAST_ROOT(msg), sndlen, CMI_DEST_RANK(msg));
-        char *copymsg = (char *)CmiAlloc(sndlen);
-        CmiMemcpy(copymsg,msg,sndlen);
-
-        CmiLock(CsvAccess(node_bcastLock));
-        PCQueuePush(CsvAccess(node_bcastq), copymsg);
-        CmiUnlock(CsvAccess(node_bcastLock));  
-    }
-#endif
-    if (CMI_DEST_RANK(msg) == SMP_NODEMESSAGE)
-        CmiPushNode(msg);
-    else
-#endif
-        CmiPushPE(CMI_DEST_RANK(msg), (void *)msg);
+    handleOneRecvedMsg(CMI_MSG_SIZE(msg), msg);
 
-    outstanding_recvs --;
+    outstanding_recvs--;
+    MACHSTATE(2,"} recv_done end ");
+    return;
 }
 
-
-void     short_pkt_recv (void             * clientdata,
-                         const DCQuad     * info,
-                         unsigned           count,
-                         unsigned           senderrank,
-                         const char       * buffer,
-                         const unsigned     sndlen) {
+void short_pkt_recv (void             * clientdata,
+                     const DCQuad     * info,
+                     unsigned           count,
+                     unsigned           senderrank,
+                     const char       * buffer,
+                     const unsigned     sndlen) {
     outstanding_recvs ++;
     int alloc_size = sndlen;
 
     char * new_buffer = (char *)CmiAlloc(alloc_size);
     CmiMemcpy (new_buffer, buffer, sndlen);
-    
+
 #if (DCMF_VERSION_MAJOR >= 2)
     recv_done (new_buffer, NULL);
 #else
@@ -539,26 +541,22 @@ void     short_pkt_recv (void             * clientdata,
 #endif
 }
 
-
 DCMF_Request_t * first_multi_pkt_recv_done (const DCQuad      * info,
-                                           unsigned            count,
-                                           unsigned            senderrank,                                    
-                                           const unsigned      sndlen,
-                                           unsigned            connid,
-                                           void              * clientdata,
-                                           unsigned          * rcvlen,
-                                           char             ** buffer,
-                                           unsigned          * pw,
-                                           DCMF_Callback_t   * cb
-                                           ) {
+        unsigned            count,
+        unsigned            senderrank,
+        const unsigned      sndlen,
+        unsigned            connid,
+        void              * clientdata,
+        unsigned          * rcvlen,
+        char             ** buffer,
+        unsigned          * pw,
+        DCMF_Callback_t   * cb
+                                           ) {
     outstanding_recvs ++;
     int alloc_size = sndlen + sizeof(DCMF_Request_t) + 16;
-
-    //printf ("%d: Receiving message %d bytes from %d\n", CmiMyPe(), sndlen, senderrank);
-
+    /*printf ("%d: Receiving message %d bytes from %d\n", CmiMyPe(), sndlen, senderrank);*/
     /* printf ("Receiving %d bytes\n", sndlen); */
-    *rcvlen = sndlen;  /* to avoid malloc(0) which might
-                                   return NULL */
+    *rcvlen = sndlen;  /* to avoid malloc(0) which might return NULL */
 
     *buffer = (char *)CmiAlloc(alloc_size);
     cb->function = recv_done;
@@ -568,7 +566,6 @@ DCMF_Request_t * first_multi_pkt_recv_done (const DCQuad      * info,
     return (DCMF_Request_t *) ALIGN_16(*buffer + sndlen);
 }
 
-
 DCMF_Request_t * first_pkt_recv_done (void              * clientdata,
                                       const DCQuad      * info,
                                       unsigned            count,
@@ -580,12 +577,9 @@ DCMF_Request_t * first_pkt_recv_done (void              * clientdata,
                                      ) {
     outstanding_recvs ++;
     int alloc_size = sndlen + sizeof(DCMF_Request_t) + 16;
-
-    //printf ("%d: Receiving message %d bytes from %d\n", CmiMyPe(), sndlen, senderrank);
-
+    /* printf ("%d: Receiving message %d bytes from %d\n", CmiMyPe(), sndlen, senderrank);*/
     /* printf ("Receiving %d bytes\n", sndlen); */
-    *rcvlen = sndlen;  /* to avoid malloc(0) which might
-                                   return NULL */
+    *rcvlen = sndlen;  /* to avoid malloc(0) which might return NULL */
 
     *buffer = (char *)CmiAlloc(alloc_size);
     cb->function = recv_done;
@@ -594,81 +588,21 @@ DCMF_Request_t * first_pkt_recv_done (void              * clientdata,
     return (DCMF_Request_t *) ALIGN_16(*buffer + sndlen);
 }
 
+#if 0
+/* -----------------------------------------
+ * Rectangular broadcast implementation
+ * -----------------------------------------
+ */
+unsigned int *ranklist;
+BGTsC_t        barrier;
+#define MAX_COMM  256
+static void * comm_table [MAX_COMM];
 
-#if CMK_NODE_QUEUE_AVAILABLE
-void sendBroadcastMessagesNode() {
-    //this should be exectued on comm thread
-    CmiAssert(CmiMyRank() == CmiMyNodeSize());
-    if (PCQueueLength(CsvAccess(node_bcastq))==0) return;
-    //node broadcast message could be always handled by any cores (including
-    //comm thd) on this node
-    CmiLock(CsvAccess(node_bcastLock));
-    char *msg = PCQueuePop(CsvAccess(node_bcastq));
-    CmiUnlock(CsvAccess(node_bcastLock));
-    while (msg) {
-#if CMK_BROADCAST_SPANNING_TREE
-        //printf("sendBroadcastMessagesNode: node %d rank %d with msg root %d\n", CmiMyNode(), CmiMyRank(), CMI_BROADCAST_ROOT(msg));
-        SendSpanningChildrenNode(((CmiMsgHeaderBasic *) msg)->size, msg);
-#endif
-        CmiFree(msg);
-
-        CmiLock(CsvAccess(node_bcastLock));
-        msg = PCQueuePop(CsvAccess(node_bcastq));
-        CmiUnlock(CsvAccess(node_bcastLock));
-    }
-}
-#endif
-
-static void CmiSendChildrenPeers(int rank, int size, char *msg);
-//Should be only called from comm thd
-void sendBroadcastMessages() {
-#if CMK_SMP
-    CmiAssert(CmiMyRank()==_Cmi_mynodesize); 
-#endif
-
-    if (PCQueueLength(broadcast_q)==0) return;
-
-    char *msg = (char *) PCQueuePop(broadcast_q);
-
-    while (msg) {
-       int msgsize = ((CmiMsgHeaderBasic *)msg)->size;
-#if CMK_BROADCAST_SPANNING_TREE
-        SendSpanningChildren(msgsize, msg);
-#elif CMK_BROADCAST_HYPERCUBE
-        SendHypercube(msgsize, msg);
-#endif
-
-#if CMK_SMP
-       //this msg has already been pushed into CMI_DEST_RANK(msg)'s queue
-       //so we just need to send the msg to other cores, and free the msg as it 
-       //is a copy in recv_done --Chao Mei
-       CmiSendChildrenPeers(CMI_DEST_RANK(msg), msgsize, msg); 
-#endif       
-       CmiFree(msg);
-       msg = (char *) PCQueuePop(broadcast_q);
-    }
-}
-
-CpvDeclare(unsigned, networkProgressCount);
-int  networkProgressPeriod;
-
-#if 0
-unsigned int *ranklist;
-
-BGTsC_t        barrier;
-
-// -----------------------------------------
-// Rectangular broadcast implementation
-// -----------------------------------------
-
-#define MAX_COMM  256
-static void * comm_table [MAX_COMM];
-
-typedef struct rectbcast_msg {
-    BGTsRC_t           request;
-    DCMF_Callback_t    cb;
-    char              *msg;
-} RectBcastInfo;
+typedef struct rectbcast_msg {
+    BGTsRC_t           request;
+    DCMF_Callback_t    cb;
+    char              *msg;
+} RectBcastInfo;
 
 
 static void bcast_done (void *data) {
@@ -704,8 +638,8 @@ static  void *  bcast_recv     (unsigned               root,
 
 
 extern void bgl_machine_RectBcast (unsigned                 commid,
-                                       const char             * sndbuf,
-                                       unsigned                 sndlen) {
+                                   const char             * sndbuf,
+                                   unsigned                 sndlen) {
     RectBcastInfo *rinfo  =   (RectBcastInfo *) malloc (sizeof(RectBcastInfo));
     rinfo->cb.function    =   bcast_done;
     rinfo->cb.clientdata  =   rinfo;
@@ -714,1189 +648,330 @@ extern void bgl_machine_RectBcast (unsigned                 commid,
 
 }
 
-extern void        bgl_machine_RectBcastInit  (unsigned               commID,
-            const BGTsRC_Geometry_t* geometry) {
-
-    CmiAssert (commID < 256);
-    CmiAssert (comm_table [commID] == NULL);
-
-    BGTsRC_t *request =  (BGTsRC_t *) malloc (sizeof (BGTsRC_t));
-    comm_table [commID] = request;
-
-    BGTsRC_AsyncBcast_init  (request, commID,  geometry);
-}
-
-
-
-
-//--------------------------------------------------------------
-//----- End Rectangular Broadcast Implementation ---------------
-//--------------------------------------------------------------
-#endif
-
-//approx sleep command
-void mysleep (int cycles) {
-    unsigned long long start = DCMF_Timebase();
-    unsigned long long end = start + cycles;
-
-    while (start < end)
-        start = DCMF_Timebase();
-
-    return;
-}
-
-static void * test_buf;
-
-void ConverseInit(int argc, char **argv, CmiStartFn fn, int usched, int initret) {
-    int n, i, count;
-
-    //fprintf(stderr, "Initializing Converse Blue Gene/P machine Layer\n");
-
-    DCMF_Messager_initialize();
-
-#if CMK_SMP
-    DCMF_Configure_t  config_in, config_out;
-    config_in.thread_level= DCMF_THREAD_MULTIPLE;
-    config_in.interrupts  = DCMF_INTERRUPTS_OFF;
-
-    DCMF_Messager_configure(&config_in, &config_out);
-    //assert (config_out.thread_level == DCMF_THREAD_MULTIPLE); //not supported in vn mode
-#endif
-
-    DCMF_Send_Configuration_t short_config, eager_config, rzv_config;
-
-
-    short_config.protocol      = DCMF_DEFAULT_SEND_PROTOCOL;
-    short_config.cb_recv_short = short_pkt_recv;
-    short_config.cb_recv       = first_pkt_recv_done;
-
-#if (DCMF_VERSION_MAJOR >= 3)
-    short_config.network  = DCMF_DEFAULT_NETWORK;
-#elif (DCMF_VERSION_MAJOR == 2)
-    short_config.network  = DCMF_DefaultNetwork;
-#endif
-
-    eager_config.protocol      = DCMF_DEFAULT_SEND_PROTOCOL;
-    eager_config.cb_recv_short = short_pkt_recv;
-    eager_config.cb_recv       = first_pkt_recv_done;
-#if (DCMF_VERSION_MAJOR >= 3)
-    eager_config.network  = DCMF_DEFAULT_NETWORK;
-#elif (DCMF_VERSION_MAJOR == 2)
-    eager_config.network  = DCMF_DefaultNetwork;
-#endif
-
-#ifdef  OPT_RZV
-#warning "Enabling Optimize Rzv"
-    rzv_config.protocol        = DCMF_RZV_SEND_PROTOCOL;
-#else
-    rzv_config.protocol        = DCMF_DEFAULT_SEND_PROTOCOL;
-#endif
-    rzv_config.cb_recv_short   = short_pkt_recv;
-    rzv_config.cb_recv         = first_pkt_recv_done;
-#if (DCMF_VERSION_MAJOR >= 3)
-    rzv_config.network  = DCMF_DEFAULT_NETWORK;
-#elif (DCMF_VERSION_MAJOR == 2)
-    rzv_config.network  = DCMF_DefaultNetwork;
-#endif
-
-    DCMF_Send_register (&cmi_dcmf_short_registration, &short_config);
-    DCMF_Send_register (&cmi_dcmf_eager_registration, &eager_config);
-    DCMF_Send_register (&cmi_dcmf_rzv_registration,   &rzv_config);
-
-#ifdef BGP_USE_AM_DIRECT
-    DCMF_Send_Configuration_t direct_config;
-    direct_config.protocol      = DCMF_DEFAULT_SEND_PROTOCOL;
-    direct_config.cb_recv_short = direct_short_pkt_recv;
-    direct_config.cb_recv       = direct_first_pkt_recv_done;
-#if (DCMF_VERSION_MAJOR >= 3)
-    direct_config.network  = DCMF_DEFAULT_NETWORK;
-#elif (DCMF_VERSION_MAJOR == 2)
-    direct_config.network  = DCMF_DefaultNetwork;
-#endif
-    DCMF_Send_register (&cmi_dcmf_direct_registration,   &direct_config);
-    directcb.function=direct_send_done_cb;
-    directcb.clientdata=NULL;
-#endif
-
-#ifdef BGP_USE_RDMA_DIRECT
-    /* notification protocol */
-    DCMF_Send_Configuration_t direct_rdma_config;
-    direct_rdma_config.protocol      = DCMF_DEFAULT_SEND_PROTOCOL;
-    direct_rdma_config.cb_recv_short = direct_short_rdma_pkt_recv;
-    direct_rdma_config.cb_recv       = direct_first_rdma_pkt_recv_done;
-#if (DCMF_VERSION_MAJOR >= 3)
-    direct_rdma_config.network  = DCMF_DEFAULT_NETWORK;
-#elif (DCMF_VERSION_MAJOR == 2)
-    direct_rdma_config.network  = DCMF_DefaultNetwork;
-#endif
-    DCMF_Send_register (&cmi_dcmf_direct_rdma_registration,   &direct_rdma_config);
-    directcb.function=direct_send_rdma_done_cb;
-    directcb.clientdata=NULL;
-    /* put protocol */
-   DCMF_Put_Configuration_t put_configuration = { DCMF_DEFAULT_PUT_PROTOCOL };
-   DCMF_Put_register (&cmi_dcmf_direct_put_registration, &put_configuration);
-   DCMF_Get_Configuration_t get_configuration = { DCMF_DEFAULT_GET_PROTOCOL };
-   DCMF_Get_register (&cmi_dcmf_direct_get_registration, &get_configuration);
-    
-#endif
-    //fprintf(stderr, "Initializing Eager Protocol\n");
-
-    _Cmi_numnodes = DCMF_Messager_size();
-    _Cmi_mynode = DCMF_Messager_rank();
-
-    unsigned rank = DCMF_Messager_rank();
-    unsigned size = DCMF_Messager_size();
-
-    CmiBarrier();
-    CmiBarrier();
-    CmiBarrier();
-
-    /* processor per node */
-    _Cmi_mynodesize = 1;
-    CmiGetArgInt(argv,"+ppn", &_Cmi_mynodesize);
-#if ! CMK_SMP
-    if (_Cmi_mynodesize > 1 && _Cmi_mynode == 0)
-        CmiAbort("+ppn cannot be used in non SMP version!\n");
-#endif
-
-    _Cmi_numpes = _Cmi_numnodes * _Cmi_mynodesize;
-    Cmi_nodestart = _Cmi_mynode * _Cmi_mynodesize;
-    Cmi_argvcopy = CmiCopyArgs(argv);
-    Cmi_argv = argv;
-    Cmi_startfn = fn;
-    Cmi_usrsched = usched;
-
-    //printf ("Starting Charm with %d nodes and %d processors\n", CmiNumNodes(), CmiNumPes());
-
-    DCMF_Multicast_Configuration_t mconfig;
-    mconfig.protocol = DCMF_MEMFIFO_DMA_MSEND_PROTOCOL;
-    mconfig.cb_recv  = first_multi_pkt_recv_done;
-    mconfig.clientdata = NULL;
-    mconfig.connectionlist = (void **) malloc (CmiNumPes() * sizeof(unsigned long));
-    mconfig.nconnections = CmiNumPes();  
-    DCMF_Multicast_register(&cmi_dcmf_multicast_registration, &mconfig);
-
-
-    /* find dim = log2(numpes), to pretend we are a hypercube */
-    for ( Cmi_dim=0,n=_Cmi_numpes; n>1; n/=2 )
-        Cmi_dim++ ;
-
-
-    /* checksum flag */
-    if (CmiGetArgFlag(argv,"+checksum")) {
-#if CMK_ERROR_CHECKING
-        checksum_flag = 1;
-        if (_Cmi_mynode == 0) CmiPrintf("Charm++: CheckSum checking enabled! \n");
-#else
-        if (_Cmi_mynode == 0) CmiPrintf("Charm++: +checksum ignored in optimized version! \n");
-#endif
-    }
-
-    CsvInitialize(CmiNodeState, NodeState);
-    CmiNodeStateInit(&CsvAccess(NodeState));
-
-    broadcast_q = PCQueueCreate();
-
-#if CMK_NODE_QUEUE_AVAILABLE
-    CsvInitialize(PCQueue, node_bcastq);
-    CsvAccess(node_bcastq) = PCQueueCreate();
-    CsvInitialize(CmiNodeLock, node_bcastLock);
-    CsvAccess(node_bcastLock) = CmiCreateLock();
-#endif
-
-    int actualNodeSize = _Cmi_mynodesize;
-#if !CMK_MULTICORE
-    actualNodeSize++; //considering the extra comm thread
-#endif
-
-    procState = (ProcState *)CmiAlloc((actualNodeSize) * sizeof(ProcState));
-    for (i=0; i<actualNodeSize; i++) {
-        /*    procState[i].sendMsgBuf = PCQueueCreate();   */
-        procState[i].recvLock = CmiCreateLock();
-        procState[i].bcastLock = CmiCreateLock();
-    }
-
-#if CMK_SMP && !CMK_MULTICORE
-    commThdExitLock = CmiCreateLock();
-#endif
-
-    /* Network progress function is used to poll the network when for
-       messages. This flushes receive buffers on some  implementations*/
-    networkProgressPeriod = PROGRESS_PERIOD;
-    CmiGetArgInt(argv, "+networkProgressPeriod", &networkProgressPeriod);
-
-    //printf ("Starting Threads\n");
-
-    CmiStartThreads(argv);
-
-    ConverseRunPE(initret);
-}
-
-
-int PerrorExit (char *err) {
-    fprintf (stderr, "err\n\n");
-    exit (-1);
-    return -1;
-}
-
-
-void ConverseRunPE(int everReturn) {
-    //printf ("ConverseRunPE on rank %d\n", CmiMyPe());
-
-    CmiIdleState *s=CmiNotifyGetState();
-    CmiState cs;
-    char** CmiMyArgv;
-    CmiNodeAllBarrier();
-
-    cs = CmiGetState();
-    CpvInitialize(void *,CmiLocalQueue);
-    CpvAccess(CmiLocalQueue) = cs->localqueue;
-
-    if (CmiMyRank())
-        CmiMyArgv=CmiCopyArgs(Cmi_argvcopy);
-    else
-        CmiMyArgv=Cmi_argv;
-
-    CthInit(CmiMyArgv);
-
-    /* initialize the network progress counter*/
-    /* Network progress function is used to poll the network when for
-       messages. This flushes receive buffers on some  implementations*/
-    CpvInitialize(int , networkProgressCount);
-    CpvAccess(networkProgressCount) = 0;
-
-    
-
-    CpvInitialize(PCQueue, smsg_list_q);
-    CpvAccess(smsg_list_q) = PCQueueCreate();
-
-    //printf ("Before Converse Common Init\n");
-    ConverseCommonInit(CmiMyArgv);
-
-    CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,(CcdVoidFn)CmiNotifyIdle,NULL);
-
-    CmiBarrier();
-
-    /* Converse initialization finishes, immediate messages can be processed.
-       node barrier previously should take care of the node synchronization */
-    _immediateReady = 1;
-
-    /* communication thread */
-    if (CmiMyRank() == CmiMyNodeSize()) {
-        Cmi_startfn(CmiGetArgc(CmiMyArgv), CmiMyArgv);
-        while (1) CommunicationServer(5);
-    } else {
-        //printf ("Calling Start Fn and the scheduler \n");
-
-        if (!everReturn) {
-            Cmi_startfn(CmiGetArgc(CmiMyArgv), CmiMyArgv);
-            if (Cmi_usrsched==0) CsdScheduler(-1);
-            ConverseExit();
-        }
-    }
-}
-
-#if CMK_SMP
-static int inexit = 0;
-
-/* test if all processors recv queues are empty */
-static int RecvQueueEmpty() {
-    int i;
-    for (i=0; i<_Cmi_mynodesize; i++) {
-        CmiState cs=CmiGetStateN(i);
-        if (!PCQueueEmpty(cs->recv)) return 0;
-    }
-    return 1;
-}
-
-#endif
-
-
-//extern void DCMF_Messager_dumpTimers();
-
-void ConverseExit(void) {
-
-#if !CMK_SMP
-    /* in SMP mode, the comm thread is advancing the communication */
-    while (msgQueueLen > 0 || outstanding_recvs > 0) {
-        AdvanceCommunications();
-    }
-#endif
-
-    CmiNodeBarrier();
-    ConverseCommonExit();
-
-    //  if(CmiMyPe()%101 == 0)
-    //DCMF_Messager_dumpTimers();
-
-    if (CmiMyPe() == 0) {
-        printf("End of program\n");
-    }
-
-    CmiNodeBarrier();
-//  CmiNodeAllBarrier ();
-
-#if CMK_SMP && !CMK_MULTICORE
-    //CmiLock(commThdExitLock);
-    commThdExit = 1;
-    //CmiUnlock(commThdExitLock);
-
-    _bgp_msync();
-#endif
-
-    int rank0 = 0;
-
-    if (CmiMyRank() == 0) {
-        rank0 = 1;
-        //CmiFree(procState);
-        DCMF_Messager_finalize();
-    }
-
-    CmiNodeBarrier();
-//  CmiNodeAllBarrier ();
-
-    if (rank0)
-        exit(0);
-    else
-        pthread_exit(NULL);
-}
-
-/* exit() called on any node would abort the whole program */
-void CmiAbort(const char * message) {
-    CmiError("------------- Processor %d Exiting: Called CmiAbort ------------\n"
-             "{snd:%d,rcv:%d} Reason: %s\n",CmiMyPe(),
-             msgQueueLen, outstanding_recvs, message);
-    //CmiPrintStackTrace(0);
-#if 0
-    /* Since it's abortion, why need to advance the comm? The system should
-     * clean itself.
-     */
-    while (msgQueueLen > 0 || outstanding_recvs > 0) {
-        AdvanceCommunications();
-    }
-
-    CmiBarrier();
-#endif
-    assert (0);
-}
-
-static void CommunicationServer(int sleepTime) {
-#if CMK_SMP
-    if (commThdExit) {
-        while (msgQueueLen > 0 || outstanding_recvs > 0) {
-            AdvanceCommunications();
-        }
-        pthread_exit(NULL);
-        return;
-    }
-#endif
-    AdvanceCommunications();
-
-#if CMK_IMMEDIATE_MSG && CMK_SMP
-    CmiHandleImmediate();
-#endif
-
-    //mysleep(sleepTime);
-}
-
-static void CommunicationServerThread(int sleepTime) {
-#if CMK_SMP
-    CommunicationServer(sleepTime);
-#endif
-//immediate msgs are handled in AdvanceCommunications
-}
-
-#if CMK_NODE_QUEUE_AVAILABLE
-char *CmiGetNonLocalNodeQ(void) {
-    CmiState cs = CmiGetState();
-    char *result = 0;
-    CmiIdleLock_checkMessage(&cs->idle);
-    if (!PCQueueEmpty(CsvAccess(NodeState).NodeRecv)) {
-        MACHSTATE1(3,"CmiGetNonLocalNodeQ begin %d {", CmiMyPe());
-
-        if (CmiTryLock(CsvAccess(NodeState).CmiNodeRecvLock) == 0) {
-            //CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
-            result = (char *) PCQueuePop(CsvAccess(NodeState).NodeRecv);
-            CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
-        }
-
-        MACHSTATE1(3,"} CmiGetNonLocalNodeQ end %d ", CmiMyPe());
-    }
-    return result;
-}
-#endif
-
-
-void *CmiGetNonLocal() {
-
-    CmiState cs = CmiGetState();
-
-    void *msg = NULL;
-    CmiIdleLock_checkMessage(&cs->idle);
-    /* although it seems that lock is not needed, I found it crashes very often
-       on mpi-smp without lock */
-
-#if !CMK_SMP 
-//ChaoMei changes
-    AdvanceCommunications();
-#endif
-
-    /*if(CmiMyRank()==0) printf("Got stuck here on proc[%d] node[%d]\n", CmiMyPe(), CmiMyNode());*/
-
-    if (PCQueueLength(cs->recv)==0) return NULL;
-
-    msg =  PCQueuePop(cs->recv);
-
-    return msg;
-}
-
-static void CmiSendSelf(char *msg) {
-#if CMK_IMMEDIATE_MSG
-    if (CmiIsImmediate(msg)) {
-        /* CmiBecomeNonImmediate(msg); */
-        //printf("In SendSelf, N[%d]P[%d]R[%d] received an imm msg with hdl: %p\n", CmiMyNode(), CmiMyPe(), CmiMyRank(), CmiGetHandler(msg));
-        CmiPushImmediateMsg(msg);
-        CmiHandleImmediate();
-        return;
-    }
-#endif
-    
-    CdsFifo_Enqueue(CpvAccess(CmiLocalQueue),msg);
-}
-
-void machineSend(SMSG_LIST *msg_tmp) {    
-
-    if (msg_tmp->destpe == CmiMyNode())
-        CmiAbort("Sending to self\n");
-
-    CmiAssert(msg_tmp->destpe >= 0 && msg_tmp->destpe < CmiNumNodes());
-    msg_tmp->cb.function     =   send_done;
-    msg_tmp->cb.clientdata   =   msg_tmp;
-
-    DCMF_Protocol_t *protocol = NULL;
-
-    if (msg_tmp->size < 224)
-        protocol = &cmi_dcmf_short_registration;
-    else if (msg_tmp->size < 2048)
-        protocol = &cmi_dcmf_eager_registration;
-    else
-        protocol = &cmi_dcmf_rzv_registration;
-
-
-#if CMK_SMP
-    DCMF_CriticalSection_enter (0);
-#endif
-
-    msgQueueLen ++;
-    DCMF_Send (protocol, &msg_tmp->send, msg_tmp->cb,
-               DCMF_MATCH_CONSISTENCY, msg_tmp->destpe,
-               msg_tmp->size, msg_tmp->msg, &msg_tmp->info, 1);
-
-/*    
-    #if CMK_SMP && !CMK_MULTICORE
-    //Adding this advance call here improves the SMP performance
-    //a little bit although it is possible that some more bugs are
-    //introduced
-    DCMF_Messager_advance();
-    #endif
-*/
-
-#if CMK_SMP
-    DCMF_CriticalSection_exit (0);
-#endif
-}
-
-#define MAX_MULTICAST 128
-DCMF_Opcode_t  CmiOpcodeList [MAX_MULTICAST];
-
-void  machineMulticast(int npes, int *pelist, int size, char* msg){  
-  CQdCreate(CpvAccess(cQdState), npes);
-  
-  CmiAssert (npes < MAX_MULTICAST);
-
-  CMI_MAGIC(msg) = CHARM_MAGIC_NUMBER;
-  ((CmiMsgHeaderBasic *)msg)->size = size;  
-  CMI_SET_BROADCAST_ROOT(msg,0);
-  CMI_SET_CHECKSUM(msg, size);
-  
-  SMSG_LIST *msg_tmp = smsg_allocate(); //(SMSG_LIST *) malloc(sizeof(SMSG_LIST));
-  
-  msg_tmp->destpe    = -1;      //multicast operation
-  msg_tmp->size      = size * npes; //keep track of #bytes outstanding
-  msg_tmp->msg       = msg;
-  msg_tmp->pelist    = pelist;
-  
-  msgQueueLen ++;
-  
-  DCMF_Multicast_t  mcast_info __attribute__((__aligned__(16)));
-  
-  mcast_info.registration   = & cmi_dcmf_multicast_registration;
-  mcast_info.request        = & msg_tmp->send;
-  mcast_info.cb_done.function    =   send_multi_done;
-  mcast_info.cb_done.clientdata  =   msg_tmp;
-  mcast_info.consistency    =   DCMF_MATCH_CONSISTENCY;
-  mcast_info.connection_id  =   CmiMyPe();
-  mcast_info.bytes          =   size;
-  mcast_info.src            =   msg;
-  mcast_info.nranks         =   npes;
-  mcast_info.ranks          =   (unsigned *)pelist;
-  mcast_info.opcodes        =   CmiOpcodeList;   //static list of MAX_MULTICAST entires with 0 in them
-  mcast_info.flags          =   0;
-  mcast_info.msginfo        =   &msg_tmp->info;
-  mcast_info.count          =   1;
-
-  DCMF_Multicast (&mcast_info);
-}
-
-
-
-void CmiGeneralFreeSendN (int node, int rank, int size, char * msg);
-
-/* The general free send function
- * Send is synchronous, and free msg after posted
- */
-void  CmiGeneralFreeSend(int destPE, int size, char* msg) {
-
-  if (destPE < 0 || destPE > CmiNumPes ())
-    printf ("Sending to %d\n", destPE);
-
-  CmiAssert (destPE >= 0 && destPE < CmiNumPes());
-
-    CmiState cs = CmiGetState();
-
-    if (destPE==cs->pe) {
-        CmiSendSelf(msg);
-        return;
-    }
-    //printf ("%d: Sending Message to %d \n", CmiMyPe(), destPE);
-    CmiGeneralFreeSendN (CmiNodeOf(destPE), CmiRankOf(destPE), size, msg);
-}
-
-void CmiGeneralFreeSendN (int node, int rank, int size, char * msg) {
-
-    //printf ("%d, %d: Sending Message to node %d rank %d \n", CmiMyPe(),
-    //  CmiMyNode(), node, rank);
-
-#if CMK_SMP
-    CMI_DEST_RANK(msg) = rank;
-    //CMI_SET_CHECKSUM(msg, size);
-
-    if (node == CmiMyNode()) {
-        CmiPushPE(rank,msg);
-        return;
-    }
-#endif
-
-    SMSG_LIST *msg_tmp = smsg_allocate(); //(SMSG_LIST *) malloc(sizeof(SMSG_LIST));
-    msg_tmp->destpe = node; //destPE;
-    msg_tmp->size = size;
-    msg_tmp->msg = msg;
-
-    machineSend(msg_tmp);
-}
-
-void CmiSyncSendFn(int destPE, int size, char *msg) {
-    char *copymsg;
-    copymsg = (char *)CmiAlloc(size);
-    CmiMemcpy(copymsg,msg,size);
-    //if(CmiMyRank()==CmiMyNodeSize()) printf("CmiSyncSendFn on comm thd on node %d\n", CmiMyNode());
-    CmiFreeSendFn(destPE,size,copymsg);
-}
-
-void CmiFreeSendFn(int destPE, int size, char *msg) {    
-    CQdCreate(CpvAccess(cQdState), 1);
-    //if(CmiMyRank()==CmiMyNodeSize()) printf("CmiFreeSendFn on comm thd on node %d\n", CmiMyNode());
-
-    CMI_SET_BROADCAST_ROOT(msg,0);
-    CMI_MAGIC(msg) = CHARM_MAGIC_NUMBER;
-    ((CmiMsgHeaderBasic *)msg)->size = size;
-    CMI_SET_CHECKSUM(msg, size);
-
-    CmiGeneralFreeSend(destPE,size,msg);
-}
-
-/* same as CmiSyncSendFn, but don't set broadcast root in msg header */
-void CmiSyncSendFn1(int destPE, int size, char *msg) {
-    char *copymsg;
-    copymsg = (char *)CmiAlloc(size);
-    CmiMemcpy(copymsg, msg, size);
-
-    //  asm volatile("sync" ::: "memory");
-
-    CMI_MAGIC(copymsg) = CHARM_MAGIC_NUMBER;
-    ((CmiMsgHeaderBasic *)copymsg)->size = size;
-    CMI_SET_CHECKSUM(copymsg, size);
-
-    CmiGeneralFreeSend(destPE,size,copymsg);
-}
-
-//send msgs to other ranks except the rank specified in the argument
-//if rank==-1, then it means the msg should be sent to all cores on the node
-static void CmiSendChildrenPeers(int rank, int size, char *msg) {
-    //printf ("%d [%d]: Send children peers except rank %d\n",  CmiMyPe(), CmiMyNode(), CmiMyRank());
-    int r=0;
-
-//With comm thd, broadcast msg will be pulled from bcast queue from the comm thd
-//And the msg would be finally pushed into other cores on the same node by the
-//comm thd. But it's possible a msg has already been pushed into rank 0 in
-//recv_done func call. So there's no need to push the bcast msg into the recv
-//queue again in the case BCASTMSG_ONLY_TO_COMMTHD is not set
-
-    for (;r<rank; r++) {
-        char *copymsg;
-        copymsg = (char *)CmiAlloc(size);
-        CmiMemcpy(copymsg,msg,size);        
-        CmiPushPE (r, copymsg);
-    }
-
-    for (r=rank+1; r<_Cmi_mynodesize; r++) {
-        char *copymsg;
-        copymsg = (char *)CmiAlloc(size);
-        CmiMemcpy(copymsg,msg,size);        
-        CmiPushPE (r, copymsg);
-    }
-}
-
-//In this implementation, msgs are first sent out to the comm thd or rank 0 of other nodes
-//then send msgs to the other cores on the same node
-//Routine is responsible to send outgoing inter-node msgs
-void SendSpanningChildren(int size, char *msg) {
-    CmiState cs = CmiGetState();
-    int startpe = CMI_BROADCAST_ROOT(msg)-1;
-    int i;
-
-    //printf ("%d [%d]: In Send Spanning Tree with startpe %d\n",  CmiMyPe(), CmiMyNode(), startpe);
-
-    CmiAssert(startpe>=0 && startpe<_Cmi_numpes);
-
-    int startNid = CmiNodeOf(startpe);
-    int thisNid;
-    thisNid = CmiMyNode();
-
-    //printf ("%d [%d/%d]: In Send Spanning Tree with startpe %d\n",  CmiMyPe(), CmiMyNode(), CmiMyRank(), startpe);
-    //send to other nodes
-    int dist = thisNid - startNid;
-    if (dist<0) dist += _Cmi_numnodes;
-    for (i=1; i <= BROADCAST_SPANNING_FACTOR; i++) {
-        int nid = BROADCAST_SPANNING_FACTOR*dist + i;
-        if (nid > _Cmi_numnodes - 1) break;
-        nid += startNid;
-        nid = nid%_Cmi_numnodes;
-        CmiAssert(nid>=0 && nid<_Cmi_numnodes && nid!=thisNid);
-        int p = CmiNodeFirst(nid);
-        //printf ("%d [%d]: Sending Spanning Tree Msg to %d\n",  CmiMyPe(), CmiMyNode(), p);
-        CmiSyncSendFn1(p, size, msg);
-    }
-
-#if !CMK_SMP
-#if ENABLE_BROADCAST_THROTTLE
-    SendMsgsUntil (0);
-#endif
-#endif
-}
-
-/* send msg along the hypercube in broadcast. (Sameer) */
-void SendHypercube(int size, char *msg) {
-    CmiState cs = CmiGetState();
-    int curcycle = CMI_GET_CYCLE(msg);
-    int i;
-
-    double logp = CmiNumPes();
-    logp = log(logp)/log(2.0);
-    logp = ceil(logp);
-
-    /*  CmiPrintf("In hypercube\n"); */
-    /* assert(startpe>=0 && startpe<_Cmi_numpes); */
+extern void        bgl_machine_RectBcastInit  (unsigned               commID,
+        const BGTsRC_Geometry_t* geometry) {
 
-    for (i = curcycle; i < logp; i++) {
-        int p = cs->pe ^ (1 << i);
-        /*   CmiPrintf("p = %d, logp = %5.1f\n", p, logp);*/
-        if (p < CmiNumPes()) {
-            CMI_SET_CYCLE(msg, i + 1);
+    CmiAssert (commID < 256);
+    CmiAssert (comm_table [commID] == NULL);
 
-            CmiAssert(p>=0 && p<_Cmi_numpes && p!=cs->pe);
-            CmiSyncSendFn1(p, size, msg);
-        }
-    }
-}
+    BGTsRC_t *request =  (BGTsRC_t *) malloc (sizeof (BGTsRC_t));
+    comm_table [commID] = request;
 
-void CmiSyncBroadcastFn(int size, char *msg) {
-    char *copymsg;
-    copymsg = (char *)CmiAlloc(size);
-    CmiMemcpy(copymsg,msg,size);
-    CmiFreeBroadcastFn(size,copymsg);
+    BGTsRC_AsyncBcast_init  (request, commID,  geometry);
 }
 
-void CmiFreeBroadcastFn(int size, char *msg) {
-    //printf("%d: Calling Broadcast %d\n", CmiMyPe(), size);
-    CmiState cs = CmiGetState();
-#if CMK_BROADCAST_SPANNING_TREE    
-    CQdCreate(CpvAccess(cQdState), CmiNumPes()-1);
-    CMI_SET_BROADCAST_ROOT(msg, cs->pe+1);
-    SendSpanningChildren(size, msg);
-    CmiSendChildrenPeers(CmiMyRank(), size, msg);
-#elif CMK_BROADCAST_HYPERCUBE    
-    CQdCreate(CpvAccess(cQdState), CmiNumPes()-1);
-    CMI_SET_CYCLE(msg, 0);
-    SendHypercube(size, msg);
-    CmiSendChildrenPeers(CmiMyRank(), size, msg);
-#else
-    int i;
-    for ( i=cs->pe+1; i<_Cmi_numpes; i++ )
-        CmiSyncSendFn(i,size,msg);
-    for ( i=0; i<cs->pe; i++ )
-        CmiSyncSendFn(i,size,msg);
+/*--------------------------------------------------------------
+ *----- End Rectangular Broadcast Implementation ---------------
+ *--------------------------------------------------------------*/
 #endif
-    CmiFree(msg);
-}
 
-void CmiSyncBroadcastAllFn(int size, char *msg) {
-    char *copymsg;
-    copymsg = (char *)CmiAlloc(size);
-    CmiMemcpy(copymsg,msg,size);
-    CmiState cs = CmiGetState();
-    CmiSyncSendFn(cs->pe,size,copymsg);
-    CmiFreeBroadcastFn(size, copymsg);
-}
 
-void CmiFreeBroadcastAllFn(int size, char *msg) {
-    CmiState cs = CmiGetState();
-    CmiSyncSendFn(cs->pe,size,msg);
-    CmiFreeBroadcastFn(size, msg);
-}
+/*######End of functions related with Communication-Op functions ######*/
 
-void AdvanceCommunications() {
 
+/* ######Beginning of functions related with communication progress ###### */
+static INLINE_KEYWORD void AdvanceCommunicationForDCMF() {
 #if CMK_SMP
     DCMF_CriticalSection_enter (0);
 #endif
 
-    while(DCMF_Messager_advance()>0);
+    while (DCMF_Messager_advance()>0);
     //DCMF_Messager_advance();
 
 #if CMK_SMP
     DCMF_CriticalSection_exit (0);
 #endif
-
-    sendBroadcastMessages();
-#if CMK_NODE_QUEUE_AVAILABLE
-    sendBroadcastMessagesNode();
-#endif
-
-#if CMK_IMMEDIATE_MSG && !CMK_SMP
-    CmiHandleImmediate();
-#endif
 }
+/* ######End of functions related with communication progress ###### */
 
-
-static void SendMsgsUntil(int targetm) {
-
-    while (msgQueueLen>targetm) {
-      //AdvanceCommunications ();
-#if CMK_SMP
-      DCMF_CriticalSection_enter (0);
-#endif
-      
-      while(DCMF_Messager_advance()>0);
-      //DCMF_Messager_advance();
-      
-#if CMK_SMP
-      DCMF_CriticalSection_exit (0);
+/* Network progress function is used to poll the network when for
+   messages. This flushes receive buffers on some  implementations*/
+#if CMK_MACHINE_PROGRESS_DEFINED
+void CmiMachineProgressImpl() {
+    AdvanceCommunicationForDCMF();
+#if CMK_IMMEDIATE_MSG
+    CmiHandleImmediate();
 #endif
-    }
 }
-
-void CmiNotifyIdle() {
-#if !CMK_SMP || CMK_MULTICORE
-    AdvanceCommunications();
 #endif
-}
-
-
-/*==========================================================*/
-/*==========================================================*/
-/*==========================================================*/
-
-/************ Recommended routines ***********************/
-/************ You dont have to implement these but they are supported
- in the converse syntax and some rare programs may crash. But most
- programs dont need them. *************/
-
-CmiCommHandle CmiAsyncSendFn(int dest, int size, char *msg) {
-    CmiAbort("CmiAsyncSendFn not implemented.");
-    return (CmiCommHandle) 0;
-}
-
-CmiCommHandle CmiAsyncBroadcastFn(int size, char *msg) {
-    CmiAbort("CmiAsyncBroadcastFn not implemented.");
-    return (CmiCommHandle) 0;
-}
 
-CmiCommHandle CmiAsyncBroadcastAllFn(int size, char *msg) {
-    CmiAbort("CmiAsyncBroadcastAllFn not implemented.");
-    return (CmiCommHandle) 0;
+/* ######Beginning of functions related with exiting programs###### */
+static void DrainResourcesForDCMF() {
+    while (msgQueueLen > 0 || outstanding_recvs > 0) {
+        AdvanceCommunicationForDCMF();
+    }
 }
 
-int           CmiAsyncMsgSent(CmiCommHandle handle) {
-    CmiAbort("CmiAsyncMsgSent not implemented.");
-    return 0;
-}
-void          CmiReleaseCommHandle(CmiCommHandle handle) {
-    CmiAbort("CmiReleaseCommHandle not implemented.");
+static void MachineExitForDCMF() {
+    DCMF_Messager_finalize();
+    exit(EXIT_SUCCESS);
 }
+/* ######End of functions related with exiting programs###### */
 
 
-/*==========================================================*/
-/*==========================================================*/
-/*==========================================================*/
-
-/* Optional routines which could use common code which is shared with
-   other machine layer implementations. */
-
-/* MULTICAST/VECTOR SENDING FUNCTIONS
-
- * In relations to some flags, some other delivery functions may be needed.
+/* ######Beginning of functions related with starting programs###### */
+/**
+ *  Obtain the number of nodes, my node id, and consuming machine layer
+ *  specific arguments
  */
+static void MachineInitForDCMF(int argc, char **argv, int *numNodes, int *myNodeID) {
 
-#if ! CMK_MULTICAST_LIST_USE_COMMON_CODE
-
-void CmiSyncListSendFn(int npes, int *pes, int size, char *msg) {
-    char *copymsg;
-    copymsg = (char *)CmiAlloc(size);
-    CmiMemcpy(copymsg,msg,size);
-    CmiFreeListSendFn(npes, pes, size, msg);
-}
+    DCMF_Messager_initialize();
 
-//#define OPTIMIZED_MULTICAST  0
+#if CMK_SMP
+    DCMF_Configure_t  config_in, config_out;
+    config_in.thread_level= DCMF_THREAD_MULTIPLE;
+    config_in.interrupts  = DCMF_INTERRUPTS_OFF;
 
-void CmiFreeListSendFn(int npes, int *pes, int size, char *msg) {
-#if CMK_SMP && !CMK_MULTICORE
-    //DCMF_CriticalSection_enter (0);
+    DCMF_Messager_configure(&config_in, &config_out);
+    //assert (config_out.thread_level == DCMF_THREAD_MULTIPLE); //not supported in vn mode
 #endif
-    CMI_SET_BROADCAST_ROOT(msg,0);
-    CMI_MAGIC(msg) = CHARM_MAGIC_NUMBER;
-    ((CmiMsgHeaderBasic *)msg)->size = size;
-    CMI_SET_CHECKSUM(msg, size);
 
-    //if(CmiMyRank()==CmiMyNodeSize()) printf("CmiFreeListSendFn on comm thd on node %d\n", CmiMyNode());
+    DCMF_Send_Configuration_t short_config, eager_config, rzv_config;
 
-    //printf("%d: In Free List Send Fn\n", CmiMyPe());
-    int new_npes = 0;
 
-    int i, count = 0, my_loc = -1;
-    for (i=0; i<npes; i++) {
-        //if (pes[i] == CmiMyPe() || CmiNodeOf(pes[i]) == CmiMyNode()) {
-        if (CmiNodeOf(pes[i]) == CmiMyNode()) {
-            CmiSyncSend(pes[i], size, msg);
-            //my_loc = i;
-        }
-    }
+    short_config.protocol      = DCMF_DEFAULT_SEND_PROTOCOL;
+    short_config.cb_recv_short = short_pkt_recv;
+    short_config.cb_recv       = first_pkt_recv_done;
 
-#if OPTIMIZED_MULTICAST && CMK_SMP
-#warning "Using Optimized Multicast"
-    if (npes > 1) {    
-      int *newpelist = (int *) malloc (sizeof(int) * npes);
-      int new_npes = 0;
-    
-      for(i=0; i<npes; i++) {
-       if(CmiNodeOf(pes[i]) == CmiMyNode()) 
-         continue;
-       else
-         newpelist[new_npes++] = pes[i];
-      }
-
-      if (new_npes >= 1)
-       machineMulticast (new_npes, newpelist, size, msg);
-      else
-       CmiFree (msg);
-      return;
-    }
+#if (DCMF_VERSION_MAJOR >= 3)
+    short_config.network  = DCMF_DEFAULT_NETWORK;
+#elif (DCMF_VERSION_MAJOR == 2)
+    short_config.network  = DCMF_DefaultNetwork;
 #endif
 
-    for (i=0;i<npes;i++) {
-        //if (pes[i] == CmiMyPe() || CmiNodeOf(pes[i]) == CmiMyNode());
-        if (CmiNodeOf(pes[i]) == CmiMyNode());
-        else if (i < npes - 1) {
-#if !CMK_SMP /*|| (CMK_SMP && !CMK_MULTICORE)*/
-            CmiReference(msg);
-            CmiGeneralFreeSend(pes[i], size, msg);
+    eager_config.protocol      = DCMF_DEFAULT_SEND_PROTOCOL;
+    eager_config.cb_recv_short = short_pkt_recv;
+    eager_config.cb_recv       = first_pkt_recv_done;
+#if (DCMF_VERSION_MAJOR >= 3)
+    eager_config.network  = DCMF_DEFAULT_NETWORK;
+#elif (DCMF_VERSION_MAJOR == 2)
+    eager_config.network  = DCMF_DefaultNetwork;
+#endif
+
+#ifdef  OPT_RZV
+#warning "Enabling Optimize Rzv"
+    rzv_config.protocol        = DCMF_RZV_SEND_PROTOCOL;
 #else
-            CmiSyncSend(pes[i], size, msg);
+    rzv_config.protocol        = DCMF_DEFAULT_SEND_PROTOCOL;
+#endif
+    rzv_config.cb_recv_short   = short_pkt_recv;
+    rzv_config.cb_recv         = first_pkt_recv_done;
+#if (DCMF_VERSION_MAJOR >= 3)
+    rzv_config.network  = DCMF_DEFAULT_NETWORK;
+#elif (DCMF_VERSION_MAJOR == 2)
+    rzv_config.network  = DCMF_DefaultNetwork;
 #endif
-        }
-    }
 
-    //if (npes  && (pes[npes-1] != CmiMyPe() && CmiNodeOf(pes[i]) != CmiMyNode()))
-    if (npes  && CmiNodeOf(pes[npes-1]) != CmiMyNode())
-        CmiSyncSendAndFree(pes[npes-1], size, msg); //Sameto CmiFreeSendFn
-    else
-        CmiFree(msg);
+    DCMF_Send_register (&cmi_dcmf_short_registration, &short_config);
+    DCMF_Send_register (&cmi_dcmf_eager_registration, &eager_config);
+    DCMF_Send_register (&cmi_dcmf_rzv_registration,   &rzv_config);
 
-    //AdvanceCommunications();
-#if CMK_SMP && !CMK_MULTICORE
-    //DCMF_CriticalSection_exit (0);
+#ifdef BGP_USE_AM_DIRECT
+    DCMF_Send_Configuration_t direct_config;
+    direct_config.protocol      = DCMF_DEFAULT_SEND_PROTOCOL;
+    direct_config.cb_recv_short = direct_short_pkt_recv;
+    direct_config.cb_recv       = direct_first_pkt_recv_done;
+#if (DCMF_VERSION_MAJOR >= 3)
+    direct_config.network  = DCMF_DEFAULT_NETWORK;
+#elif (DCMF_VERSION_MAJOR == 2)
+    direct_config.network  = DCMF_DefaultNetwork;
 #endif
-}
-
-CmiCommHandle CmiAsyncListSendFn(int npes, int *pes, int size, char *msg) {
-    CmiAbort("CmiAsyncListSendFn not implemented.");
-    return (CmiCommHandle) 0;
-}
+    DCMF_Send_register (&cmi_dcmf_direct_registration,   &direct_config);
+    directcb.function=direct_send_done_cb;
+    directcb.clientdata=NULL;
 #endif
 
-/** NODE SENDING FUNCTIONS
-
- * If there is a node queue, and we consider also nodes as entity (tipically in
- * SMP versions), these functions are needed.
- */
+#ifdef BGP_USE_RDMA_DIRECT
+    /* notification protocol */
+    DCMF_Send_Configuration_t direct_rdma_config;
+    direct_rdma_config.protocol      = DCMF_DEFAULT_SEND_PROTOCOL;
+    direct_rdma_config.cb_recv_short = direct_short_rdma_pkt_recv;
+    direct_rdma_config.cb_recv       = direct_first_rdma_pkt_recv_done;
+#if (DCMF_VERSION_MAJOR >= 3)
+    direct_rdma_config.network  = DCMF_DEFAULT_NETWORK;
+#elif (DCMF_VERSION_MAJOR == 2)
+    direct_rdma_config.network  = DCMF_DefaultNetwork;
+#endif
+    DCMF_Send_register (&cmi_dcmf_direct_rdma_registration,   &direct_rdma_config);
+    directcb.function=direct_send_rdma_done_cb;
+    directcb.clientdata=NULL;
+    /* put protocol */
+    DCMF_Put_Configuration_t put_configuration = { DCMF_DEFAULT_PUT_PROTOCOL };
+    DCMF_Put_register (&cmi_dcmf_direct_put_registration, &put_configuration);
+    DCMF_Get_Configuration_t get_configuration = { DCMF_DEFAULT_GET_PROTOCOL };
+    DCMF_Get_register (&cmi_dcmf_direct_get_registration, &get_configuration);
 
-#if CMK_NODE_QUEUE_AVAILABLE
+#endif
+    //fprintf(stderr, "Initializing Eager Protocol\n");
 
-void          CmiSyncNodeSendFn(int, int, char *);
-CmiCommHandle CmiAsyncNodeSendFn(int, int, char *);
-void          CmiFreeNodeSendFn(int, int, char *);
+    *numNodes = DCMF_Messager_size();
+    *myNodeID = DCMF_Messager_rank();
 
-void          CmiSyncNodeBroadcastFn(int, char *);
-CmiCommHandle CmiAsyncNodeBroadcastFn(int, char *);
-void          CmiFreeNodeBroadcastFn(int, char *);
+    CmiBarrier();
+    CmiBarrier();
+    CmiBarrier();
 
-void          CmiSyncNodeBroadcastAllFn(int, char *);
-CmiCommHandle CmiAsyncNodeBroadcastAllFn(int, char *);
-void          CmiFreeNodeBroadcastAllFn(int, char *);
+    /* NOTE: the following codes requires #PEs, which is not available
+     * until this function finishes. And it allocate O(p) space */
+    int totalPEs = _Cmi_mynodesize * (*numNodes);
+    DCMF_Multicast_Configuration_t mconfig;
+    mconfig.protocol = DCMF_MEMFIFO_DMA_MSEND_PROTOCOL;
+    mconfig.cb_recv  = first_multi_pkt_recv_done;
+    mconfig.clientdata = NULL;
+    mconfig.connectionlist = (void **) malloc (totalPEs * sizeof(unsigned long));
+    mconfig.nconnections = totalPEs;
+    DCMF_Multicast_register(&cmi_dcmf_multicast_registration, &mconfig);
 
+    int actualNodeSize = _Cmi_mynodesize;
+#if !CMK_SMP_NO_COMMTHD
+    actualNodeSize++; //considering the extra comm thread
 #endif
 
+    procState = (ProcState *)CmiAlloc((actualNodeSize) * sizeof(ProcState));
+    for (int i=0; i<actualNodeSize; i++) {
+        /*    procState[i].sendMsgBuf = PCQueueCreate();   */
+        procState[i].recvLock = CmiCreateLock();
+        procState[i].bcastLock = CmiCreateLock();
+    }
 
-#if CMK_SHARED_VARS_POSIX_THREADS_SMP
-
-int CmiMyPe();
-int CmiMyRank();
-int CmiNodeFirst(int node);
-int CmiNodeSize(int node);
-int CmiNodeOf(int pe);
-int CmiRankOf(int pe);
-
-int CmiMyPe(void) {
-    return CmiGetState()->pe;
-}
-
-int CmiMyRank(void) {
-    return CmiGetState()->rank;
-}
+    /* checksum flag */
+    if (CmiGetArgFlag(argv,"+checksum")) {
+#if CMK_ERROR_CHECKING
+        checksum_flag = 1;
+        if (*myNodeID == 0) CmiPrintf("Charm++: CheckSum checking enabled! \n");
+#else
+        if (*myNodeID == 0) CmiPrintf("Charm++: +checksum ignored in optimized version! \n");
+#endif
+    }
 
-int CmiNodeFirst(int node) {
-    return node*_Cmi_mynodesize;
-}
-int CmiNodeSize(int node)  {
-    return _Cmi_mynodesize;
 }
 
-int CmiNodeOf(int pe)      {
-    return (pe/_Cmi_mynodesize);
-}
-int CmiRankOf(int pe)      {
-    return pe%_Cmi_mynodesize;
+static void MachinePreCommonInitForDCMF(int everReturn) {
+    CpvInitialize(PCQueue, smsg_list_q);
+    CpvAccess(smsg_list_q) = PCQueueCreate();
 }
 
-
-/* optional, these functions are implemented in "machine-smp.c", so including
-   this file avoid the necessity to reimplement them.
- */
-void CmiNodeBarrier(void);
-void CmiNodeAllBarrier(void);
-CmiNodeLock CmiCreateLock();
-void CmiDestroyLock(CmiNodeLock lock);
-
+static void MachinePostCommonInitForDCMF(int everReturn) {
+#if !CMK_SMP || CMK_SMP_NO_COMMTHD
+    CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,(CcdVoidFn)CmiNotifyIdle,NULL);
 #endif
 
-/** IMMEDIATE MESSAGES
-
- * If immediate messages are supported, the following function is needed. There
- * is an exeption if the machine progress is also defined (see later for this).
-
- * Moreover, the file "immediate.c" should be included, otherwise all its
- * functions and variables have to be redefined.
-*/
-
-#if CMK_CCS_AVAILABLE
+    CmiBarrier();
+}
+/* ######End of functions related with starting programs###### */
 
-#include "immediate.c"
+/***********************************************************************
+ *
+ * Abort function:
+ *
+ ************************************************************************/
 
-#if ! CMK_MACHINE_PROGRESS_DEFINED /* Hack for some machines */
-void CmiProbeImmediateMsg();
-#endif
+void CmiAbort(const char *message) {
+    CmiError("------------- Processor %d Exiting: Called CmiAbort ------------\n"
+             "{snd:%d,rcv:%d} Reason: %s\n",CmiMyPe(),
+             msgQueueLen, outstanding_recvs, message);
 
+#if 0
+    /* Since it's a abort, why bother to drain the resources? The system
+     * should clean it self
+     */
+    /* FIXME: what happens in the SMP mode??? */
+    DrainResourcesForDCMF();
 #endif
+    assert(0);
+}
 
 
-/** MACHINE PROGRESS DEFINED
+/*********** Beginning of MULTICAST/VECTOR SENDING FUNCTIONS **************/
+/*
 
- * Some machines (like BlueGene/L) do not have coprocessors, and messages need
- * to be pulled out of the network manually. For this reason the following
- * functions are needed. Notice that the function "CmiProbeImmediateMsg" must
- * not be defined anymore.
+ * In relations to some flags, some other delivery functions may be needed.
  */
 
-#if CMK_MACHINE_PROGRESS_DEFINED
-
+#if !CMK_MULTICAST_LIST_USE_COMMON_CODE
 
+void CmiSyncListSendFn(int npes, int *pes, int size, char *msg) {
+    char *copymsg = CopyMsg(msg, size);
+    CmiFreeListSendFn(npes, pes, size, copymsg);
+}
 
-void CmiMachineProgressImpl() {
-
+/* Currently disable optimized multicast for non-SMP as it fails
+ * for hybrid ldb in NAMD as reported by Gengbin --Chao Mei
+ */
 #if !CMK_SMP
-    AdvanceCommunications();
+#define OPTIMIZED_MULTICAST  0
 #else
-    /*Not implemented yet. Communication server does not seem to be
-      thread safe */
+#define OPTIMIZED_MULTICAST  1
 #endif
-}
 
+#if OPTIMIZED_MULTICAST
+#warning "Using Optimized Multicast"
 #endif
 
-/* Dummy implementation */
-extern int CmiBarrier() {
-    //Use DCMF barrier later
-}
-
-#if CMK_NODE_QUEUE_AVAILABLE
-static void CmiSendNodeSelf(char *msg) {
-#if CMK_IMMEDIATE_MSG
-    if (CmiIsImmediate(msg)) {
-        //printf("SendNodeSelf: N[%d]P[%d]R[%d] received an imm msg with hdl: %p\n", CmiMyNode(), CmiMyPe(), CmiMyRank(), CmiGetHandler(msg));
-        CmiPushImmediateMsg(msg);
-#if CMK_MULTICORE
-        CmiHandleImmediate();
-#endif
+void CmiFreeListSendFn(int npes, int *pes, int size, char *msg) {
+    CmiAssert(npes>=1);
+    if (npes==1) {
+        CmiFreeSendFn(pes[0], size, msg);
         return;
     }
-#endif    
-    CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
-    PCQueuePush(CsvAccess(NodeState).NodeRecv, msg);
-    CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
-}
 
-CmiCommHandle CmiAsyncNodeSendFn(int dstNode, int size, char *msg) {
-    CmiAbort ("Async Node Send not supported\n");
-}
+    //if(CmiMyRank()==CmiMyNodeSize()) printf("CmiFreeListSendFn on comm thd on node %d\n", CmiMyNode());
+    //printf("%d: In Free List Send Fn\n", CmiMyPe());
 
-void CmiFreeNodeSendFn(int node, int size, char *msg) {
+    int i;
+#if OPTIMIZED_MULTICAST
+    int *newpelist = pes;
+    int new_npes = npes;
+#if CMK_SMP
+    newpelist = (int *)malloc(sizeof(int)*npes);
+    new_npes = 0;
+    for (i=0; i<npes; i++) {
+        if (CmiNodeOf(pes[i]) == CmiMyNode()) {
+            CmiSyncSend(pes[i], size, msg);
+        } else {
+            newpelist[new_npes++] = pes[i];
+        }
+    }
+    if (new_npes == 0) {
+        CmiFree(msg);
+        return;
+    }
+#endif
 
     CMI_SET_BROADCAST_ROOT(msg,0);
+    CMI_MSG_SIZE(msg) = size;
+#if CMK_ERROR_CHECKING
     CMI_MAGIC(msg) = CHARM_MAGIC_NUMBER;
-    ((CmiMsgHeaderBasic *)msg)->size = size;
     CMI_SET_CHECKSUM(msg, size);
-    //if(CmiMyRank()==CmiMyNodeSize()) printf("CmiFreeNodeSendFn on comm thd on node %d\n", CmiMyNode());
-    
-    CQdCreate(CpvAccess(cQdState), 1);
-
-    if (node == _Cmi_mynode) {
-        CmiSendNodeSelf(msg);
-    } else {
-        CmiGeneralFreeSendN(node, SMP_NODEMESSAGE, size, msg);
-    }
-}
-
-void CmiSyncNodeSendFn(int p, int s, char *m) {
-    char *dupmsg;
-    dupmsg = (char *)CmiAlloc(s);
-    CmiMemcpy(dupmsg,m,s);
-    //if(CmiMyRank()==CmiMyNodeSize()) printf("CmiSyncNodeSendFn on comm thd on node %d\n", CmiMyNode());
-    CmiFreeNodeSendFn(p, s, dupmsg);
-}
-
-CmiCommHandle CmiAsyncNodeBroadcastFn(int s, char *m) {
-    return NULL;
-}
-
-void SendSpanningChildrenNode(int size, char *msg) {
-    int startnode = -CMI_BROADCAST_ROOT(msg)-1;
-    //printf("on node %d rank %d, send node spanning children with root %d\n", CmiMyNode(), CmiMyRank(), startnode);
-    assert(startnode>=0 && startnode<CmiNumNodes());
+#endif
 
-    int dist = CmiMyNode()-startnode;
-    if (dist<0) dist += CmiNumNodes();
-    int i;
-    for (i=1; i <= BROADCAST_SPANNING_FACTOR; i++) {
-        int nid = BROADCAST_SPANNING_FACTOR*dist + i;
-        if (nid > CmiNumNodes() - 1) break;
-        nid += startnode;
-        nid = nid%CmiNumNodes();
-        assert(nid>=0 && nid<CmiNumNodes() && nid!=CmiMyNode());
-        char *dupmsg = (char *)CmiAlloc(size);
-        CmiMemcpy(dupmsg,msg,size);
-        //printf("In SendSpanningChildrenNode, sending bcast msg (root %d) from node %d to node %d\n", startnode, CmiMyNode(), nid);
-        CmiGeneralFreeSendN(nid, SMP_NODEMESSAGE, size, dupmsg);
-    }
-}
+    CQdCreate(CpvAccess(cQdState), new_npes);
+    machineMulticast (new_npes, newpelist, size, msg);
+#else /* non-optimized multicast */
 
-/* need */
-void CmiFreeNodeBroadcastFn(int s, char *m) {
-#if CMK_BROADCAST_SPANNING_TREE
-    //if(CmiMyRank()==CmiMyNodeSize()) printf("CmiFreeNodeBcastFn on comm thd on node %d\n", CmiMyNode());
-    
-    CQdCreate(CpvAccess(cQdState), CmiNumNodes()-1);
-
-    int mynode = CmiMyNode();
-    CMI_SET_BROADCAST_ROOT(m, -mynode-1);
-    CMI_MAGIC(m) = CHARM_MAGIC_NUMBER;
-    ((CmiMsgHeaderBasic *)m)->size = s;
-    CMI_SET_CHECKSUM(m, s);
-    //printf("In CmiFreeNodeBroadcastFn, sending bcast msg from root node %d\n", CMI_BROADCAST_ROOT(m));
-
-    SendSpanningChildrenNode(s, m);
+    for (i=0; i<npes-1; i++) {
+#if !CMK_SMP
+        CmiReference(msg);
+        CmiFreeSendFn(pes[i], size, msg);
 #else
-    int i;
-    for (i=0; i<CmiNumNodes(); i++) {
-        if (i==CmiMyNode()) continue;
-        char *dupmsg = (char *)CmiAlloc(s);
-        CmiMemcpy(dupmsg,m,s);
-        CmiFreeNodeSendFn(i, s, dupmsg);
-    }
+    CmiSyncSend(pes[i], size, msg);
 #endif
-    CmiFree(m);    
-}
-
-void CmiSyncNodeBroadcastFn(int s, char *m) {
-    char *dupmsg;
-    dupmsg = (char *)CmiAlloc(s);
-    CmiMemcpy(dupmsg,m,s);
-    //if(CmiMyRank()==CmiMyNodeSize()) printf("CmiSyncNodeBcastFn on comm thd on node %d\n", CmiMyNode());
-    CmiFreeNodeBroadcastFn(s, dupmsg);
+    }
+    CmiFreeSendFn(pes[npes-1], size, msg);
+#endif /* end of #if OPTIMIZED_MULTICAST */
 }
+#endif /* end of #if !CMK_MULTICAST_LIST_USE_COMMON_CODE */
 
-/* need */
-void CmiFreeNodeBroadcastAllFn(int s, char *m) {
-    char *dupmsg = (char *)CmiAlloc(s);
-    CmiMemcpy(dupmsg,m,s);
-    CMI_MAGIC(dupmsg) = CHARM_MAGIC_NUMBER;
-    ((CmiMsgHeaderBasic *)dupmsg)->size = s;
-    CMI_SET_CHECKSUM(dupmsg, s);
-
-    //if(CmiMyRank()==CmiMyNodeSize()) printf("CmiFreeNodeBcastAllFn on comm thd on node %d\n", CmiMyNode());
-    
-    CQdCreate(CpvAccess(cQdState), 1);
-    CmiSendNodeSelf(dupmsg);
-
-    CmiFreeNodeBroadcastFn(s, m);
-}
+/*********** End of MULTICAST/VECTOR SENDING FUNCTIONS **************/
 
-void CmiSyncNodeBroadcastAllFn(int s, char *m) {
-    char *dupmsg;
-    dupmsg = (char *)CmiAlloc(s);
-    CmiMemcpy(dupmsg,m,s);
-    //if(CmiMyRank()==CmiMyNodeSize()) printf("CmiSyncNodeBcastAllFn on comm thd on node %d\n", CmiMyNode());
-    CmiFreeNodeBroadcastAllFn(s, dupmsg);
-}
+/**************************  TIMER FUNCTIONS **************************/
 
+/************Barrier Related Functions****************/
 
-CmiCommHandle CmiAsyncNodeBroadcastAllFn(int s, char *m) {
-    return NULL;
-}
-#endif //end of CMK_NODE_QUEUE_AVAILABLE
 
 #include "manytomany.c"
 
-
 /*********************************************************************************************
 This section is for CmiDirect. This is a variant of the  persistent communication in which
 the user can transfer data between processors without using Charm++ messages. This lets the user
@@ -1905,8 +980,6 @@ side
 *********************************************************************************************/
 
 
-
-
 #ifdef BGP_USE_AM_DIRECT
 
 #include "cmidirect.h"
@@ -2011,8 +1084,7 @@ void CmiDirect_get(struct infiDirectUserHandle *userHandle) {
 }
 
 /**** up to the user to safely call this */
-void CmiDirect_deassocLocalBuffer(struct infiDirectUserHandle *userHandle)
-{
+void CmiDirect_deassocLocalBuffer(struct infiDirectUserHandle *userHandle) {
     CmiAssert(userHandle->senderNode==_Cmi_mynode);
 #if CMK_SMP
     DCMF_CriticalSection_enter (0);
@@ -2025,7 +1097,7 @@ void CmiDirect_deassocLocalBuffer(struct infiDirectUserHandle *userHandle)
 }
 
 /**** up to the user to safely call this */
-void CmiDirect_destroyHandle(struct infiDirectUserHandle *userHandle){
+void CmiDirect_destroyHandle(struct infiDirectUserHandle *userHandle) {
     CmiAssert(userHandle->recverNode==_Cmi_mynode);
 #if CMK_SMP
     DCMF_CriticalSection_enter (0);
@@ -2059,7 +1131,7 @@ void CmiDirect_readyMark(struct infiDirectUserHandle *userHandle) {
 
 #include "cmidirect.h"
 
-/* 
+/*
    Notification protocol passes callback function and data in a single
    quadword.  This occurs in a message triggered by the sender side ack
    callback and therefore has higher latency than polling, but is guaranteed
@@ -2079,8 +1151,7 @@ void CmiDirect_readyMark(struct infiDirectUserHandle *userHandle) {
 
 
 /* local function to use the ack as our signal to send a remote notify */
-static void CmiNotifyRemoteRDMA(void *handle, struct DCMF_Error_t *error)
-{
+static void CmiNotifyRemoteRDMA(void *handle, struct DCMF_Error_t *error) {
     struct infiDirectUserHandle *userHandle= (struct infiDirectUserHandle *) handle;
     dcmfDirectRDMAMsgHeader msgHead;
     msgHead.callbackFnPtr=userHandle->callbackFnPtr;
@@ -2092,16 +1163,16 @@ static void CmiNotifyRemoteRDMA(void *handle, struct DCMF_Error_t *error)
     CmiPrintf("[%d] RDMA notify put addr %p %d to recverNode %d receiver addr %p callback %p callbackdata %p \n",CmiMyPe(),userHandle->senderBuf,userHandle->recverBufSize, userHandle->recverNode,userHandle->recverBuf, userHandle->callbackFnPtr, userHandle->callbackData);
 #endif
     DCMF_Result res=DCMF_Send (&cmi_dcmf_direct_rdma_registration,
-              userHandle->DCMF_rq_tsend,
-              directcb, DCMF_MATCH_CONSISTENCY, userHandle->recverNode,
-              sizeof(dcmfDirectRDMAMsgHeader), 
+                               userHandle->DCMF_rq_tsend,
+                               directcb, DCMF_MATCH_CONSISTENCY, userHandle->recverNode,
+                               sizeof(dcmfDirectRDMAMsgHeader),
 
-                              userHandle->DCMF_notify_buf,
-              (struct DCQuad *) &(msgHead), 1);
+                               userHandle->DCMF_notify_buf,
+                               (struct DCQuad *) &(msgHead), 1);
 //    CmiAssert(res==DCMF_SUCCESS);
 #if CMK_SMP
     DCMF_CriticalSection_exit (0);
-#endif    
+#endif
 }
 
 /**
@@ -2114,13 +1185,13 @@ struct infiDirectUserHandle CmiDirect_createHandle(int senderNode,void *recvBuf,
     struct infiDirectUserHandle userHandle;
     size_t numbytesRegistered=0;
     DCMF_Result regresult=DCMF_Memregion_create( &userHandle.DCMF_recverMemregion,
-                                                &numbytesRegistered,
-                                                recvBufSize,
-                                                recvBuf,
-                                                0);
+                          &numbytesRegistered,
+                          recvBufSize,
+                          recvBuf,
+                          0);
     CmiAssert(numbytesRegistered==recvBufSize);
     CmiAssert(regresult==DCMF_SUCCESS);
-    
+
 
     userHandle.handle=1; /* doesn't matter on BG/P*/
     userHandle.senderNode=senderNode;
@@ -2148,13 +1219,13 @@ void CmiDirect_assocLocalBuffer(struct infiDirectUserHandle *userHandle,void *se
     userHandle->DCMF_rq_tsend =(DCMF_Request_t *) ALIGN_16(CmiAlloc(sizeof(DCMF_Request_t)+16));
     size_t numbytesRegistered=0;  // set as return value from create
     userHandle->DCMF_notify_buf=ALIGN_16(CmiAlloc(sizeof(DCMF_Request_t)+32));
-    userHandle->DCMF_notify_cb.function=CmiNotifyRemoteRDMA; 
+    userHandle->DCMF_notify_cb.function=CmiNotifyRemoteRDMA;
     userHandle->DCMF_notify_cb.clientdata=userHandle;
     DCMF_Result regresult=DCMF_Memregion_create( &userHandle->DCMF_senderMemregion,
-                                                &numbytesRegistered,
-                                                sendBufSize,
-                                                sendBuf,
-                                                0);
+                          &numbytesRegistered,
+                          sendBufSize,
+                          sendBuf,
+                          0);
     CmiAssert(numbytesRegistered==sendBufSize);
     CmiAssert(regresult==DCMF_SUCCESS);
 
@@ -2188,19 +1259,19 @@ void CmiDirect_put(struct infiDirectUserHandle *userHandle) {
 #if CMI_DIRECT_DEBUG
         CmiPrintf("[%d] RDMA put addr %p %d to recverNode %d receiver addr %p callback %p callbackdata %p\n",CmiMyPe(),userHandle->senderBuf,userHandle->recverBufSize, userHandle->recverNode,userHandle->recverBuf, userHandle->callbackFnPtr, userHandle->callbackData);
 #endif
-       DCMF_Result 
-           Res= DCMF_Put(&cmi_dcmf_direct_put_registration,
-                         userHandle->DCMF_rq_tsend,
-                         directcb, DCMF_RELAXED_CONSISTENCY, 
-                         userHandle->recverNode,
-                         userHandle->recverBufSize,
-                         &userHandle->DCMF_senderMemregion,
-                         &userHandle->DCMF_recverMemregion,
-                         0, /* offsets are zero */
-                         0, 
-                         userHandle->DCMF_notify_cb
-                         );
-       CmiAssert(Res==DCMF_SUCCESS); 
+        DCMF_Result
+        Res= DCMF_Put(&cmi_dcmf_direct_put_registration,
+                      userHandle->DCMF_rq_tsend,
+                      directcb, DCMF_RELAXED_CONSISTENCY,
+                      userHandle->recverNode,
+                      userHandle->recverBufSize,
+                      &userHandle->DCMF_senderMemregion,
+                      &userHandle->DCMF_recverMemregion,
+                      0, /* offsets are zero */
+                      0,
+                      userHandle->DCMF_notify_cb
+                     );
+        CmiAssert(Res==DCMF_SUCCESS);
 #if CMK_SMP
         DCMF_CriticalSection_exit (0);
 #endif
@@ -2225,26 +1296,26 @@ void CmiDirect_get(struct infiDirectUserHandle *userHandle) {
         (*(userHandle->callbackFnPtr))(userHandle->callbackData);
     } else {
         struct DCMF_Callback_t done_cb;
-       done_cb.function=userHandle->callbackFnPtr;
-       done_cb.clientdata=userHandle->callbackData;
+        done_cb.function=userHandle->callbackFnPtr;
+        done_cb.clientdata=userHandle->callbackData;
 #if CMK_SMP
         DCMF_CriticalSection_enter (0);
 #endif
 #if CMI_DIRECT_DEBUG
         CmiPrintf("[%d] RDMA get addr %p %d to recverNode %d receiver addr %p callback %p callbackdata %p\n",CmiMyPe(),userHandle->senderBuf,userHandle->recverBufSize, userHandle->recverNode,userHandle->recverBuf, userHandle->callbackFnPtr, userHandle->callbackData);
 #endif
-       DCMF_Result 
-           Res= DCMF_Get(&cmi_dcmf_direct_get_registration,
-                         (DCMF_Request_t *) userHandle->DCMF_rq_tsend,
-                         done_cb, DCMF_RELAXED_CONSISTENCY, 
-                         userHandle->recverNode,
-                         userHandle->recverBufSize,
-                         & userHandle->DCMF_recverMemregion,
-                         & userHandle->DCMF_senderMemregion,
-                         0, /* offsets are zero */
-                         0
-                         );
-       CmiAssert(Res==DCMF_SUCCESS); 
+        DCMF_Result
+        Res= DCMF_Get(&cmi_dcmf_direct_get_registration,
+                      (DCMF_Request_t *) userHandle->DCMF_rq_tsend,
+                      done_cb, DCMF_RELAXED_CONSISTENCY,
+                      userHandle->recverNode,
+                      userHandle->recverBufSize,
+                      & userHandle->DCMF_recverMemregion,
+                      & userHandle->DCMF_senderMemregion,
+                      0, /* offsets are zero */
+                      0
+                     );
+        CmiAssert(Res==DCMF_SUCCESS);
 
 
 #if CMK_SMP
@@ -2254,8 +1325,7 @@ void CmiDirect_get(struct infiDirectUserHandle *userHandle) {
 }
 
 /**** up to the user to safely call this */
-void CmiDirect_deassocLocalBuffer(struct infiDirectUserHandle *userHandle)
-{
+void CmiDirect_deassocLocalBuffer(struct infiDirectUserHandle *userHandle) {
     CmiAssert(userHandle->senderNode==_Cmi_mynode);
 #if CMK_SMP
     DCMF_CriticalSection_enter (0);
@@ -2271,7 +1341,7 @@ void CmiDirect_deassocLocalBuffer(struct infiDirectUserHandle *userHandle)
 }
 
 /**** up to the user to safely call this */
-void CmiDirect_destroyHandle(struct infiDirectUserHandle *userHandle){
+void CmiDirect_destroyHandle(struct infiDirectUserHandle *userHandle) {
     CmiAssert(userHandle->recverNode==_Cmi_mynode);
 #if CMK_SMP
     DCMF_CriticalSection_enter (0);
@@ -2304,3 +1374,5 @@ void CmiDirect_readyMark(struct infiDirectUserHandle *userHandle) {
 
 #endif /* BGP_USE_RDMA_DIRECT*/
 
+/*@}*/
+
index 868e17af0d4d485ed6dcecb1e9991bf72a0e4e3f..ee2f8baf0daa9551db42e9874241950834e7d9e2 100755 (executable)
@@ -4,57 +4,62 @@ Based on the template machine layer
 
 Developed by
 Filippo Gioachin   03/23/05
-Chao Mei 01/28/2010
+Chao Mei 01/28/2010, 05/07/2011
 ************************************************************************/
 
-#include <lapi.h>
-
-#include "converse.h"
+/** @file
+ * LAPI based machine layer
+ * @ingroup Machine
+ */
+/*@{*/
 
-#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <errno.h>
+#include <assert.h>
+
+#include <lapi.h>
+#include "converse.h"
 
 /*Support for ++debug: */
 #include <unistd.h> /*For getpid()*/
 #include <stdlib.h> /*For sleep()*/
 
-#include "machine.h"
-
 /* Read the following carefully before building the machine layer on LAPI */
 /* =========BEGIN OF EXPLANATION OF MACRO USAGE=============*/
 /**
- * 1. non-SMP mode: 
- *   CMK_SMP = 0; 
- *   CMK_PCQUEUE_LOCK = 1; (could be removed if memory fence and atomic ops are used) 
- *  
- *   (The following two could be disabled to reduce the overhead of machine layer) 
- *     ENSURE_MSG_PAIRORDER = 0|1; 
- *     ENABLE_CONVERSE_QD = 0|1; 
- *  
- *   (If ENSURE_MSG_PAIRORDER is 1, then setting DECOUPLE_BCAST_PROCESS to 1
+ * 1. non-SMP mode:
+ *   CMK_SMP = 0;
+ *   CMK_PCQUEUE_LOCK = 1; (could be removed if memory fence and atomic ops are used)
+ *
+ *   (The following two could be disabled to reduce the overhead of machine layer)
+ *     ENSURE_MSG_PAIRORDER = 0|1;
+ *     ENABLE_CONVERSE_QD = 0|1;
+ *
+ *   (If ENSURE_MSG_PAIRORDER is 1, then setting CMK_OFFLOAD_BCAST_PROCESS to 1
  *   will make the msg seqno increase at step of 1 w/o data race;
- *     DECOUPLE_BCAST_PROCESS = 0|1;
- * =========================================================== 
+ *     CMK_OFFLOAD_BCAST_PROCESS = 0|1;
+ * ===========================================================
  * 2. SMP mode without comm thd:
  *    CMK_SMP = 1;
  *    CMK_PCQUEUE_LOCK = 1;
  *    CMK_SMP_NO_COMMTHD = 1;
- *  
+ *
  *    ENSURE_MSG_PAIRORDER and ENABLE_CONVERSE_QD have same options as in non-SMP mode;
- *  
- *    DECOUPLE_BCAST_PROCESS has same options as in non-SMP mode;
- * =========================================================== 
+ *
+ *    CMK_OFFLOAD_BCAST_PROCESS has same options as in non-SMP mode;
+ * ===========================================================
  *  3. SMP mode with comm thd:
  *     CMK_SMP = 1;
  *     CMK_PCQUEUE_LOCK = 1;
  *     CMK_SMP_NO_COMMTHD = 0;
- *  
+ *
  *     ENSURE_MSG_PAIRORDER and ENABLE_CONVERSE_QD have same options as in non-SMP mode;
- *  
+ *
  *     (The following must be set with 1 as bcast msg is dealt with in comm thd!)
- *     DECOUPLE_BCAST_PROCESS = 1;
+ *     CMK_OFFLOAD_BCAST_PROCESS = 1;
  *  ===========================================================
- *  
+ *
  *  Assumptions we made in different mode:
  *  1. non-SMP:
  *     a) imm msgs are processed when the proc is idle, and periodically. They should
@@ -64,21 +69,23 @@ Chao Mei 01/28/2010
  *  2. SMP w/o comm thd:
  *     a) same with non-SMP a)
  *     b) forwarding bcast msgs could be done on proc whose rank=0;
- *        (enable DECOUPLE_BCAST_PROCESS)  or in internal LAPI completion
+ *        (enable CMK_OFFLOAD_BCAST_PROCESS)  or in internal LAPI completion
  *        handler threads;
  *     c) the destination rank of proc-level bcast msg is always 0;
  *  3. SMP w/ comm thd:
  *     a) imm msgs are processed in comm thd;
  *     b) forwarding bcast msgs is done in comm thd;
  *     c) same with 2 c)
- *  
+ *
  */
 /* =========END OF EXPLANATION OF MACRO USAGE=============*/
 
+#include "machine.h"
+
 #if CMK_SMP
 #define CMK_PCQUEUE_LOCK 1
 #else
-/** 
+/**
  *  In non-smp case: the LAPI completion handler thread will
  *  also access the proc's recv queue (a PCQueue), so the queue
  *  needs to be protected. The number of producers equals the
@@ -96,15 +103,15 @@ Chao Mei 01/28/2010
 #undef CmiTryLock
 #undef CmiDestroyLock
 typedef pthread_mutex_t *CmiNodeLock_nonsmp;
-CmiNodeLock CmiCreateLock(){
-  CmiNodeLock lk = (CmiNodeLock)malloc(sizeof(pthread_mutex_t));  
-  pthread_mutex_init(lk,(pthread_mutexattr_t *)0);
-  return lk;
+CmiNodeLock CmiCreateLock() {
+    CmiNodeLock lk = (CmiNodeLock)malloc(sizeof(pthread_mutex_t));
+    pthread_mutex_init(lk,(pthread_mutexattr_t *)0);
+    return lk;
 }
 #define CmiLock(lock) (pthread_mutex_lock(lock))
 #define CmiUnlock(lock) (pthread_mutex_unlock(lock))
 #define CmiTryLock(lock) (pthread_mutex_trylock(lock))
-void CmiDestroyLock(CmiNodeLock lock){
+void CmiDestroyLock(CmiNodeLock lock) {
     pthread_mutex_destroy(lock);
     free(lock);
 }
@@ -112,64 +119,34 @@ void CmiDestroyLock(CmiNodeLock lock){
 #endif
 #include "pcqueue.h"
 
-/** 
- *  The converse qd is rarely used in current charm apps, so the
- *  counter for converse qd could be disabled for max
- *  performance. --Chao Mei
- */
-#define ENABLE_CONVERSE_QD 1
-
-#if CMK_SMP
-/** 
- *  The macro defines whether to have a comm thd to offload some
- *  work such as processing immdiate messages, forwarding
- *  broadcast messages etc. This macro should be defined before
- *  including "machine-smp.c".
- *  --Chao Mei
- */
-#define CMK_SMP_NO_COMMTHD 0
-#if CMK_SMP_NO_COMMTHD
-int Cmi_commthread = 0;
-#else
-int Cmi_commthread = 1;
-#endif
-
-#endif
-
-/** 
- *  Enable this macro will offload the broadcast relay from the
- *  internal completion handler thread. This will make the msg
- *  seqno free of data-race. In SMP mode with comm thread where
- *  comm thread will forward bcast msgs, this macro should be
- *  enabled.
- */
-#define DECOUPLE_BCAST_PROCESS 1
-
-/** 
- * #####REGARDING IN-ORDER MESSAGE DELIVERY BETWEEN A PAIR OF 
- * PROCESSORS#####: 
- *  
- * Since the lapi doesn't guarantee the order of msg delivery 
- * (via network) between a pair of processors, we need to ensure 
- * this order via msg seq no and a window sliding based msg 
- * receiving scheme. So two extra fields are added to the basic 
- * msg header: srcPe and seqno. For node messages, we process it 
- * like a msg to be delivered to the first proc (rank=0) of that 
- * node. 
- *  
+/* =======Beginning of Definitions of Performance-Specific Macros =======*/
+/**
+ * #####REGARDING IN-ORDER MESSAGE DELIVERY BETWEEN A PAIR OF
+ * PROCESSORS#####:
+ *
+ * Since the lapi doesn't guarantee the order of msg delivery
+ * (via network) between a pair of processors, we need to ensure
+ * this order via msg seq no and a window sliding based msg
+ * receiving scheme. So two extra fields are added to the basic
+ * msg header: srcPe and seqno. For node messages, we process it
+ * like a msg to be delivered to the first proc (rank=0) of that
+ * node.
+ *
  * BTW: The in-order delivery between two processors in the same
- * node is guaranteed in the SMP mode as the msg transfer 
- * doesn't go through LAPI. 
- *  
- * The msg transferred through LAPI (via network) is always 
- * delivered to the first proc (whose rank is 0) on that node! 
- *  
- * --Chao Mei 
+ * node is guaranteed in the SMP mode as the msg transfer
+ * doesn't go through LAPI.
+ *
+ * The msg transferred through LAPI (via network) is always
+ * delivered to the first proc (whose rank is 0) on that node!
+ *
+ * --Chao Mei
  */
-#define ENSURE_MSG_PAIRORDER 1
+#define ENSURE_MSG_PAIRORDER 0
 
 #if ENSURE_MSG_PAIRORDER
 
+/* NOTE: this feature requires O(P) space on every proc to be functional */
+
 #define MAX_MSG_SEQNO 65535
 /* MAX_WINDOW_SIZE should be smaller than MAX_MSG_SEQNO, and MAX(unsigned char) */
 #define MAX_WINDOW_SIZE 128
@@ -178,169 +155,113 @@ int Cmi_commthread = 1;
 /* The lock to ensure the completion handler (PumpMsgsComplete) is thread-safe */
 CmiNodeLock cmplHdlrThdLock = NULL;
 
-/** 
+/**
  *  expectedMsgSeqNo is an int array of size "#procs". It tracks
  *  the expected seqno recved from other procs to this proc.
- *  
+ *
  *  nextMsgSeqNo is an int array of size "#procs". It tracks
  *  the next seqno of the msg to be sent from this proc to other
  *  procs.
- *  
+ *
  *  oooMsgBuffer is an array of sizeof(void **)*(#procs), each
- * element (created on demand) points to a window (array) size 
- * of CUR_WINDOW_SIZE which buffers the out-of-order incoming 
- * messages (a (void *) array) 
- *  
- * oooMaxOffset indicates the maximum offset of the ooo msg 
- * ahead of the expected msg. The offset begins with 1, i.e., 
- * (offset-1) is the index of the ooo msg in the window 
- * (oooMsgBuffer) 
- *  
+ * element (created on demand) points to a window (array) size
+ * of CUR_WINDOW_SIZE which buffers the out-of-order incoming
+ * messages (a (void *) array)
+ *
+ * oooMaxOffset indicates the maximum offset of the ooo msg
+ * ahead of the expected msg. The offset begins with 1, i.e.,
+ * (offset-1) is the index of the ooo msg in the window
+ * (oooMsgBuffer)
+ *
  *  --Chao Mei
  */
 
-typedef struct MsgOrderInfoStruct{
+typedef struct MsgOrderInfoStruct {
     /* vars used on sender side */
     int *nextMsgSeqNo;
 
     /* vars used on recv side */
-    int *expectedMsgSeqNo;        
+    int *expectedMsgSeqNo;
     void ***oooMsgBuffer;
     unsigned char *oooMaxOffset;
     unsigned char *CUR_WINDOW_SIZE;
-}MsgOrderInfo;
+} MsgOrderInfo;
 
-/** 
- *  broadcast msgs and p2p msgs uses different tracks of seq no
- *  as is the case with "net" layers.
+/**
+ * Once p2p msgs are ensured in-order delivery for a pair
+ * of procs, then the bcast msg is guaranteed correspondently
+ * as the order of msgs sent is fixed (i.e. the spanning tree
+ * or the hypercube is fixed)
  */
 CpvDeclare(MsgOrderInfo, p2pMsgSeqInfo);
-CpvDeclare(MsgOrderInfo, bcastMsgSeqInfo);
-
-
 #endif
 
-/*
-    To reduce the buffer used in broadcast and distribute the load from
-  broadcasting node, define CMK_BROADCAST_SPANNING_TREE enforce the use of
-  spanning tree broadcast algorithm.
-    This will use the fourth short in message as an indicator of spanning tree
-  root.
-*/
+/**
+ *  Enable this macro will offload the broadcast relay from the
+ *  internal completion handler thread. This will make the msg
+ *  seqno free of data-race. In SMP mode with comm thread where
+ *  comm thread will forward bcast msgs, this macro should be
+ *  enabled.
+ */
+/* TODO: need re-consideration */
+#define CMK_OFFLOAD_BCAST_PROCESS 1
+/* When ENSURE_MSG_PAIRORDER is enabled, CMK_OFFLOAD_BCAST_PROCESS
+ * requires to be defined because if the bcast message is processed
+ * in the lapi completion handler (the internal lapi thread), then
+ * there's possibility of data races in setting the sequence number.
+ * In SMP mode, the bcast forwarding should be offloaded from the
+ * completion handler to the comm thread to reduce the overhead if
+ * there's comm thread. If there's no commthread, and if cpv is
+ * tls-based, then CMK_OFFLOAD_BCAST_PROCESS also requires enabled
+ * because there's charm proc-private variable access would be
+ * incorrect in lapi's internal threads. -Chao Mei
+ */
+#if (CMK_SMP && (!CMK_SMP_NO_COMMTHD || (CMK_TLS_THREAD && !CMK_NOT_USE_TLS_THREAD))) || ENSURE_MSG_PAIRORDER
+#undef CMK_OFFLOAD_BCAST_PROCESS
+#define CMK_OFFLOAD_BCAST_PROCESS 1
+#endif
 
-#undef CMK_BROADCAST_SPANNING_TREE
-#define CMK_BROADCAST_SPANNING_TREE 0
+#if CMK_OFFLOAD_BCAST_PROCESS
+CsvDeclare(PCQueue, procBcastQ);
+#if CMK_NODE_QUEUE_AVAILABLE
+CsvDeclare(PCQueue, nodeBcastQ);
+#endif
+#endif
 
-/*#define BROADCAST_SPANNING_FACTOR        CMK_SPANTREE_MAXSPAN*/
-#define BROADCAST_SPANNING_FACTOR   2
+/* =======End of Definitions of Performance-Specific Macros =======*/
 
-#undef CMK_BROADCAST_HYPERCUBE
-#define CMK_BROADCAST_HYPERCUBE     1
 
-/**
- * The broadcast root of a msg. 
- * 0: indicate a non-broadcast msg 
- *  
- * >0: indicate a proc-level broadcast msg ("root-1" indicates 
- * the proc that starts a broadcast)
- *  
- * <0: indicate a node-level broadcast msg ("-root-1" indicates 
- * the node that starts a broadcast) 
- *  
- * On BG/P, we have a separate broadcast queue on each 
- * processor. This will allow us to use the separate thread 
- * (comm thread) to offload the broadcast operation from worker 
- * threads --Chao Mei 
+/* =======Beginning of Definitions of Msg Header Specific Macros =======*/
+/* msg size and srcpe are required info as they will be used for forwarding
+ * bcast msg and for ensuring message ordering
  */
-#define CMI_BROADCAST_ROOT(msg)          ((CmiMsgHeaderBasic *)msg)->root
-#define CMI_DEST_RANK(msg)               ((CmiMsgHeaderBasic *)msg)->rank
-/* The actual msg size including the msg header */
-#define CMI_MSG_SIZE(msg)                ((CmiMsgHeaderBasic *)msg)->size
-
 #define CMI_MSG_SRCPE(msg)               ((CmiMsgHeaderBasic *)msg)->srcpe
 #define CMI_MSG_SEQNO(msg)               ((CmiMsgHeaderBasic *)msg)->seqno
+/* =======End of Definitions of Msg Header Specific Macros =======*/
 
-CpvDeclare(unsigned , networkProgressCount);
-int networkProgressPeriod = 1000;
-
-static int lapiDebugMode=0;
-CsvDeclare(int, lapiInterruptMode);
-
-static void ConverseRunPE(int everReturn);
-static void PerrorExit(const char *msg);
-
-static int Cmi_nodestart;   /* First processor in this node - stupid need due to machine-smp.h that uses it!!  */
-
-static volatile int commThdExit = 0;
-
-#include "machine-smp.c"
-
-
-/* Variables describing the processor ID */
-
-/* non-smp mode */
-#if CMK_SHARED_VARS_UNAVAILABLE
-/* Should the non-smp also needs the concept of node which equals to processor -Chao Mei */
-int _Cmi_mype;
-int _Cmi_numpes;
-int _Cmi_myrank;
-
-void CmiMemLock() {}
-void CmiMemUnlock() {}
+/* =====Beginning of Definitions of Message-Corruption Related Macros=====*/
+/* =====End of Definitions of Message-Corruption Related Macros=====*/
 
-static struct CmiStateStruct Cmi_state;
 
-#define CmiGetState() (&Cmi_state)
-#define CmiGetStateN(n) (&Cmi_state)
+/* =====Beginning of Declarations of Machine Specific Variables===== */
 
-void CmiYield() {
-    sleep(0);
-}
-
-#elif CMK_SHARED_VARS_POSIX_THREADS_SMP
-
-int _Cmi_numpes;
-int _Cmi_mynodesize;
-int _Cmi_mynode;
-int _Cmi_numnodes;
-
-int CmiMyPe(void) {
-    return CmiGetState()->pe;
-}
-
-int CmiMyRank(void) {
-    return CmiGetState()->rank;
-}
-
-int CmiNodeFirst(int node) {
-    return node*_Cmi_mynodesize;
-}
-int CmiNodeSize(int node)  {
-    return _Cmi_mynodesize;
-}
-
-int CmiNodeOf(int pe)      {
-    return (pe / _Cmi_mynodesize);
-}
-int CmiRankOf(int pe)      {
-    return (pe % _Cmi_mynodesize);
-}
-#endif
+static int lapiDebugMode=0;
+CsvDeclare(int, lapiInterruptMode);
 
-CpvDeclare(void*, CmiLocalQueue);
+/**
+ * The lapiContext stands for the lapi context for a single lapi
+ * task. And inside one lapi task, only one lapi context could
+ * be created via lapi_init. In SMP mode, this context is
+ * created by proc of rank 0, and then it is shared among all
+ * cores on a node (threads) --Chao Mei
+ *
+ */
+static lapi_handle_t lapiContext;
+static lapi_long_t lapiHeaderHandler = 1;
+/* =====End of Declarations of Machine Specific Variables===== */
 
-#if DECOUPLE_BCAST_PROCESS
-CpvDeclare(PCQueue, procBcastQ);
-#if CMK_NODE_QUEUE_AVAILABLE
-CsvDeclare(PCQueue, nodeBcastQ);
-#endif
-#endif
 
-#if CMK_NODE_QUEUE_AVAILABLE
-#define DGRAM_NODEMESSAGE   (0x7EFB)
-#define NODE_BROADCAST_OTHERS (-1)
-#define NODE_BROADCAST_ALL    (-2)
-#endif
+/* =====Beginning of Declarations of Machine Specific Functions===== */
 
 /* The way to read this macro
  * "routine args" becomes a function call inside the parameters of check_lapi_err,
@@ -362,8 +283,8 @@ static void check_lapi_err(int returnCode,const char *routine,int line) {
     }
 }
 
-static void lapi_err_hndlr(lapi_handle_t *hndl, int *error_code, 
-                            lapi_err_t *err_type, int *task_ID, int *src){
+static void lapi_err_hndlr(lapi_handle_t *hndl, int *error_code,
+                           lapi_err_t *err_type, int *task_ID, int *src) {
     char errstr[LAPI_MAX_ERR_STRING];
     LAPI_Msg_string(*error_code, errstr);
     fprintf(stderr, "ERROR IN LAPI: %s for task %d at src %d\n", errstr, *task_ID, *src);
@@ -371,260 +292,352 @@ static void lapi_err_hndlr(lapi_handle_t *hndl, int *error_code,
     exit(1);
 }
 
-/**
- * The lapiContext stands for the lapi context for a single lapi 
- * task. And inside one lapi task, only one lapi context could 
- * be created via lapi_init. In SMP mode, this context is 
- * created by proc of rank 0, and then it is shared among all 
- * cores on a node (threads) --Chao Mei 
- * 
- */
-static lapi_handle_t lapiContext;
-static lapi_long_t lapiHeaderHandler = 1;
-
-/**
- * Note on broadcast functions: 
- * The converse QD may be wrong if using spanning tree or 
- * hypercube schemes to send messages --Chao Mei 
- */
-void SendMsgToPeers(int size, char *msg, int includeSelf);
+/* ===== Beginging of functions regarding ensure in-order msg delivery ===== */
 #if ENSURE_MSG_PAIRORDER
-void SendSpanningChildren(int size, char *msg, int srcPe, int *seqNoArr);
-void SendHypercube(int size, char *msg, int srcPe, int *seqNoArr);
-#else
-void SendSpanningChildren(int size, char *msg);
-void SendHypercube(int size, char *msg);
-#endif
-
-#if CMK_NODE_QUEUE_AVAILABLE
-/** 
- *  The sending schemes of the following two functions are very
- *  similar to its corresponding proc-level functions
- */
-void SendSpanningChildrenNode(int size, char *msg);
-void SendHypercubeNode(int size, char *msg);
-#endif
 
 /**
- * There is a function "CkCopyMsg" in the charm++ level, which
- * considers more than mere memcpy as there could be var size msg
+ * "setNextMsgSeqNo" actually sets the current seqno, the
+ * "getNextMsgSeqNo" will increment the seqno, i.e.,
+ * "getNextMsgSeqNo" returns the next seqno based on the previous
+ * seqno stored in the seqno array.
  * --Chao Mei
  */
-char *CopyMsg(char *msg, int len) {
-    char *copy = (char *)CmiAlloc(len);
-    if (!copy)
-        fprintf(stderr, "Out of memory\n");
-    memcpy(copy, msg, len);
-    return copy;
+static int getNextMsgSeqNo(int *seqNoArr, int destPe) {
+    int ret = seqNoArr[destPe];
+    ret++;
+    return ret;
+}
+static void setNextMsgSeqNo(int *seqNoArr, int destPe, int val) {
+    /* the seq no. may fast-forward to a new round (i.e., starting from 1 again!) */
+    if (val>=MAX_MSG_SEQNO) val -= MAX_MSG_SEQNO;
+    seqNoArr[destPe] = val;
 }
-CsvDeclare(CmiNodeState, NodeState);
 
-#if CMK_IMMEDIATE_MSG
-#include "immediate.c"
+#define getNextExpectedMsgSeqNo(seqNoArr,pe) getNextMsgSeqNo(seqNoArr, pe)
+#define setNextExpectedMsgSeqNo(seqNoArr,pe,val) setNextMsgSeqNo(seqNoArr, pe, val)
+
+static int checkMsgInOrder(char *msg, MsgOrderInfo *info);
 #endif
+/* ===== End of functions regarding ensure in-order msg delivery ===== */
 
-/** 
- *  This function will be never called in the comm thd!
- *  It is only used in the non-SMP mode, or in SMP mode w/o comm
- *  thd! --Chao Mei
- */
-static void AdvanceCommunication(){
-#if !CMK_SMP || CMK_SMP_NO_COMMTHD
 
-    if(!CsvAccess(lapiInterruptMode)) check_lapi(LAPI_Probe,(lapiContext));
-#if CMK_IMMEDIATE_MSG
-    /** 
-     * Immediate msgs are handled in CmiPushNode and 
-     * CmiSendNodeSelf, CmiPushPe and CmiSendSelf in the non-SMP 
-     * case, but in SMP case, those four functions could be called 
-     * in the completition handler where "CmiMyPe(), CmiMyRank()" 
-     * will be wrong as the "CmiGetState()" will not return a right 
-     * proc-specific CmiState!! So immediate messages are handled 
-     * when proc is idle. This may cause a big delay for processing 
-     * immdiate messages in SMP mode if there's not a dedicated 
-     * communication thread. 
-     *  
-     * Even in non-SMP, inside imm msg handlers, array proxy 
-     * messages could be sent. If handled in LAPI internal 
-     * completion thread, it will cause data-racing problems for 
-     * data structures that maintain charm array info. So it needs 
-     * to be handled in the context of a proc. 
-     *  
-     * -Chao Mei 
-     */
-    MACHSTATE1(2, "[%p] Handling Immediate Message begin{",CmiGetState());
-    CmiHandleImmediate();
-    MACHSTATE1(2, "[%p] Handling Immediate Message end}",CmiGetState());
-#endif
+/* The machine-specific send function */
+static CmiCommHandle MachineSendFuncForLAPI(int destNode, int size, char *msg, int mode);
+#define CmiMachineSpecificSendFunc MachineSendFuncForLAPI
 
-#endif
-}
+/* ### Beginning of Machine-startup Related Functions ### */
+static void MachineInitForLAPI(int argc, char **argv, int *numNodes, int *myNodeID);
+#define MachineSpecificInit MachineInitForLAPI
 
-/* non-smp CmiStartThreads. -Chao Mei */
-#if CMK_SHARED_VARS_UNAVAILABLE
-/* To conform with the call made in SMP mode */
-static void CmiStartThreads(char **argv) {
-    CmiStateInit(Cmi_nodestart, 0, &Cmi_state);
-}
-#endif
+static void MachinePreCommonInitForLAPI(int everReturn);
+static void MachinePostCommonInitForLAPI(int everReturn);
+#define MachineSpecificPreCommonInit MachinePreCommonInitForLAPI
+#define MachineSpecificPostCommonInit MachinePostCommonInitForLAPI
+/* ### End of Machine-startup Related Functions ### */
 
-/* ===== Beginging of functions regarding ensure in-order msg delivery ===== */
-#if ENSURE_MSG_PAIRORDER
+/* ### Beginning of Machine-running Related Functions ### */
+static void AdvanceCommunicationForLAPI();
+#define MachineSpecificAdvanceCommunication AdvanceCommunicationForLAPI
+
+static void DrainResourcesForLAPI(); /* used when exit */
+#define MachineSpecificDrainResources DrainResourcesForLAPI
+
+static void MachineExitForLAPI();
+#define MachineSpecificExit MachineExitForLAPI
+/* ### End of Machine-running Related Functions ### */
+
+/* ### Beginning of Idle-state Related Functions ### */
+/* ### End of Idle-state Related Functions ### */
+
+void MachinePostNonLocalForLAPI();
+#define MachineSpecificPostNonLocal MachinePostNonLocalForLAPI
+
+/* =====End of Declarations of Machine Specific Functions===== */
 
 /**
- * "setNextMsgSeqNo" actually sets the current seqno, the 
- * "getNextMsgSeqNo" will increment the seqno, i.e., 
- * "getNextMgSeqNo" returns the next seqno based on the previous 
- * seqno stored in the seqno array. 
- * --Chao Mei 
+ *  Macros that overwrites the common codes, such as
+ *  CMK_SMP_NO_COMMTHD, NETWORK_PROGRESS_PERIOD_DEFAULT,
+ *  USE_COMMON_SYNC_P2P, CMK_HAS_SIZE_IN_MSGHDR,
+ *  CMK_OFFLOAD_BCAST_PROCESS etc.
  */
-static int getNextMsgSeqNo(int *seqNoArr, int destPe){
-    int ret = seqNoArr[destPe];
-    ret++;
-    return ret;
+/* For async msg sending ops, using lapi specific implementations */
+#define USE_COMMON_ASYNC_BCAST 0
+#define CMK_OFFLOAD_BCAST_PROCESS 1
+#include "machine-common.c"
+
+/* The machine specific msg-sending function */
+
+/* ######Beginning of functions for sending a msg ###### */
+//lapi sending completion callback
+/* The following two are callbacks for sync and async send respectively */
+static void ReleaseMsg(lapi_handle_t *myLapiContext, void *msg, lapi_sh_info_t *info) {
+    MACHSTATE2(2,"[%d] ReleaseMsg begin %p {",CmiMyNode(),msg);
+    check_lapi_err(info->reason, "ReleaseMsg", __LINE__);
+    CmiFree(msg);
+    MACHSTATE(2,"} ReleaseMsg end");
 }
-static void setNextMsgSeqNo(int *seqNoArr, int destPe, int val){
-    /* the seq no. may fast-forward to a new round (i.e., starting from 1 again!) */
-    if(val>=MAX_MSG_SEQNO) val -= MAX_MSG_SEQNO;
-    seqNoArr[destPe] = val;
+
+static void DeliveredMsg(lapi_handle_t *myLapiContext, void *msg, lapi_sh_info_t *info) {
+    MACHSTATE1(2,"[%d] DeliveredMsg begin {",CmiMyNode());
+    check_lapi_err(info->reason, "DeliveredMsg", __LINE__);
+    *((int *)msg) = *((int *)msg) - 1;
+    MACHSTATE(2,"} DeliveredMsg end");
 }
 
-#define getNextExpectedMsgSeqNo(seqNoArr,srcPe) getNextMsgSeqNo(seqNoArr, srcPe)
-#define setNextExpectedMsgSeqNo(seqNoArr,srcPe,val) setNextMsgSeqNo(seqNoArr, srcPe, val)
+static INLINE_KEYWORD void lapiSendFn(int destNode, int size, char *msg, scompl_hndlr_t *shdlr, void *sinfo) {
+    lapi_xfer_t xfer_cmd;
 
-#endif
-/* ===== End of functions regarding ensure in-order msg delivery ===== */
+    MACHSTATE3(2,"lapiSendFn to destNode=%d with msg %p (isImm=%d) begin {",destNode,msg, CmiIsImmediate(msg));
+    MACHSTATE3(2, "inside lapiSendFn 1: size=%d, sinfo=%p, deliverable=%d", size, sinfo, deliverable);
 
-/* ===========CmiPushPe and CmiPushNode============*/
-/* Add a message to this processor's receive queue, pe is a rank */
-void CmiPushPE(int pe,void *msg) {
-    CmiState cs = CmiGetStateN(pe);
-    MACHSTATE3(3,"Pushing message(%p) into rank %d's queue %p {",msg,pe,(cs->recv));
+    MACHSTATE2(2, "Ready to call LAPI_Xfer with destNode=%d, destRank=%d",destNode,CMI_DEST_RANK(msg));
 
-#if CMK_IMMEDIATE_MSG
-    if (CmiIsImmediate(msg)) {
-        MACHSTATE1(3, "[%p] Push Immediate Message begin{",CmiGetState());
-        CMI_DEST_RANK(msg) = pe;
-        CmiPushImmediateMsg(msg);
-        MACHSTATE1(3, "[%p] Push Immediate Message end }",CmiGetState());
-        return;
-    }
-#endif
+    xfer_cmd.Am.Xfer_type = LAPI_AM_XFER;
+    xfer_cmd.Am.flags     = 0;
+    xfer_cmd.Am.tgt       = destNode;
+    xfer_cmd.Am.hdr_hdl   = lapiHeaderHandler;
+    xfer_cmd.Am.uhdr_len  = 0;
+    xfer_cmd.Am.uhdr      = NULL;
+    xfer_cmd.Am.udata     = msg;
+    xfer_cmd.Am.udata_len = size;
+    xfer_cmd.Am.shdlr     = shdlr;
+    xfer_cmd.Am.sinfo     = sinfo;
+    xfer_cmd.Am.tgt_cntr  = NULL;
+    xfer_cmd.Am.org_cntr  = NULL;
+    xfer_cmd.Am.cmpl_cntr = NULL;
 
-    /* Note atomicity is guaranteed inside pcqueue data structure --Chao Mei */
-    PCQueuePush(cs->recv,msg);
+    check_lapi(LAPI_Xfer,(lapiContext, &xfer_cmd));
 
-    CmiIdleLock_addMessage(&cs->idle);
-    MACHSTATE1(3,"} Pushing message into rank %d's queue done",pe);
+    MACHSTATE(2,"} lapiSendFn end");
 }
 
-#if CMK_NODE_QUEUE_AVAILABLE
-/*Add a message to this processor's receive queue */
-/*Note: CmiPushNode is essentially same with CimSendNodeSelf */
-static void CmiPushNode(void *msg) {    
-    MACHSTATE1(3,"[%p] Pushing message into NodeRecv queue",CmiGetState());
+static CmiCommHandle MachineSendFuncForLAPI(int destNode, int size, char *msg, int mode) {
+    scompl_hndlr_t *shdlr = NULL;
+    void *sinfo = NULL;
 
-#if CMK_IMMEDIATE_MSG
-    if (CmiIsImmediate(msg)) {
-        MACHSTATE1(3, "[%p] Push Immediate Message begin {",CmiGetState());
-        CMI_DEST_RANK(msg) = 0;
-        CmiPushImmediateMsg(msg);
-        MACHSTATE1(3, "[%p] Push Immediate Message end }",CmiGetState());
-        return;
+    if (mode==P2P_SYNC) {
+        shdlr = ReleaseMsg;
+        sinfo = (void *)msg;
+    } else if (mode==P2P_ASYNC) {
+        shdlr = DeliveredMsg;
+        sinfo = malloc(sizeof(int));
+        *((int *)sinfo) = 1;
     }
-#endif
-    /* CmiNodeRecvLock may not be needed  --Chao Mei*/
-    CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
-    PCQueuePush(CsvAccess(NodeState).NodeRecv,msg);
-    CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
 
-    CmiState cs=CmiGetStateN(0);
-    CmiIdleLock_addMessage(&cs->idle);
+    CMI_MSG_SIZE(msg) = size;
 
-    MACHSTATE(3,"Pushing message into NodeRecv queue {");
-}
+#if ENSURE_MSG_PAIRORDER
+#if CMK_NODE_QUEUE_AVAILABLE
+    if (CMI_DEST_RANK(msg) == DGRAM_NODEMESSAGE) {
+        lapiSendFn(destNode, size, msg, shdlr, sinfo);
+        return sinfo;
+    }
+#endif
+    int destPE = CmiNodeFirst(destNode)+CMI_DEST_RANK(msg);
+    CMI_MSG_SRCPE(msg) = CmiMyPe();
+    /* Note: This could be executed on comm threads, where CmiMyPe() >= CmiNumPes() */
+    CMI_MSG_SEQNO(msg) = getNextMsgSeqNo(CpvAccess(p2pMsgSeqInfo).nextMsgSeqNo, destPE);
+    setNextMsgSeqNo(CpvAccess(p2pMsgSeqInfo).nextMsgSeqNo, destPE, CMI_MSG_SEQNO(msg));
 #endif
 
-/* ======Beginning of helper functions for processing an incoming (network) message ======*/
-/* Process a proc-level broadcast message */
-static void ProcessProcBroadcastMsg(char *msg){
-    int nbytes = CMI_MSG_SIZE(msg);    
+    lapiSendFn(destNode, size, msg, shdlr, sinfo);
+    return sinfo;
+}
+
+/* Lapi-specific implementation of async msg sending operations */
+#if !USE_COMMON_ASYNC_BCAST
+CmiCommHandle CmiAsyncBroadcastFn(int size, char *msg) {
 #if ENSURE_MSG_PAIRORDER
-    MACHSTATE3(2,"[%p] the broadcast msg is from pe=%d with seq no=%d", CmiGetState(), CMI_MSG_SRCPE(msg), CMI_MSG_SEQNO(msg));
-    #if CMK_BROADCAST_SPANNING_TREE    
-    SendSpanningChildren(nbytes, msg, CmiNodeFirst(CmiMyNode()), CpvAccessOther(bcastMsgSeqInfo, 0).nextMsgSeqNo);
-    #elif CMK_BROADCAST_HYPERCUBE    
-    SendHypercube(nbytes, msg, CmiNodeFirst(CmiMyNode()), CpvAccessOther(bcastMsgSeqInfo, 0).nextMsgSeqNo);
-    #endif
-#else
-    #if CMK_BROADCAST_SPANNING_TREE
-    SendSpanningChildren(nbytes, msg);
-    #elif CMK_BROADCAST_HYPERCUBE
-    SendHypercube(nbytes, msg);
-    #endif
-#endif                     
-#if CMK_SMP
-    SendMsgToPeers(nbytes, msg, 1);                   
-    CmiFree(msg);
+    /* Not sure how to add the msg seq no for async broadcast messages --Chao Mei */
+    /* so abort here ! */
+    CmiAssert(0);
+    return 0;
 #else
-    /* nonsmp case */
-    CmiPushPE(0, msg);
+    int i, rank;
+    int mype = CmiMyPe();
+#if ENABLE_CONVERSE_QD
+    CQdCreate(CpvAccess(cQdState), CmiNumPes()-1);
+#endif
+    MACHSTATE1(3,"[%d] Sending async broadcast message from {",CmiMyNode());
+    CMI_BROADCAST_ROOT(msg) = 0;
+    void *handle = malloc(sizeof(int));
+    *((int *)handle) = CmiNumPes()-1;
+
+    for (i=mype+1; i<CmiNumPes(); i++) {
+        CMI_DEST_RANK(msg) = CmiRankOf(i);
+        lapiSendFn(CmiNodeOf(i), size, msg, DeliveredMsg, handle);
+    }
+    for (i=0; i<mype; i++) {
+        CMI_DEST_RANK(msg) = CmiRankOf(i);
+        lapiSendFn(CmiNodeOf(i), size, msg, DeliveredMsg, handle);
+    }
+
+    MACHSTATE(3,"} Sending async broadcast message end");
+    return handle;
 #endif
 }
 
 #if CMK_NODE_QUEUE_AVAILABLE
-/* Process a node-level broadcast message */
-static void ProcessNodeBroadcastMsg(char *msg){
-    int nbytes = CMI_MSG_SIZE(msg);
-#if CMK_BROADCAST_SPANNING_TREE
-    SendSpanningChildrenNode(nbytes, msg);
-#elif CMK_BROADCAST_HYPERCUBE
-    SendHypercubeNode(nbytes, msg);
-#endif            
-    CmiPushNode(msg);
-}
+CmiCommHandle CmiAsyncNodeBroadcastFn(int size, char *msg) {
+    int i;
+
+#if ENABLE_CONVERSE_QD
+    CQdCreate(CpvAccess(cQdState), CmiNumNodes()-1);
 #endif
 
-/* Pull msgs from two queues, this function should not be called from cmpl_hdlr thread */
-static void ProcessBroadcastMsg(int pullRank){
-    char *msg;
-    do{
-        msg = PCQueuePop(CpvAccessOther(procBcastQ, pullRank));
-        if(msg) {
-            MACHSTATE2(4, "[%p]: process a proc-level bcast msg %p begin{", CmiGetState(), msg);
-            ProcessProcBroadcastMsg(msg);
-            MACHSTATE2(4, "[%p]: process a proc-level bcast msg %p end}", CmiGetState(), msg);
-        }else{ 
-            break;
-        }
-    }while (1);
-#if CMK_NODE_QUEUE_AVAILABLE
-    do{
-        msg = PCQueuePop(CsvAccess(nodeBcastQ));
-        if(msg) {
-            MACHSTATE2(4, "[%p]: process a node-level bcast msg %p begin{", CmiGetState(), msg);
-            ProcessNodeBroadcastMsg(msg);
-            MACHSTATE2(4, "[%p]: process a node-level bcast msg %p end}", CmiGetState(), msg);
-        }else{ 
-            break;
-        }
-    }while (1);    
+    MACHSTATE1(3,"[%d] Sending async node broadcast message from {",CmiMyNode());
+    CMI_BROADCAST_ROOT(msg) = 0;
+    CMI_DEST_RANK(msg) =DGRAM_NODEMESSAGE;
+    void *handle = malloc(sizeof(int));
+    *((int *)handle) = CmiNumNodes()-1;
+    for (i=CmiMyNode()+1; i<CmiNumNodes(); i++) {
+        lapiSendFn(i, size, msg, DeliveredMsg, handle);
+    }
+    for (i=0; i<CmiMyNode(); i++) {
+        lapiSendFn(i, size, msg, DeliveredMsg, handle);
+    }
+
+    MACHSTATE(3,"} Sending async broadcast message end");
+    return handle;
+}
 #endif
+#endif/* end of !USE_COMMON_ASYNC_BCAST */
+
+int CmiAsyncMsgSent(CmiCommHandle handle) {
+    return (*((int *)handle) == 0)?1:0;
 }
 
+void CmiReleaseCommHandle(CmiCommHandle handle) {
+#ifndef CMK_OPTIMIZE
+    if (*((int *)handle) != 0) CmiAbort("Released a CmiCommHandle not free!");
+#endif
+    free(handle);
+}
+/* ######End of functions for sending a msg ###### */
 
-#if ENSURE_MSG_PAIRORDER
-/* return 1 if this msg is an out-of-order incoming message */
+/* ######Beginning of functions for receiving a msg ###### */
+/* lapi recv callback when the first packet of the msg arrives as header handler*/
+static void* PumpMsgsBegin(lapi_handle_t *myLapiContext,
+                           void *hdr, uint *uhdr_len,
+                           lapi_return_info_t *msg_info,
+                           compl_hndlr_t **comp_h, void **comp_am_info);
+/* lapi recv completion callback when all the msg is received */
+static void PumpMsgsComplete(lapi_handle_t *myLapiContext, void *am_info);
 
+/** lapi header handler: executed on the recv side, when the
+ *  first packet of the recving msg arrives, it is called to
+ *  prepare the memory buffer in the user space for recving the
+ *  data --Chao Mei
+ */
+static void* PumpMsgsBegin(lapi_handle_t *myLapiContext,
+                           void *hdr, uint *uhdr_len,
+                           lapi_return_info_t *msg_info,
+                           compl_hndlr_t **comp_h, void **comp_am_info) {
+    void *msg_buf;
+    MACHSTATE1(2,"[%d] PumpMsgsBegin begin {",CmiMyNode());
+    /* prepare the space for receiving the data, set the completion handler to
+       be executed inline */
+    msg_buf = (void *)CmiAlloc(msg_info->msg_len);
+
+    msg_info->ret_flags = LAPI_SEND_REPLY;
+    *comp_h = PumpMsgsComplete;
+    *comp_am_info = msg_buf;
+    MACHSTATE(2,"} PumpMsgsBegin end");
+    return msg_buf;
+
+}
+
+/**
+  * lapi completion handler on the recv side. It's responsible to push messages
+  * to the destination proc or relay broadcast messages. --Chao Mei
+  *
+  * Note: The completion handler could be executed on any cores within a node ???
+  * So in SMP mode when there's a comm thread, the completion handler should be carefully
+  * dealt with.
+  *
+  * Given lapi also provides an internal lapi thread to deal with network progress which
+  * will call this function (???), we should be careful with the following situations:
+  * 1) non SMP mode, with interrupt (lapi internal completion thread)
+  * 2) non SMP mode, with polling (machine layer is responsible for network progress)
+  * 3) SMP mode, no comm thread, with polling
+  * 4) SMP mode, no comm thread, with interrupt
+  * 5) SMP mode, with comm thread, with polling (not yet implemented, comm server is empty right now)
+  * 6) SMP mode, with comm thread, with interrupt??
+  *
+  * Currently, SMP mode without comm thread is undergoing implementation.
+  *
+  * This function is executed by LAPI internal threads. It seems that the number of internal
+  * completion handler threads could vary during the program. LAPI adaptively creates more
+  * threads if there are more outstanding messages!!!! This means pcqueue needs protection
+  * even in the nonsmp case!!!!
+  *
+  * --Chao Mei
+  */
+static void PumpMsgsComplete(lapi_handle_t *myLapiContext, void *am_info) {
+    int i;
+    char *msg = am_info;
+    int broot, destrank;
+
+    MACHSTATE3(2,"[%d] PumpMsgsComplete with msg %p (isImm=%d) begin {",CmiMyNode(), msg, CmiIsImmediate(msg));
+#if ENSURE_MSG_PAIRORDER
+    MACHSTATE3(2,"msg %p info: srcpe=%d, seqno=%d", msg, CMI_MSG_SRCPE(msg), CMI_MSG_SEQNO(msg));
+#endif
+    /**
+     * First, we check if the msg is a broadcast msg via spanning
+     * tree. If it is, it needs to call SendSpanningChildren to
+     * relay the broadcast, and then send the msg to every cores on
+     * this node.
+     *
+     * After the first check, we deal with normal messages.
+     * --Chao Mei
+     */
+    /* It's the right place to relay the broadcast message */
+    /**
+     * 1. For in-order delivery, because this is the handler for
+     * receiving a message, and we assume the cross-network msgs are
+     * always delivered to the first proc (rank 0) of this node, we
+     * select the srcpe of the bcast msgs and the next msg seq no
+     * correspondingly.
+     *
+     * --Chao Mei
+     */
+#if ENSURE_MSG_PAIRORDER
+    broot = CMI_BROADCAST_ROOT(msg);
+    destrank = CMI_DEST_RANK(msg);
+    /* Only check proc-level msgs */
+    if (broot>=0
+#if CMK_NODE_QUEUE_AVAILABLE
+            && destrank != DGRAM_NODEMESSAGE
+#endif
+       ) {
+        MsgOrderInfo *info;
+        info = &CpvAccessOther(p2pMsgSeqInfo, destrank);
+        MACHSTATE1(2, "Check msg in-order for p2p msg %p", msg);
+
+        if (checkMsgInOrder(msg,info)) {
+            MACHSTATE(2,"} PumpMsgsComplete end ");
+            return;
+        }
+    }
+#endif
+
+    handleOneRecvedMsg(CMI_MSG_SIZE(msg), msg);
+
+    MACHSTATE(2,"} PumpMsgsComplete end ");
+    return;
+}
+
+/* utility function for ensuring the message pair-ordering */
+#if ENSURE_MSG_PAIRORDER
+/* return 1 if this msg is an out-of-order incoming message */
 /**
- * Returns 1 if this "msg" is an out-of-order message, or 
- * this "msg" is a late message which triggers the process 
- * of all buffered ooo msgs. 
- * --Chao Mei 
+ * Returns 1 if this "msg" is an out-of-order message, or
+ * this "msg" is a late message which triggers the process
+ * of all buffered ooo msgs.
+ * --Chao Mei
  */
-static int CheckMsgInOrder(char *msg, MsgOrderInfo *info){
-    int srcpe, destrank; 
+static int checkMsgInOrder(char *msg, MsgOrderInfo *info) {
+    int srcpe, destrank;
     int incomingSeqNo, expectedSeqNo;
     int curOffset, maxOffset;
     int i, curWinSize;
@@ -633,78 +646,77 @@ static int CheckMsgInOrder(char *msg, MsgOrderInfo *info){
     /* numMsg is the number of msgs to be processed in this buffer*/
     /* Reason to have this extra copy of msgs to be processed: Reduce the atomic granularity */
     void **toProcessMsgBuffer;
-    int numMsgs = 0;    
+    int numMsgs = 0;
+
     srcpe = CMI_MSG_SRCPE(msg);
-    destrank = CMI_DEST_RANK(msg);  
+    destrank = CMI_DEST_RANK(msg);
     incomingSeqNo = CMI_MSG_SEQNO(msg);
-    
+
     CmiLock(cmplHdlrThdLock);
 
     expectedSeqNo = getNextExpectedMsgSeqNo(info->expectedMsgSeqNo, srcpe);
-    if(expectedSeqNo == incomingSeqNo){
+    if (expectedSeqNo == incomingSeqNo) {
         /* Two cases: has ooo msg buffered or not */
         maxOffset = (info->oooMaxOffset)[srcpe];
-        if(maxOffset>0) {
+        if (maxOffset>0) {
             MACHSTATE1(4, "Processing all buffered ooo msgs (maxOffset=%d) including the just recved begin {", maxOffset);
             curWinSize = info->CUR_WINDOW_SIZE[srcpe];
             toProcessMsgBuffer = malloc((curWinSize+1)*sizeof(void *));
             /* process the msg just recved */
-            toProcessMsgBuffer[numMsgs++] = msg;            
+            toProcessMsgBuffer[numMsgs++] = msg;
             /* process the buffered ooo msg until the first empty slot in the window */
-            destMsgBuffer = (info->oooMsgBuffer)[srcpe];                       
-            for(curOffset=0; curOffset<maxOffset; curOffset++) {
+            destMsgBuffer = (info->oooMsgBuffer)[srcpe];
+            for (curOffset=0; curOffset<maxOffset; curOffset++) {
                 char *curMsg = destMsgBuffer[curOffset];
-                if(curMsg == NULL){
-                    CmiAssert(curOffset!=(maxOffset-1));                                        
+                if (curMsg == NULL) {
+                    CmiAssert(curOffset!=(maxOffset-1));
                     break;
                 }
                 toProcessMsgBuffer[numMsgs++] = curMsg;
                 destMsgBuffer[curOffset] = NULL;
-            }            
+            }
             /* Update expected seqno, maxOffset and slide the window */
-            if(curOffset < maxOffset) {
+            if (curOffset < maxOffset) {
                 int i;
-                /** 
-                 * now, the seqno of the next to-be-recved msg should be 
-                 * "expectedSeqNo+curOffset+1" as the seqno of the just 
-                 * processed msg is "expectedSeqNo+curOffset. We need to slide 
-                 * the msg buffer window from "curOffset+1" because the first 
-                 * element of the buffer window should always points to the ooo 
-                 * msg that's 1 in terms of seqno ahead of the next to-be-recved 
-                 * msg. --Chao Mei 
-                 */                
-                
+                /**
+                 * now, the seqno of the next to-be-recved msg should be
+                 * "expectedSeqNo+curOffset+1" as the seqno of the just
+                 * processed msg is "expectedSeqNo+curOffset. We need to slide
+                 * the msg buffer window from "curOffset+1" because the first
+                 * element of the buffer window should always points to the ooo
+                 * msg that's 1 in terms of seqno ahead of the next to-be-recved
+                 * msg. --Chao Mei
+                 */
+
                 /* moving [curOffset+1, maxOffset) to [0, maxOffset-curOffset-1) in the window */
                 /* The following two loops could be combined --Chao Mei */
-                for(i=0; i<maxOffset-curOffset-1; i++){
+                for (i=0; i<maxOffset-curOffset-1; i++) {
                     destMsgBuffer[i] = destMsgBuffer[curOffset+i+1];
                 }
-                for(i=maxOffset-curOffset-1; i<maxOffset; i++) {
+                for (i=maxOffset-curOffset-1; i<maxOffset; i++) {
                     destMsgBuffer[i] = NULL;
                 }
                 (info->oooMaxOffset)[srcpe] = maxOffset-curOffset-1;
                 setNextExpectedMsgSeqNo(info->expectedMsgSeqNo, srcpe, expectedSeqNo+curOffset);
-            }else{
+            } else {
                 /* there's no remaining buffered ooo msgs */
                 (info->oooMaxOffset)[srcpe] = 0;
                 setNextExpectedMsgSeqNo(info->expectedMsgSeqNo, srcpe, expectedSeqNo+maxOffset);
             }
 
             CmiUnlock(cmplHdlrThdLock);
-                        
+
             /* Process the msgs */
-            for(i=0; i<numMsgs; i++){
-                char *curMsg = toProcessMsgBuffer[i];                
-                if(CMI_BROADCAST_ROOT(curMsg)>0) {
-                                        
-                #if DECOUPLE_BCAST_PROCESS
-                    PCQueuePush(CpvAccessOther(procBcastQ, 0), curMsg);
-                #else
-                    ProcessProcBroadcastMsg(curMsg);
-                #endif
-
-                }else{
+            for (i=0; i<numMsgs; i++) {
+                char *curMsg = toProcessMsgBuffer[i];
+                if (CMI_BROADCAST_ROOT(curMsg)>0) {
+
+#if CMK_OFFLOAD_BCAST_PROCESS
+                    PCQueuePush(CsvAccess(procBcastQ), curMsg);
+#else
+                    processProcBcastMsg(CMI_MSG_SIZE(curMsg), curMsg);
+#endif
+                } else {
                     CmiPushPE(CMI_DEST_RANK(curMsg), curMsg);
                 }
             }
@@ -712,38 +724,38 @@ static int CheckMsgInOrder(char *msg, MsgOrderInfo *info){
             free(toProcessMsgBuffer);
 
             MACHSTATE1(4, "Processing all buffered ooo msgs (actually processed %d) end }", curOffset);
-            /** 
-             * Since we have processed all buffered ooo msgs including 
-             * this just recved one, 1 should be returned so that this 
-             * msg no longer needs processing 
+            /**
+             * Since we have processed all buffered ooo msgs including
+             * this just recved one, 1 should be returned so that this
+             * msg no longer needs processing
              */
             return 1;
-        }else{
+        } else {
             /* An expected msg recved without any ooo msg buffered */
             MACHSTATE1(4, "Receiving an expected msg with seqno=%d\n", incomingSeqNo);
             setNextExpectedMsgSeqNo(info->expectedMsgSeqNo, srcpe, expectedSeqNo);
 
             CmiUnlock(cmplHdlrThdLock);
             return 0;
-        }        
+        }
     }
 
     MACHSTATE2(4, "Receiving an out-of-order msg with seqno=%d, but expect seqno=%d", incomingSeqNo, expectedSeqNo);
     curWinSize = info->CUR_WINDOW_SIZE[srcpe];
-    if((info->oooMsgBuffer)[srcpe]==NULL) {        
+    if ((info->oooMsgBuffer)[srcpe]==NULL) {
         (info->oooMsgBuffer)[srcpe] = malloc(curWinSize*sizeof(void *));
         memset((info->oooMsgBuffer)[srcpe], 0, curWinSize*sizeof(void *));
     }
     destMsgBuffer = (info->oooMsgBuffer)[srcpe];
     curOffset = incomingSeqNo - expectedSeqNo;
     maxOffset = (info->oooMaxOffset)[srcpe];
-    if(curOffset<0) {
+    if (curOffset<0) {
         /* It's possible that the seqNo starts with another round (exceeding MAX_MSG_SEQNO) with 1 */
         curOffset += MAX_MSG_SEQNO;
     }
-    if(curOffset > curWinSize) {
+    if (curOffset > curWinSize) {
         int newWinSize;
-        if(curOffset > MAX_WINDOW_SIZE) {
+        if (curOffset > MAX_WINDOW_SIZE) {
             CmiAbort("Exceeding the MAX_WINDOW_SIZE!\n");
         }
         newWinSize = ((curOffset/curWinSize)+1)*curWinSize;
@@ -754,1184 +766,158 @@ static int CheckMsgInOrder(char *msg, MsgOrderInfo *info){
         info->CUR_WINDOW_SIZE[srcpe] = newWinSize;
         free(destMsgBuffer);
         destMsgBuffer = (info->oooMsgBuffer)[srcpe];
-    }    
+    }
     CmiAssert(destMsgBuffer[curOffset-1] == NULL);
     destMsgBuffer[curOffset-1] = msg;
-    if(curOffset > maxOffset) (info->oooMaxOffset)[srcpe] = curOffset;
+    if (curOffset > maxOffset) (info->oooMaxOffset)[srcpe] = curOffset;
 
     CmiUnlock(cmplHdlrThdLock);
     return 1;
 }
+#endif /* end of ENSURE_MSG_PAIRORDER */
 
-#endif
-/* ======End of helper functions for processing an incoming (network) message ======*/
-
-/* ======Begining of lapi callbacks such as the completion handler on the sender and recver side ======*/
-/** 
-  * lapi completion handler on the recv side. It's responsible to push messages 
-  * to the destination proc or relay broadcast messages. --Chao Mei 
-  *  
-  * Note: The completion handler could be executed on any cores within a node ??? 
-  * So in SMP mode when there's a comm thread, the completion handler should be carefully 
-  * dealt with. 
-  *  
-  * Given lapi also provides an internal lapi thread to deal with network progress which 
-  * will call this function (???), we should be careful with the following situations: 
-  * 1) non SMP mode, with interrupt (lapi internal completion thread) 
-  * 2) non SMP mode, with polling (machine layer is responsible for network progress) 
-  * 3) SMP mode, no comm thread, with polling 
-  * 4) SMP mode, no comm thread, with interrupt 
-  * 5) SMP mode, with comm thread, with polling (not yet implemented, comm server is empty right now)
-  * 6) SMP mode, with comm thread, with interrupt?? 
-  *  
-  * Currently, SMP mode without comm thread is undergoing implementation. 
-  *  
-  * This function is executed by LAPI internal threads. It seems that the number of internal 
-  * completion handler threads could vary during the program. LAPI adaptively creates more 
-  * threads if there are more outstanding messages!!!! This means pcqueue needs protection 
-  * even in the nonsmp case!!!!
-  *  
-  * --Chao Mei 
-  */
-static void PumpMsgsComplete(lapi_handle_t *myLapiContext, void *am_info) {
-    int i;
-    char *msg = am_info;
-    int broot, destrank;
-
-    MACHSTATE3(2,"[%p] PumpMsgsComplete with msg %p (isImm=%d) begin {",CmiGetState(), msg, CmiIsImmediate(msg));    
-#if ENSURE_MSG_PAIRORDER
-    MACHSTATE3(2,"msg %p info: srcpe=%d, seqno=%d", msg, CMI_MSG_SRCPE(msg), CMI_MSG_SEQNO(msg));
-#endif
-    /**
-     * First, we check if the msg is a broadcast msg via spanning 
-     * tree. If it is, it needs to call SendSpanningChildren to 
-     * relay the broadcast, and then send the msg to every cores on 
-     * this node.
-     *  
-     * After the first check, we deal with normal messages. 
-     * --Chao Mei
-     */
-/* It's the right place to relay the broadcast message */
-    /**
-     * 1. For in-order delivery, because this is the handler for 
-     * receiving a message, and we assume the cross-network msgs are 
-     * always delivered to the first proc (rank 0) of this node, we 
-     * select the srcpe of the bcast msgs and the next msg seq no 
-     * correspondingly. 
-     *  
-     * 2. TODO: checking the in-order delivery of p2p msgs!! 
-     *  
-     * --Chao Mei 
-     */
-#if ENSURE_MSG_PAIRORDER 
-    broot = CMI_BROADCAST_ROOT(msg);
-    destrank = CMI_DEST_RANK(msg);
-    /* Only check proc-level msgs */
-    if (broot>=0
-#if CMK_NODE_QUEUE_AVAILABLE
-        && destrank != DGRAM_NODEMESSAGE
-#endif
-    )
-    {
-        MsgOrderInfo *info;        
-        if(broot>0){
-            info = &CpvAccessOther(bcastMsgSeqInfo, destrank);
-            MACHSTATE1(2, "Check msg in-order for bcast msg %p", msg);
-        } else {
-            info = &CpvAccessOther(p2pMsgSeqInfo, destrank);
-            MACHSTATE1(2, "Check msg in-order for p2p msg %p", msg);
-        }
-        if(CheckMsgInOrder(msg,info)) {
-            MACHSTATE(2,"} PumpMsgsComplete end ");
-            return;
-        }
-    }
-#endif    
-
-#if CMK_BROADCAST_SPANNING_TREE || CMK_BROADCAST_HYPERCUBE
-    if (CMI_BROADCAST_ROOT(msg)>0) {
-        MACHSTATE2(2,"[%p] Recved a proc-level broadcast msg %p",CmiGetState(), msg);     
-                
-    #if DECOUPLE_BCAST_PROCESS
-        PCQueuePush(CpvAccessOther(procBcastQ, 0), msg);
-    #else
-        ProcessProcBroadcastMsg(msg);
-    #endif
-
-        MACHSTATE(2,"} PumpMsgsComplete end ");
-        return;
-    }
-
-#if CMK_NODE_QUEUE_AVAILABLE
-    if(CMI_BROADCAST_ROOT(msg) < 0) {
-        MACHSTATE1(2,"[%p] Recved a node-level broadcast msg",CmiGetState());  
-        
-    #if DECOUPLE_BCAST_PROCESS
-        PCQueuePush(CsvAccess(nodeBcastQ), msg);
-    #else
-        ProcessNodeBroadcastMsg(msg);
-    #endif
-
-        MACHSTATE(2,"} PumpMsgsComplete end ");
-        return;
-    }
-#endif
-
-#endif
-
-#if CMK_NODE_QUEUE_AVAILABLE
-    if (CMI_DEST_RANK(msg)==DGRAM_NODEMESSAGE)
-        CmiPushNode(msg);
-    else{
-        MACHSTATE3(2,"[%p] Recv a p2p msg from pe=%d with seq no=%d", CmiGetState(), CMI_MSG_SRCPE(msg), CMI_MSG_SEQNO(msg));
-        CmiPushPE(CMI_DEST_RANK(msg), msg);
-    }
-#else
-    CmiPushPE(CMI_DEST_RANK(msg), msg);
-#endif
-
-    MACHSTATE(2,"} PumpMsgsComplete end ");
-    return;
-}
-
-/** lapi header handler: executed on the recv side, when the
- *  first packet of the recving msg arrives, it is called to
- *  prepare the memory buffer in the user space for recving the
- *  data --Chao Mei
- */
-static void* PumpMsgsBegin(lapi_handle_t *myLapiContext,
-                           void *hdr, uint *uhdr_len,
-                           lapi_return_info_t *msg_info,
-                           compl_hndlr_t **comp_h, void **comp_am_info) {
-    void *msg_buf;
-    MACHSTATE1(2,"[%p] PumpMsgsBegin begin {",CmiGetState());
-    /* prepare the space for receiving the data, set the completion handler to
-       be executed inline */
-    msg_buf = (void *)CmiAlloc(msg_info->msg_len);
-
-    msg_info->ret_flags = LAPI_SEND_REPLY;
-    *comp_h = PumpMsgsComplete;
-    *comp_am_info = msg_buf;
-    MACHSTATE(2,"} PumpMsgsBegin end");
-    return msg_buf;
-
-}
-
-/* The following two are lapi sender handlers */
-static void ReleaseMsg(lapi_handle_t *myLapiContext, void *msg, lapi_sh_info_t *info) {
-    MACHSTATE2(2,"[%p] ReleaseMsg begin %p {",CmiGetState(),msg);
-    check_lapi_err(info->reason, "ReleaseMsg", __LINE__);
-    CmiFree(msg);
-    MACHSTATE(2,"} ReleaseMsg end");
-}
-
-static void DeliveredMsg(lapi_handle_t *myLapiContext, void *msg, lapi_sh_info_t *info) {
-    MACHSTATE1(2,"[%p] DeliveredMsg begin {",CmiGetState());
-    check_lapi_err(info->reason, "DeliveredMsg", __LINE__);
-    *((int *)msg) = *((int *)msg) - 1;
-    MACHSTATE(2,"} DeliveredMsg end");
-}
-/* ======End of lapi callbacks such as the completion handler on the sender and recver side ======*/
+/* ######End of functions for receiving a msg ###### */
 
+/* ######Beginning of functions related with communication progress ###### */
 
-#if CMK_NODE_QUEUE_AVAILABLE
-char *CmiGetNonLocalNodeQ(void) {
-    CmiState cs = CmiGetState();
-    char *result = 0;
-    CmiIdleLock_checkMessage(&cs->idle);
-    if (!PCQueueEmpty(CsvAccess(NodeState).NodeRecv)) {
-        MACHSTATE2(3,"[%p] CmiGetNonLocalNodeQ begin %d {",CmiGetState(),CmiMyPe());
-        CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
-        result = (char *) PCQueuePop(CsvAccess(NodeState).NodeRecv);
-        CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
-        MACHSTATE1(3,"} CmiGetNonLocalNodeQ end %d ", CmiMyPe());
-    }
-    return result;
+static INLINE_KEYWORD void AdvanceCommunicationForLAPI() {
+    /* What about CMK_SMP_NO_COMMTHD in the original implementation?? */
+    /* It does nothing but sleep */
+    if (!CsvAccess(lapiInterruptMode)) check_lapi(LAPI_Probe,(lapiContext));
 }
-#endif
-
-void *CmiGetNonLocal(void) {    
-    CmiState cs = CmiGetState();
-    MACHSTATE2(3, "[%p] CmiGetNonLocal begin %d{", cs, CmiMyPe());
-    CmiIdleLock_checkMessage(&cs->idle); 
-       
-#if DECOUPLE_BCAST_PROCESS
-#if !CMK_SMP
-    ProcessBroadcastMsg(0);
-#elif CMK_SMP_NO_COMMTHD
-    if(CmiMyRank()==0) ProcessBroadcastMsg(0);
-#endif
-#endif
-           
-    void *msg = PCQueuePop(cs->recv);
-    MACHSTATE3(3,"[%p] CmiGetNonLocal from queue %p with msg %p end }",CmiGetState(),(cs->recv), msg);    
-    return msg;
+/* ######End of functions related with communication progress ###### */
 
+void MachinePostNonLocalForLAPI() {
+    /* None here */
 }
 
 /**
- * TODO: What will be the effects if calling LAPI_Probe in the 
- * interrupt mode??? --Chao Mei 
+ * TODO: What will be the effects if calling LAPI_Probe in the
+ * interrupt mode??? --Chao Mei
  */
-
-/* user call to handle immediate message, since there is no ServerThread polling
-   messages (lapi does all the polling) every thread is authorized to process
-   immediate messages. If we are not in lapiInterruptMode check for progress.
-*/
-void CmiMachineProgressImpl(){
+/* Network progress function is used to poll the network when for
+   messages. This flushes receive buffers on some  implementations*/
+#if CMK_MACHINE_PROGRESS_DEFINED
+void CmiMachineProgressImpl() {
     if (!CsvAccess(lapiInterruptMode)) check_lapi(LAPI_Probe,(lapiContext));
 
 #if CMK_IMMEDIATE_MSG
-    MACHSTATE1(2, "[%p] Handling Immediate Message begin {",CmiGetState());
+    MACHSTATE1(2, "[%d] Handling Immediate Message begin {",CmiMyNode());
     CmiHandleImmediate();
-    MACHSTATE1(2, "[%p] Handling Immediate Message end }",CmiGetState());
+    MACHSTATE1(2, "[%d] Handling Immediate Message end }",CmiMyNode());
 #endif
 
-#if CMK_SMP && !CMK_SMP_NO_COMMTHD && DECOUPLE_BCAST_PROCESS
-    if(CmiMyRank()==CmiMyNodeSize()) ProcessBroadcastMsg(0);
+#if CMK_SMP && !CMK_SMP_NO_COMMTHD && CMK_OFFLOAD_BCAST_PROCESS
+    if (CmiMyRank()==CmiMyNodeSize()) processBcastQs(); /* FIXME ????????????????*/
 #endif
 }
+#endif
 
-/*TODO: does lapi provide any Barrrier related functions as DCMF provides??? --Chao Mei */
-/* Barrier needs to be implemented!!! -Chao Mei */
-/* These two barriers are only needed by CmiTimerInit to synchronize all the
-   threads. They do not need to provide a general barrier. */
-int CmiBarrier() {
-    return 0;
+/* ######Beginning of functions related with exiting programs###### */
+void DrainResourcesForLAPI() {
+    /* None here */
 }
-int CmiBarrierZero() {
-    return 0;
+
+void MachineExitForLAPI(void) {
+    check_lapi(LAPI_Gfence, (lapiContext));
+    check_lapi(LAPI_Term, (lapiContext));
+    exit(EXIT_SUCCESS);
 }
+/* ######End of functions related with exiting programs###### */
 
-/********************* MESSAGE SEND FUNCTIONS ******************/
 
-/** 
- * "deliverable": used to know if the message can be encoded 
- * into the destPE queue withtout duplication (for usage of 
- * SMP). If it has already been duplicated (and therefore is 
- * deliverable), we do not want to copy it again, while if it 
- * has been copied we must do it before enqueuing it. 
- *  
- * The general send function for all Cmi send functions.
+/* ######Beginning of functions related with starting programs###### */
+/**
+ *  Obtain the number of nodes, my node id, and consuming machine layer
+ *  specific arguments
  */
-void lapiSendFn(int destPE, int size, char *msg, scompl_hndlr_t *shdlr, void *sinfo, int deliverable) {
-    /* CmiState cs = CmiGetState(); */
-    CmiUInt2  rank, node;
-    lapi_xfer_t xfer_cmd;
+static void MachineInitForLAPI(int argc, char **argv, int *numNodes, int *myNodeID) {
 
-    MACHSTATE3(2,"lapiSendFn to destPE=%d with msg %p (isImm=%d) begin {",destPE,msg, CmiIsImmediate(msg));
-    MACHSTATE3(2, "inside lapiSendFn 1: size=%d, sinfo=%p, deliverable=%d", size, sinfo, deliverable);
-    
-#if ENSURE_MSG_PAIRORDER
-    MACHSTATE3(2, "inside lapiSendFn 2: msg src->dest (%d->%d), seqno=%d", CMI_MSG_SRCPE(msg), destPE, CMI_MSG_SEQNO(msg));
-#endif
+    lapi_info_t info;
 
-    node = CmiNodeOf(destPE);
-    /** 
-     *  The rank of the msg should be set before calling
-     *  lapiSendFn!!
-     *  The rank could be DGRAM_NODEMESSAGE which indicates
-     *  a node-level message.
-     */
-#if CMK_SMP
-    /*CMI_DEST_RANK(msg) = rank;*/
-    if (node == CmiMyNode())  {
-        rank = CmiRankOf(destPE);
-        MACHSTATE2(2,"[%p] inside lapiSendFn for intra-node message (%p)",CmiGetState(), msg);
-        if (deliverable) {
-            CmiPushPE(rank, msg);
-            /* the acknowledge of delivery must not be called */
-        } else {
-            CmiPushPE(rank, CopyMsg(msg, size));
-            /* acknowledge that the message has been delivered */
-            lapi_sh_info_t lapiInfo;
-            lapiInfo.src = node;
-            lapiInfo.reason = LAPI_SUCCESS;
-            (*shdlr)(&lapiContext, sinfo, &lapiInfo);
-        }
-        return;
-    }
-#endif
-    
-    MACHSTATE2(2, "Ready to call LAPI_Xfer with destPe=%d, destRank=%d",destPE,CMI_DEST_RANK(msg));
+    memset(&info,0,sizeof(info));
 
-    xfer_cmd.Am.Xfer_type = LAPI_AM_XFER;
-    xfer_cmd.Am.flags     = 0;
-    xfer_cmd.Am.tgt       = node;
-    xfer_cmd.Am.hdr_hdl   = lapiHeaderHandler;
-    xfer_cmd.Am.uhdr_len  = 0;
-    xfer_cmd.Am.uhdr      = NULL;
-    xfer_cmd.Am.udata     = msg;
-    xfer_cmd.Am.udata_len = size;
-    xfer_cmd.Am.shdlr     = shdlr;
-    xfer_cmd.Am.sinfo     = sinfo;
-    xfer_cmd.Am.tgt_cntr  = NULL;
-    xfer_cmd.Am.org_cntr  = NULL;
-    xfer_cmd.Am.cmpl_cntr = NULL;
+    /* Register error handler (redundant?) -- added by Chao Mei*/
+    info.err_hndlr = (LAPI_err_hndlr *)lapi_err_hndlr;
 
-    check_lapi(LAPI_Xfer,(lapiContext, &xfer_cmd));
+    /* Indicates the number of completion handler threads to create */
+    /* The number of completion hndlr thds will affect the atomic PCQueue operations!! */
+    /* NOTE: num_compl_hndlr_thr is obsolete now! --Chao Mei */
+    /* info.num_compl_hndlr_thr = 1; */
 
-    MACHSTATE(2,"} lapiSendFn end");
-}
+    check_lapi(LAPI_Init,(&lapiContext, &info));
 
-static void CmiSendSelf(char *msg) {
-    MACHSTATE1(3,"[%p] Sending itself a message {",CmiGetState());
+    /* It's a good idea to start with a fence,
+       because packets recv'd before a LAPI_Init are just dropped. */
+    check_lapi(LAPI_Gfence,(lapiContext));
 
-#if CMK_IMMEDIATE_MSG
-    if (CmiIsImmediate(msg)) {
-        MACHSTATE1(3, "[%p] Push Immediate Message begin {",CmiGetState());        
-        CmiPushImmediateMsg(msg);
-        MACHSTATE1(3, "[%p] Push Immediate Message end }",CmiGetState());        
-        return;
-    }
-#endif
-    CQdCreate(CpvAccess(cQdState), 1);
-    CdsFifo_Enqueue(CmiGetState()->localqueue,msg);
+    check_lapi(LAPI_Qenv,(lapiContext, TASK_ID, myNodeID));
+    check_lapi(LAPI_Qenv,(lapiContext, NUM_TASKS, numNodes));
 
-    MACHSTATE(3,"} Sending itself a message");
-}
+    /* Make polling as the default mode as real apps have better perf */
+    CsvAccess(lapiInterruptMode) = 0;
+    if (CmiGetArgFlag(argv,"+poll")) CsvAccess(lapiInterruptMode) = 0;
+    if (CmiGetArgFlag(argv,"+nopoll")) CsvAccess(lapiInterruptMode) = 1;
+
+    check_lapi(LAPI_Senv,(lapiContext, ERROR_CHK, lapiDebugMode));
+    check_lapi(LAPI_Senv,(lapiContext, INTERRUPT_SET, CsvAccess(lapiInterruptMode)));
 
-void CmiSyncSendFn(int destPE, int size, char *msg) {
-    CmiState cs = CmiGetState();
-    char *dupmsg = CopyMsg(msg, size);
-
-    MACHSTATE1(3,"[%p] Sending sync message begin {",CmiGetState());
-    CMI_BROADCAST_ROOT(dupmsg) = 0;
-    CMI_DEST_RANK(dupmsg) = CmiRankOf(destPE);
-
-    if (cs->pe==destPE) {
-        CmiSendSelf(dupmsg);
-    } else {
-    #if ENSURE_MSG_PAIRORDER
-        CMI_MSG_SRCPE(dupmsg) = CmiMyPe();        
-        CMI_MSG_SEQNO(dupmsg) = getNextMsgSeqNo(CpvAccess(p2pMsgSeqInfo).nextMsgSeqNo, destPE);
-        setNextMsgSeqNo(CpvAccess(p2pMsgSeqInfo).nextMsgSeqNo, destPE, CMI_MSG_SEQNO(dupmsg));
-    #endif
-
-    #if ENABLE_CONVERSE_QD
-        CQdCreate(CpvAccess(cQdState), 1);
-    #endif
-        lapiSendFn(destPE, size, dupmsg, ReleaseMsg, dupmsg, 1);
+    if (*myNodeID == 0) {
+        printf("Running lapi in interrupt mode: %d\n", CsvAccess(lapiInterruptMode));
+        printf("Running lapi with %d completion handler threads.\n", info.num_compl_hndlr_thr);
     }
-    MACHSTATE(3,"} Sending sync message end");
-}
 
-int CmiAsyncMsgSent(CmiCommHandle handle) {
-    return (*((int *)handle) == 0)?1:0;
-}
+    /**
+     *  Associate PumpMsgsBegin with var "lapiHeaderHandler". Then inside Xfer calls,
+     *  lapiHeaderHandler could be used to indicate the callback
+     *  instead of PumpMsgsBegin --Chao Mei
+     */
+    check_lapi(LAPI_Addr_set,(lapiContext,(void *)PumpMsgsBegin,lapiHeaderHandler));
 
-void CmiReleaseCommHandle(CmiCommHandle handle) {
-#ifndef CMK_OPTIMIZE
-    if (*((int *)handle) != 0) CmiAbort("Released a CmiCommHandle not free!");
+    if (CmiGetArgFlag(argv,"++debug")) {  /*Pause so user has a chance to start and attach debugger*/
+        printf("CHARMDEBUG> Processor %d has PID %d\n",*myNodeID,getpid());
+        if (!CmiGetArgFlag(argv,"++debug-no-pause"))
+            sleep(30);
+    }
+
+#if ENSURE_MSG_PAIRORDER
+    cmplHdlrThdLock = CmiCreateLock();
 #endif
-    free(handle);
 }
 
-/* the CmiCommHandle returned is a pointer to the location of an int. When it is
-   set to 1 the message is available. */
-CmiCommHandle CmiAsyncSendFn(int destPE, int size, char *msg) {
-    MACHSTATE1(3,"[%p] Sending async message begin {",CmiGetState());
-    void *handle;
-    CmiState cs = CmiGetState();
-    CMI_BROADCAST_ROOT(msg) = 0;
-    CMI_DEST_RANK(msg) = CmiRankOf(destPE);
-
-    /* if we are the destination, send ourself a copy of the message */
-    if (cs->pe==destPE) {
-        CmiSendSelf(CopyMsg(msg, size));
-        MACHSTATE(3,"} Sending async message end");
-        return 0;
-    }
-
-    handle = malloc(sizeof(int));
-    *((int *)handle) = 1;
+#if MACHINE_DEBUG_LOG
+CpvDeclare(FILE *, debugLog);
+#endif
 
 #if ENSURE_MSG_PAIRORDER
-    CMI_MSG_SRCPE(msg) = CmiMyPe();    
-    CMI_MSG_SEQNO(msg) = getNextMsgSeqNo(CpvAccess(p2pMsgSeqInfo).nextMsgSeqNo, destPE);
-    setNextMsgSeqNo(CpvAccess(p2pMsgSeqInfo).nextMsgSeqNo, destPE, CMI_MSG_SEQNO(msg));
+static void initMsgOrderInfo(MsgOrderInfo *info) {
+    int i;
+    int totalPEs = CmiNumPes();
+#if CMK_SMP && CMK_OFFLOAD_BCAST_PROCESS
+    /* the comm thread will also access such info */
+    totalPEs += CmiNumNodes();
 #endif
+    info->nextMsgSeqNo = malloc(totalPEs*sizeof(int));
+    memset(info->nextMsgSeqNo, 0, totalPEs*sizeof(int));
 
-#if ENABLE_CONVERSE_QD
-    CQdCreate(CpvAccess(cQdState), 1);
-#endif
-    lapiSendFn(destPE, size, msg, DeliveredMsg, handle, 0);
-    /* the message may have been duplicated and already delivered if we are in SMP
-       mode and the destination is on the same node, but there is no optimized
-       check for that. */
-    MACHSTATE(3,"} Sending async message end");
-    return handle;
-}
-
-void CmiFreeSendFn(int destPE, int size, char *msg) {
-    MACHSTATE1(3,"[%p] Sending sync free message begin {",CmiGetState());
-    CmiState cs = CmiGetState();
-    CMI_BROADCAST_ROOT(msg) = 0;
-    CMI_DEST_RANK(msg) = CmiRankOf(destPE);
-
-    if (cs->pe==destPE) {
-        CmiSendSelf(msg);
-    } else {
-    #if ENSURE_MSG_PAIRORDER
-        CMI_MSG_SRCPE(msg) = CmiMyPe();        
-        CMI_MSG_SEQNO(msg) = getNextMsgSeqNo(CpvAccess(p2pMsgSeqInfo).nextMsgSeqNo, destPE);
-        setNextMsgSeqNo(CpvAccess(p2pMsgSeqInfo).nextMsgSeqNo, destPE, CMI_MSG_SEQNO(msg));
-    #endif
-    #if ENABLE_CONVERSE_QD
-        CQdCreate(CpvAccess(cQdState), 1);
-    #endif        
-        lapiSendFn(destPE, size, msg, ReleaseMsg, msg, 1);
-        /*CmiAsyncSendFn(destPE, size, msg);*/
-    }
-    MACHSTATE(3,"} Sending sync free message end");
-}
-
-/* ===========Node level p2p send functions============= */
-#if CMK_NODE_QUEUE_AVAILABLE
-static void CmiSendNodeSelf(char *msg) {
-    CmiState cs;
-    MACHSTATE1(3,"[%p] Sending itself a node message {",CmiGetState());
-
-#if CMK_IMMEDIATE_MSG
-    if (CmiIsImmediate(msg)) {
-        MACHSTATE1(3, "[%p] Push Immediate Message {",CmiGetState());
-        CMI_DEST_RANK(msg) = 0;
-        CmiPushImmediateMsg(msg);
-        MACHSTATE(3, "} Push Immediate Message end");
-        return;
-    }
-#endif
-    CQdCreate(CpvAccess(cQdState), 1);
-    CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
-    PCQueuePush(CsvAccess(NodeState).NodeRecv, msg);
-    CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
-
-    cs=CmiGetStateN(0);
-    CmiIdleLock_addMessage(&cs->idle);
-
-    MACHSTATE(3,"} Sending itself a node message");
-}
-
-/*TODO: not sure whether the in-order delivery affects for node messages?? --Chao Mei */
-void CmiSyncNodeSendFn(int destNode, int size, char *msg) {
-    char *dupmsg = CopyMsg(msg, size);
-
-    MACHSTATE1(3,"[%p] Sending sync node message begin {",CmiGetState());
-    CMI_BROADCAST_ROOT(dupmsg) = 0;
-    CMI_DEST_RANK(dupmsg) = DGRAM_NODEMESSAGE;
-
-    if (CmiMyNode()==destNode) {
-        CmiSendNodeSelf(dupmsg);
-    } else {
-    #if ENABLE_CONVERSE_QD
-        CQdCreate(CpvAccess(cQdState), 1);
-    #endif
-        lapiSendFn(CmiNodeFirst(destNode), size, dupmsg, ReleaseMsg, dupmsg, 1);
-    }
-    MACHSTATE(3,"} Sending sync node message end");
-}
-
-CmiCommHandle CmiAsyncNodeSendFn(int destNode, int size, char *msg) {
-    void *handle;
-    CMI_BROADCAST_ROOT(msg) = 0;
-    CMI_DEST_RANK(msg) = DGRAM_NODEMESSAGE;
-
-    MACHSTATE1(3,"[%p] Sending async node message begin {",CmiGetState());
-    /* if we are the destination, send ourself a copy of the message */
-    if (CmiMyNode()==destNode) {
-        CmiSendNodeSelf(CopyMsg(msg, size));
-        MACHSTATE(3,"} Sending async node message end");
-        return 0;
-    }
-
-    handle = malloc(sizeof(int));
-    *((int *)handle) = 1;
-
-#if ENABLE_CONVERSE_QD
-    CQdCreate(CpvAccess(cQdState), 1);
-#endif
-    lapiSendFn(CmiNodeFirst(destNode), size, msg, DeliveredMsg, handle, 0);
-    /* the message may have been duplicated and already delivered if we are in SMP
-       mode and the destination is on the same node, but there is no optimized
-       check for that. */
-    MACHSTATE(3,"} Sending async node message end");
-    return handle;
-
-}
-
-void CmiFreeNodeSendFn(int destNode, int size, char *msg) {
-    CMI_BROADCAST_ROOT(msg) = 0;
-    CMI_DEST_RANK(msg) = DGRAM_NODEMESSAGE;
-
-    MACHSTATE1(3,"[%p] Sending sync free node message begin {",CmiGetState());
-    if (CmiMyNode()==destNode) {
-        CmiSendNodeSelf(msg);
-    } else {
-    #if ENABLE_CONVERSE_QD
-        CQdCreate(CpvAccess(cQdState), 1);
-    #endif
-        lapiSendFn(CmiNodeFirst(destNode), size, msg, ReleaseMsg, msg, 1);
-    }
-    MACHSTATE(3,"} Sending sync free node message end");
-}
-#endif
-
-/*********************** BROADCAST FUNCTIONS **********************/
-#if CMK_SMP
-/** 
-  * Sending msgs to cores in the same node 
-  * "includeSelf" indicates whether the msg should be sent to 
-  * the proc of rank CMI_DEST_RANK(msg) 
-  * --Chao mei 
-  *  
-  */
-void SendMsgToPeers(int size, char *msg, int includeSelf){
-    if(includeSelf) {
-        int i;
-        for(i=0; i<CmiMyNodeSize(); i++) {
-            char *dupmsg = CopyMsg(msg,size);
-            CmiPushPE(i,dupmsg);
-        }
-    }else{
-        int i;
-        int excludeRank = CMI_DEST_RANK(msg);
-        for(i=excludeRank+1; i<CmiMyNodeSize(); i++) {
-            char *dupmsg = CopyMsg(msg,size);
-            CmiPushPE(i,dupmsg);
-        }
-        for(i=0; i<excludeRank; i++) {
-            char *dupmsg = CopyMsg(msg,size);
-            CmiPushPE(i,dupmsg);
-        }
-    }
-}
-#endif
-
-/** 
- * SendSpanningChildren only sends inter-node messages. The 
- * intra-node messages are delivered via SendMsgToPeers if it is 
- * in SMP mode. 
- */
-#if ENSURE_MSG_PAIRORDER
-void SendSpanningChildren(int size, char *msg, int srcPe, int *seqNoArr){
-#else
-void SendSpanningChildren(int size, char *msg) {
-#endif
-    int startproc = CMI_BROADCAST_ROOT(msg)-1;
-    int startnode = CmiNodeOf(startproc);
-    int i, rp;
-    char *dupmsg;
-
-    CmiAssert(startnode>=0 && startnode<CmiNumNodes());
-    
-    MACHSTATE3(3, "[%p] SendSpanningChildren on proc=%d with start proc %d begin {",CmiGetState(), CmiMyPe(), startproc);  
-    /* rp is the relative node id from start node */  
-    rp = CmiMyNode() - startnode;
-    if(rp<0) rp += CmiNumNodes();
-    for (i=1; i<=BROADCAST_SPANNING_FACTOR; i++) {
-        int p = BROADCAST_SPANNING_FACTOR*rp + i;
-        if (p > CmiNumNodes() - 1) break;
-        p += startnode;
-        p = p%CmiNumNodes();
-        
-#if CMK_BROADCAST_USE_CMIREFERENCE
-        CmiReference(msg);
-        lapiSendFn(CmiNodeFirst(p), size, msg, ReleaseMsg, msg, 0);
-#else
-        dupmsg = CopyMsg(msg, size);
-    #if ENSURE_MSG_PAIRORDER
-        CMI_MSG_SRCPE(dupmsg) = srcPe;
-        CMI_MSG_SEQNO(dupmsg) = getNextMsgSeqNo(seqNoArr, CmiNodeFirst(p));
-        setNextMsgSeqNo(seqNoArr, CmiNodeFirst(p), CMI_MSG_SEQNO(dupmsg));
-    #endif
-        lapiSendFn(CmiNodeFirst(p), size, dupmsg, ReleaseMsg, dupmsg, 1);
-#endif
-    }    
-
-    MACHSTATE3(3, "[%p] SendSpanningChildren on proc=%d with start proc %d end }",CmiGetState(), CmiMyPe(), startproc);    
-}
-
-/* Return the smallest integer that is larger than or equal to log2(i), e.g CmiLog2(14) = 4*/
-static int CmiLog2 (int i) {
-    int m;
-    for (m=0; i>(1<<m); ++m);
-    return m;
-}
-
-/* send msg along the hypercube in broadcast. (Chao Mei) */
-#if ENSURE_MSG_PAIRORDER
-void SendHypercube(int size, char *msg, int srcPe, int *seqNoArr){
-#else
-void SendHypercube(int size, char *msg) {
-#endif
-    int i, tmp, cnt;   
-    char *dupmsg;
-    int dims = 0;
-    int startproc = CMI_BROADCAST_ROOT(msg)-1;
-    int startnode = CmiNodeOf(startproc);
-    /* relative proc id to startnode */
-    int rp = CmiMyNode() - startnode;    
-    if(rp < 0) rp += CmiNumNodes();
-
-       /* dims = ceil(log2(CmiNumNodes)) except when #nodes is 1 */
-       tmp = CmiNumNodes()-1;
-       for(tmp=CmiNumNodes()-1; tmp>0; tmp=tmp>>1) dims++;
-       if(CmiNumNodes()==1) dims=1;
-
-       cnt=0; tmp=rp;
-       for(i=0; i<dims; i++, cnt++){
-               if(tmp & 1 == 1) break;
-               tmp = tmp >> 1;
-       }
-       
-    MACHSTATE3(3, "[%p] SendHypercube on proc=%d with start proc %d begin {",CmiGetState(), CmiMyPe(), startproc);    
-    for(i=cnt-1; i>=0; i--) { 
-        /* destnode is still the relative node id from startnode */
-        int destnode = rp + (1<<i);
-        if(destnode > CmiNumNodes()-1) continue; 
-        
-        destnode += startnode;
-        destnode = destnode % CmiNumNodes();
-
-        CmiAssert(destnode != CmiMyNode());
-               
-#if CMK_BROADCAST_USE_CMIREFERENCE
-        CmiReference(msg);
-        lapiSendFn(CmiNodeFirst(destnode), size, msg, ReleaseMsg, msg, 0);
-#else
-        dupmsg = CopyMsg(msg, size);
-    #if ENSURE_MSG_PAIRORDER
-        CMI_MSG_SRCPE(dupmsg) = srcPe;
-        CMI_MSG_SEQNO(dupmsg) = getNextMsgSeqNo(seqNoArr, CmiNodeFirst(destnode));
-        setNextMsgSeqNo(seqNoArr, CmiNodeFirst(destnode), CMI_MSG_SEQNO(dupmsg));
-    #endif
-        lapiSendFn(CmiNodeFirst(destnode), size, dupmsg, ReleaseMsg, dupmsg, 1);
-#endif
-    }    
-    MACHSTATE3(3, "[%p] SendHypercube on proc=%d with start proc %d end }",CmiGetState(), CmiMyPe(), startproc);    
-}
-
-void CmiSyncBroadcastGeneralFn(int size, char *msg) {    /* ALL_EXCEPT_ME  */
-    int i, rank;
-    MACHSTATE3(3,"[%p] Sending sync broadcast message %p with size %d begin {",CmiGetState(), msg, size);
-
-#if ENABLE_CONVERSE_QD
-    CQdCreate(CpvAccess(cQdState), CmiNumPes()-1);
-#endif
-
-#if CMK_BROADCAST_SPANNING_TREE
-    CMI_BROADCAST_ROOT(msg) = CmiMyPe()+1;
-    /** 
-     * since the broadcast msg will be relayed separately on 
-     * remote procs by SendSpanningChildren, the actual msg size 
-     * needs to be recorded in the header for proper memory 
-     * allocation. E.g. the bcast msg is relayed in PumpMsgComplete.
-     * But at that time, the actual msg size is not known if the 
-     * filed inside the msg header is not set. The unknown actual 
-     * msg size will cause the relay of msg fail because CopyMsg 
-     * doesn't have a correct msg size input!! -Chao Mei 
-     */
-    CMI_MSG_SIZE(msg) = size;
-    /* node-aware spanning tree, so bcast msg is always delivered to the first core on each node */
-    CMI_DEST_RANK(msg) = 0;
-#if ENSURE_MSG_PAIRORDER    
-    SendSpanningChildren(size, msg, CmiMyPe(), CpvAccess(bcastMsgSeqInfo).nextMsgSeqNo);
-#else
-    SendSpanningChildren(size, msg);
-#endif
-        
-#if CMK_SMP
-    CMI_DEST_RANK(msg) = CmiMyRank();
-    SendMsgToPeers(size, msg, 0);
-#endif
-
-#elif CMK_BROADCAST_HYPERCUBE 
-   
-    CMI_BROADCAST_ROOT(msg) = CmiMyPe()+1;
-    CMI_MSG_SIZE(msg) = size;
-    CMI_DEST_RANK(msg) = 0;    
-
-#if ENSURE_MSG_PAIRORDER    
-    SendHypercube(size, msg, CmiMyPe(), CpvAccess(bcastMsgSeqInfo).nextMsgSeqNo);
-#else
-    SendHypercube(size, msg);
-#endif
-      
-#if CMK_SMP
-    CMI_DEST_RANK(msg) = CmiMyRank();
-    SendMsgToPeers(size, msg, 0);
-#endif
-
-#else
-    CmiState cs = CmiGetState();
-    char *dupmsg;
-
-    CMI_BROADCAST_ROOT(msg) = 0;
-#if CMK_BROADCAST_USE_CMIREFERENCE
-    for (i=cs->pe+1; i<CmiNumPes(); i++) {
-        CmiReference(msg);
-        lapiSendFn(i, size, msg, ReleaseMsg, msg, 0);
-        /*CmiSyncSendFn(i, size, msg) ;*/
-    }
-    for (i=0; i<cs->pe; i++) {
-        CmiReference(msg);
-        lapiSendFn(i, size, msg, ReleaseMsg, msg, 0);
-        /*CmiSyncSendFn(i, size,msg) ;*/
-    }
-#else
-#if ENSURE_MSG_PAIRORDER
-    CMI_MSG_SRCPE(msg) = CmiMyPe();
-#endif
-    for (i=cs->pe+1; i<CmiNumPes(); i++) {
-        dupmsg = CopyMsg(msg, size);
-        CMI_DEST_RANK(dupmsg) = CmiRankOf(i);
-    #if ENSURE_MSG_PAIRORDER        
-        CMI_MSG_SEQNO(dupmsg) = getNextMsgSeqNo(CpvAccess(p2pMsgSeqInfo).nextMsgSeqNo, i);
-        setNextMsgSeqNo(CpvAccess(p2pMsgSeqInfo).nextMsgSeqNo, i, CMI_MSG_SEQNO(dupmsg));
-    #endif
-        lapiSendFn(i, size, dupmsg, ReleaseMsg, dupmsg, 1);        
-    }
-    for (i=0; i<cs->pe; i++) {
-        dupmsg = CopyMsg(msg, size);
-    #if ENSURE_MSG_PAIRORDER        
-        CMI_MSG_SEQNO(dupmsg) = getNextMsgSeqNo(CpvAccess(p2pMsgSeqInfo).nextMsgSeqNo, i);
-        setNextMsgSeqNo(CpvAccess(p2pMsgSeqInfo).nextMsgSeqNo, i, CMI_MSG_SEQNO(dupmsg));
-    #endif
-        CMI_DEST_RANK(dupmsg) = CmiRankOf(i);
-        lapiSendFn(i, size, dupmsg, ReleaseMsg, dupmsg, 1);        
-    }
-#endif
-#endif
-
-    MACHSTATE(3,"} Sending sync broadcast message end");
-}
-
-CmiCommHandle CmiAsyncBroadcastGeneralFn(int size, char *msg) {
-#if ENSURE_MSG_PAIRORDER
-    /* Not sure how to add the msg seq no for async broadcast messages --Chao Mei */
-    /* so abort here ! */
-    CmiAssert(0);
-    return 0;
-#else
-    CmiState cs = CmiGetState();
-    int i, rank;
-#if ENABLE_CONVERSE_QD
-    CQdCreate(CpvAccess(cQdState), CmiNumPes()-1);
-#endif
-    MACHSTATE1(3,"[%p] Sending async broadcast message from {",CmiGetState());
-    CMI_BROADCAST_ROOT(msg) = 0;
-    void *handle = malloc(sizeof(int));
-    *((int *)handle) = CmiNumPes()-1;
-
-    for (i=cs->pe+1; i<CmiNumPes(); i++) {
-        CMI_DEST_RANK(msg) = CmiRankOf(i);
-        lapiSendFn(i, size, msg, DeliveredMsg, handle, 0);
-    }
-    for (i=0; i<cs->pe; i++) {
-        CMI_DEST_RANK(msg) = CmiRankOf(i);
-        lapiSendFn(i, size, msg, DeliveredMsg, handle, 0);
-    }
-
-    MACHSTATE(3,"} Sending async broadcast message end");
-    return handle;
-#endif
-}
-
-void CmiSyncBroadcastFn(int size, char *msg) {
-    /*CMI_DEST_RANK(msg) = 0;*/
-    CmiSyncBroadcastGeneralFn(size, msg);
-}
-
-CmiCommHandle CmiAsyncBroadcastFn(int size, char *msg) {
-    /*CMI_DEST_RANK(msg) = 0;*/
-    return CmiAsyncBroadcastGeneralFn(size, msg);
-}
-
-void CmiFreeBroadcastFn(int size, char *msg) {
-    CmiSyncBroadcastFn(size,msg);
-    CmiFree(msg);
-}
-
-void CmiSyncBroadcastAllFn(int size, char *msg) {       /* All including me */
-    CmiSendSelf(CopyMsg(msg, size));
-    CmiSyncBroadcastFn(size, msg);
-}
-
-CmiCommHandle CmiAsyncBroadcastAllFn(int size, char *msg) {
-    CmiSendSelf(CopyMsg(msg, size));
-    return CmiAsyncBroadcastFn(size, msg);
-}
-
-void CmiFreeBroadcastAllFn(int size, char *msg) {       /* All including me */
-    CmiSendSelf(CopyMsg(msg, size));
-    CmiSyncBroadcastFn(size, msg);
-    CmiFree(msg);
-}
-
-#if CMK_NODE_QUEUE_AVAILABLE
-void SendSpanningChildrenNode(int size, char *msg){    
-    int startnode = -CMI_BROADCAST_ROOT(msg)-1;    
-    int i, rp;
-    char *dupmsg;
-
-    MACHSTATE3(2, "[%p] SendSpanningChildrenNode on node %d with startnode %d", CmiGetState(), CmiMyNode(), startnode);
-    CmiAssert(startnode>=0 && startnode<CmiNumNodes());
-        
-    rp = CmiMyNode() - startnode;
-    if (rp<0) rp+=CmiNumNodes();        
-    for (i=1; i<=BROADCAST_SPANNING_FACTOR; i++) {
-        int p = BROADCAST_SPANNING_FACTOR*rp + i;
-        if (p > CmiNumNodes() - 1) break;
-        p += startnode;
-        p = p%CmiNumNodes();
-        
-#if CMK_BROADCAST_USE_CMIREFERENCE
-        CmiReference(msg);
-        lapiSendFn(CmiNodeFirst(p), size, msg, ReleaseMsg, msg, 0);
-#else
-        dupmsg = CopyMsg(msg, size);
-        lapiSendFn(CmiNodeFirst(p), size, dupmsg, ReleaseMsg, dupmsg, 1);
-#endif
-    }
-    MACHSTATE3(3, "[%p] SendSpanningChildrenNode on node=%d with start node %d end }",CmiGetState(), CmiMyNode(), startnode);
-}
-
-/* send msg along the hypercube in broadcast. (Chao Mei) */
-void SendHypercubeNode(int size, char *msg) {
-    int i, dist, tmp, cnt;   
-    char *dupmsg;
-    int dims = 0;
-    int startnode = -CMI_BROADCAST_ROOT(msg)-1;
-    int rp = CmiMyNode() - startnode;    
-    if(rp < 0) rp += CmiNumNodes();
-    dist = rp;
-
-       /* dims = ceil(log2(CmiNumNodes)) except when #nodes is 1 */    
-       tmp = CmiNumNodes()-1;
-       for(tmp=CmiNumNodes()-1; tmp>0; tmp=tmp>>1) dims++;
-       if(CmiNumNodes()==1) dims=1;
-       
-       cnt=0; tmp=rp;
-       for(i=0; i<dims; i++, cnt++){
-               if(tmp & 1 == 1) break;
-               tmp = tmp >> 1;
-       }
-       
-    MACHSTATE3(3, "[%p] SendHypercubeNode on node=%d with start node %d begin {",CmiGetState(), CmiMyNode(), startnode);
-    for(i=cnt-1; i>=0; i--) {         
-        int destnode = rp + (1<<i);
-        if(destnode > CmiNumNodes()-1) continue;
-        
-        destnode += startnode;
-        destnode = destnode % CmiNumNodes();        
-                        
-        CmiAssert(destnode != CmiMyNode());
-
-#if CMK_BROADCAST_USE_CMIREFERENCE
-        CmiReference(msg);
-        lapiSendFn(CmiNodeFirst(destnode), size, msg, ReleaseMsg, msg, 0);
-#else
-        dupmsg = CopyMsg(msg, size);
-        lapiSendFn(CmiNodeFirst(destnode), size, dupmsg, ReleaseMsg, dupmsg, 1);
-#endif 
-    }
-    MACHSTATE3(3, "[%p] SendHypercubeNode on node=%d with start node %d end }",CmiGetState(), CmiMyNode(), startnode);  
-}
-
-void CmiSyncNodeBroadcastGeneralFn(int size, char *msg) {    /* ALL_EXCEPT_THIS_NODE  */     
-#if ENABLE_CONVERSE_QD
-    CQdCreate(CpvAccess(cQdState), CmiNumNodes()-1);
-#endif
-#if CMK_BROADCAST_SPANNING_TREE
-
-    MACHSTATE1(3,"[%p] Sending sync node broadcast message (use spanning tree) begin {",CmiGetState());
-    CMI_BROADCAST_ROOT(msg) = -(CmiMyNode()+1);
-    CMI_MSG_SIZE(msg) = size;
-    CMI_DEST_RANK(msg) = DGRAM_NODEMESSAGE;    
-    SendSpanningChildrenNode(size, msg);
-    
-#elif CMK_BROADCAST_HYPERCUBE
-
-    MACHSTATE1(3,"[%p] Sending sync node broadcast message (use Hypercube) begin {",CmiGetState());
-    CMI_BROADCAST_ROOT(msg) = -(CmiMyNode()+1);
-    CMI_MSG_SIZE(msg) = size;
-    CMI_DEST_RANK(msg) = DGRAM_NODEMESSAGE;    
-    SendHypercubeNode(size, msg);
-    
-#else      
-    char *dupmsg;
-    int i;
-    MACHSTATE1(3,"[%p] Sending sync node broadcast message (use p2p) begin {",CmiGetState());
-
-    CMI_BROADCAST_ROOT(msg) = 0;
-    CMI_DEST_RANK(msg) = DGRAM_NODEMESSAGE;
-    for (i=CmiMyNode()+1; i<CmiNumNodes(); i++) {
-        dupmsg = CopyMsg(msg, size);        
-        lapiSendFn(CmiNodeFirst(i), size, dupmsg, ReleaseMsg, dupmsg, 1);        
-    }
-    for (i=0; i<CmiMyNode(); i++) {
-        dupmsg = CopyMsg(msg, size);        
-        lapiSendFn(CmiNodeFirst(i), size, dupmsg, ReleaseMsg, dupmsg, 1);        
-    }
-#endif
-    MACHSTATE(3,"} Sending sync node broadcast message end");
-}
-
-CmiCommHandle CmiAsyncNodeBroadcastGeneralFn(int size, char *msg) {
-    int i;
-
-#if ENABLE_CONVERSE_QD
-    CQdCreate(CpvAccess(cQdState), CmiNumNodes()-1);
-#endif
-
-    MACHSTATE1(3,"[%p] Sending async node broadcast message from {",CmiGetState());
-    CMI_BROADCAST_ROOT(msg) = 0;
-    CMI_DEST_RANK(msg) =DGRAM_NODEMESSAGE;
-    void *handle = malloc(sizeof(int));
-    *((int *)handle) = CmiNumNodes()-1;
-    for (i=CmiMyNode()+1; i<CmiNumNodes(); i++) {        
-        lapiSendFn(CmiNodeFirst(i), size, msg, DeliveredMsg, handle, 0);
-    }
-    for (i=0; i<CmiMyNode(); i++) {        
-        lapiSendFn(CmiNodeFirst(i), size, msg, DeliveredMsg, handle, 0);
-    }
-
-    MACHSTATE(3,"} Sending async broadcast message end");
-    return handle;
-}
-
-void CmiSyncNodeBroadcastFn(int size, char *msg) {
-    /*CMI_DEST_RANK(msg) = DGRAM_NODEMESSAGE;*/
-    CmiSyncNodeBroadcastGeneralFn(size, msg);
-}
-
-CmiCommHandle CmiAsyncNodeBroadcastFn(int size, char *msg) {
-    /*CMI_DEST_RANK(msg) = DGRAM_NODEMESSAGE;*/
-    return CmiAsyncNodeBroadcastGeneralFn(size, msg);
-}
-
-void CmiFreeNodeBroadcastFn(int size, char *msg) {
-    CmiSyncNodeBroadcastFn(size, msg);
-    CmiFree(msg);
-}
-
-void CmiSyncNodeBroadcastAllFn(int size, char *msg) {
-    CmiSendNodeSelf(CopyMsg(msg, size));
-    CmiSyncNodeBroadcastFn(size, msg);
-}
-
-CmiCommHandle CmiAsyncNodeBroadcastAllFn(int size, char *msg) {
-    CmiSendNodeSelf(CopyMsg(msg, size));
-    return CmiAsyncNodeBroadcastFn(size, msg);
-}
-
-void CmiFreeNodeBroadcastAllFn(int size, char *msg) {
-    CmiSendNodeSelf(CopyMsg(msg, size));
-    CmiSyncNodeBroadcastFn(size, msg);
-    CmiFree(msg);
-}
-#endif
-
-#if ! CMK_MULTICAST_LIST_USE_COMMON_CODE
-void CmiSyncListSendFn(int, int *, int, char*) {
-
-}
-
-CmiCommHandle CmiAsyncListSendFn(int, int *, int, char*) {
-
-}
-
-void CmiFreeListSendFn(int, int *, int, char*) {
-
-}
-#endif
-
-#if ! CMK_VECTOR_SEND_USES_COMMON_CODE
-void CmiSyncVectorSend(int, int, int *, char **) {
-
-}
-
-CmiCommHandle CmiAsyncVectorSend(int, int, int *, char **) {
+    info->expectedMsgSeqNo = malloc(totalPEs*sizeof(int));
+    memset(info->expectedMsgSeqNo, 0, totalPEs*sizeof(int));
 
-}
+    info->oooMsgBuffer = malloc(totalPEs*sizeof(void **));
+    memset(info->oooMsgBuffer, 0, totalPEs*sizeof(void **));
 
-void CmiSyncVectorSendAndFree(int, int, int *, char **) {
+    info->oooMaxOffset = malloc(totalPEs*sizeof(unsigned char));
+    memset(info->oooMaxOffset, 0, totalPEs*sizeof(unsigned char));
 
+    info->CUR_WINDOW_SIZE = malloc(totalPEs*sizeof(unsigned char));
+    for (i=0; i<totalPEs; i++) info->CUR_WINDOW_SIZE[i] = INIT_WINDOW_SIZE;
 }
 #endif
 
-
-/************************** MAIN (non comm related functions) ***********************************/
-
-void ConverseExit(void) {
-    MACHSTATE2(2, "[%d-%p] entering ConverseExit begin {",CmiMyPe(),CmiGetState());
-    
-    /* TODO: Is it necessary to drive the network progress here?? -Chao Mei */
-
-    /* A barrier excluding the comm thread if present */
-    CmiNodeBarrier();
-
-#if CMK_SMP && !CMK_SMP_NO_COMMTHD
-    /* Signal the comm thd to exit now! */
-    if(CmiMyRank()==0) {
-        commThdExit = 1;
-    }
-#endif
-
-    ConverseCommonExit();
-
-#if (CMK_DEBUG_MODE || CMK_WEB_MODE || NODE_0_IS_CONVHOST)
-    if (CmiMyPe() == 0) CmiPrintf("End of program\n");
-#endif
-
-    CmiNodeBarrier();
-
-    MACHSTATE2(2, "[%d-%p] ConverseExit end }",CmiMyPe(),CmiGetState());
-#if CMK_SMP
-    if(CmiMyRank()==0) {
-        check_lapi(LAPI_Gfence, (lapiContext));
-        check_lapi(LAPI_Term, (lapiContext));
-        exit(EXIT_SUCCESS);
-    }else{
-        pthread_exit(NULL);
-    }
-#else
-    check_lapi(LAPI_Gfence, (lapiContext));      
-    check_lapi(LAPI_Term, (lapiContext));
-    exit(EXIT_SUCCESS);
-#endif
-}
-
-/* Those be Cpved?? --Chao Mei */
-static char     **Cmi_argv;
-static CmiStartFn Cmi_startfn;   /* The start function */
-static int        Cmi_usrsched;  /* Continue after start function finishes? */
-
-/** 
- *  CmiNotifyIdle is used in non-SMP mode when the proc is idle.
- *  When the proc is idle, the LAPI_Probe is called to make
- *  network progress.
- *  
- *  While in SMP mode, CmiNotifyStillIdle and CmiNotifyBeginIdle
- *  are used. Particularly, when idle, the frequency of calling
- *  lapi_probe (network progress) is given by "sleepMs"
- */
-void CmiNotifyIdle(void) {    
-    AdvanceCommunication();
-    CmiYield();
-}
-
-typedef struct {
-    int sleepMs; /*Milliseconds to sleep while idle*/
-    int nIdles; /*Number of times we've been idle in a row*/
-    CmiState cs; /*Machine state*/
-} CmiIdleState;
-
-static CmiIdleState *CmiNotifyGetState(void) {
-    CmiIdleState *s=(CmiIdleState *)malloc(sizeof(CmiIdleState));
-    s->sleepMs=0;
-    s->nIdles=0;
-    s->cs=CmiGetState();
-    return s;
-}
-
-static void CmiNotifyBeginIdle(CmiIdleState *s) {
-    s->sleepMs=0;
-    s->nIdles=0;
-}
-
-#define SPINS_BEFORE_SLEEP     20
-
-static void CmiNotifyStillIdle(CmiIdleState *s) {
-    MACHSTATE2(2,"[%p] still idle (%d) begin {",CmiGetState(),CmiMyPe());
-    s->nIdles++;
-    if (s->nIdles>SPINS_BEFORE_SLEEP) { /*Start giving some time back to the OS*/
-        s->sleepMs+=2;
-        if (s->sleepMs>10) s->sleepMs=10;
-    }
-    if (s->sleepMs>0) {
-        MACHSTATE1(2,"idle sleep (%d) {",CmiMyPe());
-        CmiIdleLock_sleep(&s->cs->idle,s->sleepMs);
-        MACHSTATE1(2,"} idle sleep (%d)",CmiMyPe());
-    }
-
-    AdvanceCommunication();
-    
-    MACHSTATE1(2,"still idle (%d) end }",CmiMyPe());
-}
-
-#if MACHINE_DEBUG_LOG
-CpvDeclare(FILE *, debugLog);
-#endif
-
-
-#if ENSURE_MSG_PAIRORDER
-static void initMsgOrderInfo(MsgOrderInfo *info){
-    int i;
-    info->nextMsgSeqNo = malloc(CmiNumPes()*sizeof(int));
-    memset(info->nextMsgSeqNo, 0, CmiNumPes()*sizeof(int));
-    
-    info->expectedMsgSeqNo = malloc(CmiNumPes()*sizeof(int));
-    memset(info->expectedMsgSeqNo, 0, CmiNumPes()*sizeof(int));
-    
-    info->oooMsgBuffer = malloc(CmiNumPes()*sizeof(void **));
-    memset(info->oooMsgBuffer, 0, CmiNumPes()*sizeof(void **));
-    
-    info->oooMaxOffset = malloc(CmiNumPes()*sizeof(unsigned char));
-    memset(info->oooMaxOffset, 0, CmiNumPes()*sizeof(unsigned char));
-
-    info->CUR_WINDOW_SIZE = malloc(CmiNumPes()*sizeof(unsigned char));
-    for(i=0; i<CmiNumPes(); i++) info->CUR_WINDOW_SIZE[i] = INIT_WINDOW_SIZE;
-}
-#endif
-
-/* Only called from communication thread in SMP mode */
-static void CommunicationServer(int sleepTime) {
-#if CMK_SMP_NO_COMMTHD
-    sleep(sleepTime);
-#else
-    
-    if(commThdExit) {
-        MACHSTATE2(2, "[%d-%p] comm server exit begin {",CmiMyPe(),CmiGetState());
-        ConverseCommonExit();        
-        MACHSTATE2(2, "[%d-%p] comm server exit end }",CmiMyPe(),CmiGetState());
-        pthread_exit(NULL);
-    }
-
-    if(!CsvAccess(lapiInterruptMode)) check_lapi(LAPI_Probe,(lapiContext));
-
-#if CMK_IMMEDIATE_MSG
-    /*MACHSTATE1(2, "[%p] Handling Immediate Message begin{",CmiGetState());*/
-    CmiHandleImmediate();
-    /*MACHSTATE1(2, "[%p] Handling Immediate Message end}",CmiGetState());*/
-#endif
-
-#if DECOUPLE_BCAST_PROCESS
-    /*MACHSTATE1(2, "[%p] Enter ProcessBroadcastMsg begin{",CmiGetState());*/
-    ProcessBroadcastMsg(0);
-    /*MACHSTATE1(2, "[%p] Enter ProcessBroadcastMsg end}",CmiGetState());*/
-#endif
-
-    /* sleep(sleepTime) */
-#endif
-}
-
-static void ConverseRunPE(int everReturn) {
-    CmiIdleState *s;
-    char** CmiMyArgv;
-    int i;
-    CpvInitialize(void *,CmiLocalQueue);
-    CpvInitialize(unsigned, networkProgressCount);
-
-    CpvInitialize(PCQueue, procBcastQ);
-    CpvAccess(procBcastQ) = PCQueueCreate();
-
+static void MachinePreCommonInitForLAPI(int everReturn) {
 #if ENSURE_MSG_PAIRORDER
     CpvInitialize(MsgOrderInfo, p2pMsgSeqInfo);
     initMsgOrderInfo(&CpvAccess(p2pMsgSeqInfo));
-
-    CpvInitialize(MsgOrderInfo, bcastMsgSeqInfo); 
-    initMsgOrderInfo(&CpvAccess(bcastMsgSeqInfo));    
 #endif
 
 #if MACHINE_DEBUG_LOG
@@ -1943,67 +929,28 @@ static void ConverseRunPE(int everReturn) {
     }
 #endif
 
-    /* To make sure cpvaccess is correct? -Chao Mei */
-    CmiNodeAllBarrier();
-
-    /* Added by Chao Mei */
-#if CMK_SMP
-    if(CmiMyRank()) {
-        /* The master core of this node is already initialized */
-        lapi_info_t info;
-        int testnode, testnumnodes;
-        memset(&info,0,sizeof(info));
-        /*CpvInitialize(lapi_handle_t *, lapiContext);
-        CpvAccess(lapiContext) = CpvAccessOther(lapiContext, 0)+CmiMyRank();
-        CpvAccess(lapiContext) = CpvAccessOther(lapiContext, 0);
-        */       
-        MACHSTATE2(2, "My rank id=%d, lapicontext=%p", CmiMyRank(), &lapiContext);
-
-        check_lapi(LAPI_Qenv,(lapiContext, TASK_ID, &testnode));
-        check_lapi(LAPI_Qenv,(lapiContext, NUM_TASKS, &testnumnodes));
-
-        MACHSTATE3(2, "My rank id=%d, Task id=%d, Num tasks=%d", CmiMyRank(), testnode, testnumnodes);
-    }
-#endif
-
-
-    MACHSTATE2(2, "[%d] ConverseRunPE (thread %p)",CmiMyRank(),CmiGetState());
-       
-    CmiNodeAllBarrier();
-
-    MACHSTATE(2, "After NodeBarrier in ConverseRunPE");
-    
-    CpvAccess(CmiLocalQueue) = CmiGetState()->localqueue;
-
-    if(CmiMyRank())
-        CmiMyArgv=CmiCopyArgs(Cmi_argv);
-    else
-       CmiMyArgv=Cmi_argv;
-
-    CthInit(CmiMyArgv);
-
-    MACHSTATE(2, "After CthInit in ConverseRunPE");
-
-    ConverseCommonInit(CmiMyArgv);
+}
 
-    MACHSTATE(2, "After ConverseCommonInit in ConverseRunPE");
+static void MachinePostCommonInitForLAPI(int everReturn) {
+    /**
+         * In SMP, the machine layer usually has one comm thd, and it is
+         * designed to be responsible for all network communication. So
+         * if there's no dedicated processor for the comm thread, it has
+         * to share a proc with a worker thread. In this scenario,
+         * the worker thread needs to yield for some time to give CPU
+         * time to comm thread. However, in current configuration, we
+         * will always dedicate one proc for the comm thd, therefore,
+         * such yielding scheme is not necessary.  Besides, avoiding
+         * this yielding scheme improves performance because worker
+         * thread doesn't need to yield and will be more responsive to
+         * incoming messages. So, we will always use CmiNotifyIdle
+         * instead.
+         *
+         * --Chao Mei
+         */
+
+    /* Not registering any Idle-state related functions right now!! */
 
-   /**
-     * In SMP, the machine layer usually has one comm thd, and it is 
-     * designed to be responsible for all network communication. So 
-     * if there's no dedicated processor for the comm thread, it has 
-     * to share a proc with a worker thread. In this scenario, 
-     * the worker thread needs to yield for some time to give CPU 
-     * time to comm thread. However, in current configuration, we 
-     * will always dedicate one proc for the comm thd, therefore, 
-     * such yielding scheme is not necessary.  Besides, avoiding 
-     * this yielding scheme improves performance because worker 
-     * thread doesn't need to yield and will be more responsive to 
-     * incoming messages. So, we will always use CmiNotifyIdle 
-     * instead. 
-     *  
-     * --Chao Mei
-     */
 #if 0 && CMK_SMP
     s=CmiNotifyGetState();
     CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE,(CcdVoidFn)CmiNotifyBeginIdle,(void *)s);
@@ -2012,120 +959,13 @@ static void ConverseRunPE(int everReturn) {
     CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,(CcdVoidFn)CmiNotifyIdle,NULL);
 #if !CMK_SMP || CMK_SMP_NO_COMMTHD
     /* If there's comm thread, then comm thd is responsible for advancing comm */
-    if(!CsvAccess(lapiInterruptMode)) {
-        CcdCallOnConditionKeep(CcdPERIODIC_10ms, (CcdVoidFn)AdvanceCommunication, NULL);
+    if (!CsvAccess(lapiInterruptMode)) {
+        CcdCallOnConditionKeep(CcdPERIODIC_10ms, (CcdVoidFn)AdvanceCommunicationForLAPI, NULL);
     }
 #endif
 #endif
-
-#if CMK_IMMEDIATE_MSG
-    /* Converse initialization finishes, immediate messages can be processed.
-       node barrier previously should take care of the node synchronization */
-    _immediateReady = 1;
-#endif
-
-    /* communication thread */
-    if (CmiMyRank() == CmiMyNodeSize()) {
-        Cmi_startfn(CmiGetArgc(CmiMyArgv), CmiMyArgv);
-        MACHSTATE2(3, "[%p]: Comm thread on node %d is going to be a communication server", CmiGetState(), CmiMyNode());            
-        while(1) CommunicationServer(5);        
-    } else { /* worker thread */
-        if (!everReturn) {
-            Cmi_startfn(CmiGetArgc(CmiMyArgv), CmiMyArgv);
-            MACHSTATE1(3, "[%p]: Worker thread is going to work", CmiGetState());
-            if (Cmi_usrsched==0) CsdScheduler(-1);
-            ConverseExit();
-        }
-    }
-}
-
-void ConverseInit(int argc, char **argv, CmiStartFn fn, int usched, int initret) {
-    int n,i;
-
-    lapi_info_t info;
-
-#if ENSURE_MSG_PAIRORDER
-   cmplHdlrThdLock = CmiCreateLock();
-#endif
-
-    /* processor per node */
-    /** 
-     *  We have to determin the ppn at this point in order to create
-     *  the corresponding number of lapiContext instances.
-     */
-#if CMK_SMP
-    CmiMyNodeSize() = 1;
-    CmiGetArgInt(argv,"+ppn", &CmiMyNodeSize());
-#else
-    if (CmiGetArgFlag(argv,"+ppn")) {
-        CmiAbort("+ppn cannot be used in non SMP version!\n");
-    }
-#endif
-
-    memset(&info,0,sizeof(info));
-
-    /* Register error handler (redundant?) -- added by Chao Mei*/
-    info.err_hndlr = (LAPI_err_hndlr *)lapi_err_hndlr;
-
-    /* Indicates the number of completion handler threads to create */
-    /* The number of completion hndlr thds will affect the atomic PCQueue operations!! */
-    /* NOTE: num_compl_hndlr_thr is obsolete now! --Chao Mei */
-    /* info.num_compl_hndlr_thr = 1; */
-
-    check_lapi(LAPI_Init,(&lapiContext, &info));
-    
-    /* It's a good idea to start with a fence,
-       because packets recv'd before a LAPI_Init are just dropped. */
-    check_lapi(LAPI_Gfence,(lapiContext));
-
-    check_lapi(LAPI_Qenv,(lapiContext, TASK_ID, &CmiMyNode()));
-    check_lapi(LAPI_Qenv,(lapiContext, NUM_TASKS, &CmiNumNodes()));
-
-    /* Make polling as the default mode as real apps have better perf */
-    CsvAccess(lapiInterruptMode) = 0;
-    if(CmiGetArgFlag(argv,"+poll")) CsvAccess(lapiInterruptMode) = 0;
-    if(CmiGetArgFlag(argv,"+nopoll")) CsvAccess(lapiInterruptMode) = 1;    
-
-    check_lapi(LAPI_Senv,(lapiContext, ERROR_CHK, lapiDebugMode));
-    check_lapi(LAPI_Senv,(lapiContext, INTERRUPT_SET, CsvAccess(lapiInterruptMode)));
-
-    if(CmiMyNode()==0) {
-        printf("Running lapi in interrupt mode: %d\n", CsvAccess(lapiInterruptMode));
-        printf("Running lapi with %d completion handler threads.\n", info.num_compl_hndlr_thr);
-    }
-
-    /** 
-     *  Associate PumpMsgsBegin with var "lapiHeaderHandler". Then inside Xfer calls,
-     *  lapiHeaderHandler could be used to indicate the callback
-     *  instead of PumpMsgsBegin --Chao Mei
-     */
-    check_lapi(LAPI_Addr_set,(lapiContext,(void *)PumpMsgsBegin,lapiHeaderHandler));
-
-    CmiNumPes() = CmiNumNodes() * CmiMyNodeSize();
-    Cmi_nodestart = CmiMyNode() * CmiMyNodeSize();
-
-    Cmi_argv = argv;
-    Cmi_startfn = fn;
-    Cmi_usrsched = usched;
-
-    if (CmiGetArgFlag(argv,"++debug")) {  /*Pause so user has a chance to start and attach debugger*/
-        printf("CHARMDEBUG> Processor %d has PID %d\n",CmiMyNode(),getpid());
-        if (!CmiGetArgFlag(argv,"++debug-no-pause"))
-            sleep(30);
-    }
-
-    CsvInitialize(CmiNodeState, NodeState);
-    CmiNodeStateInit(&CsvAccess(NodeState));
-
-#if CMK_NODE_QUEUE_AVAILABLE
-    CsvInitialize(PCQueue, nodeBcastQ);
-    CsvAccess(nodeBcastQ) = PCQueueCreate();
-#endif
-
-    CmiStartThreads(argv);
-
-    ConverseRunPE(initret);
 }
+/* ######End of functions related with starting programs###### */
 
 /***********************************************************************
  *
@@ -2139,9 +979,28 @@ void CmiAbort(const char *message) {
     exit(1);
 }
 
+/* What's the difference of this function with CmiAbort????
+   and whether LAPI_Term is needed?? It should be shared across
+   all machine layers.
 static void PerrorExit(const char *msg) {
     perror(msg);
     LAPI_Term(lapiContext);
     exit(1);
 }
+*/
+
+/* Barrier related functions */
+/*TODO: does lapi provide any Barrrier related functions as DCMF provides??? --Chao Mei */
+/* Barrier needs to be implemented!!! -Chao Mei */
+/* These two barriers are only needed by CmiTimerInit to synchronize all the
+   threads. They do not need to provide a general barrier. */
+int CmiBarrier() {
+    return 0;
+}
+int CmiBarrierZero() {
+    return 0;
+}
+
+
+/*@}*/
 
index ef07391c37ae954f1ee05e7e9aabe14d14df53a4..fc81c569052c58f6580421cf5ae8cd579c4d21cb 100644 (file)
@@ -10,7 +10,7 @@
 #if CMK_ERROR_CHECKING
 #define CMK_MSG_HEADER_EXT_    CmiUInt2 rank, hdl,xhdl,info, stratid, redID; CmiUInt4 root; unsigned char cksum, magic;
 #else
-#define CMK_MSG_HEADER_EXT_    CmiUInt2 rank, hdl,xhdl,info, stratid, redID; CmiUInt4 root; 
+#define CMK_MSG_HEADER_EXT_    CmiUInt2 rank, hdl,xhdl,info, stratid, redID; CmiInt4 root; 
 #endif
 #define CMK_MSG_HEADER_BASIC  CMK_MSG_HEADER_EXT
 #define CMK_MSG_HEADER_EXT    { CMK_MSG_HEADER_EXT_ }
index 743a689310d1d3a587240dbcbc3f398acaef2179..c38fa631b733c0c8473078d2ddc01076b92daaec 100644 (file)
 #include <wincon.h>
 #include <sys/types.h>
 #include <sys/timeb.h>
-static void sleep(int secs) {Sleep(1000*secs);}
+static void sleep(int secs) {
+    Sleep(1000*secs);
+}
 #else
 #include <unistd.h> /*For getpid()*/
 #endif
 #include <stdlib.h> /*For sleep()*/
 
-#define MULTI_SENDQUEUE    0
+#include "machine.h"
+#include "pcqueue.h"
 
-#if defined(CMK_SHARED_VARS_POSIX_THREADS_SMP)
-#define CMK_SMP 1
-#endif
+/* =======Beginning of Definitions of Performance-Specific Macros =======*/
+/* Whether to use multiple send queue in SMP mode */
+#define MULTI_SENDQUEUE    0
 
+/* ###Beginning of flow control related macros ### */
 #define CMI_EXERT_SEND_CAP 0
 #define CMI_EXERT_RECV_CAP 0
 
 #define CMI_DYNAMIC_EXERT_CAP 0
-/* This macro defines the max number of msgs in the sender msg buffer 
+/* This macro defines the max number of msgs in the sender msg buffer
  * that is allowed for recving operation to continue
  */
 #define CMI_DYNAMIC_OUTGOING_THRESHOLD 4
@@ -66,8 +70,9 @@ static int dynamicRecvCap = CMI_DYNAMIC_MAXCAPSIZE;
 #if CMI_EXERT_RECV_CAP
 #define RECV_CAP 2
 #endif
+/* ###End of flow control related macros ### */
 
-
+/* ###Beginning of machine-layer-tracing related macros ### */
 #if CMK_TRACE_ENABLED && CMK_SMP_TRACE_COMMTHREAD
 #define CMI_MPI_TRACE_MOREDETAILED 0
 #undef CMI_MPI_TRACE_USEREVENTS
@@ -86,11 +91,49 @@ static int dynamicRecvCap = CMI_DYNAMIC_MAXCAPSIZE;
 #define CMK_TRACE_COMMOVERHEAD 0
 #endif
 
-#include "machine.h"
+#if CMI_MPI_TRACE_USEREVENTS && CMK_TRACE_ENABLED && ! CMK_TRACE_IN_CHARM
+CpvStaticDeclare(double, projTraceStart);
+#define  START_EVENT()  CpvAccess(projTraceStart) = CmiWallTimer();
+#define  END_EVENT(x)   traceUserBracketEvent(x, CpvAccess(projTraceStart), CmiWallTimer());
+#else
+#define  START_EVENT()
+#define  END_EVENT(x)
+#endif
+/* ###End of machine-layer-tracing related macros ### */
 
-#include "pcqueue.h"
+/* ###Beginning of POST_RECV related macros ### */
+/*
+ * If MPI_POST_RECV is defined, we provide default values for
+ * size and number of posted recieves. If MPI_POST_RECV_COUNT
+ * is set then a default value for MPI_POST_RECV_SIZE is used
+ * if not specified by the user.
+ */
+#define MPI_POST_RECV 0
 
-#define FLIPBIT(node,bitnumber) (node ^ (1 << bitnumber))
+#if MPI_POST_RECV
+#define MPI_POST_RECV_COUNT 10
+#endif
+
+#if MPI_POST_RECV_COUNT > 0
+#define MPI_POST_RECV_LOWERSIZE 2000
+#define MPI_POST_RECV_UPPERSIZE 4000
+#define MPI_POST_RECV_SIZE MPI_POST_RECV_UPPERSIZE
+
+CpvDeclare(unsigned long long, Cmi_posted_recv_total);
+CpvDeclare(unsigned long long, Cmi_unposted_recv_total);
+CpvDeclare(MPI_Request*, CmiPostedRecvRequests); /* An array of request handles for posted recvs */
+CpvDeclare(char*,CmiPostedRecvBuffers);
+#endif
+
+/* to avoid MPI's in order delivery, changing MPI Tag all the time */
+#define TAG     1375
+#if MPI_POST_RECV_COUNT > 0
+#define POST_RECV_TAG       (TAG+1)
+#define BARRIER_ZERO_TAG  TAG
+#else
+#define BARRIER_ZERO_TAG   (TAG-1)
+#endif
+/* ###End of POST_RECV related related macros ### */
 
 #if CMK_BLUEGENEL
 #define MAX_QLEN 8
@@ -99,40 +142,15 @@ static int dynamicRecvCap = CMI_DYNAMIC_MAXCAPSIZE;
 #define NETWORK_PROGRESS_PERIOD_DEFAULT 0
 #define MAX_QLEN 200
 #endif
+/* =======End of Definitions of Performance-Specific Macros =======*/
 
-#if CMI_MPI_TRACE_USEREVENTS && CMK_TRACE_ENABLED && ! CMK_TRACE_IN_CHARM
-CpvStaticDeclare(double, projTraceStart);
-# define  START_EVENT()  CpvAccess(projTraceStart) = CmiWallTimer();
-# define  END_EVENT(x)   traceUserBracketEvent(x, CpvAccess(projTraceStart), CmiWallTimer());
-#else
-# define  START_EVENT()
-# define  END_EVENT(x)
-#endif
 
-/*
-    To reduce the buffer used in broadcast and distribute the load from
-  broadcasting node, define CMK_BROADCAST_SPANNING_TREE enforce the use of
-  spanning tree broadcast algorithm.
-    This will use the fourth short in message as an indicator of spanning tree
-  root.
-*/
-#define CMK_BROADCAST_SPANNING_TREE    1
-#define CMK_BROADCAST_HYPERCUBE        0
-
-#define BROADCAST_SPANNING_FACTOR      4
-/* The number of children used when a msg is broadcast inside a node */
-#define BROADCAST_SPANNING_INTRA_FACTOR      8
-
-#define CMI_BROADCAST_ROOT(msg)          ((CmiMsgHeaderBasic *)msg)->root
-#define CMI_GET_CYCLE(msg)               ((CmiMsgHeaderBasic *)msg)->root
-
-#define CMI_DEST_RANK(msg)               ((CmiMsgHeaderBasic *)msg)->rank
+/* =====Beginning of Definitions of Message-Corruption Related Macros=====*/
 #define CMI_MAGIC(msg)                  ((CmiMsgHeaderBasic *)msg)->magic
-
-/* FIXME: need a random number that everyone agrees ! */
 #define CHARM_MAGIC_NUMBER              126
 
 #if CMK_ERROR_CHECKING
+extern unsigned char computeCheckSum(unsigned char *data, int len);
 static int checksum_flag = 0;
 #define CMI_SET_CHECKSUM(msg, len)     \
        if (checksum_flag)  {   \
@@ -147,846 +165,732 @@ static int checksum_flag = 0;
 #define CMI_SET_CHECKSUM(msg, len)
 #define CMI_CHECK_CHECKSUM(msg, len)
 #endif
+/* =====End of Definitions of Message-Corruption Related Macros=====*/
 
-#if CMK_BROADCAST_SPANNING_TREE || CMK_BROADCAST_HYPERCUBE
-#define CMI_SET_BROADCAST_ROOT(msg, root)  CMI_BROADCAST_ROOT(msg) = (root);
-#else
-#define CMI_SET_BROADCAST_ROOT(msg, root) 
-#endif
-
-
-/** 
-    If MPI_POST_RECV is defined, we provide default values for size 
-    and number of posted recieves. If MPI_POST_RECV_COUNT is set
-    then a default value for MPI_POST_RECV_SIZE is used if not specified
-    by the user.
-*/
-
-#define MPI_POST_RECV 0
-#if MPI_POST_RECV
-#define MPI_POST_RECV_COUNT 10
-#undef MPI_POST_RECV
-#endif
-#if MPI_POST_RECV_COUNT > 0
-#ifndef MPI_POST_RECV_SIZE
-#define MPI_POST_RECV_LOWERSIZE 2000
-#define MPI_POST_RECV_UPPERSIZE 4000
-#define MPI_POST_RECV_SIZE MPI_POST_RECV_UPPERSIZE
-#endif
-/* #undef  MPI_POST_RECV_DEBUG  */
-CpvDeclare(unsigned long long, Cmi_posted_recv_total);
-CpvDeclare(unsigned long long, Cmi_unposted_recv_total);
-CpvDeclare(MPI_Request*, CmiPostedRecvRequests); /* An array of request handles for posted recvs */
-CpvDeclare(char*,CmiPostedRecvBuffers);
-#endif
-
-/*
- to avoid MPI's in order delivery, changing MPI Tag all the time
-*/
-#define TAG     1375
-
-#if MPI_POST_RECV_COUNT > 0
-#define POST_RECV_TAG (TAG+1)
-#define BARRIER_ZERO_TAG TAG
-#else
-#define BARRIER_ZERO_TAG     1375
-#endif
-
-#define BLK_LEN  512
-
-#if CMK_NODE_QUEUE_AVAILABLE
-#define DGRAM_NODEMESSAGE   (0xFB)
-
-#define NODE_BROADCAST_OTHERS (-1)
-#define NODE_BROADCAST_ALL    (-2)
-#endif
 
+/* =====Beginning of Declarations of Machine Specific Variables===== */
 #include <signal.h>
 void (*signal_int)(int);
 
-/*
-static int mpi_tag = TAG;
-#define NEW_MPI_TAG    mpi_tag++; if (mpi_tag == MPI_TAG_UB) mpi_tag=TAG;
-*/
-
-static int        _thread_provided = -1;
-int               _Cmi_mynode;    /* Which address space am I */
-int               _Cmi_mynodesize;/* Number of processors in my address space */
-int               _Cmi_numnodes;  /* Total number of address spaces */
-int               _Cmi_numpes;    /* Total number of processors */
-static int        Cmi_nodestart; /* First processor in this address space */
-CpvDeclare(void*, CmiLocalQueue);
-
-/*Network progress utility variables. Period controls the rate at
-  which the network poll is called */
-CpvDeclare(unsigned , networkProgressCount);
-int networkProgressPeriod;
-
-int              idleblock = 0;
-
-#if 0
-static void **recdQueue_blk;
-static unsigned int recdQueue_blk_len;
-static unsigned int recdQueue_first;
-static unsigned int recdQueue_len;
-static void recdQueueInit(void);
-static void recdQueueAddToBack(void *element);
-static void *recdQueueRemoveFromFront(void);
-#endif
-
-static void ConverseRunPE(int everReturn);
-static void CommunicationServer(int sleepTime);
-static void CommunicationServerThread(int sleepTime);
+static int _thread_provided = -1; /* Indicating MPI thread level */
+static int idleblock = 0;
 
+/* A simple list for msgs that have been sent by MPI_Isend */
 typedef struct msg_list {
-     char *msg;
-     struct msg_list *next;
-     int size, destpe;
-
+    char *msg;
+    struct msg_list *next;
+    int size, destpe;
 #if CMK_SMP_TRACE_COMMTHREAD
-       int srcpe;
-#endif 
-       
-     MPI_Request req;
+    int srcpe;
+#endif
+    MPI_Request req;
 } SMSG_LIST;
 
-int MsgQueueLen=0;
-static int request_max;
-
 static SMSG_LIST *sent_msgs=0;
 static SMSG_LIST *end_sent=0;
 
-static int Cmi_dim;
-
-static int no_outstanding_sends=0; /*FLAG: consume outstanding Isends in scheduler loop*/
+int MsgQueueLen=0;
+static int request_max;
+/*FLAG: consume outstanding Isends in scheduler loop*/
+static int no_outstanding_sends=0;
 
 #if NODE_0_IS_CONVHOST
 int inside_comm = 0;
 #endif
 
-void CmiAbort(const char *message);
-static void PerrorExit(const char *msg);
-
-void SendSpanningChildren(int size, char *msg);
-void SendHypercube(int size, char *msg);
-
-static void PerrorExit(const char *msg)
-{
-  perror(msg);
-  exit(1);
-}
-
-extern unsigned char computeCheckSum(unsigned char *data, int len);
-
-
-
 typedef struct ProcState {
 #if MULTI_SENDQUEUE
-PCQueue      sendMsgBuf;       /* per processor message sending queue */
+    PCQueue      sendMsgBuf;       /* per processor message sending queue */
 #endif
-CmiNodeLock  recvLock;             /* for cs->recv */
+    CmiNodeLock  recvLock;                 /* for cs->recv */
 } ProcState;
-
 static ProcState  *procState;
 
-#if CMK_SMP
-
-#if !MULTI_SENDQUEUE
+#if CMK_SMP && !MULTI_SENDQUEUE
 static PCQueue sendMsgBuf;
 static CmiNodeLock  sendMsgBufLock = NULL;        /* for sendMsgBuf */
 #endif
+/* =====End of Declarations of Machine Specific Variables===== */
 
+
+/* =====Beginning of Declarations of Machine Specific Functions===== */
+/* Utility functions */
+#if CMK_BLUEGENEL
+extern void MPID_Progress_test();
 #endif
+static size_t CmiAllAsyncMsgsSent(void);
+static void CmiReleaseSentMessages(void);
+static int PumpMsgs(void);
+static void PumpMsgsBlocking(void);
 
-/************************************************************
- *
- * Processor state structure
- *
- ************************************************************/
+#if CMK_SMP
+static int MsgQueueEmpty();
+static int RecvQueueEmpty();
+static int SendMsgBuf();
+static  void EnqueueMsg(void *m, int size, int node);
+#endif
 
-/* fake Cmi_charmrun_fd */
-static int Cmi_charmrun_fd = 0;
-#include "machine-smp.c"
+/* The machine-specific send function */
+static CmiCommHandle MachineSpecificSendForMPI(int destNode, int size, char *msg, int mode);
+#define CmiMachineSpecificSendFunc MachineSpecificSendForMPI
 
-CsvDeclare(CmiNodeState, NodeState);
+/* ### Beginning of Machine-startup Related Functions ### */
+static void MachineInitForMPI(int argc, char **argv, int *numNodes, int *myNodeID);
+#define MachineSpecificInit MachineInitForMPI
 
-#include "immediate.c"
+static void MachinePreCommonInitForMPI(int everReturn);
+static void MachinePostCommonInitForMPI(int everReturn);
+#define MachineSpecificPreCommonInit MachinePreCommonInitForMPI
+#define MachineSpecificPostCommonInit MachinePostCommonInitForMPI
+/* ### End of Machine-startup Related Functions ### */
 
-#if CMK_SHARED_VARS_UNAVAILABLE
-/************ non SMP **************/
-static struct CmiStateStruct Cmi_state;
-int _Cmi_mype;
-int _Cmi_myrank;
+/* ### Beginning of Machine-running Related Functions ### */
+static void AdvanceCommunicationForMPI();
+#define MachineSpecificAdvanceCommunication AdvanceCommunicationForMPI
 
-void CmiMemLock() {}
-void CmiMemUnlock() {}
+static void DrainResourcesForMPI(); /* used when exit */
+#define MachineSpecificDrainResources DrainResourcesForMPI
 
-#define CmiGetState() (&Cmi_state)
-#define CmiGetStateN(n) (&Cmi_state)
+static void MachineExitForMPI();
+#define MachineSpecificExit MachineExitForMPI
+/* ### End of Machine-running Related Functions ### */
 
-void CmiYield(void) { sleep(0); }
+/* ### Beginning of Idle-state Related Functions ### */
+void CmiNotifyIdleForMPI(void);
+/* ### End of Idle-state Related Functions ### */
 
-static void CmiStartThreads(char **argv)
-{
-  CmiStateInit(Cmi_nodestart, 0, &Cmi_state);
-  _Cmi_mype = Cmi_nodestart;
-  _Cmi_myrank = 0;
-}
-#else  /* non smp */
-int CmiMyPe(void)
-{
-  return CmiGetState()->pe;
-}
-int CmiMyRank(void)
-{
-  return CmiGetState()->rank;
-}
-int CmiNodeFirst(int node) { return node*_Cmi_mynodesize; }
-int CmiNodeSize(int node)  { return _Cmi_mynodesize; }
-int CmiNodeOf(int pe)      { return (pe/_Cmi_mynodesize); }
-int CmiRankOf(int pe)      { return pe%_Cmi_mynodesize; }
-#endif
+void MachinePostNonLocalForMPI();
+#define MachineSpecificPostNonLocal MachinePostNonLocalForMPI
 
-/*Add a message to this processor's receive queue, pe is a rank */
-void CmiPushPE(int pe,void *msg)
-{
-  CmiState cs = CmiGetStateN(pe);
-  MACHSTATE2(3,"Pushing message into rank %d's queue %p{",pe, cs->recv);
-#if CMK_IMMEDIATE_MSG
-  if (CmiIsImmediate(msg)) {
-/*
-CmiPrintf("[node %d] Immediate Message hdl: %d rank: %d {{. \n", CmiMyNode(), CmiGetHandler(msg), pe);
-    CmiHandleMessage(msg);
-CmiPrintf("[node %d] Immediate Message done.}} \n", CmiMyNode());
-*/
-    /**(CmiUInt2 *)msg = pe;*/
-    CMI_DEST_RANK(msg) = pe;
-    CmiPushImmediateMsg(msg);
-    return;
-  }
-#endif
+/* =====End of Declarations of Machine Specific Functions===== */
+
+/**
+ *  Macros that overwrites the common codes, such as
+ *  CMK_SMP_NO_COMMTHD, NETWORK_PROGRESS_PERIOD_DEFAULT,
+ *  USE_COMMON_SYNC_P2P, CMK_HAS_SIZE_IN_MSGHDR,
+ *  CMK_OFFLOAD_BCAST_PROCESS etc.
+ */
+#define CMK_HAS_SIZE_IN_MSGHDR 0
+#include "machine-common.c"
+
+/* The machine specific msg-sending function */
 
 #if CMK_SMP
-  CmiLock(procState[pe].recvLock);
+static void EnqueueMsg(void *m, int size, int node) {
+    SMSG_LIST *msg_tmp = (SMSG_LIST *) CmiAlloc(sizeof(SMSG_LIST));
+    MACHSTATE1(3,"EnqueueMsg to node %d {{ ", node);
+    msg_tmp->msg = m;
+    msg_tmp->size = size;
+    msg_tmp->destpe = node;
+
+#if CMK_SMP_TRACE_COMMTHREAD
+    msg_tmp->srcpe = CmiMyPe();
 #endif
-  PCQueuePush(cs->recv,msg);
-#if CMK_SMP
-  CmiUnlock(procState[pe].recvLock);
+
+#if MULTI_SENDQUEUE
+    PCQueuePush(procState[CmiMyRank()].sendMsgBuf,(char *)msg_tmp);
+#else
+    /*CmiLock(sendMsgBufLock);*/
+    PCQueuePush(sendMsgBuf,(char *)msg_tmp);
+    /*CmiUnlock(sendMsgBufLock);*/
 #endif
-  CmiIdleLock_addMessage(&cs->idle);
-  MACHSTATE1(3,"} Pushing message into rank %d's queue done",pe);
-}
 
-#if CMK_NODE_QUEUE_AVAILABLE
-/*Add a message to this processor's receive queue */
-static void CmiPushNode(void *msg)
-{
-  MACHSTATE(3,"Pushing message into NodeRecv queue");
-#if CMK_IMMEDIATE_MSG
-  if (CmiIsImmediate(msg)) {
-    CMI_DEST_RANK(msg) = 0;
-    CmiPushImmediateMsg(msg);
-    return;
-  }
-#endif
-  CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
-  PCQueuePush(CsvAccess(NodeState).NodeRecv,msg);
-  CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
-  {
-  CmiState cs=CmiGetStateN(0);
-  CmiIdleLock_addMessage(&cs->idle);
-  }
+    MACHSTATE3(3,"}} EnqueueMsg to %d finish with queue %p len: %d", node, sendMsgBuf, PCQueueLength(sendMsgBuf));
 }
 #endif
 
+static CmiCommHandle MachineSpecificSendForMPI(int destNode, int size, char *msg, int mode) {
+    /* Ignoring the mode for MPI layer */
 
-static size_t CmiAllAsyncMsgsSent(void)
-{
-   SMSG_LIST *msg_tmp = sent_msgs;
-   MPI_Status sts;
-   int done;
+    CmiState cs = CmiGetState();
+    SMSG_LIST *msg_tmp;
+    int  rank;
 
-   while(msg_tmp!=0) {
-    done = 0;
-    if (MPI_SUCCESS != MPI_Test(&(msg_tmp->req), &done, &sts))
-      CmiAbort("CmiAllAsyncMsgsSent: MPI_Test failed!\n");
-    if(!done)
-      return 0;
-    msg_tmp = msg_tmp->next;
-/*    MsgQueueLen--; ????? */
-   }
-   return 1;
-}
+    CmiAssert(destNode != CmiMyNode());
+#if CMK_SMP
+    EnqueueMsg(msg, size, destNode);
+    return 0;
+#else
+    /* non smp */
+    msg_tmp = (SMSG_LIST *) CmiAlloc(sizeof(SMSG_LIST));
+    msg_tmp->msg = msg;
+    msg_tmp->next = 0;
+    while (MsgQueueLen > request_max) {
+        /*printf("Waiting for %d messages to be sent\n", MsgQueueLen);*/
+        CmiReleaseSentMessages();
+        PumpMsgs();
+    }
+#if CMK_ERROR_CHECKING
+    CMI_MAGIC(msg) = CHARM_MAGIC_NUMBER;
+#endif
+    CMI_SET_CHECKSUM(msg, size);
 
-int CmiAsyncMsgSent(CmiCommHandle c) {
+#if MPI_POST_RECV_COUNT > 0
+    if (size>=MPI_POST_RECV_LOWERSIZE && size <= MPI_POST_RECV_UPPERSIZE) {
+        START_EVENT();
+        if (MPI_SUCCESS != MPI_Isend((void *)msg,size,MPI_BYTE,destNode,POST_RECV_TAG,MPI_COMM_WORLD,&(msg_tmp->req)))
+            CmiAbort("MachineSpecificSendForMPI: MPI_Isend failed!\n");
+        END_EVENT(40);
+    } else {
+        START_EVENT();
+        if (MPI_SUCCESS != MPI_Isend((void *)msg,size,MPI_BYTE,destNode,TAG,MPI_COMM_WORLD,&(msg_tmp->req)))
+            CmiAbort("MachineSpecificSendForMPI: MPI_Isend failed!\n");
+        END_EVENT(40);
+    }
+#else
+    START_EVENT();
+    if (MPI_SUCCESS != MPI_Isend((void *)msg,size,MPI_BYTE,destNode,TAG,MPI_COMM_WORLD,&(msg_tmp->req)))
+        CmiAbort("MachineSpecificSendForMPI: MPI_Isend failed!\n");
+    /*END_EVENT(40);*/
+#if CMK_TRACE_COMMOVERHEAD
+    char tmp[64];
+    sprintf(tmp, "MPI_Isend: from proc %d to proc %d", CmiMyPe(), destNode);
+    traceUserSuppliedBracketedNote(tmp, 40, CpvAccess(projTraceStart), CmiWallTimer());
+#endif
+#endif
+
+    MsgQueueLen++;
+    if (sent_msgs==0)
+        sent_msgs = msg_tmp;
+    else
+        end_sent->next = msg_tmp;
+    end_sent = msg_tmp;
+    return (CmiCommHandle) &(msg_tmp->req);
+#endif              /* non-smp */
+}
 
-  SMSG_LIST *msg_tmp = sent_msgs;
-  int done;
-  MPI_Status sts;
-
-  while ((msg_tmp) && ((CmiCommHandle)&(msg_tmp->req) != c))
-    msg_tmp = msg_tmp->next;
-  if(msg_tmp) {
-    done = 0;
-    if (MPI_SUCCESS != MPI_Test(&(msg_tmp->req), &done, &sts))
-      CmiAbort("CmiAsyncMsgSent: MPI_Test failed!\n");
-    return ((done)?1:0);
-  } else {
+static size_t CmiAllAsyncMsgsSent(void) {
+    SMSG_LIST *msg_tmp = sent_msgs;
+    MPI_Status sts;
+    int done;
+
+    while (msg_tmp!=0) {
+        done = 0;
+        if (MPI_SUCCESS != MPI_Test(&(msg_tmp->req), &done, &sts))
+            CmiAbort("CmiAllAsyncMsgsSent: MPI_Test failed!\n");
+        if (!done)
+            return 0;
+        msg_tmp = msg_tmp->next;
+        /*    MsgQueueLen--; ????? */
+    }
     return 1;
-  }
 }
 
-void CmiReleaseCommHandle(CmiCommHandle c)
-{
-  return;
+int CmiAsyncMsgSent(CmiCommHandle c) {
+
+    SMSG_LIST *msg_tmp = sent_msgs;
+    int done;
+    MPI_Status sts;
+
+    while ((msg_tmp) && ((CmiCommHandle)&(msg_tmp->req) != c))
+        msg_tmp = msg_tmp->next;
+    if (msg_tmp) {
+        done = 0;
+        if (MPI_SUCCESS != MPI_Test(&(msg_tmp->req), &done, &sts))
+            CmiAbort("CmiAsyncMsgSent: MPI_Test failed!\n");
+        return ((done)?1:0);
+    } else {
+        return 1;
+    }
 }
 
-#if CMK_BLUEGENEL
-extern void MPID_Progress_test();
-#endif
+void CmiReleaseCommHandle(CmiCommHandle c) {
+    return;
+}
 
-void CmiReleaseSentMessages(void)
-{
-  SMSG_LIST *msg_tmp=sent_msgs;
-  SMSG_LIST *prev=0;
-  SMSG_LIST *temp;
-  int done;
-  MPI_Status sts;
+/* ######Beginning of functions related with communication progress ###### */
+static void CmiReleaseSentMessages(void) {
+    SMSG_LIST *msg_tmp=sent_msgs;
+    SMSG_LIST *prev=0;
+    SMSG_LIST *temp;
+    int done;
+    MPI_Status sts;
 
 #if CMK_BLUEGENEL
-  MPID_Progress_test();
+    MPID_Progress_test();
 #endif
 
-  MACHSTATE1(2,"CmiReleaseSentMessages begin on %d {", CmiMyPe());
-  while(msg_tmp!=0) {
-    done =0;
+    MACHSTATE1(2,"CmiReleaseSentMessages begin on %d {", CmiMyPe());
+    while (msg_tmp!=0) {
+        done =0;
 #if CMK_SMP_TRACE_COMMTHREAD || CMK_TRACE_COMMOVERHEAD
-    double startT = CmiWallTimer();
-#endif
-    if(MPI_Test(&(msg_tmp->req), &done, &sts) != MPI_SUCCESS)
-      CmiAbort("CmiReleaseSentMessages: MPI_Test failed!\n");
-    if(done) {
-      MACHSTATE2(3,"CmiReleaseSentMessages release one %d to %d", CmiMyPe(), msg_tmp->destpe);
-      MsgQueueLen--;
-      /* Release the message */
-      temp = msg_tmp->next;
-      if(prev==0)  /* first message */
-        sent_msgs = temp;
-      else
-        prev->next = temp;
-      CmiFree(msg_tmp->msg);
-      CmiFree(msg_tmp);
-      msg_tmp = temp;
-    } else {
-      prev = msg_tmp;
-      msg_tmp = msg_tmp->next;
-    }
+        double startT = CmiWallTimer();
+#endif
+        if (MPI_Test(&(msg_tmp->req), &done, &sts) != MPI_SUCCESS)
+            CmiAbort("CmiReleaseSentMessages: MPI_Test failed!\n");
+        if (done) {
+            MACHSTATE2(3,"CmiReleaseSentMessages release one %d to %d", CmiMyPe(), msg_tmp->destpe);
+            MsgQueueLen--;
+            /* Release the message */
+            temp = msg_tmp->next;
+            if (prev==0) /* first message */
+                sent_msgs = temp;
+            else
+                prev->next = temp;
+            CmiFree(msg_tmp->msg);
+            CmiFree(msg_tmp);
+            msg_tmp = temp;
+        } else {
+            prev = msg_tmp;
+            msg_tmp = msg_tmp->next;
+        }
 #if CMK_SMP_TRACE_COMMTHREAD || CMK_TRACE_COMMOVERHEAD
-    {
-    double endT = CmiWallTimer();
-    /* only record the event if it takes more than 1ms */
-    if(endT-startT>=0.001) traceUserSuppliedBracketedNote("MPI_Test: release a msg", 60, startT, endT);
-    }
+        {
+            double endT = CmiWallTimer();
+            /* only record the event if it takes more than 1ms */
+            if (endT-startT>=0.001) traceUserSuppliedBracketedNote("MPI_Test: release a msg", 60, startT, endT);
+        }
 #endif
-  }
-  end_sent = prev;
-  MACHSTATE(2,"} CmiReleaseSentMessages end");
+    }
+    end_sent = prev;
+    MACHSTATE(2,"} CmiReleaseSentMessages end");
 }
 
-int PumpMsgs(void)
-{
-  int nbytes, flg, res;
-  char *msg;
-  MPI_Status sts;
-  int recd=0;
+static int PumpMsgs(void) {
+    int nbytes, flg, res;
+    char *msg;
+    MPI_Status sts;
+    int recd=0;
 
 #if CMI_EXERT_RECV_CAP || CMI_DYNAMIC_EXERT_CAP
-  int recvCnt=0;
+    int recvCnt=0;
 #endif
-       
+
 #if CMK_BLUEGENEL
-  MPID_Progress_test();
+    MPID_Progress_test();
 #endif
 
-  MACHSTATE(2,"PumpMsgs begin {");
+    MACHSTATE(2,"PumpMsgs begin {");
 
 #if CMI_DYNAMIC_EXERT_CAP
-  dynamicRecvCap = CMI_DYNAMIC_MAXCAPSIZE;
+    dynamicRecvCap = CMI_DYNAMIC_MAXCAPSIZE;
 #endif
-       
-  while(1) {
+
+    while (1) {
 #if CMI_EXERT_RECV_CAP
-       if(recvCnt==RECV_CAP) break;
+        if (recvCnt==RECV_CAP) break;
 #elif CMI_DYNAMIC_EXERT_CAP
-       if(recvCnt >= dynamicRecvCap) break;
-#endif
-         
-    /* First check posted recvs then do  probe unmatched outstanding messages */
-#if MPI_POST_RECV_COUNT > 0 
-    int completed_index=-1;
-    if(MPI_SUCCESS != MPI_Testany(MPI_POST_RECV_COUNT, CpvAccess(CmiPostedRecvRequests), &completed_index, &flg, &sts))
-        CmiAbort("PumpMsgs: MPI_Testany failed!\n");
-    if(flg){
-        if (MPI_SUCCESS != MPI_Get_count(&sts, MPI_BYTE, &nbytes))
-            CmiAbort("PumpMsgs: MPI_Get_count failed!\n");
-
-               recd = 1;
-        msg = (char *) CmiAlloc(nbytes);
-        memcpy(msg,&(CpvAccess(CmiPostedRecvBuffers)[completed_index*MPI_POST_RECV_SIZE]),nbytes);
-        /* and repost the recv */
+        if (recvCnt >= dynamicRecvCap) break;
+#endif
 
-        START_EVENT();
+        /* First check posted recvs then do  probe unmatched outstanding messages */
+#if MPI_POST_RECV_COUNT > 0
+        int completed_index=-1;
+        if (MPI_SUCCESS != MPI_Testany(MPI_POST_RECV_COUNT, CpvAccess(CmiPostedRecvRequests), &completed_index, &flg, &sts))
+            CmiAbort("PumpMsgs: MPI_Testany failed!\n");
+        if (flg) {
+            if (MPI_SUCCESS != MPI_Get_count(&sts, MPI_BYTE, &nbytes))
+                CmiAbort("PumpMsgs: MPI_Get_count failed!\n");
+
+            recd = 1;
+            msg = (char *) CmiAlloc(nbytes);
+            memcpy(msg,&(CpvAccess(CmiPostedRecvBuffers)[completed_index*MPI_POST_RECV_SIZE]),nbytes);
+            /* and repost the recv */
 
-        if (MPI_SUCCESS != MPI_Irecv(  &(CpvAccess(CmiPostedRecvBuffers)[completed_index*MPI_POST_RECV_SIZE])  ,
-            MPI_POST_RECV_SIZE,
-            MPI_BYTE,
-            MPI_ANY_SOURCE,
-            POST_RECV_TAG,
-            MPI_COMM_WORLD,
-            &(CpvAccess(CmiPostedRecvRequests)[completed_index])  ))
+            START_EVENT();
+
+            if (MPI_SUCCESS != MPI_Irecv(  &(CpvAccess(CmiPostedRecvBuffers)[completed_index*MPI_POST_RECV_SIZE])      ,
+                                           MPI_POST_RECV_SIZE,
+                                           MPI_BYTE,
+                                           MPI_ANY_SOURCE,
+                                           POST_RECV_TAG,
+                                           MPI_COMM_WORLD,
+                                           &(CpvAccess(CmiPostedRecvRequests)[completed_index])  ))
                 CmiAbort("PumpMsgs: MPI_Irecv failed!\n");
 
-        END_EVENT(50);
+            END_EVENT(50);
 
-        CpvAccess(Cmi_posted_recv_total)++;
-    }
-    else {
-        res = MPI_Iprobe(MPI_ANY_SOURCE, TAG, MPI_COMM_WORLD, &flg, &sts);
-        if(res != MPI_SUCCESS)
-        CmiAbort("MPI_Iprobe failed\n");
-        if(!flg) break;
-        recd = 1;
-        MPI_Get_count(&sts, MPI_BYTE, &nbytes);
-        msg = (char *) CmiAlloc(nbytes);
+            CpvAccess(Cmi_posted_recv_total)++;
+        } else {
+            res = MPI_Iprobe(MPI_ANY_SOURCE, TAG, MPI_COMM_WORLD, &flg, &sts);
+            if (res != MPI_SUCCESS)
+                CmiAbort("MPI_Iprobe failed\n");
+            if (!flg) break;
+            recd = 1;
+            MPI_Get_count(&sts, MPI_BYTE, &nbytes);
+            msg = (char *) CmiAlloc(nbytes);
 
-        START_EVENT();
+            START_EVENT();
 
-        if (MPI_SUCCESS != MPI_Recv(msg,nbytes,MPI_BYTE,sts.MPI_SOURCE,sts.MPI_TAG, MPI_COMM_WORLD,&sts))
-            CmiAbort("PumpMsgs: MPI_Recv failed!\n");
+            if (MPI_SUCCESS != MPI_Recv(msg,nbytes,MPI_BYTE,sts.MPI_SOURCE,sts.MPI_TAG, MPI_COMM_WORLD,&sts))
+                CmiAbort("PumpMsgs: MPI_Recv failed!\n");
 
-        END_EVENT(30);
+            END_EVENT(30);
 
-        CpvAccess(Cmi_unposted_recv_total)++;
-    }
+            CpvAccess(Cmi_unposted_recv_total)++;
+        }
 #else
-    /* Original version */
+        /* Original version */
 #if CMK_SMP_TRACE_COMMTHREAD || CMK_TRACE_COMMOVERHEAD
-  double startT = CmiWallTimer(); 
+        double startT = CmiWallTimer();
 #endif
-    res = MPI_Iprobe(MPI_ANY_SOURCE, TAG, MPI_COMM_WORLD, &flg, &sts);
-    if(res != MPI_SUCCESS)
-      CmiAbort("MPI_Iprobe failed\n");
+        res = MPI_Iprobe(MPI_ANY_SOURCE, TAG, MPI_COMM_WORLD, &flg, &sts);
+        if (res != MPI_SUCCESS)
+            CmiAbort("MPI_Iprobe failed\n");
 
-    if(!flg) break;
+        if (!flg) break;
 #if CMK_SMP_TRACE_COMMTHREAD || CMK_TRACE_COMMOVERHEAD
-    {
-    double endT = CmiWallTimer();
-    /* only trace the probe that last longer than 1ms */
-    if(endT-startT>=0.001) traceUserSuppliedBracketedNote("MPI_Iprobe before a recv call", 70, startT, endT);
-    }
+        {
+            double endT = CmiWallTimer();
+            /* only trace the probe that last longer than 1ms */
+            if (endT-startT>=0.001) traceUserSuppliedBracketedNote("MPI_Iprobe before a recv call", 70, startT, endT);
+        }
 #endif
 
-    recd = 1;
-    MPI_Get_count(&sts, MPI_BYTE, &nbytes);
-    msg = (char *) CmiAlloc(nbytes);
-    
-    START_EVENT();
+        recd = 1;
+        MPI_Get_count(&sts, MPI_BYTE, &nbytes);
+        msg = (char *) CmiAlloc(nbytes);
+
+        START_EVENT();
 
-    if (MPI_SUCCESS != MPI_Recv(msg,nbytes,MPI_BYTE,sts.MPI_SOURCE,sts.MPI_TAG, MPI_COMM_WORLD,&sts))
-      CmiAbort("PumpMsgs: MPI_Recv failed!\n");
+        if (MPI_SUCCESS != MPI_Recv(msg,nbytes,MPI_BYTE,sts.MPI_SOURCE,sts.MPI_TAG, MPI_COMM_WORLD,&sts))
+            CmiAbort("PumpMsgs: MPI_Recv failed!\n");
 
-    /*END_EVENT(30);*/
+        /*END_EVENT(30);*/
 
 #endif
 
 #if CMK_SMP_TRACE_COMMTHREAD
         traceBeginCommOp(msg);
-       traceChangeLastTimestamp(CpvAccess(projTraceStart));
-       traceEndCommOp(msg);
-       #if CMI_MPI_TRACE_MOREDETAILED
-       char tmp[32];
-       sprintf(tmp, "MPI_Recv: to proc %d", CmiNodeFirst(CmiMyNode())+CMI_DEST_RANK(msg));
-       traceUserSuppliedBracketedNote(tmp, 30, CpvAccess(projTraceStart), CmiWallTimer());
-       #endif
+        traceChangeLastTimestamp(CpvAccess(projTraceStart));
+        traceEndCommOp(msg);
+#if CMI_MPI_TRACE_MOREDETAILED
+        char tmp[32];
+        sprintf(tmp, "MPI_Recv: to proc %d", CmiNodeFirst(CmiMyNode())+CMI_DEST_RANK(msg));
+        traceUserSuppliedBracketedNote(tmp, 30, CpvAccess(projTraceStart), CmiWallTimer());
+#endif
 #elif CMK_TRACE_COMMOVERHEAD
-       char tmp[32];
-       sprintf(tmp, "MPI_Recv: to proc %d", CmiNodeFirst(CmiMyNode())+CMI_DEST_RANK(msg));
-       traceUserSuppliedBracketedNote(tmp, 30, CpvAccess(projTraceStart), CmiWallTimer());
-#endif
-       
-       
-    MACHSTATE2(3,"PumpMsgs recv one from node:%d to rank:%d", sts.MPI_SOURCE, CMI_DEST_RANK(msg));
-    CMI_CHECK_CHECKSUM(msg, nbytes);
-#if CMK_ERROR_CHECKING
-    if (CMI_MAGIC(msg) != CHARM_MAGIC_NUMBER) { /* received a non-charm msg */
-      CmiPrintf("Charm++ Abort: Non Charm++ Message Received of size %d. \n", nbytes);
-      CmiFree(msg);
-      CmiAbort("Abort!\n");
-      continue;
-    }
+        char tmp[32];
+        sprintf(tmp, "MPI_Recv: to proc %d", CmiNodeFirst(CmiMyNode())+CMI_DEST_RANK(msg));
+        traceUserSuppliedBracketedNote(tmp, 30, CpvAccess(projTraceStart), CmiWallTimer());
 #endif
-       
-#if CMK_BROADCAST_SPANNING_TREE
-    if (CMI_BROADCAST_ROOT(msg))
-      SendSpanningChildren(nbytes, msg);
-#elif CMK_BROADCAST_HYPERCUBE
-    if (CMI_BROADCAST_ROOT(msg))
-      SendHypercube(nbytes, msg);
-#endif
-       
-       /* In SMP mode, this push operation needs to be executed
-     * after forwarding broadcast messages. If it is executed
-     * earlier, then during the bcast msg forwarding period,   
-        * the msg could be already freed on the worker thread.
-        * As a result, the forwarded message could be wrong! 
-        * --Chao Mei
-        */
-#if CMK_NODE_QUEUE_AVAILABLE
-    if (CMI_DEST_RANK(msg)==DGRAM_NODEMESSAGE)
-      CmiPushNode(msg);
-    else
+
+
+        MACHSTATE2(3,"PumpMsgs recv one from node:%d to rank:%d", sts.MPI_SOURCE, CMI_DEST_RANK(msg));
+        CMI_CHECK_CHECKSUM(msg, nbytes);
+#if CMK_ERROR_CHECKING
+        if (CMI_MAGIC(msg) != CHARM_MAGIC_NUMBER) { /* received a non-charm msg */
+            CmiPrintf("Charm++ Abort: Non Charm++ Message Received of size %d. \n", nbytes);
+            CmiFree(msg);
+            CmiAbort("Abort!\n");
+            continue;
+        }
 #endif
-       CmiPushPE(CMI_DEST_RANK(msg), msg);     
-       
+
+        handleOneRecvedMsg(nbytes, msg);
+
 #if CMI_EXERT_RECV_CAP
-       recvCnt++;
+        recvCnt++;
 #elif CMI_DYNAMIC_EXERT_CAP
-       recvCnt++;
+        recvCnt++;
 #if CMK_SMP
-       /* check sendMsgBuf to get the  number of messages that have not been sent
-         * which is only available in SMP mode
-        * MsgQueueLen indicates the number of messages that have not been released 
-         * by MPI 
-         */
-       if(PCQueueLength(sendMsgBuf) > CMI_DYNAMIC_OUTGOING_THRESHOLD
-               || MsgQueueLen > CMI_DYNAMIC_OUTGOING_THRESHOLD){
-               dynamicRecvCap = CMI_DYNAMIC_RECV_CAPSIZE;
-       }
+        /* check sendMsgBuf to get the  number of messages that have not been sent
+             * which is only available in SMP mode
+         * MsgQueueLen indicates the number of messages that have not been released
+             * by MPI
+             */
+        if (PCQueueLength(sendMsgBuf) > CMI_DYNAMIC_OUTGOING_THRESHOLD
+                || MsgQueueLen > CMI_DYNAMIC_OUTGOING_THRESHOLD) {
+            dynamicRecvCap = CMI_DYNAMIC_RECV_CAPSIZE;
+        }
 #else
-       /* MsgQueueLen indicates the number of messages that have not been released 
-         * by MPI 
-         */
-       if(MsgQueueLen > CMI_DYNAMIC_OUTGOING_THRESHOLD){
-               dynamicRecvCap = CMI_DYNAMIC_RECV_CAPSIZE;
-       }
+        /* MsgQueueLen indicates the number of messages that have not been released
+             * by MPI
+             */
+        if (MsgQueueLen > CMI_DYNAMIC_OUTGOING_THRESHOLD) {
+            dynamicRecvCap = CMI_DYNAMIC_RECV_CAPSIZE;
+        }
 #endif
 
-#endif 
-       
-  }
-
-  
-#if CMK_IMMEDIATE_MSG && !CMK_SMP
-  CmiHandleImmediate();
 #endif
-  
-  MACHSTATE(2,"} PumpMsgs end ");
-  return recd;
+
+    }
+
+    MACHSTATE(2,"} PumpMsgs end ");
+    return recd;
 }
 
 /* blocking version */
-static void PumpMsgsBlocking(void)
-{
-  static int maxbytes = 20000000;
-  static char *buf = NULL;
-  int nbytes, flg;
-  MPI_Status sts;
-  char *msg;
-  int recd=0;
-
-  if (!PCQueueEmpty(CmiGetState()->recv)) return;
-  if (!CdsFifo_Empty(CpvAccess(CmiLocalQueue))) return;
-  if (!CqsEmpty(CpvAccess(CsdSchedQueue))) return;
-  if (sent_msgs)  return;
+static void PumpMsgsBlocking(void) {
+    static int maxbytes = 20000000;
+    static char *buf = NULL;
+    int nbytes, flg;
+    MPI_Status sts;
+    char *msg;
+    int recd=0;
+
+    if (!PCQueueEmpty(CmiGetState()->recv)) return;
+    if (!CdsFifo_Empty(CpvAccess(CmiLocalQueue))) return;
+    if (!CqsEmpty(CpvAccess(CsdSchedQueue))) return;
+    if (sent_msgs)  return;
 
 #if 0
-  CmiPrintf("[%d] PumpMsgsBlocking. \n", CmiMyPe());
+    CmiPrintf("[%d] PumpMsgsBlocking. \n", CmiMyPe());
 #endif
 
-  if (buf == NULL) {
-    buf = (char *) CmiAlloc(maxbytes);
-    _MEMCHECK(buf);
-  }
+    if (buf == NULL) {
+        buf = (char *) CmiAlloc(maxbytes);
+        _MEMCHECK(buf);
+    }
 
 
 #if MPI_POST_RECV_COUNT > 0
 #warning "Using MPI posted receives and PumpMsgsBlocking() will break"
-CmiAbort("Unsupported use of PumpMsgsBlocking. This call should be extended to check posted recvs, cancel them all, and then wait on any incoming message, and then re-post the recvs");
+    CmiAbort("Unsupported use of PumpMsgsBlocking. This call should be extended to check posted recvs, cancel them all, and then wait on any incoming message, and then re-post the recvs");
 #endif
 
-  START_EVENT();
+    START_EVENT();
+
+    if (MPI_SUCCESS != MPI_Recv(buf,maxbytes,MPI_BYTE,MPI_ANY_SOURCE,TAG, MPI_COMM_WORLD,&sts))
+        CmiAbort("PumpMsgs: PMP_Recv failed!\n");
 
-  if (MPI_SUCCESS != MPI_Recv(buf,maxbytes,MPI_BYTE,MPI_ANY_SOURCE,TAG, MPI_COMM_WORLD,&sts))
-      CmiAbort("PumpMsgs: PMP_Recv failed!\n");
+    /*END_EVENT(30);*/
 
-  /*END_EVENT(30);*/
-    
-   MPI_Get_count(&sts, MPI_BYTE, &nbytes);
-   msg = (char *) CmiAlloc(nbytes);
-   memcpy(msg, buf, nbytes);
+    MPI_Get_count(&sts, MPI_BYTE, &nbytes);
+    msg = (char *) CmiAlloc(nbytes);
+    memcpy(msg, buf, nbytes);
 
 #if CMK_SMP_TRACE_COMMTHREAD
-        traceBeginCommOp(msg);
-       traceChangeLastTimestamp(CpvAccess(projTraceStart));
-       traceEndCommOp(msg);
-       #if CMI_MPI_TRACE_MOREDETAILED
-       char tmp[32];
-       sprintf(tmp, "To proc %d", CmiNodeFirst(CmiMyNode())+CMI_DEST_RANK(msg));
-       traceUserSuppliedBracketedNote(tmp, 30, CpvAccess(projTraceStart), CmiWallTimer());
-       #endif
-#endif
-
-#if CMK_BROADCAST_SPANNING_TREE
-   if (CMI_BROADCAST_ROOT(msg))
-      SendSpanningChildren(nbytes, msg);
-#elif CMK_BROADCAST_HYPERCUBE
-   if (CMI_BROADCAST_ROOT(msg))
-      SendHypercube(nbytes, msg);
-#endif
-  
-       /* In SMP mode, this push operation needs to be executed
-     * after forwarding broadcast messages. If it is executed
-     * earlier, then during the bcast msg forwarding period,   
-        * the msg could be already freed on the worker thread.
-        * As a result, the forwarded message could be wrong! 
-        * --Chao Mei
-        */  
-#if CMK_NODE_QUEUE_AVAILABLE
-   if (CMI_DEST_RANK(msg)==DGRAM_NODEMESSAGE)
-      CmiPushNode(msg);
-   else
-#endif
-      CmiPushPE(CMI_DEST_RANK(msg), msg);
+    traceBeginCommOp(msg);
+    traceChangeLastTimestamp(CpvAccess(projTraceStart));
+    traceEndCommOp(msg);
+#if CMI_MPI_TRACE_MOREDETAILED
+    char tmp[32];
+    sprintf(tmp, "To proc %d", CmiNodeFirst(CmiMyNode())+CMI_DEST_RANK(msg));
+    traceUserSuppliedBracketedNote(tmp, 30, CpvAccess(projTraceStart), CmiWallTimer());
+#endif
+#endif
+
+    handleOneRecvedMsg(nbytes, msg);
 }
 
-/********************* MESSAGE RECEIVE FUNCTIONS ******************/
 
 #if CMK_SMP
 
-static int inexit = 0;
-static CmiNodeLock  exitLock = 0;
+/* called by communication thread in SMP */
+static int SendMsgBuf() {
+    SMSG_LIST *msg_tmp;
+    char *msg;
+    int node, rank, size;
+    int i;
+    int sent = 0;
+
+#if CMI_EXERT_SEND_CAP || CMI_DYNAMIC_EXERT_CAP
+    int sentCnt = 0;
+#endif
 
-static int MsgQueueEmpty()
-{
-  int i;
+#if CMI_DYNAMIC_EXERT_CAP
+    dynamicSendCap = CMI_DYNAMIC_MAXCAPSIZE;
+#endif
+
+    MACHSTATE(2,"SendMsgBuf begin {");
 #if MULTI_SENDQUEUE
-  for (i=0; i<_Cmi_mynodesize; i++)
-    if (!PCQueueEmpty(procState[i].sendMsgBuf)) return 0;
+    for (i=0; i<_Cmi_mynodesize+1; i++) { /* subtle: including comm thread */
+        if (!PCQueueEmpty(procState[i].sendMsgBuf)) {
+            msg_tmp = (SMSG_LIST *)PCQueuePop(procState[i].sendMsgBuf);
 #else
-  return PCQueueEmpty(sendMsgBuf);
+    /* single message sending queue */
+    /* CmiLock(sendMsgBufLock); */
+    msg_tmp = (SMSG_LIST *)PCQueuePop(sendMsgBuf);
+    /* CmiUnlock(sendMsgBufLock); */
+    while (NULL != msg_tmp) {
 #endif
-  return 1;
-}
+            node = msg_tmp->destpe;
+            size = msg_tmp->size;
+            msg = msg_tmp->msg;
+            msg_tmp->next = 0;
 
-static int SendMsgBuf();
+#if !CMI_DYNAMIC_EXERT_CAP && !CMI_EXERT_SEND_CAP
+            while (MsgQueueLen > request_max) {
+                CmiReleaseSentMessages();
+                PumpMsgs();
+            }
+#endif
 
-/* test if all processors recv queues are empty */
-static int RecvQueueEmpty()
-{
-  int i;
-  for (i=0; i<_Cmi_mynodesize; i++) {
-    CmiState cs=CmiGetStateN(i);
-    if (!PCQueueEmpty(cs->recv)) return 0;
-  }
-  return 1;
-}
-
-/**
-CommunicationServer calls MPI to send messages in the queues and probe message from network.
-*/
-
-#define REPORT_COMM_METRICS 0
-#if REPORT_COMM_METRICS
-static double pumptime = 0.0;
-static double releasetime = 0.0;
-static double sendtime = 0.0;
+            MACHSTATE2(3,"MPI_send to node %d rank: %d{", node, CMI_DEST_RANK(msg));
+#if CMK_ERROR_CHECKING
+            CMI_MAGIC(msg) = CHARM_MAGIC_NUMBER;
 #endif
+            CMI_SET_CHECKSUM(msg, size);
 
-static void CommunicationServer(int sleepTime)
-{
-  int static count=0;
-/*
-  count ++;
-  if (count % 10000000==0) MACHSTATE(3, "Entering CommunicationServer {");
-*/
-#if REPORT_COMM_METRICS
-  double t1, t2, t3, t4;
-  t1 = CmiWallTimer();
-#endif
-  PumpMsgs();
-#if REPORT_COMM_METRICS
-  t2 = CmiWallTimer();
-#endif
-  CmiReleaseSentMessages();
-#if REPORT_COMM_METRICS
-  t3 = CmiWallTimer();
-#endif
-  SendMsgBuf();
-#if REPORT_COMM_METRICS
-  t4 = CmiWallTimer();
-  pumptime += (t2-t1);
-  releasetime += (t3-t2);
-  sendtime += (t4-t3);
-#endif
-/*
-  if (count % 10000000==0) MACHSTATE(3, "} Exiting CommunicationServer.");
-*/
-  if (inexit == CmiMyNodeSize()) {
-    MACHSTATE(2, "CommunicationServer exiting {");
-#if 0
-    while(!MsgQueueEmpty() || !CmiAllAsyncMsgsSent() || !RecvQueueEmpty()) {
+#if MPI_POST_RECV_COUNT > 0
+            if (size>=MPI_POST_RECV_LOWERSIZE && size <= MPI_POST_RECV_UPPERSIZE) {
+                START_EVENT();
+                if (MPI_SUCCESS != MPI_Isend((void *)msg,size,MPI_BYTE,node,POST_RECV_TAG,MPI_COMM_WORLD,&(msg_tmp->req)))
+                    CmiAbort("MachineSpecificSendForMPI: MPI_Isend failed!\n");
+                END_EVENT(40);
+            } else {
+                START_EVENT();
+                if (MPI_SUCCESS != MPI_Isend((void *)msg,size,MPI_BYTE,node,TAG,MPI_COMM_WORLD,&(msg_tmp->req)))
+                    CmiAbort("MachineSpecificSendForMPI: MPI_Isend failed!\n");
+                END_EVENT(40);
+            }
+#else
+            START_EVENT();
+            if (MPI_SUCCESS != MPI_Isend((void *)msg,size,MPI_BYTE,node,TAG,MPI_COMM_WORLD,&(msg_tmp->req)))
+                CmiAbort("MachineSpecificSendForMPI: MPI_Isend failed!\n");
+            /*END_EVENT(40);*/
 #endif
-    while(!MsgQueueEmpty() || !CmiAllAsyncMsgsSent()) {
-      CmiReleaseSentMessages();
-      SendMsgBuf();
-      PumpMsgs();
-    }
-    MACHSTATE(2, "CommunicationServer barrier begin {");
 
-    START_EVENT();
-
-    if (MPI_SUCCESS != MPI_Barrier(MPI_COMM_WORLD))
-      CmiAbort("ConverseExit: MPI_Barrier failed!\n");
+#if CMK_SMP_TRACE_COMMTHREAD
+            traceBeginCommOp(msg);
+            traceChangeLastTimestamp(CpvAccess(projTraceStart));
+            /* traceSendMsgComm must execute after traceBeginCommOp because
+                 * we pretend we execute an entry method, and inside this we
+                 * pretend we will send another message. Otherwise how could
+                 * a message creation just before an entry method invocation?
+                 * If such logic is broken, the projections will not trace
+                 * messages correctly! -Chao Mei
+                 */
+            traceSendMsgComm(msg);
+            traceEndCommOp(msg);
+#if CMI_MPI_TRACE_MOREDETAILED
+            char tmp[64];
+            sprintf(tmp, "MPI_Isend: from proc %d to proc %d", msg_tmp->srcpe, CmiNodeFirst(node)+CMI_DEST_RANK(msg));
+            traceUserSuppliedBracketedNote(tmp, 40, CpvAccess(projTraceStart), CmiWallTimer());
+#endif
+#endif
+
+
+            MACHSTATE(3,"}MPI_send end");
+            MsgQueueLen++;
+            if (sent_msgs==0)
+                sent_msgs = msg_tmp;
+            else
+                end_sent->next = msg_tmp;
+            end_sent = msg_tmp;
+            sent=1;
 
-    END_EVENT(10);
+#if CMI_EXERT_SEND_CAP
+            if (++sentCnt == SEND_CAP) break;
+#elif CMI_DYNAMIC_EXERT_CAP
+            if (++sentCnt >= dynamicSendCap) break;
+            if (MsgQueueLen > CMI_DYNAMIC_OUTGOING_THRESHOLD)
+                dynamicSendCap = CMI_DYNAMIC_SEND_CAPSIZE;
+#endif
 
-    MACHSTATE(2, "} CommunicationServer barrier end");
-#if (CMK_DEBUG_MODE || CMK_WEB_MODE || NODE_0_IS_CONVHOST)
-    if (CmiMyNode() == 0){
-      CmiPrintf("End of program\n");
-         #if MPI_POST_RECV_COUNT > 0
-        CmiPrintf("%llu posted receives,  %llu unposted receives\n", CpvAccess(Cmi_posted_recv_total), CpvAccess(Cmi_unposted_recv_total));
-         #endif
+#if ! MULTI_SENDQUEUE
+            /* CmiLock(sendMsgBufLock); */
+            msg_tmp = (SMSG_LIST *)PCQueuePop(sendMsgBuf);
+            /* CmiUnlock(sendMsgBufLock); */
+#endif
+        }
+#if MULTI_SENDQUEUE
     }
 #endif
-    MACHSTATE(2, "} CommunicationServer EXIT");
+    MACHSTATE(2,"}SendMsgBuf end ");
+    return sent;
+}
 
-    ConverseCommonExit();   
-#if REPORT_COMM_METRICS
-    CmiPrintf("Report comm metrics from node %d[%d-%d]: pumptime: %f, releasetime: %f, senttime: %f\n", CmiMyNode(), CmiNodeFirst(CmiMyNode()), CmiNodeFirst(CmiMyNode())+CmiMyNodeSize()-1, pumptime, releasetime, sendtime);
+static int MsgQueueEmpty() {
+    int i;
+#if MULTI_SENDQUEUE
+    for (i=0; i<_Cmi_mynodesize; i++)
+        if (!PCQueueEmpty(procState[i].sendMsgBuf)) return 0;
+#else
+    return PCQueueEmpty(sendMsgBuf);
 #endif
+    return 1;
+}
 
-#if ! CMK_AUTOBUILD
-    signal(SIGINT, signal_int);
-    MPI_Finalize();
-    #endif
-    exit(0);
-  }
+/* test if all processors recv queues are empty */
+static int RecvQueueEmpty() {
+    int i;
+    for (i=0; i<_Cmi_mynodesize; i++) {
+        CmiState cs=CmiGetStateN(i);
+        if (!PCQueueEmpty(cs->recv)) return 0;
+    }
+    return 1;
 }
 
-#endif
 
-static void CommunicationServerThread(int sleepTime)
-{
-#if CMK_SMP
-  CommunicationServer(sleepTime);
-#endif
-#if CMK_IMMEDIATE_MSG
-  CmiHandleImmediate();
+#define REPORT_COMM_METRICS 0
+#if REPORT_COMM_METRICS
+static double pumptime = 0.0;
+static double releasetime = 0.0;
+static double sendtime = 0.0;
 #endif
-}
 
-#if CMK_NODE_QUEUE_AVAILABLE
-char *CmiGetNonLocalNodeQ(void)
-{
-  CmiState cs = CmiGetState();
-  char *result = 0;
-  CmiIdleLock_checkMessage(&cs->idle);
-/*  if(!PCQueueEmpty(CsvAccess(NodeState).NodeRecv)) {  */
-    MACHSTATE1(3,"CmiGetNonLocalNodeQ begin %d {", CmiMyPe());
-    CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
-    result = (char *) PCQueuePop(CsvAccess(NodeState).NodeRecv);
-    CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
-    MACHSTATE1(3,"} CmiGetNonLocalNodeQ end %d ", CmiMyPe());
-/*  }  */
-
-  return result;
-}
+#endif //end of CMK_SMP
+
+static void AdvanceCommunicationForMPI() {
+#if REPORT_COMM_METRICS
+    double t1, t2, t3, t4;
+    t1 = CmiWallTimer();
 #endif
 
-void *CmiGetNonLocal(void)
-{
-  static int count=0;
-  CmiState cs = CmiGetState();
-  void *msg;
+#if CMK_SMP
+    PumpMsgs();
 
-#if ! CMK_SMP
-  if (CmiNumPes() == 1) return NULL;
+#if REPORT_COMM_METRICS
+    t2 = CmiWallTimer();
 #endif
 
-  CmiIdleLock_checkMessage(&cs->idle);
-  /* although it seems that lock is not needed, I found it crashes very often
-     on mpi-smp without lock */
-
-#if ! CMK_SMP
-  CmiReleaseSentMessages();
-  PumpMsgs();
+    CmiReleaseSentMessages();
+#if REPORT_COMM_METRICS
+    t3 = CmiWallTimer();
 #endif
 
-  /* CmiLock(procState[cs->rank].recvLock); */
-  msg =  PCQueuePop(cs->recv);
-  /* CmiUnlock(procState[cs->rank].recvLock); */
+    SendMsgBuf();
 
-/*
-  if (msg) {
-    MACHSTATE2(3,"CmiGetNonLocal done on pe %d for queue %p", CmiMyPe(), cs->recv); }
-  else {
-    count++;
-    if (count%1000000==0) MACHSTATE2(3,"CmiGetNonLocal empty on pe %d for queue %p", CmiMyPe(), cs->recv);
-  }
-*/
-#if ! CMK_SMP
-  if (no_outstanding_sends) {
-    while (MsgQueueLen>0) {
-      CmiReleaseSentMessages();
-      PumpMsgs();
-    }
-  }
+#if REPORT_COMM_METRICS
+    t4 = CmiWallTimer();
+    pumptime += (t2-t1);
+    releasetime += (t3-t2);
+    sendtime += (t4-t3);
+#endif
 
-  if(!msg) {
+#else /* non-SMP case */
     CmiReleaseSentMessages();
-    if (PumpMsgs())
-      return  PCQueuePop(cs->recv);
-    else
-      return 0;
-  }
+
+#if REPORT_COMM_METRICS
+    t2 = CmiWallTimer();
 #endif
+    PumpMsgs();
 
-  return msg;
-}
+#if REPORT_COMM_METRICS
+    t3 = CmiWallTimer();
+    pumptime += (t3-t2);
+    releasetime += (t2-t1);
+#endif
 
-/* called in non-smp mode */
-void CmiNotifyIdle(void)
-{
-  CmiReleaseSentMessages();
-  if (!PumpMsgs() && idleblock) PumpMsgsBlocking();
+#endif /* end of #if CMK_SMP */
 }
+/* ######End of functions related with communication progress ###### */
 
-
-/********************************************************
-    The call to probe immediate messages has been renamed to
-    CmiMachineProgressImpl
-******************************************************/
-/* user call to handle immediate message, only useful in non SMP version
-   using polling method to schedule message.
-*/
-/*
-#if CMK_IMMEDIATE_MSG
-void CmiProbeImmediateMsg()
-{
+void MachinePostNonLocalForMPI() {
 #if !CMK_SMP
-  PumpMsgs();
-  CmiHandleImmediate();
+    if (no_outstanding_sends) {
+        while (MsgQueueLen>0) {
+            AdvanceCommunicationForMPI();
+        }
+    }
+
+    /* FIXME: I don't think the following codes are needed because
+     * it repeats the same job of the next call of CmiGetNonLocal
+     */
+#if 0
+    if (!msg) {
+        CmiReleaseSentMessages();
+        if (PumpMsgs())
+            return  PCQueuePop(cs->recv);
+        else
+            return 0;
+    }
 #endif
-}
 #endif
-*/
+}
+
+/* Idle-state related functions: called in non-smp mode */
+void CmiNotifyIdleForMPI(void) {
+    CmiReleaseSentMessages();
+    if (!PumpMsgs() && idleblock) PumpMsgsBlocking();
+}
 
 /* Network progress function is used to poll the network when for
    messages. This flushes receive buffers on some  implementations*/
 #if CMK_MACHINE_PROGRESS_DEFINED
-void CmiMachineProgressImpl()
-{
+void CmiMachineProgressImpl() {
 #if !CMK_SMP
     PumpMsgs();
 #if CMK_IMMEDIATE_MSG
@@ -1001,661 +905,101 @@ void CmiMachineProgressImpl()
 }
 #endif
 
-/********************* MESSAGE SEND FUNCTIONS ******************/
-
-CmiCommHandle CmiAsyncSendFn_(int destPE, int size, char *msg);
-
-static void CmiSendSelf(char *msg)
-{
-#if CMK_IMMEDIATE_MSG
-    if (CmiIsImmediate(msg)) {
-      /* CmiBecomeNonImmediate(msg); */
-      CmiPushImmediateMsg(msg);
-      CmiHandleImmediate();
-      return;
+/* ######Beginning of functions related with exiting programs###### */
+void DrainResourcesForMPI() {
+#if !CMK_SMP
+    while (!CmiAllAsyncMsgsSent()) {
+        PumpMsgs();
+        CmiReleaseSentMessages();
     }
-#endif
-    CQdCreate(CpvAccess(cQdState), 1);
-    CdsFifo_Enqueue(CpvAccess(CmiLocalQueue),msg);
-}
-
-void CmiSyncSendFn(int destPE, int size, char *msg)
-{
-  CmiState cs = CmiGetState();
-  char *dupmsg = (char *) CmiAlloc(size);
-  memcpy(dupmsg, msg, size);
-
-  CMI_SET_BROADCAST_ROOT(dupmsg, 0);
-
-  if (cs->pe==destPE) {
-    CmiSendSelf(dupmsg);
-  }
-  else
-    CmiAsyncSendFn_(destPE, size, dupmsg);
-}
-
-#if CMK_SMP
-
-/* called by communication thread in SMP */
-static int SendMsgBuf()
-{
-  SMSG_LIST *msg_tmp;
-  char *msg;
-  int node, rank, size;
-  int i;
-  int sent = 0;
-
-#if CMI_EXERT_SEND_CAP || CMI_DYNAMIC_EXERT_CAP
-       int sentCnt = 0;
-#endif 
-       
-#if CMI_DYNAMIC_EXERT_CAP
-       dynamicSendCap = CMI_DYNAMIC_MAXCAPSIZE;
-#endif
-       
-  MACHSTATE(2,"SendMsgBuf begin {");
-#if MULTI_SENDQUEUE
-  for (i=0; i<_Cmi_mynodesize=1; i++)  /* subtle: including comm thread */
-  {
-    if (!PCQueueEmpty(procState[i].sendMsgBuf))
-    {
-      msg_tmp = (SMSG_LIST *)PCQueuePop(procState[i].sendMsgBuf);
 #else
-    /* single message sending queue */
-    /* CmiLock(sendMsgBufLock); */
-    msg_tmp = (SMSG_LIST *)PCQueuePop(sendMsgBuf);
-    /* CmiUnlock(sendMsgBufLock); */
-    while (NULL != msg_tmp)
-    {
-#endif
-      node = msg_tmp->destpe;
-      size = msg_tmp->size;
-      msg = msg_tmp->msg;
-      msg_tmp->next = 0;
-               
-#if !CMI_DYNAMIC_EXERT_CAP && !CMI_EXERT_SEND_CAP
-      while (MsgQueueLen > request_max) {
-               CmiReleaseSentMessages();
-               PumpMsgs();
-      }
-#endif
-         
-      MACHSTATE2(3,"MPI_send to node %d rank: %d{", node, CMI_DEST_RANK(msg));
-#if CMK_ERROR_CHECKING
-      CMI_MAGIC(msg) = CHARM_MAGIC_NUMBER;
-#endif
-      CMI_SET_CHECKSUM(msg, size);
-
-#if MPI_POST_RECV_COUNT > 0
-        if(size>=MPI_POST_RECV_LOWERSIZE && size <= MPI_POST_RECV_UPPERSIZE){
-          START_EVENT();
-          if (MPI_SUCCESS != MPI_Isend((void *)msg,size,MPI_BYTE,node,POST_RECV_TAG,MPI_COMM_WORLD,&(msg_tmp->req)))
-                CmiAbort("CmiAsyncSendFn: MPI_Isend failed!\n");
-          END_EVENT(40);
-        }
-        else {
-            START_EVENT();
-            if (MPI_SUCCESS != MPI_Isend((void *)msg,size,MPI_BYTE,node,TAG,MPI_COMM_WORLD,&(msg_tmp->req)))
-                CmiAbort("CmiAsyncSendFn: MPI_Isend failed!\n");
-            END_EVENT(40);
-        }
-#else
-        START_EVENT();
-        if (MPI_SUCCESS != MPI_Isend((void *)msg,size,MPI_BYTE,node,TAG,MPI_COMM_WORLD,&(msg_tmp->req)))
-            CmiAbort("CmiAsyncSendFn: MPI_Isend failed!\n");
-        /*END_EVENT(40);*/
-#endif
-       
-#if CMK_SMP_TRACE_COMMTHREAD
-       traceBeginCommOp(msg);
-       traceChangeLastTimestamp(CpvAccess(projTraceStart));
-       /* traceSendMsgComm must execute after traceBeginCommOp because
-         * we pretend we execute an entry method, and inside this we
-         * pretend we will send another message. Otherwise how could
-         * a message creation just before an entry method invocation?
-         * If such logic is broken, the projections will not trace
-         * messages correctly! -Chao Mei
-         */
-       traceSendMsgComm(msg);
-       traceEndCommOp(msg);
-       #if CMI_MPI_TRACE_MOREDETAILED
-       char tmp[64];
-       sprintf(tmp, "MPI_Isend: from proc %d to proc %d", msg_tmp->srcpe, CmiNodeFirst(node)+CMI_DEST_RANK(msg));
-       traceUserSuppliedBracketedNote(tmp, 40, CpvAccess(projTraceStart), CmiWallTimer());
-       #endif
-#endif
-               
-               
-      MACHSTATE(3,"}MPI_send end");
-      MsgQueueLen++;
-      if(sent_msgs==0)
-        sent_msgs = msg_tmp;
-      else
-        end_sent->next = msg_tmp;
-      end_sent = msg_tmp;
-      sent=1;
-         
-#if CMI_EXERT_SEND_CAP   
-         if(++sentCnt == SEND_CAP) break;
-#elif CMI_DYNAMIC_EXERT_CAP
-         if(++sentCnt >= dynamicSendCap) break;
-         if(MsgQueueLen > CMI_DYNAMIC_OUTGOING_THRESHOLD)
-                 dynamicSendCap = CMI_DYNAMIC_SEND_CAPSIZE;
-#endif   
-         
-#if ! MULTI_SENDQUEUE
-      /* CmiLock(sendMsgBufLock); */
-      msg_tmp = (SMSG_LIST *)PCQueuePop(sendMsgBuf);
-      /* CmiUnlock(sendMsgBufLock); */
-#endif
+    while (!MsgQueueEmpty() || !CmiAllAsyncMsgsSent()) {
+        CmiReleaseSentMessages();
+        SendMsgBuf();
+        PumpMsgs();
     }
-#if MULTI_SENDQUEUE
-  }
-#endif
-  MACHSTATE(2,"}SendMsgBuf end ");
-  return sent;
-}
-
-void EnqueueMsg(void *m, int size, int node)
-{
-  SMSG_LIST *msg_tmp = (SMSG_LIST *) CmiAlloc(sizeof(SMSG_LIST));
-  MACHSTATE1(3,"EnqueueMsg to node %d {{ ", node);
-  msg_tmp->msg = m;
-  msg_tmp->size = size;
-  msg_tmp->destpe = node;
-       
-#if CMK_SMP_TRACE_COMMTHREAD
-       msg_tmp->srcpe = CmiMyPe();
-#endif 
-
-#if MULTI_SENDQUEUE
-  PCQueuePush(procState[CmiMyRank()].sendMsgBuf,(char *)msg_tmp);
-#else
-  CmiLock(sendMsgBufLock);
-  PCQueuePush(sendMsgBuf,(char *)msg_tmp);
-  CmiUnlock(sendMsgBufLock);
 #endif
-       
-  MACHSTATE3(3,"}} EnqueueMsg to %d finish with queue %p len: %d", node, sendMsgBuf, PCQueueLength(sendMsgBuf));
+    MACHSTATE(2, "Machine exit barrier begin {");
+    START_EVENT();
+    if (MPI_SUCCESS != MPI_Barrier(MPI_COMM_WORLD))
+        CmiAbort("DrainResourcesForMPI: MPI_Barrier failed!\n");
+    END_EVENT(10);
+    MACHSTATE(2, "} Machine exit barrier end");
 }
 
-#endif
-
-CmiCommHandle CmiAsyncSendFn_(int destPE, int size, char *msg)
-{
-  CmiState cs = CmiGetState();
-  SMSG_LIST *msg_tmp;
-  CmiUInt2  rank, node;
-
-  if(destPE == cs->pe) {
-    char *dupmsg = (char *) CmiAlloc(size);
-    memcpy(dupmsg, msg, size);
-    CmiSendSelf(dupmsg);
-    return 0;
-  }
-  CQdCreate(CpvAccess(cQdState), 1);
+void MachineExitForMPI(void) {
+#if (CMK_DEBUG_MODE || CMK_WEB_MODE || NODE_0_IS_CONVHOST)
+    int doPrint = 0;
 #if CMK_SMP
-  node = CmiNodeOf(destPE);
-  rank = CmiRankOf(destPE);
-  if (node == CmiMyNode())  {
-    CmiPushPE(rank, msg);
-    return 0;
-  }
-  CMI_DEST_RANK(msg) = rank;
-  EnqueueMsg(msg, size, node);
-  return 0;
+    if (CmiMyNode()==0) doPrint = 1;
 #else
-  /* non smp */
-  CMI_DEST_RANK(msg) = 0;      /* rank is always 0 */
-  msg_tmp = (SMSG_LIST *) CmiAlloc(sizeof(SMSG_LIST));
-  msg_tmp->msg = msg;
-  msg_tmp->next = 0;
-  while (MsgQueueLen > request_max) {
-       /*printf("Waiting for %d messages to be sent\n", MsgQueueLen);*/
-       CmiReleaseSentMessages();
-       PumpMsgs();
-  }
-#if CMK_ERROR_CHECKING
-  CMI_MAGIC(msg) = CHARM_MAGIC_NUMBER;
+    if (CmiMyPe()==0) doPrint = 1;
 #endif
-  CMI_SET_CHECKSUM(msg, size);
 
+    if (doPrint) {
 #if MPI_POST_RECV_COUNT > 0
-               if(size>=MPI_POST_RECV_LOWERSIZE && size <= MPI_POST_RECV_UPPERSIZE){
-          START_EVENT();
-          if (MPI_SUCCESS != MPI_Isend((void *)msg,size,MPI_BYTE,destPE,POST_RECV_TAG,MPI_COMM_WORLD,&(msg_tmp->req)))
-                CmiAbort("CmiAsyncSendFn: MPI_Isend failed!\n");
-          END_EVENT(40);
-        }
-        else {
-          START_EVENT();
-          if (MPI_SUCCESS != MPI_Isend((void *)msg,size,MPI_BYTE,destPE,TAG,MPI_COMM_WORLD,&(msg_tmp->req)))
-                CmiAbort("CmiAsyncSendFn: MPI_Isend failed!\n");
-          END_EVENT(40);
-        }
-#else
-  START_EVENT();
-  if (MPI_SUCCESS != MPI_Isend((void *)msg,size,MPI_BYTE,destPE,TAG,MPI_COMM_WORLD,&(msg_tmp->req)))
-    CmiAbort("CmiAsyncSendFn: MPI_Isend failed!\n");
-  /*END_EVENT(40);*/
-  #if CMK_TRACE_COMMOVERHEAD
-       char tmp[64];
-       sprintf(tmp, "MPI_Isend: from proc %d to proc %d", CmiMyPe(), destPE);
-       traceUserSuppliedBracketedNote(tmp, 40, CpvAccess(projTraceStart), CmiWallTimer());
-  #endif
-#endif
-
-  MsgQueueLen++;
-  if(sent_msgs==0)
-    sent_msgs = msg_tmp;
-  else
-    end_sent->next = msg_tmp;
-  end_sent = msg_tmp;
-  return (CmiCommHandle) &(msg_tmp->req);
-#endif              /* non-smp */
-}
-
-CmiCommHandle CmiAsyncSendFn(int destPE, int size, char *msg)
-{
-  CMI_SET_BROADCAST_ROOT(msg, 0);
-  CmiAsyncSendFn_(destPE, size, msg);
-}
-
-void CmiFreeSendFn(int destPE, int size, char *msg)
-{
-  CmiState cs = CmiGetState();
-  CMI_SET_BROADCAST_ROOT(msg, 0);
-
-  if (cs->pe==destPE) {
-    CmiSendSelf(msg);
-  } else {
-    CmiAsyncSendFn_(destPE, size, msg);
-  }
-}
-
-/*********************** BROADCAST FUNCTIONS **********************/
-
-/* same as CmiSyncSendFn, but don't set broadcast root in msg header */
-void CmiSyncSendFn1(int destPE, int size, char *msg)
-{
-  CmiState cs = CmiGetState();
-  char *dupmsg = (char *) CmiAlloc(size);
-  memcpy(dupmsg, msg, size);
-  if (cs->pe==destPE)
-    CmiSendSelf(dupmsg);
-  else
-    CmiAsyncSendFn_(destPE, size, dupmsg);
-}
-
-/* send msg to its spanning children in broadcast. G. Zheng */
-void SendSpanningChildren(int size, char *msg)
-{
-  CmiState cs = CmiGetState();
-  int startpe = CMI_BROADCAST_ROOT(msg)-1;
-  int startnode = CmiNodeOf(startpe);
-  int i, exceptRank;
-       
-   /* first send msgs to other nodes */
-  CmiAssert(startnode >=0 &&  startnode<CmiNumNodes());
-  for (i=1; i<=BROADCAST_SPANNING_FACTOR; i++) {
-    int nd = CmiMyNode()-startnode;
-    if (nd<0) nd+=CmiNumNodes();
-    nd = BROADCAST_SPANNING_FACTOR*nd + i;
-    if (nd > CmiNumNodes() - 1) break;
-    nd += startnode;
-    nd = nd%CmiNumNodes();
-    CmiAssert(nd>=0 && nd!=CmiMyNode());       
-#if CMK_SMP
-      /* always send to the first rank of other nodes */
-    char *newmsg = CmiCopyMsg(msg, size);
-    CMI_DEST_RANK(newmsg) = 0;
-    EnqueueMsg(newmsg, size, nd);
-#else
-    CmiSyncSendFn1(nd, size, msg);
-#endif
-  }
-#if CMK_SMP  
-   /* second send msgs to my peers on this node */
-  /* FIXME: now it's just a flat p2p send!! When node size is large,
-   * it should also be sent in a tree
-   */
-   exceptRank = CMI_DEST_RANK(msg);
-   for(i=0; i<exceptRank; i++){
-          CmiPushPE(i, CmiCopyMsg(msg, size));
-   }
-   for(i=exceptRank+1; i<CmiMyNodeSize(); i++){
-          CmiPushPE(i, CmiCopyMsg(msg, size));
-   }
-#endif
-}
-
-#include <math.h>
-
-/* send msg along the hypercube in broadcast. (Sameer) */
-void SendHypercube(int size, char *msg)
-{
-  CmiState cs = CmiGetState();
-  int startpe = CMI_BROADCAST_ROOT(msg)-1;
-  int startnode = CmiNodeOf(startpe);
-  int i, exceptRank, cnt, tmp, relPE;
-  int dims=0;
-
-  /* dims = ceil(log2(CmiNumNodes)) except when #nodes is 1*/
-  tmp = CmiNumNodes()-1;
-  while(tmp>0){
-         dims++;
-         tmp = tmp >> 1;
-  }
-  if(CmiNumNodes()==1) dims=1;
-  
-   /* first send msgs to other nodes */  
-  relPE = CmiMyNode()-startnode;
-  if(relPE < 0) relPE += CmiNumNodes();
-  cnt=0;
-  tmp = relPE;
-  /* count how many zeros (in binary format) relPE has */
-  for(i=0; i<dims; i++, cnt++){
-    if(tmp & 1 == 1) break;
-    tmp = tmp >> 1;
-  }
-  
-  /*CmiPrintf("ND[%d]: SendHypercube with spe=%d, snd=%d, relpe=%d, cnt=%d\n", CmiMyNode(), startpe, startnode, relPE, cnt);*/
-  for (i = cnt-1; i >= 0; i--) {
-    int nd = relPE + (1 << i);
-       if(nd >= CmiNumNodes()) continue;
-       nd = (nd+startnode)%CmiNumNodes();
-       /*CmiPrintf("ND[%d]: send to node %d\n", CmiMyNode(), nd);*/
-#if CMK_SMP
-    /* always send to the first rank of other nodes */
-    char *newmsg = CmiCopyMsg(msg, size);
-    CMI_DEST_RANK(newmsg) = 0;
-    EnqueueMsg(newmsg, size, nd);
-#else
-       CmiSyncSendFn1(nd, size, msg);
-#endif
-  }
-  
-#if CMK_SMP
-   /* second send msgs to my peers on this node */
-   /* FIXME: now it's just a flat p2p send!! When node size is large,
-    * it should also be sent in a tree
-    */
-   exceptRank = CMI_DEST_RANK(msg);
-   for(i=0; i<exceptRank; i++){
-          CmiPushPE(i, CmiCopyMsg(msg, size));
-   }
-   for(i=exceptRank+1; i<CmiMyNodeSize(); i++){
-          CmiPushPE(i, CmiCopyMsg(msg, size));
-   }
-#endif
-}
-
-void CmiSyncBroadcastFn(int size, char *msg)     /* ALL_EXCEPT_ME  */
-{
-  CmiState cs = CmiGetState();
-
-#if CMK_SMP    
-  /* record the rank to avoid re-sending the msg in SendSpanningChildren */
-  CMI_DEST_RANK(msg) = CmiMyRank();
-#endif
-       
-#if CMK_BROADCAST_SPANNING_TREE
-  CMI_SET_BROADCAST_ROOT(msg, cs->pe+1);
-  SendSpanningChildren(size, msg);
-
-#elif CMK_BROADCAST_HYPERCUBE
-  CMI_SET_BROADCAST_ROOT(msg, cs->pe+1);
-  SendHypercube(size, msg);
-
-#else
-  int i;
-
-  for ( i=cs->pe+1; i<_Cmi_numpes; i++ )
-    CmiSyncSendFn(i, size,msg) ;
-  for ( i=0; i<cs->pe; i++ )
-    CmiSyncSendFn(i, size,msg) ;
+        CmiPrintf("%llu posted receives,  %llu unposted receives\n", CpvAccess(Cmi_posted_recv_total), CpvAccess(Cmi_unposted_recv_total));
 #endif
-
-  /*CmiPrintf("In  SyncBroadcast broadcast\n");*/
-}
-
-
-/*  FIXME: luckily async is never used  G. Zheng */
-CmiCommHandle CmiAsyncBroadcastFn(int size, char *msg)
-{
-  CmiState cs = CmiGetState();
-  int i ;
-
-  for ( i=cs->pe+1; i<_Cmi_numpes; i++ )
-    CmiAsyncSendFn(i,size,msg) ;
-  for ( i=0; i<cs->pe; i++ )
-    CmiAsyncSendFn(i,size,msg) ;
-
-  /*CmiPrintf("In  AsyncBroadcast broadcast\n");*/
-  CmiAbort("CmiAsyncBroadcastFn should never be called");
-  return (CmiCommHandle) (CmiAllAsyncMsgsSent());
-}
-
-void CmiFreeBroadcastFn(int size, char *msg)
-{
-   CmiSyncBroadcastFn(size,msg);
-   CmiFree(msg);
-}
-
-void CmiSyncBroadcastAllFn(int size, char *msg)        /* All including me */
-{
-
-#if CMK_SMP    
-  /* record the rank to avoid re-sending the msg in SendSpanningChildren */
-  CMI_DEST_RANK(msg) = CmiMyRank();
+    }
 #endif
 
-#if CMK_BROADCAST_SPANNING_TREE
-  CmiState cs = CmiGetState();
-  CmiSyncSendFn(cs->pe, size,msg) ;
-  CMI_SET_BROADCAST_ROOT(msg, cs->pe+1);
-  SendSpanningChildren(size, msg);
-
-#elif CMK_BROADCAST_HYPERCUBE
-  CmiState cs = CmiGetState();
-  CmiSyncSendFn(cs->pe, size,msg) ;
-  CMI_SET_BROADCAST_ROOT(msg, cs->pe+1);
-  SendHypercube(size, msg);
-
+#if REPORT_COMM_METRICS
+#if CMK_SMP
+    CmiPrintf("Report comm metrics for node %d[%d-%d]: pumptime: %f, releasetime: %f, senttime: %f\n",
+              CmiMyNode(), CmiNodeFirst(CmiMyNode()), CmiNodeFirst(CmiMyNode())+CmiMyNodeSize()-1,
+              pumptime, releasetime, sendtime);
 #else
-    int i ;
-
-  for ( i=0; i<_Cmi_numpes; i++ )
-    CmiSyncSendFn(i,size,msg) ;
+    CmiPrintf("Report comm metrics for proc %d: pumptime: %f, releasetime: %f, senttime: %f\n",
+              CmiMyPe(), pumptime, releasetime, sendtime);
 #endif
-
-  /*CmiPrintf("In  SyncBroadcastAll broadcast\n");*/
-}
-
-CmiCommHandle CmiAsyncBroadcastAllFn(int size, char *msg)
-{
-  int i ;
-
-  for ( i=1; i<_Cmi_numpes; i++ )
-    CmiAsyncSendFn(i,size,msg) ;
-
-  CmiAbort("In  AsyncBroadcastAll broadcast\n");
-
-  return (CmiCommHandle) (CmiAllAsyncMsgsSent());
-}
-
-void CmiFreeBroadcastAllFn(int size, char *msg)  /* All including me */
-{
-#if CMK_SMP    
-  /* record the rank to avoid re-sending the msg in SendSpanningChildren */
-  CMI_DEST_RANK(msg) = CmiMyRank();
 #endif
 
-#if CMK_BROADCAST_SPANNING_TREE
-  CmiState cs = CmiGetState();
-  CmiSyncSendFn(cs->pe, size,msg) ;
-  CMI_SET_BROADCAST_ROOT(msg, cs->pe+1);
-  SendSpanningChildren(size, msg);
-
-#elif CMK_BROADCAST_HYPERCUBE
-  CmiState cs = CmiGetState();
-  CmiSyncSendFn(cs->pe, size,msg) ;
-  CMI_SET_BROADCAST_ROOT(msg, cs->pe+1);
-  SendHypercube(size, msg);
-
-#else
-  int i ;
-
-  for ( i=0; i<_Cmi_numpes; i++ )
-    CmiSyncSendFn(i,size,msg) ;
+#if ! CMK_AUTOBUILD
+    signal(SIGINT, signal_int);
+    MPI_Finalize();
 #endif
-  CmiFree(msg) ;
-  /*CmiPrintf("In FreeBroadcastAll broadcast\n");*/
+    exit(0);
 }
 
-#if CMK_NODE_QUEUE_AVAILABLE
-
-static void CmiSendNodeSelf(char *msg)
-{
-#if CMK_IMMEDIATE_MSG
-#if 0
-    if (CmiIsImmediate(msg) && !_immRunning) {
-      /*CmiHandleImmediateMessage(msg); */
-      CmiPushImmediateMsg(msg);
-      CmiHandleImmediate();
-      return;
-    }
-#endif
-    if (CmiIsImmediate(msg))
-    {
-      CmiPushImmediateMsg(msg);
-      if (!_immRunning) CmiHandleImmediate();
-      return;
+static int machine_exit_idx;
+static void machine_exit(char *m) {
+    EmergencyExit();
+    /*printf("--> %d: machine_exit\n",CmiMyPe());*/
+    fflush(stdout);
+    CmiNodeBarrier();
+    if (CmiMyRank() == 0) {
+        MPI_Barrier(MPI_COMM_WORLD);
+        /*printf("==> %d: passed barrier\n",CmiMyPe());*/
+        MPI_Abort(MPI_COMM_WORLD, 1);
+    } else {
+        while (1) CmiYield();
     }
-#endif
-    CQdCreate(CpvAccess(cQdState), 1);
-    CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
-    PCQueuePush(CsvAccess(NodeState).NodeRecv, msg);
-    CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
 }
 
-CmiCommHandle CmiAsyncNodeSendFn(int dstNode, int size, char *msg)
-{
-  int i;
-  SMSG_LIST *msg_tmp;
-  char *dupmsg;
-
-  CMI_SET_BROADCAST_ROOT(msg, 0);
-  CMI_DEST_RANK(msg) = DGRAM_NODEMESSAGE;
-  switch (dstNode) {
-  case NODE_BROADCAST_ALL:
-    CmiSendNodeSelf((char *)CmiCopyMsg(msg,size));
-  case NODE_BROADCAST_OTHERS:
-    CQdCreate(CpvAccess(cQdState), _Cmi_numnodes-1);
-    for (i=0; i<_Cmi_numnodes; i++)
-      if (i!=_Cmi_mynode) {
-        EnqueueMsg((char *)CmiCopyMsg(msg,size), size, i);
-      }
-    break;
-  default:
-    dupmsg = (char *)CmiCopyMsg(msg,size);
-    if(dstNode == _Cmi_mynode) {
-      CmiSendNodeSelf(dupmsg);
-    }
-    else {
-      CQdCreate(CpvAccess(cQdState), 1);
-      EnqueueMsg(dupmsg, size, dstNode);
+static void KillOnAllSigs(int sigNo) {
+    static int already_in_signal_handler = 0;
+    char *m;
+    if (already_in_signal_handler) MPI_Abort(MPI_COMM_WORLD,1);
+    already_in_signal_handler = 1;
+#if CMK_CCS_AVAILABLE
+    if (CpvAccess(cmiArgDebugFlag)) {
+        CpdNotify(CPD_SIGNAL, sigNo);
+        CpdFreeze();
     }
-  }
-  return 0;
-}
-
-void CmiSyncNodeSendFn(int p, int s, char *m)
-{
-  CmiAsyncNodeSendFn(p, s, m);
-}
-
-/* need */
-void CmiFreeNodeSendFn(int p, int s, char *m)
-{
-  CmiAsyncNodeSendFn(p, s, m);
-  CmiFree(m);
-}
-
-/* need */
-void CmiSyncNodeBroadcastFn(int s, char *m)
-{
-  CmiAsyncNodeSendFn(NODE_BROADCAST_OTHERS, s, m);
-}
-
-CmiCommHandle CmiAsyncNodeBroadcastFn(int s, char *m)
-{
-}
-
-/* need */
-void CmiFreeNodeBroadcastFn(int s, char *m)
-{
-  CmiAsyncNodeSendFn(NODE_BROADCAST_OTHERS, s, m);
-  CmiFree(m);
-}
-
-void CmiSyncNodeBroadcastAllFn(int s, char *m)
-{
-  CmiAsyncNodeSendFn(NODE_BROADCAST_ALL, s, m);
-}
-
-CmiCommHandle CmiAsyncNodeBroadcastAllFn(int s, char *m)
-{
-  CmiAsyncNodeSendFn(NODE_BROADCAST_ALL, s, m);
-}
-
-/* need */
-void CmiFreeNodeBroadcastAllFn(int s, char *m)
-{
-  CmiAsyncNodeSendFn(NODE_BROADCAST_ALL, s, m);
-  CmiFree(m);
-}
 #endif
+    CmiError("------------- Processor %d Exiting: Caught Signal ------------\n"
+             "Signal: %d\n",CmiMyPe(),sigNo);
+    CmiPrintStackTrace(1);
 
-/************************** MAIN ***********************************/
-#define MPI_REQUEST_MAX 16      /* 1024*10 */
-
-void ConverseExit(void)
-{
-#if ! CMK_SMP
-  while(!CmiAllAsyncMsgsSent()) {
-    PumpMsgs();
-    CmiReleaseSentMessages();
-  }
-  if (MPI_SUCCESS != MPI_Barrier(MPI_COMM_WORLD))
-    CmiAbort("ConverseExit: MPI_Barrier failed!\n");
-
-  ConverseCommonExit();
-#if (CMK_DEBUG_MODE || CMK_WEB_MODE || NODE_0_IS_CONVHOST)
-  if (CmiMyPe() == 0){
-    CmiPrintf("End of program\n");
-#if MPI_POST_RECV_COUNT > 0
-    CmiPrintf("%llu posted receives,  %llu unposted receives\n", CpvAccess(Cmi_posted_recv_total), CpvAccess(Cmi_unposted_recv_total));
-#endif
+    m = CmiAlloc(CmiMsgHeaderSizeBytes);
+    CmiSetHandler(m, machine_exit_idx);
+    CmiSyncBroadcastAndFree(CmiMsgHeaderSizeBytes, m);
+    machine_exit(m);
 }
-#endif
-#if ! CMK_AUTOBUILD
-  signal(SIGINT, signal_int);
-  MPI_Finalize();
-#endif
-  exit(0);
+/* ######End of functions related with exiting programs###### */
 
-#else
-    /* SMP version, communication thread will exit */
-  ConverseCommonExit();
-  /* atomic increment */
-  CmiLock(exitLock);
-  inexit++;
-  CmiUnlock(exitLock);
-  while (1) CmiYield();
-#endif
-}
 
+/* ######Beginning of functions related with starting programs###### */
 static void registerMPITraceEvents() {
 #if CMI_MPI_TRACE_USEREVENTS && CMK_TRACE_ENABLED && !CMK_TRACE_IN_CHARM
     traceRegisterUserEvent("MPI_Barrier", 10);
@@ -1668,396 +1012,225 @@ static void registerMPITraceEvents() {
 #endif
 }
 
-
-static char     **Cmi_argv;
-static char     **Cmi_argvcopy;
-static CmiStartFn Cmi_startfn;   /* The start function */
-static int        Cmi_usrsched;  /* Continue after start function finishes? */
-
-typedef struct {
-  int sleepMs; /*Milliseconds to sleep while idle*/
-  int nIdles; /*Number of times we've been idle in a row*/
-  CmiState cs; /*Machine state*/
-} CmiIdleState;
-
-static CmiIdleState *CmiNotifyGetState(void)
-{
-  CmiIdleState *s=(CmiIdleState *)malloc(sizeof(CmiIdleState));
-  s->sleepMs=0;
-  s->nIdles=0;
-  s->cs=CmiGetState();
-  return s;
-}
-
-static void CmiNotifyBeginIdle(CmiIdleState *s)
-{
-  s->sleepMs=0;
-  s->nIdles=0;
-}
-
-static void CmiNotifyStillIdle(CmiIdleState *s)
-{
-#if ! CMK_SMP
-  CmiReleaseSentMessages();
-  PumpMsgs();
-#else
-/*  CmiYield();  */
-#endif
-
-#if 1
-  {
-  int nSpins=20; /*Number of times to spin before sleeping*/
-  MACHSTATE1(2,"still idle (%d) begin {",CmiMyPe())
-  s->nIdles++;
-  if (s->nIdles>nSpins) { /*Start giving some time back to the OS*/
-    s->sleepMs+=2;
-    if (s->sleepMs>10) s->sleepMs=10;
-  }
-  /*Comm. thread will listen on sockets-- just sleep*/
-  if (s->sleepMs>0) {
-    MACHSTATE1(2,"idle lock(%d) {",CmiMyPe())
-    CmiIdleLock_sleep(&s->cs->idle,s->sleepMs);
-    MACHSTATE1(2,"} idle lock(%d)",CmiMyPe())
-  }
-  MACHSTATE1(2,"still idle (%d) end {",CmiMyPe())
-  }
-#endif
-}
-
 #if MACHINE_DEBUG_LOG
 FILE *debugLog = NULL;
 #endif
 
-static int machine_exit_idx;
-static void machine_exit(char *m) {
-  EmergencyExit();
-  /*printf("--> %d: machine_exit\n",CmiMyPe());*/
-  fflush(stdout);
-  CmiNodeBarrier();
-  if (CmiMyRank() == 0) {
-    MPI_Barrier(MPI_COMM_WORLD);
-    /*printf("==> %d: passed barrier\n",CmiMyPe());*/
-    MPI_Abort(MPI_COMM_WORLD, 1);
-  } else {
-    while (1) CmiYield();
-  }
-}
-
-static void KillOnAllSigs(int sigNo) {
-  static int already_in_signal_handler = 0;
-  char *m;
-  if (already_in_signal_handler) MPI_Abort(MPI_COMM_WORLD,1);
-  already_in_signal_handler = 1;
-#if CMK_CCS_AVAILABLE
-  if (CpvAccess(cmiArgDebugFlag)) {
-    CpdNotify(CPD_SIGNAL, sigNo);
-    CpdFreeze();
-  }
-#endif
-  CmiError("------------- Processor %d Exiting: Caught Signal ------------\n"
-      "Signal: %d\n",CmiMyPe(),sigNo);
-  CmiPrintStackTrace(1);
-
-  m = CmiAlloc(CmiMsgHeaderSizeBytes);
-  CmiSetHandler(m, machine_exit_idx);
-  CmiSyncBroadcastAndFree(CmiMsgHeaderSizeBytes, m);
-  machine_exit(m);
-}
-
-static void ConverseRunPE(int everReturn)
-{
-  CmiIdleState *s=CmiNotifyGetState();
-  CmiState cs;
-  char** CmiMyArgv;
-
-#if MPI_POST_RECV_COUNT > 0
-       int doInit = 1;
-       int i;
-       
-#if CMK_SMP
-       if (CmiMyRank() != CmiMyNodeSize()) doInit = 0;
-#endif
-       
-       /* Currently, in mpi smp, the main thread will be the comm thread, so
-     * only the comm thread should post recvs. Cpvs, however, need to be
-        * created on rank 0 (the ptrs to the actual cpv memory), while
-     * other ranks are busy waiting for this to finish.        So cpv initialize
-        * routines have to be called on every ranks, although they are only
-        * useful on comm thread (whose rank is not zero) -Chao Mei
-        */
-       CpvInitialize(unsigned long long, Cmi_posted_recv_total);
-       CpvInitialize(unsigned long long, Cmi_unposted_recv_total);
-       CpvInitialize(MPI_Request*, CmiPostedRecvRequests); 
-       CpvInitialize(char*,CmiPostedRecvBuffers);
-
-       if(doInit){
-               /* Post some extra recvs to help out with incoming messages */
-               /* On some MPIs the messages are unexpected and thus slow */
-
-               /* An array of request handles for posted recvs */
-               CpvAccess(CmiPostedRecvRequests) = (MPI_Request*)malloc(sizeof(MPI_Request)*MPI_POST_RECV_COUNT);
-
-               /* An array of buffers for posted recvs */
-               CpvAccess(CmiPostedRecvBuffers) = (char*)malloc(MPI_POST_RECV_COUNT*MPI_POST_RECV_SIZE);
-
-               /* Post Recvs */
-               for(i=0; i<MPI_POST_RECV_COUNT; i++){
-                       printf("Pre post recv %d\n", i);
-                       if(MPI_SUCCESS != MPI_Irecv(  &(CpvAccess(CmiPostedRecvBuffers)[i*MPI_POST_RECV_SIZE])  ,
-                                               MPI_POST_RECV_SIZE,
-                                               MPI_BYTE,
-                                               MPI_ANY_SOURCE,
-                                               POST_RECV_TAG,
-                                               MPI_COMM_WORLD,
-                               &(CpvAccess(CmiPostedRecvRequests)[i])  ))
-                                       CmiAbort("MPI_Irecv failed\n");
-               }
-       }
-#endif
-       
-  CmiNodeAllBarrier();
-       
-  cs = CmiGetState();
-  CpvInitialize(void *,CmiLocalQueue);
-  CpvAccess(CmiLocalQueue) = cs->localqueue;
-
-  if (CmiMyRank())
-    CmiMyArgv=CmiCopyArgs(Cmi_argvcopy);
-  else
-    CmiMyArgv=Cmi_argv;
-
-  CthInit(CmiMyArgv);
-
-  ConverseCommonInit(CmiMyArgv);
-  machine_exit_idx = CmiRegisterHandler((CmiHandler)machine_exit);
-
-#if CMI_MPI_TRACE_USEREVENTS && CMK_TRACE_ENABLED && !CMK_TRACE_IN_CHARM
-  CpvInitialize(double, projTraceStart);
-  /* only PE 0 needs to care about registration (to generate sts file). */
-  if (CmiMyPe() == 0) {
-    registerMachineUserEventsFunction(&registerMPITraceEvents);
-  }
-#endif
-
-  /* initialize the network progress counter*/
-  /* Network progress function is used to poll the network when for
-     messages. This flushes receive buffers on some  implementations*/
-  CpvInitialize(unsigned , networkProgressCount);
-  CpvAccess(networkProgressCount) = 0;
-
-#if CMK_SMP
-  CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE,(CcdVoidFn)CmiNotifyBeginIdle,(void *)s);
-  CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,(CcdVoidFn)CmiNotifyStillIdle,(void *)s);
-#else
-  CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,(CcdVoidFn)CmiNotifyIdle,NULL);
-#endif
-
-#if MACHINE_DEBUG_LOG
-  if (CmiMyRank() == 0) {
-    char ln[200];
-    sprintf(ln,"debugLog.%d",CmiMyNode());
-    debugLog=fopen(ln,"w");
-  }
-#endif
-
-  /* Converse initialization finishes, immediate messages can be processed.
-     node barrier previously should take care of the node synchronization */
-  _immediateReady = 1;
-
-  /* communication thread */
-  if (CmiMyRank() == CmiMyNodeSize()) {
-    Cmi_startfn(CmiGetArgc(CmiMyArgv), CmiMyArgv);
-    while (1) CommunicationServerThread(5);
-  }
-  else {  /* worker thread */
-  if (!everReturn) {
-    Cmi_startfn(CmiGetArgc(CmiMyArgv), CmiMyArgv);
-    if (Cmi_usrsched==0) CsdScheduler(-1);
-    ConverseExit();
-  }
-  }
-}
-
-static char *thread_level_tostring(int thread_level)
-{
+static char *thread_level_tostring(int thread_level) {
 #if CMK_MPI_INIT_THREAD
-  switch (thread_level) {
-  case MPI_THREAD_SINGLE:
-      return "MPI_THREAD_SINGLE";
-  case MPI_THREAD_FUNNELED:
-      return "MPI_THREAD_FUNNELED";
-  case MPI_THREAD_SERIALIZED:
-      return "MPI_THREAD_SERIALIZED";
-  case MPI_THREAD_MULTIPLE :
-      return "MPI_THREAD_MULTIPLE ";
-  default: {
-      char *str = (char*)malloc(5);
-      sprintf(str,"%d", thread_level);
-      return str;
-      }
-  }
-  return  "unknown";
+    switch (thread_level) {
+    case MPI_THREAD_SINGLE:
+        return "MPI_THREAD_SINGLE";
+    case MPI_THREAD_FUNNELED:
+        return "MPI_THREAD_FUNNELED";
+    case MPI_THREAD_SERIALIZED:
+        return "MPI_THREAD_SERIALIZED";
+    case MPI_THREAD_MULTIPLE :
+        return "MPI_THREAD_MULTIPLE ";
+    default: {
+        char *str = (char*)malloc(5);
+        sprintf(str,"%d", thread_level);
+        return str;
+    }
+    }
+    return  "unknown";
 #else
-  char *str = (char*)malloc(5);
-  sprintf(str,"%d", thread_level);
-  return str;
+    char *str = (char*)malloc(5);
+    sprintf(str,"%d", thread_level);
+    return str;
 #endif
 }
 
-void ConverseInit(int argc, char **argv, CmiStartFn fn, int usched, int initret)
-{
-  int n,i;
-  int ver, subver;
-  int provided;
-  int thread_level;
+/**
+ *  Obtain the number of nodes, my node id, and consuming machine layer
+ *  specific arguments
+ */
+static void MachineInitForMPI(int argc, char **argv, int *numNodes, int *myNodeID) {
+    int n,i;
+    int ver, subver;
+    int provided;
+    int thread_level;
+    int myNID;
 
 #if MACHINE_DEBUG
-  debugLog=NULL;
+    debugLog=NULL;
 #endif
 #if CMK_USE_HP_MAIN_FIX
 #if FOR_CPLUS
-  _main(argc,argv);
+    _main(argc,argv);
 #endif
 #endif
 
 #if CMK_MPI_INIT_THREAD
 #if CMK_SMP
-  thread_level = MPI_THREAD_FUNNELED;
+    thread_level = MPI_THREAD_FUNNELED;
 #else
-  thread_level = MPI_THREAD_SINGLE;
+    thread_level = MPI_THREAD_SINGLE;
 #endif
-  MPI_Init_thread(&argc, &argv, thread_level, &provided);
-  _thread_provided = provided;
+    MPI_Init_thread(&argc, &argv, thread_level, &provided);
+    _thread_provided = provided;
 #else
-  MPI_Init(&argc, &argv);
-  thread_level = 0;
-  provided = -1;
-#endif
-  MPI_Comm_size(MPI_COMM_WORLD, &_Cmi_numnodes);
-  MPI_Comm_rank(MPI_COMM_WORLD, &_Cmi_mynode);
-
-  MPI_Get_version(&ver, &subver);
-  if (_Cmi_mynode == 0) {
-    printf("Charm++> Running on MPI version: %d.%d multi-thread support: %s (max supported: %s)\n", ver, subver, thread_level_tostring(thread_level), thread_level_tostring(provided));
-  }
-
-  /* processor per node */
-  _Cmi_mynodesize = 1;
-  if (!CmiGetArgInt(argv,"+ppn", &_Cmi_mynodesize))
-    CmiGetArgInt(argv,"++ppn", &_Cmi_mynodesize);
-#if ! CMK_SMP
-  if (_Cmi_mynodesize > 1 && _Cmi_mynode == 0)
-    CmiAbort("+ppn cannot be used in non SMP version!\n");
-#endif
-  idleblock = CmiGetArgFlag(argv, "+idleblocking");
-  if (idleblock && _Cmi_mynode == 0) {
-    printf("Charm++: Running in idle blocking mode.\n");
-  }
-
-  /* setup signal handlers */
-  signal(SIGSEGV, KillOnAllSigs);
-  signal(SIGFPE, KillOnAllSigs);
-  signal(SIGILL, KillOnAllSigs);
-  signal_int = signal(SIGINT, KillOnAllSigs);
-  signal(SIGTERM, KillOnAllSigs);
-  signal(SIGABRT, KillOnAllSigs);
+    MPI_Init(&argc, &argv);
+    thread_level = 0;
+    provided = -1;
+#endif
+    MPI_Comm_size(MPI_COMM_WORLD, numNodes);
+    MPI_Comm_rank(MPI_COMM_WORLD, myNodeID);
+
+    myNID = *myNodeID;
+
+    MPI_Get_version(&ver, &subver);
+    if (myNID == 0) {
+        printf("Charm++> Running on MPI version: %d.%d multi-thread support: %s (max supported: %s)\n", ver, subver, thread_level_tostring(thread_level), thread_level_tostring(provided));
+    }
+
+    idleblock = CmiGetArgFlag(argv, "+idleblocking");
+    if (idleblock && _Cmi_mynode == 0) {
+        printf("Charm++: Running in idle blocking mode.\n");
+    }
+
+    /* setup signal handlers */
+    signal(SIGSEGV, KillOnAllSigs);
+    signal(SIGFPE, KillOnAllSigs);
+    signal(SIGILL, KillOnAllSigs);
+    signal_int = signal(SIGINT, KillOnAllSigs);
+    signal(SIGTERM, KillOnAllSigs);
+    signal(SIGABRT, KillOnAllSigs);
 #   if !defined(_WIN32) || defined(__CYGWIN__) /*UNIX-only signals*/
-  signal(SIGQUIT, KillOnAllSigs);
-  signal(SIGBUS, KillOnAllSigs);
-/*#     if CMK_HANDLE_SIGUSR
-  signal(SIGUSR1, HandleUserSignals);
-  signal(SIGUSR2, HandleUserSignals);
-#     endif*/
+    signal(SIGQUIT, KillOnAllSigs);
+    signal(SIGBUS, KillOnAllSigs);
 #   endif /*UNIX*/
-  
+
 #if CMK_NO_OUTSTANDING_SENDS
-  no_outstanding_sends=1;
-#endif
-  if (CmiGetArgFlag(argv,"+no_outstanding_sends")) {
-    no_outstanding_sends = 1;
-    if (_Cmi_mynode == 0)
-      printf("Charm++: Will%s consume outstanding sends in scheduler loop\n",
-       no_outstanding_sends?"":" not");
-  }
-  _Cmi_numpes = _Cmi_numnodes * _Cmi_mynodesize;
-  Cmi_nodestart = _Cmi_mynode * _Cmi_mynodesize;
-  Cmi_argvcopy = CmiCopyArgs(argv);
-  Cmi_argv = argv; Cmi_startfn = fn; Cmi_usrsched = usched;
-  /* find dim = log2(numpes), to pretend we are a hypercube */
-  for ( Cmi_dim=0,n=_Cmi_numpes; n>1; n/=2 )
-    Cmi_dim++ ;
- /* CmiSpanTreeInit();*/
-  request_max=MAX_QLEN;
-  CmiGetArgInt(argv,"+requestmax",&request_max);
-  /*printf("request max=%d\n", request_max);*/
-
-  /* checksum flag */
-  if (CmiGetArgFlag(argv,"+checksum")) {
-#if !CMK_OPTIMIZE
-    checksum_flag = 1;
-    if (_Cmi_mynode == 0) CmiPrintf("Charm++: CheckSum checking enabled! \n");
+    no_outstanding_sends=1;
+#endif
+    if (CmiGetArgFlag(argv,"+no_outstanding_sends")) {
+        no_outstanding_sends = 1;
+        if (myNID == 0)
+            printf("Charm++: Will%s consume outstanding sends in scheduler loop\n",
+                   no_outstanding_sends?"":" not");
+    }
+
+    request_max=MAX_QLEN;
+    CmiGetArgInt(argv,"+requestmax",&request_max);
+    /*printf("request max=%d\n", request_max);*/
+
+    /* checksum flag */
+    if (CmiGetArgFlag(argv,"+checksum")) {
+#if CMK_ERROR_CHECKING
+        checksum_flag = 1;
+        if (myNID == 0) CmiPrintf("Charm++: CheckSum checking enabled! \n");
 #else
-    if (_Cmi_mynode == 0) CmiPrintf("Charm++: +checksum ignored in optimized version! \n");
+        if (myNID == 0) CmiPrintf("Charm++: +checksum ignored in optimized version! \n");
 #endif
-  }
+    }
 
-  {
-  int debug = CmiGetArgFlag(argv,"++debug");
-  int debug_no_pause = CmiGetArgFlag(argv,"++debug-no-pause");
-  if (debug || debug_no_pause)
-  {   /*Pause so user has a chance to start and attach debugger*/
+    {
+        int debug = CmiGetArgFlag(argv,"++debug");
+        int debug_no_pause = CmiGetArgFlag(argv,"++debug-no-pause");
+        if (debug || debug_no_pause) {  /*Pause so user has a chance to start and attach debugger*/
 #if CMK_HAS_GETPID
-    printf("CHARMDEBUG> Processor %d has PID %d\n",_Cmi_mynode,getpid());
-    fflush(stdout);
-    if (!debug_no_pause)
-      sleep(15);
+            printf("CHARMDEBUG> Processor %d has PID %d\n",myNID,getpid());
+            fflush(stdout);
+            if (!debug_no_pause)
+                sleep(15);
 #else
-    printf("++debug ignored.\n");
+            printf("++debug ignored.\n");
 #endif
-  }
-  }
+        }
+    }
 
-  /* CmiTimerInit(); */
+    procState = (ProcState *)malloc((_Cmi_mynodesize+1) * sizeof(ProcState));
+    for (i=0; i<_Cmi_mynodesize+1; i++) {
+#if MULTI_SENDQUEUE
+        procState[i].sendMsgBuf = PCQueueCreate();
+#endif
+        procState[i].recvLock = CmiCreateLock();
+    }
+#if CMK_SMP
+#if !MULTI_SENDQUEUE
+    sendMsgBuf = PCQueueCreate();
+    sendMsgBufLock = CmiCreateLock();
+#endif
+#endif
+}
 
-#if 0
-  CthInit(argv);
-  ConverseCommonInit(argv);
+static void MachinePreCommonInitForMPI(int everReturn) {
+#if MPI_POST_RECV_COUNT > 0
+    int doInit = 1;
+    int i;
 
-  CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,CmiNotifyIdle,NULL);
-  if (initret==0) {
-    fn(CmiGetArgc(argv), argv);
-    if (usched==0) CsdScheduler(-1);
-    ConverseExit();
-  }
+#if CMK_SMP
+    if (CmiMyRank() != CmiMyNodeSize()) doInit = 0;
 #endif
 
-  CsvInitialize(CmiNodeState, NodeState);
-  CmiNodeStateInit(&CsvAccess(NodeState));
+    /* Currently, in mpi smp, the main thread will be the comm thread, so
+     * only the comm thread should post recvs. Cpvs, however, need to be
+     * created on rank 0 (the ptrs to the actual cpv memory), while
+     * other ranks are busy waiting for this to finish.        So cpv initialize
+     * routines have to be called on every ranks, although they are only
+     * useful on comm thread (whose rank is not zero) -Chao Mei
+     */
+    CpvInitialize(unsigned long long, Cmi_posted_recv_total);
+    CpvInitialize(unsigned long long, Cmi_unposted_recv_total);
+    CpvInitialize(MPI_Request*, CmiPostedRecvRequests);
+    CpvInitialize(char*,CmiPostedRecvBuffers);
+
+    if (doInit) {
+        /* Post some extra recvs to help out with incoming messages */
+        /* On some MPIs the messages are unexpected and thus slow */
+
+        /* An array of request handles for posted recvs */
+        CpvAccess(CmiPostedRecvRequests) = (MPI_Request*)malloc(sizeof(MPI_Request)*MPI_POST_RECV_COUNT);
+
+        /* An array of buffers for posted recvs */
+        CpvAccess(CmiPostedRecvBuffers) = (char*)malloc(MPI_POST_RECV_COUNT*MPI_POST_RECV_SIZE);
+
+        /* Post Recvs */
+        for (i=0; i<MPI_POST_RECV_COUNT; i++) {
+            printf("Pre post recv %d\n", i);
+            if (MPI_SUCCESS != MPI_Irecv(  &(CpvAccess(CmiPostedRecvBuffers)[i*MPI_POST_RECV_SIZE])    ,
+                                           MPI_POST_RECV_SIZE,
+                                           MPI_BYTE,
+                                           MPI_ANY_SOURCE,
+                                           POST_RECV_TAG,
+                                           MPI_COMM_WORLD,
+                                           &(CpvAccess(CmiPostedRecvRequests)[i])  ))
+                CmiAbort("MPI_Irecv failed\n");
+        }
+    }
+#endif
 
-  procState = (ProcState *)malloc((_Cmi_mynodesize+1) * sizeof(ProcState));
+}
 
-  for (i=0; i<_Cmi_mynodesize+1; i++) {
-#if MULTI_SENDQUEUE
-    procState[i].sendMsgBuf = PCQueueCreate();
+static void MachinePostCommonInitForMPI(int everReturn) {
+    CmiIdleState *s=CmiNotifyGetState();
+    machine_exit_idx = CmiRegisterHandler((CmiHandler)machine_exit);
+
+#if CMI_MPI_TRACE_USEREVENTS && CMK_TRACE_ENABLED && !CMK_TRACE_IN_CHARM
+    CpvInitialize(double, projTraceStart);
+    /* only PE 0 needs to care about registration (to generate sts file). */
+    if (CmiMyPe() == 0) {
+        registerMachineUserEventsFunction(&registerMPITraceEvents);
+    }
 #endif
-    procState[i].recvLock = CmiCreateLock();
-  }
+
 #if CMK_SMP
-#if !MULTI_SENDQUEUE
-  sendMsgBuf = PCQueueCreate();
-  sendMsgBufLock = CmiCreateLock();
-#endif
-  exitLock = CmiCreateLock();            /* exit count lock */
+    CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE,(CcdVoidFn)CmiNotifyBeginIdle,(void *)s);
+    CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,(CcdVoidFn)CmiNotifyStillIdle,(void *)s);
+#else
+    CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,(CcdVoidFn)CmiNotifyIdleForMPI,NULL);
 #endif
 
-  /* Network progress function is used to poll the network when for
-     messages. This flushes receive buffers on some  implementations*/
-  networkProgressPeriod = NETWORK_PROGRESS_PERIOD_DEFAULT;
-  CmiGetArgInt(argv, "+networkProgressPeriod", &networkProgressPeriod);
-
-  CmiStartThreads(argv);
-  ConverseRunPE(initret);
+#if MACHINE_DEBUG_LOG
+    if (CmiMyRank() == 0) {
+        char ln[200];
+        sprintf(ln,"debugLog.%d",CmiMyNode());
+        debugLog=fopen(ln,"w");
+    }
+#endif
 }
+/* ######End of functions related with starting programs###### */
 
 /***********************************************************************
  *
@@ -2065,97 +1238,27 @@ void ConverseInit(int argc, char **argv, CmiStartFn fn, int usched, int initret)
  *
  ************************************************************************/
 
-void CmiAbort(const char *message)
-{
-  char *m;
-  /* if CharmDebug is attached simply try to send a message to it */
+void CmiAbort(const char *message) {
+    char *m;
+    /* if CharmDebug is attached simply try to send a message to it */
 #if CMK_CCS_AVAILABLE
-  if (CpvAccess(cmiArgDebugFlag)) {
-    CpdNotify(CPD_ABORT, message);
-    CpdFreeze();
-  }
-#endif  
-  CmiError("------------- Processor %d Exiting: Called CmiAbort ------------\n"
-        "Reason: %s\n",CmiMyPe(),message);
- /*  CmiError(message); */
-  CmiPrintStackTrace(0);
-  m = CmiAlloc(CmiMsgHeaderSizeBytes);
-  CmiSetHandler(m, machine_exit_idx);
-  CmiSyncBroadcastAndFree(CmiMsgHeaderSizeBytes, m);
-  machine_exit(m);
-  /* Program never reaches here */
-  MPI_Abort(MPI_COMM_WORLD, 1);
-}
-
-
-#if 0
-
-/* ****************************************************************** */
-/*    The following internal functions implement recd msg queue       */
-/* ****************************************************************** */
-
-static void ** AllocBlock(unsigned int len)
-{
-  void ** blk;
-
-  blk=(void **)CmiAlloc(len*sizeof(void *));
-  if(blk==(void **)0) {
-    CmiError("Cannot Allocate Memory!\n");
-    MPI_Abort(MPI_COMM_WORLD, 1);
-  }
-  return blk;
-}
-
-static void
-SpillBlock(void **srcblk, void **destblk, unsigned int first, unsigned int len)
-{
-  memcpy(destblk, &srcblk[first], (len-first)*sizeof(void *));
-  memcpy(&destblk[len-first],srcblk,first*sizeof(void *));
-}
-
-void recdQueueInit(void)
-{
-  recdQueue_blk = AllocBlock(BLK_LEN);
-  recdQueue_blk_len = BLK_LEN;
-  recdQueue_first = 0;
-  recdQueue_len = 0;
-}
-
-void recdQueueAddToBack(void *element)
-{
-#if NODE_0_IS_CONVHOST
-  inside_comm = 1;
-#endif
-  if(recdQueue_len==recdQueue_blk_len) {
-    void **blk;
-    recdQueue_blk_len *= 3;
-    blk = AllocBlock(recdQueue_blk_len);
-    SpillBlock(recdQueue_blk, blk, recdQueue_first, recdQueue_len);
-    CmiFree(recdQueue_blk);
-    recdQueue_blk = blk;
-    recdQueue_first = 0;
-  }
-  recdQueue_blk[(recdQueue_first+recdQueue_len++)%recdQueue_blk_len] = element;
-#if NODE_0_IS_CONVHOST
-  inside_comm = 0;
+    if (CpvAccess(cmiArgDebugFlag)) {
+        CpdNotify(CPD_ABORT, message);
+        CpdFreeze();
+    }
 #endif
+    CmiError("------------- Processor %d Exiting: Called CmiAbort ------------\n"
+             "Reason: %s\n",CmiMyPe(),message);
+    /*  CmiError(message); */
+    CmiPrintStackTrace(0);
+    m = CmiAlloc(CmiMsgHeaderSizeBytes);
+    CmiSetHandler(m, machine_exit_idx);
+    CmiSyncBroadcastAndFree(CmiMsgHeaderSizeBytes, m);
+    machine_exit(m);
+    /* Program never reaches here */
+    MPI_Abort(MPI_COMM_WORLD, 1);
 }
 
-
-void * recdQueueRemoveFromFront(void)
-{
-  if(recdQueue_len) {
-    void *element;
-    element = recdQueue_blk[recdQueue_first++];
-    recdQueue_first %= recdQueue_blk_len;
-    recdQueue_len--;
-    return element;
-  }
-  return 0;
-}
-
-#endif
-
 /**************************  TIMER FUNCTIONS **************************/
 #if CMK_TIMER_USE_SPECIAL || CMK_TIMER_USE_XT3_DCLOCK
 
@@ -2165,75 +1268,69 @@ static int _absoluteTime = 0;
 static double starttimer = 0;
 static int _is_global = 0;
 
-int CmiTimerIsSynchronized()
-{
-  int  flag;
-  void *v;
-
-  /*  check if it using synchronized timer */
-  if (MPI_SUCCESS != MPI_Attr_get(MPI_COMM_WORLD, MPI_WTIME_IS_GLOBAL, &v, &flag))
-    printf("MPI_WTIME_IS_GLOBAL not valid!\n");
-  if (flag) {
-    _is_global = *(int*)v;
-    if (_is_global && CmiMyPe() == 0)
-      printf("Charm++> MPI timer is synchronized\n");
-  }
-  return _is_global;
+int CmiTimerIsSynchronized() {
+    int  flag;
+    void *v;
+
+    /*  check if it using synchronized timer */
+    if (MPI_SUCCESS != MPI_Attr_get(MPI_COMM_WORLD, MPI_WTIME_IS_GLOBAL, &v, &flag))
+        printf("MPI_WTIME_IS_GLOBAL not valid!\n");
+    if (flag) {
+        _is_global = *(int*)v;
+        if (_is_global && CmiMyPe() == 0)
+            printf("Charm++> MPI timer is synchronized\n");
+    }
+    return _is_global;
 }
 
-int CmiTimerAbsolute()
-{       
-  return _absoluteTime;
+int CmiTimerAbsolute() {
+    return _absoluteTime;
 }
 
-double CmiStartTimer()
-{
-  return 0.0;
+double CmiStartTimer() {
+    return 0.0;
 }
 
-double CmiInitTime()
-{
-  return starttimer;
+double CmiInitTime() {
+    return starttimer;
 }
 
-void CmiTimerInit(char **argv)
-{
-  _absoluteTime = CmiGetArgFlagDesc(argv,"+useAbsoluteTime", "Use system's absolute time as wallclock time.");
-  if (_absoluteTime && CmiMyPe() == 0)
-      printf("Charm++> absolute MPI timer is used\n");
+void CmiTimerInit(char **argv) {
+    _absoluteTime = CmiGetArgFlagDesc(argv,"+useAbsoluteTime", "Use system's absolute time as wallclock time.");
+    if (_absoluteTime && CmiMyPe() == 0)
+        printf("Charm++> absolute MPI timer is used\n");
 
-  _is_global = CmiTimerIsSynchronized();
+    _is_global = CmiTimerIsSynchronized();
 
-  if (_is_global) {
-    if (CmiMyRank() == 0) {
-      double minTimer;
+    if (_is_global) {
+        if (CmiMyRank() == 0) {
+            double minTimer;
 #if CMK_TIMER_USE_XT3_DCLOCK
-      starttimer = dclock();
+            starttimer = dclock();
 #else
-      starttimer = MPI_Wtime();
+            starttimer = MPI_Wtime();
 #endif
 
-      MPI_Allreduce(&starttimer, &minTimer, 1, MPI_DOUBLE, MPI_MIN,
-                                  MPI_COMM_WORLD );
-      starttimer = minTimer;
-    }
-  }
-  else {  /* we don't have a synchronous timer, set our own start time */
-    CmiBarrier();
-    CmiBarrier();
-    CmiBarrier();
+            MPI_Allreduce(&starttimer, &minTimer, 1, MPI_DOUBLE, MPI_MIN,
+                          MPI_COMM_WORLD );
+            starttimer = minTimer;
+        }
+    } else { /* we don't have a synchronous timer, set our own start time */
+        CmiBarrier();
+        CmiBarrier();
+        CmiBarrier();
 #if CMK_TIMER_USE_XT3_DCLOCK
-    starttimer = dclock();
+        starttimer = dclock();
 #else
-    starttimer = MPI_Wtime();
+        starttimer = MPI_Wtime();
 #endif
-  }
+    }
 
 #if 0 && CMK_SMP && CMK_MPI_INIT_THREAD
-  if (CmiMyRank()==0 && _thread_provided == MPI_THREAD_SINGLE)
-    timerLock = CmiCreateLock();
+    if (CmiMyRank()==0 && _thread_provided == MPI_THREAD_SINGLE)
+        timerLock = CmiCreateLock();
 #endif
-  CmiNodeAllBarrier();          /* for smp */
+    CmiNodeAllBarrier();          /* for smp */
 }
 
 /**
@@ -2242,125 +1339,121 @@ void CmiTimerInit(char **argv)
  * the timer functions could be disabled right
  * now in the case of SMP. --Chao Mei
  */
-double CmiTimer(void)
-{
-  double t;
+double CmiTimer(void) {
+    double t;
 #if 0 && CMK_SMP
-  if (timerLock) CmiLock(timerLock);
+    if (timerLock) CmiLock(timerLock);
 #endif
 
 #if CMK_TIMER_USE_XT3_DCLOCK
-  t = dclock();
+    t = dclock();
 #else
-  t = MPI_Wtime();
+    t = MPI_Wtime();
 #endif
 
 #if 0 && CMK_SMP
-  if (timerLock) CmiUnlock(timerLock);
+    if (timerLock) CmiUnlock(timerLock);
 #endif
 
-  return _absoluteTime?t: (t-starttimer);
+    return _absoluteTime?t: (t-starttimer);
 }
 
-double CmiWallTimer(void)
-{
-  double t;
+double CmiWallTimer(void) {
+    double t;
 #if 0 && CMK_SMP
-  if (timerLock) CmiLock(timerLock);
+    if (timerLock) CmiLock(timerLock);
 #endif
 
 #if CMK_TIMER_USE_XT3_DCLOCK
-  t = dclock();
+    t = dclock();
 #else
-  t = MPI_Wtime();
+    t = MPI_Wtime();
 #endif
 
 #if 0 && CMK_SMP
-  if (timerLock) CmiUnlock(timerLock);
+    if (timerLock) CmiUnlock(timerLock);
 #endif
 
-  return _absoluteTime? t: (t-starttimer);
+    return _absoluteTime? t: (t-starttimer);
 }
 
-double CmiCpuTimer(void)
-{
-  double t;
+double CmiCpuTimer(void) {
+    double t;
 #if 0 && CMK_SMP
-  if (timerLock) CmiLock(timerLock);
+    if (timerLock) CmiLock(timerLock);
 #endif
 #if CMK_TIMER_USE_XT3_DCLOCK
-  t = dclock() - starttimer;
+    t = dclock() - starttimer;
 #else
-  t = MPI_Wtime() - starttimer;
+    t = MPI_Wtime() - starttimer;
 #endif
 #if 0 && CMK_SMP
-  if (timerLock) CmiUnlock(timerLock);
+    if (timerLock) CmiUnlock(timerLock);
 #endif
-  return t;
+    return t;
 }
 
 #endif
 
+/************Barrier Related Functions****************/
 /* must be called on all ranks including comm thread in SMP */
-int CmiBarrier()
-{
+int CmiBarrier() {
 #if CMK_SMP
     /* make sure all ranks reach here, otherwise comm threads may reach barrier ignoring other ranks  */
-  CmiNodeAllBarrier();
-  if (CmiMyRank() == CmiMyNodeSize()) 
+    CmiNodeAllBarrier();
+    if (CmiMyRank() == CmiMyNodeSize())
 #else
-  if (CmiMyRank() == 0) 
+    if (CmiMyRank() == 0)
 #endif
-  {
-/**
- *  The call of CmiBarrier is usually before the initialization
- *  of trace module of Charm++, therefore, the START_EVENT
- *  and END_EVENT are disabled here. -Chao Mei
- */    
-    /*START_EVENT();*/
+    {
+        /**
        *  The call of CmiBarrier is usually before the initialization
        *  of trace module of Charm++, therefore, the START_EVENT
        *  and END_EVENT are disabled here. -Chao Mei
+         */
+        /*START_EVENT();*/
 
-    if (MPI_SUCCESS != MPI_Barrier(MPI_COMM_WORLD))
-        CmiAbort("Timernit: MPI_Barrier failed!\n");
+        if (MPI_SUCCESS != MPI_Barrier(MPI_COMM_WORLD))
+            CmiAbort("Timernit: MPI_Barrier failed!\n");
 
-    /*END_EVENT(10);*/
-  }
-  CmiNodeAllBarrier();
-  return 0;
+        /*END_EVENT(10);*/
+    }
+    CmiNodeAllBarrier();
+    return 0;
 }
 
 /* CmiBarrierZero make sure node 0 is the last one exiting the barrier */
-int CmiBarrierZero()
-{
-  int i;
+int CmiBarrierZero() {
+    int i;
 #if CMK_SMP
-  if (CmiMyRank() == CmiMyNodeSize()) 
+    if (CmiMyRank() == CmiMyNodeSize())
 #else
-  if (CmiMyRank() == 0) 
+    if (CmiMyRank() == 0)
 #endif
-  {
-    char msg[1];
-    MPI_Status sts;
-    if (CmiMyNode() == 0)  {
-      for (i=0; i<CmiNumNodes()-1; i++) {
-         START_EVENT();
-
-         if (MPI_SUCCESS != MPI_Recv(msg,1,MPI_BYTE,MPI_ANY_SOURCE,BARRIER_ZERO_TAG, MPI_COMM_WORLD,&sts))
-            CmiPrintf("MPI_Recv failed!\n");
-
-         END_EVENT(30);
-      }
-    }
-    else {
-      START_EVENT();
+    {
+        char msg[1];
+        MPI_Status sts;
+        if (CmiMyNode() == 0)  {
+            for (i=0; i<CmiNumNodes()-1; i++) {
+                START_EVENT();
+
+                if (MPI_SUCCESS != MPI_Recv(msg,1,MPI_BYTE,MPI_ANY_SOURCE,BARRIER_ZERO_TAG, MPI_COMM_WORLD,&sts))
+                    CmiPrintf("MPI_Recv failed!\n");
+
+                END_EVENT(30);
+            }
+        } else {
+            START_EVENT();
 
-      if (MPI_SUCCESS != MPI_Send((void *)msg,1,MPI_BYTE,0,BARRIER_ZERO_TAG,MPI_COMM_WORLD))
-         printf("MPI_Send failed!\n");
+            if (MPI_SUCCESS != MPI_Send((void *)msg,1,MPI_BYTE,0,BARRIER_ZERO_TAG,MPI_COMM_WORLD))
+                printf("MPI_Send failed!\n");
 
-      END_EVENT(20);
+            END_EVENT(20);
+        }
     }
-  }
-  CmiNodeAllBarrier();
-  return 0;
+    CmiNodeAllBarrier();
+    return 0;
 }
 
 /*@}*/
+
diff --git a/src/arch/util/machine-common.c b/src/arch/util/machine-common.c
new file mode 100644 (file)
index 0000000..67b78c7
--- /dev/null
@@ -0,0 +1,1100 @@
+#if CMK_C_INLINE
+#define INLINE_KEYWORD inline
+#else
+#define INLINE_KEYWORD
+#endif
+
+/* ###Beginning of Broadcast related definitions ### */
+#ifndef CMK_BROADCAST_SPANNING_TREE
+#define CMK_BROADCAST_SPANNING_TREE    1
+#endif
+
+#ifndef CMK_BROADCAST_HYPERCUBE
+#define CMK_BROADCAST_HYPERCUBE        0
+#endif
+
+#define BROADCAST_SPANNING_FACTOR      4
+/* The number of children used when a msg is broadcast inside a node */
+#define BROADCAST_SPANNING_INTRA_FACTOR  8
+
+/* Root of broadcast:
+ * non-bcast msg: root = 0;
+ * proc-level bcast msg: root >=1; (CmiMyPe()+1)
+ * node-level bcast msg: root <=-1; (-CmiMyNode()-1)
+ */
+#define CMI_BROADCAST_ROOT(msg)          ((CmiMsgHeaderBasic *)msg)->root
+#define CMI_DEST_RANK(msg)               ((CmiMsgHeaderBasic *)msg)->rank
+#define CMI_SET_BROADCAST_ROOT(msg, root)  CMI_BROADCAST_ROOT(msg) = (root);
+
+#if USE_COMMON_SYNC_BCAST || USE_COMMON_ASYNC_BCAST
+#if !CMK_BROADCAST_SPANNING_TREE && !CMK_BROADCAST_HYPERCUBE
+#warning "Broadcast function is based on the plain P2P O(P)-message scheme!!!"
+#endif
+#endif
+
+/**
+ * For some machine layers such as on Active Message framework,
+ * the receiver callback is usally executed on an internal
+ * thread (i.e. not the flow managed by ours). Therefore, for
+ * forwarding broadcast messages, we could have a choice whether
+ * to offload such function to the flow we manage such as the
+ * communication thread. -Chao Mei
+ */
+
+#ifndef CMK_OFFLOAD_BCAST_PROCESS
+#define CMK_OFFLOAD_BCAST_PROCESS 0
+#endif
+#if CMK_OFFLOAD_BCAST_PROCESS
+CsvDeclare(PCQueue, procBcastQ);
+#if CMK_NODE_QUEUE_AVAILABLE
+CsvDeclare(PCQueue, nodeBcastQ);
+#endif
+#endif
+
+#if CMK_BROADCAST_HYPERCUBE
+/* ceil(log2(CmiNumNodes)) except when _Cmi_numnodes is 1, used for hypercube */
+static int CmiNodesDim;
+#endif
+/* ###End of Broadcast related definitions ### */
+
+
+#ifndef CMK_HAS_SIZE_IN_MSGHDR
+#define CMK_HAS_SIZE_IN_MSGHDR 1
+#endif
+#if CMK_HAS_SIZE_IN_MSGHDR
+#define CMI_MSG_SIZE(msg)  ((CmiMsgHeaderBasic *)msg)->size
+#else
+#define CMI_MSG_SIZE(msg)  (CmiAbort("Has no msg size in header"))
+#endif
+
+#if CMK_NODE_QUEUE_AVAILABLE
+/* This value should be larger than the number of cores used
+ * per charm smp node. So it's currently set to such a large
+ * value.
+ */
+#define DGRAM_NODEMESSAGE   (0x1FFB)
+#endif
+
+/* Node state structure */
+int               _Cmi_mynode;    /* Which address space am I */
+int               _Cmi_mynodesize;/* Number of processors in my address space */
+int               _Cmi_numnodes;  /* Total number of address spaces */
+int               _Cmi_numpes;    /* Total number of processors */
+
+CpvDeclare(void*, CmiLocalQueue);
+
+/* different modes for sending a message */
+#define P2P_SYNC 0x1
+#define P2P_ASYNC 0x2
+#define BCAST_SYNC 0x3
+#define BCAST_ASYNC 0x4
+
+#if CMK_SMP
+static volatile int commThdExit = 0;
+static CmiNodeLock  commThdExitLock = 0;
+
+/**
+ *  The macro defines whether to have a comm thd to offload some
+ *  work such as forwarding bcast messages etc. This macro
+ *  should be defined before including "machine-smp.c". Note
+ *  that whether a machine layer in SMP mode could run w/o comm
+ *  thread depends on the support of the underlying
+ *  communication library.
+ *
+ *  --Chao Mei
+ */
+#ifndef CMK_SMP_NO_COMMTHD
+#define CMK_SMP_NO_COMMTHD 0
+#endif
+
+#if CMK_SMP_NO_COMMTHD
+int Cmi_commthread = 0;
+#else
+int Cmi_commthread = 1;
+#endif
+
+#endif
+
+/*SHOULD BE MOVED TO MACHINE-SMP.C ??*/
+static int Cmi_nodestart;
+
+/*
+ * Network progress utility variables. Period controls the rate at
+ * which the network poll is called
+ */
+#ifndef NETWORK_PROGRESS_PERIOD_DEFAULT
+#define NETWORK_PROGRESS_PERIOD_DEFAULT 1000
+#endif
+
+CpvDeclare(unsigned , networkProgressCount);
+int networkProgressPeriod;
+
+
+/* ===== Beginning of Common Function Declarations ===== */
+void CmiAbort(const char *message);
+static void PerrorExit(const char *msg);
+
+/* This function handles the msg received as which queue to push into */
+static void handleOneRecvedMsg(int size, char *msg);
+
+static void handleOneBcastMsg(int size, char *msg);
+static void processBcastQs();
+
+/* Utility functions for forwarding broadcast messages,
+ * should not be used in machine-specific implementations
+ * except in some special occasions.
+ */
+static void processProcBcastMsg(int size, char *msg);
+static void processNodeBcastMsg(int size, char *msg);
+static void SendSpanningChildrenProc(int size, char *msg);
+static void SendHyperCubeProc(int size, char *msg);
+#if CMK_NODE_QUEUE_AVAILABLE
+static void SendSpanningChildrenNode(int size, char *msg);
+static void SendHyperCubeNode(int size, char *msg);
+#endif
+
+static void SendSpanningChildren(int size, char *msg, int rankToAssign, int startNode);
+static void SendHyperCube(int size,  char *msg, int rankToAssign, int startNode);
+/* send to other ranks except me on the same node*/
+static void SendToPeers(int size, char *msg);
+
+
+void CmiPushPE(int rank, void *msg);
+
+#if CMK_NODE_QUEUE_AVAILABLE
+void CmiPushNode(void *msg);
+#endif
+
+/* Functions regarding send ops declared in converse.h */
+
+/* In default, using the common codes for msg sending */
+#ifndef USE_COMMON_SYNC_P2P
+#define USE_COMMON_SYNC_P2P 1
+#endif
+#ifndef USE_COMMON_ASYNC_P2P
+#define USE_COMMON_ASYNC_P2P 1
+#endif
+#ifndef USE_COMMON_SYNC_BCAST
+#define USE_COMMON_SYNC_BCAST 1
+#endif
+#ifndef USE_COMMON_ASYNC_BCAST
+#define USE_COMMON_ASYNC_BCAST 1
+#endif
+
+static void CmiSendSelf(char *msg);
+
+void CmiSyncSendFn(int destPE, int size, char *msg);
+CmiCommHandle CmiAsyncSendFn(int destPE, int size, char *msg);
+void CmiFreeSendFn(int destPE, int size, char *msg);
+
+void CmiSyncBroadcastFn(int size, char *msg);
+CmiCommHandle CmiAsyncBroadcastFn(int size, char *msg);
+void CmiFreeBroadcastFn(int size, char *msg);
+
+void CmiSyncBroadcastAllFn(int size, char *msg);
+CmiCommHandle CmiAsyncBroadcastAllFn(int size, char *msg);
+void CmiFreeBroadcastAllFn(int size, char *msg);
+
+#if CMK_NODE_QUEUE_AVAILABLE
+static void CmiSendNodeSelf(char *msg);
+
+void CmiSyncNodeSendFn(int destNode, int size, char *msg);
+CmiCommHandle CmiAsyncNodeSendFn(int destNode, int size, char *msg);
+void CmiFreeNodeSendFn(int destNode, int size, char *msg);
+
+void CmiSyncNodeBroadcastFn(int size, char *msg);
+CmiCommHandle CmiAsyncNodeBroadcastFn(int size, char *msg);
+void CmiFreeNodeBroadcastFn(int size, char *msg);
+
+void CmiSyncNodeBroadcastAllFn(int size, char *msg);
+CmiCommHandle CmiAsyncNodeBroadcastAllFn(int size, char *msg);
+void CmiFreeNodeBroadcastAllFn(int size, char *msg);
+#endif
+
+/* Functions and variables regarding machine startup */
+static char     **Cmi_argv;
+static char     **Cmi_argvcopy;
+static CmiStartFn Cmi_startfn;   /* The start function */
+static int        Cmi_usrsched;  /* Continue after start function finishes? */
+void ConverseInit(int argc, char **argv, CmiStartFn fn, int usched, int initret);
+static void ConverseRunPE(int everReturn);
+
+static void MachineSpecificInit(int argc, char **argv, int *numNodes, int *myNodeID);
+/* Used in ConverseRunPE: one is called before ConverseCommonInit;
+  * The other is called after ConverseCommonInit as some data structures
+  * have been initialized, such as the tracing-relatd stuff --Chao Mei
+  */
+static void MachineSpecificPreCommonInit(int everReturn);
+static void MachineSpecificPostCommonInit(int everReturn);
+
+/* Functions regarding machine running on every proc */
+static void AdvanceCommunication();
+static void CommunicationServer(int sleepTime);
+static void CommunicationServerThread(int sleepTime);
+void ConverseExit(void);
+
+static void MachineSpecificAdvanceCommunication();
+static void MachineSpecificDrainResources(); /* used when exit */
+static void MachineSpecificExit();
+
+/* Functions providing incoming network messages */
+void *CmiGetNonLocal(void);
+#if CMK_NODE_QUEUE_AVAILABLE
+void *CmiGetNonLocalNodeQ(void);
+#endif
+void MachineSpecificPostNonLocal(void);
+
+/* Utiltiy functions */
+static char *CopyMsg(char *msg, int len);
+
+/* ===== End of Common Function Declarations ===== */
+
+#include "machine-smp.c"
+
+/* ===== Beginning of Idle-state Related Declarations =====  */
+typedef struct {
+    int sleepMs; /*Milliseconds to sleep while idle*/
+    int nIdles; /*Number of times we've been idle in a row*/
+    CmiState cs; /*Machine state*/
+} CmiIdleState;
+
+static CmiIdleState *CmiNotifyGetState(void);
+
+/**
+ *  Generally,
+ *
+ *  CmiNotifyIdle is used in non-SMP mode when the proc is idle.
+ *  When the proc is idle, AdvanceCommunication needs to be
+ *  called.
+ *
+ *  CmiNotifyStillIdle and CmiNotifyBeginIdle are used in SMP mode.
+ *
+ *  Different layers have choices of registering different callbacks for
+ *  idle state.
+ */
+static void CmiNotifyBeginIdle(CmiIdleState *s);
+static void CmiNotifyStillIdle(CmiIdleState *s);
+void CmiNotifyIdle(void);
+/* ===== End of Idle-state Related Declarations =====  */
+
+/* ===== Beginning of Processor/Node State-related Stuff =====*/
+#if !CMK_SMP
+/************ non SMP **************/
+static struct CmiStateStruct Cmi_state;
+int _Cmi_mype;
+int _Cmi_myrank;
+
+void CmiMemLock() {}
+void CmiMemUnlock() {}
+
+#define CmiGetState() (&Cmi_state)
+#define CmiGetStateN(n) (&Cmi_state)
+
+void CmiYield(void) {
+    sleep(0);
+}
+
+static void CmiStartThreads(char **argv) {
+    CmiStateInit(Cmi_nodestart, 0, &Cmi_state);
+    _Cmi_mype = Cmi_nodestart;
+    _Cmi_myrank = 0;
+}
+#else
+/************** SMP *******************/
+INLINE_KEYWORD int CmiMyPe(void) {
+    return CmiGetState()->pe;
+}
+INLINE_KEYWORD int CmiMyRank(void) {
+    return CmiGetState()->rank;
+}
+INLINE_KEYWORD int CmiNodeFirst(int node) {
+    return node*_Cmi_mynodesize;
+}
+INLINE_KEYWORD int CmiNodeSize(int node) {
+    return _Cmi_mynodesize;
+}
+INLINE_KEYWORD int CmiNodeOf(int pe) {
+    return (pe/_Cmi_mynodesize);
+}
+INLINE_KEYWORD int CmiRankOf(int pe) {
+    return pe%_Cmi_mynodesize;
+}
+#endif
+CsvDeclare(CmiNodeState, NodeState);
+/* ===== End of Processor/Node State-related Stuff =====*/
+
+#include "immediate.c"
+
+/* ===== Beginning of Common Function Definitions ===== */
+static void PerrorExit(const char *msg) {
+    perror(msg);
+    exit(1);
+}
+
+/* ##### Beginning of Functions Related with Message Sending OPs ##### */
+/*Add a message to this processor's receive queue, pe is a rank */
+void CmiPushPE(int rank,void *msg) {
+    CmiState cs = CmiGetStateN(rank);
+    MACHSTATE2(3,"Pushing message into rank %d's queue %p{",rank, cs->recv);
+#if CMK_IMMEDIATE_MSG
+    if (CmiIsImmediate(msg)) {
+        MACHSTATE1(3, "[%p] Push Immediate Message begin{",CmiGetState());
+        CMI_DEST_RANK(msg) = rank;
+        CmiPushImmediateMsg(msg);
+        MACHSTATE1(3, "[%p] Push Immediate Message end}",CmiGetState());
+        return;
+    }
+#endif
+
+    PCQueuePush(cs->recv,msg);
+    CmiIdleLock_addMessage(&cs->idle);
+    MACHSTATE1(3,"} Pushing message into rank %d's queue done",rank);
+}
+
+#if CMK_NODE_QUEUE_AVAILABLE
+/*Add a message to this processor's receive queue */
+void CmiPushNode(void *msg) {
+    MACHSTATE(3,"Pushing message into NodeRecv queue");
+#if CMK_IMMEDIATE_MSG
+    if (CmiIsImmediate(msg)) {
+        CMI_DEST_RANK(msg) = 0;
+        CmiPushImmediateMsg(msg);
+        return;
+    }
+#endif
+    CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
+    PCQueuePush(CsvAccess(NodeState).NodeRecv,msg);
+    CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
+    {
+        CmiState cs=CmiGetStateN(0);
+        CmiIdleLock_addMessage(&cs->idle);
+    }
+}
+#endif
+
+/* This function handles the msg received as which queue to push into */
+static INLINE_KEYWORD void handleOneRecvedMsg(int size, char *msg) {
+    int isBcastMsg = 0;
+#if CMK_BROADCAST_SPANNING_TREE || CMK_BROADCAST_HYPERCUBE
+    isBcastMsg = (CMI_BROADCAST_ROOT(msg)!=0);
+#endif
+
+    if (isBcastMsg) {
+        handleOneBcastMsg(size, msg);
+        return;
+    }
+
+#if CMK_NODE_QUEUE_AVAILABLE
+    if (CMI_DEST_RANK(msg)==DGRAM_NODEMESSAGE)
+        CmiPushNode(msg);
+    else
+#endif
+        CmiPushPE(CMI_DEST_RANK(msg), msg);
+
+}
+
+
+/* ##### Beginning of Broadcast-related functions' defitions ##### */
+static void handleOneBcastMsg(int size, char *msg) {
+    CmiAssert(CMI_BROADCAST_ROOT(msg)!=0);
+#if CMK_OFFLOAD_BCAST_PROCESS
+    if (CMI_BROADCAST_ROOT(msg)>0) {
+        PCQueuePush(CsvAccess(procBcastQ), msg);
+    } else {
+#if CMK_NODE_QUEUE_AVAILABLE
+        PCQueuePush(CsvAccess(nodeBcastQ), msg);
+#endif
+    }
+#else
+    if (CMI_BROADCAST_ROOT(msg)>0) {
+        processProcBcastMsg(size, msg);
+    } else {
+#if CMK_NODE_QUEUE_AVAILABLE
+        processNodeBcastMsg(size, msg);
+#endif
+    }
+#endif
+}
+
+static void processBcastQs() {
+#if CMK_OFFLOAD_BCAST_PROCESS
+    char *msg;
+    do {
+        msg = PCQueuePop(CsvAccess(procBcastQ));
+        if (!msg) break;
+        MACHSTATE2(4, "[%d]: process a proc-level bcast msg %p begin{", CmiMyNode(), msg);
+        processProcBcastMsg(CMI_MSG_SIZE(msg), msg);
+        MACHSTATE2(4, "[%d]: process a proc-level bcast msg %p end}", CmiMyNode(), msg);
+    } while (1);
+#if CMK_NODE_QUEUE_AVAILABLE
+    do {
+        msg = PCQueuePop(CsvAccess(nodeBcastQ));
+        if (!msg) break;
+        MACHSTATE2(4, "[%d]: process a node-level bcast msg %p begin{", CmiMyNode(), msg);
+        processNodeBcastMsg(CMI_MSG_SIZE(msg), msg);
+        MACHSTATE2(4, "[%d]: process a node-level bcast msg %p end}", CmiMyNode(), msg);
+    } while (1);
+#endif
+#endif
+}
+
+static INLINE_KEYWORD void processProcBcastMsg(int size, char *msg) {
+#if CMK_BROADCAST_SPANNING_TREE
+    SendSpanningChildrenProc(size, msg);
+#elif CMK_BROADCAST_HYPERCUBE
+    SendHyperCubeProc(size, msg);
+#endif
+
+    /* Since this function is only called on intermediate nodes,
+     * the rank of this msg should be 0.
+     */
+    CmiAssert(CMI_DEST_RANK(msg)==0);
+    /*CmiPushPE(CMI_DEST_RANK(msg), msg);*/
+    CmiPushPE(0, msg);
+}
+
+static INLINE_KEYWORD void processNodeBcastMsg(int size, char *msg) {
+#if CMK_BROADCAST_SPANNING_TREE
+    SendSpanningChildrenNode(size, msg);
+#elif CMK_BROADCAST_HYPERCUBE
+    SendHyperCubeNode(size, msg);
+#endif
+
+    /* In SMP mode, this push operation needs to be executed
+     * after forwarding broadcast messages. If it is executed
+     * earlier, then during the bcast msg forwarding period,
+     * the msg could be already freed on the worker thread.
+     * As a result, the forwarded message could be wrong!
+     * --Chao Mei
+     */
+    CmiPushNode(msg);
+}
+
+static void SendSpanningChildren(int size, char *msg, int rankToAssign, int startNode) {
+#if CMK_BROADCAST_SPANNING_TREE
+    int i, oldRank;
+
+    oldRank = CMI_DEST_RANK(msg);
+    /* doing this is to avoid the multiple assignment in the following for loop */
+    CMI_DEST_RANK(msg) = rankToAssign;
+    /* first send msgs to other nodes */
+    CmiAssert(startNode >=0 &&  startNode<CmiNumNodes());
+    for (i=1; i<=BROADCAST_SPANNING_FACTOR; i++) {
+        int nd = CmiMyNode()-startNode;
+        if (nd<0) nd+=CmiNumNodes();
+        nd = BROADCAST_SPANNING_FACTOR*nd + i;
+        if (nd > CmiNumNodes() - 1) break;
+        nd += startNode;
+        nd = nd%CmiNumNodes();
+        CmiAssert(nd>=0 && nd!=CmiMyNode());
+#if CMK_BROADCAST_USE_CMIREFERENCE
+        CmiReference(msg);
+        CmiMachineSpecificSendFunc(nd, size, msg, P2P_SYNC);
+#else
+        char *newmsg = CopyMsg(msg, size);
+        CmiMachineSpecificSendFunc(nd, size, newmsg, P2P_SYNC);
+#endif
+    }
+    CMI_DEST_RANK(msg) = oldRank;
+#endif
+}
+static void SendHyperCube(int size,  char *msg, int rankToAssign, int startNode) {
+#if CMK_BROADCAST_HYPERCUBE
+    int i, cnt, tmp, relDist, oldRank;
+    const int dims=CmiNodesDim;
+
+    oldRank = CMI_DEST_RANK(msg);
+    /* doing this is to avoid the multiple assignment in the following for loop */
+    CMI_DEST_RANK(msg) = rankToAssign;
+
+    /* first send msgs to other nodes */
+    relDist = CmiMyNode()-startNode;
+    if (relDist < 0) relDist += CmiNumNodes();
+    cnt=0;
+    tmp = relDist;
+    /* count how many zeros (in binary format) relDist has */
+    for (i=0; i<dims; i++, cnt++) {
+        if (tmp & 1 == 1) break;
+        tmp = tmp >> 1;
+    }
+
+    /*CmiPrintf("ND[%d]: SendHypercube with snd=%d, relDist=%d, cnt=%d\n", CmiMyNode(), startnode, relDist, cnt);*/
+    for (i = cnt-1; i >= 0; i--) {
+        int nd = relDist + (1 << i);
+        if (nd >= CmiNumNodes()) continue;
+        nd = (nd+startNode)%CmiNumNodes();
+        /*CmiPrintf("ND[%d]: send to node %d\n", CmiMyNode(), nd);*/
+        CmiAssert(nd>=0 && nd!=CmiMyNode());
+#if CMK_BROADCAST_USE_CMIREFERENCE
+        CmiReference(msg);
+        CmiMachineSpecificSendFunc(nd, size, msg, P2P_SYNC);
+#else
+        char *newmsg = CopyMsg(msg, size);
+        CmiMachineSpecificSendFunc(nd, size, newmsg, P2P_SYNC);
+#endif
+    }
+    CMI_DEST_RANK(msg) = oldRank;
+#endif
+}
+
+static void SendSpanningChildrenProc(int size, char *msg) {
+    int startpe = CMI_BROADCAST_ROOT(msg)-1;
+    int startnode = CmiNodeOf(startpe);
+#if CMK_SMP
+    if (startpe > CmiNumPes()) startnode = startpe - CmiNumPes();
+#endif
+    SendSpanningChildren(size, msg, 0, startnode);
+#if CMK_SMP
+    /* second send msgs to my peers on this node */
+    SendToPeers(size, msg);
+#endif
+}
+
+/* send msg along the hypercube in broadcast. (Sameer) */
+static void SendHyperCubeProc(int size, char *msg) {
+    int startpe = CMI_BROADCAST_ROOT(msg)-1;
+    int startnode = CmiNodeOf(startpe);
+#if CMK_SMP
+    if (startpe > CmiNumPes()) startnode = startpe - CmiNumPes();
+#endif
+    SendHyperCube(size, msg, 0, startnode);
+#if CMK_SMP
+    /* second send msgs to my peers on this node */
+    SendToPeers(size, msg);
+#endif
+}
+
+static void SendToPeers(int size, char *msg) {
+    /* FIXME: now it's just a flat p2p send!! When node size is large,
+    * it should also be sent in a tree
+    */
+    int exceptRank = CMI_DEST_RANK(msg);
+    int i;
+    for (i=0; i<exceptRank; i++) {
+        CmiPushPE(i, CopyMsg(msg, size));
+    }
+    for (i=exceptRank+1; i<CmiMyNodeSize(); i++) {
+        CmiPushPE(i, CopyMsg(msg, size));
+    }
+}
+
+#if CMK_NODE_QUEUE_AVAILABLE
+static void SendSpanningChildrenNode(int size, char *msg) {
+    int startnode = -CMI_BROADCAST_ROOT(msg)-1;
+    SendSpanningChildren(size, msg, DGRAM_NODEMESSAGE, startnode);
+}
+static void SendHyperCubeNode(int size, char *msg) {
+    int startnode = -CMI_BROADCAST_ROOT(msg)-1;
+    SendHyperCube(size, msg, DGRAM_NODEMESSAGE, startnode);
+}
+#endif
+/*##### End of Broadcast-related functions' defitions #####*/
+
+/* Functions regarding sending operations */
+static void CmiSendSelf(char *msg) {
+#if CMK_IMMEDIATE_MSG
+    if (CmiIsImmediate(msg)) {
+        /* CmiBecomeNonImmediate(msg); */
+        CmiPushImmediateMsg(msg);
+        CmiHandleImmediate();
+        return;
+    }
+#endif
+    CdsFifo_Enqueue(CpvAccess(CmiLocalQueue),msg);
+}
+
+/* Functions regarding P2P send op */
+#if USE_COMMON_SYNC_P2P
+void CmiSyncSendFn(int destPE, int size, char *msg) {
+    char *dupmsg = CopyMsg(msg, size);
+    CmiFreeSendFn(destPE, size, dupmsg);
+}
+
+void CmiFreeSendFn(int destPE, int size, char *msg) {
+    CMI_SET_BROADCAST_ROOT(msg, 0);
+    CQdCreate(CpvAccess(cQdState), 1);
+    if (CmiMyPe()==destPE) {
+        CmiSendSelf(msg);
+    } else {
+        int destNode = CmiNodeOf(destPE);
+#if CMK_SMP
+        if (CmiMyNode()==destNode) {
+            CmiPushPE(CmiRankOf(destPE), msg);
+            return;
+        }
+#endif
+        CMI_DEST_RANK(msg) = CmiRankOf(destPE);
+        CmiMachineSpecificSendFunc(destNode, size, msg, P2P_SYNC);
+    }
+}
+#endif
+
+#if USE_COMMON_ASYNC_P2P
+CmiCommHandle CmiAsyncSendFn(int destPE, int size, char *msg) {
+    int destNode = CmiNodeOf(destPE);
+    if (destNode == CmiMyNode()) {
+        CmiSyncSendFn(destPE,size,msg);
+        return 0;
+    } else {
+        return CmiMachineSpecificSendFunc(destPE, size, msg, P2P_ASYNC);
+    }
+}
+#endif
+
+#if USE_COMMON_SYNC_BCAST
+/* Functions regarding broadcat op that sends to every one else except me */
+void CmiSyncBroadcastFn(int size, char *msg) {
+    int mype = CmiMyPe();
+    int i;
+
+    CQdCreate(CpvAccess(cQdState), CmiNumPes()-1);
+#if CMK_SMP
+    /*record the rank to avoid re-sending the msg in  spanning tree or hypercube*/
+    CMI_DEST_RANK(msg) = CmiMyRank();
+#endif
+
+#if CMK_BROADCAST_SPANNING_TREE
+    CMI_SET_BROADCAST_ROOT(msg, mype+1);
+    SendSpanningChildrenProc(size, msg);
+#elif CMK_BROADCAST_HYPERCUBE
+    CMI_SET_BROADCAST_ROOT(msg, mype+1);
+    SendHyperCubeProc(size, msg);
+#else
+    for ( i=mype+1; i<_Cmi_numpes; i++ )
+        CmiSyncSendFn(i, size, msg) ;
+    for ( i=0; i<mype; i++ )
+        CmiSyncSendFn(i, size, msg) ;
+#endif
+
+    /*CmiPrintf("In  SyncBroadcast broadcast\n");*/
+}
+
+void CmiFreeBroadcastFn(int size, char *msg) {
+    CmiSyncBroadcastFn(size,msg);
+    CmiFree(msg);
+}
+#endif
+
+#if USE_COMMON_ASYNC_BCAST
+/* FIXME: should use spanning or hypercube, but luckily async is never used */
+CmiCommHandle CmiAsyncBroadcastFn(int size, char *msg) {
+    /*CmiPrintf("In  AsyncBroadcast broadcast\n");*/
+    CmiAbort("CmiAsyncBroadcastFn should never be called");
+    return 0;
+}
+#endif
+
+/* Functions regarding broadcat op that sends to every one */
+void CmiSyncBroadcastAllFn(int size, char *msg) {
+    CmiSyncSendFn(CmiMyPe(), size, msg) ;
+    CmiSyncBroadcastFn(size, msg);
+}
+
+void CmiFreeBroadcastAllFn(int size, char *msg) {
+    CmiSendSelf(msg);
+    CmiSyncBroadcastFn(size, msg);
+}
+
+CmiCommHandle CmiAsyncBroadcastAllFn(int size, char *msg) {
+    CmiSendSelf(CopyMsg(msg, size));
+    return CmiAsyncBroadcastFn(size, msg);
+}
+
+#if CMK_NODE_QUEUE_AVAILABLE
+static void CmiSendNodeSelf(char *msg) {
+#if CMK_IMMEDIATE_MSG
+    if (CmiIsImmediate(msg)) {
+        CmiPushImmediateMsg(msg);
+        if (!_immRunning) CmiHandleImmediate();
+        return;
+    }
+#endif
+    CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
+    PCQueuePush(CsvAccess(NodeState).NodeRecv, msg);
+    CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
+}
+
+#if USE_COMMON_ASYNC_P2P
+void CmiSyncNodeSendFn(int destNode, int size, char *msg) {
+    char *dupmsg = CopyMsg(msg, size);
+    CmiFreeNodeSendFn(destNode, size, dupmsg);
+}
+
+void CmiFreeNodeSendFn(int destNode, int size, char *msg) {
+    CMI_DEST_RANK(msg) = DGRAM_NODEMESSAGE;
+    CQdCreate(CpvAccess(cQdState), 1);
+    CMI_SET_BROADCAST_ROOT(msg, 0);
+    if (destNode == CmiMyNode()) {
+        CmiSendNodeSelf(msg);
+    } else {
+        CmiMachineSpecificSendFunc(destNode, size, msg, P2P_SYNC);
+    }
+}
+#endif
+
+#if USE_COMMON_ASYNC_P2P
+CmiCommHandle CmiAsyncNodeSendFn(int destNode, int size, char *msg) {
+    if (destNode == CmiMyNode()) {
+        CmiSyncNodeSendFn(destNode, size, msg);
+        return 0;
+    } else {
+        return CmiMachineSpecificSendFunc(destNode, size, msg, P2P_ASYNC);
+    }
+}
+#endif
+
+#if USE_COMMON_SYNC_BCAST
+void CmiSyncNodeBroadcastFn(int size, char *msg) {
+    int mynode = CmiMyNode();
+    int i;
+    CQdCreate(CpvAccess(cQdState), CmiNumNodes()-1);
+#if CMK_BROADCAST_SPANNING_TREE
+    CMI_SET_BROADCAST_ROOT(msg, -CmiMyNode()-1);
+    SendSpanningChildrenNode(size, msg);
+#elif CMK_BROADCAST_HYPERCUBE
+    CMI_SET_BROADCAST_ROOT(msg, -CmiMyNode()-1);
+    SendHyperCubeNode(size, msg);
+#else
+    for (i=mynode+1; i<CmiNumNodes(); i++)
+        CmiSyncNodeSendFn(i, size, msg);
+    for (i=0; i<mynode; i++)
+        CmiSyncNodeSendFn(i, size, msg);
+#endif
+}
+
+void CmiFreeNodeBroadcastFn(int size, char *msg) {
+    CmiSyncNodeBroadcastFn(size, msg);
+    CmiFree(msg);
+}
+#endif
+
+#if USE_COMMON_ASYNC_BCAST
+CmiCommHandle CmiAsyncNodeBroadcastFn(int size, char *msg) {
+    CmiSyncNodeBroadcastFn(size, msg);
+    return 0;
+}
+#endif
+
+void CmiSyncNodeBroadcastAllFn(int size, char *msg) {
+    CmiSyncNodeSendFn(CmiMyNode(), size, msg);
+    CmiSyncNodeBroadcastFn(size, msg);
+}
+
+CmiCommHandle CmiAsyncNodeBroadcastAllFn(int size, char *msg) {
+    CmiSendNodeSelf(CopyMsg(msg, size));
+    return CmiAsyncNodeBroadcastFn(size, msg);
+}
+
+void CmiFreeNodeBroadcastAllFn(int size, char *msg) {
+    CmiSyncNodeBroadcastFn(size, msg);
+    /* Since it's a node-level msg, the msg could be executed on any other
+     * procs on the same node. This means, the push of this msg to the
+     * node-level queue could be immediately followed a pop of this msg on
+     * other cores on the same node even when this msg has not been sent to
+     * other nodes. This is the reason CmiSendNodeSelf must be called after
+     * CmiSyncNodeBroadcastFn -Chao Mei
+     */
+    CmiSendNodeSelf(msg);
+}
+#endif
+/* ##### End of Functions Related with Message Sending OPs ##### */
+
+/* ##### Beginning of Functions Related with Machine Startup ##### */
+void ConverseInit(int argc, char **argv, CmiStartFn fn, int usched, int initret) {
+    int tmp;
+    /* processor per node */
+    _Cmi_mynodesize = 1;
+    if (!CmiGetArgInt(argv,"+ppn", &_Cmi_mynodesize))
+        CmiGetArgInt(argv,"++ppn", &_Cmi_mynodesize);
+#if ! CMK_SMP
+    if (_Cmi_mynodesize > 1 && _Cmi_mynode == 0)
+        CmiAbort("+ppn cannot be used in non SMP version!\n");
+#endif
+
+    /* Network progress function is used to poll the network when for
+    messages. This flushes receive buffers on some  implementations*/
+    networkProgressPeriod = NETWORK_PROGRESS_PERIOD_DEFAULT;
+    CmiGetArgInt(argv, "+networkProgressPeriod", &networkProgressPeriod);
+
+    /* _Cmi_mynodesize has to be obtained before MachineSpecificInit
+     * because it may be used inside MachineSpecificInit
+     */
+    /* argv could be changed inside MachineSpecificInit */
+    /* Inside this function, the number of nodes and my node id are obtained */
+    MachineSpecificInit(argc, argv, &_Cmi_numnodes, &_Cmi_mynode);
+
+    _Cmi_numpes = _Cmi_numnodes * _Cmi_mynodesize;
+    Cmi_nodestart = _Cmi_mynode * _Cmi_mynodesize;
+    Cmi_argvcopy = CmiCopyArgs(argv);
+    Cmi_argv = argv;
+    Cmi_startfn = fn;
+    Cmi_usrsched = usched;
+
+    /* CmiTimerInit(); */
+#if CMK_BROADCAST_HYPERCUBE
+    /* CmiNodesDim = ceil(log2(CmiNumNodes)) except when #nodes is 1*/
+    tmp = CmiNumNodes()-1;
+    CmiNodesDim = 0;
+    while (tmp>0) {
+        CmiNodesDim++;
+        tmp = tmp >> 1;
+    }
+    if (CmiNumNodes()==1) CmiNodesDim=1;
+#endif
+
+    CsvInitialize(CmiNodeState, NodeState);
+    CmiNodeStateInit(&CsvAccess(NodeState));
+#if CMK_SMP
+    commThdExitLock = CmiCreateLock();
+#endif
+
+#if CMK_OFFLOAD_BCAST_PROCESS
+    /* the actual queues should be created on comm thread considering NUMA in SMP */
+    CsvInitialize(PCQueue, procBcastQ);
+#if CMK_NODE_QUEUE_AVAILABLE
+    CsvInitialize(PCQueue, nodeBcastQ);
+#endif
+#endif
+
+    CmiStartThreads(argv);
+    ConverseRunPE(initret);
+}
+
+static void ConverseRunPE(int everReturn) {
+    CmiState cs;
+    char** CmiMyArgv;
+
+    MachineSpecificPreCommonInit(everReturn);
+
+#if CMK_OFFLOAD_BCAST_PROCESS
+    int createQueue = 1;
+#if CMK_SMP
+#if CMK_SMP_NO_COMMTHD
+    /* If there's no comm thread, then the queue is created on rank 0 */
+    if (CmiMyRank()) createQueue = 0;
+#else
+    if (CmiMyRank()<CmiMyNodeSize()) createQueue = 0;
+#endif
+#endif
+
+    if (createQueue) {
+        CsvAccess(procBcastQ) = PCQueueCreate();
+#if CMK_NODE_QUEUE_AVAILABLE
+        CsvAccess(nodeBcastQ) = PCQueueCreate();
+#endif
+    }
+#endif
+
+    CmiNodeAllBarrier();
+
+    cs = CmiGetState();
+    CpvInitialize(void *,CmiLocalQueue);
+    CpvAccess(CmiLocalQueue) = cs->localqueue;
+
+    if (CmiMyRank())
+        CmiMyArgv=CmiCopyArgs(Cmi_argvcopy);
+    else
+        CmiMyArgv=Cmi_argv;
+
+    CthInit(CmiMyArgv);
+
+    /* initialize the network progress counter*/
+    /* Network progress function is used to poll the network when for
+       messages. This flushes receive buffers on some  implementations*/
+    CpvInitialize(unsigned , networkProgressCount);
+    CpvAccess(networkProgressCount) = 0;
+
+    ConverseCommonInit(CmiMyArgv);
+
+    MachineSpecificPostCommonInit(everReturn);
+
+    /* Converse initialization finishes, immediate messages can be processed.
+       node barrier previously should take care of the node synchronization */
+    _immediateReady = 1;
+
+    /* communication thread */
+    if (CmiMyRank() == CmiMyNodeSize()) {
+        Cmi_startfn(CmiGetArgc(CmiMyArgv), CmiMyArgv);
+        while (1) CommunicationServerThread(5);
+    } else { /* worker thread */
+        if (!everReturn) {
+            Cmi_startfn(CmiGetArgc(CmiMyArgv), CmiMyArgv);
+            if (Cmi_usrsched==0) CsdScheduler(-1);
+            ConverseExit();
+        }
+    }
+}
+/* ##### End of Functions Related with Machine Startup ##### */
+
+/* ##### Beginning of Functions Related with Machine Running ##### */
+static INLINE_KEYWORD void AdvanceCommunication() {
+    int doProcessBcast = 1;
+
+    MachineSpecificAdvanceCommunication();
+
+#if CMK_OFFLOAD_BCAST_PROCESS
+#if CMK_SMP_NO_COMMTHD
+    /*FIXME: only asks rank 0 to process bcast msgs, so perf may suffer*/
+    if (CmiMyRank()) doProcessBcast = 0;
+#endif
+    if (doProcessBcast) processBcastQs();
+#endif
+
+#if CMK_IMMEDIATE_MSG
+#if !CMK_SMP
+    CmiHandleImmediate();
+#endif
+#if CMK_SMP && CMK_SMP_NO_COMMTHD
+    if (CmiMyRank()==0) CmiHandleImmediate();
+#endif
+#endif
+
+}
+
+static void CommunicationServer(int sleepTime) {
+#if CMK_SMP
+    AdvanceCommunication();
+
+    if (commThdExit == CmiMyNodeSize()) {
+        MACHSTATE(2, "CommunicationServer exiting {");
+        MachineSpecificDrainResources();
+        MACHSTATE(2, "} CommunicationServer EXIT");
+
+        ConverseCommonExit();
+
+        MachineSpecificExit();
+    }
+#endif
+}
+
+static void CommunicationServerThread(int sleepTime) {
+    CommunicationServer(sleepTime);
+#if CMK_IMMEDIATE_MSG
+    CmiHandleImmediate();
+#endif
+}
+
+void ConverseExit(void) {
+#if !CMK_SMP
+    MachineSpecificDrainResources();
+#endif
+
+    ConverseCommonExit();
+
+#if (CMK_DEBUG_MODE || CMK_WEB_MODE || NODE_0_IS_CONVHOST)
+    if (CmiMyPe() == 0) CmiPrintf("End of program\n");
+#endif
+
+#if !CMK_SMP
+    MachineSpecificExit();
+#else
+    /* In SMP, the communication thread will exit */
+    /* atomic increment */
+    CmiLock(commThdExitLock);
+    commThdExit++;
+    CmiUnlock(commThdExitLock);
+    while (1) CmiYield();
+#endif
+}
+/* ##### End of Functions Related with Machine Running ##### */
+
+
+/* ##### Beginning of Functions Providing Incoming Network Messages ##### */
+void *CmiGetNonLocal(void) {
+    CmiState cs = CmiGetState();
+    void *msg = NULL;
+
+    if (CmiNumPes() == 1) return NULL;
+
+    MACHSTATE2(3, "[%p] CmiGetNonLocal begin %d{", cs, CmiMyPe());
+    CmiIdleLock_checkMessage(&cs->idle);
+    /* ?????although it seems that lock is not needed, I found it crashes very often
+       on mpi-smp without lock */
+#if !CMK_SMP
+    AdvanceCommunication();
+#endif
+
+    msg = PCQueuePop(cs->recv);
+
+#if !CMK_SMP
+    MachineSpecificPostNonLocal();
+#endif
+
+    MACHSTATE3(3,"[%p] CmiGetNonLocal from queue %p with msg %p end }",CmiGetState(),(cs->recv), msg);
+
+    return msg;
+}
+#if CMK_NODE_QUEUE_AVAILABLE
+void *CmiGetNonLocalNodeQ(void) {
+    CmiState cs = CmiGetState();
+    char *result = 0;
+    CmiIdleLock_checkMessage(&cs->idle);
+    if (!PCQueueEmpty(CsvAccess(NodeState).NodeRecv)) {
+        MACHSTATE1(3,"CmiGetNonLocalNodeQ begin %d {", CmiMyPe());
+        CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
+        result = (char *) PCQueuePop(CsvAccess(NodeState).NodeRecv);
+        CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
+        MACHSTATE1(3,"} CmiGetNonLocalNodeQ end %d ", CmiMyPe());
+    }
+
+    return result;
+}
+#endif
+/* ##### End of Functions Providing Incoming Network Messages ##### */
+
+/* ##### Beginning of Functions Related with Idle-state ##### */
+static CmiIdleState *CmiNotifyGetState(void) {
+    CmiIdleState *s=(CmiIdleState *)malloc(sizeof(CmiIdleState));
+    s->sleepMs=0;
+    s->nIdles=0;
+    s->cs=CmiGetState();
+    return s;
+}
+
+static void CmiNotifyBeginIdle(CmiIdleState *s) {
+    s->sleepMs=0;
+    s->nIdles=0;
+}
+
+/*Number of times to spin before sleeping*/
+#define SPINS_BEFORE_SLEEP 20
+static void CmiNotifyStillIdle(CmiIdleState *s) {
+    MACHSTATE1(2,"still idle (%d) begin {",CmiMyPe())
+    s->nIdles++;
+    if (s->nIdles>SPINS_BEFORE_SLEEP) { /*Start giving some time back to the OS*/
+        s->sleepMs+=2;
+        if (s->sleepMs>10) s->sleepMs=10;
+    }
+
+    if (s->sleepMs>0) {
+        MACHSTATE1(2,"idle lock(%d) {",CmiMyPe())
+        CmiIdleLock_sleep(&s->cs->idle,s->sleepMs);
+        MACHSTATE1(2,"} idle lock(%d)",CmiMyPe())
+    }
+
+#if !CMK_SMP
+    AdvanceCommunication();
+#endif
+
+    MACHSTATE1(2,"still idle (%d) end {",CmiMyPe())
+}
+
+/* usually called in non-smp mode */
+void CmiNotifyIdle(void) {
+    AdvanceCommunication();
+    CmiYield();
+}
+/* ##### End of Functions Related with Idle-state ##### */
+
+/* Utiltiy functions */
+static char *CopyMsg(char *msg, int len) {
+    char *copy = (char *)CmiAlloc(len);
+#if CMK_ERROR_CHECKING
+    if (!copy) {
+        CmiAbort("Error: out of memory in machine layer\n");
+    }
+#endif
+    memcpy(copy, msg, len);
+    return copy;
+}
+/* ===== End of Common Function Definitions ===== */