Exemple #1
0
static int _open_open64_work(int(*fn) (const char *path, int flags, ...),
                             const char *path, int flags, mode_t mode)
{
  const char *newpath = path;

  WRAPPER_EXECUTION_DISABLE_CKPT();

  if (dmtcp::Util::strStartsWith(path, UNIQUE_PTS_PREFIX_STR)) {
    dmtcp::string currPtsDevName =
      dmtcp::UniquePtsNameToPtmxConId::instance().retrieveCurrentPtsDeviceName(path);
    newpath = currPtsDevName.c_str();
  }

  int fd =(*fn) (newpath, flags, mode);

  if (fd >= 0 && strcmp(path, "/dev/ptmx") == 0) {
    processDevPtmxConnection(fd);
  } else if (fd >= 0 && dmtcp::Util::strStartsWith(path, UNIQUE_PTS_PREFIX_STR)) {
    processDevPtsConnection(fd, path, newpath);
  }

  WRAPPER_EXECUTION_ENABLE_CKPT();

  return fd;
}
extern "C" int pthread_tryjoin_np(pthread_t thread, void **retval)
{
  int ret;
  if (!dmtcp::ProcessInfo::instance().beginPthreadJoin(thread)) {
    return EINVAL;
  }

  WRAPPER_EXECUTION_DISABLE_CKPT();
  ret = _real_pthread_tryjoin_np(thread, retval);
  WRAPPER_EXECUTION_ENABLE_CKPT();

#ifdef PTRACE
  /* Wrap the call to pthread_join() to make sure we call
   * delete_thread_on_pthread_join().
   * FIXME:  MTCP:process_pthread_join(thread) is calling threadisdead() THIS
   *         SHOULDN'T BE NECESSARY.
   */
  if (ret == 0) {
    mtcpFuncPtrs.process_pthread_join(thread);
  }
#endif

  dmtcp::ProcessInfo::instance().endPthreadJoin(thread);
  return ret;
}
//need to forward user clone
extern "C" int __clone(int (*fn) (void *arg), void *child_stack, int flags,
                       void *arg, int *parent_tidptr,
                       struct user_desc *newtls, int *child_tidptr)
{
  WRAPPER_EXECUTION_DISABLE_CKPT();
  dmtcp::ThreadSync::incrementUninitializedThreadCount();

  void *mtcpArg = mtcpFuncPtrs.prepare_for_clone(fn, child_stack, &flags, arg,
                                                 parent_tidptr, newtls,
                                                 &child_tidptr);

  struct ThreadArg *threadArg =
    (struct ThreadArg *) JALLOC_HELPER_MALLOC (sizeof (struct ThreadArg));
  threadArg->fn = fn;
  threadArg->arg = arg;
  threadArg->mtcpArg = mtcpArg;

  pid_t tid = _real_clone(clone_start, child_stack, flags, threadArg,
                          parent_tidptr, newtls, child_tidptr);

  if (tid == -1) {
    JTRACE("Clone call failed")(JASSERT_ERRNO);
    dmtcp::ThreadSync::decrementUninitializedThreadCount();
  } else {
    dmtcp_process_event(DMTCP_EVENT_THREAD_CREATED, (void*) (unsigned long) tid);
  }

  WRAPPER_EXECUTION_ENABLE_CKPT();
  return tid;
}
/*
 * pthread_join() is a blocking call that waits for the given thread to exit.
 * It examines the value of 'tid' field in 'struct pthread' of the given
 * thread. The kernel will write '0' to this field when the thread exits.
 *
 * In pthread_join(), the thread makes a futex call in the following fashion:
 *   _tid = pd->tid;
 *   while !succeeded
 *     futex(&pd->tid, FUTEX_WAIT, 0, _tid, ...)
 * As we can see, if the checkpoint is issued during pthread_join(), on
 * restart, the tid would have changed, but the call to futex would still used
 * the previously cached tid. This causes the caller to spin with 100% cpu
 * usage.
 *
 * The fix is to use the non blocking pthread_tryjoin_np function. To maintain
 * the semantics of pthread_join(), we need to ensure that only one thread is
 * allowed to wait on the given thread. This is done by keeping track of
 * threads that are being waited on by some other thread.
 *
 * Similar measures are taken for pthread_timedjoin_np().
 */
