root/mtcpinterface.cpp

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. initializeMtcpEngine
  2. callbackSleepBetweenCheckpoint
  3. callbackPreCheckpoint
  4. callbackPostCheckpoint
  5. callbackHoldsAnyLocks
  6. callbackPreSuspendUserThread
  7. callbackPreResumeUserThread
  8. restoreArgvAfterRestart
  9. unmapRestoreArgv

   1 /****************************************************************************
   2  *   Copyright (C) 2006-2013 by Jason Ansel, Kapil Arya, and Gene Cooperman *
   3  *   jansel@csail.mit.edu, kapil@ccs.neu.edu, gene@ccs.neu.edu              *
   4  *                                                                          *
   5  *  This file is part of DMTCP.                                             *
   6  *                                                                          *
   7  *  DMTCP is free software: you can redistribute it and/or                  *
   8  *  modify it under the terms of the GNU Lesser General Public License as   *
   9  *  published by the Free Software Foundation, either version 3 of the      *
  10  *  License, or (at your option) any later version.                         *
  11  *                                                                          *
  12  *  DMTCP is distributed in the hope that it will be useful,                *
  13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of          *
  14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
  15  *  GNU Lesser General Public License for more details.                     *
  16  *                                                                          *
  17  *  You should have received a copy of the GNU Lesser General Public        *
  18  *  License along with DMTCP:dmtcp/src.  If not, see                        *
  19  *  <http://www.gnu.org/licenses/>.                                         *
  20  ****************************************************************************/
  21 #include "constants.h"
  22 #include "mtcpinterface.h"
  23 #include "syscallwrappers.h"
  24 #include "dmtcpworker.h"
  25 #include "processinfo.h"
  26 #include "dmtcpmessagetypes.h"
  27 #include "util.h"
  28 #include "threadsync.h"
  29 #include "ckptserializer.h"
  30 #include "protectedfds.h"
  31 #include "shareddata.h"
  32 #include "threadlist.h"
  33 
  34 #include "../jalib/jfilesystem.h"
  35 #include "../jalib/jconvert.h"
  36 #include "../jalib/jassert.h"
  37 #include "../jalib/jalloc.h"
  38 
  39 using namespace dmtcp;
  40 
  41 int rounding_mode = 1;
  42 
  43 static char *_mtcpRestoreArgvStartAddr = NULL;
  44 #ifdef RESTORE_ARGV_AFTER_RESTART
  45 static void restoreArgvAfterRestart(char* mtcpRestoreArgvStartAddr);
  46 #endif
  47 static void unmapRestoreArgv();
  48 
  49 
  50 extern "C" int dmtcp_is_ptracing() __attribute__ ((weak));
  51 extern "C" int dmtcp_update_ppid() __attribute__ ((weak));
  52 
  53 void dmtcp::initializeMtcpEngine()
  54 {
  55   ThreadSync::initMotherOfAll();
  56   ThreadList::init();
  57 }
  58 
  59 void dmtcp::callbackSleepBetweenCheckpoint ( int sec )
  60 {
  61   ThreadSync::waitForUserThreadsToFinishPreResumeCB();
  62   DmtcpWorker::eventHook(DMTCP_EVENT_WAIT_FOR_SUSPEND_MSG, NULL);
  63   if (dmtcp_is_ptracing && dmtcp_is_ptracing()) {
  64     // FIXME: Add a test to make check that can insert a delay of a couple of
  65     //        seconds in here. This helps testing the initialization routines
  66     //        of various plugins.
  67     // Inform coordinator of our RUNNING state;
  68     DmtcpWorker::informCoordinatorOfRUNNINGState();
  69   }
  70   DmtcpWorker::waitForStage1Suspend();
  71 
  72   unmapRestoreArgv();
  73 }
  74 
  75 void dmtcp::callbackPreCheckpoint()
  76 {
  77   //now user threads are stopped
  78   DmtcpWorker::waitForStage2Checkpoint();
  79 }
  80 
  81 void dmtcp::callbackPostCheckpoint(int isRestart,
  82                                    char* mtcpRestoreArgvStartAddr)
  83 {
  84   if (isRestart) {
  85     //restoreArgvAfterRestart(mtcpRestoreArgvStartAddr);
  86 
  87     JTRACE("begin postRestart()");
  88     WorkerState::setCurrentState(WorkerState::RESTARTING);
  89     if (dmtcp_update_ppid) {
  90       dmtcp_update_ppid();
  91     }
  92     DmtcpWorker::eventHook(DMTCP_EVENT_RESTART, NULL);
  93   } else {
  94     DmtcpWorker::eventHook(DMTCP_EVENT_RESUME, NULL);
  95   }
  96 
  97   DmtcpWorker::waitForStage3Refill(isRestart);
  98 
  99   DmtcpWorker::waitForStage4Resume(isRestart);
 100 
 101   WorkerState::setCurrentState( WorkerState::RUNNING );
 102 
 103   if (dmtcp_is_ptracing == NULL || !dmtcp_is_ptracing()) {
 104     // Inform coordinator of our RUNNING state;
 105     // If running under ptrace, let's do this in sleep-between-ckpt callback.
 106     DmtcpWorker::informCoordinatorOfRUNNINGState();
 107   }
 108   // After this, the user threads will be unlocked in mtcp.c and will resume.
 109 }
 110 
 111 void dmtcp::callbackHoldsAnyLocks(int *retval)
 112 {
 113   /* This callback is useful only for the ptrace plugin currently, but may be
 114    * used for other stuff as well.
 115    *
 116    * This is invoked as the first thing in stopthisthread() routine, which is
 117    * the signal handler for CKPT signal, to check if the current thread is
 118    * holding any of the wrapperExecLock or threadCreationLock. If the thread is
 119    * holding any of these locks, we return from the signal handler and wait for
 120    * the thread to release the lock. Once the thread has release the last lock,
 121    * it will send itself the CKPT signal and will return to the signal handler
 122    * and will proceed normally.
 123    */
 124 
 125   ThreadSync::unsetOkToGrabLock();
 126   *retval = ThreadSync::isThisThreadHoldingAnyLocks();
 127   if (*retval) {
 128     JASSERT(dmtcp_is_ptracing && dmtcp_is_ptracing());
 129     ThreadSync::setSendCkptSignalOnFinalUnlock();
 130   }
 131 }
 132 
 133 void dmtcp::callbackPreSuspendUserThread()
 134 {
 135   ThreadSync::incrNumUserThreads();
 136   DmtcpWorker::eventHook(DMTCP_EVENT_PRE_SUSPEND_USER_THREAD, NULL);
 137 }
 138 
 139 void dmtcp::callbackPreResumeUserThread(int isRestart)
 140 {
 141   DmtcpEventData_t edata;
 142   edata.resumeUserThreadInfo.isRestart = isRestart;
 143   DmtcpWorker::eventHook(DMTCP_EVENT_RESUME_USER_THREAD, &edata);
 144   ThreadSync::setOkToGrabLock();
 145   // This should be the last significant work before returning from this
 146   // function.
 147   ThreadSync::processPreResumeCB();
 148   // Make a dummy syscall to inform superior of our status before we resume. If
 149   // ptrace is disabled, this call has no significant effect.
 150   syscall(DMTCP_FAKE_SYSCALL);
 151 }
 152 
 153 #ifdef RESTORE_ARGV_AFTER_RESTART
 154 static void restoreArgvAfterRestart(char* mtcpRestoreArgvStartAddr)
 155 {
 156   /*
 157    * The addresses where argv of mtcp_restart process starts. /proc/PID/cmdline
 158    * information is looked up from these addresses.  We observed that the
 159    * stack-base for mtcp_restart is always 0x7ffffffff000 in 64-bit system and
 160    * 0xc0000000 in case of 32-bit system.  Once we restore the checkpointed
 161    * process's memory, we will map the pages ending in these address into the
 162    * process's memory if they are unused i.e. not mapped by the process (which
 163    * is true for most processes running with ASLR).  Once we map them, we can
 164    * put the argv of the checkpointed process in there so that
 165    * /proc/self/cmdline shows the correct values.
 166    * Note that if compiled in 32-bit mode '-m32', the stack base address
 167    * is in still a different location, and so this logic is not valid.
 168    */
 169   JASSERT(mtcpRestoreArgvStartAddr != NULL);
 170 
 171   long page_size = sysconf(_SC_PAGESIZE);
 172   long page_mask = ~(page_size - 1);
 173   char *startAddr = (char*) ((unsigned long) mtcpRestoreArgvStartAddr & page_mask);
 174 
 175   size_t len;
 176   len = (ProcessInfo::instance().argvSize() + page_size) & page_mask;
 177 
 178   // Check to verify if any page in the given range is already mmap()'d.
 179   // It assumes that the given addresses may belong to stack only, and if
 180   // mapped, will have read+write permissions.
 181   for (size_t i = 0; i < len; i += page_size) {
 182     int ret = mprotect ((char*) startAddr + i, page_size,
 183                         PROT_READ | PROT_WRITE);
 184     if (ret != -1 || errno != ENOMEM) {
 185       _mtcpRestoreArgvStartAddr = NULL;
 186       return;
 187     }
 188   }
 189 
 190   //None of the pages are mapped -- it is safe to mmap() them
 191   void *retAddr = mmap((void*) startAddr, len, PROT_READ | PROT_WRITE,
 192                     MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
 193   if (retAddr != MAP_FAILED) {
 194     JTRACE("Restoring /proc/self/cmdline")
 195       (mtcpRestoreArgvStartAddr) (startAddr) (len) (JASSERT_ERRNO) ;
 196     vector<string> args = jalib::Filesystem::GetProgramArgs();
 197     char *addr = mtcpRestoreArgvStartAddr;
 198     // Do NOT change restarted process's /proc/self/cmdline.
 199     //args[0] = DMTCP_PRGNAME_PREFIX + args[0];
 200     for ( size_t i=0; i< args.size(); ++i ) {
 201       if (addr + args[i].length() >= startAddr + len)
 202         break;
 203       strcpy(addr, args[i].c_str());
 204       addr += args[i].length() + 1;
 205     }
 206     _mtcpRestoreArgvStartAddr = startAddr;
 207   } else {
 208     JTRACE("Unable to restore /proc/self/cmdline") (startAddr) (len) (JASSERT_ERRNO) ;
 209     _mtcpRestoreArgvStartAddr = NULL;
 210   }
 211   return;
 212 }
 213 #endif
 214 
 215 static void unmapRestoreArgv()
 216 {
 217   long page_size = sysconf(_SC_PAGESIZE);
 218   long page_mask = ~(page_size - 1);
 219   if (_mtcpRestoreArgvStartAddr != NULL) {
 220     JTRACE("Unmapping previously mmap()'d pages (that were mmap()'d for restoring argv");
 221     size_t len;
 222     len = (ProcessInfo::instance().argvSize() + page_size) & page_mask;
 223     JASSERT(_real_munmap(_mtcpRestoreArgvStartAddr, len) == 0)
 224       (_mtcpRestoreArgvStartAddr) (len)
 225       .Text ("Failed to munmap extra pages that were mapped during restart");
 226   }
 227 }

/* [<][>][^][v][top][bottom][index][help] */