t_timerfd.c revision 1.2 1 /* $NetBSD: t_timerfd.c,v 1.2 2021/09/19 15:51:28 thorpej Exp $ */
2
3 /*-
4 * Copyright (c) 2020 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __COPYRIGHT("@(#) Copyright (c) 2020\
31 The NetBSD Foundation, inc. All rights reserved.");
32 __RCSID("$NetBSD: t_timerfd.c,v 1.2 2021/09/19 15:51:28 thorpej Exp $");
33
34 #include <sys/types.h>
35 #include <sys/event.h>
36 #include <sys/select.h>
37 #include <sys/stat.h>
38 #include <sys/syscall.h>
39 #include <sys/timerfd.h>
40 #include <errno.h>
41 #include <poll.h>
42 #include <pthread.h>
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <time.h>
46 #include <unistd.h>
47
48 #include <atf-c.h>
49
50 struct helper_context {
51 int fd;
52
53 pthread_barrier_t barrier;
54 };
55
56 static void
57 init_helper_context(struct helper_context * const ctx)
58 {
59
60 memset(ctx, 0, sizeof(*ctx));
61
62 ATF_REQUIRE(pthread_barrier_init(&ctx->barrier, NULL, 2) == 0);
63 }
64
65 static bool
66 wait_barrier(struct helper_context * const ctx)
67 {
68 int rv = pthread_barrier_wait(&ctx->barrier);
69
70 return rv == 0 || rv == PTHREAD_BARRIER_SERIAL_THREAD;
71 }
72
73 /*****************************************************************************/
74
75 static int
76 timerfd_read(int fd, uint64_t *valp)
77 {
78 uint64_t val;
79
80 switch (read(fd, &val, sizeof(val))) {
81 case -1:
82 return -1;
83
84 case sizeof(val):
85 *valp = val;
86 return 0;
87
88 default:
89 /* ?? Should never happen. */
90 errno = EIO;
91 return -1;
92 }
93 }
94
95 /*****************************************************************************/
96
97 ATF_TC(timerfd_create);
98 ATF_TC_HEAD(timerfd_create, tc)
99 {
100 atf_tc_set_md_var(tc, "descr", "validates timerfd_create()");
101 }
102 ATF_TC_BODY(timerfd_create, tc)
103 {
104 int fd;
105
106 ATF_REQUIRE((fd = timerfd_create(CLOCK_REALTIME, 0)) >= 0);
107 (void) close(fd);
108
109 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0);
110 (void) close(fd);
111
112 ATF_REQUIRE_ERRNO(EINVAL,
113 (fd = timerfd_create(CLOCK_VIRTUAL, 0)) == -1);
114
115 ATF_REQUIRE_ERRNO(EINVAL,
116 (fd = timerfd_create(CLOCK_PROF, 0)) == -1);
117
118 ATF_REQUIRE_ERRNO(EINVAL,
119 (fd = timerfd_create(CLOCK_REALTIME,
120 ~(TFD_CLOEXEC | TFD_NONBLOCK))) == -1);
121 }
122
123 /*****************************************************************************/
124
125 ATF_TC(timerfd_bogusfd);
126 ATF_TC_HEAD(timerfd_bogusfd, tc)
127 {
128 atf_tc_set_md_var(tc, "descr",
129 "validates rejection of bogus fds by timerfd_{get,set}time()");
130 }
131 ATF_TC_BODY(timerfd_bogusfd, tc)
132 {
133 struct itimerspec its = { 0 };
134 int fd;
135
136 ATF_REQUIRE((fd = kqueue()) >= 0); /* arbitrary fd type */
137
138 ATF_REQUIRE_ERRNO(EINVAL,
139 timerfd_gettime(fd, &its) == -1);
140
141 its.it_value.tv_sec = 5;
142 ATF_REQUIRE_ERRNO(EINVAL,
143 timerfd_settime(fd, 0, &its, NULL) == -1);
144
145 (void) close(fd);
146 }
147
148 /*****************************************************************************/
149
150 ATF_TC(timerfd_block);
151 ATF_TC_HEAD(timerfd_block, tc)
152 {
153 atf_tc_set_md_var(tc, "descr", "validates blocking behavior");
154 }
155 ATF_TC_BODY(timerfd_block, tc)
156 {
157 struct timespec then, now, delta;
158 uint64_t val;
159 int fd;
160
161 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0);
162
163 const struct itimerspec its = {
164 .it_value = { .tv_sec = 1, .tv_nsec = 0 },
165 .it_interval = { .tv_sec = 0, .tv_nsec = 0 },
166 };
167
168 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0);
169 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0);
170 ATF_REQUIRE(timerfd_read(fd, &val) == 0);
171 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0);
172 ATF_REQUIRE(val == 1);
173
174 timespecsub(&now, &then, &delta);
175 ATF_REQUIRE(delta.tv_sec == 1);
176
177 (void) close(fd);
178 }
179
180 /*****************************************************************************/
181
182 ATF_TC(timerfd_repeating);
183 ATF_TC_HEAD(timerfd_repeating, tc)
184 {
185 atf_tc_set_md_var(tc, "descr", "validates repeating timer behavior");
186 }
187 ATF_TC_BODY(timerfd_repeating, tc)
188 {
189 struct timespec then, now, delta;
190 uint64_t val;
191 int fd;
192
193 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC,
194 TFD_NONBLOCK)) >= 0);
195
196 const struct itimerspec its = {
197 .it_value = { .tv_sec = 0, .tv_nsec = 200000000 },
198 .it_interval = { .tv_sec = 0, .tv_nsec = 200000000 },
199 };
200
201 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0);
202 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0);
203 ATF_REQUIRE(sleep(1) == 0);
204 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0);
205 ATF_REQUIRE(timerfd_read(fd, &val) == 0);
206 ATF_REQUIRE(val >= 3 && val <= 5); /* allow some slop */
207
208 timespecsub(&now, &then, &delta);
209 ATF_REQUIRE(delta.tv_sec == 1);
210
211 (void) close(fd);
212 }
213
214 /*****************************************************************************/
215
216 ATF_TC(timerfd_abstime);
217 ATF_TC_HEAD(timerfd_abstime, tc)
218 {
219 atf_tc_set_md_var(tc, "descr", "validates specifying abstime");
220 }
221 ATF_TC_BODY(timerfd_abstime, tc)
222 {
223 struct timespec then, now, delta;
224 uint64_t val;
225 int fd;
226
227 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0);
228
229 struct itimerspec its = {
230 .it_value = { .tv_sec = 0, .tv_nsec = 0 },
231 .it_interval = { .tv_sec = 0, .tv_nsec = 0 },
232 };
233
234 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0);
235 its.it_value = then;
236 its.it_value.tv_sec += 1;
237 ATF_REQUIRE(timerfd_settime(fd, TFD_TIMER_ABSTIME, &its, NULL) == 0);
238 ATF_REQUIRE(timerfd_read(fd, &val) == 0);
239 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0);
240 ATF_REQUIRE(val == 1);
241
242 timespecsub(&now, &then, &delta);
243 ATF_REQUIRE(delta.tv_sec == 1);
244
245 (void) close(fd);
246 }
247
248 /*****************************************************************************/
249
250 ATF_TC(timerfd_cancel_on_set_immed);
251 ATF_TC_HEAD(timerfd_cancel_on_set_immed, tc)
252 {
253 atf_tc_set_md_var(tc, "descr", "validates cancel-on-set - immediate");
254 atf_tc_set_md_var(tc, "require.user", "root");
255 }
256 ATF_TC_BODY(timerfd_cancel_on_set_immed, tc)
257 {
258 struct timespec now;
259 uint64_t val;
260 int fd;
261
262 ATF_REQUIRE((fd = timerfd_create(CLOCK_REALTIME, 0)) >= 0);
263
264 const struct itimerspec its = {
265 .it_value = { .tv_sec = 60 * 60, .tv_nsec = 0 },
266 .it_interval = { .tv_sec = 0, .tv_nsec = 0 },
267 };
268
269 ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &now) == 0);
270 ATF_REQUIRE(timerfd_settime(fd, TFD_TIMER_CANCEL_ON_SET,
271 &its, NULL) == 0);
272 ATF_REQUIRE(clock_settime(CLOCK_REALTIME, &now) == 0);
273 ATF_REQUIRE_ERRNO(ECANCELED, timerfd_read(fd, &val) == -1);
274
275 (void) close(fd);
276 }
277
278 /*****************************************************************************/
279
280 static void *
281 timerfd_cancel_on_set_block_helper(void * const v)
282 {
283 struct helper_context * const ctx = v;
284 struct timespec now;
285
286 ATF_REQUIRE(wait_barrier(ctx));
287
288 ATF_REQUIRE(sleep(2) == 0);
289 ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &now) == 0);
290 ATF_REQUIRE(clock_settime(CLOCK_REALTIME, &now) == 0);
291
292 return NULL;
293 }
294
295 ATF_TC(timerfd_cancel_on_set_block);
296 ATF_TC_HEAD(timerfd_cancel_on_set_block, tc)
297 {
298 atf_tc_set_md_var(tc, "descr", "validates cancel-on-set - blocking");
299 atf_tc_set_md_var(tc, "require.user", "root");
300 }
301 ATF_TC_BODY(timerfd_cancel_on_set_block, tc)
302 {
303 struct helper_context ctx;
304 pthread_t helper;
305 void *join_val;
306 uint64_t val;
307 int fd;
308
309 ATF_REQUIRE((fd = timerfd_create(CLOCK_REALTIME, 0)) >= 0);
310
311 const struct itimerspec its = {
312 .it_value = { .tv_sec = 60 * 60, .tv_nsec = 0 },
313 .it_interval = { .tv_sec = 0, .tv_nsec = 0 },
314 };
315
316 init_helper_context(&ctx);
317
318 ATF_REQUIRE(timerfd_settime(fd, TFD_TIMER_CANCEL_ON_SET,
319 &its, NULL) == 0);
320 ATF_REQUIRE(pthread_create(&helper, NULL,
321 timerfd_cancel_on_set_block_helper, &ctx) == 0);
322 ATF_REQUIRE(wait_barrier(&ctx));
323 ATF_REQUIRE_ERRNO(ECANCELED, timerfd_read(fd, &val) == -1);
324
325 ATF_REQUIRE(pthread_join(helper, &join_val) == 0);
326
327 (void) close(fd);
328 }
329
330 /*****************************************************************************/
331
332 ATF_TC(timerfd_select_poll_kevent_immed);
333 ATF_TC_HEAD(timerfd_select_poll_kevent_immed, tc)
334 {
335 atf_tc_set_md_var(tc, "descr",
336 "validates select/poll/kevent behavior - immediate return");
337 }
338 ATF_TC_BODY(timerfd_select_poll_kevent_immed, tc)
339 {
340 const struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 };
341 struct itimerspec its;
342 struct timeval tv;
343 struct stat st;
344 struct pollfd fds[1];
345 uint64_t val;
346 fd_set readfds, writefds, exceptfds;
347 int fd;
348 int kq;
349 struct kevent kev[1];
350
351 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)) >= 0);
352
353 ATF_REQUIRE((kq = kqueue()) >= 0);
354 EV_SET(&kev[0], fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
355 ATF_REQUIRE(kevent(kq, kev, 1, NULL, 0, &ts) == 0);
356
357 /*
358 * fd should be writable but not readable. Pass all of the
359 * event bits; we should only get back POLLOUT | POLLWRNORM.
360 * (It's writable only in so far as we'll get an error if we try.)
361 */
362 fds[0].fd = fd;
363 fds[0].events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI |
364 POLLOUT | POLLWRNORM | POLLWRBAND | POLLHUP;
365 fds[0].revents = 0;
366 ATF_REQUIRE(poll(fds, 1, 0) == 1);
367 ATF_REQUIRE(fds[0].revents == (POLLOUT | POLLWRNORM));
368
369 /*
370 * As above; fd should only be set in writefds upon return
371 * from the select() call.
372 */
373 FD_ZERO(&readfds);
374 FD_ZERO(&writefds);
375 FD_ZERO(&exceptfds);
376 tv.tv_sec = 0;
377 tv.tv_usec = 0;
378 FD_SET(fd, &readfds);
379 FD_SET(fd, &writefds);
380 FD_SET(fd, &exceptfds);
381 ATF_REQUIRE(select(fd + 1, &readfds, &writefds, &exceptfds, &tv) == 1);
382 ATF_REQUIRE(!FD_ISSET(fd, &readfds));
383 ATF_REQUIRE(FD_ISSET(fd, &writefds));
384 ATF_REQUIRE(!FD_ISSET(fd, &exceptfds));
385
386 /*
387 * Now set a one-shot half-second timer, wait for it to expire, and
388 * then check again.
389 */
390 memset(&its, 0, sizeof(its));
391 its.it_value.tv_sec = 0;
392 its.it_value.tv_nsec = 500000000;
393 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0);
394 ATF_REQUIRE(sleep(2) == 0);
395
396 /* Verify it actually fired via the stat() back-channel. */
397 ATF_REQUIRE(fstat(fd, &st) == 0);
398 ATF_REQUIRE(st.st_size == 1);
399
400 fds[0].fd = fd;
401 fds[0].events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI |
402 POLLOUT | POLLWRNORM | POLLWRBAND | POLLHUP;
403 fds[0].revents = 0;
404 ATF_REQUIRE(poll(fds, 1, 0) == 1);
405 ATF_REQUIRE(fds[0].revents == (POLLIN | POLLRDNORM |
406 POLLOUT | POLLWRNORM));
407
408 FD_ZERO(&readfds);
409 FD_ZERO(&writefds);
410 FD_ZERO(&exceptfds);
411 tv.tv_sec = 0;
412 tv.tv_usec = 0;
413 FD_SET(fd, &readfds);
414 FD_SET(fd, &writefds);
415 FD_SET(fd, &exceptfds);
416 ATF_REQUIRE(select(fd + 1, &readfds, &writefds, &exceptfds, &tv) == 2);
417 ATF_REQUIRE(FD_ISSET(fd, &readfds));
418 ATF_REQUIRE(FD_ISSET(fd, &writefds));
419 ATF_REQUIRE(!FD_ISSET(fd, &exceptfds));
420
421 /*
422 * Check that we get an EVFILT_READ event on fd.
423 */
424 memset(kev, 0, sizeof(kev));
425 ATF_REQUIRE(kevent(kq, NULL, 0, kev, 1, &ts) == 1);
426 ATF_REQUIRE(kev[0].ident == (uintptr_t)fd);
427 ATF_REQUIRE(kev[0].filter == EVFILT_READ);
428 ATF_REQUIRE((kev[0].flags & (EV_EOF | EV_ERROR)) == 0);
429 ATF_REQUIRE(kev[0].data == 1);
430
431 /*
432 * Read the timerfd to ensure we get the correct numnber of
433 * expirations.
434 */
435 ATF_REQUIRE(timerfd_read(fd, &val) == 0);
436 ATF_REQUIRE(val == 1);
437
438 /* And ensure that we would block if we tried again. */
439 ATF_REQUIRE_ERRNO(EAGAIN, timerfd_read(fd, &val) == -1);
440
441 (void) close(kq);
442 (void) close(fd);
443 }
444
445 /*****************************************************************************/
446
447 ATF_TC(timerfd_select_poll_kevent_block);
448 ATF_TC_HEAD(timerfd_select_poll_kevent_block, tc)
449 {
450 atf_tc_set_md_var(tc, "descr",
451 "validates select/poll/kevent behavior - blocking");
452 }
453 ATF_TC_BODY(timerfd_select_poll_kevent_block, tc)
454 {
455 const struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 };
456 struct timespec then, now;
457 struct pollfd fds[1];
458 fd_set readfds;
459 int fd;
460 int kq;
461 struct kevent kev[1];
462
463 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)) >= 0);
464
465 ATF_REQUIRE((kq = kqueue()) >= 0);
466 EV_SET(&kev[0], fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
467 ATF_REQUIRE(kevent(kq, kev, 1, NULL, 0, &ts) == 0);
468
469 /*
470 * For each of these tests, we do the following:
471 *
472 * - Get the current time.
473 * - Set a 1-second one-shot timer.
474 * - Block in the multiplexing call.
475 * - Get the current time and verify that the timer expiration
476 * interval has passed.
477 */
478
479 const struct itimerspec its = {
480 .it_value = { .tv_sec = 1, .tv_nsec = 0 },
481 .it_interval = { .tv_sec = 0, .tv_nsec = 0 },
482 };
483
484 /* poll(2) */
485 fds[0].fd = fd;
486 fds[0].events = POLLIN | POLLRDNORM;
487 fds[0].revents = 0;
488
489 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0);
490 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0);
491 ATF_REQUIRE(poll(fds, 1, INFTIM) == 1);
492 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0);
493 ATF_REQUIRE(fds[0].revents == (POLLIN | POLLRDNORM));
494 ATF_REQUIRE(now.tv_sec - then.tv_sec >= 1);
495
496 /* select(2) */
497 FD_ZERO(&readfds);
498 FD_SET(fd, &readfds);
499
500 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0);
501 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0);
502 ATF_REQUIRE(select(fd + 1, &readfds, NULL, NULL, NULL) == 1);
503 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0);
504 ATF_REQUIRE(FD_ISSET(fd, &readfds));
505 ATF_REQUIRE(now.tv_sec - then.tv_sec >= 1);
506
507 /* kevent(2) */
508 memset(kev, 0, sizeof(kev));
509 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0);
510 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0);
511 ATF_REQUIRE(kevent(kq, NULL, 0, kev, 1, NULL) == 1);
512 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0);
513 ATF_REQUIRE(kev[0].ident == (uintptr_t)fd);
514 ATF_REQUIRE(kev[0].filter == EVFILT_READ);
515 ATF_REQUIRE((kev[0].flags & (EV_EOF | EV_ERROR)) == 0);
516 ATF_REQUIRE(kev[0].data == 1);
517
518 (void) close(kq);
519 (void) close(fd);
520 }
521
522 /*****************************************************************************/
523
524 static void *
525 timerfd_restart_helper(void * const v)
526 {
527 struct helper_context * const ctx = v;
528
529 ATF_REQUIRE(wait_barrier(ctx));
530
531 /*
532 * Wait 5 seconds (that should give the main thread time to
533 * block), and then close the descriptor.
534 */
535 ATF_REQUIRE(sleep(5) == 0);
536 ATF_REQUIRE(close(ctx->fd) == 0);
537
538 return NULL;
539 }
540
541 ATF_TC(timerfd_restart);
542 ATF_TC_HEAD(timerfd_restart, tc)
543 {
544 atf_tc_set_md_var(tc, "descr",
545 "exercises the 'restart' fileop code path");
546 }
547 ATF_TC_BODY(timerfd_restart, tc)
548 {
549 struct timespec then, now, delta;
550 struct helper_context ctx;
551 uint64_t val;
552 pthread_t helper;
553 void *join_val;
554
555 init_helper_context(&ctx);
556
557 ATF_REQUIRE((ctx.fd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0);
558
559 const struct itimerspec its = {
560 .it_value = { .tv_sec = 60 * 60, .tv_nsec = 0 },
561 .it_interval = { .tv_sec = 0, .tv_nsec = 0 },
562 };
563 ATF_REQUIRE(timerfd_settime(ctx.fd, 0, &its, NULL) == 0);
564
565
566 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0);
567 ATF_REQUIRE(pthread_create(&helper, NULL,
568 timerfd_restart_helper, &ctx) == 0);
569
570 /*
571 * Wait for the helper to be ready, and then immediately block
572 * in read(). The helper will close the file, and we should get
573 * EBADF after a few seconds.
574 */
575 ATF_REQUIRE(wait_barrier(&ctx));
576 ATF_REQUIRE_ERRNO(EBADF, timerfd_read(ctx.fd, &val) == -1);
577 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0);
578
579 timespecsub(&now, &then, &delta);
580 ATF_REQUIRE(delta.tv_sec >= 5);
581
582 /* Reap the helper. */
583 ATF_REQUIRE(pthread_join(helper, &join_val) == 0);
584 }
585
586 /*****************************************************************************/
587
588 ATF_TP_ADD_TCS(tp)
589 {
590 ATF_TP_ADD_TC(tp, timerfd_create);
591 ATF_TP_ADD_TC(tp, timerfd_bogusfd);
592 ATF_TP_ADD_TC(tp, timerfd_block);
593 ATF_TP_ADD_TC(tp, timerfd_repeating);
594 ATF_TP_ADD_TC(tp, timerfd_abstime);
595 ATF_TP_ADD_TC(tp, timerfd_cancel_on_set_block);
596 ATF_TP_ADD_TC(tp, timerfd_cancel_on_set_immed);
597 ATF_TP_ADD_TC(tp, timerfd_select_poll_kevent_immed);
598 ATF_TP_ADD_TC(tp, timerfd_select_poll_kevent_block);
599 ATF_TP_ADD_TC(tp, timerfd_restart);
600
601 return atf_no_error();
602 }
603