1*b61cc256Sriastradh /* $NetBSD: t_timer_create.c,v 1.9 2024/12/19 23:41:46 riastradh Exp $ */ 2068fb4f1Sjruoho 3068fb4f1Sjruoho /*- 4068fb4f1Sjruoho * Copyright (c) 2010 The NetBSD Foundation, Inc. 5068fb4f1Sjruoho * All rights reserved. 6068fb4f1Sjruoho * 7068fb4f1Sjruoho * Redistribution and use in source and binary forms, with or without 8068fb4f1Sjruoho * modification, are permitted provided that the following conditions 9068fb4f1Sjruoho * are met: 10068fb4f1Sjruoho * 1. Redistributions of source code must retain the above copyright 11068fb4f1Sjruoho * notice, this list of conditions and the following disclaimer. 12068fb4f1Sjruoho * 2. Redistributions in binary form must reproduce the above copyright 13068fb4f1Sjruoho * notice, this list of conditions and the following disclaimer in the 14068fb4f1Sjruoho * documentation and/or other materials provided with the distribution. 15068fb4f1Sjruoho * 16068fb4f1Sjruoho * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17068fb4f1Sjruoho * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18068fb4f1Sjruoho * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19068fb4f1Sjruoho * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20068fb4f1Sjruoho * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21068fb4f1Sjruoho * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22068fb4f1Sjruoho * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23068fb4f1Sjruoho * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24068fb4f1Sjruoho * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25068fb4f1Sjruoho * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26068fb4f1Sjruoho * POSSIBILITY OF SUCH DAMAGE. 27068fb4f1Sjruoho */ 28068fb4f1Sjruoho 299cbb4897Sjruoho #include <atf-c.h> 30068fb4f1Sjruoho #include <errno.h> 319cbb4897Sjruoho #include <stdio.h> 32068fb4f1Sjruoho #include <signal.h> 33068fb4f1Sjruoho #include <string.h> 34068fb4f1Sjruoho #include <time.h> 35068fb4f1Sjruoho #include <unistd.h> 36068fb4f1Sjruoho 37c7921dd2Sriastradh #include "h_macros.h" 38c7921dd2Sriastradh 39068fb4f1Sjruoho static timer_t t; 40c7921dd2Sriastradh static sig_atomic_t expired; 41c7921dd2Sriastradh 42c7921dd2Sriastradh enum mode { 43c7921dd2Sriastradh PAST, 44c7921dd2Sriastradh EXPIRE, 45c7921dd2Sriastradh NOEXPIRE, 46c7921dd2Sriastradh }; 47068fb4f1Sjruoho 489cbb4897Sjruoho static void 49424ba067Schristos timer_signal_handler(int signo, siginfo_t *si, void *osi __unused) 50068fb4f1Sjruoho { 518aa55f9bSriastradh const int errno_save = errno; 529cbb4897Sjruoho timer_t *tp; 53068fb4f1Sjruoho 549cbb4897Sjruoho tp = si->si_value.sival_ptr; 559cbb4897Sjruoho 569cbb4897Sjruoho if (*tp == t && signo == SIGALRM) 57c7921dd2Sriastradh expired = 1; 589cbb4897Sjruoho 599cbb4897Sjruoho (void)fprintf(stderr, "%s: %s\n", __func__, strsignal(signo)); 608aa55f9bSriastradh errno = errno_save; 61068fb4f1Sjruoho } 62068fb4f1Sjruoho 639cbb4897Sjruoho static void 64c7921dd2Sriastradh timer_signal_create(clockid_t cid, enum mode mode, int flags) 65068fb4f1Sjruoho { 66c7921dd2Sriastradh struct itimerspec tim, rtim, otim; 67c7921dd2Sriastradh struct timespec t0, t1, dt; 689cbb4897Sjruoho struct sigaction act; 69068fb4f1Sjruoho struct sigevent evt; 709cbb4897Sjruoho sigset_t set; 71068fb4f1Sjruoho 72068fb4f1Sjruoho t = 0; 73c7921dd2Sriastradh expired = 0; 74068fb4f1Sjruoho 759cbb4897Sjruoho (void)memset(&evt, 0, sizeof(struct sigevent)); 769cbb4897Sjruoho (void)memset(&act, 0, sizeof(struct sigaction)); 779cbb4897Sjruoho (void)memset(&tim, 0, sizeof(struct itimerspec)); 78068fb4f1Sjruoho 799cbb4897Sjruoho /* 809cbb4897Sjruoho * Set handler. 819cbb4897Sjruoho */ 829cbb4897Sjruoho act.sa_flags = SA_SIGINFO; 839cbb4897Sjruoho act.sa_sigaction = timer_signal_handler; 849cbb4897Sjruoho 859cbb4897Sjruoho ATF_REQUIRE(sigemptyset(&set) == 0); 869cbb4897Sjruoho ATF_REQUIRE(sigemptyset(&act.sa_mask) == 0); 879cbb4897Sjruoho 889cbb4897Sjruoho /* 899cbb4897Sjruoho * Block SIGALRM while configuring the timer. 909cbb4897Sjruoho */ 919cbb4897Sjruoho ATF_REQUIRE(sigaction(SIGALRM, &act, NULL) == 0); 929cbb4897Sjruoho ATF_REQUIRE(sigaddset(&set, SIGALRM) == 0); 939cbb4897Sjruoho ATF_REQUIRE(sigprocmask(SIG_SETMASK, &set, NULL) == 0); 949cbb4897Sjruoho 959cbb4897Sjruoho /* 969cbb4897Sjruoho * Create the timer (SIGEV_SIGNAL). 979cbb4897Sjruoho */ 989cbb4897Sjruoho evt.sigev_signo = SIGALRM; 999cbb4897Sjruoho evt.sigev_value.sival_ptr = &t; 1009cbb4897Sjruoho evt.sigev_notify = SIGEV_SIGNAL; 1019cbb4897Sjruoho 1029cbb4897Sjruoho ATF_REQUIRE(timer_create(cid, &evt, &t) == 0); 1039cbb4897Sjruoho 1049cbb4897Sjruoho /* 105c7921dd2Sriastradh * Configure the timer for -1, 1, or 5 sec from now, depending 106c7921dd2Sriastradh * on whether we want it to have fired, to fire within 2sec, or 107c7921dd2Sriastradh * to not fire within 2sec. 1089cbb4897Sjruoho */ 109c7921dd2Sriastradh switch (mode) { 110c7921dd2Sriastradh case PAST: 1118aa55f9bSriastradh ATF_REQUIRE(flags & TIMER_ABSTIME); 112c7921dd2Sriastradh tim.it_value.tv_sec = -1; 113c7921dd2Sriastradh break; 114c7921dd2Sriastradh case EXPIRE: 115c7921dd2Sriastradh tim.it_value.tv_sec = 1; 116c7921dd2Sriastradh break; 117c7921dd2Sriastradh case NOEXPIRE: 118c7921dd2Sriastradh tim.it_value.tv_sec = 5; 119c7921dd2Sriastradh break; 120c7921dd2Sriastradh } 1219cbb4897Sjruoho tim.it_value.tv_nsec = 0; 1229cbb4897Sjruoho 123c7921dd2Sriastradh /* 124c7921dd2Sriastradh * Save the relative time and adjust for absolute time of 125c7921dd2Sriastradh * requested. 126c7921dd2Sriastradh */ 127c7921dd2Sriastradh rtim = tim; 128c7921dd2Sriastradh RL(clock_gettime(cid, &t0)); 129c7921dd2Sriastradh if (flags & TIMER_ABSTIME) 130c7921dd2Sriastradh timespecadd(&t0, &tim.it_value, &tim.it_value); 131c7921dd2Sriastradh 132c7921dd2Sriastradh fprintf(stderr, "now is %lld sec %d nsec\n", 133c7921dd2Sriastradh (long long)t0.tv_sec, (int)t0.tv_nsec); 134c7921dd2Sriastradh fprintf(stderr, "expire at %lld sec %d nsec\n", 135c7921dd2Sriastradh (long long)tim.it_value.tv_sec, (int)tim.it_value.tv_nsec); 136c7921dd2Sriastradh RL(timer_settime(t, flags, &tim, NULL)); 137c7921dd2Sriastradh RL(timer_settime(t, flags, &tim, &otim)); 138c7921dd2Sriastradh 139c7921dd2Sriastradh RL(clock_gettime(cid, &t1)); 140c7921dd2Sriastradh timespecsub(&t1, &t0, &dt); 141c7921dd2Sriastradh fprintf(stderr, "%lld sec %d nsec elapsed\n", 142c7921dd2Sriastradh (long long)dt.tv_sec, (int)dt.tv_nsec); 143c7921dd2Sriastradh 144c7921dd2Sriastradh /* 145c7921dd2Sriastradh * Check to make sure the time remaining is at most the 1468aa55f9bSriastradh * relative time we expected -- plus slop of up to 2sec, 1478aa55f9bSriastradh * because timer_settime rounds the duration up to a multiple 1488aa55f9bSriastradh * of a tick period, which is at most 1sec (usually more like 1498aa55f9bSriastradh * 10ms or 1ms, and in the future with high-resolution timers 1508aa55f9bSriastradh * it'll be more like clock_getres(cid), but we don't have a 1518aa55f9bSriastradh * way to get this bound right now), and if we ask for a wakeup 1528aa55f9bSriastradh * (say) 0.9tick at a time 0.8tick before the next tick, the 1538aa55f9bSriastradh * next tick is too early so we have to wait two ticks. 1548aa55f9bSriastradh * 1558aa55f9bSriastradh * The main point of this is to make sure that we're not 1568aa55f9bSriastradh * getting absolute time by mistake (PR 58917) so the slop of 1578aa55f9bSriastradh * 2sec is fine. 1588aa55f9bSriastradh * 1598aa55f9bSriastradh * Parentheses are required around the argument 1608aa55f9bSriastradh * 1618aa55f9bSriastradh * &(const struct timespec){2, 0} 1628aa55f9bSriastradh * 1638aa55f9bSriastradh * to timespecadd because it's a macro and the brilliant C 1648aa55f9bSriastradh * preprocessor splits arguments at a comma if they're not 1658aa55f9bSriastradh * parenthesized. 166c7921dd2Sriastradh */ 1678aa55f9bSriastradh if (flags & TIMER_ABSTIME) { 1688aa55f9bSriastradh timespecadd(&rtim.it_value, (&(const struct timespec){2, 0}), 1698aa55f9bSriastradh &rtim.it_value); 1708aa55f9bSriastradh } 171c7921dd2Sriastradh ATF_CHECK_MSG(timespeccmp(&otim.it_value, &rtim.it_value, <=), 172c7921dd2Sriastradh "time remaining %lld sec %d nsec," 173c7921dd2Sriastradh " expected at most %lld sec %d nsec", 174c7921dd2Sriastradh (long long)otim.it_value.tv_sec, (int)otim.it_value.tv_nsec, 175c7921dd2Sriastradh (long long)rtim.it_value.tv_sec, (int)rtim.it_value.tv_nsec); 176c7921dd2Sriastradh 177c7921dd2Sriastradh #if 0 178c7921dd2Sriastradh /* 179c7921dd2Sriastradh * Check to make sure that the amount the time remaining has 180c7921dd2Sriastradh * gone down is at most the time elapsed. 181c7921dd2Sriastradh * 182c7921dd2Sriastradh * XXX Currently the time returned by timer_settime is only 183c7921dd2Sriastradh * good to the nearest kernel tick (typically 10ms or 1ms), not 184c7921dd2Sriastradh * to the resolution of the underlying clock -- unlike 185c7921dd2Sriastradh * clock_gettime. So we can't set this bound. Not sure 186c7921dd2Sriastradh * whether this is a bug or not, hence #if 0 instead of 187c7921dd2Sriastradh * atf_tc_expect_fail. 188c7921dd2Sriastradh */ 189c7921dd2Sriastradh timespecsub(&t1, &t0, &dt); 190c7921dd2Sriastradh timespecsub(&rtim.it_value, &otim.it_value, &rtim.it_value); 191c7921dd2Sriastradh ATF_CHECK_MSG(timespeccmp(&rtim.it_value, &dt, <=), 192c7921dd2Sriastradh "time remaining went down by %lld sec %d nsec," 193c7921dd2Sriastradh " expected at most %lld sec %d nsec", 194c7921dd2Sriastradh (long long)rtim.it_value.tv_sec, (int)rtim.it_value.tv_nsec, 195c7921dd2Sriastradh (long long)dt.tv_sec, (int)dt.tv_nsec); 196c7921dd2Sriastradh #endif 197c7921dd2Sriastradh 198c7921dd2Sriastradh /* 199c7921dd2Sriastradh * Check to make sure the reload interval is what we set. 200c7921dd2Sriastradh */ 201c7921dd2Sriastradh ATF_CHECK_MSG(timespeccmp(&otim.it_interval, &rtim.it_interval, ==), 202c7921dd2Sriastradh "interval %lld sec %d nsec," 203c7921dd2Sriastradh " expected %lld sec %d nsec", 204c7921dd2Sriastradh (long long)otim.it_interval.tv_sec, (int)otim.it_interval.tv_nsec, 205c7921dd2Sriastradh (long long)rtim.it_interval.tv_sec, (int)rtim.it_interval.tv_nsec); 2069cbb4897Sjruoho 2079cbb4897Sjruoho (void)sigprocmask(SIG_UNBLOCK, &set, NULL); 208c7921dd2Sriastradh switch (mode) { 209c7921dd2Sriastradh case PAST: 2108aa55f9bSriastradh /* 2118aa55f9bSriastradh * Wait for at least one tick to pass. 2128aa55f9bSriastradh * 2138aa55f9bSriastradh * XXX This does not really follow POSIX, which says 2148aa55f9bSriastradh * `If the specified time has already passed, the 2158aa55f9bSriastradh * function shall succeed and the expiration 2168aa55f9bSriastradh * notification shall be made.' 2178aa55f9bSriastradh * (https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/timer_settime.html), 2188aa55f9bSriastradh * suggesting that it should be immediate without any 2198aa55f9bSriastradh * further delay, but other operating systems also 2208aa55f9bSriastradh * sometimes have a small delay. 2218aa55f9bSriastradh */ 2228aa55f9bSriastradh RL(clock_nanosleep(cid, 0, &(const struct timespec){0, 1}, 2238aa55f9bSriastradh NULL)); 224c7921dd2Sriastradh ATF_CHECK_MSG(expired, "timer failed to fire immediately"); 225c7921dd2Sriastradh break; 226c7921dd2Sriastradh case EXPIRE: 227c7921dd2Sriastradh case NOEXPIRE: 228c7921dd2Sriastradh ATF_CHECK_MSG(!expired, "timer fired too soon"); 2299cbb4897Sjruoho (void)sleep(2); 230c7921dd2Sriastradh switch (mode) { 231c7921dd2Sriastradh case PAST: 232c7921dd2Sriastradh __unreachable(); 233c7921dd2Sriastradh case EXPIRE: 234c7921dd2Sriastradh ATF_CHECK_MSG(expired, 235c7921dd2Sriastradh "timer failed to fire immediately"); 236c7921dd2Sriastradh break; 237c7921dd2Sriastradh case NOEXPIRE: 238c7921dd2Sriastradh ATF_CHECK_MSG(!expired, "timer fired too soon"); 239c7921dd2Sriastradh break; 240c7921dd2Sriastradh } 241c7921dd2Sriastradh break; 242068fb4f1Sjruoho } 243068fb4f1Sjruoho 24428aeeb58Schristos ATF_REQUIRE(timer_delete(t) == 0); 24528aeeb58Schristos } 24628aeeb58Schristos 2479cbb4897Sjruoho ATF_TC(timer_create_err); 2489cbb4897Sjruoho ATF_TC_HEAD(timer_create_err, tc) 2499cbb4897Sjruoho { 2508b18a8bfSjruoho atf_tc_set_md_var(tc, "descr", 251c7921dd2Sriastradh "Check errors from timer_create(2) (PR lib/42434)"); 2529cbb4897Sjruoho } 2539cbb4897Sjruoho 2549cbb4897Sjruoho ATF_TC_BODY(timer_create_err, tc) 2559cbb4897Sjruoho { 2569cbb4897Sjruoho struct sigevent ev; 2579cbb4897Sjruoho 2589cbb4897Sjruoho (void)memset(&ev, 0, sizeof(struct sigevent)); 2599cbb4897Sjruoho 2609cbb4897Sjruoho errno = 0; 2619cbb4897Sjruoho ev.sigev_signo = -1; 2629cbb4897Sjruoho ev.sigev_notify = SIGEV_SIGNAL; 2639cbb4897Sjruoho 2649cbb4897Sjruoho ATF_REQUIRE_ERRNO(EINVAL, timer_create(CLOCK_REALTIME, &ev, &t) == -1); 2659cbb4897Sjruoho 2669cbb4897Sjruoho errno = 0; 2679cbb4897Sjruoho ev.sigev_signo = SIGUSR1; 2689cbb4897Sjruoho ev.sigev_notify = SIGEV_THREAD + 100; 2699cbb4897Sjruoho 2709cbb4897Sjruoho ATF_REQUIRE_ERRNO(EINVAL, timer_create(CLOCK_REALTIME, &ev, &t) == -1); 2719cbb4897Sjruoho } 2729cbb4897Sjruoho 2739cbb4897Sjruoho ATF_TC(timer_create_real); 2749cbb4897Sjruoho ATF_TC_HEAD(timer_create_real, tc) 275068fb4f1Sjruoho { 276068fb4f1Sjruoho 277068fb4f1Sjruoho atf_tc_set_md_var(tc, "descr", 278068fb4f1Sjruoho "Checks timer_create(2) with CLOCK_REALTIME and sigevent(3), " 279068fb4f1Sjruoho "SIGEV_SIGNAL"); 280068fb4f1Sjruoho } 281068fb4f1Sjruoho 2829cbb4897Sjruoho ATF_TC_BODY(timer_create_real, tc) 283068fb4f1Sjruoho { 284c7921dd2Sriastradh timer_signal_create(CLOCK_REALTIME, NOEXPIRE, 0); 285c7921dd2Sriastradh } 286c7921dd2Sriastradh 287c7921dd2Sriastradh ATF_TC(timer_create_real_abs); 288c7921dd2Sriastradh ATF_TC_HEAD(timer_create_real_abs, tc) 289c7921dd2Sriastradh { 290c7921dd2Sriastradh 291c7921dd2Sriastradh atf_tc_set_md_var(tc, "descr", 292c7921dd2Sriastradh "Checks timer_create(2) with CLOCK_REALTIME and sigevent(3), " 293c7921dd2Sriastradh "SIGEV_SIGNAL, using absolute time"); 294c7921dd2Sriastradh } 295c7921dd2Sriastradh 296c7921dd2Sriastradh ATF_TC_BODY(timer_create_real_abs, tc) 297c7921dd2Sriastradh { 298c7921dd2Sriastradh timer_signal_create(CLOCK_REALTIME, NOEXPIRE, TIMER_ABSTIME); 299068fb4f1Sjruoho } 300068fb4f1Sjruoho 3019cbb4897Sjruoho ATF_TC(timer_create_mono); 3029cbb4897Sjruoho ATF_TC_HEAD(timer_create_mono, tc) 303068fb4f1Sjruoho { 304068fb4f1Sjruoho 305068fb4f1Sjruoho atf_tc_set_md_var(tc, "descr", 306068fb4f1Sjruoho "Checks timer_create(2) with CLOCK_MONOTONIC and sigevent(3), " 307068fb4f1Sjruoho "SIGEV_SIGNAL"); 308068fb4f1Sjruoho } 309068fb4f1Sjruoho 3109cbb4897Sjruoho ATF_TC_BODY(timer_create_mono, tc) 311068fb4f1Sjruoho { 312c7921dd2Sriastradh timer_signal_create(CLOCK_MONOTONIC, NOEXPIRE, 0); 313c7921dd2Sriastradh } 314c7921dd2Sriastradh 315c7921dd2Sriastradh ATF_TC(timer_create_mono_abs); 316c7921dd2Sriastradh ATF_TC_HEAD(timer_create_mono_abs, tc) 317c7921dd2Sriastradh { 318c7921dd2Sriastradh 319c7921dd2Sriastradh atf_tc_set_md_var(tc, "descr", 320c7921dd2Sriastradh "Checks timer_create(2) with CLOCK_MONOTONIC and sigevent(3), " 321c7921dd2Sriastradh "SIGEV_SIGNAL, using absolute time"); 322c7921dd2Sriastradh } 323c7921dd2Sriastradh 324c7921dd2Sriastradh ATF_TC_BODY(timer_create_mono_abs, tc) 325c7921dd2Sriastradh { 326c7921dd2Sriastradh timer_signal_create(CLOCK_MONOTONIC, NOEXPIRE, TIMER_ABSTIME); 32728aeeb58Schristos } 32828aeeb58Schristos 32928aeeb58Schristos ATF_TC(timer_create_real_expire); 33028aeeb58Schristos ATF_TC_HEAD(timer_create_real_expire, tc) 33128aeeb58Schristos { 33228aeeb58Schristos 33328aeeb58Schristos atf_tc_set_md_var(tc, "descr", 33428aeeb58Schristos "Checks timer_create(2) with CLOCK_REALTIME and sigevent(3), " 33528aeeb58Schristos "SIGEV_SIGNAL, with expiration"); 33628aeeb58Schristos } 33728aeeb58Schristos 33828aeeb58Schristos ATF_TC_BODY(timer_create_real_expire, tc) 33928aeeb58Schristos { 340c7921dd2Sriastradh timer_signal_create(CLOCK_REALTIME, EXPIRE, 0); 341c7921dd2Sriastradh } 342c7921dd2Sriastradh 343c7921dd2Sriastradh ATF_TC(timer_create_real_expire_abs); 344c7921dd2Sriastradh ATF_TC_HEAD(timer_create_real_expire_abs, tc) 345c7921dd2Sriastradh { 346c7921dd2Sriastradh 347c7921dd2Sriastradh atf_tc_set_md_var(tc, "descr", 348c7921dd2Sriastradh "Checks timer_create(2) with CLOCK_REALTIME and sigevent(3), " 349c7921dd2Sriastradh "SIGEV_SIGNAL, with expiration, using absolute time"); 350c7921dd2Sriastradh } 351c7921dd2Sriastradh 352c7921dd2Sriastradh ATF_TC_BODY(timer_create_real_expire_abs, tc) 353c7921dd2Sriastradh { 354c7921dd2Sriastradh timer_signal_create(CLOCK_REALTIME, EXPIRE, TIMER_ABSTIME); 35528aeeb58Schristos } 35628aeeb58Schristos 35728aeeb58Schristos ATF_TC(timer_create_mono_expire); 35828aeeb58Schristos ATF_TC_HEAD(timer_create_mono_expire, tc) 35928aeeb58Schristos { 36028aeeb58Schristos 36128aeeb58Schristos atf_tc_set_md_var(tc, "descr", 36228aeeb58Schristos "Checks timer_create(2) with CLOCK_MONOTONIC and sigevent(3), " 36328aeeb58Schristos "SIGEV_SIGNAL, with expiration"); 36428aeeb58Schristos } 36528aeeb58Schristos 36628aeeb58Schristos ATF_TC_BODY(timer_create_mono_expire, tc) 36728aeeb58Schristos { 368c7921dd2Sriastradh timer_signal_create(CLOCK_MONOTONIC, EXPIRE, 0); 369c7921dd2Sriastradh } 370c7921dd2Sriastradh 371c7921dd2Sriastradh ATF_TC(timer_create_mono_expire_abs); 372c7921dd2Sriastradh ATF_TC_HEAD(timer_create_mono_expire_abs, tc) 373c7921dd2Sriastradh { 374c7921dd2Sriastradh 375c7921dd2Sriastradh atf_tc_set_md_var(tc, "descr", 376c7921dd2Sriastradh "Checks timer_create(2) with CLOCK_MONOTONIC and sigevent(3), " 377c7921dd2Sriastradh "SIGEV_SIGNAL, with expiration, using absolute time"); 378c7921dd2Sriastradh } 379c7921dd2Sriastradh 380c7921dd2Sriastradh ATF_TC_BODY(timer_create_mono_expire_abs, tc) 381c7921dd2Sriastradh { 382c7921dd2Sriastradh timer_signal_create(CLOCK_MONOTONIC, EXPIRE, TIMER_ABSTIME); 383c7921dd2Sriastradh } 384c7921dd2Sriastradh 385c7921dd2Sriastradh ATF_TC(timer_create_real_past_abs); 386c7921dd2Sriastradh ATF_TC_HEAD(timer_create_real_past_abs, tc) 387c7921dd2Sriastradh { 388c7921dd2Sriastradh 389c7921dd2Sriastradh atf_tc_set_md_var(tc, "descr", 390c7921dd2Sriastradh "Checks timer_create(2) with CLOCK_REALTIME and sigevent(3), " 391c7921dd2Sriastradh "SIGEV_SIGNAL, with expiration passed before timer_settime(2)," 392c7921dd2Sriastradh " using absolute time"); 393c7921dd2Sriastradh } 394c7921dd2Sriastradh 395c7921dd2Sriastradh ATF_TC_BODY(timer_create_real_past_abs, tc) 396c7921dd2Sriastradh { 397c7921dd2Sriastradh timer_signal_create(CLOCK_REALTIME, PAST, TIMER_ABSTIME); 398c7921dd2Sriastradh } 399c7921dd2Sriastradh 400c7921dd2Sriastradh ATF_TC(timer_create_mono_past_abs); 401c7921dd2Sriastradh ATF_TC_HEAD(timer_create_mono_past_abs, tc) 402c7921dd2Sriastradh { 403c7921dd2Sriastradh 404c7921dd2Sriastradh atf_tc_set_md_var(tc, "descr", 405c7921dd2Sriastradh "Checks timer_create(2) with CLOCK_MONOTONIC and sigevent(3), " 406c7921dd2Sriastradh "SIGEV_SIGNAL, with expiration passed before timer_settime(2)," 407c7921dd2Sriastradh " using absolute time"); 408c7921dd2Sriastradh } 409c7921dd2Sriastradh 410c7921dd2Sriastradh ATF_TC_BODY(timer_create_mono_past_abs, tc) 411c7921dd2Sriastradh { 412c7921dd2Sriastradh timer_signal_create(CLOCK_MONOTONIC, PAST, TIMER_ABSTIME); 413c7921dd2Sriastradh } 414c7921dd2Sriastradh 415c7921dd2Sriastradh ATF_TC(timer_invalidtime); 416c7921dd2Sriastradh ATF_TC_HEAD(timer_invalidtime, tc) 417c7921dd2Sriastradh { 418c7921dd2Sriastradh atf_tc_set_md_var(tc, "descr", 419c7921dd2Sriastradh "Verify timer_settime(2) rejects invalid times"); 420c7921dd2Sriastradh } 421c7921dd2Sriastradh 422c7921dd2Sriastradh ATF_TC_BODY(timer_invalidtime, tc) 423c7921dd2Sriastradh { 424c7921dd2Sriastradh const struct itimerspec einval_its[] = { 4258aa55f9bSriastradh [0] = { .it_value = {-1, 0} }, 4268aa55f9bSriastradh [1] = { .it_value = {0, -1} }, 427c7921dd2Sriastradh [2] = { .it_value = {0, 1000000001} }, 4288aa55f9bSriastradh [3] = { .it_value = {1, 0}, .it_interval = {-1, 0} }, 4298aa55f9bSriastradh [4] = { .it_value = {1, 0}, .it_interval = {0, -1} }, 4308aa55f9bSriastradh [5] = { .it_value = {1, 0}, .it_interval = {0, 1000000001} }, 431c7921dd2Sriastradh }; 432c7921dd2Sriastradh struct timespec now; 4338aa55f9bSriastradh sigset_t sigs, mask; 434c7921dd2Sriastradh unsigned i; 435c7921dd2Sriastradh 4368aa55f9bSriastradh RL(sigemptyset(&sigs)); 4378aa55f9bSriastradh RL(sigaddset(&sigs, SIGALRM)); 4388aa55f9bSriastradh RL(sigprocmask(SIG_BLOCK, &sigs, &mask)); 4398aa55f9bSriastradh 440c7921dd2Sriastradh RL(clock_gettime(CLOCK_MONOTONIC, &now)); 441c7921dd2Sriastradh 442c7921dd2Sriastradh RL(timer_create(CLOCK_MONOTONIC, NULL, &t)); 443c7921dd2Sriastradh 444c7921dd2Sriastradh for (i = 0; i < __arraycount(einval_its); i++) { 445c7921dd2Sriastradh struct itimerspec its; 446c7921dd2Sriastradh 4478aa55f9bSriastradh fprintf(stderr, "case %u\n", i); 4488aa55f9bSriastradh 449c7921dd2Sriastradh ATF_CHECK_ERRNO(EINVAL, 450c7921dd2Sriastradh timer_settime(t, 0, &einval_its[i], NULL) == -1); 451c7921dd2Sriastradh 452c7921dd2Sriastradh /* Try the same with an absolute time near now. */ 453c7921dd2Sriastradh its.it_value = einval_its[i].it_value; 454c7921dd2Sriastradh its.it_value.tv_sec += now.tv_sec + 60; 455c7921dd2Sriastradh ATF_CHECK_ERRNO(EINVAL, 456c7921dd2Sriastradh timer_settime(t, TIMER_ABSTIME, &its, NULL) == -1); 4578aa55f9bSriastradh } 4588aa55f9bSriastradh 4598aa55f9bSriastradh /* Wait up to 2sec to make sure no timer got set anyway. */ 4608aa55f9bSriastradh ATF_CHECK_ERRNO(EAGAIN, 4618aa55f9bSriastradh sigtimedwait(&sigs, NULL, &(const struct timespec){2, 0}) == -1); 4628aa55f9bSriastradh RL(sigprocmask(SIG_SETMASK, &mask, NULL)); 463c7921dd2Sriastradh 464c7921dd2Sriastradh RL(timer_delete(t)); 465068fb4f1Sjruoho } 466068fb4f1Sjruoho 467068fb4f1Sjruoho ATF_TP_ADD_TCS(tp) 468068fb4f1Sjruoho { 469068fb4f1Sjruoho 4709cbb4897Sjruoho ATF_TP_ADD_TC(tp, timer_create_err); 4719cbb4897Sjruoho ATF_TP_ADD_TC(tp, timer_create_real); 472c7921dd2Sriastradh ATF_TP_ADD_TC(tp, timer_create_real_abs); 4739cbb4897Sjruoho ATF_TP_ADD_TC(tp, timer_create_mono); 474c7921dd2Sriastradh ATF_TP_ADD_TC(tp, timer_create_mono_abs); 47528aeeb58Schristos ATF_TP_ADD_TC(tp, timer_create_real_expire); 476c7921dd2Sriastradh ATF_TP_ADD_TC(tp, timer_create_real_expire_abs); 47728aeeb58Schristos ATF_TP_ADD_TC(tp, timer_create_mono_expire); 478c7921dd2Sriastradh ATF_TP_ADD_TC(tp, timer_create_mono_expire_abs); 479c7921dd2Sriastradh ATF_TP_ADD_TC(tp, timer_create_real_past_abs); 480c7921dd2Sriastradh ATF_TP_ADD_TC(tp, timer_create_mono_past_abs); 481c7921dd2Sriastradh ATF_TP_ADD_TC(tp, timer_invalidtime); 482068fb4f1Sjruoho 483068fb4f1Sjruoho return atf_no_error(); 484068fb4f1Sjruoho } 485