1 /* $NetBSD: t_timer.c,v 1.3 2021/10/22 13:53:20 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 2021 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_timer.c,v 1.3 2021/10/22 13:53:20 thorpej Exp $"); 31 32 #include <sys/types.h> 33 #include <sys/event.h> 34 #include <errno.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <time.h> 38 #include <unistd.h> 39 40 #include <atf-c.h> 41 42 ATF_TC(basic_timer); 43 ATF_TC_HEAD(basic_timer, tc) 44 { 45 atf_tc_set_md_var(tc, "descr", 46 "tests basic EVFILT_TIMER functionality"); 47 } 48 49 #define TIME1 1000 /* 1000ms -> 1s */ 50 #define TIME1_COUNT 5 51 #define TIME2 6000 /* 6000ms -> 6s */ 52 53 #define TIME1_TOTAL_SEC ((TIME1 * TIME1_COUNT) / 1000) 54 #define TIME2_TOTAL_SEC (TIME2 / 1000) 55 56 ATF_TC_BODY(basic_timer, tc) 57 { 58 struct kevent event[2]; 59 int ntimer1 = 0, ntimer2 = 0; 60 struct timespec ots, ts; 61 int kq; 62 63 ATF_REQUIRE((kq = kqueue()) >= 0); 64 65 EV_SET(&event[0], 1, EVFILT_TIMER, EV_ADD, 0, TIME1, NULL); 66 EV_SET(&event[1], 2, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, TIME2, NULL); 67 68 ATF_REQUIRE(kevent(kq, event, 2, NULL, 0, NULL) == 0); 69 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ots) == 0); 70 71 for (;;) { 72 ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, NULL) == 1); 73 ATF_REQUIRE(event[0].filter == EVFILT_TIMER); 74 ATF_REQUIRE(event[0].ident == 1 || 75 event[0].ident == 2); 76 if (event[0].ident == 1) { 77 ATF_REQUIRE(ntimer1 < TIME1_COUNT); 78 if (++ntimer1 == TIME1_COUNT) { 79 /* 80 * Make sure TIME1_TOTAL_SEC seconds have 81 * elapsed, allowing for a little slop. 82 */ 83 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, 84 &ts) == 0); 85 timespecsub(&ts, &ots, &ts); 86 ATF_REQUIRE(ts.tv_sec == 87 (TIME1_TOTAL_SEC - 1) || 88 ts.tv_sec == TIME1_TOTAL_SEC); 89 if (ts.tv_sec == TIME1_TOTAL_SEC - 1) { 90 ATF_REQUIRE(ts.tv_nsec >= 91 900000000); 92 } 93 EV_SET(&event[0], 1, EVFILT_TIMER, EV_DELETE, 94 0, 0, NULL); 95 ATF_REQUIRE(kevent(kq, event, 1, NULL, 0, 96 NULL) == 0); 97 } 98 } else { 99 ATF_REQUIRE(ntimer1 == TIME1_COUNT); 100 ATF_REQUIRE(ntimer2 == 0); 101 ntimer2++; 102 /* 103 * Make sure TIME2_TOTAL_SEC seconds have 104 * elapsed, allowing for a little slop. 105 */ 106 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, 107 &ts) == 0); 108 timespecsub(&ts, &ots, &ts); 109 ATF_REQUIRE(ts.tv_sec == 110 (TIME2_TOTAL_SEC - 1) || 111 ts.tv_sec == TIME2_TOTAL_SEC); 112 if (ts.tv_sec == TIME2_TOTAL_SEC - 1) { 113 ATF_REQUIRE(ts.tv_nsec >= 900000000); 114 } 115 EV_SET(&event[0], 2, EVFILT_TIMER, EV_DELETE, 116 0, 0, NULL); 117 ATF_REQUIRE_ERRNO(ENOENT, 118 kevent(kq, event, 1, NULL, 0, NULL) == -1); 119 break; 120 } 121 } 122 123 /* 124 * Now block in kqueue for TIME2_TOTAL_SEC, and ensure we 125 * don't receive any new events. 126 */ 127 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ots) == 0); 128 ts.tv_sec = TIME2_TOTAL_SEC; 129 ts.tv_nsec = 0; 130 ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, &ts) == 0); 131 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ts) == 0); 132 timespecsub(&ts, &ots, &ts); 133 ATF_REQUIRE(ts.tv_sec == (TIME2_TOTAL_SEC - 1) || 134 ts.tv_sec == TIME2_TOTAL_SEC || 135 ts.tv_sec == (TIME2_TOTAL_SEC + 1)); 136 if (ts.tv_sec == TIME2_TOTAL_SEC - 1) { 137 ATF_REQUIRE(ts.tv_nsec >= 900000000); 138 } else if (ts.tv_sec == TIME2_TOTAL_SEC + 1) { 139 ATF_REQUIRE(ts.tv_nsec < 500000000); 140 } 141 } 142 143 ATF_TC(count_expirations); 144 ATF_TC_HEAD(count_expirations, tc) 145 { 146 atf_tc_set_md_var(tc, "descr", 147 "tests counting timer expirations"); 148 } 149 150 ATF_TC_BODY(count_expirations, tc) 151 { 152 struct kevent event[1]; 153 struct timespec ts = { 0, 0 }; 154 struct timespec sleepts; 155 int kq; 156 157 ATF_REQUIRE((kq = kqueue()) >= 0); 158 159 EV_SET(&event[0], 1, EVFILT_TIMER, EV_ADD, 0, TIME1, NULL); 160 ATF_REQUIRE(kevent(kq, event, 1, NULL, 0, NULL) == 0); 161 162 /* Sleep a little longer to mitigate timing jitter. */ 163 sleepts.tv_sec = TIME1_TOTAL_SEC; 164 sleepts.tv_nsec = 500000000; 165 ATF_REQUIRE(nanosleep(&sleepts, NULL) == 0); 166 167 ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, &ts) == 1); 168 ATF_REQUIRE(event[0].ident == 1); 169 ATF_REQUIRE(event[0].data == TIME1_COUNT || 170 event[0].data == TIME1_COUNT + 1); 171 } 172 173 ATF_TC(modify); 174 ATF_TC_HEAD(modify, tc) 175 { 176 atf_tc_set_md_var(tc, "descr", 177 "tests modifying a timer"); 178 } 179 180 ATF_TC_BODY(modify, tc) 181 { 182 struct kevent event[1]; 183 struct timespec ts = { 0, 0 }; 184 struct timespec sleepts; 185 int kq; 186 187 ATF_REQUIRE((kq = kqueue()) >= 0); 188 189 /* 190 * Start a 500ms timer, sleep for 5 seconds, and check 191 * the total count. 192 */ 193 EV_SET(&event[0], 1, EVFILT_TIMER, EV_ADD, 0, 500, NULL); 194 ATF_REQUIRE(kevent(kq, event, 1, NULL, 0, NULL) == 0); 195 196 sleepts.tv_sec = 5; 197 sleepts.tv_nsec = 0; 198 ATF_REQUIRE(nanosleep(&sleepts, NULL) == 0); 199 200 ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, &ts) == 1); 201 ATF_REQUIRE(event[0].ident == 1); 202 ATF_REQUIRE(event[0].data >= 9 && event[0].data <= 11); 203 204 /* 205 * Modify to a 4 second timer, sleep for 5 seconds, and check 206 * the total count. 207 */ 208 EV_SET(&event[0], 1, EVFILT_TIMER, EV_ADD, 0, 4000, NULL); 209 ATF_REQUIRE(kevent(kq, event, 1, NULL, 0, NULL) == 0); 210 211 /* 212 * Before we sleep, verify that the knote for this timer is 213 * no longer activated. 214 */ 215 ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, &ts) == 0); 216 217 sleepts.tv_sec = 5; 218 sleepts.tv_nsec = 0; 219 ATF_REQUIRE(nanosleep(&sleepts, NULL) == 0); 220 221 ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, &ts) == 1); 222 ATF_REQUIRE(event[0].ident == 1); 223 ATF_REQUIRE(event[0].data == 1); 224 225 /* 226 * Start a 500ms timer, sleep for 2 seconds. 227 */ 228 EV_SET(&event[0], 1, EVFILT_TIMER, EV_ADD, 0, 500, NULL); 229 ATF_REQUIRE(kevent(kq, event, 1, NULL, 0, NULL) == 0); 230 231 sleepts.tv_sec = 2; 232 sleepts.tv_nsec = 0; 233 ATF_REQUIRE(nanosleep(&sleepts, NULL) == 0); 234 235 /* 236 * Set the SAME timer, sleep for 2 seconds. 237 */ 238 EV_SET(&event[0], 1, EVFILT_TIMER, EV_ADD, 0, 500, NULL); 239 ATF_REQUIRE(kevent(kq, event, 1, NULL, 0, NULL) == 0); 240 241 sleepts.tv_sec = 2; 242 sleepts.tv_nsec = 0; 243 ATF_REQUIRE(nanosleep(&sleepts, NULL) == 0); 244 245 /* 246 * The kernel should have reset the count when modifying the 247 * timer, so we should only expect to see the expiration count 248 * for the second sleep. 249 */ 250 ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, &ts) == 1); 251 ATF_REQUIRE(event[0].ident == 1); 252 ATF_REQUIRE(event[0].data >= 3 && event[0].data <= 5); 253 } 254 255 ATF_TC(abstime); 256 ATF_TC_HEAD(abstime, tc) 257 { 258 atf_tc_set_md_var(tc, "descr", 259 "tests timers with NOTE_ABSTIME"); 260 } 261 262 ATF_TC_BODY(abstime, tc) 263 { 264 struct kevent event[1]; 265 struct timespec ts, ots; 266 time_t seconds; 267 int kq; 268 269 ATF_REQUIRE((kq = kqueue()) >= 0); 270 271 ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &ots) == 0); 272 ATF_REQUIRE(ots.tv_sec < INTPTR_MAX - TIME1_TOTAL_SEC); 273 274 seconds = ots.tv_sec + TIME1_TOTAL_SEC; 275 if (ots.tv_nsec >= 500000000) { 276 seconds++; 277 } 278 279 EV_SET(&event[0], 1, EVFILT_TIMER, EV_ADD, 280 NOTE_ABSTIME | NOTE_SECONDS, seconds, NULL); 281 ATF_REQUIRE(kevent(kq, event, 1, event, 1, NULL) == 1); 282 283 ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &ts) == 0); 284 timespecsub(&ts, &ots, &ts); 285 286 /* 287 * We're not going for precision here; just verify that it was 288 * delivered anywhere between 4.5-6.whatever seconds later. 289 */ 290 ATF_REQUIRE(ts.tv_sec >= 4 && ts.tv_sec <= 6); 291 if (ts.tv_sec == 4) { 292 ATF_REQUIRE(ts.tv_nsec >= 500000000); 293 } 294 295 ts.tv_sec = 0; 296 ts.tv_nsec = 0; 297 ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, &ts) == 1); 298 } 299 300 #define PREC_TIMEOUT_SEC 2 301 302 static void 303 do_test_timer_units(const char *which, uint32_t fflag, int64_t data) 304 { 305 struct kevent event[1]; 306 struct timespec ts, ots; 307 int kq; 308 309 ATF_REQUIRE((kq = kqueue()) >= 0); 310 311 EV_SET(&event[0], 1, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 312 fflag, data, NULL); 313 314 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ots) == 0); 315 ATF_REQUIRE(kevent(kq, event, 1, event, 1, NULL) == 1); 316 ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ts) == 0); 317 318 timespecsub(&ts, &ots, &ts); 319 ATF_REQUIRE_MSG(ts.tv_sec == (PREC_TIMEOUT_SEC - 1) || 320 ts.tv_sec == PREC_TIMEOUT_SEC, 321 "units '%s' failed [sec]", which); 322 if (ts.tv_sec == PREC_TIMEOUT_SEC - 1) { 323 ATF_REQUIRE_MSG(ts.tv_nsec >= 900000000, 324 "units '%s' failed [nsec]", which); 325 } 326 327 (void)close(kq); 328 } 329 330 #define test_timer_units(fflag, data) \ 331 do_test_timer_units(#fflag, fflag, data) 332 333 ATF_TC(timer_units); 334 ATF_TC_HEAD(timer_units, tc) 335 { 336 atf_tc_set_md_var(tc, "descr", 337 "tests timers with NOTE_* units modifiers"); 338 } 339 340 ATF_TC_BODY(timer_units, tc) 341 { 342 test_timer_units(NOTE_SECONDS, PREC_TIMEOUT_SEC); 343 test_timer_units(NOTE_MSECONDS, PREC_TIMEOUT_SEC * 1000); 344 test_timer_units(NOTE_USECONDS, PREC_TIMEOUT_SEC * 1000000); 345 test_timer_units(NOTE_NSECONDS, PREC_TIMEOUT_SEC * 1000000000); 346 } 347 348 ATF_TP_ADD_TCS(tp) 349 { 350 ATF_TP_ADD_TC(tp, basic_timer); 351 ATF_TP_ADD_TC(tp, count_expirations); 352 ATF_TP_ADD_TC(tp, abstime); 353 ATF_TP_ADD_TC(tp, timer_units); 354 ATF_TP_ADD_TC(tp, modify); 355 356 return atf_no_error(); 357 } 358