1 /* $NetBSD: t_timerfd.c,v 1.4 2022/02/20 15:21:14 thorpej 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.4 2022/02/20 15:21:14 thorpej 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(check_value_against_bounds(delta.tv_sec, 1, 1)); 199 200 (void) close(fd); 201 } 202 203 /*****************************************************************************/ 204 205 ATF_TC(timerfd_repeating); 206 ATF_TC_HEAD(timerfd_repeating, tc) 207 { 208 atf_tc_set_md_var(tc, "descr", "validates repeating timer behavior"); 209 } 210 ATF_TC_BODY(timerfd_repeating, tc) 211 { 212 struct timespec then, now, delta; 213 uint64_t val; 214 int fd; 215 216 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, 217 TFD_NONBLOCK)) >= 0); 218 219 const struct itimerspec its = { 220 .it_value = { .tv_sec = 0, .tv_nsec = 200000000 }, 221 .it_interval = { .tv_sec = 0, .tv_nsec = 200000000 }, 222 }; 223 224 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 225 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0); 226 ATF_REQUIRE(sleep(1) == 0); 227 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 228 ATF_REQUIRE(timerfd_read(fd, &val) == 0); 229 /* allow some slop */ 230 ATF_REQUIRE(check_value_against_bounds(val, 3, 5)); 231 232 timespecsub(&now, &then, &delta); 233 ATF_REQUIRE(check_value_against_bounds(delta.tv_sec, 1, 1)); 234 235 (void) close(fd); 236 } 237 238 /*****************************************************************************/ 239 240 ATF_TC(timerfd_abstime); 241 ATF_TC_HEAD(timerfd_abstime, tc) 242 { 243 atf_tc_set_md_var(tc, "descr", "validates specifying abstime"); 244 } 245 ATF_TC_BODY(timerfd_abstime, tc) 246 { 247 struct timespec then, now, delta; 248 uint64_t val; 249 int fd; 250 251 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0); 252 253 struct itimerspec its = { 254 .it_value = { .tv_sec = 0, .tv_nsec = 0 }, 255 .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, 256 }; 257 258 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 259 its.it_value = then; 260 its.it_value.tv_sec += 1; 261 ATF_REQUIRE(timerfd_settime(fd, TFD_TIMER_ABSTIME, &its, NULL) == 0); 262 ATF_REQUIRE(timerfd_read(fd, &val) == 0); 263 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 264 ATF_REQUIRE(check_value_against_bounds(val, 1, 1)); 265 266 timespecsub(&now, &then, &delta); 267 ATF_REQUIRE(check_value_against_bounds(delta.tv_sec, 1, 1)); 268 269 (void) close(fd); 270 } 271 272 /*****************************************************************************/ 273 274 ATF_TC(timerfd_cancel_on_set_immed); 275 ATF_TC_HEAD(timerfd_cancel_on_set_immed, tc) 276 { 277 atf_tc_set_md_var(tc, "descr", "validates cancel-on-set - immediate"); 278 atf_tc_set_md_var(tc, "require.user", "root"); 279 } 280 ATF_TC_BODY(timerfd_cancel_on_set_immed, tc) 281 { 282 struct timespec now; 283 uint64_t val; 284 int fd; 285 286 ATF_REQUIRE((fd = timerfd_create(CLOCK_REALTIME, 0)) >= 0); 287 288 const struct itimerspec its = { 289 .it_value = { .tv_sec = 60 * 60, .tv_nsec = 0 }, 290 .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, 291 }; 292 293 ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &now) == 0); 294 ATF_REQUIRE(timerfd_settime(fd, TFD_TIMER_CANCEL_ON_SET, 295 &its, NULL) == 0); 296 ATF_REQUIRE(clock_settime(CLOCK_REALTIME, &now) == 0); 297 ATF_REQUIRE_ERRNO(ECANCELED, timerfd_read(fd, &val) == -1); 298 299 (void) close(fd); 300 } 301 302 /*****************************************************************************/ 303 304 static void * 305 timerfd_cancel_on_set_block_helper(void * const v) 306 { 307 struct helper_context * const ctx = v; 308 struct timespec now; 309 310 ATF_REQUIRE(wait_barrier(ctx)); 311 312 ATF_REQUIRE(sleep(2) == 0); 313 ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &now) == 0); 314 ATF_REQUIRE(clock_settime(CLOCK_REALTIME, &now) == 0); 315 316 return NULL; 317 } 318 319 ATF_TC(timerfd_cancel_on_set_block); 320 ATF_TC_HEAD(timerfd_cancel_on_set_block, tc) 321 { 322 atf_tc_set_md_var(tc, "descr", "validates cancel-on-set - blocking"); 323 atf_tc_set_md_var(tc, "require.user", "root"); 324 } 325 ATF_TC_BODY(timerfd_cancel_on_set_block, tc) 326 { 327 struct helper_context ctx; 328 pthread_t helper; 329 void *join_val; 330 uint64_t val; 331 int fd; 332 333 ATF_REQUIRE((fd = timerfd_create(CLOCK_REALTIME, 0)) >= 0); 334 335 const struct itimerspec its = { 336 .it_value = { .tv_sec = 60 * 60, .tv_nsec = 0 }, 337 .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, 338 }; 339 340 init_helper_context(&ctx); 341 342 ATF_REQUIRE(timerfd_settime(fd, TFD_TIMER_CANCEL_ON_SET, 343 &its, NULL) == 0); 344 ATF_REQUIRE(pthread_create(&helper, NULL, 345 timerfd_cancel_on_set_block_helper, &ctx) == 0); 346 ATF_REQUIRE(wait_barrier(&ctx)); 347 ATF_REQUIRE_ERRNO(ECANCELED, timerfd_read(fd, &val) == -1); 348 349 ATF_REQUIRE(pthread_join(helper, &join_val) == 0); 350 351 (void) close(fd); 352 } 353 354 /*****************************************************************************/ 355 356 ATF_TC(timerfd_select_poll_kevent_immed); 357 ATF_TC_HEAD(timerfd_select_poll_kevent_immed, tc) 358 { 359 atf_tc_set_md_var(tc, "descr", 360 "validates select/poll/kevent behavior - immediate return"); 361 } 362 ATF_TC_BODY(timerfd_select_poll_kevent_immed, tc) 363 { 364 const struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; 365 struct itimerspec its; 366 struct timeval tv; 367 struct stat st; 368 struct pollfd fds[1]; 369 uint64_t val; 370 fd_set readfds, writefds, exceptfds; 371 int fd; 372 int kq; 373 struct kevent kev[1]; 374 375 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)) >= 0); 376 377 ATF_REQUIRE((kq = kqueue()) >= 0); 378 EV_SET(&kev[0], fd, EVFILT_READ, EV_ADD, 0, 0, NULL); 379 ATF_REQUIRE(kevent(kq, kev, 1, NULL, 0, &ts) == 0); 380 381 /* 382 * fd should be writable but not readable. Pass all of the 383 * event bits; we should only get back POLLOUT | POLLWRNORM. 384 * (It's writable only in so far as we'll get an error if we try.) 385 */ 386 fds[0].fd = fd; 387 fds[0].events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI | 388 POLLOUT | POLLWRNORM | POLLWRBAND | POLLHUP; 389 fds[0].revents = 0; 390 ATF_REQUIRE(poll(fds, 1, 0) == 1); 391 ATF_REQUIRE(fds[0].revents == (POLLOUT | POLLWRNORM)); 392 393 /* 394 * As above; fd should only be set in writefds upon return 395 * from the select() call. 396 */ 397 FD_ZERO(&readfds); 398 FD_ZERO(&writefds); 399 FD_ZERO(&exceptfds); 400 tv.tv_sec = 0; 401 tv.tv_usec = 0; 402 FD_SET(fd, &readfds); 403 FD_SET(fd, &writefds); 404 FD_SET(fd, &exceptfds); 405 ATF_REQUIRE(select(fd + 1, &readfds, &writefds, &exceptfds, &tv) == 1); 406 ATF_REQUIRE(!FD_ISSET(fd, &readfds)); 407 ATF_REQUIRE(FD_ISSET(fd, &writefds)); 408 ATF_REQUIRE(!FD_ISSET(fd, &exceptfds)); 409 410 /* 411 * Now set a one-shot half-second timer, wait for it to expire, and 412 * then check again. 413 */ 414 memset(&its, 0, sizeof(its)); 415 its.it_value.tv_sec = 0; 416 its.it_value.tv_nsec = 500000000; 417 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0); 418 ATF_REQUIRE(sleep(2) == 0); 419 420 /* Verify it actually fired via the stat() back-channel. */ 421 ATF_REQUIRE(fstat(fd, &st) == 0); 422 ATF_REQUIRE(st.st_size == 1); 423 424 fds[0].fd = fd; 425 fds[0].events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI | 426 POLLOUT | POLLWRNORM | POLLWRBAND | POLLHUP; 427 fds[0].revents = 0; 428 ATF_REQUIRE(poll(fds, 1, 0) == 1); 429 ATF_REQUIRE(fds[0].revents == (POLLIN | POLLRDNORM | 430 POLLOUT | POLLWRNORM)); 431 432 FD_ZERO(&readfds); 433 FD_ZERO(&writefds); 434 FD_ZERO(&exceptfds); 435 tv.tv_sec = 0; 436 tv.tv_usec = 0; 437 FD_SET(fd, &readfds); 438 FD_SET(fd, &writefds); 439 FD_SET(fd, &exceptfds); 440 ATF_REQUIRE(select(fd + 1, &readfds, &writefds, &exceptfds, &tv) == 2); 441 ATF_REQUIRE(FD_ISSET(fd, &readfds)); 442 ATF_REQUIRE(FD_ISSET(fd, &writefds)); 443 ATF_REQUIRE(!FD_ISSET(fd, &exceptfds)); 444 445 /* 446 * Check that we get an EVFILT_READ event on fd. 447 */ 448 memset(kev, 0, sizeof(kev)); 449 ATF_REQUIRE(kevent(kq, NULL, 0, kev, 1, &ts) == 1); 450 ATF_REQUIRE(kev[0].ident == (uintptr_t)fd); 451 ATF_REQUIRE(kev[0].filter == EVFILT_READ); 452 ATF_REQUIRE((kev[0].flags & (EV_EOF | EV_ERROR)) == 0); 453 ATF_REQUIRE(kev[0].data == 1); 454 455 /* 456 * Read the timerfd to ensure we get the correct numnber of 457 * expirations. 458 */ 459 ATF_REQUIRE(timerfd_read(fd, &val) == 0); 460 ATF_REQUIRE(val == 1); 461 462 /* And ensure that we would block if we tried again. */ 463 ATF_REQUIRE_ERRNO(EAGAIN, timerfd_read(fd, &val) == -1); 464 465 (void) close(kq); 466 (void) close(fd); 467 } 468 469 /*****************************************************************************/ 470 471 ATF_TC(timerfd_select_poll_kevent_block); 472 ATF_TC_HEAD(timerfd_select_poll_kevent_block, tc) 473 { 474 atf_tc_set_md_var(tc, "descr", 475 "validates select/poll/kevent behavior - blocking"); 476 } 477 ATF_TC_BODY(timerfd_select_poll_kevent_block, tc) 478 { 479 const struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; 480 struct timespec then, now; 481 struct pollfd fds[1]; 482 fd_set readfds; 483 int fd; 484 int kq; 485 struct kevent kev[1]; 486 487 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)) >= 0); 488 489 ATF_REQUIRE((kq = kqueue()) >= 0); 490 EV_SET(&kev[0], fd, EVFILT_READ, EV_ADD, 0, 0, NULL); 491 ATF_REQUIRE(kevent(kq, kev, 1, NULL, 0, &ts) == 0); 492 493 /* 494 * For each of these tests, we do the following: 495 * 496 * - Get the current time. 497 * - Set a 1-second one-shot timer. 498 * - Block in the multiplexing call. 499 * - Get the current time and verify that the timer expiration 500 * interval has passed. 501 */ 502 503 const struct itimerspec its = { 504 .it_value = { .tv_sec = 1, .tv_nsec = 0 }, 505 .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, 506 }; 507 508 /* poll(2) */ 509 fds[0].fd = fd; 510 fds[0].events = POLLIN | POLLRDNORM; 511 fds[0].revents = 0; 512 513 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 514 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0); 515 ATF_REQUIRE(poll(fds, 1, INFTIM) == 1); 516 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 517 ATF_REQUIRE(fds[0].revents == (POLLIN | POLLRDNORM)); 518 ATF_REQUIRE(now.tv_sec - then.tv_sec >= 1); 519 520 /* select(2) */ 521 FD_ZERO(&readfds); 522 FD_SET(fd, &readfds); 523 524 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 525 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0); 526 ATF_REQUIRE(select(fd + 1, &readfds, NULL, NULL, NULL) == 1); 527 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 528 ATF_REQUIRE(FD_ISSET(fd, &readfds)); 529 ATF_REQUIRE(now.tv_sec - then.tv_sec >= 1); 530 531 /* kevent(2) */ 532 memset(kev, 0, sizeof(kev)); 533 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 534 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0); 535 ATF_REQUIRE(kevent(kq, NULL, 0, kev, 1, NULL) == 1); 536 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 537 ATF_REQUIRE(kev[0].ident == (uintptr_t)fd); 538 ATF_REQUIRE(kev[0].filter == EVFILT_READ); 539 ATF_REQUIRE((kev[0].flags & (EV_EOF | EV_ERROR)) == 0); 540 ATF_REQUIRE(kev[0].data == 1); 541 542 (void) close(kq); 543 (void) close(fd); 544 } 545 546 /*****************************************************************************/ 547 548 static void * 549 timerfd_restart_helper(void * const v) 550 { 551 struct helper_context * const ctx = v; 552 553 ATF_REQUIRE(wait_barrier(ctx)); 554 555 /* 556 * Wait 5 seconds (that should give the main thread time to 557 * block), and then close the descriptor. 558 */ 559 ATF_REQUIRE(sleep(5) == 0); 560 ATF_REQUIRE(close(ctx->fd) == 0); 561 562 return NULL; 563 } 564 565 ATF_TC(timerfd_restart); 566 ATF_TC_HEAD(timerfd_restart, tc) 567 { 568 atf_tc_set_md_var(tc, "descr", 569 "exercises the 'restart' fileop code path"); 570 } 571 ATF_TC_BODY(timerfd_restart, tc) 572 { 573 struct timespec then, now, delta; 574 struct helper_context ctx; 575 uint64_t val; 576 pthread_t helper; 577 void *join_val; 578 579 init_helper_context(&ctx); 580 581 ATF_REQUIRE((ctx.fd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0); 582 583 const struct itimerspec its = { 584 .it_value = { .tv_sec = 60 * 60, .tv_nsec = 0 }, 585 .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, 586 }; 587 ATF_REQUIRE(timerfd_settime(ctx.fd, 0, &its, NULL) == 0); 588 589 590 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 591 ATF_REQUIRE(pthread_create(&helper, NULL, 592 timerfd_restart_helper, &ctx) == 0); 593 594 /* 595 * Wait for the helper to be ready, and then immediately block 596 * in read(). The helper will close the file, and we should get 597 * EBADF after a few seconds. 598 */ 599 ATF_REQUIRE(wait_barrier(&ctx)); 600 ATF_REQUIRE_ERRNO(EBADF, timerfd_read(ctx.fd, &val) == -1); 601 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 602 603 timespecsub(&now, &then, &delta); 604 ATF_REQUIRE(delta.tv_sec >= 5); 605 606 /* Reap the helper. */ 607 ATF_REQUIRE(pthread_join(helper, &join_val) == 0); 608 } 609 610 /*****************************************************************************/ 611 612 ATF_TC(timerfd_fcntl); 613 ATF_TC_HEAD(timerfd_fcntl, tc) 614 { 615 atf_tc_set_md_var(tc, "descr", 616 "validates fcntl behavior"); 617 } 618 619 ATF_TC_BODY(timerfd_fcntl, tc) 620 { 621 int tfd; 622 int val; 623 624 ATF_REQUIRE((tfd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0); 625 ATF_REQUIRE((fcntl(tfd, F_GETFL) & O_NONBLOCK) == 0); 626 ATF_REQUIRE(fcntl(tfd, F_SETFL, O_NONBLOCK) == 0); 627 ATF_REQUIRE((fcntl(tfd, F_GETFL) & O_NONBLOCK) != 0); 628 ATF_REQUIRE((fcntl(tfd, F_GETFD) & FD_CLOEXEC) == 0); 629 630 /* If the timer hasn't fired, there is no readable data. */ 631 ATF_REQUIRE(ioctl(tfd, FIONREAD, &val) == 0); 632 ATF_REQUIRE(val == 0); 633 634 ATF_REQUIRE_ERRNO(ENOTTY, ioctl(tfd, FIONWRITE, &val) == -1); 635 ATF_REQUIRE_ERRNO(ENOTTY, ioctl(tfd, FIONSPACE, &val) == -1); 636 (void)close(tfd); 637 638 ATF_REQUIRE((tfd = timerfd_create(CLOCK_MONOTONIC, 639 TFD_NONBLOCK | TFD_CLOEXEC)) >= 0); 640 ATF_REQUIRE((fcntl(tfd, F_GETFL) & ~O_ACCMODE) == O_NONBLOCK); 641 ATF_REQUIRE((fcntl(tfd, F_GETFD) & FD_CLOEXEC) != 0); 642 ATF_REQUIRE(fcntl(tfd, F_SETFD, 0) == 0); 643 ATF_REQUIRE((fcntl(tfd, F_GETFD) & FD_CLOEXEC) == 0); 644 ATF_REQUIRE(fcntl(tfd, F_SETFD, FD_CLOEXEC) == 0); 645 ATF_REQUIRE((fcntl(tfd, F_GETFD) & FD_CLOEXEC) != 0); 646 (void)close(tfd); 647 } 648 649 /*****************************************************************************/ 650 651 ATF_TP_ADD_TCS(tp) 652 { 653 ATF_TP_ADD_TC(tp, timerfd_create); 654 ATF_TP_ADD_TC(tp, timerfd_bogusfd); 655 ATF_TP_ADD_TC(tp, timerfd_block); 656 ATF_TP_ADD_TC(tp, timerfd_repeating); 657 ATF_TP_ADD_TC(tp, timerfd_abstime); 658 ATF_TP_ADD_TC(tp, timerfd_cancel_on_set_block); 659 ATF_TP_ADD_TC(tp, timerfd_cancel_on_set_immed); 660 ATF_TP_ADD_TC(tp, timerfd_select_poll_kevent_immed); 661 ATF_TP_ADD_TC(tp, timerfd_select_poll_kevent_block); 662 ATF_TP_ADD_TC(tp, timerfd_restart); 663 ATF_TP_ADD_TC(tp, timerfd_fcntl); 664 665 return atf_no_error(); 666 } 667