fix for migration
[charm.git] / src / arch / mpi / machine.c
index 0bbda836c48e0735d81cded3eea80ecf08c0ea55..e6c19ece5309e8351988bc5646e48ccaf19aa58a 100644 (file)
@@ -56,7 +56,7 @@ 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;
-static MPI_Comm charmComm;
+MPI_Comm charmComm;
 
 #if CMI_EXERT_SEND_CAP
 static int SEND_CAP=3;
@@ -198,13 +198,24 @@ static void reportMsgHistogramInfo();
 
 #endif /* end of MPI_POST_RECV defined */
 
+/* to avoid MPI's in order delivery, changing MPI Tag all the time */
+#define TAG     1375
+#if MPI_POST_RECV
+#define POST_RECV_TAG       (TAG+1)
+#define BARRIER_ZERO_TAG  TAG
+#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
 
-#ifdef USE_ASYNC_RECV_FUNC
+#if USE_ASYNC_RECV_FUNC || USE_MPI_CTRLMSG_SCHEME
 static int IRECV_MSG_THRESHOLD = 8000;
 typedef struct IRecvListEntry{
     MPI_Request req;
@@ -233,7 +244,7 @@ static void irecvListEntryFree(IRecvList used){
     freedIrecvList = used;
 }
 
-#endif /* end of USE_ASYNC_RECV_FUNC */
+#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
@@ -249,14 +260,6 @@ static void recordMsgHistogramInfo(int size);
 static void reportMsgHistogramInfo();
 #endif
 
-/* to avoid MPI's in order delivery, changing MPI Tag all the time */
-#define TAG     1375
-#if MPI_POST_RECV
-#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
@@ -298,12 +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;
     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);
@@ -332,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;
@@ -357,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(int whenidle);
-#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===== */
 
 /**
@@ -401,6 +390,10 @@ 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
@@ -460,11 +453,14 @@ static CmiCommHandle MPISendOneMsg(SMSG_LIST *smsg) {
             CmiAbort("MPISendOneMsg: MPI_Isend failed!\n");
         END_TRACE_SENDCOMM(msg);
     }
+#elif USE_MPI_CTRLMSG_SCHEME
+    sendViaCtrlMsg(node, size, msg, smsg);
 #else
-/* branch not using MPI_POST_RECV */
+/* branch not using MPI_POST_RECV or USE_MPI_CTRLMSG_SCHEME */
 
-#if CMK_MEM_CHECKPOINT
+#if CMK_MEM_CHECKPOINT || CMK_MESSAGE_LOGGING
        dstrank = petorank[node];
+        smsg->dstrank = dstrank;
 #else
        dstrank=node;
 #endif
