xref: /netbsd-src/tests/kernel/t_time_arith.c (revision faf3bea1422fb86b481b6b57a9907d22e5c3f1b2)
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