1 1.12 riastrad /* $NetBSD: t_timerfd.c,v 1.12 2025/04/16 01:32:48 riastradh Exp $ */ 2 1.2 thorpej 3 1.2 thorpej /*- 4 1.2 thorpej * Copyright (c) 2020 The NetBSD Foundation, Inc. 5 1.2 thorpej * All rights reserved. 6 1.2 thorpej * 7 1.2 thorpej * Redistribution and use in source and binary forms, with or without 8 1.2 thorpej * modification, are permitted provided that the following conditions 9 1.2 thorpej * are met: 10 1.2 thorpej * 1. Redistributions of source code must retain the above copyright 11 1.2 thorpej * notice, this list of conditions and the following disclaimer. 12 1.2 thorpej * 2. Redistributions in binary form must reproduce the above copyright 13 1.2 thorpej * notice, this list of conditions and the following disclaimer in the 14 1.2 thorpej * documentation and/or other materials provided with the distribution. 15 1.2 thorpej * 16 1.2 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 1.2 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 1.2 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 1.2 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 1.2 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 1.2 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 1.2 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 1.2 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 1.2 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 1.2 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 1.2 thorpej * POSSIBILITY OF SUCH DAMAGE. 27 1.2 thorpej */ 28 1.2 thorpej 29 1.2 thorpej #include <sys/cdefs.h> 30 1.2 thorpej __COPYRIGHT("@(#) Copyright (c) 2020\ 31 1.2 thorpej The NetBSD Foundation, inc. All rights reserved."); 32 1.12 riastrad __RCSID("$NetBSD: t_timerfd.c,v 1.12 2025/04/16 01:32:48 riastradh Exp $"); 33 1.2 thorpej 34 1.2 thorpej #include <sys/types.h> 35 1.8 riastrad 36 1.2 thorpej #include <sys/event.h> 37 1.4 thorpej #include <sys/ioctl.h> 38 1.2 thorpej #include <sys/select.h> 39 1.2 thorpej #include <sys/stat.h> 40 1.2 thorpej #include <sys/syscall.h> 41 1.2 thorpej #include <sys/timerfd.h> 42 1.8 riastrad 43 1.2 thorpej #include <errno.h> 44 1.2 thorpej #include <poll.h> 45 1.2 thorpej #include <pthread.h> 46 1.8 riastrad #include <stdio.h> 47 1.2 thorpej #include <stdlib.h> 48 1.2 thorpej #include <time.h> 49 1.2 thorpej #include <unistd.h> 50 1.2 thorpej 51 1.2 thorpej #include <atf-c.h> 52 1.2 thorpej 53 1.8 riastrad #include "h_macros.h" 54 1.3 hannken #include "isqemu.h" 55 1.3 hannken 56 1.2 thorpej struct helper_context { 57 1.2 thorpej int fd; 58 1.2 thorpej 59 1.2 thorpej pthread_barrier_t barrier; 60 1.2 thorpej }; 61 1.2 thorpej 62 1.2 thorpej static void 63 1.2 thorpej init_helper_context(struct helper_context * const ctx) 64 1.2 thorpej { 65 1.2 thorpej 66 1.2 thorpej memset(ctx, 0, sizeof(*ctx)); 67 1.2 thorpej 68 1.2 thorpej ATF_REQUIRE(pthread_barrier_init(&ctx->barrier, NULL, 2) == 0); 69 1.2 thorpej } 70 1.2 thorpej 71 1.2 thorpej static bool 72 1.2 thorpej wait_barrier(struct helper_context * const ctx) 73 1.2 thorpej { 74 1.2 thorpej int rv = pthread_barrier_wait(&ctx->barrier); 75 1.2 thorpej 76 1.2 thorpej return rv == 0 || rv == PTHREAD_BARRIER_SERIAL_THREAD; 77 1.2 thorpej } 78 1.2 thorpej 79 1.3 hannken static bool 80 1.3 hannken check_value_against_bounds(uint64_t value, uint64_t lower, uint64_t upper) 81 1.3 hannken { 82 1.3 hannken 83 1.3 hannken /* 84 1.3 hannken * If running under QEMU make sure the upper bound is large 85 1.3 hannken * enough for the effect of kern/43997 86 1.3 hannken */ 87 1.3 hannken if (isQEMU()) { 88 1.3 hannken upper *= 4; 89 1.3 hannken } 90 1.3 hannken 91 1.3 hannken if (value < lower || value > upper) { 92 1.3 hannken printf("val %" PRIu64 " not in [ %" PRIu64 ", %" PRIu64 " ]\n", 93 1.3 hannken value, lower, upper); 94 1.3 hannken } 95 1.3 hannken 96 1.3 hannken return value >= lower && value <= upper; 97 1.3 hannken } 98 1.3 hannken 99 1.2 thorpej /*****************************************************************************/ 100 1.2 thorpej 101 1.2 thorpej static int 102 1.2 thorpej timerfd_read(int fd, uint64_t *valp) 103 1.2 thorpej { 104 1.2 thorpej uint64_t val; 105 1.2 thorpej 106 1.2 thorpej switch (read(fd, &val, sizeof(val))) { 107 1.2 thorpej case -1: 108 1.2 thorpej return -1; 109 1.2 thorpej 110 1.2 thorpej case sizeof(val): 111 1.2 thorpej *valp = val; 112 1.2 thorpej return 0; 113 1.2 thorpej 114 1.2 thorpej default: 115 1.2 thorpej /* ?? Should never happen. */ 116 1.2 thorpej errno = EIO; 117 1.2 thorpej return -1; 118 1.2 thorpej } 119 1.2 thorpej } 120 1.2 thorpej 121 1.2 thorpej /*****************************************************************************/ 122 1.2 thorpej 123 1.2 thorpej ATF_TC(timerfd_create); 124 1.2 thorpej ATF_TC_HEAD(timerfd_create, tc) 125 1.2 thorpej { 126 1.2 thorpej atf_tc_set_md_var(tc, "descr", "validates timerfd_create()"); 127 1.2 thorpej } 128 1.2 thorpej ATF_TC_BODY(timerfd_create, tc) 129 1.2 thorpej { 130 1.2 thorpej int fd; 131 1.2 thorpej 132 1.2 thorpej ATF_REQUIRE((fd = timerfd_create(CLOCK_REALTIME, 0)) >= 0); 133 1.2 thorpej (void) close(fd); 134 1.2 thorpej 135 1.2 thorpej ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0); 136 1.2 thorpej (void) close(fd); 137 1.2 thorpej 138 1.2 thorpej ATF_REQUIRE_ERRNO(EINVAL, 139 1.2 thorpej (fd = timerfd_create(CLOCK_VIRTUAL, 0)) == -1); 140 1.2 thorpej 141 1.2 thorpej ATF_REQUIRE_ERRNO(EINVAL, 142 1.2 thorpej (fd = timerfd_create(CLOCK_PROF, 0)) == -1); 143 1.2 thorpej 144 1.2 thorpej ATF_REQUIRE_ERRNO(EINVAL, 145 1.2 thorpej (fd = timerfd_create(CLOCK_REALTIME, 146 1.2 thorpej ~(TFD_CLOEXEC | TFD_NONBLOCK))) == -1); 147 1.2 thorpej } 148 1.2 thorpej 149 1.2 thorpej /*****************************************************************************/ 150 1.2 thorpej 151 1.8 riastrad ATF_TC(timerfd_write); 152 1.8 riastrad ATF_TC_HEAD(timerfd_write, tc) 153 1.8 riastrad { 154 1.8 riastrad atf_tc_set_md_var(tc, "descr", 155 1.8 riastrad "validates rejection of writes to timerfds"); 156 1.8 riastrad } 157 1.8 riastrad ATF_TC_BODY(timerfd_write, tc) 158 1.8 riastrad { 159 1.8 riastrad int fd; 160 1.8 riastrad char c = 1; 161 1.8 riastrad 162 1.8 riastrad RL(fd = timerfd_create(CLOCK_REALTIME, 0)); 163 1.8 riastrad ATF_CHECK_ERRNO(EBADF, write(fd, &c, 1) == -1); 164 1.8 riastrad RL(close(fd)); 165 1.8 riastrad } 166 1.8 riastrad 167 1.8 riastrad /*****************************************************************************/ 168 1.8 riastrad 169 1.2 thorpej ATF_TC(timerfd_bogusfd); 170 1.2 thorpej ATF_TC_HEAD(timerfd_bogusfd, tc) 171 1.2 thorpej { 172 1.2 thorpej atf_tc_set_md_var(tc, "descr", 173 1.2 thorpej "validates rejection of bogus fds by timerfd_{get,set}time()"); 174 1.2 thorpej } 175 1.2 thorpej ATF_TC_BODY(timerfd_bogusfd, tc) 176 1.2 thorpej { 177 1.2 thorpej struct itimerspec its = { 0 }; 178 1.2 thorpej int fd; 179 1.2 thorpej 180 1.2 thorpej ATF_REQUIRE((fd = kqueue()) >= 0); /* arbitrary fd type */ 181 1.2 thorpej 182 1.2 thorpej ATF_REQUIRE_ERRNO(EINVAL, 183 1.2 thorpej timerfd_gettime(fd, &its) == -1); 184 1.2 thorpej 185 1.2 thorpej its.it_value.tv_sec = 5; 186 1.2 thorpej ATF_REQUIRE_ERRNO(EINVAL, 187 1.2 thorpej timerfd_settime(fd, 0, &its, NULL) == -1); 188 1.2 thorpej 189 1.2 thorpej (void) close(fd); 190 1.2 thorpej } 191 1.2 thorpej 192 1.2 thorpej /*****************************************************************************/ 193 1.2 thorpej 194 1.8 riastrad ATF_TC(timerfd_invalidtime); 195 1.8 riastrad ATF_TC_HEAD(timerfd_invalidtime, tc) 196 1.8 riastrad { 197 1.8 riastrad atf_tc_set_md_var(tc, "descr", 198 1.8 riastrad "validates rejection of invalid itimerspec by timerfd_settime()"); 199 1.8 riastrad } 200 1.8 riastrad ATF_TC_BODY(timerfd_invalidtime, tc) 201 1.8 riastrad { 202 1.8 riastrad const struct itimerspec einval_its[] = { 203 1.8 riastrad [0] = { .it_value = {-1, 0} }, 204 1.8 riastrad [1] = { .it_value = {0, -1} }, 205 1.8 riastrad [2] = { .it_value = {0, 1000000001} }, 206 1.8 riastrad [3] = { .it_value = {1, 0}, .it_interval = {-1, 0} }, 207 1.8 riastrad [4] = { .it_value = {1, 0}, .it_interval = {0, -1} }, 208 1.8 riastrad [5] = { .it_value = {1, 0}, .it_interval = {0, 1000000001} }, 209 1.8 riastrad }; 210 1.8 riastrad struct timespec now; 211 1.8 riastrad unsigned i; 212 1.8 riastrad fd_set readfds; 213 1.8 riastrad uint64_t val; 214 1.8 riastrad int fd; 215 1.8 riastrad 216 1.8 riastrad RL(clock_gettime(CLOCK_MONOTONIC, &now)); 217 1.8 riastrad RL(fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)); 218 1.8 riastrad 219 1.8 riastrad for (i = 0; i < __arraycount(einval_its); i++) { 220 1.8 riastrad struct itimerspec its; 221 1.8 riastrad 222 1.8 riastrad fprintf(stderr, "case %u\n", i); 223 1.8 riastrad 224 1.8 riastrad ATF_CHECK_ERRNO(EINVAL, 225 1.8 riastrad timerfd_settime(fd, 0, &einval_its[i], NULL) == -1); 226 1.8 riastrad 227 1.12 riastrad /* 228 1.12 riastrad * Try the same with an absolute time near now (unless 229 1.12 riastrad * that makes it a valid time, in case 0). 230 1.12 riastrad */ 231 1.12 riastrad if (i == 0) 232 1.12 riastrad continue; 233 1.8 riastrad its.it_value = einval_its[i].it_value; 234 1.12 riastrad its.it_value.tv_sec += now.tv_sec; 235 1.12 riastrad its.it_interval = einval_its[i].it_interval; 236 1.8 riastrad ATF_CHECK_ERRNO(EINVAL, 237 1.8 riastrad timerfd_settime(fd, TFD_TIMER_ABSTIME, &its, NULL) == -1); 238 1.8 riastrad } 239 1.8 riastrad 240 1.8 riastrad /* Wait up to 2sec to make sure no timer got set anyway. */ 241 1.8 riastrad FD_ZERO(&readfds); 242 1.8 riastrad FD_SET(fd, &readfds); 243 1.8 riastrad RL(select(fd + 1, &readfds, NULL, NULL, &(struct timeval){2, 0})); 244 1.8 riastrad ATF_CHECK(!FD_ISSET(fd, &readfds)); 245 1.8 riastrad ATF_CHECK_ERRNO(EAGAIN, timerfd_read(fd, &val) == -1); 246 1.8 riastrad 247 1.8 riastrad RL(close(fd)); 248 1.8 riastrad } 249 1.8 riastrad 250 1.8 riastrad /*****************************************************************************/ 251 1.8 riastrad 252 1.8 riastrad ATF_TC(timerfd_past); 253 1.8 riastrad ATF_TC_HEAD(timerfd_past, tc) 254 1.8 riastrad { 255 1.8 riastrad atf_tc_set_md_var(tc, "descr", "validates trigger on past time"); 256 1.8 riastrad } 257 1.8 riastrad ATF_TC_BODY(timerfd_past, tc) 258 1.8 riastrad { 259 1.8 riastrad struct itimerspec its = {.it_value = {-1, 0}, .it_interval = {0, 0}}; 260 1.8 riastrad struct timespec then, now, delta; 261 1.8 riastrad uint64_t val; 262 1.8 riastrad int fd; 263 1.8 riastrad 264 1.8 riastrad RL(fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)); 265 1.8 riastrad 266 1.8 riastrad RL(clock_gettime(CLOCK_MONOTONIC, &then)); 267 1.8 riastrad timespecadd(&then, &its.it_value, &its.it_value); 268 1.8 riastrad RL(timerfd_settime(fd, TFD_TIMER_ABSTIME, &its, NULL)); 269 1.8 riastrad 270 1.8 riastrad /* 271 1.8 riastrad * Wait for one tick to pass. 272 1.8 riastrad * 273 1.8 riastrad * XXX Having to do this seems silly, but it matches Linux, so. 274 1.8 riastrad */ 275 1.8 riastrad RL(clock_nanosleep(CLOCK_MONOTONIC, 0, &(const struct timespec){0, 1}, 276 1.8 riastrad NULL)); 277 1.8 riastrad 278 1.8 riastrad RL(timerfd_read(fd, &val)); 279 1.8 riastrad RL(clock_gettime(CLOCK_MONOTONIC, &now)); 280 1.8 riastrad ATF_REQUIRE(check_value_against_bounds(val, 1, 1)); 281 1.8 riastrad 282 1.8 riastrad timespecsub(&now, &then, &delta); 283 1.8 riastrad ATF_CHECK_MSG(check_value_against_bounds(delta.tv_sec, 0, 0), 284 1.8 riastrad "then=%jd.%09lu now=%jd.%09lu delta=%jd.%09lu", 285 1.8 riastrad (intmax_t)then.tv_sec, then.tv_nsec, 286 1.8 riastrad (intmax_t)now.tv_sec, now.tv_nsec, 287 1.8 riastrad (intmax_t)delta.tv_sec, delta.tv_nsec); 288 1.8 riastrad 289 1.8 riastrad RL(close(fd)); 290 1.8 riastrad } 291 1.8 riastrad 292 1.8 riastrad /*****************************************************************************/ 293 1.8 riastrad 294 1.2 thorpej ATF_TC(timerfd_block); 295 1.2 thorpej ATF_TC_HEAD(timerfd_block, tc) 296 1.2 thorpej { 297 1.2 thorpej atf_tc_set_md_var(tc, "descr", "validates blocking behavior"); 298 1.2 thorpej } 299 1.2 thorpej ATF_TC_BODY(timerfd_block, tc) 300 1.2 thorpej { 301 1.2 thorpej struct timespec then, now, delta; 302 1.2 thorpej uint64_t val; 303 1.2 thorpej int fd; 304 1.2 thorpej 305 1.2 thorpej ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0); 306 1.2 thorpej 307 1.9 riastrad struct itimerspec oits; 308 1.2 thorpej const struct itimerspec its = { 309 1.2 thorpej .it_value = { .tv_sec = 1, .tv_nsec = 0 }, 310 1.2 thorpej .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, 311 1.2 thorpej }; 312 1.2 thorpej 313 1.2 thorpej ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 314 1.2 thorpej ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0); 315 1.9 riastrad ATF_REQUIRE(timerfd_settime(fd, 0, &its, &oits) == 0); 316 1.9 riastrad ATF_CHECK_MSG(timespeccmp(&oits.it_value, &its.it_value, <=), 317 1.9 riastrad "timerfd_settime returned %jd.%09lu remaining," 318 1.9 riastrad " expected at most %jd.%09lu", 319 1.9 riastrad (intmax_t)oits.it_value.tv_sec, oits.it_value.tv_nsec, 320 1.9 riastrad (intmax_t)its.it_value.tv_sec, its.it_value.tv_nsec); 321 1.2 thorpej ATF_REQUIRE(timerfd_read(fd, &val) == 0); 322 1.2 thorpej ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 323 1.3 hannken ATF_REQUIRE(check_value_against_bounds(val, 1, 1)); 324 1.2 thorpej 325 1.2 thorpej timespecsub(&now, &then, &delta); 326 1.5 riastrad ATF_REQUIRE_MSG(check_value_against_bounds(delta.tv_sec, 1, 1), 327 1.5 riastrad "then=%jd.%09lu now=%jd.%09lu delta=%jd.%09lu", 328 1.5 riastrad (intmax_t)then.tv_sec, then.tv_nsec, 329 1.5 riastrad (intmax_t)now.tv_sec, now.tv_nsec, 330 1.5 riastrad (intmax_t)delta.tv_sec, delta.tv_nsec); 331 1.2 thorpej 332 1.2 thorpej (void) close(fd); 333 1.2 thorpej } 334 1.2 thorpej 335 1.2 thorpej /*****************************************************************************/ 336 1.2 thorpej 337 1.2 thorpej ATF_TC(timerfd_repeating); 338 1.2 thorpej ATF_TC_HEAD(timerfd_repeating, tc) 339 1.2 thorpej { 340 1.2 thorpej atf_tc_set_md_var(tc, "descr", "validates repeating timer behavior"); 341 1.2 thorpej } 342 1.2 thorpej ATF_TC_BODY(timerfd_repeating, tc) 343 1.2 thorpej { 344 1.2 thorpej struct timespec then, now, delta; 345 1.2 thorpej uint64_t val; 346 1.2 thorpej int fd; 347 1.2 thorpej 348 1.2 thorpej ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, 349 1.2 thorpej TFD_NONBLOCK)) >= 0); 350 1.2 thorpej 351 1.2 thorpej const struct itimerspec its = { 352 1.2 thorpej .it_value = { .tv_sec = 0, .tv_nsec = 200000000 }, 353 1.2 thorpej .it_interval = { .tv_sec = 0, .tv_nsec = 200000000 }, 354 1.2 thorpej }; 355 1.2 thorpej 356 1.2 thorpej ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 357 1.2 thorpej ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0); 358 1.2 thorpej ATF_REQUIRE(sleep(1) == 0); 359 1.2 thorpej ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 360 1.2 thorpej ATF_REQUIRE(timerfd_read(fd, &val) == 0); 361 1.3 hannken /* allow some slop */ 362 1.3 hannken ATF_REQUIRE(check_value_against_bounds(val, 3, 5)); 363 1.2 thorpej 364 1.2 thorpej timespecsub(&now, &then, &delta); 365 1.5 riastrad ATF_REQUIRE_MSG(check_value_against_bounds(delta.tv_sec, 1, 1), 366 1.5 riastrad "then=%jd.%09lu now=%jd.%09lu delta=%jd.%09lu", 367 1.5 riastrad (intmax_t)then.tv_sec, then.tv_nsec, 368 1.5 riastrad (intmax_t)now.tv_sec, now.tv_nsec, 369 1.5 riastrad (intmax_t)delta.tv_sec, delta.tv_nsec); 370 1.2 thorpej 371 1.2 thorpej (void) close(fd); 372 1.2 thorpej } 373 1.2 thorpej 374 1.2 thorpej /*****************************************************************************/ 375 1.2 thorpej 376 1.2 thorpej ATF_TC(timerfd_abstime); 377 1.2 thorpej ATF_TC_HEAD(timerfd_abstime, tc) 378 1.2 thorpej { 379 1.2 thorpej atf_tc_set_md_var(tc, "descr", "validates specifying abstime"); 380 1.2 thorpej } 381 1.2 thorpej ATF_TC_BODY(timerfd_abstime, tc) 382 1.2 thorpej { 383 1.2 thorpej struct timespec then, now, delta; 384 1.2 thorpej uint64_t val; 385 1.2 thorpej int fd; 386 1.2 thorpej 387 1.2 thorpej ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0); 388 1.2 thorpej 389 1.9 riastrad struct itimerspec oits, its = { 390 1.2 thorpej .it_value = { .tv_sec = 0, .tv_nsec = 0 }, 391 1.2 thorpej .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, 392 1.2 thorpej }; 393 1.2 thorpej 394 1.2 thorpej ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 395 1.9 riastrad delta = (struct timespec){1, 0}; 396 1.9 riastrad timespecadd(&then, &delta, &its.it_value); 397 1.2 thorpej ATF_REQUIRE(timerfd_settime(fd, TFD_TIMER_ABSTIME, &its, NULL) == 0); 398 1.9 riastrad ATF_REQUIRE(timerfd_settime(fd, TFD_TIMER_ABSTIME, &its, &oits) == 0); 399 1.9 riastrad timespecadd(&delta, (&(const struct timespec){2, 0}), /* tick slop */ 400 1.9 riastrad &delta); 401 1.9 riastrad ATF_CHECK_MSG(timespeccmp(&oits.it_value, &delta, <=), 402 1.9 riastrad "timerfd_settime returned %jd.%09lu remaining," 403 1.9 riastrad " expected at most %jd.%09lu", 404 1.9 riastrad (intmax_t)oits.it_value.tv_sec, oits.it_value.tv_nsec, 405 1.9 riastrad (intmax_t)delta.tv_sec, delta.tv_nsec); 406 1.2 thorpej ATF_REQUIRE(timerfd_read(fd, &val) == 0); 407 1.2 thorpej ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 408 1.3 hannken ATF_REQUIRE(check_value_against_bounds(val, 1, 1)); 409 1.2 thorpej 410 1.2 thorpej timespecsub(&now, &then, &delta); 411 1.5 riastrad ATF_REQUIRE_MSG(check_value_against_bounds(delta.tv_sec, 1, 1), 412 1.5 riastrad "then=%jd.%09lu now=%jd.%09lu delta=%jd.%09lu", 413 1.5 riastrad (intmax_t)then.tv_sec, then.tv_nsec, 414 1.5 riastrad (intmax_t)now.tv_sec, now.tv_nsec, 415 1.5 riastrad (intmax_t)delta.tv_sec, delta.tv_nsec); 416 1.2 thorpej 417 1.2 thorpej (void) close(fd); 418 1.2 thorpej } 419 1.2 thorpej 420 1.2 thorpej /*****************************************************************************/ 421 1.2 thorpej 422 1.2 thorpej ATF_TC(timerfd_cancel_on_set_immed); 423 1.2 thorpej ATF_TC_HEAD(timerfd_cancel_on_set_immed, tc) 424 1.2 thorpej { 425 1.2 thorpej atf_tc_set_md_var(tc, "descr", "validates cancel-on-set - immediate"); 426 1.2 thorpej atf_tc_set_md_var(tc, "require.user", "root"); 427 1.2 thorpej } 428 1.2 thorpej ATF_TC_BODY(timerfd_cancel_on_set_immed, tc) 429 1.2 thorpej { 430 1.2 thorpej struct timespec now; 431 1.2 thorpej uint64_t val; 432 1.2 thorpej int fd; 433 1.2 thorpej 434 1.2 thorpej ATF_REQUIRE((fd = timerfd_create(CLOCK_REALTIME, 0)) >= 0); 435 1.2 thorpej 436 1.2 thorpej const struct itimerspec its = { 437 1.2 thorpej .it_value = { .tv_sec = 60 * 60, .tv_nsec = 0 }, 438 1.2 thorpej .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, 439 1.2 thorpej }; 440 1.2 thorpej 441 1.2 thorpej ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &now) == 0); 442 1.2 thorpej ATF_REQUIRE(timerfd_settime(fd, TFD_TIMER_CANCEL_ON_SET, 443 1.2 thorpej &its, NULL) == 0); 444 1.2 thorpej ATF_REQUIRE(clock_settime(CLOCK_REALTIME, &now) == 0); 445 1.2 thorpej ATF_REQUIRE_ERRNO(ECANCELED, timerfd_read(fd, &val) == -1); 446 1.2 thorpej 447 1.2 thorpej (void) close(fd); 448 1.2 thorpej } 449 1.2 thorpej 450 1.2 thorpej /*****************************************************************************/ 451 1.2 thorpej 452 1.2 thorpej static void * 453 1.2 thorpej timerfd_cancel_on_set_block_helper(void * const v) 454 1.2 thorpej { 455 1.2 thorpej struct helper_context * const ctx = v; 456 1.2 thorpej struct timespec now; 457 1.2 thorpej 458 1.2 thorpej ATF_REQUIRE(wait_barrier(ctx)); 459 1.2 thorpej 460 1.2 thorpej ATF_REQUIRE(sleep(2) == 0); 461 1.2 thorpej ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &now) == 0); 462 1.2 thorpej ATF_REQUIRE(clock_settime(CLOCK_REALTIME, &now) == 0); 463 1.2 thorpej 464 1.2 thorpej return NULL; 465 1.2 thorpej } 466 1.2 thorpej 467 1.2 thorpej ATF_TC(timerfd_cancel_on_set_block); 468 1.2 thorpej ATF_TC_HEAD(timerfd_cancel_on_set_block, tc) 469 1.2 thorpej { 470 1.2 thorpej atf_tc_set_md_var(tc, "descr", "validates cancel-on-set - blocking"); 471 1.2 thorpej atf_tc_set_md_var(tc, "require.user", "root"); 472 1.2 thorpej } 473 1.2 thorpej ATF_TC_BODY(timerfd_cancel_on_set_block, tc) 474 1.2 thorpej { 475 1.2 thorpej struct helper_context ctx; 476 1.2 thorpej pthread_t helper; 477 1.2 thorpej void *join_val; 478 1.2 thorpej uint64_t val; 479 1.2 thorpej int fd; 480 1.2 thorpej 481 1.2 thorpej ATF_REQUIRE((fd = timerfd_create(CLOCK_REALTIME, 0)) >= 0); 482 1.2 thorpej 483 1.2 thorpej const struct itimerspec its = { 484 1.2 thorpej .it_value = { .tv_sec = 60 * 60, .tv_nsec = 0 }, 485 1.2 thorpej .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, 486 1.2 thorpej }; 487 1.2 thorpej 488 1.2 thorpej init_helper_context(&ctx); 489 1.2 thorpej 490 1.2 thorpej ATF_REQUIRE(timerfd_settime(fd, TFD_TIMER_CANCEL_ON_SET, 491 1.2 thorpej &its, NULL) == 0); 492 1.2 thorpej ATF_REQUIRE(pthread_create(&helper, NULL, 493 1.2 thorpej timerfd_cancel_on_set_block_helper, &ctx) == 0); 494 1.2 thorpej ATF_REQUIRE(wait_barrier(&ctx)); 495 1.2 thorpej ATF_REQUIRE_ERRNO(ECANCELED, timerfd_read(fd, &val) == -1); 496 1.2 thorpej 497 1.2 thorpej ATF_REQUIRE(pthread_join(helper, &join_val) == 0); 498 1.2 thorpej 499 1.2 thorpej (void) close(fd); 500 1.2 thorpej } 501 1.2 thorpej 502 1.2 thorpej /*****************************************************************************/ 503 1.2 thorpej 504 1.2 thorpej ATF_TC(timerfd_select_poll_kevent_immed); 505 1.2 thorpej ATF_TC_HEAD(timerfd_select_poll_kevent_immed, tc) 506 1.2 thorpej { 507 1.2 thorpej atf_tc_set_md_var(tc, "descr", 508 1.2 thorpej "validates select/poll/kevent behavior - immediate return"); 509 1.2 thorpej } 510 1.2 thorpej ATF_TC_BODY(timerfd_select_poll_kevent_immed, tc) 511 1.2 thorpej { 512 1.2 thorpej const struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; 513 1.2 thorpej struct itimerspec its; 514 1.2 thorpej struct timeval tv; 515 1.2 thorpej struct stat st; 516 1.2 thorpej struct pollfd fds[1]; 517 1.2 thorpej uint64_t val; 518 1.2 thorpej fd_set readfds, writefds, exceptfds; 519 1.2 thorpej int fd; 520 1.2 thorpej int kq; 521 1.2 thorpej struct kevent kev[1]; 522 1.2 thorpej 523 1.2 thorpej ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)) >= 0); 524 1.2 thorpej 525 1.2 thorpej ATF_REQUIRE((kq = kqueue()) >= 0); 526 1.2 thorpej EV_SET(&kev[0], fd, EVFILT_READ, EV_ADD, 0, 0, NULL); 527 1.2 thorpej ATF_REQUIRE(kevent(kq, kev, 1, NULL, 0, &ts) == 0); 528 1.7 riastrad EV_SET(&kev[0], fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL); 529 1.7 riastrad ATF_CHECK_ERRNO(EINVAL, kevent(kq, kev, 1, NULL, 0, &ts) == -1); 530 1.2 thorpej 531 1.2 thorpej /* 532 1.6 riastrad * fd should not be ready for anything. Pass all of the event 533 1.6 riastrad * bits; we should get back nothing. 534 1.2 thorpej */ 535 1.2 thorpej fds[0].fd = fd; 536 1.2 thorpej fds[0].events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI | 537 1.2 thorpej POLLOUT | POLLWRNORM | POLLWRBAND | POLLHUP; 538 1.2 thorpej fds[0].revents = 0; 539 1.7 riastrad ATF_REQUIRE(poll(fds, 1, 0) == 0); 540 1.2 thorpej 541 1.2 thorpej /* 542 1.6 riastrad * As above; fd should not be set on return from the select() 543 1.6 riastrad * call. 544 1.2 thorpej */ 545 1.2 thorpej FD_ZERO(&readfds); 546 1.2 thorpej FD_ZERO(&writefds); 547 1.2 thorpej FD_ZERO(&exceptfds); 548 1.2 thorpej tv.tv_sec = 0; 549 1.2 thorpej tv.tv_usec = 0; 550 1.2 thorpej FD_SET(fd, &readfds); 551 1.2 thorpej FD_SET(fd, &writefds); 552 1.2 thorpej FD_SET(fd, &exceptfds); 553 1.7 riastrad ATF_REQUIRE(select(fd + 1, &readfds, &writefds, &exceptfds, &tv) == 0); 554 1.2 thorpej ATF_REQUIRE(!FD_ISSET(fd, &readfds)); 555 1.6 riastrad ATF_REQUIRE(!FD_ISSET(fd, &writefds)); 556 1.2 thorpej ATF_REQUIRE(!FD_ISSET(fd, &exceptfds)); 557 1.2 thorpej 558 1.2 thorpej /* 559 1.2 thorpej * Now set a one-shot half-second timer, wait for it to expire, and 560 1.2 thorpej * then check again. 561 1.2 thorpej */ 562 1.2 thorpej memset(&its, 0, sizeof(its)); 563 1.2 thorpej its.it_value.tv_sec = 0; 564 1.2 thorpej its.it_value.tv_nsec = 500000000; 565 1.2 thorpej ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0); 566 1.2 thorpej ATF_REQUIRE(sleep(2) == 0); 567 1.2 thorpej 568 1.2 thorpej /* Verify it actually fired via the stat() back-channel. */ 569 1.2 thorpej ATF_REQUIRE(fstat(fd, &st) == 0); 570 1.2 thorpej ATF_REQUIRE(st.st_size == 1); 571 1.2 thorpej 572 1.2 thorpej fds[0].fd = fd; 573 1.2 thorpej fds[0].events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI | 574 1.2 thorpej POLLOUT | POLLWRNORM | POLLWRBAND | POLLHUP; 575 1.2 thorpej fds[0].revents = 0; 576 1.2 thorpej ATF_REQUIRE(poll(fds, 1, 0) == 1); 577 1.6 riastrad ATF_REQUIRE(fds[0].revents == (POLLIN | POLLRDNORM)); 578 1.2 thorpej 579 1.2 thorpej FD_ZERO(&readfds); 580 1.2 thorpej FD_ZERO(&writefds); 581 1.2 thorpej FD_ZERO(&exceptfds); 582 1.2 thorpej tv.tv_sec = 0; 583 1.2 thorpej tv.tv_usec = 0; 584 1.2 thorpej FD_SET(fd, &readfds); 585 1.2 thorpej FD_SET(fd, &writefds); 586 1.2 thorpej FD_SET(fd, &exceptfds); 587 1.7 riastrad ATF_REQUIRE(select(fd + 1, &readfds, &writefds, &exceptfds, &tv) == 1); 588 1.2 thorpej ATF_REQUIRE(FD_ISSET(fd, &readfds)); 589 1.6 riastrad ATF_REQUIRE(!FD_ISSET(fd, &writefds)); 590 1.2 thorpej ATF_REQUIRE(!FD_ISSET(fd, &exceptfds)); 591 1.2 thorpej 592 1.2 thorpej /* 593 1.2 thorpej * Check that we get an EVFILT_READ event on fd. 594 1.2 thorpej */ 595 1.2 thorpej memset(kev, 0, sizeof(kev)); 596 1.2 thorpej ATF_REQUIRE(kevent(kq, NULL, 0, kev, 1, &ts) == 1); 597 1.2 thorpej ATF_REQUIRE(kev[0].ident == (uintptr_t)fd); 598 1.2 thorpej ATF_REQUIRE(kev[0].filter == EVFILT_READ); 599 1.2 thorpej ATF_REQUIRE((kev[0].flags & (EV_EOF | EV_ERROR)) == 0); 600 1.2 thorpej ATF_REQUIRE(kev[0].data == 1); 601 1.2 thorpej 602 1.2 thorpej /* 603 1.2 thorpej * Read the timerfd to ensure we get the correct numnber of 604 1.2 thorpej * expirations. 605 1.2 thorpej */ 606 1.2 thorpej ATF_REQUIRE(timerfd_read(fd, &val) == 0); 607 1.2 thorpej ATF_REQUIRE(val == 1); 608 1.2 thorpej 609 1.2 thorpej /* And ensure that we would block if we tried again. */ 610 1.2 thorpej ATF_REQUIRE_ERRNO(EAGAIN, timerfd_read(fd, &val) == -1); 611 1.2 thorpej 612 1.2 thorpej (void) close(kq); 613 1.2 thorpej (void) close(fd); 614 1.2 thorpej } 615 1.2 thorpej 616 1.2 thorpej /*****************************************************************************/ 617 1.2 thorpej 618 1.2 thorpej ATF_TC(timerfd_select_poll_kevent_block); 619 1.2 thorpej ATF_TC_HEAD(timerfd_select_poll_kevent_block, tc) 620 1.2 thorpej { 621 1.2 thorpej atf_tc_set_md_var(tc, "descr", 622 1.2 thorpej "validates select/poll/kevent behavior - blocking"); 623 1.2 thorpej } 624 1.2 thorpej ATF_TC_BODY(timerfd_select_poll_kevent_block, tc) 625 1.2 thorpej { 626 1.2 thorpej const struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; 627 1.2 thorpej struct timespec then, now; 628 1.2 thorpej struct pollfd fds[1]; 629 1.2 thorpej fd_set readfds; 630 1.2 thorpej int fd; 631 1.2 thorpej int kq; 632 1.2 thorpej struct kevent kev[1]; 633 1.2 thorpej 634 1.2 thorpej ATF_REQUIRE((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)) >= 0); 635 1.2 thorpej 636 1.2 thorpej ATF_REQUIRE((kq = kqueue()) >= 0); 637 1.2 thorpej EV_SET(&kev[0], fd, EVFILT_READ, EV_ADD, 0, 0, NULL); 638 1.2 thorpej ATF_REQUIRE(kevent(kq, kev, 1, NULL, 0, &ts) == 0); 639 1.2 thorpej 640 1.2 thorpej /* 641 1.2 thorpej * For each of these tests, we do the following: 642 1.2 thorpej * 643 1.2 thorpej * - Get the current time. 644 1.2 thorpej * - Set a 1-second one-shot timer. 645 1.2 thorpej * - Block in the multiplexing call. 646 1.2 thorpej * - Get the current time and verify that the timer expiration 647 1.2 thorpej * interval has passed. 648 1.2 thorpej */ 649 1.2 thorpej 650 1.2 thorpej const struct itimerspec its = { 651 1.2 thorpej .it_value = { .tv_sec = 1, .tv_nsec = 0 }, 652 1.2 thorpej .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, 653 1.2 thorpej }; 654 1.2 thorpej 655 1.2 thorpej /* poll(2) */ 656 1.2 thorpej fds[0].fd = fd; 657 1.2 thorpej fds[0].events = POLLIN | POLLRDNORM; 658 1.2 thorpej fds[0].revents = 0; 659 1.2 thorpej 660 1.2 thorpej ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 661 1.2 thorpej ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0); 662 1.2 thorpej ATF_REQUIRE(poll(fds, 1, INFTIM) == 1); 663 1.2 thorpej ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 664 1.2 thorpej ATF_REQUIRE(fds[0].revents == (POLLIN | POLLRDNORM)); 665 1.2 thorpej ATF_REQUIRE(now.tv_sec - then.tv_sec >= 1); 666 1.2 thorpej 667 1.2 thorpej /* select(2) */ 668 1.2 thorpej FD_ZERO(&readfds); 669 1.2 thorpej FD_SET(fd, &readfds); 670 1.2 thorpej 671 1.2 thorpej ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 672 1.2 thorpej ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0); 673 1.2 thorpej ATF_REQUIRE(select(fd + 1, &readfds, NULL, NULL, NULL) == 1); 674 1.2 thorpej ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 675 1.2 thorpej ATF_REQUIRE(FD_ISSET(fd, &readfds)); 676 1.2 thorpej ATF_REQUIRE(now.tv_sec - then.tv_sec >= 1); 677 1.2 thorpej 678 1.2 thorpej /* kevent(2) */ 679 1.2 thorpej memset(kev, 0, sizeof(kev)); 680 1.2 thorpej ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 681 1.2 thorpej ATF_REQUIRE(timerfd_settime(fd, 0, &its, NULL) == 0); 682 1.2 thorpej ATF_REQUIRE(kevent(kq, NULL, 0, kev, 1, NULL) == 1); 683 1.2 thorpej ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 684 1.2 thorpej ATF_REQUIRE(kev[0].ident == (uintptr_t)fd); 685 1.2 thorpej ATF_REQUIRE(kev[0].filter == EVFILT_READ); 686 1.2 thorpej ATF_REQUIRE((kev[0].flags & (EV_EOF | EV_ERROR)) == 0); 687 1.2 thorpej ATF_REQUIRE(kev[0].data == 1); 688 1.2 thorpej 689 1.2 thorpej (void) close(kq); 690 1.2 thorpej (void) close(fd); 691 1.2 thorpej } 692 1.2 thorpej 693 1.2 thorpej /*****************************************************************************/ 694 1.2 thorpej 695 1.2 thorpej static void * 696 1.2 thorpej timerfd_restart_helper(void * const v) 697 1.2 thorpej { 698 1.2 thorpej struct helper_context * const ctx = v; 699 1.2 thorpej 700 1.2 thorpej ATF_REQUIRE(wait_barrier(ctx)); 701 1.2 thorpej 702 1.2 thorpej /* 703 1.2 thorpej * Wait 5 seconds (that should give the main thread time to 704 1.2 thorpej * block), and then close the descriptor. 705 1.2 thorpej */ 706 1.2 thorpej ATF_REQUIRE(sleep(5) == 0); 707 1.2 thorpej ATF_REQUIRE(close(ctx->fd) == 0); 708 1.2 thorpej 709 1.2 thorpej return NULL; 710 1.2 thorpej } 711 1.2 thorpej 712 1.2 thorpej ATF_TC(timerfd_restart); 713 1.2 thorpej ATF_TC_HEAD(timerfd_restart, tc) 714 1.2 thorpej { 715 1.2 thorpej atf_tc_set_md_var(tc, "descr", 716 1.2 thorpej "exercises the 'restart' fileop code path"); 717 1.2 thorpej } 718 1.2 thorpej ATF_TC_BODY(timerfd_restart, tc) 719 1.2 thorpej { 720 1.2 thorpej struct timespec then, now, delta; 721 1.2 thorpej struct helper_context ctx; 722 1.2 thorpej uint64_t val; 723 1.2 thorpej pthread_t helper; 724 1.2 thorpej void *join_val; 725 1.2 thorpej 726 1.2 thorpej init_helper_context(&ctx); 727 1.2 thorpej 728 1.2 thorpej ATF_REQUIRE((ctx.fd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0); 729 1.2 thorpej 730 1.2 thorpej const struct itimerspec its = { 731 1.2 thorpej .it_value = { .tv_sec = 60 * 60, .tv_nsec = 0 }, 732 1.2 thorpej .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, 733 1.2 thorpej }; 734 1.2 thorpej ATF_REQUIRE(timerfd_settime(ctx.fd, 0, &its, NULL) == 0); 735 1.2 thorpej 736 1.2 thorpej 737 1.2 thorpej ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &then) == 0); 738 1.2 thorpej ATF_REQUIRE(pthread_create(&helper, NULL, 739 1.2 thorpej timerfd_restart_helper, &ctx) == 0); 740 1.2 thorpej 741 1.2 thorpej /* 742 1.2 thorpej * Wait for the helper to be ready, and then immediately block 743 1.2 thorpej * in read(). The helper will close the file, and we should get 744 1.2 thorpej * EBADF after a few seconds. 745 1.2 thorpej */ 746 1.2 thorpej ATF_REQUIRE(wait_barrier(&ctx)); 747 1.2 thorpej ATF_REQUIRE_ERRNO(EBADF, timerfd_read(ctx.fd, &val) == -1); 748 1.2 thorpej ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &now) == 0); 749 1.2 thorpej 750 1.2 thorpej timespecsub(&now, &then, &delta); 751 1.2 thorpej ATF_REQUIRE(delta.tv_sec >= 5); 752 1.2 thorpej 753 1.2 thorpej /* Reap the helper. */ 754 1.2 thorpej ATF_REQUIRE(pthread_join(helper, &join_val) == 0); 755 1.2 thorpej } 756 1.2 thorpej 757 1.2 thorpej /*****************************************************************************/ 758 1.2 thorpej 759 1.4 thorpej ATF_TC(timerfd_fcntl); 760 1.4 thorpej ATF_TC_HEAD(timerfd_fcntl, tc) 761 1.4 thorpej { 762 1.4 thorpej atf_tc_set_md_var(tc, "descr", 763 1.4 thorpej "validates fcntl behavior"); 764 1.4 thorpej } 765 1.4 thorpej 766 1.4 thorpej ATF_TC_BODY(timerfd_fcntl, tc) 767 1.4 thorpej { 768 1.4 thorpej int tfd; 769 1.4 thorpej int val; 770 1.4 thorpej 771 1.4 thorpej ATF_REQUIRE((tfd = timerfd_create(CLOCK_MONOTONIC, 0)) >= 0); 772 1.4 thorpej ATF_REQUIRE((fcntl(tfd, F_GETFL) & O_NONBLOCK) == 0); 773 1.4 thorpej ATF_REQUIRE(fcntl(tfd, F_SETFL, O_NONBLOCK) == 0); 774 1.4 thorpej ATF_REQUIRE((fcntl(tfd, F_GETFL) & O_NONBLOCK) != 0); 775 1.4 thorpej ATF_REQUIRE((fcntl(tfd, F_GETFD) & FD_CLOEXEC) == 0); 776 1.4 thorpej 777 1.4 thorpej /* If the timer hasn't fired, there is no readable data. */ 778 1.4 thorpej ATF_REQUIRE(ioctl(tfd, FIONREAD, &val) == 0); 779 1.4 thorpej ATF_REQUIRE(val == 0); 780 1.4 thorpej 781 1.4 thorpej ATF_REQUIRE_ERRNO(ENOTTY, ioctl(tfd, FIONWRITE, &val) == -1); 782 1.4 thorpej ATF_REQUIRE_ERRNO(ENOTTY, ioctl(tfd, FIONSPACE, &val) == -1); 783 1.4 thorpej (void)close(tfd); 784 1.4 thorpej 785 1.4 thorpej ATF_REQUIRE((tfd = timerfd_create(CLOCK_MONOTONIC, 786 1.4 thorpej TFD_NONBLOCK | TFD_CLOEXEC)) >= 0); 787 1.4 thorpej ATF_REQUIRE((fcntl(tfd, F_GETFL) & ~O_ACCMODE) == O_NONBLOCK); 788 1.4 thorpej ATF_REQUIRE((fcntl(tfd, F_GETFD) & FD_CLOEXEC) != 0); 789 1.4 thorpej ATF_REQUIRE(fcntl(tfd, F_SETFD, 0) == 0); 790 1.4 thorpej ATF_REQUIRE((fcntl(tfd, F_GETFD) & FD_CLOEXEC) == 0); 791 1.4 thorpej ATF_REQUIRE(fcntl(tfd, F_SETFD, FD_CLOEXEC) == 0); 792 1.4 thorpej ATF_REQUIRE((fcntl(tfd, F_GETFD) & FD_CLOEXEC) != 0); 793 1.4 thorpej (void)close(tfd); 794 1.4 thorpej } 795 1.4 thorpej 796 1.4 thorpej /*****************************************************************************/ 797 1.4 thorpej 798 1.2 thorpej ATF_TP_ADD_TCS(tp) 799 1.2 thorpej { 800 1.8 riastrad 801 1.2 thorpej ATF_TP_ADD_TC(tp, timerfd_create); 802 1.8 riastrad ATF_TP_ADD_TC(tp, timerfd_write); 803 1.2 thorpej ATF_TP_ADD_TC(tp, timerfd_bogusfd); 804 1.8 riastrad ATF_TP_ADD_TC(tp, timerfd_invalidtime); 805 1.8 riastrad ATF_TP_ADD_TC(tp, timerfd_past); 806 1.2 thorpej ATF_TP_ADD_TC(tp, timerfd_block); 807 1.2 thorpej ATF_TP_ADD_TC(tp, timerfd_repeating); 808 1.2 thorpej ATF_TP_ADD_TC(tp, timerfd_abstime); 809 1.2 thorpej ATF_TP_ADD_TC(tp, timerfd_cancel_on_set_block); 810 1.2 thorpej ATF_TP_ADD_TC(tp, timerfd_cancel_on_set_immed); 811 1.2 thorpej ATF_TP_ADD_TC(tp, timerfd_select_poll_kevent_immed); 812 1.2 thorpej ATF_TP_ADD_TC(tp, timerfd_select_poll_kevent_block); 813 1.2 thorpej ATF_TP_ADD_TC(tp, timerfd_restart); 814 1.4 thorpej ATF_TP_ADD_TC(tp, timerfd_fcntl); 815 1.2 thorpej 816 1.2 thorpej return atf_no_error(); 817 1.2 thorpej } 818