1*640235e2SEnji Cooper /* $NetBSD: t_sleep.c,v 1.9 2016/08/11 21:34:11 kre Exp $ */ 257718be8SEnji Cooper 357718be8SEnji Cooper /*- 457718be8SEnji Cooper * Copyright (c) 2006 Frank Kardel 557718be8SEnji Cooper * All rights reserved. 657718be8SEnji Cooper * 757718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without 857718be8SEnji Cooper * modification, are permitted provided that the following conditions 957718be8SEnji Cooper * are met: 1057718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright 1157718be8SEnji Cooper * notice, this list of conditions and the following disclaimer. 1257718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 1357718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in the 1457718be8SEnji Cooper * documentation and/or other materials provided with the distribution. 1557718be8SEnji Cooper * 1657718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 1757718be8SEnji Cooper * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 1857718be8SEnji Cooper * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 1957718be8SEnji Cooper * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 2057718be8SEnji Cooper * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2157718be8SEnji Cooper * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2257718be8SEnji Cooper * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2357718be8SEnji Cooper * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2457718be8SEnji Cooper * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2557718be8SEnji Cooper * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2657718be8SEnji Cooper * POSSIBILITY OF SUCH DAMAGE. 2757718be8SEnji Cooper */ 2857718be8SEnji Cooper 2957718be8SEnji Cooper #include <atf-c.h> 3057718be8SEnji Cooper #include <errno.h> 3157718be8SEnji Cooper #include <poll.h> 3257718be8SEnji Cooper #include <stdio.h> 3357718be8SEnji Cooper #include <stdlib.h> 3457718be8SEnji Cooper #include <string.h> 3557718be8SEnji Cooper #include <time.h> 3657718be8SEnji Cooper #include <unistd.h> 3757718be8SEnji Cooper 3857718be8SEnji Cooper #include <sys/cdefs.h> 3957718be8SEnji Cooper #include <sys/event.h> 4057718be8SEnji Cooper #include <sys/signal.h> 4157718be8SEnji Cooper 4257718be8SEnji Cooper #include "isqemu.h" 4357718be8SEnji Cooper 4457718be8SEnji Cooper #define BILLION 1000000000LL /* nano-seconds per second */ 4557718be8SEnji Cooper #define MILLION 1000000LL /* nano-seconds per milli-second */ 4657718be8SEnji Cooper 4757718be8SEnji Cooper #define ALARM 6 /* SIGALRM after this many seconds */ 4857718be8SEnji Cooper #define MAXSLEEP 22 /* Maximum delay in seconds */ 4957718be8SEnji Cooper #define KEVNT_TIMEOUT 10300 /* measured in milli-seconds */ 5057718be8SEnji Cooper #define FUZZ (40 * MILLION) /* scheduling fuzz accepted - 40 ms */ 5157718be8SEnji Cooper 526ffeed45SEnji Cooper #ifdef __FreeBSD__ 536ffeed45SEnji Cooper #include <sys/time.h> 546ffeed45SEnji Cooper #include <inttypes.h> 556ffeed45SEnji Cooper #endif 566ffeed45SEnji Cooper 5757718be8SEnji Cooper /* 5857718be8SEnji Cooper * Timer notes 5957718be8SEnji Cooper * 6057718be8SEnji Cooper * Most tests use FUZZ as their initial delay value, but 'sleep' 6157718be8SEnji Cooper * starts at 1sec (since it cannot handle sub-second intervals). 6257718be8SEnji Cooper * Subsequent passes double the previous interval, up to MAXSLEEP. 6357718be8SEnji Cooper * 6457718be8SEnji Cooper * The current values result in 5 passes for the 'sleep' test (at 1, 6557718be8SEnji Cooper * 2, 4, 8, and 16 seconds) and 10 passes for the other tests (at 6657718be8SEnji Cooper * 0.04, 0.08, 0.16, 0.32, 0.64, 1.28, 2.56, 5.12, 10.24, and 20.48 6757718be8SEnji Cooper * seconds). 6857718be8SEnji Cooper * 6957718be8SEnji Cooper * The ALARM is only set if the current pass's delay is longer, and 7057718be8SEnji Cooper * only if the ALARM has not already been triggered. 7157718be8SEnji Cooper * 7257718be8SEnji Cooper * The 'kevent' test needs the ALARM to be set on a different pass 7357718be8SEnji Cooper * from when the KEVNT_TIMEOUT fires. So set ALARM to fire on the 7457718be8SEnji Cooper * penultimate pass, and the KEVNT_TIMEOUT on the final pass. We 7557718be8SEnji Cooper * set KEVNT_TIMEOUT just barely long enough to put it into the 7657718be8SEnji Cooper * last test pass, and set MAXSLEEP a couple seconds longer than 7757718be8SEnji Cooper * necessary, in order to avoid a QEMU bug which nearly doubles 7857718be8SEnji Cooper * some timers. 7957718be8SEnji Cooper */ 8057718be8SEnji Cooper 8157718be8SEnji Cooper static volatile int sig; 8257718be8SEnji Cooper 8357718be8SEnji Cooper int sleeptest(int (*)(struct timespec *, struct timespec *), bool, bool); 8457718be8SEnji Cooper int do_nanosleep(struct timespec *, struct timespec *); 8557718be8SEnji Cooper int do_select(struct timespec *, struct timespec *); 866ffeed45SEnji Cooper #ifdef __NetBSD__ 8757718be8SEnji Cooper int do_poll(struct timespec *, struct timespec *); 886ffeed45SEnji Cooper #endif 8957718be8SEnji Cooper int do_sleep(struct timespec *, struct timespec *); 9057718be8SEnji Cooper int do_kevent(struct timespec *, struct timespec *); 9157718be8SEnji Cooper void sigalrm(int); 9257718be8SEnji Cooper 9357718be8SEnji Cooper void 9457718be8SEnji Cooper sigalrm(int s) 9557718be8SEnji Cooper { 9657718be8SEnji Cooper 9757718be8SEnji Cooper sig++; 9857718be8SEnji Cooper } 9957718be8SEnji Cooper 10057718be8SEnji Cooper int 10157718be8SEnji Cooper do_nanosleep(struct timespec *delay, struct timespec *remain) 10257718be8SEnji Cooper { 10357718be8SEnji Cooper int ret; 10457718be8SEnji Cooper 10557718be8SEnji Cooper if (nanosleep(delay, remain) == -1) 10657718be8SEnji Cooper ret = (errno == EINTR ? 0 : errno); 10757718be8SEnji Cooper else 10857718be8SEnji Cooper ret = 0; 10957718be8SEnji Cooper return ret; 11057718be8SEnji Cooper } 11157718be8SEnji Cooper 11257718be8SEnji Cooper int 11357718be8SEnji Cooper do_select(struct timespec *delay, struct timespec *remain) 11457718be8SEnji Cooper { 11557718be8SEnji Cooper int ret; 11657718be8SEnji Cooper struct timeval tv; 11757718be8SEnji Cooper 11857718be8SEnji Cooper TIMESPEC_TO_TIMEVAL(&tv, delay); 11957718be8SEnji Cooper if (select(0, NULL, NULL, NULL, &tv) == -1) 12057718be8SEnji Cooper ret = (errno == EINTR ? 0 : errno); 12157718be8SEnji Cooper else 12257718be8SEnji Cooper ret = 0; 12357718be8SEnji Cooper return ret; 12457718be8SEnji Cooper } 12557718be8SEnji Cooper 1266ffeed45SEnji Cooper #ifdef __NetBSD__ 12757718be8SEnji Cooper int 12857718be8SEnji Cooper do_poll(struct timespec *delay, struct timespec *remain) 12957718be8SEnji Cooper { 13057718be8SEnji Cooper int ret; 13157718be8SEnji Cooper struct timeval tv; 13257718be8SEnji Cooper 13357718be8SEnji Cooper TIMESPEC_TO_TIMEVAL(&tv, delay); 13457718be8SEnji Cooper if (pollts(NULL, 0, delay, NULL) == -1) 13557718be8SEnji Cooper ret = (errno == EINTR ? 0 : errno); 13657718be8SEnji Cooper else 13757718be8SEnji Cooper ret = 0; 13857718be8SEnji Cooper return ret; 13957718be8SEnji Cooper } 1406ffeed45SEnji Cooper #endif 14157718be8SEnji Cooper 14257718be8SEnji Cooper int 14357718be8SEnji Cooper do_sleep(struct timespec *delay, struct timespec *remain) 14457718be8SEnji Cooper { 14557718be8SEnji Cooper struct timeval tv; 14657718be8SEnji Cooper 14757718be8SEnji Cooper TIMESPEC_TO_TIMEVAL(&tv, delay); 14857718be8SEnji Cooper remain->tv_sec = sleep(delay->tv_sec); 14957718be8SEnji Cooper remain->tv_nsec = 0; 15057718be8SEnji Cooper 15157718be8SEnji Cooper return 0; 15257718be8SEnji Cooper } 15357718be8SEnji Cooper 15457718be8SEnji Cooper int 15557718be8SEnji Cooper do_kevent(struct timespec *delay, struct timespec *remain) 15657718be8SEnji Cooper { 15757718be8SEnji Cooper struct kevent ktimer; 15857718be8SEnji Cooper struct kevent kresult; 15957718be8SEnji Cooper int rtc, kq, kerrno; 16057718be8SEnji Cooper int tmo; 16157718be8SEnji Cooper 16257718be8SEnji Cooper ATF_REQUIRE_MSG((kq = kqueue()) != -1, "kqueue: %s", strerror(errno)); 16357718be8SEnji Cooper 16457718be8SEnji Cooper tmo = KEVNT_TIMEOUT; 16557718be8SEnji Cooper 16657718be8SEnji Cooper /* 16757718be8SEnji Cooper * If we expect the KEVNT_TIMEOUT to fire, and we're running 16857718be8SEnji Cooper * under QEMU, make sure the delay is long enough to account 16957718be8SEnji Cooper * for the effects of PR kern/43997 ! 17057718be8SEnji Cooper */ 17157718be8SEnji Cooper if (isQEMU() && 17257718be8SEnji Cooper tmo/1000 < delay->tv_sec && tmo/500 > delay->tv_sec) 17357718be8SEnji Cooper delay->tv_sec = MAXSLEEP; 17457718be8SEnji Cooper 17557718be8SEnji Cooper EV_SET(&ktimer, 1, EVFILT_TIMER, EV_ADD, 0, tmo, 0); 17657718be8SEnji Cooper 17757718be8SEnji Cooper rtc = kevent(kq, &ktimer, 1, &kresult, 1, delay); 17857718be8SEnji Cooper kerrno = errno; 17957718be8SEnji Cooper 18057718be8SEnji Cooper (void)close(kq); 18157718be8SEnji Cooper 18257718be8SEnji Cooper if (rtc == -1) { 183*640235e2SEnji Cooper ATF_REQUIRE_MSG(kerrno == EINTR, "kevent: %s", 184*640235e2SEnji Cooper strerror(kerrno)); 18557718be8SEnji Cooper return 0; 18657718be8SEnji Cooper } 18757718be8SEnji Cooper 18857718be8SEnji Cooper if (delay->tv_sec * BILLION + delay->tv_nsec > tmo * MILLION) 18957718be8SEnji Cooper ATF_REQUIRE_MSG(rtc > 0, 19057718be8SEnji Cooper "kevent: KEVNT_TIMEOUT did not cause EVFILT_TIMER event"); 19157718be8SEnji Cooper 19257718be8SEnji Cooper return 0; 19357718be8SEnji Cooper } 19457718be8SEnji Cooper 19557718be8SEnji Cooper ATF_TC(nanosleep); 19657718be8SEnji Cooper ATF_TC_HEAD(nanosleep, tc) 19757718be8SEnji Cooper { 19857718be8SEnji Cooper 19957718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test nanosleep(2) timing"); 20057718be8SEnji Cooper atf_tc_set_md_var(tc, "timeout", "65"); 20157718be8SEnji Cooper } 20257718be8SEnji Cooper 20357718be8SEnji Cooper ATF_TC_BODY(nanosleep, tc) 20457718be8SEnji Cooper { 20557718be8SEnji Cooper 20657718be8SEnji Cooper sleeptest(do_nanosleep, true, false); 20757718be8SEnji Cooper } 20857718be8SEnji Cooper 20957718be8SEnji Cooper ATF_TC(select); 21057718be8SEnji Cooper ATF_TC_HEAD(select, tc) 21157718be8SEnji Cooper { 21257718be8SEnji Cooper 21357718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test select(2) timing"); 21457718be8SEnji Cooper atf_tc_set_md_var(tc, "timeout", "65"); 21557718be8SEnji Cooper } 21657718be8SEnji Cooper 21757718be8SEnji Cooper ATF_TC_BODY(select, tc) 21857718be8SEnji Cooper { 21957718be8SEnji Cooper 22057718be8SEnji Cooper sleeptest(do_select, true, true); 22157718be8SEnji Cooper } 22257718be8SEnji Cooper 2236ffeed45SEnji Cooper #ifdef __NetBSD__ 22457718be8SEnji Cooper ATF_TC(poll); 22557718be8SEnji Cooper ATF_TC_HEAD(poll, tc) 22657718be8SEnji Cooper { 22757718be8SEnji Cooper 22857718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test poll(2) timing"); 22957718be8SEnji Cooper atf_tc_set_md_var(tc, "timeout", "65"); 23057718be8SEnji Cooper } 23157718be8SEnji Cooper 23257718be8SEnji Cooper ATF_TC_BODY(poll, tc) 23357718be8SEnji Cooper { 23457718be8SEnji Cooper 23557718be8SEnji Cooper sleeptest(do_poll, true, true); 23657718be8SEnji Cooper } 2376ffeed45SEnji Cooper #endif 23857718be8SEnji Cooper 23957718be8SEnji Cooper ATF_TC(sleep); 24057718be8SEnji Cooper ATF_TC_HEAD(sleep, tc) 24157718be8SEnji Cooper { 24257718be8SEnji Cooper 24357718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test sleep(3) timing"); 24457718be8SEnji Cooper atf_tc_set_md_var(tc, "timeout", "65"); 24557718be8SEnji Cooper } 24657718be8SEnji Cooper 24757718be8SEnji Cooper ATF_TC_BODY(sleep, tc) 24857718be8SEnji Cooper { 24957718be8SEnji Cooper 25057718be8SEnji Cooper sleeptest(do_sleep, false, false); 25157718be8SEnji Cooper } 25257718be8SEnji Cooper 25357718be8SEnji Cooper ATF_TC(kevent); 25457718be8SEnji Cooper ATF_TC_HEAD(kevent, tc) 25557718be8SEnji Cooper { 25657718be8SEnji Cooper 25757718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test kevent(2) timing"); 25857718be8SEnji Cooper atf_tc_set_md_var(tc, "timeout", "65"); 25957718be8SEnji Cooper } 26057718be8SEnji Cooper 26157718be8SEnji Cooper ATF_TC_BODY(kevent, tc) 26257718be8SEnji Cooper { 26357718be8SEnji Cooper 26457718be8SEnji Cooper sleeptest(do_kevent, true, true); 26557718be8SEnji Cooper } 26657718be8SEnji Cooper 26757718be8SEnji Cooper int 26857718be8SEnji Cooper sleeptest(int (*test)(struct timespec *, struct timespec *), 26957718be8SEnji Cooper bool subsec, bool sim_remain) 27057718be8SEnji Cooper { 27157718be8SEnji Cooper struct timespec tsa, tsb, tslp, tremain; 27257718be8SEnji Cooper int64_t delta1, delta2, delta3, round; 27357718be8SEnji Cooper 27457718be8SEnji Cooper sig = 0; 27557718be8SEnji Cooper signal(SIGALRM, sigalrm); 27657718be8SEnji Cooper 27757718be8SEnji Cooper if (subsec) { 27857718be8SEnji Cooper round = 1; 27957718be8SEnji Cooper delta3 = FUZZ; 28057718be8SEnji Cooper } else { 28157718be8SEnji Cooper round = 1000000000; 28257718be8SEnji Cooper delta3 = round; 28357718be8SEnji Cooper } 28457718be8SEnji Cooper 28557718be8SEnji Cooper tslp.tv_sec = delta3 / 1000000000; 28657718be8SEnji Cooper tslp.tv_nsec = delta3 % 1000000000; 28757718be8SEnji Cooper 28857718be8SEnji Cooper while (tslp.tv_sec <= MAXSLEEP) { 28957718be8SEnji Cooper /* 29057718be8SEnji Cooper * disturb sleep by signal on purpose 29157718be8SEnji Cooper */ 29257718be8SEnji Cooper if (tslp.tv_sec > ALARM && sig == 0) 29357718be8SEnji Cooper alarm(ALARM); 29457718be8SEnji Cooper 29557718be8SEnji Cooper clock_gettime(CLOCK_REALTIME, &tsa); 29657718be8SEnji Cooper (*test)(&tslp, &tremain); 29757718be8SEnji Cooper clock_gettime(CLOCK_REALTIME, &tsb); 29857718be8SEnji Cooper 29957718be8SEnji Cooper if (sim_remain) { 30057718be8SEnji Cooper timespecsub(&tsb, &tsa, &tremain); 30157718be8SEnji Cooper timespecsub(&tslp, &tremain, &tremain); 30257718be8SEnji Cooper } 30357718be8SEnji Cooper 30457718be8SEnji Cooper delta1 = (int64_t)tsb.tv_sec - (int64_t)tsa.tv_sec; 30557718be8SEnji Cooper delta1 *= BILLION; 30657718be8SEnji Cooper delta1 += (int64_t)tsb.tv_nsec - (int64_t)tsa.tv_nsec; 30757718be8SEnji Cooper 30857718be8SEnji Cooper delta2 = (int64_t)tremain.tv_sec * BILLION; 30957718be8SEnji Cooper delta2 += (int64_t)tremain.tv_nsec; 31057718be8SEnji Cooper 31157718be8SEnji Cooper delta3 = (int64_t)tslp.tv_sec * BILLION; 31257718be8SEnji Cooper delta3 += (int64_t)tslp.tv_nsec - delta1 - delta2; 31357718be8SEnji Cooper 31457718be8SEnji Cooper delta3 /= round; 31557718be8SEnji Cooper delta3 *= round; 31657718be8SEnji Cooper 31757718be8SEnji Cooper if (delta3 > FUZZ || delta3 < -FUZZ) { 31857718be8SEnji Cooper if (!sim_remain) 31957718be8SEnji Cooper atf_tc_expect_fail("Long reschedule latency " 32057718be8SEnji Cooper "due to PR kern/43997"); 32157718be8SEnji Cooper 32257718be8SEnji Cooper atf_tc_fail("Reschedule latency %"PRId64" exceeds " 32357718be8SEnji Cooper "allowable fuzz %lld", delta3, FUZZ); 32457718be8SEnji Cooper } 32557718be8SEnji Cooper delta3 = (int64_t)tslp.tv_sec * 2 * BILLION; 32657718be8SEnji Cooper delta3 += (int64_t)tslp.tv_nsec * 2; 32757718be8SEnji Cooper 32857718be8SEnji Cooper delta3 /= round; 32957718be8SEnji Cooper delta3 *= round; 33057718be8SEnji Cooper if (delta3 < FUZZ) 33157718be8SEnji Cooper break; 33257718be8SEnji Cooper tslp.tv_sec = delta3 / BILLION; 33357718be8SEnji Cooper tslp.tv_nsec = delta3 % BILLION; 33457718be8SEnji Cooper } 33557718be8SEnji Cooper ATF_REQUIRE_MSG(sig == 1, "Alarm did not fire!"); 33657718be8SEnji Cooper 33757718be8SEnji Cooper atf_tc_pass(); 33857718be8SEnji Cooper } 33957718be8SEnji Cooper 34057718be8SEnji Cooper ATF_TP_ADD_TCS(tp) 34157718be8SEnji Cooper { 34257718be8SEnji Cooper ATF_TP_ADD_TC(tp, nanosleep); 34357718be8SEnji Cooper ATF_TP_ADD_TC(tp, select); 3446ffeed45SEnji Cooper #ifdef __NetBSD__ 34557718be8SEnji Cooper ATF_TP_ADD_TC(tp, poll); 3466ffeed45SEnji Cooper #endif 34757718be8SEnji Cooper ATF_TP_ADD_TC(tp, sleep); 34857718be8SEnji Cooper ATF_TP_ADD_TC(tp, kevent); 34957718be8SEnji Cooper 35057718be8SEnji Cooper return atf_no_error(); 35157718be8SEnji Cooper } 352