1*57718be8SEnji Cooper /* $NetBSD: t_sleep.c,v 1.8 2014/07/15 14:56:34 gson Exp $ */ 2*57718be8SEnji Cooper 3*57718be8SEnji Cooper /*- 4*57718be8SEnji Cooper * Copyright (c) 2006 Frank Kardel 5*57718be8SEnji Cooper * All rights reserved. 6*57718be8SEnji Cooper * 7*57718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without 8*57718be8SEnji Cooper * modification, are permitted provided that the following conditions 9*57718be8SEnji Cooper * are met: 10*57718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright 11*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer. 12*57718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 13*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in the 14*57718be8SEnji Cooper * documentation and/or other materials provided with the distribution. 15*57718be8SEnji Cooper * 16*57718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17*57718be8SEnji Cooper * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18*57718be8SEnji Cooper * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19*57718be8SEnji Cooper * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20*57718be8SEnji Cooper * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21*57718be8SEnji Cooper * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22*57718be8SEnji Cooper * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23*57718be8SEnji Cooper * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24*57718be8SEnji Cooper * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25*57718be8SEnji Cooper * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26*57718be8SEnji Cooper * POSSIBILITY OF SUCH DAMAGE. 27*57718be8SEnji Cooper */ 28*57718be8SEnji Cooper 29*57718be8SEnji Cooper #include <atf-c.h> 30*57718be8SEnji Cooper #include <errno.h> 31*57718be8SEnji Cooper #include <poll.h> 32*57718be8SEnji Cooper #include <stdio.h> 33*57718be8SEnji Cooper #include <stdlib.h> 34*57718be8SEnji Cooper #include <string.h> 35*57718be8SEnji Cooper #include <time.h> 36*57718be8SEnji Cooper #include <unistd.h> 37*57718be8SEnji Cooper 38*57718be8SEnji Cooper #include <sys/cdefs.h> 39*57718be8SEnji Cooper #include <sys/event.h> 40*57718be8SEnji Cooper #include <sys/signal.h> 41*57718be8SEnji Cooper 42*57718be8SEnji Cooper #include "isqemu.h" 43*57718be8SEnji Cooper 44*57718be8SEnji Cooper #define BILLION 1000000000LL /* nano-seconds per second */ 45*57718be8SEnji Cooper #define MILLION 1000000LL /* nano-seconds per milli-second */ 46*57718be8SEnji Cooper 47*57718be8SEnji Cooper #define ALARM 6 /* SIGALRM after this many seconds */ 48*57718be8SEnji Cooper #define MAXSLEEP 22 /* Maximum delay in seconds */ 49*57718be8SEnji Cooper #define KEVNT_TIMEOUT 10300 /* measured in milli-seconds */ 50*57718be8SEnji Cooper #define FUZZ (40 * MILLION) /* scheduling fuzz accepted - 40 ms */ 51*57718be8SEnji Cooper 52*57718be8SEnji Cooper /* 53*57718be8SEnji Cooper * Timer notes 54*57718be8SEnji Cooper * 55*57718be8SEnji Cooper * Most tests use FUZZ as their initial delay value, but 'sleep' 56*57718be8SEnji Cooper * starts at 1sec (since it cannot handle sub-second intervals). 57*57718be8SEnji Cooper * Subsequent passes double the previous interval, up to MAXSLEEP. 58*57718be8SEnji Cooper * 59*57718be8SEnji Cooper * The current values result in 5 passes for the 'sleep' test (at 1, 60*57718be8SEnji Cooper * 2, 4, 8, and 16 seconds) and 10 passes for the other tests (at 61*57718be8SEnji Cooper * 0.04, 0.08, 0.16, 0.32, 0.64, 1.28, 2.56, 5.12, 10.24, and 20.48 62*57718be8SEnji Cooper * seconds). 63*57718be8SEnji Cooper * 64*57718be8SEnji Cooper * The ALARM is only set if the current pass's delay is longer, and 65*57718be8SEnji Cooper * only if the ALARM has not already been triggered. 66*57718be8SEnji Cooper * 67*57718be8SEnji Cooper * The 'kevent' test needs the ALARM to be set on a different pass 68*57718be8SEnji Cooper * from when the KEVNT_TIMEOUT fires. So set ALARM to fire on the 69*57718be8SEnji Cooper * penultimate pass, and the KEVNT_TIMEOUT on the final pass. We 70*57718be8SEnji Cooper * set KEVNT_TIMEOUT just barely long enough to put it into the 71*57718be8SEnji Cooper * last test pass, and set MAXSLEEP a couple seconds longer than 72*57718be8SEnji Cooper * necessary, in order to avoid a QEMU bug which nearly doubles 73*57718be8SEnji Cooper * some timers. 74*57718be8SEnji Cooper */ 75*57718be8SEnji Cooper 76*57718be8SEnji Cooper static volatile int sig; 77*57718be8SEnji Cooper 78*57718be8SEnji Cooper int sleeptest(int (*)(struct timespec *, struct timespec *), bool, bool); 79*57718be8SEnji Cooper int do_nanosleep(struct timespec *, struct timespec *); 80*57718be8SEnji Cooper int do_select(struct timespec *, struct timespec *); 81*57718be8SEnji Cooper int do_poll(struct timespec *, struct timespec *); 82*57718be8SEnji Cooper int do_sleep(struct timespec *, struct timespec *); 83*57718be8SEnji Cooper int do_kevent(struct timespec *, struct timespec *); 84*57718be8SEnji Cooper void sigalrm(int); 85*57718be8SEnji Cooper 86*57718be8SEnji Cooper void 87*57718be8SEnji Cooper sigalrm(int s) 88*57718be8SEnji Cooper { 89*57718be8SEnji Cooper 90*57718be8SEnji Cooper sig++; 91*57718be8SEnji Cooper } 92*57718be8SEnji Cooper 93*57718be8SEnji Cooper int 94*57718be8SEnji Cooper do_nanosleep(struct timespec *delay, struct timespec *remain) 95*57718be8SEnji Cooper { 96*57718be8SEnji Cooper int ret; 97*57718be8SEnji Cooper 98*57718be8SEnji Cooper if (nanosleep(delay, remain) == -1) 99*57718be8SEnji Cooper ret = (errno == EINTR ? 0 : errno); 100*57718be8SEnji Cooper else 101*57718be8SEnji Cooper ret = 0; 102*57718be8SEnji Cooper return ret; 103*57718be8SEnji Cooper } 104*57718be8SEnji Cooper 105*57718be8SEnji Cooper int 106*57718be8SEnji Cooper do_select(struct timespec *delay, struct timespec *remain) 107*57718be8SEnji Cooper { 108*57718be8SEnji Cooper int ret; 109*57718be8SEnji Cooper struct timeval tv; 110*57718be8SEnji Cooper 111*57718be8SEnji Cooper TIMESPEC_TO_TIMEVAL(&tv, delay); 112*57718be8SEnji Cooper if (select(0, NULL, NULL, NULL, &tv) == -1) 113*57718be8SEnji Cooper ret = (errno == EINTR ? 0 : errno); 114*57718be8SEnji Cooper else 115*57718be8SEnji Cooper ret = 0; 116*57718be8SEnji Cooper return ret; 117*57718be8SEnji Cooper } 118*57718be8SEnji Cooper 119*57718be8SEnji Cooper int 120*57718be8SEnji Cooper do_poll(struct timespec *delay, struct timespec *remain) 121*57718be8SEnji Cooper { 122*57718be8SEnji Cooper int ret; 123*57718be8SEnji Cooper struct timeval tv; 124*57718be8SEnji Cooper 125*57718be8SEnji Cooper TIMESPEC_TO_TIMEVAL(&tv, delay); 126*57718be8SEnji Cooper if (pollts(NULL, 0, delay, NULL) == -1) 127*57718be8SEnji Cooper ret = (errno == EINTR ? 0 : errno); 128*57718be8SEnji Cooper else 129*57718be8SEnji Cooper ret = 0; 130*57718be8SEnji Cooper return ret; 131*57718be8SEnji Cooper } 132*57718be8SEnji Cooper 133*57718be8SEnji Cooper int 134*57718be8SEnji Cooper do_sleep(struct timespec *delay, struct timespec *remain) 135*57718be8SEnji Cooper { 136*57718be8SEnji Cooper struct timeval tv; 137*57718be8SEnji Cooper 138*57718be8SEnji Cooper TIMESPEC_TO_TIMEVAL(&tv, delay); 139*57718be8SEnji Cooper remain->tv_sec = sleep(delay->tv_sec); 140*57718be8SEnji Cooper remain->tv_nsec = 0; 141*57718be8SEnji Cooper 142*57718be8SEnji Cooper return 0; 143*57718be8SEnji Cooper } 144*57718be8SEnji Cooper 145*57718be8SEnji Cooper int 146*57718be8SEnji Cooper do_kevent(struct timespec *delay, struct timespec *remain) 147*57718be8SEnji Cooper { 148*57718be8SEnji Cooper struct kevent ktimer; 149*57718be8SEnji Cooper struct kevent kresult; 150*57718be8SEnji Cooper int rtc, kq, kerrno; 151*57718be8SEnji Cooper int tmo; 152*57718be8SEnji Cooper 153*57718be8SEnji Cooper ATF_REQUIRE_MSG((kq = kqueue()) != -1, "kqueue: %s", strerror(errno)); 154*57718be8SEnji Cooper 155*57718be8SEnji Cooper tmo = KEVNT_TIMEOUT; 156*57718be8SEnji Cooper 157*57718be8SEnji Cooper /* 158*57718be8SEnji Cooper * If we expect the KEVNT_TIMEOUT to fire, and we're running 159*57718be8SEnji Cooper * under QEMU, make sure the delay is long enough to account 160*57718be8SEnji Cooper * for the effects of PR kern/43997 ! 161*57718be8SEnji Cooper */ 162*57718be8SEnji Cooper if (isQEMU() && 163*57718be8SEnji Cooper tmo/1000 < delay->tv_sec && tmo/500 > delay->tv_sec) 164*57718be8SEnji Cooper delay->tv_sec = MAXSLEEP; 165*57718be8SEnji Cooper 166*57718be8SEnji Cooper EV_SET(&ktimer, 1, EVFILT_TIMER, EV_ADD, 0, tmo, 0); 167*57718be8SEnji Cooper 168*57718be8SEnji Cooper rtc = kevent(kq, &ktimer, 1, &kresult, 1, delay); 169*57718be8SEnji Cooper kerrno = errno; 170*57718be8SEnji Cooper 171*57718be8SEnji Cooper (void)close(kq); 172*57718be8SEnji Cooper 173*57718be8SEnji Cooper if (rtc == -1) { 174*57718be8SEnji Cooper ATF_REQUIRE_MSG(kerrno == EINTR, "kevent: %s", strerror(errno)); 175*57718be8SEnji Cooper return 0; 176*57718be8SEnji Cooper } 177*57718be8SEnji Cooper 178*57718be8SEnji Cooper if (delay->tv_sec * BILLION + delay->tv_nsec > tmo * MILLION) 179*57718be8SEnji Cooper ATF_REQUIRE_MSG(rtc > 0, 180*57718be8SEnji Cooper "kevent: KEVNT_TIMEOUT did not cause EVFILT_TIMER event"); 181*57718be8SEnji Cooper 182*57718be8SEnji Cooper return 0; 183*57718be8SEnji Cooper } 184*57718be8SEnji Cooper 185*57718be8SEnji Cooper ATF_TC(nanosleep); 186*57718be8SEnji Cooper ATF_TC_HEAD(nanosleep, tc) 187*57718be8SEnji Cooper { 188*57718be8SEnji Cooper 189*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test nanosleep(2) timing"); 190*57718be8SEnji Cooper atf_tc_set_md_var(tc, "timeout", "65"); 191*57718be8SEnji Cooper } 192*57718be8SEnji Cooper 193*57718be8SEnji Cooper ATF_TC_BODY(nanosleep, tc) 194*57718be8SEnji Cooper { 195*57718be8SEnji Cooper 196*57718be8SEnji Cooper sleeptest(do_nanosleep, true, false); 197*57718be8SEnji Cooper } 198*57718be8SEnji Cooper 199*57718be8SEnji Cooper ATF_TC(select); 200*57718be8SEnji Cooper ATF_TC_HEAD(select, tc) 201*57718be8SEnji Cooper { 202*57718be8SEnji Cooper 203*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test select(2) timing"); 204*57718be8SEnji Cooper atf_tc_set_md_var(tc, "timeout", "65"); 205*57718be8SEnji Cooper } 206*57718be8SEnji Cooper 207*57718be8SEnji Cooper ATF_TC_BODY(select, tc) 208*57718be8SEnji Cooper { 209*57718be8SEnji Cooper 210*57718be8SEnji Cooper sleeptest(do_select, true, true); 211*57718be8SEnji Cooper } 212*57718be8SEnji Cooper 213*57718be8SEnji Cooper ATF_TC(poll); 214*57718be8SEnji Cooper ATF_TC_HEAD(poll, tc) 215*57718be8SEnji Cooper { 216*57718be8SEnji Cooper 217*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test poll(2) timing"); 218*57718be8SEnji Cooper atf_tc_set_md_var(tc, "timeout", "65"); 219*57718be8SEnji Cooper } 220*57718be8SEnji Cooper 221*57718be8SEnji Cooper ATF_TC_BODY(poll, tc) 222*57718be8SEnji Cooper { 223*57718be8SEnji Cooper 224*57718be8SEnji Cooper sleeptest(do_poll, true, true); 225*57718be8SEnji Cooper } 226*57718be8SEnji Cooper 227*57718be8SEnji Cooper ATF_TC(sleep); 228*57718be8SEnji Cooper ATF_TC_HEAD(sleep, tc) 229*57718be8SEnji Cooper { 230*57718be8SEnji Cooper 231*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test sleep(3) timing"); 232*57718be8SEnji Cooper atf_tc_set_md_var(tc, "timeout", "65"); 233*57718be8SEnji Cooper } 234*57718be8SEnji Cooper 235*57718be8SEnji Cooper ATF_TC_BODY(sleep, tc) 236*57718be8SEnji Cooper { 237*57718be8SEnji Cooper 238*57718be8SEnji Cooper sleeptest(do_sleep, false, false); 239*57718be8SEnji Cooper } 240*57718be8SEnji Cooper 241*57718be8SEnji Cooper ATF_TC(kevent); 242*57718be8SEnji Cooper ATF_TC_HEAD(kevent, tc) 243*57718be8SEnji Cooper { 244*57718be8SEnji Cooper 245*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test kevent(2) timing"); 246*57718be8SEnji Cooper atf_tc_set_md_var(tc, "timeout", "65"); 247*57718be8SEnji Cooper } 248*57718be8SEnji Cooper 249*57718be8SEnji Cooper ATF_TC_BODY(kevent, tc) 250*57718be8SEnji Cooper { 251*57718be8SEnji Cooper 252*57718be8SEnji Cooper sleeptest(do_kevent, true, true); 253*57718be8SEnji Cooper } 254*57718be8SEnji Cooper 255*57718be8SEnji Cooper int 256*57718be8SEnji Cooper sleeptest(int (*test)(struct timespec *, struct timespec *), 257*57718be8SEnji Cooper bool subsec, bool sim_remain) 258*57718be8SEnji Cooper { 259*57718be8SEnji Cooper struct timespec tsa, tsb, tslp, tremain; 260*57718be8SEnji Cooper int64_t delta1, delta2, delta3, round; 261*57718be8SEnji Cooper 262*57718be8SEnji Cooper sig = 0; 263*57718be8SEnji Cooper signal(SIGALRM, sigalrm); 264*57718be8SEnji Cooper 265*57718be8SEnji Cooper if (subsec) { 266*57718be8SEnji Cooper round = 1; 267*57718be8SEnji Cooper delta3 = FUZZ; 268*57718be8SEnji Cooper } else { 269*57718be8SEnji Cooper round = 1000000000; 270*57718be8SEnji Cooper delta3 = round; 271*57718be8SEnji Cooper } 272*57718be8SEnji Cooper 273*57718be8SEnji Cooper tslp.tv_sec = delta3 / 1000000000; 274*57718be8SEnji Cooper tslp.tv_nsec = delta3 % 1000000000; 275*57718be8SEnji Cooper 276*57718be8SEnji Cooper while (tslp.tv_sec <= MAXSLEEP) { 277*57718be8SEnji Cooper /* 278*57718be8SEnji Cooper * disturb sleep by signal on purpose 279*57718be8SEnji Cooper */ 280*57718be8SEnji Cooper if (tslp.tv_sec > ALARM && sig == 0) 281*57718be8SEnji Cooper alarm(ALARM); 282*57718be8SEnji Cooper 283*57718be8SEnji Cooper clock_gettime(CLOCK_REALTIME, &tsa); 284*57718be8SEnji Cooper (*test)(&tslp, &tremain); 285*57718be8SEnji Cooper clock_gettime(CLOCK_REALTIME, &tsb); 286*57718be8SEnji Cooper 287*57718be8SEnji Cooper if (sim_remain) { 288*57718be8SEnji Cooper timespecsub(&tsb, &tsa, &tremain); 289*57718be8SEnji Cooper timespecsub(&tslp, &tremain, &tremain); 290*57718be8SEnji Cooper } 291*57718be8SEnji Cooper 292*57718be8SEnji Cooper delta1 = (int64_t)tsb.tv_sec - (int64_t)tsa.tv_sec; 293*57718be8SEnji Cooper delta1 *= BILLION; 294*57718be8SEnji Cooper delta1 += (int64_t)tsb.tv_nsec - (int64_t)tsa.tv_nsec; 295*57718be8SEnji Cooper 296*57718be8SEnji Cooper delta2 = (int64_t)tremain.tv_sec * BILLION; 297*57718be8SEnji Cooper delta2 += (int64_t)tremain.tv_nsec; 298*57718be8SEnji Cooper 299*57718be8SEnji Cooper delta3 = (int64_t)tslp.tv_sec * BILLION; 300*57718be8SEnji Cooper delta3 += (int64_t)tslp.tv_nsec - delta1 - delta2; 301*57718be8SEnji Cooper 302*57718be8SEnji Cooper delta3 /= round; 303*57718be8SEnji Cooper delta3 *= round; 304*57718be8SEnji Cooper 305*57718be8SEnji Cooper if (delta3 > FUZZ || delta3 < -FUZZ) { 306*57718be8SEnji Cooper if (!sim_remain) 307*57718be8SEnji Cooper atf_tc_expect_fail("Long reschedule latency " 308*57718be8SEnji Cooper "due to PR kern/43997"); 309*57718be8SEnji Cooper 310*57718be8SEnji Cooper atf_tc_fail("Reschedule latency %"PRId64" exceeds " 311*57718be8SEnji Cooper "allowable fuzz %lld", delta3, FUZZ); 312*57718be8SEnji Cooper } 313*57718be8SEnji Cooper delta3 = (int64_t)tslp.tv_sec * 2 * BILLION; 314*57718be8SEnji Cooper delta3 += (int64_t)tslp.tv_nsec * 2; 315*57718be8SEnji Cooper 316*57718be8SEnji Cooper delta3 /= round; 317*57718be8SEnji Cooper delta3 *= round; 318*57718be8SEnji Cooper if (delta3 < FUZZ) 319*57718be8SEnji Cooper break; 320*57718be8SEnji Cooper tslp.tv_sec = delta3 / BILLION; 321*57718be8SEnji Cooper tslp.tv_nsec = delta3 % BILLION; 322*57718be8SEnji Cooper } 323*57718be8SEnji Cooper ATF_REQUIRE_MSG(sig == 1, "Alarm did not fire!"); 324*57718be8SEnji Cooper 325*57718be8SEnji Cooper atf_tc_pass(); 326*57718be8SEnji Cooper } 327*57718be8SEnji Cooper 328*57718be8SEnji Cooper ATF_TP_ADD_TCS(tp) 329*57718be8SEnji Cooper { 330*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, nanosleep); 331*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, select); 332*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, poll); 333*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, sleep); 334*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, kevent); 335*57718be8SEnji Cooper 336*57718be8SEnji Cooper return atf_no_error(); 337*57718be8SEnji Cooper } 338