1 /* $NetBSD: t_timerfd.c,v 1.3 2021/11/01 14:33:41 hannken 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.3 2021/11/01 14:33:41 hannken Exp $"); 33 34 #include <sys/types.h> 35 #include <sys/event.h> 36 #include <sys/select.h> 37 #include <sys/stat.h> 38 #include <sys/syscall.h> 39 #include <sys/timerfd.h> 40 #include <errno.h> 41 #include <poll.h> 42 #include <pthread.h> 43 #include <stdlib.h> 44 #include <stdio.h> 45 #include <time.h> 46 #include <unistd.h> 47 48 #include <atf-c.h> 49 50 #include "isqemu.h" 51 52 struct helper_context { 53 int fd; 54 55 pthread_barrier_t barrier; 56 }; 57 58 static void 59 init_helper_context(struct helper_context * const ctx) 60 { 61 62 memset(ctx, 0, sizeof(*ctx)); 63 64 ATF_REQUIRE(pthread_barrier_init(&ctx->barrier, NULL, 2) == 0); 65 } 66 67 static bool 68 wait_barrier(struct helper_context * const ctx) 69 { 70 int rv = pthread_barrier_wait(&ctx->barrier); 71 72 return rv == 0 || rv == PTHREAD_BARRIER_SERIAL_THREAD; 73 } 74 75 static bool 76 check_value_against_bounds(uint64_t value, uint64_t lower, uint64_t upper) 77 { 78 79 /* 80 * If running under QEMU make sure the upper bound is large 81 * enough for the effect of kern/43997 82 */ 83 if (isQEMU()) { 84 upper *= 4; 85 } 86 87 if (value < lower || value > upper) { 88 printf("val %" PRIu64 " not in [ %" PRIu64 ", %" PRIu64 " ]\n", 89 value, lower, upper); 90 } 91 92 return value >= lower && value <= upper; 93 } 94 95 /*****************************************************************************/ 96 97 static int 98 timerfd_read(int fd, uint64_t *valp) 99 { 100 uint64_t val; 101 102 switch (read(fd, &val, sizeof(val))) { 103 case -1: 104 return -1; 105 106 case sizeof(val): 107 *valp = val; 108 return 0; 109 110 default: 111 /* ?? Should never happen. */ 112 errno = EIO; 113 return -1; 114 } 115 } 116 117 /*****************************************************************************/ 118 119 ATF_TC(timerfd_create); 120 ATF_TC_HEAD(timerfd_create, tc) 121 { 122 atf_tc_set_md_var(tc, "descr", "validates timerfd_create()"); 123 } 124 ATF_TC_BODY(timerfd_create, tc) 125 { 126 int fd; 127 128 ATF_REQUIRE((fd = timerfd_create(CLOCK_REALTIME, 0)) >= 0); 129 (void) close(fd); 130 131 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0); 132 (void) close(fd); 133 134 ATF_REQUIRE_ERRNO(EINVAL, 135 (fd = timerfd_create(CLOCK_VIRTUAL, 0)) == -1); 136 137 ATF_REQUIRE_ERRNO(EINVAL, 138 (fd = timerfd_create(CLOCK_PROF, 0)) == -1); 139 140 ATF_REQUIRE_ERRNO(EINVAL, 141 (fd = timerfd_create(CLOCK_REALTIME, 142 ~(TFD_CLOEXEC | TFD_NONBLOCK))) == -1); 143 } 144 145 /*****************************************************************************/ 146 147 ATF_TC(timerfd_bogusfd); 148 ATF_TC_HEAD(timerfd_bogusfd, tc) 149 { 150 atf_tc_set_md_var(tc, "descr", 151 "validates rejection of bogus fds by timerfd_{get,set}time()"); 152 } 153 ATF_TC_BODY(timerfd_bogusfd, tc) 154 { 155 struct itimerspec its = { 0 }; 156 int fd; 157 158 ATF_REQUIRE((fd = kqueue()) >= 0); /* arbitrary fd type */ 159 160 ATF_REQUIRE_ERRNO(EINVAL, 161 timerfd_gettime(fd, &its) == -1); 162 163 its.it_value.tv_sec = 5; 164 ATF_REQUIRE_ERRNO(EINVAL, 165 timerfd_settime(fd, 0, &its, NULL) == -1); 166 167 (void) close(fd); 168 } 169 170 /*****************************************************************************/ 171 172 ATF_TC(timerfd_block); 173 ATF_TC_HEAD(timerfd_block, tc) 174 { 175 atf_tc_set_md_var(tc, "descr", "validates blocking behavior"); 176 } 177 ATF_TC_BODY(timerfd_block, tc) 178 { 179 struct timespec then, now, delta; 180 uint64_t val; 181 int fd; 182 183 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0); 184 185 const struct itimerspec its = { 186 .it_value = { .tv_sec = 1, .tv_nsec = 0 }, 187 .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, 188 }; 189 190 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 191 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0); 192 ATF_REQUIRE(timerfd_read(fd, &val) == 0); 193 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 194 ATF_REQUIRE(check_value_against_bounds(val, 1, 1)); 195 196 timespecsub(&now, &then, &delta); 197 ATF_REQUIRE(check_value_against_bounds(delta.tv_sec, 1, 1)); 198 199 (void) close(fd); 200 } 201 202 /*****************************************************************************/ 203 204 ATF_TC(timerfd_repeating); 205 ATF_TC_HEAD(timerfd_repeating, tc) 206 { 207 atf_tc_set_md_var(tc, "descr", "validates repeating timer behavior"); 208 } 209 ATF_TC_BODY(timerfd_repeating, tc) 210 { 211 struct timespec then, now, delta; 212 uint64_t val; 213 int fd; 214 215 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, 216 TFD_NONBLOCK)) >= 0); 217 218 const struct itimerspec its = { 219 .it_value = { .tv_sec = 0, .tv_nsec = 200000000 }, 220 .it_interval = { .tv_sec = 0, .tv_nsec = 200000000 }, 221 }; 222 223 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 224 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0); 225 ATF_REQUIRE(sleep(1) == 0); 226 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 227 ATF_REQUIRE(timerfd_read(fd, &val) == 0); 228 /* allow some slop */ 229 ATF_REQUIRE(check_value_against_bounds(val, 3, 5)); 230 231 timespecsub(&now, &then, &delta); 232 ATF_REQUIRE(check_value_against_bounds(delta.tv_sec, 1, 1)); 233 234 (void) close(fd); 235 } 236 237 /*****************************************************************************/ 238 239 ATF_TC(timerfd_abstime); 240 ATF_TC_HEAD(timerfd_abstime, tc) 241 { 242 atf_tc_set_md_var(tc, "descr", "validates specifying abstime"); 243 } 244 ATF_TC_BODY(timerfd_abstime, tc) 245 { 246 struct timespec then, now, delta; 247 uint64_t val; 248 int fd; 249 250 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0); 251 252 struct itimerspec its = { 253 .it_value = { .tv_sec = 0, .tv_nsec = 0 }, 254 .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, 255 }; 256 257 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 258 its.it_value = then; 259 its.it_value.tv_sec += 1; 260 ATF_REQUIRE(timerfd_settime(fd, TFD_TIMER_ABSTIME, &its, NULL) == 0); 261 ATF_REQUIRE(timerfd_read(fd, &val) == 0); 262 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 263 ATF_REQUIRE(check_value_against_bounds(val, 1, 1)); 264 265 timespecsub(&now, &then, &delta); 266 ATF_REQUIRE(check_value_against_bounds(delta.tv_sec, 1, 1)); 267 268 (void) close(fd); 269 } 270 271 /*****************************************************************************/ 272 273 ATF_TC(timerfd_cancel_on_set_immed); 274 ATF_TC_HEAD(timerfd_cancel_on_set_immed, tc) 275 { 276 atf_tc_set_md_var(tc, "descr", "validates cancel-on-set - immediate"); 277 atf_tc_set_md_var(tc, "require.user", "root"); 278 } 279 ATF_TC_BODY(timerfd_cancel_on_set_immed, tc) 280 { 281 struct timespec now; 282 uint64_t val; 283 int fd; 284 285 ATF_REQUIRE((fd = timerfd_create(CLOCK_REALTIME, 0)) >= 0); 286 287 const struct itimerspec its = { 288 .it_value = { .tv_sec = 60 * 60, .tv_nsec = 0 }, 289 .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, 290 }; 291 292 ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &now) == 0); 293 ATF_REQUIRE(timerfd_settime(fd, TFD_TIMER_CANCEL_ON_SET, 294 &its, NULL) == 0); 295 ATF_REQUIRE(clock_settime(CLOCK_REALTIME, &now) == 0); 296 ATF_REQUIRE_ERRNO(ECANCELED, timerfd_read(fd, &val) == -1); 297 298 (void) close(fd); 299 } 300 301 /*****************************************************************************/ 302 303 static void * 304 timerfd_cancel_on_set_block_helper(void * const v) 305 { 306 struct helper_context * const ctx = v; 307 struct timespec now; 308 309 ATF_REQUIRE(wait_barrier(ctx)); 310 311 ATF_REQUIRE(sleep(2) == 0); 312 ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &now) == 0); 313 ATF_REQUIRE(clock_settime(CLOCK_REALTIME, &now) == 0); 314 315 return NULL; 316 } 317 318 ATF_TC(timerfd_cancel_on_set_block); 319 ATF_TC_HEAD(timerfd_cancel_on_set_block, tc) 320 { 321 atf_tc_set_md_var(tc, "descr", "validates cancel-on-set - blocking"); 322 atf_tc_set_md_var(tc, "require.user", "root"); 323 } 324 ATF_TC_BODY(timerfd_cancel_on_set_block, tc) 325 { 326 struct helper_context ctx; 327 pthread_t helper; 328 void *join_val; 329 uint64_t val; 330 int fd; 331 332 ATF_REQUIRE((fd = timerfd_create(CLOCK_REALTIME, 0)) >= 0); 333 334 const struct itimerspec its = { 335 .it_value = { .tv_sec = 60 * 60, .tv_nsec = 0 }, 336 .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, 337 }; 338 339 init_helper_context(&ctx); 340 341 ATF_REQUIRE(timerfd_settime(fd, TFD_TIMER_CANCEL_ON_SET, 342 &its, NULL) == 0); 343 ATF_REQUIRE(pthread_create(&helper, NULL, 344 timerfd_cancel_on_set_block_helper, &ctx) == 0); 345 ATF_REQUIRE(wait_barrier(&ctx)); 346 ATF_REQUIRE_ERRNO(ECANCELED, timerfd_read(fd, &val) == -1); 347 348 ATF_REQUIRE(pthread_join(helper, &join_val) == 0); 349 350 (void) close(fd); 351 } 352 353 /*****************************************************************************/ 354 355 ATF_TC(timerfd_select_poll_kevent_immed); 356 ATF_TC_HEAD(timerfd_select_poll_kevent_immed, tc) 357 { 358 atf_tc_set_md_var(tc, "descr", 359 "validates select/poll/kevent behavior - immediate return"); 360 } 361 ATF_TC_BODY(timerfd_select_poll_kevent_immed, tc) 362 { 363 const struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; 364 struct itimerspec its; 365 struct timeval tv; 366 struct stat st; 367 struct pollfd fds[1]; 368 uint64_t val; 369 fd_set readfds, writefds, exceptfds; 370 int fd; 371 int kq; 372 struct kevent kev[1]; 373 374 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)) >= 0); 375 376 ATF_REQUIRE((kq = kqueue()) >= 0); 377 EV_SET(&kev[0], fd, EVFILT_READ, EV_ADD, 0, 0, NULL); 378 ATF_REQUIRE(kevent(kq, kev, 1, NULL, 0, &ts) == 0); 379 380 /* 381 * fd should be writable but not readable. Pass all of the 382 * event bits; we should only get back POLLOUT | POLLWRNORM. 383 * (It's writable only in so far as we'll get an error if we try.) 384 */ 385 fds[0].fd = fd; 386 fds[0].events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI | 387 POLLOUT | POLLWRNORM | POLLWRBAND | POLLHUP; 388 fds[0].revents = 0; 389 ATF_REQUIRE(poll(fds, 1, 0) == 1); 390 ATF_REQUIRE(fds[0].revents == (POLLOUT | POLLWRNORM)); 391 392 /* 393 * As above; fd should only be set in writefds upon return 394 * from the select() call. 395 */ 396 FD_ZERO(&readfds); 397 FD_ZERO(&writefds); 398 FD_ZERO(&exceptfds); 399 tv.tv_sec = 0; 400 tv.tv_usec = 0; 401 FD_SET(fd, &readfds); 402 FD_SET(fd, &writefds); 403 FD_SET(fd, &exceptfds); 404 ATF_REQUIRE(select(fd + 1, &readfds, &writefds, &exceptfds, &tv) == 1); 405 ATF_REQUIRE(!FD_ISSET(fd, &readfds)); 406 ATF_REQUIRE(FD_ISSET(fd, &writefds)); 407 ATF_REQUIRE(!FD_ISSET(fd, &exceptfds)); 408 409 /* 410 * Now set a one-shot half-second timer, wait for it to expire, and 411 * then check again. 412 */ 413 memset(&its, 0, sizeof(its)); 414 its.it_value.tv_sec = 0; 415 its.it_value.tv_nsec = 500000000; 416 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0); 417 ATF_REQUIRE(sleep(2) == 0); 418 419 /* Verify it actually fired via the stat() back-channel. */ 420 ATF_REQUIRE(fstat(fd, &st) == 0); 421 ATF_REQUIRE(st.st_size == 1); 422 423 fds[0].fd = fd; 424 fds[0].events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI | 425 POLLOUT | POLLWRNORM | POLLWRBAND | POLLHUP; 426 fds[0].revents = 0; 427 ATF_REQUIRE(poll(fds, 1, 0) == 1); 428 ATF_REQUIRE(fds[0].revents == (POLLIN | POLLRDNORM | 429 POLLOUT | POLLWRNORM)); 430 431 FD_ZERO(&readfds); 432 FD_ZERO(&writefds); 433 FD_ZERO(&exceptfds); 434 tv.tv_sec = 0; 435 tv.tv_usec = 0; 436 FD_SET(fd, &readfds); 437 FD_SET(fd, &writefds); 438 FD_SET(fd, &exceptfds); 439 ATF_REQUIRE(select(fd + 1, &readfds, &writefds, &exceptfds, &tv) == 2); 440 ATF_REQUIRE(FD_ISSET(fd, &readfds)); 441 ATF_REQUIRE(FD_ISSET(fd, &writefds)); 442 ATF_REQUIRE(!FD_ISSET(fd, &exceptfds)); 443 444 /* 445 * Check that we get an EVFILT_READ event on fd. 446 */ 447 memset(kev, 0, sizeof(kev)); 448 ATF_REQUIRE(kevent(kq, NULL, 0, kev, 1, &ts) == 1); 449 ATF_REQUIRE(kev[0].ident == (uintptr_t)fd); 450 ATF_REQUIRE(kev[0].filter == EVFILT_READ); 451 ATF_REQUIRE((kev[0].flags & (EV_EOF | EV_ERROR)) == 0); 452 ATF_REQUIRE(kev[0].data == 1); 453 454 /* 455 * Read the timerfd to ensure we get the correct numnber of 456 * expirations. 457 */ 458 ATF_REQUIRE(timerfd_read(fd, &val) == 0); 459 ATF_REQUIRE(val == 1); 460 461 /* And ensure that we would block if we tried again. */ 462 ATF_REQUIRE_ERRNO(EAGAIN, timerfd_read(fd, &val) == -1); 463 464 (void) close(kq); 465 (void) close(fd); 466 } 467 468 /*****************************************************************************/ 469 470 ATF_TC(timerfd_select_poll_kevent_block); 471 ATF_TC_HEAD(timerfd_select_poll_kevent_block, tc) 472 { 473 atf_tc_set_md_var(tc, "descr", 474 "validates select/poll/kevent behavior - blocking"); 475 } 476 ATF_TC_BODY(timerfd_select_poll_kevent_block, tc) 477 { 478 const struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; 479 struct timespec then, now; 480 struct pollfd fds[1]; 481 fd_set readfds; 482 int fd; 483 int kq; 484 struct kevent kev[1]; 485 486 ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)) >= 0); 487 488 ATF_REQUIRE((kq = kqueue()) >= 0); 489 EV_SET(&kev[0], fd, EVFILT_READ, EV_ADD, 0, 0, NULL); 490 ATF_REQUIRE(kevent(kq, kev, 1, NULL, 0, &ts) == 0); 491 492 /* 493 * For each of these tests, we do the following: 494 * 495 * - Get the current time. 496 * - Set a 1-second one-shot timer. 497 * - Block in the multiplexing call. 498 * - Get the current time and verify that the timer expiration 499 * interval has passed. 500 */ 501 502 const struct itimerspec its = { 503 .it_value = { .tv_sec = 1, .tv_nsec = 0 }, 504 .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, 505 }; 506 507 /* poll(2) */ 508 fds[0].fd = fd; 509 fds[0].events = POLLIN | POLLRDNORM; 510 fds[0].revents = 0; 511 512 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 513 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0); 514 ATF_REQUIRE(poll(fds, 1, INFTIM) == 1); 515 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 516 ATF_REQUIRE(fds[0].revents == (POLLIN | POLLRDNORM)); 517 ATF_REQUIRE(now.tv_sec - then.tv_sec >= 1); 518 519 /* select(2) */ 520 FD_ZERO(&readfds); 521 FD_SET(fd, &readfds); 522 523 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 524 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0); 525 ATF_REQUIRE(select(fd + 1, &readfds, NULL, NULL, NULL) == 1); 526 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 527 ATF_REQUIRE(FD_ISSET(fd, &readfds)); 528 ATF_REQUIRE(now.tv_sec - then.tv_sec >= 1); 529 530 /* kevent(2) */ 531 memset(kev, 0, sizeof(kev)); 532 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 533 ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0); 534 ATF_REQUIRE(kevent(kq, NULL, 0, kev, 1, NULL) == 1); 535 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 536 ATF_REQUIRE(kev[0].ident == (uintptr_t)fd); 537 ATF_REQUIRE(kev[0].filter == EVFILT_READ); 538 ATF_REQUIRE((kev[0].flags & (EV_EOF | EV_ERROR)) == 0); 539 ATF_REQUIRE(kev[0].data == 1); 540 541 (void) close(kq); 542 (void) close(fd); 543 } 544 545 /*****************************************************************************/ 546 547 static void * 548 timerfd_restart_helper(void * const v) 549 { 550 struct helper_context * const ctx = v; 551 552 ATF_REQUIRE(wait_barrier(ctx)); 553 554 /* 555 * Wait 5 seconds (that should give the main thread time to 556 * block), and then close the descriptor. 557 */ 558 ATF_REQUIRE(sleep(5) == 0); 559 ATF_REQUIRE(close(ctx->fd) == 0); 560 561 return NULL; 562 } 563 564 ATF_TC(timerfd_restart); 565 ATF_TC_HEAD(timerfd_restart, tc) 566 { 567 atf_tc_set_md_var(tc, "descr", 568 "exercises the 'restart' fileop code path"); 569 } 570 ATF_TC_BODY(timerfd_restart, tc) 571 { 572 struct timespec then, now, delta; 573 struct helper_context ctx; 574 uint64_t val; 575 pthread_t helper; 576 void *join_val; 577 578 init_helper_context(&ctx); 579 580 ATF_REQUIRE((ctx.fd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0); 581 582 const struct itimerspec its = { 583 .it_value = { .tv_sec = 60 * 60, .tv_nsec = 0 }, 584 .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, 585 }; 586 ATF_REQUIRE(timerfd_settime(ctx.fd, 0, &its, NULL) == 0); 587 588 589 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 590 ATF_REQUIRE(pthread_create(&helper, NULL, 591 timerfd_restart_helper, &ctx) == 0); 592 593 /* 594 * Wait for the helper to be ready, and then immediately block 595 * in read(). The helper will close the file, and we should get 596 * EBADF after a few seconds. 597 */ 598 ATF_REQUIRE(wait_barrier(&ctx)); 599 ATF_REQUIRE_ERRNO(EBADF, timerfd_read(ctx.fd, &val) == -1); 600 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 601 602 timespecsub(&now, &then, &delta); 603 ATF_REQUIRE(delta.tv_sec >= 5); 604 605 /* Reap the helper. */ 606 ATF_REQUIRE(pthread_join(helper, &join_val) == 0); 607 } 608 609 /*****************************************************************************/ 610 611 ATF_TP_ADD_TCS(tp) 612 { 613 ATF_TP_ADD_TC(tp, timerfd_create); 614 ATF_TP_ADD_TC(tp, timerfd_bogusfd); 615 ATF_TP_ADD_TC(tp, timerfd_block); 616 ATF_TP_ADD_TC(tp, timerfd_repeating); 617 ATF_TP_ADD_TC(tp, timerfd_abstime); 618 ATF_TP_ADD_TC(tp, timerfd_cancel_on_set_block); 619 ATF_TP_ADD_TC(tp, timerfd_cancel_on_set_immed); 620 ATF_TP_ADD_TC(tp, timerfd_select_poll_kevent_immed); 621 ATF_TP_ADD_TC(tp, timerfd_select_poll_kevent_block); 622 ATF_TP_ADD_TC(tp, timerfd_restart); 623 624 return atf_no_error(); 625 } 626