fix for migration
[charm.git] / src / arch / mpi / machine.c
index 11f28a39d0440d85a88ee986e44c3ae327662319..e6c19ece5309e8351988bc5646e48ccaf19aa58a 100644 (file)
@@ -56,13 +56,14 @@ static int CMI_DYNAMIC_RECV_CAPSIZE=3;
 /* initial values, -1 indiates there's no cap */
 static int dynamicSendCap = CMI_DYNAMIC_MAXCAPSIZE;
 static int dynamicRecvCap = CMI_DYNAMIC_MAXCAPSIZE;
+MPI_Comm charmComm;
 
 #if CMI_EXERT_SEND_CAP
-#define SEND_CAP 3
+static int SEND_CAP=3;
 #endif
 
 #if CMI_EXERT_RECV_CAP
-#define RECV_CAP 2
+static int RECV_CAP=2;
 #endif
 /* ###End of flow control related macros ### */
 
@@ -85,7 +86,7 @@ static int dynamicRecvCap = CMI_DYNAMIC_MAXCAPSIZE;
 #define CMK_TRACE_COMMOVERHEAD 0
 #endif
 
-#if CMI_MPI_TRACE_USEREVENTS && CMK_TRACE_ENABLED && ! CMK_TRACE_IN_CHARM
+#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());
@@ -93,6 +94,34 @@ CpvStaticDeclare(double, projTraceStart);
 #define  START_EVENT()
 #define  END_EVENT(x)
 #endif
+
+#if CMK_SMP_TRACE_COMMTHREAD
+#define START_TRACE_SENDCOMM(msg)  \
+                        int isTraceEligible = traceBeginCommOp(msg); \
+                        if(isTraceEligible) traceSendMsgComm(msg);
+#define END_TRACE_SENDCOMM(msg) if(isTraceEligible) traceEndCommOp(msg);
+#define START_TRACE_RECVCOMM(msg) CpvAccess(projTraceStart) = CmiWallTimer();
+#define END_TRACE_RECVCOMM(msg) \
+                        if(traceBeginCommOp(msg)){ \
+                            traceChangeLastTimestamp(CpvAccess(projTraceStart)); \
+                            traceSendMsgComm(msg); \
+                            traceEndCommOp(msg); \
+                        }
+#define CONDITIONAL_TRACE_USER_EVENT(x) \
+                        do{ \
+                            double etime = CmiWallTimer(); \
+                            if(etime - CpvAccess(projTraceStart) > 5*1e-6){ \
+                                traceUserBracketEvent(x, CpvAccess(projTraceStart), etime); \
+                            }\
+                        }while(0);
+#else
+#define START_TRACE_SENDCOMM(msg)
+#define END_TRACE_SENDCOMM(msg)
+#define START_TRACE_RECVCOMM(msg)
+#define END_TRACE_RECVCOMM(msg)
+#define CONDITIONAL_TRACE_USER_EVENT(x)
+#endif
+
 /* ###End of machine-layer-tracing related macros ### */
 
 /* ###Beginning of POST_RECV related macros ### */
@@ -107,16 +136,67 @@ CpvStaticDeclare(double, projTraceStart);
 /* Making those parameters configurable for testing them easily */
 
 #if MPI_POST_RECV
+#define MPI_DYNAMIC_POST_RECV 0
+
+/* Note the tag offset of a msg is determined by
+ * (its size - MPI_RECV_LOWERSIZE)/MPI_POST_RECV_INC.
+ * based on POST_RECV_TAG.
+ */
 static int MPI_POST_RECV_COUNT=10;
-static int MPI_POST_RECV_LOWERSIZE=2000;
-static int MPI_POST_RECV_UPPERSIZE=4000;
+
+/* The range of msgs to be tracked for histogramming */
+static int MPI_POST_RECV_LOWERSIZE=8000;
+static int MPI_POST_RECV_UPPERSIZE=64000;
+
+/* The increment of msg size to be tracked, i.e. the histogram bucket size */
+static int MPI_POST_RECV_INC = 1000;
+
+/* The unit increment of msg cnt for increase #buf for a post recved msg */
+static int MPI_POST_RECV_MSG_INC = 400;
+
+/* If the #msg exceeds this value, post recv is created for such msg */
+static int MPI_POST_RECV_MSG_CNT_THRESHOLD = 200;
+
+/* The frequency of checking the existing posted recv buffers in the unit of #msgs */
+static int MPI_POST_RECV_FREQ = 1000;
+
 static int MPI_POST_RECV_SIZE;
 
+typedef struct mpiPostRecvList {
+    /* POST_RECV_TAG + msgSizeIdx is the recv tag;
+     * Based on this value, this buf corresponds to msg size ranging
+     * [msgSizeIdx*MPI_POST_RECV_INC, (msgSizeIdx+1)*MPI_POST_RECV_INC)
+     */
+    int msgSizeIdx;
+    int bufCnt;
+    MPI_Request *postedRecvReqs;
+    char **postedRecvBufs;
+    struct mpiPostRecvList *next;
+} MPIPostRecvList;
+CpvDeclare(MPIPostRecvList *, postRecvListHdr);
+CpvDeclare(MPIPostRecvList *, curPostRecvPtr);
+CpvDeclare(int, msgRecvCnt);
+
 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
+CpvDeclare(char**,CmiPostedRecvBuffers);
+
+/* Note: currently MPI doesn't provide a function whether a request is in progress.
+ * For example, a irecv has been filled partially. Then a call to MPI_Test still returns
+ * indicating it has not been finished. If only relying on this result, then calling
+ * MPI_Cancel will result in a loss of this msg. The dynamic post recv mechanism
+ * can only be safely used in a synchronized point such as load balancing.
+ */
+#if MPI_DYNAMIC_POST_RECV
+static int MSG_HISTOGRAM_BINSIZE;
+static int MAX_HISTOGRAM_BUCKETS; /* only cares msg size less 2 MB */
+CpvDeclare(int *, MSG_HISTOGRAM_ARRAY);
+static void recordMsgHistogramInfo(int size);
+static void reportMsgHistogramInfo();
+#endif /* end of MPI_DYNAMIC_POST_RECV defined */
+
+#endif /* end of MPI_POST_RECV defined */
 
 /* to avoid MPI's in order delivery, changing MPI Tag all the time */
 #define TAG     1375
@@ -126,6 +206,60 @@ CpvDeclare(char*,CmiPostedRecvBuffers);
 #else
 #define BARRIER_ZERO_TAG   (TAG-1)
 #endif
+
+#define USE_MPI_CTRLMSG_SCHEME 0
+
+/* Defining this macro will use MPI_Irecv instead of MPI_Recv for
+ * large messages. This could save synchronization overhead caused by
+ * the rzv protocol used by MPI
+ */
+#define USE_ASYNC_RECV_FUNC 0
+
+#if USE_ASYNC_RECV_FUNC || USE_MPI_CTRLMSG_SCHEME
+static int IRECV_MSG_THRESHOLD = 8000;
+typedef struct IRecvListEntry{
+    MPI_Request req;
+    char *msg;
+    int size;
+    struct IRecvListEntry *next;
+}*IRecvList;
+
+static IRecvList freedIrecvList = NULL; /* used to recycle the entries */
+static IRecvList waitIrecvListHead = NULL; /* points to the guardian entry, i.e., the next of it points to the first entry */
+static IRecvList waitIrecvListTail = NULL; /* points to the last entry */
+
+static IRecvList irecvListEntryAllocate(){
+    IRecvList ret;
+    if(freedIrecvList == NULL) {
+        ret = (IRecvList)malloc(sizeof(struct IRecvListEntry));        
+        return ret;
+    } else {
+        ret = freedIrecvList;
+        freedIrecvList = freedIrecvList->next;
+        return ret;
+    }
+}
+static void irecvListEntryFree(IRecvList used){
+    used->next = freedIrecvList;
+    freedIrecvList = used;
+}
+
+#endif /* end of USE_ASYNC_RECV_FUNC || USE_MPI_CTRLMSG_SCHEME */
+
+/* Providing functions for external usage to set up the dynamic recv buffer
+ * when the user is aware that it's safe to call such function
+ */
+void CmiSetupMachineRecvBuffers();
+
+#define CAPTURE_MSG_HISTOGRAM 0
+#if CAPTURE_MSG_HISTOGRAM && !MPI_DYNAMIC_POST_RECV
+static int MSG_HISTOGRAM_BINSIZE=1000;
+static int MAX_HISTOGRAM_BUCKETS=2000; /* only cares msg size less 2 MB */
+CpvDeclare(int *, MSG_HISTOGRAM_ARRAY);
+static void recordMsgHistogramInfo(int size);
+static void reportMsgHistogramInfo();
+#endif
+
 /* ###End of POST_RECV related related macros ### */
 
 #if CMK_BLUEGENEL
@@ -167,15 +301,24 @@ void (*signal_int)(int);
 static int _thread_provided = -1; /* Indicating MPI thread level */
 static int idleblock = 0;
 
+#ifdef CMK_MEM_CHECKPOINT || (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)
+typedef struct crashedrank{
+  int rank;
+  struct crashedrank *next;
+} crashedRankList;
+CpvDeclare(crashedRankList *, crashedRankHdr);
+CpvDeclare(crashedRankList *, crashedRankPtr);
+int isRankDie(int rank);
+#endif
 /* 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, mode;
-#if CMK_SMP_TRACE_COMMTHREAD
-    int srcpe;
-#endif
     MPI_Request req;
+#ifdef CMK_MEM_CHECKPOINT || (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)
+    int dstrank; //used in fault tolerance protocol, if the destination is the died rank, delete the msg
+#endif
 } SMSG_LIST;
 
 CpvStaticDeclare(SMSG_LIST *, sent_msgs);
@@ -204,7 +347,7 @@ static CmiNodeLock  sendMsgBufLock = NULL;        /* for sendMsgBuf */
 #endif
 /* =====End of Declarations of Machine Specific Variables===== */
 
