root/dmtcpplugin.cpp

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

DEFINITIONS

This source file includes following definitions.
  1. memfence
  2. memfence
  3. memfence
  4. dmtcp_is_enabled
  5. runCoordinatorCmd
  6. dmtcpRunCommand
  7. dmtcp_checkpoint
  8. dmtcp_get_coordinator_status
  9. dmtcp_get_local_status
  10. dmtcp_disable_ckpt
  11. dmtcp_enable_ckpt
  12. dmtcp_get_ckpt_signal
  13. dmtcp_get_tmpdir
  14. dmtcp_get_ckpt_dir
  15. dmtcp_set_ckpt_dir
  16. dmtcp_get_coord_ckpt_dir
  17. dmtcp_set_coord_ckpt_dir
  18. dmtcp_set_ckpt_file
  19. dmtcp_get_ckpt_filename
  20. dmtcp_get_ckpt_files_subdir
  21. dmtcp_should_ckpt_open_files
  22. dmtcp_get_executable_path
  23. dmtcp_get_uniquepid_str
  24. dmtcp_get_uniquepid
  25. dmtcp_get_computation_id
  26. dmtcp_get_computation_id_str
  27. dmtcp_get_coord_id
  28. dmtcp_unique_pids_equal
  29. dmtcp_get_coordinator_timestamp
  30. dmtcp_get_generation
  31. checkpoint_is_pending
  32. dmtcp_is_running_state
  33. dmtcp_is_initializing_wrappers
  34. dmtcp_is_protected_fd
  35. dmtcp_protected_environ_fd
  36. dmtcp_close_protected_fd
  37. dmtcp_get_restart_env
  38. dmtcp_get_readlog_fd
  39. dmtcp_get_ptrace_fd
  40. dmtcp_get_libc_dlsym_addr
  41. dmtcp_block_ckpt_signal
  42. dmtcp_unblock_ckpt_signal
  43. dmtcp_send_key_val_pair_to_coordinator
  44. dmtcp_send_key_val_pair_to_coordinator_sync
  45. dmtcp_send_query_to_coordinator
  46. dmtcp_get_local_ip_addr
  47. dmtcp_no_coordinator

   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 
  22 #include <stdlib.h>
  23 #include "dmtcp.h"
  24 #include "dmtcpworker.h"
  25 #include "coordinatorapi.h"
  26 #include "syscallwrappers.h"
  27 #include "processinfo.h"
  28 #include "shareddata.h"
  29 #include "threadsync.h"
  30 #include "mtcpinterface.h"
  31 #include "util.h"
  32 
  33 #undef dmtcp_is_enabled
  34 #undef dmtcp_checkpoint
  35 #undef dmtcp_disable_ckpt
  36 #undef dmtcp_enable_ckpt
  37 #undef dmtcp_get_coordinator_status
  38 #undef dmtcp_get_local_status
  39 #undef dmtcp_get_uniquepid_str
  40 #undef dmtcp_get_ckpt_filename
  41 
  42 using namespace dmtcp;
  43 
  44 //global counters
  45 static int numCheckpoints = 0;
  46 static int numRestarts    = 0;
  47 
  48 //I wish we could use pthreads for the trickery in this file, but much of our
  49 //code is executed before the thread we want to wake is restored.  Thus we do
  50 //it the bad way.
  51 #if defined(__i386__) || defined(__x86_64__)
  52 static inline void memfence(){  asm volatile ("mfence" ::: "memory"); }
  53 #elif defined(__arm__)
  54 static inline void memfence(){  asm volatile ("dmb" ::: "memory"); }
  55 #elif defined(__aarch64__)
  56 # include "membarrier.h"
  57 static inline void memfence(){  RMB; WMB; }
  58 #else
  59 # define memfence() __sync_synchronize()
  60 #endif
  61 
  62 EXTERNC int dmtcp_is_enabled() { return 1; }
  63 
  64 static void runCoordinatorCmd(char c,
  65                               int *coordCmdStatus = NULL,
  66                               int *numPeers = NULL,
  67                               int *isRunning = NULL)
  68 {
  69   _dmtcp_lock();
  70   {
  71     CoordinatorAPI coordinatorAPI;
  72 
  73     dmtcp_disable_ckpt();
  74     coordinatorAPI.connectAndSendUserCommand(c, coordCmdStatus, numPeers,
  75                                              isRunning);
  76     dmtcp_enable_ckpt();
  77   }
  78   _dmtcp_unlock();
  79 }
  80 
  81 static int dmtcpRunCommand(char command)
  82 {
  83   int coordCmdStatus;
  84   int i = 0;
  85   while (i < 100) {
  86     runCoordinatorCmd(command, &coordCmdStatus);
  87   // if we got error result - check it
  88         // There is possibility that checkpoint thread
  89         // did not send state=RUNNING yet or Coordinator did not receive it
  90         // -- Artem
  91     if (coordCmdStatus == CoordCmdStatus::ERROR_NOT_RUNNING_STATE) {
  92       struct timespec t;
  93       t.tv_sec = 0;
  94       t.tv_nsec = 1000000;
  95       nanosleep(&t, NULL);
  96       //printf("\nWAIT FOR CHECKPOINT ABLE\n\n");
  97     } else {
  98 //      printf("\nEverything is OK - return\n");
  99       break;
 100     }
 101     i++;
 102   }
 103   return coordCmdStatus == CoordCmdStatus::NOERROR;
 104 }
 105 
 106 EXTERNC int dmtcp_checkpoint()
 107 {
 108   int rv = 0;
 109   int oldNumRestarts    = numRestarts;
 110   int oldNumCheckpoints = numCheckpoints;
 111   memfence(); //make sure the reads above don't get reordered
 112 
 113   if(dmtcpRunCommand('c')){ //request checkpoint
 114     //and wait for the checkpoint
 115     while(oldNumRestarts==numRestarts && oldNumCheckpoints==numCheckpoints){
 116       //nanosleep should get interrupted by checkpointing with an EINTR error
 117       //though there is a race to get to nanosleep() before the checkpoint
 118       struct timespec t = {1,0};
 119       nanosleep(&t, NULL);
 120       memfence();  //make sure the loop condition doesn't get optimized
 121     }
 122     rv = (oldNumRestarts==numRestarts ? DMTCP_AFTER_CHECKPOINT : DMTCP_AFTER_RESTART);
 123   }else{
 124         /// TODO: Maybe we need to process it in some way????
 125     /// EXIT????
 126     /// -- Artem
 127     //  printf("\n\n\nError requesting checkpoint\n\n\n");
 128   }
 129 
 130   return rv;
 131 }
 132 
 133 EXTERNC int dmtcp_get_coordinator_status(int *numPeers, int *isRunning)
 134 {
 135   int coordCmdStatus;
 136   runCoordinatorCmd('s', &coordCmdStatus, numPeers, isRunning);
 137   return 1;
 138 }
 139 
 140 EXTERNC int dmtcp_get_local_status(int *nCheckpoints, int *nRestarts)
 141 {
 142   *nCheckpoints = numCheckpoints;
 143   *nRestarts = numRestarts;
 144   return 1;
 145 }
 146 
 147 EXTERNC int dmtcp_disable_ckpt()
 148 {
 149   ThreadSync::delayCheckpointsLock();
 150   return 1;
 151 }
 152 
 153 EXTERNC int dmtcp_enable_ckpt()
 154 {
 155   ThreadSync::delayCheckpointsUnlock();
 156   return 1;
 157 }
 158 
 159 EXTERNC int dmtcp_get_ckpt_signal(void)
 160 {
 161   const int ckpt_signal = DmtcpWorker::determineCkptSignal();
 162   return ckpt_signal;
 163 }
 164 
 165 EXTERNC const char* dmtcp_get_tmpdir(void)
 166 {
 167   static char tmpdir[PATH_MAX];
 168   JASSERT(SharedData::getTmpDir(tmpdir, sizeof(tmpdir)) != NULL);
 169   return tmpdir;
 170 }
 171 
 172 //EXTERNC void dmtcp_set_tmpdir(const char* dir)
 173 //{
 174 //  if (dir != NULL) {
 175 //    UniquePid::setTmpDir(dir);
 176 //  }
 177 //}
 178 
 179 EXTERNC const char* dmtcp_get_ckpt_dir()
 180 {
 181   static string tmpdir;
 182   tmpdir = ProcessInfo::instance().getCkptDir();
 183   return tmpdir.c_str();
 184 }
 185 
 186 EXTERNC void dmtcp_set_ckpt_dir(const char* dir)
 187 {
 188   if (dir != NULL) {
 189     ProcessInfo::instance().setCkptDir(dir);
 190   }
 191 }
 192 
 193 EXTERNC const char* dmtcp_get_coord_ckpt_dir(void)
 194 {
 195   static string dir;
 196   dir = CoordinatorAPI::instance().getCoordCkptDir();
 197   return dir.c_str();
 198 }
 199 
 200 EXTERNC void dmtcp_set_coord_ckpt_dir(const char* dir)
 201 {
 202   if (dir != NULL) {
 203     CoordinatorAPI::instance().updateCoordCkptDir(dir);
 204   }
 205 }
 206 
 207 EXTERNC void dmtcp_set_ckpt_file(const char *filename)
 208 {
 209   ProcessInfo::instance().setCkptFilename(filename);
 210 }
 211 
 212 EXTERNC const char* dmtcp_get_ckpt_filename(void)
 213 {
 214   static string filename;
 215   filename = ProcessInfo::instance().getCkptFilename();
 216   return filename.c_str();
 217 }
 218 
 219 EXTERNC const char* dmtcp_get_ckpt_files_subdir(void)
 220 {
 221   static string tmpdir;
 222   tmpdir = ProcessInfo::instance().getCkptFilesSubDir();
 223   return tmpdir.c_str();
 224 }
 225 
 226 EXTERNC int dmtcp_should_ckpt_open_files(void)
 227 {
 228   return getenv(ENV_VAR_CKPT_OPEN_FILES) != NULL;
 229 }
 230 
 231 EXTERNC const char* dmtcp_get_executable_path(void)
 232 {
 233   return ProcessInfo::instance().procSelfExe().c_str();
 234 }
 235 
 236 EXTERNC const char* dmtcp_get_uniquepid_str(void)
 237 {
 238   static string *uniquepid_str = NULL;
 239   uniquepid_str =
 240     new string(UniquePid::ThisProcess(true).toString());
 241   return uniquepid_str->c_str();
 242 }
 243 
 244 EXTERNC DmtcpUniqueProcessId dmtcp_get_uniquepid(void)
 245 {
 246   return UniquePid::ThisProcess().upid();
 247 }
 248 
 249 EXTERNC DmtcpUniqueProcessId dmtcp_get_computation_id(void)
 250 {
 251   return SharedData::getCompId();
 252 }
 253 
 254 EXTERNC const char* dmtcp_get_computation_id_str(void)
 255 {
 256   static string *compid_str = NULL;
 257   if (compid_str == NULL) {
 258     UniquePid compId = SharedData::getCompId();
 259     compid_str = new string(compId.toString());
 260   }
 261   return compid_str->c_str();
 262 }
 263 
 264 EXTERNC DmtcpUniqueProcessId dmtcp_get_coord_id(void)
 265 {
 266   return SharedData::getCoordId();
 267 }
 268 
 269 EXTERNC int dmtcp_unique_pids_equal(DmtcpUniqueProcessId a,
 270                                     DmtcpUniqueProcessId b)
 271 {
 272   return a._hostid == b._hostid &&
 273          a._pid == b._pid &&
 274          a._time == b._time &&
 275          a._computation_generation == b._computation_generation;
 276 }
 277 
 278 EXTERNC uint64_t dmtcp_get_coordinator_timestamp(void)
 279 {
 280   return SharedData::getCoordTimeStamp();
 281 }
 282 
 283 EXTERNC uint32_t dmtcp_get_generation(void)
 284 {
 285   return ProcessInfo::instance().get_generation();
 286 }
 287 
 288 EXTERNC int checkpoint_is_pending(void)
 289 {
 290   return SharedData::getCompId()._computation_generation >
 291            ProcessInfo::instance().get_generation();
 292 }
 293 
 294 EXTERNC int dmtcp_is_running_state(void)
 295 {
 296   return WorkerState::currentState() == WorkerState::RUNNING;
 297 }
 298 
 299 EXTERNC int dmtcp_is_initializing_wrappers(void)
 300 {
 301   return dmtcp_wrappers_initializing;
 302 }
 303 
 304 EXTERNC int dmtcp_is_protected_fd(int fd)
 305 {
 306   return DMTCP_IS_PROTECTED_FD(fd);
 307 }
 308 
 309 EXTERNC int dmtcp_protected_environ_fd(void)
 310 {
 311   return PROTECTED_ENVIRON_FD;
 312 }
 313 
 314 EXTERNC void dmtcp_close_protected_fd(int fd)
 315 {
 316   JASSERT(DMTCP_IS_PROTECTED_FD(fd));
 317   _real_close(fd);
 318 }
 319 
 320 // EXTERNC int dmtcp_get_restart_env(char *name, char *value, int maxvaluelen);
 321 // USAGE:
 322 //   char value[MAXSIZE];
 323 //   dmtcp_get_restart_env(name, value, MAXSIZE);
 324 //  Returns 0 on success, -1 if name not found; -2 if value > MAXSIZE
 325 // NOTE: This implementation assumes that a "name=value" string will be
 326 //   no more than MAXSIZE bytes.
 327 
 328 EXTERNC int
 329 dmtcp_get_restart_env(const char *name,   // IN
 330                       char *value,        // OUT
 331                       size_t maxvaluelen)
 332 {
 333   int env_fd = dup(dmtcp_protected_environ_fd());
 334   JASSERT(env_fd != -1)(env_fd)(dmtcp_protected_environ_fd());
 335   lseek(env_fd, 0, SEEK_SET);
 336   int namelen = strlen(name);
 337   *value = '\0'; // Default is null string
 338 
 339 #define SUCCESS 0
 340 #define NOTFOUND -1
 341 #define TOOLONG -2
 342 #define DMTCP_BUF_TOO_SMALL -3
 343 #define INTERNAL_ERROR -4
 344 #define NULL_PTR -5
 345 #define MAXSIZE 3000
 346 
 347   int rc = NOTFOUND; // Default is -1: name not found
 348 
 349   char env_buf[MAXSIZE] = {0}; // All "name=val" strings must be shorter than this.
 350 
 351   if (name == NULL || value == NULL) {
 352     close(env_fd);
 353     return NULL_PTR;
 354   }
 355 
 356   char *pos = NULL;
 357 
 358   while (rc == NOTFOUND) {
 359    memset(env_buf, 0, MAXSIZE);
 360    // read a flattened name-value pairs list
 361    int count = Util::readLine(env_fd, env_buf, MAXSIZE);
 362    if (count == 0) {
 363      break;
 364    } else if (count == -1) {
 365      rc = INTERNAL_ERROR;
 366    } else if (count == -2) {
 367      rc = DMTCP_BUF_TOO_SMALL;
 368    } else {
 369      char *start_ptr = env_buf;
 370      // iterate over the flattened list of name-value pairs
 371      while (start_ptr - env_buf < (int) sizeof(env_buf)) {
 372        pos = NULL;
 373        if (strncmp(start_ptr, name, namelen) == 0) {
 374          if ((pos = strchr(start_ptr, '='))) {
 375            strncpy(value, pos + 1, maxvaluelen);
 376            if (strlen(pos+1) >= maxvaluelen) {
 377              rc = TOOLONG; // value does not fit in the user-provided value buffer
 378              break;
 379            }
 380          }
 381          rc = SUCCESS;
 382          break;
 383        }
 384        // skip over a name-value pair
 385        start_ptr += strlen(start_ptr) + 1;
 386      }
 387    }
 388   }
 389 
 390   close(env_fd);
 391   JWARNING (rc != DMTCP_BUF_TOO_SMALL)
 392     (name) (sizeof(env_buf)) .Text("Resize env_buf[]");
 393   return rc;
 394 }
 395 
 396 EXTERNC int dmtcp_get_readlog_fd(void)
 397 {
 398   return PROTECTED_READLOG_FD;
 399 }
 400 
 401 EXTERNC int dmtcp_get_ptrace_fd(void)
 402 {
 403   return PROTECTED_PTRACE_FD;
 404 }
 405 
 406 LIB_PRIVATE int32_t dmtcp_dlsym_offset = -1;
 407 typedef void* (*dlsym_fnptr_t) (void *handle, const char *symbol);
 408 EXTERNC void *dmtcp_get_libc_dlsym_addr(void)
 409 {
 410   static dlsym_fnptr_t _libc_dlsym_fnptr = NULL;
 411 #ifndef CONFIG_M32
 412   const char *evar = ENV_VAR_DLSYM_OFFSET;
 413 #else
 414   const char *evar = ENV_VAR_DLSYM_OFFSET_M32;
 415 #endif
 416 
 417   if (_libc_dlsym_fnptr == NULL) {
 418     if (getenv(evar) == NULL) {
 419       fprintf(stderr,
 420               "%s:%d DMTCP Internal Error: Env var DMTCP_DLSYM_OFFSET not set.\n"
 421               "      Aborting.\n\n",
 422               __FILE__, __LINE__);
 423       abort();
 424     }
 425 
 426     dmtcp_dlsym_offset = (int32_t) strtol(getenv(evar), NULL, 10);
 427 
 428     _libc_dlsym_fnptr = (dlsym_fnptr_t)((char *)&LIBDL_BASE_FUNC +
 429                                         dmtcp_dlsym_offset);
 430   }
 431 
 432   return (void*) _libc_dlsym_fnptr;
 433 }
 434 
 435 EXTERNC void dmtcp_block_ckpt_signal(void)
 436 {
 437   static sigset_t signals_set;
 438   static bool initialized = false;
 439   if (!initialized) {
 440     sigemptyset (&signals_set);
 441     sigaddset (&signals_set, dmtcp_get_ckpt_signal());
 442     initialized = true;
 443   }
 444 
 445   JASSERT(_real_pthread_sigmask (SIG_BLOCK, &signals_set, NULL) == 0);
 446 }
 447 
 448 EXTERNC void dmtcp_unblock_ckpt_signal(void)
 449 {
 450   static sigset_t signals_set;
 451   static bool initialized = false;
 452   if (!initialized) {
 453     sigemptyset (&signals_set);
 454     sigaddset (&signals_set, dmtcp_get_ckpt_signal());
 455     initialized = true;
 456   }
 457 
 458   JASSERT(_real_pthread_sigmask (SIG_UNBLOCK, &signals_set, NULL) == 0);
 459 }
 460 
 461 EXTERNC int dmtcp_send_key_val_pair_to_coordinator(const char *id,
 462                                                    const void *key,
 463                                                    uint32_t key_len,
 464                                                    const void *val,
 465                                                    uint32_t val_len)
 466 {
 467   return CoordinatorAPI::instance().sendKeyValPairToCoordinator(id, key, key_len,
 468                                                                 val, val_len);
 469 }
 470 
 471 EXTERNC int dmtcp_send_key_val_pair_to_coordinator_sync(const char *id,
 472                                                         const void *key,
 473                                                         uint32_t key_len,
 474                                                         const void *val,
 475                                                         uint32_t val_len)
 476 {
 477   return CoordinatorAPI::instance().sendKeyValPairToCoordinator(id, key, key_len,
 478                                                                 val, val_len,
 479                                                                 1);
 480 }
 481 
 482 // On input, val points to a buffer in user memory and *val_len is the maximum
 483 //   size of that buffer (the memory allocated by user).
 484 // On output, we copy data to val, and set *val_len to the actual buffer size
 485 //   (to the size of the data that we copied to the user buffer).
 486 EXTERNC int dmtcp_send_query_to_coordinator(const char *id,
 487                                             const void *key, uint32_t key_len,
 488                                             void *val, uint32_t *val_len)
 489 {
 490   return CoordinatorAPI::instance().sendQueryToCoordinator(id, key, key_len,
 491                                                            val, val_len);
 492 }
 493 
 494 EXTERNC void dmtcp_get_local_ip_addr(struct in_addr *in)
 495 {
 496   SharedData::getLocalIPAddr(in);
 497 }
 498 
 499 EXTERNC int dmtcp_no_coordinator(void)
 500 {
 501   return CoordinatorAPI::noCoordinator();
 502 }

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