@@ -478,8 +474,9 @@ static CmiCommHandle MPISendOneMsg(SMSG_LIST *smsg) {
     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
@@ -495,14 +492,13 @@ 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 (Cmi_smp_mode_setting == COMM_THREAD_SEND_RECV) {
       EnqueueMsg(msg, size, destNode, mode);
@@ -529,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;
@@ -579,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)--;
@@ -637,9 +645,13 @@ static int PumpMsgs(void) {
 #endif
 
         START_TRACE_RECVCOMM(NULL);
-
-        /* First check posted recvs then do  probe unmatched outstanding messages */
-#if MPI_POST_RECV
+#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;
@@ -716,7 +728,7 @@ static int PumpMsgs(void) {
             CpvAccess(Cmi_unposted_recv_total)++;
         }
 #else
-        /* Original version */
+        /* 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)
@@ -753,20 +765,20 @@ static int PumpMsgs(void) {
         }
 #endif
 
-#endif /*end of not MPI_POST_RECV */
+#endif /*end of !MPI_POST_RECV and !USE_MPI_CTRLMSG_SCHEME*/
 
-        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
-
-        if(doSyncRecv){
+               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);
         }
@@ -845,15 +857,15 @@ static int PumpMsgs(void) {
 
     }
 
-#if USE_ASYNC_RECV_FUNC
+#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);*/
@@ -867,7 +879,7 @@ static int PumpMsgs(void) {
         handleOneRecvedMsg(irecvEnt->size, irecvEnt->msg);
         waitIrecvListHead->next = irecvEnt->next;
         irecvListEntryFree(irecvEnt);
-        recd = 1;        
+        //recd = 1;        
     }
     if(waitIrecvListHead->next == NULL)
         waitIrecvListTail = waitIrecvListHead;
@@ -1012,7 +1024,7 @@ static double sendtime = 0.0;
 
 #endif //end of CMK_SMP
 
-static void AdvanceCommunicationForMPI(int whenidle) {
+void LrtsAdvanceCommunication(int whenidle) {
 #if REPORT_COMM_METRICS
     double t1, t2, t3, t4;
     t1 = CmiWallTimer();
@@ -1057,11 +1069,11 @@ static void AdvanceCommunicationForMPI(int whenidle) {
 }
 /* ######End of functions related with communication progress ###### */
 
-static void MachinePostNonLocalForMPI() {
+void LrtsPostNonLocal() {
 #if !CMK_SMP
     if (no_outstanding_sends) {
         while (CpvAccess(MsgQueueLen)>0) {
-            AdvanceCommunicationForMPI(0);
+            LrtsAdvanceCommunication(0);
         }
     }
 
@@ -1113,7 +1125,7 @@ void CmiMachineProgressImpl() {
 #endif
 
 /* ######Beginning of functions related with exiting programs###### */
-void DrainResourcesForMPI() {
+void LrtsDrainResources() {
 #if !CMK_SMP
     while (!CmiAllAsyncMsgsSent()) {
         PumpMsgs();
@@ -1132,18 +1144,20 @@ void DrainResourcesForMPI() {
         }
     }
 #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(charmComm))
-        CmiAbort("DrainResourcesForMPI: MPI_Barrier failed!\n");
+        CmiAbort("LrtsDrainResources: MPI_Barrier failed!\n");
     END_EVENT(10);
     MACHSTATE(2, "} Machine exit barrier end");
 }
 
-void MachineExitForMPI() {
+void LrtsExit() {
     int i;
 #if (CMK_DEBUG_MODE || CMK_WEB_MODE || NODE_0_IS_CONVHOST)
     int doPrint = 0;
@@ -1272,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;
@@ -1298,6 +1312,8 @@ static void MachineInitForMPI(int *argc, char ***argv, int *numNodes, int *myNod
 #endif
     }
 
+    *argc = CmiGetArgc(largv);     /* update it in case it is out of sync */
+
     if(!CharmLibInterOperate) {
 #if CMK_MPI_INIT_THREAD
 #if CMK_SMP
@@ -1325,6 +1341,8 @@ static void MachineInitForMPI(int *argc, char ***argv, int *numNodes, int *myNod
                        MPI_Comm_rank(charmComm, myNodeID);
     }
 
+    MPI_Bcast(&_Cmi_mynodesize, 1, MPI_INT, 0, MPI_COMM_WORLD);
+
     myNID = *myNodeID;
 
     MPI_Get_version(&ver, &subver);
@@ -1359,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;
@@ -1375,11 +1393,19 @@ 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, charmComm,&sts);
       int newpe = vals[0];
       CpvAccess(_curRestartPhase) = vals[1];
+      CmiPrintf("Charm++> Spare MPI rank %d is activated for global PE %d phase %d.\n", *myNodeID, newpe,CpvAccess(_curRestartPhase));
 
       if (newpe == -1) {
           MPI_Barrier(charmComm);
@@ -1387,7 +1413,6 @@ static void MachineInitForMPI(int *argc, char ***argv, int *numNodes, int *myNod
           exit(0);
       }
 
-      CmiPrintf("Charm++> Spare MPI rank %d is activated for PE %d.\n", *myNodeID, newpe);
         /* update petorank */
       MPI_Recv(petorank, num_workpes, MPI_INT,MPI_ANY_SOURCE,FAIL_TAG,charmComm, &sts);
       nextrank = *myNodeID + 1;
@@ -1406,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;
@@ -1467,6 +1496,13 @@ static void MachineInitForMPI(int *argc, char ***argv, int *numNodes, int *myNod
                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_EXERT_SEND_CAP
     CmiGetArgInt(largv, "+dynCapSend", &SEND_CAP);
@@ -1522,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;
 
@@ -1596,15 +1638,15 @@ static void MachinePreCommonInitForMPI(int everReturn) {
         }
 #endif
     }
-#endif /* end of MPI_POST_RECV */
-
+#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
+#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()) {
@@ -1616,9 +1658,15 @@ static void MachinePreCommonInitForMPI(int everReturn) {
     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();
 
@@ -1726,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;
@@ -1746,7 +1794,7 @@ void CmiTimerInit(char **argv) {
             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();
@@ -1844,7 +1892,6 @@ int CmiBarrier() {
          *  and END_EVENT are disabled here. -Chao Mei
          */
         /*START_EVENT();*/
-
         if (MPI_SUCCESS != MPI_Barrier(charmComm))
             CmiAbort("Timernit: MPI_Barrier failed!\n");
 
@@ -1868,7 +1915,6 @@ 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, charmComm,&sts))
                     CmiPrintf("MPI_Recv failed!\n");
 
@@ -1888,12 +1934,12 @@ 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,charmComm);
     MPI_Send(petorank, num_workpes, MPI_INT,rank,FAIL_TAG,charmComm);
@@ -1905,32 +1951,66 @@ void mpi_end_spare()
     int i;
     for (i=nextrank; i<total_pes; i++) {
         int vals[2] = {-1,-1};
+        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();
     }
+    CmiPrintf("[%d] die now before barrier\n", CmiMyPe());
     MPI_Barrier(charmComm);
     MPI_Finalize();
     exit(0);
+#endif
 }
 
 #endif
@@ -2188,7 +2268,7 @@ static void recordMsgHistogramInfo(int size)
 }
 #endif /* end of MPI_DYNAMIC_POST_RECV */
 
-static void reportMsgHistogramInfo()
+void reportMsgHistogramInfo()
 {
 #if MPI_DYNAMIC_POST_RECV
     int i, count;