t_timerfd.c revision 1.5 1 /* $NetBSD: t_timerfd.c,v 1.5 2023/07/08 15:32:58 riastradh 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.5 2023/07/08 15:32:58 riastradh Exp $");
33
34 #include <sys/types.h>
35 #include <sys/event.h>
36 #include <sys/ioctl.h>
37 #include <sys/select.h>
38 #include <sys/stat.h>
39 #include <sys/syscall.h>
40 #include <sys/timerfd.h>
41 #include <errno.h>
42 #include <poll.h>
43 #include <pthread.h>
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <time.h>
47 #include <unistd.h>
48
49 #include <atf-c.h>
50
51 #include "isqemu.h"
52
53 struct helper_context {
54 int fd;
55
56 pthread_barrier_t barrier;
57 };
58
59 static void
60 init_helper_context(struct helper_context * const ctx)
61 {
62
63 memset(ctx, 0, sizeof(*ctx));
64
65 ATF_REQUIRE(pthread_barrier_init(&ctx->barrier, NULL, 2) == 0);
66 }
67
68 static bool
69 wait_barrier(struct helper_context * const ctx)
70 {
71 int rv = pthread_barrier_wait(&ctx->barrier);
72
73 return rv == 0 || rv == PTHREAD_BARRIER_SERIAL_THREAD;
74 }
75
76 static bool
77 check_value_against_bounds(uint64_t value, uint64_t lower, uint64_t upper)
78 {
79
80 /*
81 * If running under QEMU make sure the upper bound is large
82 * enough for the effect of kern/43997
83 */
84 if (isQEMU()) {
85 upper *= 4;
86 }
87
88 if (value < lower || value > upper) {
89 printf("val %" PRIu64 " not in [ %" PRIu64 ", %" PRIu64 " ]\n",
90 value, lower, upper);
91 }
92
93 return value >= lower && value <= upper;
94 }
95
96 /*****************************************************************************/
97
98 static int
99 timerfd_read(int fd, uint64_t *valp)
100 {
101 uint64_t val;
102
103 switch (read(fd, &val, sizeof(val))) {
104 case -1:
105 return -1;
106
107 case sizeof(val):
108 *valp = val;
109 return 0;
110
111 default:
112 /* ?? Should never happen. */
113 errno = EIO;
114 return -1;
115 }
116 }
117
118 /*****************************************************************************/
119
120 ATF_TC(timerfd_create);
121 ATF_TC_HEAD(timerfd_create, tc)
122 {
123 atf_tc_set_md_var(tc, "descr", "validates timerfd_create()");
124 }
125 ATF_TC_BODY(timerfd_create, tc)
126 {
127 int fd;
128
129 ATF_REQUIRE((fd = timerfd_create(CLOCK_REALTIME, 0)) >= 0);
130 (void) close(fd);
131
132 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0);
133 (void) close(fd);
134
135 ATF_REQUIRE_ERRNO(EINVAL,
136 (fd = timerfd_create(CLOCK_VIRTUAL, 0)) == -1);
137
138 ATF_REQUIRE_ERRNO(EINVAL,
139 (fd = timerfd_create(CLOCK_PROF, 0)) == -1);
140
141 ATF_REQUIRE_ERRNO(EINVAL,
142 (fd = timerfd_create(CLOCK_REALTIME,
143 ~(TFD_CLOEXEC | TFD_NONBLOCK))) == -1);
144 }
145
146 /*****************************************************************************/
147
148 ATF_TC(timerfd_bogusfd);
149 ATF_TC_HEAD(timerfd_bogusfd, tc)
150 {
151 atf_tc_set_md_var(tc, "descr",
152 "validates rejection of bogus fds by timerfd_{get,set}time()");
153 }
154 ATF_TC_BODY(timerfd_bogusfd, tc)
155 {
156 struct itimerspec its = { 0 };
157 int fd;
158
159 ATF_REQUIRE((fd = kqueue()) >= 0); /* arbitrary fd type */
160
161 ATF_REQUIRE_ERRNO(EINVAL,
162 timerfd_gettime(fd, &its) == -1);
163
164 its.it_value.tv_sec = 5;
165 ATF_REQUIRE_ERRNO(EINVAL,
166 timerfd_settime(fd, 0, &its, NULL) == -1);
167
168 (void) close(fd);
169 }
170
171 /*****************************************************************************/
172
173 ATF_TC(timerfd_block);
174 ATF_TC_HEAD(timerfd_block, tc)
175 {
176 atf_tc_set_md_var(tc, "descr", "validates blocking behavior");
177 }
178 ATF_TC_BODY(timerfd_block, tc)
179 {
180 struct timespec then, now, delta;
181 uint64_t val;
182 int fd;
183
184 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0);
185
186 const struct itimerspec its = {
187 .it_value = { .tv_sec = 1, .tv_nsec = 0 },
188 .it_interval = { .tv_sec = 0, .tv_nsec = 0 },
189 };
190
191 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0);
192 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0);
193 ATF_REQUIRE(timerfd_read(fd, &val) == 0);
194 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0);
195 ATF_REQUIRE(check_value_against_bounds(val, 1, 1));
196
197 timespecsub(&now, &then, &delta);
198 ATF_REQUIRE_MSG(check_value_against_bounds(delta.tv_sec, 1, 1),
199 "then=%jd.%09lu now=%jd.%09lu delta=%jd.%09lu",
200 (intmax_t)then.tv_sec, then.tv_nsec,
201 (intmax_t)now.tv_sec, now.tv_nsec,
202 (intmax_t)delta.tv_sec, delta.tv_nsec);
203
204 (void) close(fd);
205 }
206
207 /*****************************************************************************/
208
209 ATF_TC(timerfd_repeating);
210 ATF_TC_HEAD(timerfd_repeating, tc)
211 {
212 atf_tc_set_md_var(tc, "descr", "validates repeating timer behavior");
213 }
214 ATF_TC_BODY(timerfd_repeating, tc)
215 {
216 struct timespec then, now, delta;
217 uint64_t val;
218 int fd;
219
220 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC,
221 TFD_NONBLOCK)) >= 0);
222
223 const struct itimerspec its = {
224 .it_value = { .tv_sec = 0, .tv_nsec = 200000000 },
225 .it_interval = { .tv_sec = 0, .tv_nsec = 200000000 },
226 };
227
228 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0);
229 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0);
230 ATF_REQUIRE(sleep(1) == 0);
231 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0);
232 ATF_REQUIRE(timerfd_read(fd, &val) == 0);
233 /* allow some slop */
234 ATF_REQUIRE(check_value_against_bounds(val, 3, 5));
235
236 timespecsub(&now, &then, &delta);
237 ATF_REQUIRE_MSG(check_value_against_bounds(delta.tv_sec, 1, 1),
238 "then=%jd.%09lu now=%jd.%09lu delta=%jd.%09lu",
239 (intmax_t)then.tv_sec, then.tv_nsec,
240 (intmax_t)now.tv_sec, now.tv_nsec,
241 (intmax_t)delta.tv_sec, delta.tv_nsec);
242
243 (void) close(fd);
244 }
245
246 /*****************************************************************************/
247
248 ATF_TC(timerfd_abstime);
249 ATF_TC_HEAD(timerfd_abstime, tc)
250 {
251 atf_tc_set_md_var(tc, "descr", "validates specifying abstime");
252 }
253 ATF_TC_BODY(timerfd_abstime, tc)
254 {
255 struct timespec then, now, delta;
256 uint64_t val;
257 int fd;
258
259 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0);
260
261 struct itimerspec its = {
262 .it_value = { .tv_sec = 0, .tv_nsec = 0 },
263 .it_interval = { .tv_sec = 0, .tv_nsec = 0 },
264 };
265
266 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0);
267 its.it_value = then;
268 its.it_value.tv_sec += 1;
269 ATF_REQUIRE(timerfd_settime(fd, TFD_TIMER_ABSTIME, &its, NULL) == 0);
270 ATF_REQUIRE(timerfd_read(fd, &val) == 0);
271 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0);
272 ATF_REQUIRE(check_value_against_bounds(val, 1, 1));
273
274 timespecsub(&now, &then, &delta);
275 ATF_REQUIRE_MSG(check_value_against_bounds(delta.tv_sec, 1, 1),
276 "then=%jd.%09lu now=%jd.%09lu delta=%jd.%09lu",
277 (intmax_t)then.tv_sec, then.tv_nsec,
278 (intmax_t)now.tv_sec, now.tv_nsec,
279 (intmax_t)delta.tv_sec, delta.tv_nsec);
280
281 (void) close(fd);
282 }
283
284 /*****************************************************************************/
285
286 ATF_TC(timerfd_cancel_on_set_immed);
287 ATF_TC_HEAD(timerfd_cancel_on_set_immed, tc)
288 {
289 atf_tc_set_md_var(tc, "descr", "validates cancel-on-set - immediate");
290 atf_tc_set_md_var(tc, "require.user", "root");
291 }
292 ATF_TC_BODY(timerfd_cancel_on_set_immed, tc)
293 {
294 struct timespec now;
295 uint64_t val;
296 int fd;
297
298 ATF_REQUIRE((fd = timerfd_create(CLOCK_REALTIME, 0)) >= 0);
299
300 const struct itimerspec its = {
301 .it_value = { .tv_sec = 60 * 60, .tv_nsec = 0 },
302 .it_interval = { .tv_sec = 0, .tv_nsec = 0 },
303 };
304
305 ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &now) == 0);
306 ATF_REQUIRE(timerfd_settime(fd, TFD_TIMER_CANCEL_ON_SET,
307 &its, NULL) == 0);
308 ATF_REQUIRE(clock_settime(CLOCK_REALTIME, &now) == 0);
309 ATF_REQUIRE_ERRNO(ECANCELED, timerfd_read(fd, &val) == -1);
310
311 (void) close(fd);
312 }
313
314 /*****************************************************************************/
315
316 static void *
317 timerfd_cancel_on_set_block_helper(void * const v)
318 {
319 struct helper_context * const ctx = v;
320 struct timespec now;
321
322 ATF_REQUIRE(wait_barrier(ctx));
323
324 ATF_REQUIRE(sleep(2) == 0);
325 ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &now) == 0);
326 ATF_REQUIRE(clock_settime(CLOCK_REALTIME, &now) == 0);
327
328 return NULL;
329 }
330
331 ATF_TC(timerfd_cancel_on_set_block);
332 ATF_TC_HEAD(timerfd_cancel_on_set_block, tc)
333 {
334 atf_tc_set_md_var(tc, "descr", "validates cancel-on-set - blocking");
335 atf_tc_set_md_var(tc, "require.user", "root");
336 }
337 ATF_TC_BODY(timerfd_cancel_on_set_block, tc)
338 {
339 struct helper_context ctx;
340 pthread_t helper;
341 void *join_val;
342 uint64_t val;
343 int fd;
344
345 ATF_REQUIRE((fd = timerfd_create(CLOCK_REALTIME, 0)) >= 0);
346
347 const struct itimerspec its = {
348 .it_value = { .tv_sec = 60 * 60, .tv_nsec = 0 },
349 .it_interval = { .tv_sec = 0, .tv_nsec = 0 },
350 };
351
352 init_helper_context(&ctx);
353
354 ATF_REQUIRE(timerfd_settime(fd, TFD_TIMER_CANCEL_ON_SET,
355 &its, NULL) == 0);
356 ATF_REQUIRE(pthread_create(&helper, NULL,
357 timerfd_cancel_on_set_block_helper, &ctx) == 0);
358 ATF_REQUIRE(wait_barrier(&ctx));
359 ATF_REQUIRE_ERRNO(ECANCELED, timerfd_read(fd, &val) == -1);
360
361 ATF_REQUIRE(pthread_join(helper, &join_val) == 0);
362
363 (void) close(fd);
364 }
365
366 /*****************************************************************************/
367
368 ATF_TC(timerfd_select_poll_kevent_immed);
369 ATF_TC_HEAD(timerfd_select_poll_kevent_immed, tc)
370 {
371 atf_tc_set_md_var(tc, "descr",
372 "validates select/poll/kevent behavior - immediate return");
373 }
374 ATF_TC_BODY(timerfd_select_poll_kevent_immed, tc)
375 {
376 const struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 };
377 struct itimerspec its;
378 struct timeval tv;
379 struct stat st;
380 struct pollfd fds[1];
381 uint64_t val;
382 fd_set readfds, writefds, exceptfds;
383 int fd;
384 int kq;
385 struct kevent kev[1];
386
387 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)) >= 0);
388
389 ATF_REQUIRE((kq = kqueue()) >= 0);
390 EV_SET(&kev[0], fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
391 ATF_REQUIRE(kevent(kq, kev, 1, NULL, 0, &ts) == 0);
392
393 /*
394 * fd should be writable but not readable. Pass all of the
395 * event bits; we should only get back POLLOUT | POLLWRNORM.
396 * (It's writable only in so far as we'll get an error if we try.)
397 */
398 fds[0].fd = fd;
399 fds[0].events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI |
400 POLLOUT | POLLWRNORM | POLLWRBAND | POLLHUP;
401 fds[0].revents = 0;
402 ATF_REQUIRE(poll(fds, 1, 0) == 1);
403 ATF_REQUIRE(fds[0].revents == (POLLOUT | POLLWRNORM));
404
405 /*
406 * As above; fd should only be set in writefds upon return
407 * from the select() call.
408 */
409 FD_ZERO(&readfds);
410 FD_ZERO(&writefds);
411 FD_ZERO(&exceptfds);
412 tv.tv_sec = 0;
413 tv.tv_usec = 0;
414 FD_SET(fd, &readfds);
415 FD_SET(fd, &writefds);
416 FD_SET(fd, &exceptfds);
417 ATF_REQUIRE(select(fd + 1, &readfds, &writefds, &exceptfds, &tv) == 1);
418 ATF_REQUIRE(!FD_ISSET(fd, &readfds));
419 ATF_REQUIRE(FD_ISSET(fd, &writefds));
420 ATF_REQUIRE(!FD_ISSET(fd, &exceptfds));
421
422 /*
423 * Now set a one-shot half-second timer, wait for it to expire, and
424 * then check again.
425 */
426 memset(&its, 0, sizeof(its));
427 its.it_value.tv_sec = 0;
428 its.it_value.tv_nsec = 500000000;
429 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0);
430 ATF_REQUIRE(sleep(2) == 0);
431
432 /* Verify it actually fired via the stat() back-channel. */
433 ATF_REQUIRE(fstat(fd, &st) == 0);
434 ATF_REQUIRE(st.st_size == 1);
435
436 fds[0].fd = fd;
437 fds[0].events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI |
438 POLLOUT | POLLWRNORM | POLLWRBAND | POLLHUP;
439 fds[0].revents = 0;
440 ATF_REQUIRE(poll(fds, 1, 0) == 1);
441 ATF_REQUIRE(fds[0].revents == (POLLIN | POLLRDNORM |
442 POLLOUT | POLLWRNORM));
443
444 FD_ZERO(&readfds);
445 FD_ZERO(&writefds);
446 FD_ZERO(&exceptfds);
447 tv.tv_sec = 0;
448 tv.tv_usec = 0;
449 FD_SET(fd, &readfds);
450 FD_SET(fd, &writefds);
451 FD_SET(fd, &exceptfds);
452 ATF_REQUIRE(select(fd + 1, &readfds, &writefds, &exceptfds, &tv) == 2);
453 ATF_REQUIRE(FD_ISSET(fd, &readfds));
454 ATF_REQUIRE(FD_ISSET(fd, &writefds));
455 ATF_REQUIRE(!FD_ISSET(fd, &exceptfds));
456
457 /*
458 * Check that we get an EVFILT_READ event on fd.
459 */
460 memset(kev, 0, sizeof(kev));
461 ATF_REQUIRE(kevent(kq, NULL, 0, kev, 1, &ts) == 1);
462 ATF_REQUIRE(kev[0].ident == (uintptr_t)fd);
463 ATF_REQUIRE(kev[0].filter == EVFILT_READ);
464 ATF_REQUIRE((kev[0].flags & (EV_EOF | EV_ERROR)) == 0);
465 ATF_REQUIRE(kev[0].data == 1);
466
467 /*
468 * Read the timerfd to ensure we get the correct numnber of
469 * expirations.
470 */
471 ATF_REQUIRE(timerfd_read(fd, &val) == 0);
472 ATF_REQUIRE(val == 1);
473
474 /* And ensure that we would block if we tried again. */
475 ATF_REQUIRE_ERRNO(EAGAIN, timerfd_read(fd, &val) == -1);
476
477 (void) close(kq);
478 (void) close(fd);
479 }
480
481 /*****************************************************************************/
482
483 ATF_TC(timerfd_select_poll_kevent_block);
484 ATF_TC_HEAD(timerfd_select_poll_kevent_block, tc)
485 {
486 atf_tc_set_md_var(tc, "descr",
487 "validates select/poll/kevent behavior - blocking");
488 }
489 ATF_TC_BODY(timerfd_select_poll_kevent_block, tc)
490 {
491 const struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 };
492 struct timespec then, now;
493 struct pollfd fds[1];
494 fd_set readfds;
495 int fd;
496 int kq;
497 struct kevent kev[1];
498
499 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)) >= 0);
500
501 ATF_REQUIRE((kq = kqueue()) >= 0);
502 EV_SET(&kev[0], fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
503 ATF_REQUIRE(kevent(kq, kev, 1, NULL, 0, &ts) == 0);
504
505 /*
506 * For each of these tests, we do the following:
507 *
508 * - Get the current time.
509 * - Set a 1-second one-shot timer.
510 * - Block in the multiplexing call.
511 * - Get the current time and verify that the timer expiration
512 * interval has passed.
513 */
514
515 const struct itimerspec its = {
516 .it_value = { .tv_sec = 1, .tv_nsec = 0 },
517 .it_interval = { .tv_sec = 0, .tv_nsec = 0 },
518 };
519
520 /* poll(2) */
521 fds[0].fd = fd;
522 fds[0].events = POLLIN | POLLRDNORM;
523 fds[0].revents = 0;
524
525 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0);
526 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0);
527 ATF_REQUIRE(poll(fds, 1, INFTIM) == 1);
528 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0);
529 ATF_REQUIRE(fds[0].revents == (POLLIN | POLLRDNORM));
530 ATF_REQUIRE(now.tv_sec - then.tv_sec >= 1);
531
532 /* select(2) */
533 FD_ZERO(&readfds);
534 FD_SET(fd, &readfds);
535
536 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0);
537 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0);
538 ATF_REQUIRE(select(fd + 1, &readfds, NULL, NULL, NULL) == 1);
539 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0);
540 ATF_REQUIRE(FD_ISSET(fd, &readfds));
541 ATF_REQUIRE(now.tv_sec - then.tv_sec >= 1);
542
543 /* kevent(2) */
544 memset(kev, 0, sizeof(kev));
545 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0);
546 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0);
547 ATF_REQUIRE(kevent(kq, NULL, 0, kev, 1, NULL) == 1);
548 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0);
549 ATF_REQUIRE(kev[0].ident == (uintptr_t)fd);
550 ATF_REQUIRE(kev[0].filter == EVFILT_READ);
551 ATF_REQUIRE((kev[0].flags & (EV_EOF | EV_ERROR)) == 0);
552 ATF_REQUIRE(kev[0].data == 1);
553
554 (void) close(kq);
555 (void) close(fd);
556 }
557
558 /*****************************************************************************/
559
560 static void *
561 timerfd_restart_helper(void * const v)
562 {
563 struct helper_context * const ctx = v;
564
565 ATF_REQUIRE(wait_barrier(ctx));
566
567 /*
568 * Wait 5 seconds (that should give the main thread time to
569 * block), and then close the descriptor.
570 */
571 ATF_REQUIRE(sleep(5) == 0);
572 ATF_REQUIRE(close(ctx->fd) == 0);
573
574 return NULL;
575 }
576
577 ATF_TC(timerfd_restart);
578 ATF_TC_HEAD(timerfd_restart, tc)
579 {
580 atf_tc_set_md_var(tc, "descr",
581 "exercises the 'restart' fileop code path");
582 }
583 ATF_TC_BODY(timerfd_restart, tc)
584 {
585 struct timespec then, now, delta;
586 struct helper_context ctx;
587 uint64_t val;
588 pthread_t helper;
589 void *join_val;
590
591 init_helper_context(&ctx);
592
593 ATF_REQUIRE((ctx.fd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0);
594
595 const struct itimerspec its = {
596 .it_value = { .tv_sec = 60 * 60, .tv_nsec = 0 },
597 .it_interval = { .tv_sec = 0, .tv_nsec = 0 },
598 };
599 ATF_REQUIRE(timerfd_settime(ctx.fd, 0, &its, NULL) == 0);
600
601
602 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0);
603 ATF_REQUIRE(pthread_create(&helper, NULL,
604 timerfd_restart_helper, &ctx) == 0);
605
606 /*
607 * Wait for the helper to be ready, and then immediately block
608 * in read(). The helper will close the file, and we should get
609 * EBADF after a few seconds.
610 */
611 ATF_REQUIRE(wait_barrier(&ctx));
612 ATF_REQUIRE_ERRNO(EBADF, timerfd_read(ctx.fd, &val) == -1);
613 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0);
614
615 timespecsub(&now, &then, &delta);
616 ATF_REQUIRE(delta.tv_sec >= 5);
617
618 /* Reap the helper. */
619 ATF_REQUIRE(pthread_join(helper, &join_val) == 0);
620 }
621
622 /*****************************************************************************/
623
624 ATF_TC(timerfd_fcntl);
625 ATF_TC_HEAD(timerfd_fcntl, tc)
626 {
627 atf_tc_set_md_var(tc, "descr",
628 "validates fcntl behavior");
629 }
630
631 ATF_TC_BODY(timerfd_fcntl, tc)
632 {
633 int tfd;
634 int val;
635
636 ATF_REQUIRE((tfd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0);
637 ATF_REQUIRE((fcntl(tfd, F_GETFL) & O_NONBLOCK) == 0);
638 ATF_REQUIRE(fcntl(tfd, F_SETFL, O_NONBLOCK) == 0);
639 ATF_REQUIRE((fcntl(tfd, F_GETFL) & O_NONBLOCK) != 0);
640 ATF_REQUIRE((fcntl(tfd, F_GETFD) & FD_CLOEXEC) == 0);
641
642 /* If the timer hasn't fired, there is no readable data. */
643 ATF_REQUIRE(ioctl(tfd, FIONREAD, &val) == 0);
644 ATF_REQUIRE(val == 0);
645
646 ATF_REQUIRE_ERRNO(ENOTTY, ioctl(tfd, FIONWRITE, &val) == -1);
647 ATF_REQUIRE_ERRNO(ENOTTY, ioctl(tfd, FIONSPACE, &val) == -1);
648 (void)close(tfd);
649
650 ATF_REQUIRE((tfd = timerfd_create(CLOCK_MONOTONIC,
651 TFD_NONBLOCK | TFD_CLOEXEC)) >= 0);
652 ATF_REQUIRE((fcntl(tfd, F_GETFL) & ~O_ACCMODE) == O_NONBLOCK);
653 ATF_REQUIRE((fcntl(tfd, F_GETFD) & FD_CLOEXEC) != 0);
654 ATF_REQUIRE(fcntl(tfd, F_SETFD, 0) == 0);
655 ATF_REQUIRE((fcntl(tfd, F_GETFD) & FD_CLOEXEC) == 0);
656 ATF_REQUIRE(fcntl(tfd, F_SETFD, FD_CLOEXEC) == 0);
657 ATF_REQUIRE((fcntl(tfd, F_GETFD) & FD_CLOEXEC) != 0);
658 (void)close(tfd);
659 }
660
661 /*****************************************************************************/
662
663 ATF_TP_ADD_TCS(tp)
664 {
665 ATF_TP_ADD_TC(tp, timerfd_create);
666 ATF_TP_ADD_TC(tp, timerfd_bogusfd);
667 ATF_TP_ADD_TC(tp, timerfd_block);
668 ATF_TP_ADD_TC(tp, timerfd_repeating);
669 ATF_TP_ADD_TC(tp, timerfd_abstime);
670 ATF_TP_ADD_TC(tp, timerfd_cancel_on_set_block);
671 ATF_TP_ADD_TC(tp, timerfd_cancel_on_set_immed);
672 ATF_TP_ADD_TC(tp, timerfd_select_poll_kevent_immed);
673 ATF_TP_ADD_TC(tp, timerfd_select_poll_kevent_block);
674 ATF_TP_ADD_TC(tp, timerfd_restart);
675 ATF_TP_ADD_TC(tp, timerfd_fcntl);
676
677 return atf_no_error();
678 }
679