int timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itimerspec *old_value) { int timerfd, periodfd; int ret; uint64_t period; struct timespec now_timespec = {0}; struct timespec rel_timespec; timerfd = get_sibling_fd(fd, "timer"); if (timerfd < 0) return -1; periodfd = get_sibling_fd(fd, "period"); if (periodfd < 0) { close(timerfd); return -1; } if (old_value) { if (__timerfd_gettime(timerfd, periodfd, old_value)) { ret = -1; goto out; } } if (!new_value->it_value.tv_sec && !new_value->it_value.tv_nsec) { ret = set_timer(timerfd, 0); goto out; } period = timespec2tsc(&new_value->it_interval); ret = set_period(periodfd, period); if (ret < 0) goto out; /* So the caller is asking for timespecs in wall-clock time (depending * on the clock, actually, (TODO)), and the kernel expects TSC ticks * from boot. If !ABSTIME, then it's just relative to now. If it is * ABSTIME, then they are asking in terms of real-world time, which * means ABS - NOW to get the rel time, then convert to tsc ticks. */ if (flags & TFD_TIMER_ABSTIME) { ret = clock_gettime(CLOCK_MONOTONIC, &now_timespec); if (ret < 0) goto out; subtract_timespecs(&rel_timespec, &new_value->it_value, &now_timespec); } else { rel_timespec = new_value->it_value; } ret = set_timer(timerfd, timespec2tsc(&rel_timespec) + read_tsc()); /* fall-through */ out: close(timerfd); close(periodfd); return ret; }
int timerfd_gettime(int fd, struct itimerspec *curr_value) { int timerfd, periodfd; int ret; timerfd = get_sibling_fd(fd, "timer"); if (timerfd < 0) return -1; periodfd = get_sibling_fd(fd, "period"); if (periodfd < 0) { close(timerfd); return -1; } ret = __timerfd_gettime(timerfd, periodfd, curr_value); close(timerfd); close(periodfd); return ret; }