-#if CMK_MEM_CHECKPOINT
+#if CMK_MEM_CHECKPOINT || CMK_MESSAGE_LOGGING
 #define FAIL_TAG   1200
 int num_workpes, total_pes;
 int *petorank = NULL;
@@ -229,38 +372,12 @@ static int SendMsgBuf();
 static  void EnqueueMsg(void *m, int size, int node, int mode);
 #endif
 
-/* The machine-specific send function */
-static CmiCommHandle MachineSpecificSendForMPI(int destNode, int size, char *msg, int mode);
-#define LrtsSendFunc MachineSpecificSendForMPI
-
-/* ### Beginning of Machine-startup Related Functions ### */
-static void MachineInitForMPI(int *argc, char ***argv, int *numNodes, int *myNodeID);
-#define LrtsInit MachineInitForMPI
-
-static void MachinePreCommonInitForMPI(int everReturn);
-static void MachinePostCommonInitForMPI(int everReturn);
-#define LrtsPreCommonInit MachinePreCommonInitForMPI
-#define LrtsPostCommonInit MachinePostCommonInitForMPI
-/* ### End of Machine-startup Related Functions ### */
-
-/* ### Beginning of Machine-running Related Functions ### */
-static void AdvanceCommunicationForMPI();
-#define LrtsAdvanceCommunication AdvanceCommunicationForMPI
-
-static void DrainResourcesForMPI(); /* used when exit */
-#define LrtsDrainResources DrainResourcesForMPI
-
-static void MachineExitForMPI();
-#define LrtsExit MachineExitForMPI
 /* ### End of Machine-running Related Functions ### */
 
 /* ### Beginning of Idle-state Related Functions ### */
 void CmiNotifyIdleForMPI(void);
 /* ### End of Idle-state Related Functions ### */
 
