1 /* $NetBSD: t_timerfd.c,v 1.12 2025/04/16 01:32:48 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.12 2025/04/16 01:32:48 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 /* 228 * Try the same with an absolute time near now (unless 229 * that makes it a valid time, in case 0). 230 */ 231 if (i == 0) 232 continue; 233 its.it_value = einval_its[i].it_value; 234 its.it_value.tv_sec += now.tv_sec; 235 its.it_interval = einval_its[i].it_interval; 236 ATF_CHECK_ERRNO(EINVAL, 237 timerfd_settime(fd, TFD_TIMER_ABSTIME, &its, NULL) == -1); 238 } 239 240 /* Wait up to 2sec to make sure no timer got set anyway. */ 241 FD_ZERO(&readfds); 242 FD_SET(fd, &readfds); 243 RL(select(fd + 1, &readfds, NULL, NULL, &(struct timeval){2, 0})); 244 ATF_CHECK(!FD_ISSET(fd, &readfds)); 245 ATF_CHECK_ERRNO(EAGAIN, timerfd_read(fd, &val) == -1); 246 247 RL(close(fd)); 248 } 249 250 /*****************************************************************************/ 251 252 ATF_TC(timerfd_past); 253 ATF_TC_HEAD(timerfd_past, tc) 254 { 255 atf_tc_set_md_var(tc, "descr", "validates trigger on past time"); 256 } 257 ATF_TC_BODY(timerfd_past, tc) 258 { 259 struct itimerspec its = {.it_value = {-1, 0}, .it_interval = {0, 0}}; 260 struct timespec then, now, delta; 261 uint64_t val; 262 int fd; 263 264 RL(fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)); 265 266 RL(clock_gettime(CLOCK_MONOTONIC, &then)); 267 timespecadd(&then, &its.it_value, &its.it_value); 268 RL(timerfd_settime(fd, TFD_TIMER_ABSTIME, &its, NULL)); 269 270 /* 271 * Wait for one tick to pass. 272 * 273 * XXX Having to do this seems silly, but it matches Linux, so. 274 */ 275 RL(clock_nanosleep(CLOCK_MONOTONIC, 0, &(const struct timespec){0, 1}, 276 NULL)); 277 278 RL(timerfd_read(fd, &val)); 279 RL(clock_gettime(CLOCK_MONOTONIC, &now)); 280 ATF_REQUIRE(check_value_against_bounds(val, 1, 1)); 281 282 timespecsub(&now, &then, &delta); 283 ATF_CHECK_MSG(check_value_against_bounds(delta.tv_sec, 0, 0), 284 "then=%jd.%09lu now=%jd.%09lu delta=%jd.%09lu", 285 (intmax_t)then.tv_sec, then.tv_nsec, 286 (intmax_t)now.tv_sec, now.tv_nsec, 287 (intmax_t)delta.tv_sec, delta.tv_nsec); 288 289 RL(close(fd)); 290 } 291 292 /*****************************************************************************/ 293 294 ATF_TC(timerfd_block); 295 ATF_TC_HEAD(timerfd_block, tc) 296 { 297 atf_tc_set_md_var(tc, "descr", "validates blocking behavior"); 298 } 299 ATF_TC_BODY(timerfd_block, tc) 300 { 301 struct timespec then, now, delta; 302 uint64_t val; 303 int fd; 304 305 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0); 306 307 struct itimerspec oits; 308 const struct itimerspec its = { 309 .it_value = { .tv_sec = 1, .tv_nsec = 0 }, 310 .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, 311 }; 312 313 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 314 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0); 315 ATF_REQUIRE(timerfd_settime(fd, 0, &its, &oits) == 0); 316 ATF_CHECK_MSG(timespeccmp(&oits.it_value, &its.it_value, <=), 317 "timerfd_settime returned %jd.%09lu remaining," 318 " expected at most %jd.%09lu", 319 (intmax_t)oits.it_value.tv_sec, oits.it_value.tv_nsec, 320 (intmax_t)its.it_value.tv_sec, its.it_value.tv_nsec); 321 ATF_REQUIRE(timerfd_read(fd, &val) == 0); 322 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 323 ATF_REQUIRE(check_value_against_bounds(val, 1, 1)); 324 325 timespecsub(&now, &then, &delta); 326 ATF_REQUIRE_MSG(check_value_against_bounds(delta.tv_sec, 1, 1), 327 "then=%jd.%09lu now=%jd.%09lu delta=%jd.%09lu", 328 (intmax_t)then.tv_sec, then.tv_nsec, 329 (intmax_t)now.tv_sec, now.tv_nsec, 330 (intmax_t)delta.tv_sec, delta.tv_nsec); 331 332 (void) close(fd); 333 } 334 335 /*****************************************************************************/ 336 337 ATF_TC(timerfd_repeating); 338 ATF_TC_HEAD(timerfd_repeating, tc) 339 { 340 atf_tc_set_md_var(tc, "descr", "validates repeating timer behavior"); 341 } 342 ATF_TC_BODY(timerfd_repeating, tc) 343 { 344 struct timespec then, now, delta; 345 uint64_t val; 346 int fd; 347 348 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, 349 TFD_NONBLOCK)) >= 0); 350 351 const struct itimerspec its = { 352 .it_value = { .tv_sec = 0, .tv_nsec = 200000000 }, 353 .it_interval = { .tv_sec = 0, .tv_nsec = 200000000 }, 354 }; 355 356 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 357 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0); 358 ATF_REQUIRE(sleep(1) == 0); 359 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 360 ATF_REQUIRE(timerfd_read(fd, &val) == 0); 361 /* allow some slop */ 362 ATF_REQUIRE(check_value_against_bounds(val, 3, 5)); 363 364 timespecsub(&now, &then, &delta); 365 ATF_REQUIRE_MSG(check_value_against_bounds(delta.tv_sec, 1, 1), 366 "then=%jd.%09lu now=%jd.%09lu delta=%jd.%09lu", 367 (intmax_t)then.tv_sec, then.tv_nsec, 368 (intmax_t)now.tv_sec, now.tv_nsec, 369 (intmax_t)delta.tv_sec, delta.tv_nsec); 370 371 (void) close(fd); 372 } 373 374 /*****************************************************************************/ 375 376 ATF_TC(timerfd_abstime); 377 ATF_TC_HEAD(timerfd_abstime, tc) 378 { 379 atf_tc_set_md_var(tc, "descr", "validates specifying abstime"); 380 } 381 ATF_TC_BODY(timerfd_abstime, tc) 382 { 383 struct timespec then, now, delta; 384 uint64_t val; 385 int fd; 386 387 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0); 388 389 struct itimerspec oits, its = { 390 .it_value = { .tv_sec = 0, .tv_nsec = 0 }, 391 .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, 392 }; 393 394 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 395 delta = (struct timespec){1, 0}; 396 timespecadd(&then, &delta, &its.it_value); 397 ATF_REQUIRE(timerfd_settime(fd, TFD_TIMER_ABSTIME, &its, NULL) == 0); 398 ATF_REQUIRE(timerfd_settime(fd, TFD_TIMER_ABSTIME, &its, &oits) == 0); 399 timespecadd(&delta, (&(const struct timespec){2, 0}), /* tick slop */ 400 &delta); 401 ATF_CHECK_MSG(timespeccmp(&oits.it_value, &delta, <=), 402 "timerfd_settime returned %jd.%09lu remaining," 403 " expected at most %jd.%09lu", 404 (intmax_t)oits.it_value.tv_sec, oits.it_value.tv_nsec, 405 (intmax_t)delta.tv_sec, delta.tv_nsec); 406 ATF_REQUIRE(timerfd_read(fd, &val) == 0); 407 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 408 ATF_REQUIRE(check_value_against_bounds(val, 1, 1)); 409 410 timespecsub(&now, &then, &delta); 411 ATF_REQUIRE_MSG(check_value_against_bounds(delta.tv_sec, 1, 1), 412 "then=%jd.%09lu now=%jd.%09lu delta=%jd.%09lu", 413 (intmax_t)then.tv_sec, then.tv_nsec, 414 (intmax_t)now.tv_sec, now.tv_nsec, 415 (intmax_t)delta.tv_sec, delta.tv_nsec); 416 417 (void) close(fd); 418 } 419 420 /*****************************************************************************/ 421 422 ATF_TC(timerfd_cancel_on_set_immed); 423 ATF_TC_HEAD(timerfd_cancel_on_set_immed, tc) 424 { 425 atf_tc_set_md_var(tc, "descr", "validates cancel-on-set - immediate"); 426 atf_tc_set_md_var(tc, "require.user", "root"); 427 } 428 ATF_TC_BODY(timerfd_cancel_on_set_immed, tc) 429 { 430 struct timespec now; 431 uint64_t val; 432 int fd; 433 434 ATF_REQUIRE((fd = timerfd_create(CLOCK_REALTIME, 0)) >= 0); 435 436 const struct itimerspec its = { 437 .it_value = { .tv_sec = 60 * 60, .tv_nsec = 0 }, 438 .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, 439 }; 440 441 ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &now) == 0); 442 ATF_REQUIRE(timerfd_settime(fd, TFD_TIMER_CANCEL_ON_SET, 443 &its, NULL) == 0); 444 ATF_REQUIRE(clock_settime(CLOCK_REALTIME, &now) == 0); 445 ATF_REQUIRE_ERRNO(ECANCELED, timerfd_read(fd, &val) == -1); 446 447 (void) close(fd); 448 } 449 450 /*****************************************************************************/ 451 452 static void * 453 timerfd_cancel_on_set_block_helper(void * const v) 454 { 455 struct helper_context * const ctx = v; 456 struct timespec now; 457 458 ATF_REQUIRE(wait_barrier(ctx)); 459 460 ATF_REQUIRE(sleep(2) == 0); 461 ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &now) == 0); 462 ATF_REQUIRE(clock_settime(CLOCK_REALTIME, &now) == 0); 463 464 return NULL; 465 } 466 467 ATF_TC(timerfd_cancel_on_set_block); 468 ATF_TC_HEAD(timerfd_cancel_on_set_block, tc) 469 { 470 atf_tc_set_md_var(tc, "descr", "validates cancel-on-set - blocking"); 471 atf_tc_set_md_var(tc, "require.user", "root"); 472 } 473 ATF_TC_BODY(timerfd_cancel_on_set_block, tc) 474 { 475 struct helper_context ctx; 476 pthread_t helper; 477 void *join_val; 478 uint64_t val; 479 int fd; 480 481 ATF_REQUIRE((fd = timerfd_create(CLOCK_REALTIME, 0)) >= 0); 482 483 const struct itimerspec its = { 484 .it_value = { .tv_sec = 60 * 60, .tv_nsec = 0 }, 485 .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, 486 }; 487 488 init_helper_context(&ctx); 489 490 ATF_REQUIRE(timerfd_settime(fd, TFD_TIMER_CANCEL_ON_SET, 491 &its, NULL) == 0); 492 ATF_REQUIRE(pthread_create(&helper, NULL, 493 timerfd_cancel_on_set_block_helper, &ctx) == 0); 494 ATF_REQUIRE(wait_barrier(&ctx)); 495 ATF_REQUIRE_ERRNO(ECANCELED, timerfd_read(fd, &val) == -1); 496 497 ATF_REQUIRE(pthread_join(helper, &join_val) == 0); 498 499 (void) close(fd); 500 } 501 502 /*****************************************************************************/ 503 504 ATF_TC(timerfd_select_poll_kevent_immed); 505 ATF_TC_HEAD(timerfd_select_poll_kevent_immed, tc) 506 { 507 atf_tc_set_md_var(tc, "descr", 508 "validates select/poll/kevent behavior - immediate return"); 509 } 510 ATF_TC_BODY(timerfd_select_poll_kevent_immed, tc) 511 { 512 const struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; 513 struct itimerspec its; 514 struct timeval tv; 515 struct stat st; 516 struct pollfd fds[1]; 517 uint64_t val; 518 fd_set readfds, writefds, exceptfds; 519 int fd; 520 int kq; 521 struct kevent kev[1]; 522 523 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)) >= 0); 524 525 ATF_REQUIRE((kq = kqueue()) >= 0); 526 EV_SET(&kev[0], fd, EVFILT_READ, EV_ADD, 0, 0, NULL); 527 ATF_REQUIRE(kevent(kq, kev, 1, NULL, 0, &ts) == 0); 528 EV_SET(&kev[0], fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL); 529 ATF_CHECK_ERRNO(EINVAL, kevent(kq, kev, 1, NULL, 0, &ts) == -1); 530 531 /* 532 * fd should not be ready for anything. Pass all of the event 533 * bits; we should get back nothing. 534 */ 535 fds[0].fd = fd; 536 fds[0].events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI | 537 POLLOUT | POLLWRNORM | POLLWRBAND | POLLHUP; 538 fds[0].revents = 0; 539 ATF_REQUIRE(poll(fds, 1, 0) == 0); 540 541 /* 542 * As above; fd should not be set on return from the select() 543 * call. 544 */ 545 FD_ZERO(&readfds); 546 FD_ZERO(&writefds); 547 FD_ZERO(&exceptfds); 548 tv.tv_sec = 0; 549 tv.tv_usec = 0; 550 FD_SET(fd, &readfds); 551 FD_SET(fd, &writefds); 552 FD_SET(fd, &exceptfds); 553 ATF_REQUIRE(select(fd + 1, &readfds, &writefds, &exceptfds, &tv) == 0); 554 ATF_REQUIRE(!FD_ISSET(fd, &readfds)); 555 ATF_REQUIRE(!FD_ISSET(fd, &writefds)); 556 ATF_REQUIRE(!FD_ISSET(fd, &exceptfds)); 557 558 /* 559 * Now set a one-shot half-second timer, wait for it to expire, and 560 * then check again. 561 */ 562 memset(&its, 0, sizeof(its)); 563 its.it_value.tv_sec = 0; 564 its.it_value.tv_nsec = 500000000; 565 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0); 566 ATF_REQUIRE(sleep(2) == 0); 567 568 /* Verify it actually fired via the stat() back-channel. */ 569 ATF_REQUIRE(fstat(fd, &st) == 0); 570 ATF_REQUIRE(st.st_size == 1); 571 572 fds[0].fd = fd; 573 fds[0].events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI | 574 POLLOUT | POLLWRNORM | POLLWRBAND | POLLHUP; 575 fds[0].revents = 0; 576 ATF_REQUIRE(poll(fds, 1, 0) == 1); 577 ATF_REQUIRE(fds[0].revents == (POLLIN | POLLRDNORM)); 578 579 FD_ZERO(&readfds); 580 FD_ZERO(&writefds); 581 FD_ZERO(&exceptfds); 582 tv.tv_sec = 0; 583 tv.tv_usec = 0; 584 FD_SET(fd, &readfds); 585 FD_SET(fd, &writefds); 586 FD_SET(fd, &exceptfds); 587 ATF_REQUIRE(select(fd + 1, &readfds, &writefds, &exceptfds, &tv) == 1); 588 ATF_REQUIRE(FD_ISSET(fd, &readfds)); 589 ATF_REQUIRE(!FD_ISSET(fd, &writefds)); 590 ATF_REQUIRE(!FD_ISSET(fd, &exceptfds)); 591 592 /* 593 * Check that we get an EVFILT_READ event on fd. 594 */ 595 memset(kev, 0, sizeof(kev)); 596 ATF_REQUIRE(kevent(kq, NULL, 0, kev, 1, &ts) == 1); 597 ATF_REQUIRE(kev[0].ident == (uintptr_t)fd); 598 ATF_REQUIRE(kev[0].filter == EVFILT_READ); 599 ATF_REQUIRE((kev[0].flags & (EV_EOF | EV_ERROR)) == 0); 600 ATF_REQUIRE(kev[0].data == 1); 601 602 /* 603 * Read the timerfd to ensure we get the correct numnber of 604 * expirations. 605 */ 606 ATF_REQUIRE(timerfd_read(fd, &val) == 0); 607 ATF_REQUIRE(val == 1); 608 609 /* And ensure that we would block if we tried again. */ 610 ATF_REQUIRE_ERRNO(EAGAIN, timerfd_read(fd, &val) == -1); 611 612 (void) close(kq); 613 (void) close(fd); 614 } 615 616 /*****************************************************************************/ 617 618 ATF_TC(timerfd_select_poll_kevent_block); 619 ATF_TC_HEAD(timerfd_select_poll_kevent_block, tc) 620 { 621 atf_tc_set_md_var(tc, "descr", 622 "validates select/poll/kevent behavior - blocking"); 623 } 624 ATF_TC_BODY(timerfd_select_poll_kevent_block, tc) 625 { 626 const struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; 627 struct timespec then, now; 628 struct pollfd fds[1]; 629 fd_set readfds; 630 int fd; 631 int kq; 632 struct kevent kev[1]; 633 634 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)) >= 0); 635 636 ATF_REQUIRE((kq = kqueue()) >= 0); 637 EV_SET(&kev[0], fd, EVFILT_READ, EV_ADD, 0, 0, NULL); 638 ATF_REQUIRE(kevent(kq, kev, 1, NULL, 0, &ts) == 0); 639 640 /* 641 * For each of these tests, we do the following: 642 * 643 * - Get the current time. 644 * - Set a 1-second one-shot timer. 645 * - Block in the multiplexing call. 646 * - Get the current time and verify that the timer expiration 647 * interval has passed. 648 */ 649 650 const struct itimerspec its = { 651 .it_value = { .tv_sec = 1, .tv_nsec = 0 }, 652 .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, 653 }; 654 655 /* poll(2) */ 656 fds[0].fd = fd; 657 fds[0].events = POLLIN | POLLRDNORM; 658 fds[0].revents = 0; 659 660 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 661 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0); 662 ATF_REQUIRE(poll(fds, 1, INFTIM) == 1); 663 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 664 ATF_REQUIRE(fds[0].revents == (POLLIN | POLLRDNORM)); 665 ATF_REQUIRE(now.tv_sec - then.tv_sec >= 1); 666 667 /* select(2) */ 668 FD_ZERO(&readfds); 669 FD_SET(fd, &readfds); 670 671 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 672 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0); 673 ATF_REQUIRE(select(fd + 1, &readfds, NULL, NULL, NULL) == 1); 674 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 675 ATF_REQUIRE(FD_ISSET(fd, &readfds)); 676 ATF_REQUIRE(now.tv_sec - then.tv_sec >= 1); 677 678 /* kevent(2) */ 679 memset(kev, 0, sizeof(kev)); 680 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 681 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0); 682 ATF_REQUIRE(kevent(kq, NULL, 0, kev, 1, NULL) == 1); 683 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 684 ATF_REQUIRE(kev[0].ident == (uintptr_t)fd); 685 ATF_REQUIRE(kev[0].filter == EVFILT_READ); 686 ATF_REQUIRE((kev[0].flags & (EV_EOF | EV_ERROR)) == 0); 687 ATF_REQUIRE(kev[0].data == 1); 688 689 (void) close(kq); 690 (void) close(fd); 691 } 692 693 /*****************************************************************************/ 694 695 static void * 696 timerfd_restart_helper(void * const v) 697 { 698 struct helper_context * const ctx = v; 699 700 ATF_REQUIRE(wait_barrier(ctx)); 701 702 /* 703 * Wait 5 seconds (that should give the main thread time to 704 * block), and then close the descriptor. 705 */ 706 ATF_REQUIRE(sleep(5) == 0); 707 ATF_REQUIRE(close(ctx->fd) == 0); 708 709 return NULL; 710 } 711 712 ATF_TC(timerfd_restart); 713 ATF_TC_HEAD(timerfd_restart, tc) 714 { 715 atf_tc_set_md_var(tc, "descr", 716 "exercises the 'restart' fileop code path"); 717 } 718 ATF_TC_BODY(timerfd_restart, tc) 719 { 720 struct timespec then, now, delta; 721 struct helper_context ctx; 722 uint64_t val; 723 pthread_t helper; 724 void *join_val; 725 726 init_helper_context(&ctx); 727 728 ATF_REQUIRE((ctx.fd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0); 729 730 const struct itimerspec its = { 731 .it_value = { .tv_sec = 60 * 60, .tv_nsec = 0 }, 732 .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, 733 }; 734 ATF_REQUIRE(timerfd_settime(ctx.fd, 0, &its, NULL) == 0); 735 736 737 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 738 ATF_REQUIRE(pthread_create(&helper, NULL, 739 timerfd_restart_helper, &ctx) == 0); 740 741 /* 742 * Wait for the helper to be ready, and then immediately block 743 * in read(). The helper will close the file, and we should get 744 * EBADF after a few seconds. 745 */ 746 ATF_REQUIRE(wait_barrier(&ctx)); 747 ATF_REQUIRE_ERRNO(EBADF, timerfd_read(ctx.fd, &val) == -1); 748 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 749 750 timespecsub(&now, &then, &delta); 751 ATF_REQUIRE(delta.tv_sec >= 5); 752 753 /* Reap the helper. */ 754 ATF_REQUIRE(pthread_join(helper, &join_val) == 0); 755 } 756 757 /*****************************************************************************/ 758 759 ATF_TC(timerfd_fcntl); 760 ATF_TC_HEAD(timerfd_fcntl, tc) 761 { 762 atf_tc_set_md_var(tc, "descr", 763 "validates fcntl behavior"); 764 } 765 766 ATF_TC_BODY(timerfd_fcntl, tc) 767 { 768 int tfd; 769 int val; 770 771 ATF_REQUIRE((tfd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0); 772 ATF_REQUIRE((fcntl(tfd, F_GETFL) & O_NONBLOCK) == 0); 773 ATF_REQUIRE(fcntl(tfd, F_SETFL, O_NONBLOCK) == 0); 774 ATF_REQUIRE((fcntl(tfd, F_GETFL) & O_NONBLOCK) != 0); 775 ATF_REQUIRE((fcntl(tfd, F_GETFD) & FD_CLOEXEC) == 0); 776 777 /* If the timer hasn't fired, there is no readable data. */ 778 ATF_REQUIRE(ioctl(tfd, FIONREAD, &val) == 0); 779 ATF_REQUIRE(val == 0); 780 781 ATF_REQUIRE_ERRNO(ENOTTY, ioctl(tfd, FIONWRITE, &val) == -1); 782 ATF_REQUIRE_ERRNO(ENOTTY, ioctl(tfd, FIONSPACE, &val) == -1); 783 (void)close(tfd); 784 785 ATF_REQUIRE((tfd = timerfd_create(CLOCK_MONOTONIC, 786 TFD_NONBLOCK | TFD_CLOEXEC)) >= 0); 787 ATF_REQUIRE((fcntl(tfd, F_GETFL) & ~O_ACCMODE) == O_NONBLOCK); 788 ATF_REQUIRE((fcntl(tfd, F_GETFD) & FD_CLOEXEC) != 0); 789 ATF_REQUIRE(fcntl(tfd, F_SETFD, 0) == 0); 790 ATF_REQUIRE((fcntl(tfd, F_GETFD) & FD_CLOEXEC) == 0); 791 ATF_REQUIRE(fcntl(tfd, F_SETFD, FD_CLOEXEC) == 0); 792 ATF_REQUIRE((fcntl(tfd, F_GETFD) & FD_CLOEXEC) != 0); 793 (void)close(tfd); 794 } 795 796 /*****************************************************************************/ 797 798 ATF_TP_ADD_TCS(tp) 799 { 800 801 ATF_TP_ADD_TC(tp, timerfd_create); 802 ATF_TP_ADD_TC(tp, timerfd_write); 803 ATF_TP_ADD_TC(tp, timerfd_bogusfd); 804 ATF_TP_ADD_TC(tp, timerfd_invalidtime); 805 ATF_TP_ADD_TC(tp, timerfd_past); 806 ATF_TP_ADD_TC(tp, timerfd_block); 807 ATF_TP_ADD_TC(tp, timerfd_repeating); 808 ATF_TP_ADD_TC(tp, timerfd_abstime); 809 ATF_TP_ADD_TC(tp, timerfd_cancel_on_set_block); 810 ATF_TP_ADD_TC(tp, timerfd_cancel_on_set_immed); 811 ATF_TP_ADD_TC(tp, timerfd_select_poll_kevent_immed); 812 ATF_TP_ADD_TC(tp, timerfd_select_poll_kevent_block); 813 ATF_TP_ADD_TC(tp, timerfd_restart); 814 ATF_TP_ADD_TC(tp, timerfd_fcntl); 815 816 return atf_no_error(); 817 } 818