/** * Wrapper around various monotone time sources. */ DECLINLINE(int) mono_clock(struct timespec *ts) { static int iWorking = -1; switch (iWorking) { #ifdef CLOCK_MONOTONIC /* * Standard clock_gettime() */ case 0: return clock_gettime(CLOCK_MONOTONIC, ts); /* * Syscall clock_gettime(). */ case 1: return sys_clock_gettime(CLOCK_MONOTONIC, ts); #endif /* CLOCK_MONOTONIC */ /* * Figure out what's working. */ case -1: { int rc; #ifdef CLOCK_MONOTONIC /* * Real-Time API. */ rc = clock_gettime(CLOCK_MONOTONIC, ts); if (!rc) { iWorking = 0; return 0; } rc = sys_clock_gettime(CLOCK_MONOTONIC, ts); if (!rc) { iWorking = 1; return 0; } #endif /* CLOCK_MONOTONIC */ /* give up */ iWorking = -2; break; } } return -1; }
static void test_one_clock_gettime(int clock, const char *name) { struct timespec start, vdso, end; int vdso_ret, end_ret; printf("[RUN]\tTesting clock_gettime for clock %s (%d)...\n", name, clock); if (sys_clock_gettime(clock, &start) < 0) { if (errno == EINVAL) { vdso_ret = vdso_clock_gettime(clock, &vdso); if (vdso_ret == -EINVAL) { printf("[OK]\tNo such clock.\n"); } else { printf("[FAIL]\tNo such clock, but __vdso_clock_gettime returned %d\n", vdso_ret); nerrs++; } } else { printf("[WARN]\t clock_gettime(%d) syscall returned error %d\n", clock, errno); } return; } vdso_ret = vdso_clock_gettime(clock, &vdso); end_ret = sys_clock_gettime(clock, &end); if (vdso_ret != 0 || end_ret != 0) { printf("[FAIL]\tvDSO returned %d, syscall errno=%d\n", vdso_ret, errno); nerrs++; return; } printf("\t%llu.%09ld %llu.%09ld %llu.%09ld\n", (unsigned long long)start.tv_sec, start.tv_nsec, (unsigned long long)vdso.tv_sec, vdso.tv_nsec, (unsigned long long)end.tv_sec, end.tv_nsec); if (!ts_leq(&start, &vdso) || !ts_leq(&vdso, &end)) { printf("[FAIL]\tTimes are out of sequence\n"); nerrs++; } }
static int timerfd_arm(struct task_restore_args *args) { int i; for (i = 0; i < args->timerfd_n; i++) { struct restore_timerfd *t = &args->timerfd[i]; int ret; pr_debug("timerfd: arm for fd %d (%d)\n", t->fd, i); if (t->settime_flags & TFD_TIMER_ABSTIME) { struct timespec ts = { }; /* * We might need to adjust value because the checkpoint * and restore procedure takes some time itself. Note * we don't adjust nanoseconds, since the result may * overflow the limit NSEC_PER_SEC FIXME */ if (sys_clock_gettime(t->clockid, &ts)) { pr_err("Can't get current time"); return -1; } t->val.it_value.tv_sec += (time_t)ts.tv_sec; pr_debug("Ajust id %#x it_value(%llu, %llu) -> it_value(%llu, %llu)\n", t->id, (unsigned long long)ts.tv_sec, (unsigned long long)ts.tv_nsec, (unsigned long long)t->val.it_value.tv_sec, (unsigned long long)t->val.it_value.tv_nsec); } ret = sys_timerfd_settime(t->fd, t->settime_flags, &t->val, NULL); if (t->ticks) ret |= sys_ioctl(t->fd, TFD_IOC_SET_TICKS, (unsigned long)&t->ticks); if (ret) { pr_err("Can't restore ticks/time for timerfd - %d\n", i); return ret; } } return 0; }