void ThreadSleepMs(uint64_t msec) {
  struct nacl_abi_timespec nap_duration;

  nap_duration.tv_sec = (nacl_abi_time_t) (msec / 1000);
  nap_duration.tv_nsec = (long) (msec % 1000);
  NaClNanosleep(&nap_duration, (struct nacl_abi_timespec *) NULL);
}
Beispiel #2
0
int32_t NaClSysNanosleep(struct NaClAppThread     *natp,
                         struct nacl_abi_timespec *req,
                         struct nacl_abi_timespec *rem) {
  uintptr_t                 sys_req;
  int                       retval = -NACL_ABI_EINVAL;
  struct nacl_abi_timespec  host_req;

  UNREFERENCED_PARAMETER(rem);

  NaClLog(4, "NaClSysNanosleep(%08x)\n", (uintptr_t) req);

  NaClSysCommonThreadSyscallEnter(natp);

  sys_req = NaClUserToSysAddrRange(natp->nap, (uintptr_t) req, sizeof *req);
  if (kNaClBadAddress == sys_req) {
    retval = -NACL_ABI_EFAULT;
    goto cleanup;
  }

  /* copy once */
  host_req = *(struct nacl_abi_timespec *) sys_req;
  /*
   * We assume that we do not need to normalize the time request values.
   *
   * If bogus values can cause the underlying OS to get into trouble,
   * then we need more checking here.
   */

  NaClLog(4, "NaClSysNanosleep(time = %d.%09ld S)\n",
          host_req.tv_sec, host_req.tv_nsec);

  retval = NaClNanosleep(&host_req, NULL);

cleanup:
  NaClSysCommonThreadSyscallLeave(natp);
  return retval;
}
/*
 * ClockMonotonicAccuracyTest samples the NACL_ABI_CLOCK_MONOTONIC
 * clock before and after invoking NaClNanosleep and computes the time
 * delta.  The test is considered to pass if the time delta is close
 * to the requested value.  "Close" is a per-host-OS attribute, thus
 * the above testing parameters.
 */
int ClockMonotonicAccuracyTest(uint64_t sleep_nanos) {
  int                       num_failures = 0;

  int                       err;
  struct nacl_abi_timespec  t_start;
  struct nacl_abi_timespec  t_sleep;
  struct nacl_abi_timespec  t_end;

  uint64_t                  elapsed_nanos;
  uint64_t                  elapsed_lower_bound;
  uint64_t                  elapsed_upper_bound;

  t_sleep.tv_sec  = sleep_nanos / NANOS_PER_UNIT;
  t_sleep.tv_nsec = sleep_nanos % NANOS_PER_UNIT;

  printf("\nCLOCK_MONOTONIC accuracy test:\n");

  if (0 != (err = NaClClockGetTime(NACL_ABI_CLOCK_MONOTONIC, &t_start))) {
    fprintf(stderr,
            "nacl_clock_test: NaClClockGetTime (start) failed, error %d\n",
            err);
    ++num_failures;
    goto done;
  }
  for (;;) {
    err = NaClNanosleep(&t_sleep, &t_sleep);
    if (0 == err) {
      break;
    }
    if (-NACL_ABI_EINTR == err) {
      /* interrupted syscall: sleep some more */
      continue;
    }
    fprintf(stderr,
            "nacl_clock_test: NaClNanoSleep failed, error %d\n", err);
    num_failures++;
    goto done;
  }
  if (0 != (err = NaClClockGetTime(NACL_ABI_CLOCK_MONOTONIC, &t_end))) {
    fprintf(stderr,
            "nacl_clock_test: NaClClockGetTime (end) failed, error %d\n",
            err);
    return 1;
  }

  elapsed_nanos = (t_end.tv_sec - t_start.tv_sec) * NANOS_PER_UNIT
      + (t_end.tv_nsec - t_start.tv_nsec) + g_slop_ms * NANOS_PER_MILLI;

  elapsed_lower_bound = sleep_nanos;
  elapsed_upper_bound = (uint64_t) (sleep_nanos * g_fuzzy_factor
                                    + g_syscall_overhead);

  printf("requested sleep:      %20"NACL_PRIu64" nS\n", sleep_nanos);
  printf("actual elapsed sleep: %20"NACL_PRIu64" nS\n", elapsed_nanos);
  printf("sleep lower bound:    %20"NACL_PRIu64" nS\n", elapsed_lower_bound);
  printf("sleep upper bound:    %20"NACL_PRIu64" nS\n", elapsed_upper_bound);

  if (elapsed_nanos < elapsed_lower_bound
      || elapsed_upper_bound < elapsed_nanos) {
    printf("discrepancy too large\n");
    num_failures++;
  }
 done:
  printf((0 == num_failures) ? "PASSED\n" : "FAILED\n");
  return num_failures;
}
Beispiel #4
0
int32_t NaClSysNanosleep(struct NaClAppThread     *natp,
                         struct nacl_abi_timespec *req,
                         struct nacl_abi_timespec *rem) {
  uintptr_t                 sys_req;
  uintptr_t                 sys_rem;
  struct nacl_abi_timespec  t_sleep;
  struct nacl_abi_timespec  t_rem;
  struct nacl_abi_timespec  *remptr;
  int                       retval = -NACL_ABI_EINVAL;

  NaClLog(3,
          ("Entered NaClSysNanosleep(0x%08"NACL_PRIxPTR
           ", 0x%08"NACL_PRIxPTR", 0x%08"NACL_PRIxPTR"x)\n"),
          (uintptr_t) natp, (uintptr_t) req, (uintptr_t) rem);

  NaClSysCommonThreadSyscallEnter(natp);

  sys_req = NaClUserToSysAddrRange(natp->nap, (uintptr_t) req, sizeof *req);
  if (kNaClBadAddress == sys_req) {
    retval = -NACL_ABI_EFAULT;
    goto cleanup;
  }
  if (NULL == rem) {
    sys_rem = 0;
  } else {
    sys_rem = NaClUserToSysAddrRange(natp->nap, (uintptr_t) rem, sizeof *rem);
    if (kNaClBadAddress == sys_rem) {
      retval = -NACL_ABI_EFAULT;
      goto cleanup;
    }
  }
  /*
   * post-condition: if sys_rem is non-NULL, it's safe to write to
   * (modulo thread races) and the user code wants the remaining time
   * written there.
   */

  NaClLog(4, " copying timespec from %08"NACL_PRIxPTR"x\n", sys_req);
  /* copy once */
  t_sleep = *(struct nacl_abi_timespec *) sys_req;

  remptr = (0 == sys_rem) ? NULL : &t_rem;
  /* NULL != remptr \equiv NULL != rem */

  /*
   * We assume that we do not need to normalize the time request values.
   *
   * If bogus values can cause the underlying OS to get into trouble,
   * then we need more checking here.
   */
  NaClLog(4, "NaClSysNanosleep(time = %"NACL_PRId64".%09"NACL_PRId64" S)\n",
          (int64_t) t_sleep.tv_sec, (int64_t) t_sleep.tv_nsec);
  retval = NaClNanosleep(&t_sleep, remptr);
  NaClLog(4, "NaClNanosleep returned %d\n", retval);

  if (-EINTR == retval && NULL != rem) {
    /* definitely different types, and shape may actually differ too. */
    rem = (struct nacl_abi_timespec *) sys_rem;
    rem->tv_sec = remptr->tv_sec;
    rem->tv_nsec = remptr->tv_nsec;
  }

cleanup:
  NaClLog(4, "nanosleep done.\n");
  NaClSysCommonThreadSyscallLeave(natp);
  return retval;
}