xref: /netbsd-src/tests/lib/libc/sys/t_timerfd.c (revision 4b169a6ba595ae283ca507b26b15fdff40495b1c)
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