8#include <sys/timerfd.h>
10static int restore(int64_t realtime, int64_t monotonic) {
11 struct timespec target = ed_timespec(realtime + ed_now(CLOCK_MONOTONIC) - monotonic);
12 return clock_settime(CLOCK_REALTIME, &target);
14static int jump(int64_t delta) {
15 struct timespec target = ed_timespec(ed_now(CLOCK_REALTIME) + delta);
16 return clock_settime(CLOCK_REALTIME, &target);
18static int64_t remaining(
const struct itimerspec* setting) {
19 return (int64_t)setting->it_value.tv_sec * 1000000000 + setting->it_value.tv_nsec;
22static int deadlines(
void) {
23 int failed = 0, absolute = -1, relative = -1, monotonic_fd = -1, active = 0;
26 struct itimerspec setting = {0}, snapshot;
28 const int64_t realtime = ed_now(CLOCK_REALTIME), monotonic = ed_now(CLOCK_MONOTONIC);
29 CHECK((absolute = timerfd_create(CLOCK_REALTIME, 0)) >= 0);
30 CHECK((relative = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK)) >= 0);
31 CHECK((monotonic_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)) >= 0);
32 setting.it_value = ed_timespec(ed_now(CLOCK_REALTIME) + 5000000000);
33 CHECK(timerfd_settime(absolute, TFD_TIMER_ABSTIME, &setting, NULL) == 0);
34 setting.it_value = ed_timespec(3000000000);
35 CHECK(timerfd_settime(relative, TFD_TIMER_CANCEL_ON_SET, &setting, NULL) == 0);
36 setting.it_value = ed_timespec(ed_now(CLOCK_MONOTONIC) + 3000000000);
37 CHECK(timerfd_settime(monotonic_fd, TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &setting,
40 CHECK(pthread_create(&
worker, NULL, ed_read_thread, &
reader) == 0);
42 CHECK(ed_wait(&
reader.started, 1000) == 0);
44 CHECK(!__atomic_load_n(&
reader.done, __ATOMIC_ACQUIRE));
45 const int64_t jumped = ed_now(CLOCK_MONOTONIC);
46 CHECK(jump(10000000000) == 0);
47 CHECK(ed_wait(&
reader.done, 1000) == 0 && pthread_join(
worker, NULL) == 0);
49 memcpy(&count,
reader.bytes,
sizeof(count));
50 CHECK(
reader.result == 8 && count == 1 &&
reader.finished - jumped >= 0 &&
51 reader.finished - jumped < 500000000);
52 CHECK(timerfd_gettime(relative, &snapshot) == 0 && remaining(&snapshot) > 1000000000);
53 CHECK(timerfd_gettime(monotonic_fd, &snapshot) == 0 && remaining(&snapshot) > 1000000000);
54 CHECK(read(relative, &count, 8) == -1 && errno == EAGAIN);
55 CHECK(read(monotonic_fd, &count, 8) == -1 && errno == EAGAIN);
57 CHECK(fcntl(absolute, F_SETFL, O_NONBLOCK) == 0);
58 setting.it_value = ed_timespec(ed_now(CLOCK_REALTIME) + 300000000);
59 CHECK(timerfd_settime(absolute, TFD_TIMER_ABSTIME, &setting, NULL) == 0);
60 CHECK(jump(-1000000000) == 0);
62 CHECK(read(absolute, &count, 8) == -1 && errno == EAGAIN);
63 CHECK(jump(1000000000) == 0);
64 CHECK(ed_readable(absolute, 1000) == 1 && read(absolute, &count, 8) == 8 && count == 1);
70 pthread_join(
worker, NULL);
74 if (monotonic_fd >= 0)
76 if (restore(realtime, monotonic))
81static int cancellation(
void) {
82 int failed = 0, fd = -1, alias = -1, active = 0;
85 const int flags = TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET;
86 struct itimerspec setting = {0}, snapshot;
88 const int64_t realtime = ed_now(CLOCK_REALTIME), monotonic = ed_now(CLOCK_MONOTONIC);
89 CHECK((fd = timerfd_create(CLOCK_REALTIME, 0)) >= 0 && (alias = dup(fd)) >= 0);
90 setting.it_value = ed_timespec(ed_now(CLOCK_REALTIME) + 5000000000);
91 CHECK(timerfd_settime(fd, flags, &setting, NULL) == 0);
93 CHECK(pthread_create(&
worker, NULL, ed_read_thread, &
reader) == 0);
95 CHECK(ed_wait(&
reader.started, 1000) == 0);
97 CHECK(!__atomic_load_n(&
reader.done, __ATOMIC_ACQUIRE));
98 const int64_t jumped = ed_now(CLOCK_MONOTONIC);
99 CHECK(jump(1000000000) == 0);
100 CHECK(ed_wait(&
reader.done, 1000) == 0 && pthread_join(
worker, NULL) == 0);
102 CHECK(
reader.result == -1 &&
reader.error == ECANCELED &&
reader.finished - jumped >= 0 &&
103 reader.finished - jumped < 500000000);
104 CHECK(fcntl(alias, F_SETFL, O_NONBLOCK) == 0);
105 CHECK(read(alias, &count, 8) == -1 && errno == EAGAIN);
107 setting.it_value = ed_timespec(ed_now(CLOCK_REALTIME) + 5000000000);
108 CHECK(timerfd_settime(alias, flags, &setting, NULL) == 0);
109 CHECK(jump(-1000000000) == 0 && ed_readable(fd, 0) == 1);
110 setting.it_value = ed_timespec(ed_now(CLOCK_REALTIME) + 300000000);
111 CHECK(timerfd_settime(fd, flags, &setting, NULL) == -1 && errno == ECANCELED);
112 CHECK(timerfd_gettime(alias, &snapshot) == 0 && remaining(&snapshot) > 0);
113 CHECK(ed_readable(alias, 2000) == 1 && read(alias, &count, 8) == 8 && count == 1);
114 CHECK(read(fd, &count, 8) == -1 && errno == EAGAIN);
116 setting.it_value = (
struct timespec){0};
117 setting.it_interval = ed_timespec(77000000);
118 CHECK(timerfd_settime(alias, flags, &setting, NULL) == 0);
119 CHECK(timerfd_gettime(fd, &snapshot) == 0 && remaining(&snapshot) == 0 &&
120 snapshot.it_interval.tv_nsec == 77000000);
121 CHECK(jump(1000000000) == 0 && ed_readable(fd, 0) == 1);
122 CHECK(read(alias, &count, 8) == -1 && errno == ECANCELED);
123 CHECK(read(fd, &count, 8) == -1 && errno == EAGAIN);
131 pthread_join(
worker, NULL);
133 if (restore(realtime, monotonic))
138int event_descriptor_test_clock(
void) {
139 if (geteuid() != 0) {
140 puts(
"EVENT-DESCRIPTOR-CONTRACT: SKIP clock requires root");
143 return deadlines() || cancellation();