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