15#include <sys/syscall.h>
16#include <sys/timerfd.h>
19static int arm(
int fd,
int milliseconds,
int interval) {
20 struct itimerspec setting = {.it_value = ed_timespec((int64_t)milliseconds * 1000000),
21 .it_interval = ed_timespec((int64_t)interval * 1000000)};
22 return timerfd_settime(fd, 0, &setting, NULL);
24static int64_t remaining(
const struct itimerspec* setting) {
25 return (int64_t)setting->it_value.tv_sec * 1000000000 + setting->it_value.tv_nsec;
28static int counter_and_settings(
void) {
29 int failed = 0, fd = -1, pipefd[2] = {-1, -1};
30 long page = sysconf(_SC_PAGESIZE);
31 void* bad = mmap(NULL, page, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
32 uint64_t counts[2] = {0};
34 char path[64], link[64];
35 struct itimerspec setting, replacement = {.it_value = {0, 1000000}}, old;
36 CHECK(bad != MAP_FAILED);
37 CHECK((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC)) >= 0);
38 CHECK((fcntl(fd, F_GETFL) & O_NONBLOCK) && (fcntl(fd, F_GETFD) & FD_CLOEXEC));
39 CHECK(fstat(fd, &info) == 0 && info.st_ino != 0 && info.st_nlink == 1 &&
40 (info.st_mode & 0777) == 0600 && info.st_size == 0);
41 CHECK(lseek(fd, 0, SEEK_SET) == 0 && lseek(fd, 123, SEEK_SET) == 0);
42 CHECK(lseek(fd, 0, 123) == -1 && errno == EINVAL);
43 snprintf(path,
sizeof(path),
"/proc/self/fd/%d", fd);
44 CHECK(readlink(path, link,
sizeof(link)) == (ssize_t)strlen(
"anon_inode:[timerfd]") &&
45 !memcmp(link,
"anon_inode:[timerfd]", strlen(
"anon_inode:[timerfd]")));
46 CHECK(write(fd, counts, 8) == -1 && errno == EINVAL);
47 CHECK(timerfd_create(-1, 0) == -1 && errno == EINVAL);
48 CHECK(timerfd_create(CLOCK_MONOTONIC, 0x40000000) == -1 && errno == EINVAL);
49 CHECK(timerfd_create(CLOCK_PROCESS_CPUTIME_ID, 0) == -1 && errno == EINVAL);
50 CHECK(timerfd_gettime(fd, &setting) == 0 && remaining(&setting) == 0);
51 CHECK(read(fd, counts, 0) == -1 && errno == EINVAL);
52 CHECK(read(fd, counts, 7) == -1 && errno == EINVAL);
53 CHECK(read(fd, counts,
sizeof(counts)) == -1 && errno == EAGAIN);
54 CHECK(timerfd_gettime(fd, bad) == -1 && errno == EFAULT);
55 CHECK(syscall(SYS_timerfd_settime, fd, 0, NULL, NULL) == -1 && errno == EFAULT);
56 CHECK(timerfd_settime(fd, 0, bad, NULL) == -1 && errno == EFAULT);
57 CHECK(timerfd_settime(fd, 4, &replacement, NULL) == -1 && errno == EINVAL);
58 replacement.it_value.tv_nsec = 1000000000;
59 CHECK(timerfd_settime(fd, 0, &replacement, NULL) == -1 && errno == EINVAL);
60 replacement.it_value.tv_nsec = 1000000;
61 replacement.it_interval.tv_sec = -1;
62 CHECK(timerfd_settime(fd, 0, &replacement, NULL) == -1 && errno == EINVAL);
63 replacement.it_interval.tv_sec = 0;
64 CHECK(pipe(pipefd) == 0);
65 CHECK(timerfd_gettime(pipefd[0], &setting) == -1 && errno == EINVAL);
66 CHECK(timerfd_gettime(-1, &setting) == -1 && errno == EBADF);
67 CHECK(arm(fd, 3000, 77) == 0);
68 CHECK(timerfd_settime(fd, 0, &replacement, bad) == -1 && errno == EFAULT);
69 CHECK(timerfd_gettime(fd, &setting) == 0 && remaining(&setting) > 1000000000 &&
70 setting.it_interval.tv_nsec == 77000000);
71 replacement.it_value = ed_timespec(30000000);
72 CHECK(timerfd_settime(fd, 0, &replacement, &old) == 0 && remaining(&old) > 1000000000 &&
73 old.it_interval.tv_nsec == 77000000);
74 CHECK(ed_readable(fd, 2000) == 1);
75 CHECK(read(fd, bad, 8) == -1 && errno == EFAULT);
76 CHECK(ed_readable(fd, 0) == 1);
77 struct iovec faulty_vectors[2] = {{counts, 3}, {bad, 5}};
78 CHECK(readv(fd, faulty_vectors, 2) == -1 && errno == EFAULT);
79 CHECK(ed_readable(fd, 0) == 1);
80 counts[1] = UINT64_C(0xa5a5a5a5a5a5a5a5);
81 CHECK(read(fd, counts,
sizeof(counts)) == 8 && counts[0] == 1 &&
82 counts[1] == UINT64_C(0xa5a5a5a5a5a5a5a5));
83 CHECK(timerfd_gettime(fd, &setting) == 0 && remaining(&setting) == 0);
84 CHECK(read(fd, counts, 8) == -1 && errno == EAGAIN);
85 CHECK(arm(fd, 20, 20) == 0);
87 struct iovec vectors[2] = {{counts, 3}, {(
unsigned char*)counts + 3, 5}};
88 CHECK(readv(fd, vectors, 2) == 8 && counts[0] >= 3);
89 CHECK(timerfd_gettime(fd, &setting) == 0 && remaining(&setting) > 0 &&
90 setting.it_interval.tv_nsec == 20000000);
91 CHECK(arm(fd, 0, 77) == 0);
92 CHECK(timerfd_gettime(fd, &setting) == 0 && remaining(&setting) == 0 &&
93 setting.it_interval.tv_sec == 0 && setting.it_interval.tv_nsec == 77000000);
94 CHECK(read(fd, counts, 8) == -1 && errno == EAGAIN);
95 CHECK(arm(fd, 10, 0) == 0 && ed_readable(fd, 2000) == 1);
96 CHECK(arm(fd, 3000, 0) == 0);
97 CHECK(read(fd, counts, 8) == -1 && errno == EAGAIN);
98 replacement.it_value = ed_timespec(ed_now(CLOCK_MONOTONIC) + 30000000);
99 CHECK(timerfd_settime(fd, TFD_TIMER_ABSTIME, &replacement, NULL) == 0);
100 CHECK(ed_readable(fd, 2000) == 1 && read(fd, counts, 8) == 8 && counts[0] == 1);
104 for (
int n = 0; n < 2; ++n)
107 if (bad != MAP_FAILED)
112static int readiness(
void) {
113 int failed = 0, fd = -1, epoll = -1;
115 struct epoll_event interest = {.events = EPOLLIN | EPOLLOUT, .data.u64 = 0x5678}, ready;
116 CHECK((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)) >= 0);
117 CHECK((epoll = epoll_create1(EPOLL_CLOEXEC)) >= 0);
118 CHECK(epoll_ctl(epoll, EPOLL_CTL_ADD, fd, &interest) == 0);
119 CHECK(ed_readable(fd, 0) == 0 && epoll_wait(epoll, &ready, 1, 0) == 0);
120 CHECK(arm(fd, 30, 0) == 0);
121 CHECK(epoll_wait(epoll, &ready, 1, 2000) == 1 && ready.data.u64 == 0x5678 &&
122 ready.events == EPOLLIN);
123 CHECK(ed_readable(fd, 0) == 1 && epoll_wait(epoll, &ready, 1, 0) == 1);
124 CHECK(read(fd, &count, 8) == 8 && count == 1);
125 CHECK(ed_readable(fd, 0) == 0 && epoll_wait(epoll, &ready, 1, 0) == 0);
126 interest.events = EPOLLIN | EPOLLET;
127 CHECK(epoll_ctl(epoll, EPOLL_CTL_MOD, fd, &interest) == 0);
128 CHECK(arm(fd, 20, 20) == 0);
129 CHECK(epoll_wait(epoll, &ready, 1, 2000) == 1);
131 CHECK(ed_readable(fd, 0) == 1 && epoll_wait(epoll, &ready, 1, 0) == 0);
132 CHECK(read(fd, &count, 8) == 8 && count >= 3);
133 CHECK(epoll_wait(epoll, &ready, 1, 2000) == 1);
134 CHECK(read(fd, &count, 8) == 8 && count >= 1);
135 CHECK(arm(fd, 0, 0) == 0);
136 CHECK(ed_readable(fd, 0) == 0 && epoll_wait(epoll, &ready, 1, 0) == 0);
145static int shared_lifetime(
void) {
146 int failed = 0, fd = -1, alias = -1, sockets[2] = {-1, -1};
149 struct itimerspec setting;
150 struct stat info, shared_info;
152 CHECK((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC)) >= 0);
153 CHECK((alias = dup(fd)) >= 0 && !(fcntl(alias, F_GETFD) & FD_CLOEXEC));
154 CHECK(fstat(fd, &info) == 0 && fstat(alias, &shared_info) == 0 &&
155 info.st_ino == shared_info.st_ino);
157 CHECK(ioctl(alias, FIONBIO, &nonblock) == 0 && !(fcntl(fd, F_GETFL) & O_NONBLOCK));
158 CHECK(fcntl(fd, F_SETFL, O_NONBLOCK) == 0 && (fcntl(alias, F_GETFL) & O_NONBLOCK));
159 CHECK((child = fork()) >= 0);
162 if (arm(alias, 30, 0))
167 int status = ed_reap(child, 2000);
169 CHECK(status == 0 && ed_readable(fd, 2000) == 1);
170 CHECK(read(alias, &count, 8) == 8 && count == 1);
171 CHECK(read(fd, &count, 8) == -1 && errno == EAGAIN);
172 CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == 0);
173 CHECK((child = fork()) >= 0);
179 int received = ed_receive_fd(sockets[1]);
180 if (received < 0 || !(fcntl(received, F_GETFD) & FD_CLOEXEC) || arm(received, 30, 70) ||
181 send(sockets[1],
"r", 1, 0) != 1 || recv(sockets[1], &
byte, 1, 0) != 1 ||
182 ed_readable(received, 2000) != 1 || read(received, &count, 8) != 8 || count < 1)
188 CHECK(ed_send_fd(sockets[0], fd) == 0 && recv(sockets[0], &
byte, 1, 0) == 1 &&
byte ==
'r');
189 CHECK(timerfd_gettime(alias, &setting) == 0 && setting.it_interval.tv_nsec == 70000000);
190 CHECK(close(fd) == 0);
192 CHECK(close(alias) == 0);
194 CHECK(send(sockets[0],
"g", 1, 0) == 1);
195 status = ed_reap(child, 3000);
200 kill(child, SIGKILL);
201 ed_reap(child, 1000);
207 for (
int n = 0; n < 2; ++n)
213int event_descriptor_timerfd_exec(
int argc,
char** argv) {
216 int keep = atoi(argv[2]), drop = atoi(argv[3]);
218 struct itimerspec setting;
219 if (fcntl(drop, F_GETFD) != -1 || errno != EBADF || fcntl(keep, F_GETFD) < 0 ||
220 timerfd_gettime(keep, &setting) || ed_readable(keep, 2000) != 1 ||
221 read(keep, &count,
sizeof(count)) != 8 || count != 1)
226static int closing_and_exec(
void) {
227 int failed = 0, fd = -1, alias = -1, active = 0;
231 CHECK((fd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0 && (alias = dup(fd)) >= 0);
233 CHECK(pthread_create(&thread, NULL, ed_read_thread, &
reader) == 0);
235 CHECK(ed_wait(&
reader.started, 1000) == 0);
237 CHECK(!__atomic_load_n(&
reader.done, __ATOMIC_ACQUIRE));
238 CHECK(close(fd) == 0);
241 CHECK(!__atomic_load_n(&
reader.done, __ATOMIC_ACQUIRE));
242 CHECK(close(alias) == 0);
244 CHECK(ed_wait(&
reader.done, 2000) == 0 && pthread_join(thread, NULL) == 0);
247 CHECK((child = fork()) >= 0);
249 int keep = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
250 int drop = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
251 char kept[24], dropped[24];
252 if (keep < 0 || drop < 0 || arm(keep, 20, 0) || ed_readable(keep, 2000) != 1)
254 snprintf(kept,
sizeof(kept),
"%d", keep);
255 snprintf(dropped,
sizeof(dropped),
"%d", drop);
256 execl(EVENT_DESCRIPTOR_APP, EVENT_DESCRIPTOR_APP,
"timerfd-exec", kept, dropped, (
char*)NULL);
259 int status = ed_reap(child, 4000);
268 pthread_cancel(thread);
269 pthread_join(thread, NULL);
272 kill(child, SIGKILL);
273 ed_reap(child, 1000);
278int event_descriptor_test_timerfd(
void) {
279 return counter_and_settings() || readiness() || shared_lifetime() || closing_and_exec();