-static void MachinePostNonLocalForMPI();
-#define LrtsPostNonLocal MachinePostNonLocalForMPI
-
 /* =====End of Declarations of Machine Specific Functions===== */
 
 /**
@@ -273,11 +390,16 @@ static void MachinePostNonLocalForMPI();
 #include "machine-lrts.h"
 #include "machine-common-core.c"
 
+#if USE_MPI_CTRLMSG_SCHEME
+#include "machine-ctrlmsg.c"
+#endif
+
 /* The machine specific msg-sending function */
 
 #if CMK_SMP
 static void EnqueueMsg(void *m, int size, int node, int mode) {
-    SMSG_LIST *msg_tmp = (SMSG_LIST *) CmiAlloc(sizeof(SMSG_LIST));
+    /*SMSG_LIST *msg_tmp = (SMSG_LIST *) CmiAlloc(sizeof(SMSG_LIST));*/
+    SMSG_LIST *msg_tmp = (SMSG_LIST *) malloc(sizeof(SMSG_LIST));
     MACHSTATE1(3,"EnqueueMsg to node %d {{ ", node);
     msg_tmp->msg = m;
     msg_tmp->size = size;
@@ -285,10 +407,6 @@ static void EnqueueMsg(void *m, int size, int node, int mode) {
     msg_tmp->next = 0;
     msg_tmp->mode = mode;
 
-#if CMK_SMP_TRACE_COMMTHREAD
-    msg_tmp->srcpe = CmiMyPe();
-#endif
-
 #if MULTI_SENDQUEUE
     PCQueuePush(procState[CmiMyRank()].sendMsgBuf,(char *)msg_tmp);
 #else
@@ -307,6 +425,7 @@ static CmiCommHandle MPISendOneMsg(SMSG_LIST *smsg) {
     int size = smsg->size;
     char *msg = smsg->msg;
     int mode = smsg->mode;
+    int dstrank;
 
     MACHSTATE2(3,"MPI_send to node %d rank: %d{", node, CMI_DEST_RANK(msg));
 #if CMK_ERROR_CHECKING
@@ -315,54 +434,49 @@ static CmiCommHandle MPISendOneMsg(SMSG_LIST *smsg) {
 #endif
 
 #if MPI_POST_RECV
-    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,&(smsg->req)))
+    if (size>=MPI_POST_RECV_LOWERSIZE && size < MPI_POST_RECV_UPPERSIZE) {
+#if MPI_DYNAMIC_POST_RECV
+        int sendTagOffset = (size-MPI_POST_RECV_LOWERSIZE)/MPI_POST_RECV_INC+1;
+        START_TRACE_SENDCOMM(msg);
+        if (MPI_SUCCESS != MPI_Isend((void *)msg,size,MPI_BYTE,node,POST_RECV_TAG+sendTagOffset,charmComm,&(smsg->req)))
             CmiAbort("MPISendOneMsg: MPI_Isend failed!\n");
-        /*END_EVENT(40);*/
+        END_TRACE_SENDCOMM(msg);
+#else
+        START_TRACE_SENDCOMM(msg);
+        if (MPI_SUCCESS != MPI_Isend((void *)msg,size,MPI_BYTE,node,POST_RECV_TAG,charmComm,&(smsg->req)))
+            CmiAbort("MPISendOneMsg: MPI_Isend failed!\n");
+        END_TRACE_SENDCOMM(msg);
+#endif
     } else {
-        START_EVENT();
-        if (MPI_SUCCESS != MPI_Isend((void *)msg,size,MPI_BYTE,node,TAG,MPI_COMM_WORLD,&(smsg->req)))
+        START_TRACE_SENDCOMM(msg);
+           if (MPI_SUCCESS != MPI_Isend((void *)msg,size,MPI_BYTE,node,TAG,charmComm,&(smsg->req)))
             CmiAbort("MPISendOneMsg: MPI_Isend failed!\n");
-        /*END_EVENT(40);*/
+        END_TRACE_SENDCOMM(msg);
     }
+#elif USE_MPI_CTRLMSG_SCHEME
+    sendViaCtrlMsg(node, size, msg, smsg);
 #else
-    START_EVENT();
-#if CMK_MEM_CHECKPOINT
-    int dstrank = petorank[node];
+/* branch not using MPI_POST_RECV or USE_MPI_CTRLMSG_SCHEME */
+
+#if CMK_MEM_CHECKPOINT || CMK_MESSAGE_LOGGING
+       dstrank = petorank[node];
+        smsg->dstrank = dstrank;
 #else
-    int dstrank = node;
+       dstrank=node;
 #endif
-    if (MPI_SUCCESS != MPI_Isend((void *)msg,size,MPI_BYTE,dstrank,TAG,MPI_COMM_WORLD,&(smsg->req)))
+    START_TRACE_SENDCOMM(msg)
+    if (MPI_SUCCESS != MPI_Isend((void *)msg,size,MPI_BYTE,dstrank,TAG,charmComm,&(smsg->req)))
         CmiAbort("MPISendOneMsg: MPI_Isend failed!\n");
-    /*END_EVENT(40);*/
-#endif
+    END_TRACE_SENDCOMM(msg)
+#endif /* end of #if MPI_POST_RECV */
 
-#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", smsg->srcpe, CmiNodeFirst(node)+CMI_DEST_RANK(msg));
-    traceUserSuppliedBracketedNote(tmp, 40, CpvAccess(projTraceStart), CmiWallTimer());
-#endif
-#endif
-
-    MACHSTATE(3,"}MPI_send end");
+    MACHSTATE(3,"}MPI_Isend end");
     CpvAccess(MsgQueueLen)++;
     if (CpvAccess(sent_msgs)==0)
         CpvAccess(sent_msgs) = smsg;
-    else
+    else {
         CpvAccess(end_sent)->next = smsg;
+    }
     CpvAccess(end_sent) = smsg;
 
 #if !CMI_DYNAMIC_EXERT_CAP && !CMI_EXERT_SEND_CAP
@@ -378,22 +492,22 @@ static CmiCommHandle MPISendOneMsg(SMSG_LIST *smsg) {
     return (CmiCommHandle) &(smsg->req);
 }
 
-static CmiCommHandle MachineSpecificSendForMPI(int destNode, int size, char *msg, int mode) {
+CmiCommHandle LrtsSendFunc(int destNode, int size, char *msg, int mode) {
     /* Ignoring the mode for MPI layer */
 
     CmiState cs = CmiGetState();
     SMSG_LIST *msg_tmp;
-    int  rank;
 
-    CmiAssert(destNode != CmiMyNode());
+    CmiAssert(destNode != CmiMyNodeGlobal());
 #if CMK_SMP
-    if (_thread_provided != MPI_THREAD_MULTIPLE) {
+    if (Cmi_smp_mode_setting == COMM_THREAD_SEND_RECV) {
       EnqueueMsg(msg, size, destNode, mode);
       return 0;
     }
 #endif
     /* non smp */
-    msg_tmp = (SMSG_LIST *) CmiAlloc(sizeof(SMSG_LIST));
+    /*msg_tmp = (SMSG_LIST *) CmiAlloc(sizeof(SMSG_LIST));*/
+    msg_tmp = (SMSG_LIST *) malloc(sizeof(SMSG_LIST));
     msg_tmp->msg = msg;
     msg_tmp->destpe = destNode;
     msg_tmp->size = size;
@@ -411,6 +525,13 @@ static size_t CmiAllAsyncMsgsSent(void) {
         done = 0;
         if (MPI_SUCCESS != MPI_Test(&(msg_tmp->req), &done, &sts))
             CmiAbort("CmiAllAsyncMsgsSent: MPI_Test failed!\n");
+#ifdef CMK_MEM_CHECKPOINT || (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)
+        if(isRankDie(msg_tmp->dstrank)){
+          //CmiPrintf("[%d][%d] msg to crashed rank\n",CmiMyPartition(),CmiMyPe());
+          //CmiAbort("unexpected send");
+          done = 1;
+        }
+#endif
         if (!done)
             return 0;
         msg_tmp = msg_tmp->next;
@@ -461,6 +582,11 @@ static void CmiReleaseSentMessages(void) {
 #endif
         if (MPI_Test(&(msg_tmp->req), &done, &sts) != MPI_SUCCESS)
             CmiAbort("CmiReleaseSentMessages: MPI_Test failed!\n");
+#ifdef CMK_MEM_CHECKPOINT || (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)
+        if (isRankDie(msg_tmp->dstrank)){
+          done = 1;
+        }
+#endif
         if (done) {
             MACHSTATE2(3,"CmiReleaseSentMessages release one %d to %d", CmiMyPe(), msg_tmp->destpe);
             CpvAccess(MsgQueueLen)--;
@@ -471,7 +597,8 @@ static void CmiReleaseSentMessages(void) {
             else
                 prev->next = temp;
             CmiFree(msg_tmp->msg);
-            CmiFree(msg_tmp);
+            /* CmiFree(msg_tmp); */
+            free(msg_tmp);
             msg_tmp = temp;
         } else {
             prev = msg_tmp;
@@ -510,117 +637,198 @@ static int PumpMsgs(void) {
 #endif
 
     while (1) {
+        int doSyncRecv = 1;
 #if CMI_EXERT_RECV_CAP
         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
-        int completed_index=-1;
-        if (MPI_SUCCESS != MPI_Testany(MPI_POST_RECV_COUNT, CpvAccess(CmiPostedRecvRequests), &completed_index, &flg, &sts))
+        START_TRACE_RECVCOMM(NULL);
+#if USE_MPI_CTRLMSG_SCHEME
+       doSyncRecv = 0;
+       nbytes = recvViaCtrlMsg();
+  recd = 1;
+       if(nbytes == -1) break;
+#elif MPI_POST_RECV
+               /* First check posted recvs then do  probe unmatched outstanding messages */
+        MPIPostRecvList *postedOne = NULL;
+        int completed_index = -1;
+        flg = 0;
+#if MPI_DYNAMIC_POST_RECV
+        MPIPostRecvList *oldPostRecvPtr = CpvAccess(curPostRecvPtr);
+        if (oldPostRecvPtr) {
+            /* post recv buf inited */
+            do {
+                /* round-robin iteration over the list */
+                MPIPostRecvList *cur = CpvAccess(curPostRecvPtr);
+                if (MPI_SUCCESS != MPI_Testany(cur->bufCnt, cur->postedRecvReqs, &completed_index, &flg, &sts))
+                    CmiAbort("PumpMsgs: MPI_Testany failed!\n");
+
+                if (flg) {
+                    postedOne = cur;
+                    break;
+                }
+                CpvAccess(curPostRecvPtr) = CpvAccess(curPostRecvPtr)->next;
+            } while (CpvAccess(curPostRecvPtr) != oldPostRecvPtr);
+        }
+#else
+        MPIPostRecvList *cur = CpvAccess(curPostRecvPtr);
+        if (MPI_SUCCESS != MPI_Testany(cur->bufCnt, cur->postedRecvReqs, &completed_index, &flg, &sts))
             CmiAbort("PumpMsgs: MPI_Testany failed!\n");
+#endif
+        CONDITIONAL_TRACE_USER_EVENT(60); /* MPI_Test related user event */
         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 */
-
-            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);
+#if !MPI_DYNAMIC_POST_RECV
+            postedOne = CpvAccess(curPostRecvPtr);
+#endif
+            msg = (postedOne->postedRecvBufs)[completed_index];
+            (postedOne->postedRecvBufs)[completed_index] = NULL;
 
             CpvAccess(Cmi_posted_recv_total)++;
         } else {
-            res = MPI_Iprobe(MPI_ANY_SOURCE, TAG, MPI_COMM_WORLD, &flg, &sts);
+            START_EVENT();
+            res = MPI_Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, charmComm, &flg, &sts);
             if (res != MPI_SUCCESS)
                 CmiAbort("MPI_Iprobe failed\n");
             if (!flg) break;
+            
+            CONDITIONAL_TRACE_USER_EVENT(70); /* MPI_Iprobe related user 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");
-
-            END_EVENT(30);
-
+#if USE_ASYNC_RECV_FUNC
+            if(nbytes >= IRECV_MSG_THRESHOLD) doSyncRecv = 0;
+#endif            
+            if(doSyncRecv){
+                START_EVENT();
+                if (MPI_SUCCESS != MPI_Recv(msg,nbytes,MPI_BYTE,sts.MPI_SOURCE,sts.MPI_TAG, charmComm,&sts))
+                    CmiAbort("PumpMsgs: MPI_Recv failed!\n");                
+            }
+#if USE_ASYNC_RECV_FUNC        
+            else {
+                START_EVENT();
+                IRecvList one = irecvListEntryAllocate();
+                if(MPI_SUCCESS != MPI_Irecv(msg, nbytes, MPI_BYTE, sts.MPI_SOURCE, sts.MPI_TAG, charmComm, &(one->req)))
+                    CmiAbort("PumpMsgs: MPI_Irecv failed!\n");
+               /*printf("[%d]: irecv msg=%p, nbytes=%d, src=%d, tag=%d\n", CmiMyPe(), msg, nbytes, sts.MPI_SOURCE, sts.MPI_TAG);*/
+                one->msg = msg;
+                one->size = nbytes;
+                one->next = NULL;
+                waitIrecvListTail->next = one;
+               waitIrecvListTail = one;
+                CONDITIONAL_TRACE_USER_EVENT(50); /* MPI_Irecv related user events */
+            }
+#endif
             CpvAccess(Cmi_unposted_recv_total)++;
         }
 #else
-        /* Original version */
-#if CMK_SMP_TRACE_COMMTHREAD || CMK_TRACE_COMMOVERHEAD
-        double startT = CmiWallTimer();
-#endif
-        res = MPI_Iprobe(MPI_ANY_SOURCE, TAG, MPI_COMM_WORLD, &flg, &sts);
+        /* Original version of not using MPI_POST_RECV and USE_MPI_CTRLMSG_SCHEME */
+        START_EVENT();
+        res = MPI_Iprobe(MPI_ANY_SOURCE, TAG, charmComm, &flg, &sts);
         if (res != MPI_SUCCESS)
             CmiAbort("MPI_Iprobe failed\n");
 
         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);
-        }
-#endif
-
+        CONDITIONAL_TRACE_USER_EVENT(70); /* MPI_Iprobe related user 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");
-
-        /*END_EVENT(30);*/
-
+#if USE_ASYNC_RECV_FUNC
+        if(nbytes >= IRECV_MSG_THRESHOLD) doSyncRecv = 0;
+#endif        
+        if(doSyncRecv){
+            START_EVENT();
+            if (MPI_SUCCESS != MPI_Recv(msg,nbytes,MPI_BYTE,sts.MPI_SOURCE,sts.MPI_TAG, charmComm,&sts))
+                CmiAbort("PumpMsgs: MPI_Recv failed!\n");            
+        }
+#if USE_ASYNC_RECV_FUNC        
+        else {
+            START_EVENT();
+            IRecvList one = irecvListEntryAllocate();
+            if(MPI_SUCCESS != MPI_Irecv(msg, nbytes, MPI_BYTE, sts.MPI_SOURCE, sts.MPI_TAG, charmComm, &(one->req)))
+                CmiAbort("PumpMsgs: MPI_Irecv failed!\n");
+            one->msg = msg;
+            one->size = nbytes;
+            one->next = NULL;
+            waitIrecvListTail->next = one;
+            waitIrecvListTail = one;
+            /*printf("PE[%d]: MPI_Irecv msg=%p, size=%d, entry=%p\n", CmiMyPe(), msg, nbytes, one);*/
+            CONDITIONAL_TRACE_USER_EVENT(50); /* MPI_Irecv related user events */
+        }
 #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
-#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 /*end of !MPI_POST_RECV and !USE_MPI_CTRLMSG_SCHEME*/
+
+               if(doSyncRecv){
+                       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
+        
+            END_TRACE_RECVCOMM(msg);
+            handleOneRecvedMsg(nbytes, msg);
+        }
+        
+#if CAPTURE_MSG_HISTOGRAM || MPI_DYNAMIC_POST_RECV
+        recordMsgHistogramInfo(nbytes);
 #endif
 
+#if  MPI_POST_RECV
+#if MPI_DYNAMIC_POST_RECV
+        if (postedOne) {
+            //printf("[%d]: get one posted recv\n", CmiMyPe());
+            /* Get the upper size of this buffer */
+            int postRecvBufSize = postedOne->msgSizeIdx*MPI_POST_RECV_INC + MPI_POST_RECV_LOWERSIZE - 1;
+            int postRecvTag = POST_RECV_TAG + postedOne->msgSizeIdx;
+            /* Has to re-allocate the buffer for the message */
+            (postedOne->postedRecvBufs)[completed_index] = (char *)CmiAlloc(postRecvBufSize);
 
-        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;
+            /* and repost the recv */
+            START_EVENT();
+
+            if (MPI_SUCCESS != MPI_Irecv((postedOne->postedRecvBufs)[completed_index] ,
+                                         postRecvBufSize,
+                                         MPI_BYTE,
+                                         MPI_ANY_SOURCE,
+                                         postRecvTag,
+                                         charmComm,
+                                         &((postedOne->postedRecvReqs)[completed_index])  ))
+                CmiAbort("PumpMsgs: MPI_Irecv failed!\n");
+            CONDITIONAL_TRACE_USER_EVENT(50); /* MPI_Irecv related user events */
         }
-#endif
+#else
+        if (postedOne) {
+            /* Has to re-allocate the buffer for the message */
+            (postedOne->postedRecvBufs)[completed_index] = (char *)CmiAlloc(MPI_POST_RECV_SIZE);
 
-        handleOneRecvedMsg(nbytes, msg);
+            /* and repost the recv */
+            START_EVENT();
+            if (MPI_SUCCESS != MPI_Irecv((postedOne->postedRecvBufs)[completed_index] ,
+                                         MPI_POST_RECV_SIZE,
+                                         MPI_BYTE,
+                                         MPI_ANY_SOURCE,
+                                         POST_RECV_TAG,
+                                         charmComm,
+                                         &((postedOne->postedRecvReqs)[completed_index])  ))
+                CmiAbort("PumpMsgs: MPI_Irecv failed!\n");
+            CONDITIONAL_TRACE_USER_EVENT(50); /* MPI_Irecv related user events */
+        }
+#endif /* not MPI_DYNAMIC_POST_RECV */
+#endif
 
 #if CMI_EXERT_RECV_CAP
         recvCnt++;
@@ -633,14 +841,14 @@ static int PumpMsgs(void) {
              * by MPI
              */
         if (PCQueueLength(sendMsgBuf) > CMI_DYNAMIC_OUTGOING_THRESHOLD
-                || MsgQueueLen > CMI_DYNAMIC_OUTGOING_THRESHOLD) {
+                || CpvAccess(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) {
+        if (CpvAccess(MsgQueueLen) > CMI_DYNAMIC_OUTGOING_THRESHOLD) {
             dynamicRecvCap = CMI_DYNAMIC_RECV_CAPSIZE;
         }
 #endif
@@ -649,6 +857,36 @@ static int PumpMsgs(void) {
 
     }
 
+#if USE_ASYNC_RECV_FUNC || USE_MPI_CTRLMSG_SCHEME
+/* Another loop to check the irecved msgs list */
+{
+       /*TODO: msg cap (throttling) is not exerted here */
+    IRecvList irecvEnt;
+    int irecvDone = 0;
+    MPI_Status sts;
+    while(waitIrecvListHead->next) {
+        IRecvList irecvEnt = waitIrecvListHead->next;
+        START_EVENT();
+                
+        /*printf("PE[%d]: check irecv entry=%p\n", CmiMyPe(), irecvEnt);*/
+        if(MPI_SUCCESS != MPI_Test(&(irecvEnt->req), &irecvDone, &sts))
+            CmiAbort("PumpMsgs: MPI_Test failed!\n");
+        if(!irecvDone) break; /* in-order recv */
+
+        END_TRACE_RECVCOMM((irecvEnt->msg));
+        /*printf("PE[%d]: irecv entry=%p finished with size=%d, msg=%p\n", CmiMyPe(), irecvEnt, irecvEnt->size, irecvEnt->msg);*/
+        
+        handleOneRecvedMsg(irecvEnt->size, irecvEnt->msg);
+        waitIrecvListHead->next = irecvEnt->next;
+        irecvListEntryFree(irecvEnt);
+        //recd = 1;        
+    }
+    if(waitIrecvListHead->next == NULL)
+        waitIrecvListTail = waitIrecvListHead;
+}
+#endif
+
+
     MACHSTATE(2,"} PumpMsgs end ");
     return recd;
 }
@@ -682,26 +920,19 @@ static void PumpMsgsBlocking(void) {
     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();
-
-    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);*/
+    START_TRACE_RECVCOMM(NULL);
+    if (MPI_SUCCESS != MPI_Recv(buf,maxbytes,MPI_BYTE,MPI_ANY_SOURCE,TAG, charmComm,&sts))
+        CmiAbort("PumpMsgs: PMP_Recv failed!\n");    
 
     MPI_Get_count(&sts, MPI_BYTE, &nbytes);
     msg = (char *) CmiAlloc(nbytes);
     memcpy(msg, buf, nbytes);
+    END_TRACE_RECVCOMM(msg);
 
-#if CMK_SMP_TRACE_COMMTHREAD
-    traceBeginCommOp(msg);
-    traceChangeLastTimestamp(CpvAccess(projTraceStart));
-    traceEndCommOp(msg);
-#if CMI_MPI_TRACE_MOREDETAILED
+#if CMK_SMP_TRACE_COMMTHREAD && 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);
@@ -745,7 +976,7 @@ static int SendMsgBuf() {
             if (++sentCnt == SEND_CAP) break;
 #elif CMI_DYNAMIC_EXERT_CAP
             if (++sentCnt >= dynamicSendCap) break;
-            if (MsgQueueLen > CMI_DYNAMIC_OUTGOING_THRESHOLD)
+            if (CpvAccess(MsgQueueLen) > CMI_DYNAMIC_OUTGOING_THRESHOLD)
                 dynamicSendCap = CMI_DYNAMIC_SEND_CAPSIZE;
 #endif
 
@@ -787,13 +1018,13 @@ static int RecvQueueEmpty() {
 #define REPORT_COMM_METRICS 0
 #if REPORT_COMM_METRICS
 static double pumptime = 0.0;
-                         static double releasetime = 0.0;
-                                                     static double sendtime = 0.0;
+static double releasetime = 0.0;
+static double sendtime = 0.0;
 #endif
 
 #endif //end of CMK_SMP
 
-static void AdvanceCommunicationForMPI() {
+void LrtsAdvanceCommunication(int whenidle) {
 #if REPORT_COMM_METRICS
     double t1, t2, t3, t4;
     t1 = CmiWallTimer();
@@ -838,11 +1069,11 @@ static void AdvanceCommunicationForMPI() {
 }
 /* ######End of functions related with communication progress ###### */
 
-static void MachinePostNonLocalForMPI() {
+void LrtsPostNonLocal() {
 #if !CMK_SMP
     if (no_outstanding_sends) {
         while (CpvAccess(MsgQueueLen)>0) {
-            AdvanceCommunicationForMPI();
+            LrtsAdvanceCommunication(0);
         }
     }
 
@@ -859,9 +1090,12 @@ static void MachinePostNonLocalForMPI() {
     }
 #endif
 #else
-  if (_thread_provided == MPI_THREAD_MULTIPLE) {
-        CmiReleaseSentMessages();
-        SendMsgBuf();
+  if (Cmi_smp_mode_setting == COMM_THREAD_ONLY_RECV) {
+        CmiReleaseSentMessages();       
+        /* ??? SendMsgBuf is a not a thread-safe function. If it is put
+         * here and this function will be called in CmiNotifyStillIdle,
+         * then a data-race problem occurs */
+        /*SendMsgBuf();*/
   }
 #endif
 }
@@ -891,46 +1125,63 @@ void CmiMachineProgressImpl() {
 #endif
 
 /* ######Beginning of functions related with exiting programs###### */
-void DrainResourcesForMPI() {
+void LrtsDrainResources() {
 #if !CMK_SMP
     while (!CmiAllAsyncMsgsSent()) {
         PumpMsgs();
         CmiReleaseSentMessages();
     }
 #else
-    while (!MsgQueueEmpty() || !CmiAllAsyncMsgsSent()) {
-        CmiReleaseSentMessages();
-        SendMsgBuf();
-        PumpMsgs();
+    if(Cmi_smp_mode_setting == COMM_THREAD_SEND_RECV){
+        while (!MsgQueueEmpty() || !CmiAllAsyncMsgsSent()) {
+           CmiReleaseSentMessages();
+            SendMsgBuf();
+            PumpMsgs();
+        }
+    }else if(Cmi_smp_mode_setting == COMM_THREAD_ONLY_RECV) {
+        while(!CmiAllAsyncMsgsSent()) {
+            CmiReleaseSentMessages();
+        }
     }
 #endif
-#if CMK_MEM_CHECKPOINT
-    if (CmiMyPe() == 0) mpi_end_spare();
+#if CMK_MEM_CHECKPOINT || CMK_MESSAGE_LOGGING
+    if (CmiMyPe() == 0&&CmiMyPartition()==0){ 
+      mpi_end_spare();
+    }
 #endif
     MACHSTATE(2, "Machine exit barrier begin {");
     START_EVENT();
-    if (MPI_SUCCESS != MPI_Barrier(MPI_COMM_WORLD))
-        CmiAbort("DrainResourcesForMPI: MPI_Barrier failed!\n");
+    if (MPI_SUCCESS != MPI_Barrier(charmComm))
+        CmiAbort("LrtsDrainResources: MPI_Barrier failed!\n");
     END_EVENT(10);
     MACHSTATE(2, "} Machine exit barrier end");
 }
 
 void LrtsExit() {
+    int i;
 #if (CMK_DEBUG_MODE || CMK_WEB_MODE || NODE_0_IS_CONVHOST)
     int doPrint = 0;
-#if CMK_SMP
     if (CmiMyNode()==0) doPrint = 1;
-#else
-    if (CmiMyPe()==0) doPrint = 1;
-#endif
 
-    if (doPrint) {
+    if (doPrint /*|| CmiMyNode()%11==0 */) {
 #if MPI_POST_RECV
-        CmiPrintf("%llu posted receives,  %llu unposted receives\n", CpvAccess(Cmi_posted_recv_total), CpvAccess(Cmi_unposted_recv_total));
+        CmiPrintf("node[%d]: %llu posted receives,  %llu unposted receives\n", CmiMyNode(), CpvAccess(Cmi_posted_recv_total), CpvAccess(Cmi_unposted_recv_total));
 #endif
     }
 #endif
 
+#if MPI_POST_RECV
+    {
+        MPIPostRecvList *ptr = CpvAccess(postRecvListHdr);
+        if (ptr) {
+            do {
+                for (i=0; i<ptr->bufCnt; i++) MPI_Cancel(ptr->postedRecvReqs+i);
+                ptr = ptr->next;
+            } while (ptr!=CpvAccess(postRecvListHdr));
+        }
+    }
+#endif
+
 #if REPORT_COMM_METRICS
 #if CMK_SMP
     CmiPrintf("Report comm metrics for node %d[%d-%d]: pumptime: %f, releasetime: %f, senttime: %f\n",
@@ -942,11 +1193,13 @@ void LrtsExit() {
 #endif
 #endif
 
+   if(!CharmLibInterOperate) {
 #if ! CMK_AUTOBUILD
-    signal(SIGINT, signal_int);
-    MPI_Finalize();
+      signal(SIGINT, signal_int);
+      MPI_Finalize();
 #endif
-    exit(0);
+      exit(0);
+    }
 }
 
 static int machine_exit_idx;
@@ -956,9 +1209,9 @@ static void machine_exit(char *m) {
     fflush(stdout);
     CmiNodeBarrier();
     if (CmiMyRank() == 0) {
-        MPI_Barrier(MPI_COMM_WORLD);
+        MPI_Barrier(charmComm);
         /*printf("==> %d: passed barrier\n",CmiMyPe());*/
-        MPI_Abort(MPI_COMM_WORLD, 1);
+        MPI_Abort(charmComm, 1);
     } else {
         while (1) CmiYield();
     }
@@ -967,7 +1220,7 @@ static void machine_exit(char *m) {
 static void KillOnAllSigs(int sigNo) {
     static int already_in_signal_handler = 0;
     char *m;
-    if (already_in_signal_handler) return;   /* MPI_Abort(MPI_COMM_WORLD,1); */
+    if (already_in_signal_handler) return;   /* MPI_Abort(charmComm,1); */
     already_in_signal_handler = 1;
 #if CMK_CCS_AVAILABLE
     if (CpvAccess(cmiArgDebugFlag)) {
@@ -995,7 +1248,7 @@ static void registerMPITraceEvents() {
     traceRegisterUserEvent("MPI_Recv", 30);
     traceRegisterUserEvent("MPI_Isend", 40);
     traceRegisterUserEvent("MPI_Irecv", 50);
-    traceRegisterUserEvent("MPI_Test", 60);
+    traceRegisterUserEvent("MPI_Test[any]", 60);
     traceRegisterUserEvent("MPI_Iprobe", 70);
 #endif
 }
@@ -1014,7 +1267,7 @@ static char *thread_level_tostring(int thread_level) {
     case MPI_THREAD_SERIALIZED:
         return "MPI_THREAD_SERIALIZED";
     case MPI_THREAD_MULTIPLE :
-        return "MPI_THREAD_MULTIPLE ";
+        return "MPI_THREAD_MULTIPLE";
     default: {
         char *str = (char*)malloc(5);
         sprintf(str,"%d", thread_level);
@@ -1033,7 +1286,7 @@ static char *thread_level_tostring(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) {
+void LrtsInit(int *argc, char ***argv, int *numNodes, int *myNodeID) {
     int n,i;
     int ver, subver;
     int provided;
@@ -1051,30 +1304,63 @@ static void MachineInitForMPI(int *argc, char ***argv, int *numNodes, int *myNod
 #endif
 #endif
 
+    if (CmiGetArgFlag(largv, "+comm_thread_only_recv")) {
+#if CMK_SMP
+      Cmi_smp_mode_setting = COMM_THREAD_ONLY_RECV;
+#else
+      CmiAbort("+comm_thread_only_recv option can only be used with SMP version of Charm++");
+#endif
+    }
+
+    *argc = CmiGetArgc(largv);     /* update it in case it is out of sync */
+
+    if(!CharmLibInterOperate) {
 #if CMK_MPI_INIT_THREAD
 #if CMK_SMP
-    thread_level = MPI_THREAD_MULTIPLE;
+    if (Cmi_smp_mode_setting == COMM_THREAD_SEND_RECV)
+        thread_level = MPI_THREAD_FUNNELED;
+      else
+        thread_level = MPI_THREAD_MULTIPLE;
 #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;
+      MPI_Init(argc, argv);
+      thread_level = 0;
+      _thread_provided = -1;
 #endif
+    }
+
     largc = *argc;
     largv = *argv;
-    MPI_Comm_size(MPI_COMM_WORLD, numNodes);
-    MPI_Comm_rank(MPI_COMM_WORLD, myNodeID);
+    if(!CharmLibInterOperate) {
+                       MPI_Comm_dup(MPI_COMM_WORLD,&charmComm);
+      MPI_Comm_size(charmComm, numNodes);
+                       MPI_Comm_rank(charmComm, myNodeID);
+    }
+
+    MPI_Bcast(&_Cmi_mynodesize, 1, MPI_INT, 0, MPI_COMM_WORLD);
 
     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));
+    if(!CharmLibInterOperate) {
+      if (myNID == 0) {
+        printf("Charm++> Running on MPI version: %d.%d\n", ver, subver);
+        printf("Charm++> level of thread support used: %s (desired: %s)\n", thread_level_tostring(_thread_provided), thread_level_tostring(thread_level));
+      }
+    }
+
+#if CMK_SMP
+    if (Cmi_smp_mode_setting == COMM_THREAD_ONLY_RECV && _thread_provided != MPI_THREAD_MULTIPLE) {
+        Cmi_smp_mode_setting = COMM_THREAD_SEND_RECV; 
+        if (myNID == 0) {
+          printf("Charm++> +comm_thread_only_recv disabled\n");
+        }
     }
+#endif
 
     {
         int debug = CmiGetArgFlag(largv,"++debug");
@@ -1091,8 +1377,8 @@ static void MachineInitForMPI(int *argc, char ***argv, int *numNodes, int *myNod
         }
     }
 
-
-#if CMK_MEM_CHECKPOINT
+    setbuf(stdout, NULL);
+#if CMK_MEM_CHECKPOINT || CMK_MESSAGE_LOGGING
     if (CmiGetArgInt(largv,"+wp",&num_workpes)) {
        CmiAssert(num_workpes <= *numNodes);
        total_pes = *numNodes;
@@ -1107,21 +1393,28 @@ static void MachineInitForMPI(int *argc, char ***argv, int *numNodes, int *myNod
     nextrank = num_workpes;
 
     if (*myNodeID >= num_workpes) {    /* is spare processor */
-      MPI_Status sts;
+      //if isomalloc_sync call mpi_barrier
+      if(CmiGetArgFlag(largv,"+isomalloc_sync")){
+          MPI_Barrier(charmComm);
+          MPI_Barrier(charmComm);
+          MPI_Barrier(charmComm);
+          MPI_Barrier(charmComm);
+      }
+         MPI_Status sts;
       int vals[2];
-      MPI_Recv(vals,2,MPI_INT,MPI_ANY_SOURCE,FAIL_TAG, MPI_COMM_WORLD,&sts);
+      MPI_Recv(vals,2,MPI_INT,MPI_ANY_SOURCE,FAIL_TAG, charmComm,&sts);
       int newpe = vals[0];
       CpvAccess(_curRestartPhase) = vals[1];
-      CmiPrintf("Charm++> Spare MPI rank %d is activated for PE %d.\n", *myNodeID, newpe);
+      CmiPrintf("Charm++> Spare MPI rank %d is activated for global PE %d phase %d.\n", *myNodeID, newpe,CpvAccess(_curRestartPhase));
 
       if (newpe == -1) {
-          MPI_Barrier(MPI_COMM_WORLD);
+          MPI_Barrier(charmComm);
           MPI_Finalize();
           exit(0);
       }
 
         /* update petorank */
-      MPI_Recv(petorank, num_workpes, MPI_INT,MPI_ANY_SOURCE,FAIL_TAG,MPI_COMM_WORLD, &sts);
+      MPI_Recv(petorank, num_workpes, MPI_INT,MPI_ANY_SOURCE,FAIL_TAG,charmComm, &sts);
       nextrank = *myNodeID + 1;
       *myNodeID = newpe;
       myNID = newpe;
@@ -1138,6 +1431,10 @@ static void MachineInitForMPI(int *argc, char ***argv, int *numNodes, int *myNod
                 i++;
       }
       restart_argv[i] = "+restartaftercrash";
+         if(CmiGetArgFlagDesc(largv,"+isomalloc_sync","synchronize isomalloc region globaly")){
+               i++;
+       restart_argv[i] = "+restartisomalloc";
+         }
       phase_str = (char*)malloc(10);
       sprintf(phase_str,"%d", CpvAccess(_curRestartPhase));
       restart_argv[i+1]=phase_str;
@@ -1186,16 +1483,40 @@ static void MachineInitForMPI(int *argc, char ***argv, int *numNodes, int *myNod
     CmiGetArgInt(largv, "+postRecvCnt", &MPI_POST_RECV_COUNT);
     CmiGetArgInt(largv, "+postRecvLowerSize", &MPI_POST_RECV_LOWERSIZE);
     CmiGetArgInt(largv, "+postRecvUpperSize", &MPI_POST_RECV_UPPERSIZE);
+    CmiGetArgInt(largv, "+postRecvThreshold", &MPI_POST_RECV_MSG_CNT_THRESHOLD);
+    CmiGetArgInt(largv, "+postRecvBucketSize", &MPI_POST_RECV_INC);
+    CmiGetArgInt(largv, "+postRecvMsgInc", &MPI_POST_RECV_MSG_INC);
+    CmiGetArgInt(largv, "+postRecvCheckFreq", &MPI_POST_RECV_FREQ);
     if (MPI_POST_RECV_COUNT<=0) MPI_POST_RECV_COUNT=1;
     if (MPI_POST_RECV_LOWERSIZE>MPI_POST_RECV_UPPERSIZE) MPI_POST_RECV_UPPERSIZE = MPI_POST_RECV_LOWERSIZE;
     MPI_POST_RECV_SIZE = MPI_POST_RECV_UPPERSIZE;
     if (myNID==0) {
-        printf("Charm++: using post-recv scheme with %d pre-posted recvs ranging from %d to %d (bytes)\n",
-               MPI_POST_RECV_COUNT, MPI_POST_RECV_LOWERSIZE, MPI_POST_RECV_UPPERSIZE);
+        printf("Charm++: using post-recv scheme with %d pre-posted recvs ranging from %d to %d (bytes) with msg count threshold %d and msg histogram bucket size %d, #buf increment every %d msgs. The buffers are checked every %d msgs\n",
+               MPI_POST_RECV_COUNT, MPI_POST_RECV_LOWERSIZE, MPI_POST_RECV_UPPERSIZE,
+               MPI_POST_RECV_MSG_CNT_THRESHOLD, MPI_POST_RECV_INC, MPI_POST_RECV_MSG_INC, MPI_POST_RECV_FREQ);
     }
 #endif
+       
+#if USE_MPI_CTRLMSG_SCHEME
+       CmiGetArgInt(largv, "+ctrlMsgCnt", &MPI_CTRL_MSG_CNT);
+       if(myNID == 0){
+               printf("Charm++: using the alternative ctrl msg scheme with %d pre-posted ctrl msgs\n", MPI_CTRL_MSG_CNT);
+       }
+#endif
 
-#if CMI_DYNAMIC_EXERT_CAP
+#if CMI_EXERT_SEND_CAP
+    CmiGetArgInt(largv, "+dynCapSend", &SEND_CAP);
+    if (myNID==0) {
+        printf("Charm++: using static send cap %d\n", SEND_CAP);
+    }
+#endif
+#if CMI_EXERT_RECV_CAP
+    CmiGetArgInt(largv, "+dynCapRecv", &RECV_CAP);
+    if (myNID==0) {
+        printf("Charm++: using static recv cap %d\n", RECV_CAP);
+    }
+#endif
+#if CMI_DYNAMIC_EXERT_CAP 
     CmiGetArgInt(largv, "+dynCapThreshold", &CMI_DYNAMIC_OUTGOING_THRESHOLD);
     CmiGetArgInt(largv, "+dynCapSend", &CMI_DYNAMIC_SEND_CAPSIZE);
     CmiGetArgInt(largv, "+dynCapRecv", &CMI_DYNAMIC_RECV_CAPSIZE);
@@ -1205,6 +1526,13 @@ static void MachineInitForMPI(int *argc, char ***argv, int *numNodes, int *myNod
     }
 #endif
 
+#if USE_ASYNC_RECV_FUNC
+    CmiGetArgInt(largv, "+irecvMsgThreshold", &IRECV_MSG_THRESHOLD);
+    if(myNID==0) {
+        printf("Charm++: for msg size larger than %d, MPI_Irecv is going to be used.\n", IRECV_MSG_THRESHOLD);
+    }
+#endif
+
     /* checksum flag */
     if (CmiGetArgFlag(largv,"+checksum")) {
 #if CMK_ERROR_CHECKING
@@ -1230,9 +1558,15 @@ static void MachineInitForMPI(int *argc, char ***argv, int *numNodes, int *myNod
 #endif
 }
 
-static void MachinePreCommonInitForMPI(int everReturn) {
+void LrtsPreCommonInit(int everReturn) {
 
-#if MPI_POST_RECV
+#if USE_MPI_CTRLMSG_SCHEME
+       #if CMK_SMP
+               if(CmiMyRank() == CmiMyNodeSize()) createCtrlMsgIrecvBufs();
+       #else
+               createCtrlMsgIrecvBufs();
+       #endif
+#elif MPI_POST_RECV
     int doInit = 1;
     int i;
 
@@ -1250,35 +1584,89 @@ static void MachinePreCommonInitForMPI(int everReturn) {
     CpvInitialize(unsigned long long, Cmi_posted_recv_total);
     CpvInitialize(unsigned long long, Cmi_unposted_recv_total);
     CpvInitialize(MPI_Request*, CmiPostedRecvRequests);
-    CpvInitialize(char*,CmiPostedRecvBuffers);
+    CpvInitialize(char **, CmiPostedRecvBuffers);
+
+    CpvAccess(CmiPostedRecvRequests) = NULL;
+    CpvAccess(CmiPostedRecvBuffers) = NULL;
+
+    CpvInitialize(MPIPostRecvList *, postRecvListHdr);
+    CpvInitialize(MPIPostRecvList *, curPostRecvPtr);
+    CpvInitialize(int, msgRecvCnt);
+
+    CpvAccess(postRecvListHdr) = NULL;
+    CpvAccess(curPostRecvPtr) = NULL;
+    CpvAccess(msgRecvCnt) = 0;
+
+#if MPI_DYNAMIC_POST_RECV
+    CpvInitialize(int *, MSG_HISTOGRAM_ARRAY);
+#endif
 
     if (doInit) {
+#if MPI_DYNAMIC_POST_RECV
+        MSG_HISTOGRAM_BINSIZE = MPI_POST_RECV_INC;
+        /* including two more buckets that are out of the range [LOWERSIZE, UPPERSIZE] */
+        MAX_HISTOGRAM_BUCKETS = (MPI_POST_RECV_UPPERSIZE - MPI_POST_RECV_LOWERSIZE)/MSG_HISTOGRAM_BINSIZE+2;
+        CpvAccess(MSG_HISTOGRAM_ARRAY) = (int *)malloc(sizeof(int)*MAX_HISTOGRAM_BUCKETS);
+        memset(CpvAccess(MSG_HISTOGRAM_ARRAY), 0, sizeof(int)*MAX_HISTOGRAM_BUCKETS);
+#else
         /* 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);
+        CpvAccess(postRecvListHdr) = (MPIPostRecvList *)malloc(sizeof(MPIPostRecvList));
 
+        /* An array of request handles for posted recvs */
+        CpvAccess(postRecvListHdr)->msgSizeIdx = -1;
+        CpvAccess(postRecvListHdr)->bufCnt = MPI_POST_RECV_COUNT;
+        CpvAccess(postRecvListHdr)->postedRecvReqs = (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);
+        CpvAccess(postRecvListHdr)->postedRecvBufs = (char**)malloc(MPI_POST_RECV_COUNT*sizeof(char *));
+        CpvAccess(postRecvListHdr)->next = CpvAccess(postRecvListHdr);
+        CpvAccess(curPostRecvPtr) = CpvAccess(postRecvListHdr);
 
         /* Post Recvs */
         for (i=0; i<MPI_POST_RECV_COUNT; 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])  ))
+            char *tmpbuf = (char *)CmiAlloc(MPI_POST_RECV_SIZE); /* Note: could be aligned allocation?? */
+            CpvAccess(postRecvListHdr)->postedRecvBufs[i] = tmpbuf;
+            if (MPI_SUCCESS != MPI_Irecv(tmpbuf,
+                                         MPI_POST_RECV_SIZE,
+                                         MPI_BYTE,
+                                         MPI_ANY_SOURCE,
+                                         POST_RECV_TAG,
+                                         charmComm,
+                                         CpvAccess(postRecvListHdr)->postedRecvReqs+i  ))
                 CmiAbort("MPI_Irecv failed\n");
         }
+#endif
     }
+#endif /* end of MPI_POST_RECV  and USE_MPI_CTRLMSG_SCHEME */
+       
+#if CAPTURE_MSG_HISTOGRAM && !MPI_DYNAMIC_POST_RECV
+    CpvInitialize(int *, MSG_HISTOGRAM_ARRAY);
+    CpvAccess(MSG_HISTOGRAM_ARRAY) = (int *)malloc(sizeof(int)*MAX_HISTOGRAM_BUCKETS);
+    memset(CpvAccess(MSG_HISTOGRAM_ARRAY), 0, sizeof(int)*MAX_HISTOGRAM_BUCKETS);
 #endif
 
+#if USE_ASYNC_RECV_FUNC || USE_MPI_CTRLMSG_SCHEME
+#if CMK_SMP
+    /* allocate the guardian entry only on comm thread considering NUMA */
+    if(CmiMyRank() == CmiMyNodeSize()) {
+        waitIrecvListHead = waitIrecvListTail = irecvListEntryAllocate();
+        waitIrecvListHead->next = NULL;
+    }
+#else    
+    waitIrecvListHead = waitIrecvListTail = irecvListEntryAllocate();
+    waitIrecvListHead->next = NULL;
+#endif
+#endif
+#ifdef CMK_MEM_CHECKPOINT || (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)
+    CpvInitialize(crashedRankList *, crashedRankHdr);
+    CpvInitialize(crashedRankList *, crashedRankPtr);
+    CpvAccess(crashedRankHdr) = NULL;
+    CpvAccess(crashedRankPtr) = NULL;
+#endif
 }
 
-static void MachinePostCommonInitForMPI(int everReturn) {
+void LrtsPostCommonInit(int everReturn) {
 
     CmiIdleState *s=CmiNotifyGetState();
 
@@ -1302,7 +1690,7 @@ static void MachinePostCommonInitForMPI(int everReturn) {
 #if CMK_SMP
     CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE,(CcdVoidFn)CmiNotifyBeginIdle,(void *)s);
     CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,(CcdVoidFn)CmiNotifyStillIdle,(void *)s);
-    if (_thread_provided == MPI_THREAD_MULTIPLE)
+    if (Cmi_smp_mode_setting == COMM_THREAD_ONLY_RECV)
       CcdCallOnConditionKeep(CcdPERIODIC,(CcdVoidFn)LrtsPostNonLocal,NULL);
 #else
     CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,(CcdVoidFn)CmiNotifyIdleForMPI,NULL);
@@ -1324,7 +1712,7 @@ static void MachinePostCommonInitForMPI(int everReturn) {
  *
  ************************************************************************/
 
-void CmiAbort(const char *message) {
+void LrtsAbort(const char *message) {
     char *m;
     /* if CharmDebug is attached simply try to send a message to it */
 #if CMK_CCS_AVAILABLE
@@ -1342,7 +1730,7 @@ void CmiAbort(const char *message) {
     CmiSyncBroadcastAndFree(CmiMsgHeaderSizeBytes, m);
     machine_exit(m);
     /* Program never reaches here */
-    MPI_Abort(MPI_COMM_WORLD, 1);
+    MPI_Abort(charmComm, 1);
 }
 
 /**************************  TIMER FUNCTIONS **************************/
@@ -1359,7 +1747,7 @@ int CmiTimerIsSynchronized() {
     void *v;
 
     /*  check if it using synchronized timer */
-    if (MPI_SUCCESS != MPI_Attr_get(MPI_COMM_WORLD, MPI_WTIME_IS_GLOBAL, &v, &flag))
+    if (MPI_SUCCESS != MPI_Attr_get(charmComm, MPI_WTIME_IS_GLOBAL, &v, &flag))
         printf("MPI_WTIME_IS_GLOBAL not valid!\n");
     if (flag) {
         _is_global = *(int*)v;
@@ -1386,7 +1774,7 @@ void CmiTimerInit(char **argv) {
     if (_absoluteTime && CmiMyPe() == 0)
         printf("Charm++> absolute MPI timer is used\n");
 
-#if ! CMK_MEM_CHECKPOINT
+#if ! CMK_MEM_CHECKPOINT && ! CMK_MESSAGE_LOGGING
     _is_global = CmiTimerIsSynchronized();
 #else
     _is_global = 0;
@@ -1402,11 +1790,11 @@ void CmiTimerInit(char **argv) {
 #endif
 
             MPI_Allreduce(&starttimer, &minTimer, 1, MPI_DOUBLE, MPI_MIN,
-                          MPI_COMM_WORLD );
+                          charmComm );
             starttimer = minTimer;
         }
     } else { /* we don't have a synchronous timer, set our own start time */
-#if ! CMK_MEM_CHECKPOINT
+#if ! CMK_MEM_CHECKPOINT && ! CMK_MESSAGE_LOGGING
         CmiBarrier();
         CmiBarrier();
         CmiBarrier();
@@ -1504,8 +1892,7 @@ int CmiBarrier() {
          *  and END_EVENT are disabled here. -Chao Mei
          */
         /*START_EVENT();*/
-
-        if (MPI_SUCCESS != MPI_Barrier(MPI_COMM_WORLD))
+        if (MPI_SUCCESS != MPI_Barrier(charmComm))
             CmiAbort("Timernit: MPI_Barrier failed!\n");
 
         /*END_EVENT(10);*/
@@ -1528,8 +1915,7 @@ int CmiBarrierZero() {
         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))
+                if (MPI_SUCCESS != MPI_Recv(msg,1,MPI_BYTE,MPI_ANY_SOURCE,BARRIER_ZERO_TAG, charmComm,&sts))
                     CmiPrintf("MPI_Recv failed!\n");
 
                 END_EVENT(30);
@@ -1537,7 +1923,7 @@ int CmiBarrierZero() {
         } else {
             START_EVENT();
 
-            if (MPI_SUCCESS != MPI_Send((void *)msg,1,MPI_BYTE,0,BARRIER_ZERO_TAG,MPI_COMM_WORLD))
+            if (MPI_SUCCESS != MPI_Send((void *)msg,1,MPI_BYTE,0,BARRIER_ZERO_TAG,charmComm))
                 printf("MPI_Send failed!\n");
 
             END_EVENT(20);
@@ -1548,15 +1934,15 @@ int CmiBarrierZero() {
 }
 
 
-#if CMK_MEM_CHECKPOINT
+#if CMK_MEM_CHECKPOINT || CMK_MESSAGE_LOGGING
 
 void mpi_restart_crashed(int pe, int rank)
 {
     int vals[2];
-    vals[0] = pe;
+    vals[0] = CmiGetPeGlobal(pe,CmiMyPartition());
     vals[1] = CpvAccess(_curRestartPhase)+1;
-    MPI_Send((void *)vals,2,MPI_INT,rank,FAIL_TAG,MPI_COMM_WORLD);
-    MPI_Send(petorank, num_workpes, MPI_INT,rank,FAIL_TAG,MPI_COMM_WORLD);
+    MPI_Send((void *)vals,2,MPI_INT,rank,FAIL_TAG,charmComm);
+    MPI_Send(petorank, num_workpes, MPI_INT,rank,FAIL_TAG,charmComm);
 }
 
 /* notify spare processors to exit */
@@ -1565,35 +1951,365 @@ void mpi_end_spare()
     int i;
     for (i=nextrank; i<total_pes; i++) {
         int vals[2] = {-1,-1};
-        MPI_Send((void *)vals,2,MPI_INT,i,FAIL_TAG,MPI_COMM_WORLD);
+        CmiPrintf("end spare send to rank %d\n",i);
+        MPI_Send((void *)vals,2,MPI_INT,i,FAIL_TAG,charmComm);
     }
 }
 
-int find_spare_mpirank(int pe)
+int find_spare_mpirank(int pe,int partition)
 {
+#ifdef CMK_MEM_CHECKPOINT || (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)
     if (nextrank == total_pes) {
       CmiAbort("Charm++> No spare processor available.");
     }
-    petorank[pe] = nextrank;
+    int newpe = CmiGetPeGlobal(pe,partition);
+    crashedRankList * crashedRank= (crashedRankList *)(malloc(sizeof(crashedRankList)));
+    crashedRank->rank = newpe;
+    crashedRank->next=NULL;
+    if(CpvAccess(crashedRankHdr)==NULL){
+      CpvAccess(crashedRankHdr) = crashedRank;
+      CpvAccess(crashedRankPtr) = CpvAccess(crashedRankHdr);
+    }else{
+      CpvAccess(crashedRankPtr)->next = crashedRank;
+      CpvAccess(crashedRankPtr) = crashedRank;
+    }
+    petorank[newpe] = nextrank;
     nextrank++;
+    //CmiPrintf("[%d][%d]spare rank %d for pe %d\n",CmiMyPartition(),CmiMyPe(),nextrank-1,newpe);
+    //fflush(stdout);
     return nextrank-1;
+#endif
 }
 
+
+int isRankDie(int rank){
+#ifdef CMK_MEM_CHECKPOINT || (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)
+  crashedRankList * cur = CpvAccess(crashedRankHdr);
+  while(cur!=NULL){
+    if(rank == cur->rank){
+      return 1;
+    }
+    cur = cur->next;
+  }
+  return 0;
+#endif
+}
+
+
 void CkDieNow()
 {
+#ifdef CMK_MEM_CHECKPOINT || (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)
     CmiPrintf("[%d] die now.\n", CmiMyPe());
-
+    fflush(stdout);
       /* release old messages */
     while (!CmiAllAsyncMsgsSent()) {
         PumpMsgs();
         CmiReleaseSentMessages();
     }
-    MPI_Barrier(MPI_COMM_WORLD);
+    CmiPrintf("[%d] die now before barrier\n", CmiMyPe());
+    MPI_Barrier(charmComm);
     MPI_Finalize();
     exit(0);
+#endif
 }
 
 #endif
 
+/*======Beginning of Msg Histogram or Dynamic Post-Recv Related Funcs=====*/
+#if CAPTURE_MSG_HISTOGRAM || MPI_DYNAMIC_POST_RECV
+/* Functions related with capturing msg histogram */
+
+#if MPI_DYNAMIC_POST_RECV
+/* Consume all messages in the request buffers */
+static void consumeAllMsgs()
+{
+    MPIPostRecvList *ptr = CpvAccess(curPostRecvPtr);
+    if (ptr) {
+        do {
+            int i;
+            for (i=0; i<ptr->bufCnt; i++) {
+                int done = 0;
+                MPI_Status sts;
+
+                /* Indicating this entry has been tested before */
+                if (ptr->postedRecvBufs[i] == NULL) continue;
+
+                START_TRACE_RECVCOMM(NULL);
+                if (MPI_SUCCESS != MPI_Test(ptr->postedRecvReqs+i, &done, &sts))
+                    CmiAbort("consumeAllMsgs failed in MPI_Test!\n");
+                if (done) {
+                    int nbytes;
+                    char *msg;                    
+                    
+                    if (MPI_SUCCESS != MPI_Get_count(&sts, MPI_BYTE, &nbytes))
+                        CmiAbort("consumeAllMsgs failed in MPI_Get_count!\n");
+                    /* ready to handle this msg */
+                    msg = (ptr->postedRecvBufs)[i];
+                    (ptr->postedRecvBufs)[i] = NULL;
+                    
+                    END_TRACE_RECVCOMM(msg);
+                    handleOneRecvedMsg(nbytes, msg);
+                } else {
+                    if (MPI_SUCCESS != MPI_Cancel(ptr->postedRecvReqs+i))
+                        CmiAbort("consumeAllMsgs failed in MPI_Cancel!\n");
+                }
+            }
+            ptr = ptr->next;
+        } while (ptr != CpvAccess(curPostRecvPtr));
+    }
+}
+
+static void recordMsgHistogramInfo(int size)
+{
+    int idx = 0;
+    size -= MPI_POST_RECV_LOWERSIZE;
+    if (size > 0)
+        idx = (size/MSG_HISTOGRAM_BINSIZE + 1);
+
+    if (idx >= MAX_HISTOGRAM_BUCKETS) idx = MAX_HISTOGRAM_BUCKETS-1;
+    CpvAccess(MSG_HISTOGRAM_ARRAY)[idx]++;
+}
+
+#define POST_RECV_USE_STATIC_PARAM 0
+#define POST_RECV_REPORT_STS 0
+
+#if POST_RECV_REPORT_STS
+static int buildDynCallCnt = 0;
+#endif
+
+static void buildDynamicRecvBuffers()
+{
+    int i;
+
+    int local_MSG_CNT_THRESHOLD;
+    int local_MSG_INC;
+
+#if POST_RECV_REPORT_STS
+    buildDynCallCnt++;
+#endif
+
+    /* For debugging usage */
+    reportMsgHistogramInfo();
+
+    CpvAccess(msgRecvCnt) = 0;
+    /* consume all outstanding msgs */
+    consumeAllMsgs();
+
+#if POST_RECV_USE_STATIC_PARAM
+    local_MSG_CNT_THRESHOLD = MPI_POST_RECV_MSG_CNT_THRESHOLD;
+    local_MSG_INC = MPI_POST_RECV_MSG_INC;
+#else
+    {
+        int total = 0;
+        int count = 0;
+        for (i=1; i<MAX_HISTOGRAM_BUCKETS-1; i++) {
+            int tmp = CpvAccess(MSG_HISTOGRAM_ARRAY)[i];
+            /* avg is temporarily used for counting how many buckets are non-zero */
+            if (tmp > 0)  {
+                total += tmp;
+                count++;
+            }
+        }
+        if (count == 1) local_MSG_CNT_THRESHOLD = 1; /* Just filter out those zero-count msgs */
+        else local_MSG_CNT_THRESHOLD = total / count /3; /* Catch >50% msgs NEED-BETTER-SCHEME HERE!!*/
+        local_MSG_INC = total/count; /* Not having a good heuristic right now */
+#if POST_RECV_REPORT_STS
+        printf("sel_histo[%d]: critia_threshold=%d, critia_msginc=%d\n", CmiMyPe(), local_MSG_CNT_THRESHOLD, local_MSG_INC);
+#endif
+    }
+#endif
+
+    /* First continue to find the first msg range that requires post recv */
+    /* Ignore the fist and the last one because they are not tracked */
+    MPIPostRecvList *newHdr = NULL;
+    MPIPostRecvList *newListPtr = newHdr;
+    MPIPostRecvList *ptr = CpvAccess(postRecvListHdr);
+    for (i=1; i<MAX_HISTOGRAM_BUCKETS-1; i++) {
+        int count = CpvAccess(MSG_HISTOGRAM_ARRAY)[i];
+        if (count >= local_MSG_CNT_THRESHOLD) {
+
+#if POST_RECV_REPORT_STS
+            /* Report histogram results */
+            int low = (i-1)*MSG_HISTOGRAM_BINSIZE + MPI_POST_RECV_LOWERSIZE;
+            int high = low + MSG_HISTOGRAM_BINSIZE;
+            int reportCnt;
+            if (count == local_MSG_CNT_THRESHOLD) reportCnt = 1;
+            else reportCnt = (count - local_MSG_CNT_THRESHOLD)/local_MSG_INC + 1;
+            printf("sel_histo[%d]-%d: msg size [%.2f, %.2f) with count=%d (%d)\n", CmiMyPe(), buildDynCallCnt, low/1000.0, high/1000.0, count, reportCnt);
+#endif
+            /* find if this msg idx exists, the "i" is the msgSizeIdx, in the current list */
+            int notFound = 1;
+            MPIPostRecvList *newEntry = NULL;
+            while (ptr) {
+                if (ptr->msgSizeIdx < i) {
+                    /* free the buffer for this range of msg size */
+                    MPIPostRecvList *nextptr = ptr->next;
+
+                    free(ptr->postedRecvReqs);
+                    int j;
+                    for (j=0; j<ptr->bufCnt; j++) {
+                        if ((ptr->postedRecvBufs)[j]) CmiFree((ptr->postedRecvBufs)[j]);
+                    }
+                    free(ptr->postedRecvBufs);
+                    ptr = nextptr;
+                } else if (ptr->msgSizeIdx == i) {
+                    int newBufCnt, j;
+                    int bufSize = i*MPI_POST_RECV_INC + MPI_POST_RECV_LOWERSIZE - 1;
+                    newEntry = ptr;
+                    /* Do some adjustment according to the current statistics */
+                    if (count == local_MSG_CNT_THRESHOLD) newBufCnt = 1;
+                    else newBufCnt = (count - local_MSG_CNT_THRESHOLD)/local_MSG_INC + 1;
+                    if (newBufCnt != ptr->bufCnt) {
+                        /* free old buffers, and allocate new buffers */
+                        free(ptr->postedRecvReqs);
+                        ptr->postedRecvReqs = (MPI_Request *)malloc(newBufCnt * sizeof(MPI_Request));
+                        for (j=0; j<ptr->bufCnt; j++) {
+                            if ((ptr->postedRecvBufs)[j]) CmiFree((ptr->postedRecvBufs)[j]);
+                        }
+                        free(ptr->postedRecvBufs);
+                        ptr->postedRecvBufs = (char **)malloc(newBufCnt * sizeof(char *));
+                    }
+
+                    /* re-post those buffers */
+                    ptr->bufCnt = newBufCnt;
+                    for (j=0; j<ptr->bufCnt; j++) {
+                        ptr->postedRecvBufs[j] = (char *)CmiAlloc(bufSize);
+                        if (MPI_SUCCESS != MPI_Irecv(ptr->postedRecvBufs[j], bufSize, MPI_BYTE,
+                                                     MPI_ANY_SOURCE, POST_RECV_TAG+ptr->msgSizeIdx,
+                                                     charmComm, ptr->postedRecvReqs+j))
+                            CmiAbort("MPI_Irecv failed in buildDynamicRecvBuffers!\n");
+                    }
+
+                    /* We already posted bufs for this range of msg size */
+                    ptr = ptr->next;
+                    /* Need to set ptr to NULL as the buf list comes to an end and the while loop exits */
+                    if (ptr == CpvAccess(postRecvListHdr)) ptr = NULL;
+                    notFound = 0;
+                    break;
+                } else {
+                    /* The msgSizeIdx is larger than i */
+                    break;
+                }
+                if (ptr == CpvAccess(postRecvListHdr)) {
+                    ptr = NULL;
+                    break;
+                }
+            } /* end while(ptr): iterating the posted recv buffer list */
+
+            if (notFound) {
+                /* the current range of msg size is not found in the list */
+                int j;
+                int bufSize = i*MPI_POST_RECV_INC + MPI_POST_RECV_LOWERSIZE - 1;
+                newEntry = malloc(sizeof(MPIPostRecvList));
+                MPIPostRecvList *one = newEntry;
+                one->msgSizeIdx = i;
+                if (count == local_MSG_CNT_THRESHOLD) one->bufCnt = 1;
+                else one->bufCnt = (count - local_MSG_CNT_THRESHOLD)/local_MSG_INC + 1;
+                one->postedRecvReqs = (MPI_Request *)malloc(sizeof(MPI_Request)*one->bufCnt);
+                one->postedRecvBufs = (char **)malloc(one->bufCnt * sizeof(char *));
+                for (j=0; j<one->bufCnt; j++) {
+                    one->postedRecvBufs[j] = (char *)CmiAlloc(bufSize);
+                    if (MPI_SUCCESS != MPI_Irecv(one->postedRecvBufs[j], bufSize, MPI_BYTE,
+                                                 MPI_ANY_SOURCE, POST_RECV_TAG+one->msgSizeIdx,
+                                                 charmComm, one->postedRecvReqs+j))
+                        CmiAbort("MPI_Irecv failed in buildDynamicRecvBuffers!\n");
+                }
+            } /* end if notFound */
+
+            /* Update the new list with the newEntry */
+            CmiAssert(newEntry != NULL);
+            if (newHdr == NULL) {
+                newHdr = newEntry;
+                newListPtr = newEntry;
+                newHdr->next = newHdr;
+            } else {
+                newListPtr->next = newEntry;
+                newListPtr = newEntry;
+                newListPtr->next = newHdr;
+            }
+        } /* end if the count of this msg size range exceeds the threshold */
+    } /* end for loop over the histogram buckets */
+
+    /* Free remaining entries in the list */
+    while (ptr) {
+        /* free the buffer for this range of msg size */
+        MPIPostRecvList *nextptr = ptr->next;
+
+        free(ptr->postedRecvReqs);
+        int j;
+        for (j=0; j<ptr->bufCnt; j++) {
+            if ((ptr->postedRecvBufs)[j]) CmiFree((ptr->postedRecvBufs)[j]);
+        }
+        free(ptr->postedRecvBufs);
+        ptr = nextptr;
+        if (ptr == CpvAccess(postRecvListHdr)) break;
+    }
+
+    CpvAccess(curPostRecvPtr) = CpvAccess(postRecvListHdr) = newHdr;
+    memset(CpvAccess(MSG_HISTOGRAM_ARRAY), 0, sizeof(int)*MAX_HISTOGRAM_BUCKETS);
+} /* end of function buildDynamicRecvBuffers */
+
+static void examineMsgHistogramInfo(int size)
+{
+    int total = CpvAccess(msgRecvCnt)++;
+    if (total < MPI_POST_RECV_FREQ) {
+        recordMsgHistogramInfo(size);
+    } else {
+        buildDynamicRecvBuffers();
+    }
+}
+#else
+/* case when CAPTURE_MSG_HISTOGRAM is defined */
+static void recordMsgHistogramInfo(int size)
+{
+    int idx = size/MSG_HISTOGRAM_BINSIZE;
+    if (idx >= MAX_HISTOGRAM_BUCKETS) idx = MAX_HISTOGRAM_BUCKETS-1;
+    CpvAccess(MSG_HISTOGRAM_ARRAY)[idx]++;
+}
+#endif /* end of MPI_DYNAMIC_POST_RECV */
+
+void reportMsgHistogramInfo()
+{
+#if MPI_DYNAMIC_POST_RECV
+    int i, count;
+    count = CpvAccess(MSG_HISTOGRAM_ARRAY)[0];
+    if (count > 0) {
+        printf("msg_histo[%d]: %d for msg [0, %.2fK)\n", CmiMyNode(), count, MPI_POST_RECV_LOWERSIZE/1000.0);
+    }
+    for (i=1; i<MAX_HISTOGRAM_BUCKETS-1; i++) {
+        int count = CpvAccess(MSG_HISTOGRAM_ARRAY)[i];
+        if (count > 0) {
+            int low = (i-1)*MSG_HISTOGRAM_BINSIZE + MPI_POST_RECV_LOWERSIZE;
+            int high = low + MSG_HISTOGRAM_BINSIZE;
+            printf("msg_histo[%d]: %d for msg [%.2fK, %.2fK)\n", CmiMyNode(), count, low/1000.0, high/1000.0);
+        }
+    }
+    count = CpvAccess(MSG_HISTOGRAM_ARRAY)[MAX_HISTOGRAM_BUCKETS-1];
+    if (count > 0) {
+        printf("msg_histo[%d]: %d for msg [%.2fK, +inf)\n", CmiMyNode(), count, MPI_POST_RECV_UPPERSIZE/1000.0);
+    }
+#else
+    int i;
+    for (i=0; i<MAX_HISTOGRAM_BUCKETS; i++) {
+        int count = CpvAccess(MSG_HISTOGRAM_ARRAY)[i];
+        if (count > 0) {
+            int low = i*MSG_HISTOGRAM_BINSIZE;
+            int high = low + MSG_HISTOGRAM_BINSIZE;
+            printf("msg_histo[%d]: %d for msg [%dK, %dK)\n", CmiMyNode(), count, low/1000, high/1000);
+        }
+    }
+#endif
+}
+#endif /* end of CAPTURE_MSG_HISTOGRAM || MPI_DYNAMIC_POST_RECV */
+
+void CmiSetupMachineRecvBuffersUser()
+{
+#if MPI_DYNAMIC_POST_RECV
+    buildDynamicRecvBuffers();
+#endif
+}
+/*=======End of Msg Histogram or Dynamic Post-Recv Related Funcs======*/
+
+
 /*@}*/