extern "C" int pthread_join(pthread_t thread, void **retval)
{
  int ret;
  if (!dmtcp::ProcessInfo::instance().beginPthreadJoin(thread)) {
    return EINVAL;
  }

  while (1) {
    WRAPPER_EXECUTION_DISABLE_CKPT();
    ret = _real_pthread_tryjoin_np(thread, retval);
    WRAPPER_EXECUTION_ENABLE_CKPT();

    if (ret != EBUSY) {
      break;
    }

    const struct timespec timeout = {(time_t) 0, (long)100 * 1000 * 1000};
    nanosleep(&timeout, NULL);
  }

#ifdef PTRACE
  /* Wrap the call to pthread_join() to make sure we call
   * delete_thread_on_pthread_join().
   * FIXME:  MTCP:process_pthread_join(thread) is calling threadisdead() THIS
   *         SHOULDN'T BE NECESSARY.
   */
  if (ret == 0) {
    mtcpFuncPtrs.process_pthread_join(thread);
  }
#endif

  dmtcp::ProcessInfo::instance().endPthreadJoin(thread);
  return ret;
}
// Invoked via pthread_create as start_routine
// On return, it calls mtcp_threadiszombie()
static void *pthread_start(void *arg)
{
  struct ThreadArg *threadArg = (struct ThreadArg*) arg;
  void *thread_arg = threadArg->arg;
  void * (*pthread_fn) (void *) = threadArg->pthread_fn;
  pid_t virtualTid = threadArg->virtualTid;

  JASSERT(pthread_fn != 0x0);
  JALLOC_HELPER_FREE(arg); // Was allocated in calling thread in pthread_create
  mtcpFuncPtrs.fill_in_pthread_id(_real_gettid(), pthread_self());
  dmtcp::ThreadSync::threadFinishedInitialization();
  void *result = (*pthread_fn)(thread_arg);
  JTRACE("Thread returned") (virtualTid);
  WRAPPER_EXECUTION_DISABLE_CKPT();
  mtcpFuncPtrs.threadiszombie();
  /*
   * This thread has finished its execution, do some cleanup on our part.
   *  erasing the virtualTid entry from virtualpidtable
   *  FIXME: What if the process gets checkpointed after erase() but before the
   *  thread actually exits?
   */
  dmtcp::ProcessInfo::instance().eraseTid(virtualTid);
  dmtcp_process_event(DMTCP_EVENT_PTHREAD_RETURN, NULL);
  WRAPPER_EXECUTION_ENABLE_CKPT();
  dmtcp::ThreadSync::unsetOkToGrabLock();
  return result;
}
Exemple #6
0
extern "C" int ptsname_r(int fd, char * buf, size_t buflen)
{
  WRAPPER_EXECUTION_DISABLE_CKPT();

  int retVal = ptsname_r_work(fd, buf, buflen);

  WRAPPER_EXECUTION_ENABLE_CKPT();

  return retVal;
}
extern "C" void pthread_exit(void * retval)
{
  WRAPPER_EXECUTION_DISABLE_CKPT();
  mtcpFuncPtrs.threadiszombie();
  dmtcp::ProcessInfo::instance().eraseTid(gettid());
  dmtcp_process_event(DMTCP_EVENT_PTHREAD_EXIT, NULL);
  WRAPPER_EXECUTION_ENABLE_CKPT();
  dmtcp::ThreadSync::unsetOkToGrabLock();
  _real_pthread_exit(retval);
  for(;;); // To hide compiler warning about "noreturn" function
}
Exemple #8
0
extern "C" int __ptsname_r_chk(int fd, char * buf, size_t buflen, size_t nreal)
{
  WRAPPER_EXECUTION_DISABLE_CKPT();

  JASSERT(buflen <= nreal) (buflen) (nreal) .Text("Buffer Overflow detected!");

  int retVal = ptsname_r_work(fd, buf, buflen);

  WRAPPER_EXECUTION_ENABLE_CKPT();

  return retVal;
}
extern "C" int pthread_timedjoin_np(pthread_t thread, void **retval,
                                    const struct timespec *abstime)
{
  int ret;
  if (!dmtcp::ProcessInfo::instance().beginPthreadJoin(thread)) {
    return EINVAL;
  }

  /*
   * We continue to call pthread_tryjoin_np (and sleep) until we have gone past
   * the abstime provided by the caller
   */
  while (1) {
    struct timeval tv;
    struct timespec ts;
    JASSERT(gettimeofday(&tv, NULL) == 0);
    TIMEVAL_TO_TIMESPEC(&tv, &ts);

    WRAPPER_EXECUTION_DISABLE_CKPT();
    ret = _real_pthread_tryjoin_np(thread, retval);
    WRAPPER_EXECUTION_ENABLE_CKPT();

    if (ret == 0) {
      break;
    }

    if (ts.tv_sec > abstime->tv_sec || (ts.tv_sec == abstime->tv_sec &&
                                        ts.tv_nsec > abstime->tv_nsec)) {
      ret = ETIMEDOUT;
      break;
    }

    const struct timespec timeout = {(time_t) 0, (long)100 * 1000 * 1000};
    nanosleep(&timeout, NULL);
  }

#ifdef PTRACE
  /* Wrap the call to pthread_join() to make sure we call
   * delete_thread_on_pthread_join().
   * FIXME:  MTCP:process_pthread_join(thread) is calling threadisdead() THIS
   *         SHOULDN'T BE NECESSARY.
   */
  if (ret == 0) {
    mtcpFuncPtrs.process_pthread_join(thread);
  }
#endif

  dmtcp::ProcessInfo::instance().endPthreadJoin(thread);
  return ret;
}
Exemple #10
0
extern "C" int getpeername(int sockfd, struct sockaddr *addr,
                           socklen_t *addrlen)
{
  WRAPPER_EXECUTION_DISABLE_CKPT();
  WRAPPER_HEADER_CKPT_DISABLED(int, getpeername, _real_getpeername,
                               sockfd, addr, addrlen);
  if (SYNC_IS_REPLAY) {
    WRAPPER_REPLAY_START(getpeername);
    if (retval != -1) {
      *addr = GET_FIELD(my_entry, getpeername, ret_addr);
      *addrlen = GET_FIELD(my_entry, getpeername, ret_addrlen);
    }
    WRAPPER_REPLAY_END(getpeername);
  } else if (SYNC_IS_RECORD) {
    retval = _real_getpeername(sockfd, addr, addrlen);
    if (retval != -1) {
      SET_FIELD2(my_entry, getpeername, ret_addr, *addr);
      SET_FIELD2(my_entry, getpeername, ret_addrlen, *addrlen);
    }
    WRAPPER_LOG_WRITE_ENTRY(my_entry);
  }
  WRAPPER_EXECUTION_ENABLE_CKPT();
  return retval;
}