1 /* $NetBSD: t_time_arith.c,v 1.1 2024/12/22 23:25:15 riastradh Exp $ */ 2 3 /*- 4 * Copyright (c) 2024 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 __RCSID("$NetBSD: t_time_arith.c,v 1.1 2024/12/22 23:25:15 riastradh Exp $"); 31 32 #include <sys/timearith.h> 33 34 #include <atf-c.h> 35 #include <errno.h> 36 #include <limits.h> 37 #include <setjmp.h> 38 #include <signal.h> 39 #include <stdbool.h> 40 #include <stdint.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <time.h> 45 #include <unistd.h> 46 #include <util.h> 47 48 #include "h_macros.h" 49 50 enum { HZ = 100 }; 51 52 int hz = HZ; 53 int tick = 1000000/HZ; 54 55 static sig_atomic_t jmp_en; 56 static int jmp_sig; 57 static jmp_buf jmp; 58 59 static void 60 handle_signal(int signo) 61 { 62 const int errno_save = errno; 63 char buf[32]; 64 65 snprintf_ss(buf, sizeof(buf), "signal %d\n", signo); 66 (void)write(STDERR_FILENO, buf, strlen(buf)); 67 68 errno = errno_save; 69 70 if (jmp_en) { 71 jmp_sig = signo; 72 jmp_en = 0; 73 longjmp(jmp, 1); 74 } else { 75 raise_default_signal(signo); 76 } 77 } 78 79 const struct itimer_transition { 80 struct itimerspec it_time; 81 struct timespec it_now; 82 struct timespec it_next; 83 int it_overruns; 84 const char *it_xfail; 85 } itimer_transitions[] = { 86 /* 87 * Fired more than one interval early -- treat clock as wound 88 * backwards, not counting overruns. Advance by somewhere 89 * between one and two intervals from now. 90 */ 91 [0] = {{.it_value = {3,0}, .it_interval = {1,0}}, 92 {0,1}, {2,0}, 0, 93 /* 1.709551617 */ 94 "PR kern/58925: itimer(9) responds erratically to clock wound back"}, 95 [1] = {{.it_value = {3,0}, .it_interval = {1,0}}, 96 {0,500000000}, {2,0}, 0, 97 /* 1.709551615 */ 98 "PR kern/58925: itimer(9) responds erratically to clock wound back"}, 99 [2] = {{.it_value = {3,0}, .it_interval = {1,0}}, 100 {0,999999999}, {2,0}, 0, 101 /* 2.709551613 */ 102 "PR kern/58925: itimer(9) responds erratically to clock wound back"}, 103 [3] = {{.it_value = {3,0}, .it_interval = {1,0}}, 104 {1,0}, {2,0}, 0, 105 /* 2.709551615 */ 106 "PR kern/58925: itimer(9) responds erratically to clock wound back"}, 107 [4] = {{.it_value = {3,0}, .it_interval = {1,0}}, 108 {1,1}, {3,0}, 0, 109 /* 2.709551617 */ 110 "PR kern/58925: itimer(9) responds erratically to clock wound back"}, 111 [5] = {{.it_value = {3,0}, .it_interval = {1,0}}, 112 {1,500000000}, {3,0}, 0, 113 /* 2.709551615 */ 114 "PR kern/58925: itimer(9) responds erratically to clock wound back"}, 115 [6] = {{.it_value = {3,0}, .it_interval = {1,0}}, 116 {1,999999999}, {3,0}, 0, 117 /* 3.709551613 */ 118 "PR kern/58925: itimer(9) responds erratically to clock wound back"}, 119 120 /* 121 * Fired exactly one interval early. Treat this too as clock 122 * wound backwards. 123 */ 124 [7] = {{.it_value = {3,0}, .it_interval = {1,0}}, 125 {2,0}, {3,0}, 0, 126 /* 3.709551615 */ 127 "PR kern/58925: itimer(9) responds erratically to clock wound back"}, 128 129 /* 130 * Fired less than one interval early -- callouts and real-time 131 * clock might not be perfectly synced, counted as zero 132 * overruns. Advance by one interval from the scheduled time. 133 */ 134 [8] = {{.it_value = {3,0}, .it_interval = {1,0}}, 135 {2,1}, {4,0}, 0, 136 /* 3.000000001 */ 137 "PR kern/58925: itimer(9) responds erratically to clock wound back"}, 138 [9] = {{.it_value = {3,0}, .it_interval = {1,0}}, 139 {2,500000000}, {4,0}, 0, 140 /* 3.999999999 */ 141 "PR kern/58925: itimer(9) responds erratically to clock wound back"}, 142 [10] = {{.it_value = {3,0}, .it_interval = {1,0}}, 143 {2,999999999}, {4,0}, 0, 144 /* 4.999999997 */ 145 "PR kern/58925: itimer(9) responds erratically to clock wound back"}, 146 147 /* 148 * Fired exactly on time. Advance by one interval. 149 */ 150 [11] = {{.it_value = {3,0}, .it_interval = {1,0}}, 151 {3,0}, {4,0}, 0, NULL}, 152 153 /* 154 * Fired late by less than one interval -- callouts and 155 * real-time clock might not be prefectly synced, counted as 156 * zero overruns. Advance by one interval from the scheduled 157 * time (even if it's very close to a full interval). 158 */ 159 [12] = {{.it_value = {3,0}, .it_interval = {1,0}}, 160 {3,1}, {4,0}, 0, NULL}, 161 [14] = {{.it_value = {3,0}, .it_interval = {1,0}}, 162 {3,500000000}, {4,0}, 0, NULL}, 163 [15] = {{.it_value = {3,0}, .it_interval = {1,0}}, 164 {3,999999999}, {4,0}, 0, NULL}, 165 166 /* 167 * Fired late by exactly one interval -- treat it as overrun. 168 * 169 * XXX ...or treat it as not overrun? wat 170 */ 171 [16] = {{.it_value = {3,0}, .it_interval = {1,0}}, 172 {4,0}, {4,0}, 0, NULL}, 173 174 /* 175 * Fired late by more than one interval but less than two -- 176 * overrun. 177 */ 178 [17] = {{.it_value = {3,0}, .it_interval = {1,0}}, 179 {4,1}, {5,0}, 1, 180 /* 4.000000000, overruns=0 */ 181 "PR kern/58927: itimer(9): overrun accounting is broken"}, 182 [18] = {{.it_value = {3,0}, .it_interval = {1,0}}, 183 {4,500000000}, {5,0}, 1, 184 /* 4.000000000, overruns=0 */ 185 "PR kern/58927: itimer(9): overrun accounting is broken"}, 186 [19] = {{.it_value = {3,0}, .it_interval = {1,0}}, 187 {4,999999999}, {5,0}, 1, 188 /* 4.000000000, overruns=0 */ 189 "PR kern/58927: itimer(9): overrun accounting is broken"}, 190 191 /* 192 * Fired late by exactly two intervals -- two overruns. 193 */ 194 [20] = {{.it_value = {3,0}, .it_interval = {1,0}}, 195 {5,0}, {6,0}, 2, 196 /* 4.000000000, overruns=0 */ 197 "PR kern/58927: itimer(9): overrun accounting is broken"}, 198 199 /* 200 * Fired late by more intervals plus slop, up to 32. 201 * 202 * XXX Define DELAYTIMER_MAX so we can write it in terms of 203 * that. 204 */ 205 [21] = {{.it_value = {3,0}, .it_interval = {1,0}}, 206 {13,123456789}, {14,0}, 10, 207 /* 4.000000000, overruns=0 */ 208 "PR kern/58927: itimer(9): overrun accounting is broken"}, 209 [22] = {{.it_value = {3,0}, .it_interval = {1,0}}, 210 {34,999999999}, {32,0}, 32, 211 /* 4.000000000, overruns=0 */ 212 "PR kern/58927: itimer(9): overrun accounting is broken"}, 213 214 /* 215 * Fired late by roughly INT_MAX intervals. 216 */ 217 [23] = {{.it_value = {3,0}, .it_interval = {1,0}}, 218 {(time_t)3 + INT_MAX - 1, 0}, 219 {(time_t)3 + INT_MAX, 0}, 220 INT_MAX, 221 /* 4.000000000, overruns=0 */ 222 "PR kern/58927: itimer(9): overrun accounting is broken"}, 223 [24] = {{.it_value = {3,0}, .it_interval = {1,0}}, 224 {(time_t)3 + INT_MAX, 0}, 225 {(time_t)3 + INT_MAX + 1, 0}, 226 INT_MAX, 227 /* 4.000000000, overruns=0 */ 228 "PR kern/58926: itimer(9) integer overflow in overrun counting"}, 229 [25] = {{.it_value = {3,0}, .it_interval = {1,0}}, 230 {(time_t)3 + INT_MAX + 1, 0}, 231 {(time_t)3 + INT_MAX + 2, 0}, 232 INT_MAX, 233 /* 4.000000000, overruns=0 */ 234 "PR kern/58926: itimer(9) integer overflow in overrun counting"}, 235 236 /* (2^63 - 1) ns */ 237 [26] = {{.it_value = {3,0}, .it_interval = {9223372036,854775807}}, 238 {3,1}, {9223372039,854775807}, 0, NULL}, 239 /* 2^63 ns */ 240 [27] = {{.it_value = {3,0}, .it_interval = {9223372036,854775808}}, 241 {3,1}, {9223372039,854775808}, 0, NULL}, 242 /* (2^63 + 1) ns */ 243 [28] = {{.it_value = {3,0}, .it_interval = {9223372036,854775809}}, 244 {3,1}, {9223372039,854775809}, 0, NULL}, 245 246 /* 247 * Overflows -- we should (XXX but currently don't) reject 248 * intervals of at least 2^64 nanoseconds up front, since this 249 * is more time than it is reasonable to wait (more than 584 250 * years). 251 */ 252 253 /* (2^64 - 1) ns */ 254 [29] = {{.it_value = {3,0}, .it_interval = {18446744073,709551615}}, 255 {2,999999999}, {0,0}, 0, 256 "PR kern/58922: itimer(9): arithmetic overflow"}, 257 /* 2^64 ns */ 258 [30] = {{.it_value = {3,0}, .it_interval = {18446744073,709551616}}, 259 {2,999999999}, {0,0}, 0, 260 "PR kern/58922: itimer(9): arithmetic overflow"}, 261 /* (2^64 + 1) ns */ 262 [31] = {{.it_value = {3,0}, .it_interval = {18446744073,709551617}}, 263 {2,999999999}, {0,0}, 0, 264 "PR kern/58922: itimer(9): arithmetic overflow"}, 265 266 /* (2^63 - 1) us */ 267 [32] = {{.it_value = {3,0}, .it_interval = {9223372036854,775807}}, 268 {2,999999999}, {0,0}, 0, 269 "PR kern/58922: itimer(9): arithmetic overflow"}, 270 /* 2^63 us */ 271 [33] = {{.it_value = {3,0}, .it_interval = {9223372036854,775808}}, 272 {2,999999999}, {0,0}, 0, 273 "PR kern/58922: itimer(9): arithmetic overflow"}, 274 /* (2^63 + 1) us */ 275 [34] = {{.it_value = {3,0}, .it_interval = {9223372036854,775809}}, 276 {2,999999999}, {0,0}, 0, 277 "PR kern/58922: itimer(9): arithmetic overflow"}, 278 279 /* (2^64 - 1) us */ 280 [35] = {{.it_value = {3,0}, .it_interval = {18446744073709,551615}}, 281 {2,999999999}, {0,0}, 0, 282 "PR kern/58922: itimer(9): arithmetic overflow"}, 283 /* 2^64 us */ 284 [36] = {{.it_value = {3,0}, .it_interval = {18446744073709,551616}}, 285 {2,999999999}, {0,0}, 0, 286 "PR kern/58922: itimer(9): arithmetic overflow"}, 287 /* (2^64 + 1) us */ 288 [37] = {{.it_value = {3,0}, .it_interval = {18446744073709,551617}}, 289 {2,999999999}, {0,0}, 0, 290 "PR kern/58922: itimer(9): arithmetic overflow"}, 291 292 /* (2^63 - 1) ms */ 293 [38] = {{.it_value = {3,0}, .it_interval = {9223372036854775,807}}, 294 {2,999999999}, {0,0}, 0, 295 "PR kern/58922: itimer(9): arithmetic overflow"}, 296 /* 2^63 ms */ 297 [39] = {{.it_value = {3,0}, .it_interval = {9223372036854775,808}}, 298 {2,999999999}, {0,0}, 0, 299 "PR kern/58922: itimer(9): arithmetic overflow"}, 300 /* (2^63 + 1) ms */ 301 [40] = {{.it_value = {3,0}, .it_interval = {9223372036854775,809}}, 302 {2,999999999}, {0,0}, 0, 303 "PR kern/58922: itimer(9): arithmetic overflow"}, 304 305 /* (2^64 - 1) ms */ 306 [41] = {{.it_value = {3,0}, .it_interval = {18446744073709551,615}}, 307 {2,999999999}, {0,0}, 0, 308 "PR kern/58922: itimer(9): arithmetic overflow"}, 309 /* 2^64 ms */ 310 [42] = {{.it_value = {3,0}, .it_interval = {18446744073709551,616}}, 311 {2,999999999}, {0,0}, 0, 312 "PR kern/58922: itimer(9): arithmetic overflow"}, 313 /* (2^64 + 1) ms */ 314 [43] = {{.it_value = {3,0}, .it_interval = {18446744073709551,617}}, 315 {2,999999999}, {0,0}, 0, 316 "PR kern/58922: itimer(9): arithmetic overflow"}, 317 318 /* invalid intervals */ 319 [44] = {{.it_value = {3,0}, .it_interval = {-1,0}}, 320 {3,1}, {0,0}, 0, NULL}, 321 [45] = {{.it_value = {3,0}, .it_interval = {0,-1}}, 322 {3,1}, {0,0}, 0, NULL}, 323 [46] = {{.it_value = {3,0}, .it_interval = {0,1000000000}}, 324 {3,1}, {0,0}, 0, NULL}, 325 }; 326 327 ATF_TC(itimer_transitions); 328 ATF_TC_HEAD(itimer_transitions, tc) 329 { 330 atf_tc_set_md_var(tc, "descr", 331 "Tests interval timer transitions"); 332 } 333 ATF_TC_BODY(itimer_transitions, tc) 334 { 335 volatile unsigned i; 336 337 REQUIRE_LIBC(signal(SIGFPE, handle_signal), SIG_ERR); 338 REQUIRE_LIBC(signal(SIGABRT, handle_signal), SIG_ERR); 339 340 for (i = 0; i < __arraycount(itimer_transitions); i++) { 341 struct itimer_transition it = itimer_transitions[i]; 342 struct timespec next; 343 int overruns; 344 volatile bool aborted = true; 345 volatile bool expect_abort = false; 346 347 fprintf(stderr, "case %u\n", i); 348 349 if (it.it_xfail) 350 atf_tc_expect_fail("%s", it.it_xfail); 351 352 if (itimespecfix(&it.it_time.it_value) != 0 || 353 itimespecfix(&it.it_time.it_interval) != 0) { 354 fprintf(stderr, "rejected by itimerspecfix\n"); 355 expect_abort = true; 356 } 357 358 if (setjmp(jmp) == 0) { 359 jmp_en = 1; 360 itimer_transition(&it.it_time, &it.it_now, 361 &next, &overruns); 362 jmp_en = 0; 363 aborted = false; 364 } 365 ATF_CHECK(!jmp_en); 366 jmp_en = 0; /* paranoia */ 367 if (expect_abort) { 368 fprintf(stderr, "expected abort\n"); 369 ATF_CHECK_MSG(aborted, 370 "[%u] missing invariant assertion", i); 371 ATF_CHECK_MSG(jmp_sig == SIGABRT, 372 "[%u] missing invariant assertion", i); 373 } else { 374 ATF_CHECK_MSG(!aborted, "[%u] raised signal %d: %s", i, 375 jmp_sig, strsignal(jmp_sig)); 376 } 377 378 ATF_CHECK_MSG((next.tv_sec == it.it_next.tv_sec && 379 next.tv_nsec == it.it_next.tv_nsec), 380 "[%u] periodic intervals of %lld.%09d from %lld.%09d" 381 " last expired at %lld.%09d:" 382 " next expiry at %lld.%09d, expected %lld.%09d", i, 383 (long long)it.it_time.it_interval.tv_sec, 384 (int)it.it_time.it_interval.tv_nsec, 385 (long long)it.it_time.it_value.tv_sec, 386 (int)it.it_time.it_value.tv_nsec, 387 (long long)it.it_now.tv_sec, (int)it.it_now.tv_nsec, 388 (long long)next.tv_sec, (int)next.tv_nsec, 389 (long long)it.it_next.tv_sec, (int)it.it_next.tv_nsec); 390 ATF_CHECK_EQ_MSG(overruns, it.it_overruns, 391 "[%u] periodic intervals of %lld.%09d from %lld.%09d" 392 " last expired at %lld.%09d:" 393 " overruns %d, expected %d", i, 394 (long long)it.it_time.it_interval.tv_sec, 395 (int)it.it_time.it_interval.tv_nsec, 396 (long long)it.it_time.it_value.tv_sec, 397 (int)it.it_time.it_value.tv_nsec, 398 (long long)it.it_now.tv_sec, (int)it.it_now.tv_nsec, 399 overruns, it.it_overruns); 400 401 if (it.it_xfail) 402 atf_tc_expect_pass(); 403 } 404 } 405 406 ATF_TP_ADD_TCS(tp) 407 { 408 409 ATF_TP_ADD_TC(tp, itimer_transitions); 410 411 return atf_no_error(); 412 } 413 414