1 1.10 riastrad /* $NetBSD: t_timer_create.c,v 1.10 2025/04/16 01:32:48 riastradh Exp $ */ 2 1.1 jruoho 3 1.1 jruoho /*- 4 1.1 jruoho * Copyright (c) 2010 The NetBSD Foundation, Inc. 5 1.1 jruoho * All rights reserved. 6 1.1 jruoho * 7 1.1 jruoho * Redistribution and use in source and binary forms, with or without 8 1.1 jruoho * modification, are permitted provided that the following conditions 9 1.1 jruoho * are met: 10 1.1 jruoho * 1. Redistributions of source code must retain the above copyright 11 1.1 jruoho * notice, this list of conditions and the following disclaimer. 12 1.1 jruoho * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 jruoho * notice, this list of conditions and the following disclaimer in the 14 1.1 jruoho * documentation and/or other materials provided with the distribution. 15 1.1 jruoho * 16 1.1 jruoho * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 1.1 jruoho * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 1.1 jruoho * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 1.1 jruoho * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 1.1 jruoho * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 1.1 jruoho * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 1.1 jruoho * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 1.1 jruoho * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 1.1 jruoho * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 1.1 jruoho * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 1.1 jruoho * POSSIBILITY OF SUCH DAMAGE. 27 1.1 jruoho */ 28 1.1 jruoho 29 1.2 jruoho #include <atf-c.h> 30 1.1 jruoho #include <errno.h> 31 1.2 jruoho #include <stdio.h> 32 1.1 jruoho #include <signal.h> 33 1.1 jruoho #include <string.h> 34 1.1 jruoho #include <time.h> 35 1.1 jruoho #include <unistd.h> 36 1.1 jruoho 37 1.6 riastrad #include "h_macros.h" 38 1.6 riastrad 39 1.2 jruoho static timer_t t; 40 1.6 riastrad static sig_atomic_t expired; 41 1.6 riastrad 42 1.6 riastrad enum mode { 43 1.6 riastrad PAST, 44 1.6 riastrad EXPIRE, 45 1.6 riastrad NOEXPIRE, 46 1.6 riastrad }; 47 1.1 jruoho 48 1.2 jruoho static void 49 1.5 christos timer_signal_handler(int signo, siginfo_t *si, void *osi __unused) 50 1.1 jruoho { 51 1.7 riastrad const int errno_save = errno; 52 1.2 jruoho timer_t *tp; 53 1.1 jruoho 54 1.2 jruoho tp = si->si_value.sival_ptr; 55 1.1 jruoho 56 1.2 jruoho if (*tp == t && signo == SIGALRM) 57 1.6 riastrad expired = 1; 58 1.1 jruoho 59 1.2 jruoho (void)fprintf(stderr, "%s: %s\n", __func__, strsignal(signo)); 60 1.7 riastrad errno = errno_save; 61 1.1 jruoho } 62 1.1 jruoho 63 1.1 jruoho static void 64 1.6 riastrad timer_signal_create(clockid_t cid, enum mode mode, int flags) 65 1.1 jruoho { 66 1.6 riastrad struct itimerspec tim, rtim, otim; 67 1.6 riastrad struct timespec t0, t1, dt; 68 1.1 jruoho struct sigaction act; 69 1.1 jruoho struct sigevent evt; 70 1.1 jruoho sigset_t set; 71 1.1 jruoho 72 1.2 jruoho t = 0; 73 1.6 riastrad expired = 0; 74 1.1 jruoho 75 1.1 jruoho (void)memset(&evt, 0, sizeof(struct sigevent)); 76 1.1 jruoho (void)memset(&act, 0, sizeof(struct sigaction)); 77 1.1 jruoho (void)memset(&tim, 0, sizeof(struct itimerspec)); 78 1.1 jruoho 79 1.2 jruoho /* 80 1.2 jruoho * Set handler. 81 1.2 jruoho */ 82 1.1 jruoho act.sa_flags = SA_SIGINFO; 83 1.1 jruoho act.sa_sigaction = timer_signal_handler; 84 1.1 jruoho 85 1.2 jruoho ATF_REQUIRE(sigemptyset(&set) == 0); 86 1.2 jruoho ATF_REQUIRE(sigemptyset(&act.sa_mask) == 0); 87 1.1 jruoho 88 1.2 jruoho /* 89 1.2 jruoho * Block SIGALRM while configuring the timer. 90 1.2 jruoho */ 91 1.2 jruoho ATF_REQUIRE(sigaction(SIGALRM, &act, NULL) == 0); 92 1.2 jruoho ATF_REQUIRE(sigaddset(&set, SIGALRM) == 0); 93 1.2 jruoho ATF_REQUIRE(sigprocmask(SIG_SETMASK, &set, NULL) == 0); 94 1.2 jruoho 95 1.2 jruoho /* 96 1.2 jruoho * Create the timer (SIGEV_SIGNAL). 97 1.2 jruoho */ 98 1.2 jruoho evt.sigev_signo = SIGALRM; 99 1.1 jruoho evt.sigev_value.sival_ptr = &t; 100 1.1 jruoho evt.sigev_notify = SIGEV_SIGNAL; 101 1.1 jruoho 102 1.2 jruoho ATF_REQUIRE(timer_create(cid, &evt, &t) == 0); 103 1.2 jruoho 104 1.2 jruoho /* 105 1.6 riastrad * Configure the timer for -1, 1, or 5 sec from now, depending 106 1.6 riastrad * on whether we want it to have fired, to fire within 2sec, or 107 1.6 riastrad * to not fire within 2sec. 108 1.2 jruoho */ 109 1.6 riastrad switch (mode) { 110 1.6 riastrad case PAST: 111 1.7 riastrad ATF_REQUIRE(flags & TIMER_ABSTIME); 112 1.6 riastrad tim.it_value.tv_sec = -1; 113 1.6 riastrad break; 114 1.6 riastrad case EXPIRE: 115 1.6 riastrad tim.it_value.tv_sec = 1; 116 1.6 riastrad break; 117 1.6 riastrad case NOEXPIRE: 118 1.6 riastrad tim.it_value.tv_sec = 5; 119 1.6 riastrad break; 120 1.6 riastrad } 121 1.2 jruoho tim.it_value.tv_nsec = 0; 122 1.2 jruoho 123 1.6 riastrad /* 124 1.6 riastrad * Save the relative time and adjust for absolute time of 125 1.6 riastrad * requested. 126 1.6 riastrad */ 127 1.6 riastrad rtim = tim; 128 1.6 riastrad RL(clock_gettime(cid, &t0)); 129 1.6 riastrad if (flags & TIMER_ABSTIME) 130 1.6 riastrad timespecadd(&t0, &tim.it_value, &tim.it_value); 131 1.6 riastrad 132 1.6 riastrad fprintf(stderr, "now is %lld sec %d nsec\n", 133 1.6 riastrad (long long)t0.tv_sec, (int)t0.tv_nsec); 134 1.6 riastrad fprintf(stderr, "expire at %lld sec %d nsec\n", 135 1.6 riastrad (long long)tim.it_value.tv_sec, (int)tim.it_value.tv_nsec); 136 1.6 riastrad RL(timer_settime(t, flags, &tim, NULL)); 137 1.6 riastrad RL(timer_settime(t, flags, &tim, &otim)); 138 1.6 riastrad 139 1.6 riastrad RL(clock_gettime(cid, &t1)); 140 1.6 riastrad timespecsub(&t1, &t0, &dt); 141 1.6 riastrad fprintf(stderr, "%lld sec %d nsec elapsed\n", 142 1.6 riastrad (long long)dt.tv_sec, (int)dt.tv_nsec); 143 1.6 riastrad 144 1.6 riastrad /* 145 1.6 riastrad * Check to make sure the time remaining is at most the 146 1.7 riastrad * relative time we expected -- plus slop of up to 2sec, 147 1.7 riastrad * because timer_settime rounds the duration up to a multiple 148 1.7 riastrad * of a tick period, which is at most 1sec (usually more like 149 1.7 riastrad * 10ms or 1ms, and in the future with high-resolution timers 150 1.7 riastrad * it'll be more like clock_getres(cid), but we don't have a 151 1.7 riastrad * way to get this bound right now), and if we ask for a wakeup 152 1.7 riastrad * (say) 0.9tick at a time 0.8tick before the next tick, the 153 1.7 riastrad * next tick is too early so we have to wait two ticks. 154 1.7 riastrad * 155 1.7 riastrad * The main point of this is to make sure that we're not 156 1.7 riastrad * getting absolute time by mistake (PR 58917) so the slop of 157 1.7 riastrad * 2sec is fine. 158 1.7 riastrad * 159 1.7 riastrad * Parentheses are required around the argument 160 1.7 riastrad * 161 1.7 riastrad * &(const struct timespec){2, 0} 162 1.7 riastrad * 163 1.7 riastrad * to timespecadd because it's a macro and the brilliant C 164 1.7 riastrad * preprocessor splits arguments at a comma if they're not 165 1.7 riastrad * parenthesized. 166 1.6 riastrad */ 167 1.7 riastrad if (flags & TIMER_ABSTIME) { 168 1.7 riastrad timespecadd(&rtim.it_value, (&(const struct timespec){2, 0}), 169 1.7 riastrad &rtim.it_value); 170 1.7 riastrad } 171 1.6 riastrad ATF_CHECK_MSG(timespeccmp(&otim.it_value, &rtim.it_value, <=), 172 1.6 riastrad "time remaining %lld sec %d nsec," 173 1.6 riastrad " expected at most %lld sec %d nsec", 174 1.6 riastrad (long long)otim.it_value.tv_sec, (int)otim.it_value.tv_nsec, 175 1.6 riastrad (long long)rtim.it_value.tv_sec, (int)rtim.it_value.tv_nsec); 176 1.6 riastrad 177 1.6 riastrad #if 0 178 1.6 riastrad /* 179 1.6 riastrad * Check to make sure that the amount the time remaining has 180 1.6 riastrad * gone down is at most the time elapsed. 181 1.6 riastrad * 182 1.6 riastrad * XXX Currently the time returned by timer_settime is only 183 1.6 riastrad * good to the nearest kernel tick (typically 10ms or 1ms), not 184 1.6 riastrad * to the resolution of the underlying clock -- unlike 185 1.6 riastrad * clock_gettime. So we can't set this bound. Not sure 186 1.6 riastrad * whether this is a bug or not, hence #if 0 instead of 187 1.6 riastrad * atf_tc_expect_fail. 188 1.6 riastrad */ 189 1.6 riastrad timespecsub(&t1, &t0, &dt); 190 1.6 riastrad timespecsub(&rtim.it_value, &otim.it_value, &rtim.it_value); 191 1.6 riastrad ATF_CHECK_MSG(timespeccmp(&rtim.it_value, &dt, <=), 192 1.6 riastrad "time remaining went down by %lld sec %d nsec," 193 1.6 riastrad " expected at most %lld sec %d nsec", 194 1.6 riastrad (long long)rtim.it_value.tv_sec, (int)rtim.it_value.tv_nsec, 195 1.6 riastrad (long long)dt.tv_sec, (int)dt.tv_nsec); 196 1.6 riastrad #endif 197 1.6 riastrad 198 1.6 riastrad /* 199 1.6 riastrad * Check to make sure the reload interval is what we set. 200 1.6 riastrad */ 201 1.6 riastrad ATF_CHECK_MSG(timespeccmp(&otim.it_interval, &rtim.it_interval, ==), 202 1.6 riastrad "interval %lld sec %d nsec," 203 1.6 riastrad " expected %lld sec %d nsec", 204 1.6 riastrad (long long)otim.it_interval.tv_sec, (int)otim.it_interval.tv_nsec, 205 1.6 riastrad (long long)rtim.it_interval.tv_sec, (int)rtim.it_interval.tv_nsec); 206 1.1 jruoho 207 1.2 jruoho (void)sigprocmask(SIG_UNBLOCK, &set, NULL); 208 1.6 riastrad switch (mode) { 209 1.6 riastrad case PAST: 210 1.7 riastrad /* 211 1.7 riastrad * Wait for at least one tick to pass. 212 1.7 riastrad * 213 1.7 riastrad * XXX This does not really follow POSIX, which says 214 1.7 riastrad * `If the specified time has already passed, the 215 1.7 riastrad * function shall succeed and the expiration 216 1.7 riastrad * notification shall be made.' 217 1.7 riastrad * (https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/timer_settime.html), 218 1.7 riastrad * suggesting that it should be immediate without any 219 1.7 riastrad * further delay, but other operating systems also 220 1.7 riastrad * sometimes have a small delay. 221 1.7 riastrad */ 222 1.7 riastrad RL(clock_nanosleep(cid, 0, &(const struct timespec){0, 1}, 223 1.7 riastrad NULL)); 224 1.6 riastrad ATF_CHECK_MSG(expired, "timer failed to fire immediately"); 225 1.6 riastrad break; 226 1.6 riastrad case EXPIRE: 227 1.6 riastrad case NOEXPIRE: 228 1.6 riastrad ATF_CHECK_MSG(!expired, "timer fired too soon"); 229 1.6 riastrad (void)sleep(2); 230 1.6 riastrad switch (mode) { 231 1.6 riastrad case PAST: 232 1.6 riastrad __unreachable(); 233 1.6 riastrad case EXPIRE: 234 1.6 riastrad ATF_CHECK_MSG(expired, 235 1.6 riastrad "timer failed to fire immediately"); 236 1.6 riastrad break; 237 1.6 riastrad case NOEXPIRE: 238 1.6 riastrad ATF_CHECK_MSG(!expired, "timer fired too soon"); 239 1.6 riastrad break; 240 1.6 riastrad } 241 1.6 riastrad break; 242 1.3 christos } 243 1.3 christos 244 1.3 christos ATF_REQUIRE(timer_delete(t) == 0); 245 1.1 jruoho } 246 1.1 jruoho 247 1.2 jruoho ATF_TC(timer_create_err); 248 1.2 jruoho ATF_TC_HEAD(timer_create_err, tc) 249 1.1 jruoho { 250 1.4 jruoho atf_tc_set_md_var(tc, "descr", 251 1.6 riastrad "Check errors from timer_create(2) (PR lib/42434)"); 252 1.1 jruoho } 253 1.1 jruoho 254 1.2 jruoho ATF_TC_BODY(timer_create_err, tc) 255 1.1 jruoho { 256 1.2 jruoho struct sigevent ev; 257 1.1 jruoho 258 1.2 jruoho (void)memset(&ev, 0, sizeof(struct sigevent)); 259 1.1 jruoho 260 1.1 jruoho errno = 0; 261 1.2 jruoho ev.sigev_signo = -1; 262 1.2 jruoho ev.sigev_notify = SIGEV_SIGNAL; 263 1.1 jruoho 264 1.2 jruoho ATF_REQUIRE_ERRNO(EINVAL, timer_create(CLOCK_REALTIME, &ev, &t) == -1); 265 1.1 jruoho 266 1.2 jruoho errno = 0; 267 1.2 jruoho ev.sigev_signo = SIGUSR1; 268 1.2 jruoho ev.sigev_notify = SIGEV_THREAD + 100; 269 1.1 jruoho 270 1.2 jruoho ATF_REQUIRE_ERRNO(EINVAL, timer_create(CLOCK_REALTIME, &ev, &t) == -1); 271 1.1 jruoho } 272 1.1 jruoho 273 1.2 jruoho ATF_TC(timer_create_real); 274 1.2 jruoho ATF_TC_HEAD(timer_create_real, tc) 275 1.1 jruoho { 276 1.1 jruoho 277 1.1 jruoho atf_tc_set_md_var(tc, "descr", 278 1.2 jruoho "Checks timer_create(2) with CLOCK_REALTIME and sigevent(3), " 279 1.2 jruoho "SIGEV_SIGNAL"); 280 1.1 jruoho } 281 1.1 jruoho 282 1.2 jruoho ATF_TC_BODY(timer_create_real, tc) 283 1.1 jruoho { 284 1.6 riastrad timer_signal_create(CLOCK_REALTIME, NOEXPIRE, 0); 285 1.6 riastrad } 286 1.6 riastrad 287 1.6 riastrad ATF_TC(timer_create_real_abs); 288 1.6 riastrad ATF_TC_HEAD(timer_create_real_abs, tc) 289 1.6 riastrad { 290 1.6 riastrad 291 1.6 riastrad atf_tc_set_md_var(tc, "descr", 292 1.6 riastrad "Checks timer_create(2) with CLOCK_REALTIME and sigevent(3), " 293 1.6 riastrad "SIGEV_SIGNAL, using absolute time"); 294 1.6 riastrad } 295 1.6 riastrad 296 1.6 riastrad ATF_TC_BODY(timer_create_real_abs, tc) 297 1.6 riastrad { 298 1.6 riastrad timer_signal_create(CLOCK_REALTIME, NOEXPIRE, TIMER_ABSTIME); 299 1.1 jruoho } 300 1.1 jruoho 301 1.2 jruoho ATF_TC(timer_create_mono); 302 1.2 jruoho ATF_TC_HEAD(timer_create_mono, tc) 303 1.1 jruoho { 304 1.1 jruoho 305 1.2 jruoho atf_tc_set_md_var(tc, "descr", 306 1.2 jruoho "Checks timer_create(2) with CLOCK_MONOTONIC and sigevent(3), " 307 1.2 jruoho "SIGEV_SIGNAL"); 308 1.1 jruoho } 309 1.1 jruoho 310 1.2 jruoho ATF_TC_BODY(timer_create_mono, tc) 311 1.1 jruoho { 312 1.6 riastrad timer_signal_create(CLOCK_MONOTONIC, NOEXPIRE, 0); 313 1.6 riastrad } 314 1.6 riastrad 315 1.6 riastrad ATF_TC(timer_create_mono_abs); 316 1.6 riastrad ATF_TC_HEAD(timer_create_mono_abs, tc) 317 1.6 riastrad { 318 1.6 riastrad 319 1.6 riastrad atf_tc_set_md_var(tc, "descr", 320 1.6 riastrad "Checks timer_create(2) with CLOCK_MONOTONIC and sigevent(3), " 321 1.6 riastrad "SIGEV_SIGNAL, using absolute time"); 322 1.6 riastrad } 323 1.6 riastrad 324 1.6 riastrad ATF_TC_BODY(timer_create_mono_abs, tc) 325 1.6 riastrad { 326 1.6 riastrad timer_signal_create(CLOCK_MONOTONIC, NOEXPIRE, TIMER_ABSTIME); 327 1.3 christos } 328 1.3 christos 329 1.3 christos ATF_TC(timer_create_real_expire); 330 1.3 christos ATF_TC_HEAD(timer_create_real_expire, tc) 331 1.3 christos { 332 1.3 christos 333 1.3 christos atf_tc_set_md_var(tc, "descr", 334 1.3 christos "Checks timer_create(2) with CLOCK_REALTIME and sigevent(3), " 335 1.3 christos "SIGEV_SIGNAL, with expiration"); 336 1.3 christos } 337 1.3 christos 338 1.3 christos ATF_TC_BODY(timer_create_real_expire, tc) 339 1.3 christos { 340 1.6 riastrad timer_signal_create(CLOCK_REALTIME, EXPIRE, 0); 341 1.6 riastrad } 342 1.6 riastrad 343 1.6 riastrad ATF_TC(timer_create_real_expire_abs); 344 1.6 riastrad ATF_TC_HEAD(timer_create_real_expire_abs, tc) 345 1.6 riastrad { 346 1.6 riastrad 347 1.6 riastrad atf_tc_set_md_var(tc, "descr", 348 1.6 riastrad "Checks timer_create(2) with CLOCK_REALTIME and sigevent(3), " 349 1.6 riastrad "SIGEV_SIGNAL, with expiration, using absolute time"); 350 1.6 riastrad } 351 1.6 riastrad 352 1.6 riastrad ATF_TC_BODY(timer_create_real_expire_abs, tc) 353 1.6 riastrad { 354 1.6 riastrad timer_signal_create(CLOCK_REALTIME, EXPIRE, TIMER_ABSTIME); 355 1.3 christos } 356 1.3 christos 357 1.3 christos ATF_TC(timer_create_mono_expire); 358 1.3 christos ATF_TC_HEAD(timer_create_mono_expire, tc) 359 1.3 christos { 360 1.3 christos 361 1.3 christos atf_tc_set_md_var(tc, "descr", 362 1.3 christos "Checks timer_create(2) with CLOCK_MONOTONIC and sigevent(3), " 363 1.3 christos "SIGEV_SIGNAL, with expiration"); 364 1.3 christos } 365 1.3 christos 366 1.3 christos ATF_TC_BODY(timer_create_mono_expire, tc) 367 1.3 christos { 368 1.6 riastrad timer_signal_create(CLOCK_MONOTONIC, EXPIRE, 0); 369 1.6 riastrad } 370 1.6 riastrad 371 1.6 riastrad ATF_TC(timer_create_mono_expire_abs); 372 1.6 riastrad ATF_TC_HEAD(timer_create_mono_expire_abs, tc) 373 1.6 riastrad { 374 1.6 riastrad 375 1.6 riastrad atf_tc_set_md_var(tc, "descr", 376 1.6 riastrad "Checks timer_create(2) with CLOCK_MONOTONIC and sigevent(3), " 377 1.6 riastrad "SIGEV_SIGNAL, with expiration, using absolute time"); 378 1.6 riastrad } 379 1.6 riastrad 380 1.6 riastrad ATF_TC_BODY(timer_create_mono_expire_abs, tc) 381 1.6 riastrad { 382 1.6 riastrad timer_signal_create(CLOCK_MONOTONIC, EXPIRE, TIMER_ABSTIME); 383 1.6 riastrad } 384 1.6 riastrad 385 1.6 riastrad ATF_TC(timer_create_real_past_abs); 386 1.6 riastrad ATF_TC_HEAD(timer_create_real_past_abs, tc) 387 1.6 riastrad { 388 1.6 riastrad 389 1.6 riastrad atf_tc_set_md_var(tc, "descr", 390 1.6 riastrad "Checks timer_create(2) with CLOCK_REALTIME and sigevent(3), " 391 1.6 riastrad "SIGEV_SIGNAL, with expiration passed before timer_settime(2)," 392 1.6 riastrad " using absolute time"); 393 1.6 riastrad } 394 1.6 riastrad 395 1.6 riastrad ATF_TC_BODY(timer_create_real_past_abs, tc) 396 1.6 riastrad { 397 1.6 riastrad timer_signal_create(CLOCK_REALTIME, PAST, TIMER_ABSTIME); 398 1.6 riastrad } 399 1.6 riastrad 400 1.6 riastrad ATF_TC(timer_create_mono_past_abs); 401 1.6 riastrad ATF_TC_HEAD(timer_create_mono_past_abs, tc) 402 1.6 riastrad { 403 1.6 riastrad 404 1.6 riastrad atf_tc_set_md_var(tc, "descr", 405 1.6 riastrad "Checks timer_create(2) with CLOCK_MONOTONIC and sigevent(3), " 406 1.6 riastrad "SIGEV_SIGNAL, with expiration passed before timer_settime(2)," 407 1.6 riastrad " using absolute time"); 408 1.6 riastrad } 409 1.6 riastrad 410 1.6 riastrad ATF_TC_BODY(timer_create_mono_past_abs, tc) 411 1.6 riastrad { 412 1.6 riastrad timer_signal_create(CLOCK_MONOTONIC, PAST, TIMER_ABSTIME); 413 1.6 riastrad } 414 1.6 riastrad 415 1.6 riastrad ATF_TC(timer_invalidtime); 416 1.6 riastrad ATF_TC_HEAD(timer_invalidtime, tc) 417 1.6 riastrad { 418 1.6 riastrad atf_tc_set_md_var(tc, "descr", 419 1.6 riastrad "Verify timer_settime(2) rejects invalid times"); 420 1.6 riastrad } 421 1.6 riastrad 422 1.6 riastrad ATF_TC_BODY(timer_invalidtime, tc) 423 1.6 riastrad { 424 1.6 riastrad const struct itimerspec einval_its[] = { 425 1.7 riastrad [0] = { .it_value = {-1, 0} }, 426 1.7 riastrad [1] = { .it_value = {0, -1} }, 427 1.7 riastrad [2] = { .it_value = {0, 1000000001} }, 428 1.7 riastrad [3] = { .it_value = {1, 0}, .it_interval = {-1, 0} }, 429 1.7 riastrad [4] = { .it_value = {1, 0}, .it_interval = {0, -1} }, 430 1.7 riastrad [5] = { .it_value = {1, 0}, .it_interval = {0, 1000000001} }, 431 1.6 riastrad }; 432 1.6 riastrad struct timespec now; 433 1.7 riastrad sigset_t sigs, mask; 434 1.6 riastrad unsigned i; 435 1.6 riastrad 436 1.7 riastrad RL(sigemptyset(&sigs)); 437 1.7 riastrad RL(sigaddset(&sigs, SIGALRM)); 438 1.7 riastrad RL(sigprocmask(SIG_BLOCK, &sigs, &mask)); 439 1.7 riastrad 440 1.6 riastrad RL(clock_gettime(CLOCK_MONOTONIC, &now)); 441 1.6 riastrad 442 1.6 riastrad RL(timer_create(CLOCK_MONOTONIC, NULL, &t)); 443 1.6 riastrad 444 1.6 riastrad for (i = 0; i < __arraycount(einval_its); i++) { 445 1.6 riastrad struct itimerspec its; 446 1.6 riastrad 447 1.7 riastrad fprintf(stderr, "case %u\n", i); 448 1.7 riastrad 449 1.6 riastrad ATF_CHECK_ERRNO(EINVAL, 450 1.6 riastrad timer_settime(t, 0, &einval_its[i], NULL) == -1); 451 1.6 riastrad 452 1.10 riastrad /* 453 1.10 riastrad * Try the same with an absolute time near now (unless 454 1.10 riastrad * that makes it a valid time, in case 0). 455 1.10 riastrad */ 456 1.10 riastrad if (i == 0) 457 1.10 riastrad continue; 458 1.6 riastrad its.it_value = einval_its[i].it_value; 459 1.10 riastrad its.it_value.tv_sec += now.tv_sec; 460 1.10 riastrad its.it_interval = einval_its[i].it_interval; 461 1.6 riastrad ATF_CHECK_ERRNO(EINVAL, 462 1.6 riastrad timer_settime(t, TIMER_ABSTIME, &its, NULL) == -1); 463 1.6 riastrad } 464 1.6 riastrad 465 1.7 riastrad /* Wait up to 2sec to make sure no timer got set anyway. */ 466 1.7 riastrad ATF_CHECK_ERRNO(EAGAIN, 467 1.7 riastrad sigtimedwait(&sigs, NULL, &(const struct timespec){2, 0}) == -1); 468 1.7 riastrad RL(sigprocmask(SIG_SETMASK, &mask, NULL)); 469 1.7 riastrad 470 1.6 riastrad RL(timer_delete(t)); 471 1.1 jruoho } 472 1.1 jruoho 473 1.1 jruoho ATF_TP_ADD_TCS(tp) 474 1.1 jruoho { 475 1.1 jruoho 476 1.2 jruoho ATF_TP_ADD_TC(tp, timer_create_err); 477 1.2 jruoho ATF_TP_ADD_TC(tp, timer_create_real); 478 1.6 riastrad ATF_TP_ADD_TC(tp, timer_create_real_abs); 479 1.2 jruoho ATF_TP_ADD_TC(tp, timer_create_mono); 480 1.6 riastrad ATF_TP_ADD_TC(tp, timer_create_mono_abs); 481 1.3 christos ATF_TP_ADD_TC(tp, timer_create_real_expire); 482 1.6 riastrad ATF_TP_ADD_TC(tp, timer_create_real_expire_abs); 483 1.3 christos ATF_TP_ADD_TC(tp, timer_create_mono_expire); 484 1.6 riastrad ATF_TP_ADD_TC(tp, timer_create_mono_expire_abs); 485 1.6 riastrad ATF_TP_ADD_TC(tp, timer_create_real_past_abs); 486 1.6 riastrad ATF_TP_ADD_TC(tp, timer_create_mono_past_abs); 487 1.6 riastrad ATF_TP_ADD_TC(tp, timer_invalidtime); 488 1.1 jruoho 489 1.1 jruoho return atf_no_error(); 490 1.1 jruoho } 491