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