Home | History | Annotate | Line # | Download | only in sys
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