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