t_sleep.c revision 313535
139215Sgibbs/* $NetBSD: t_sleep.c,v 1.11 2017/01/10 15:43:59 maya Exp $ */ 2107178Snjl 339215Sgibbs/*- 4107178Snjl * Copyright (c) 2006 Frank Kardel 539215Sgibbs * All rights reserved. 639215Sgibbs * 739215Sgibbs * Redistribution and use in source and binary forms, with or without 839215Sgibbs * modification, are permitted provided that the following conditions 939215Sgibbs * are met: 1039215Sgibbs * 1. Redistributions of source code must retain the above copyright 1139215Sgibbs * notice, this list of conditions and the following disclaimer. 1239215Sgibbs * 2. Redistributions in binary form must reproduce the above copyright 1339215Sgibbs * notice, this list of conditions and the following disclaimer in the 1439215Sgibbs * documentation and/or other materials provided with the distribution. 1539215Sgibbs * 1639215Sgibbs * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 1739215Sgibbs * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 1839215Sgibbs * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 1939215Sgibbs * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 2039215Sgibbs * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2139215Sgibbs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2239215Sgibbs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2339215Sgibbs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2439215Sgibbs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2539215Sgibbs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2639215Sgibbs * POSSIBILITY OF SUCH DAMAGE. 2739215Sgibbs */ 2850476Speter 2939215Sgibbs#ifdef __FreeBSD__ 3039215Sgibbs#include <sys/types.h> 3139215Sgibbs#endif 32121184Ssimokawa#include <sys/cdefs.h> 3344498Sgibbs#include <sys/event.h> 34107178Snjl#include <sys/signal.h> 3539215Sgibbs#include <sys/time.h> /* for TIMESPEC_TO_TIMEVAL on FreeBSD */ 3644498Sgibbs 3739215Sgibbs#include <atf-c.h> 3839215Sgibbs#include <errno.h> 3939215Sgibbs#include <inttypes.h> 40107178Snjl#include <poll.h> 4139215Sgibbs#include <stdio.h> 4239215Sgibbs#include <stdlib.h> 43107178Snjl#include <string.h> 44109161Snjl#include <time.h> 45107178Snjl#include <unistd.h> 46107178Snjl 47107178Snjl#include "isqemu.h" 48107178Snjl 49120428Ssimokawa#define BILLION 1000000000LL /* nano-seconds per second */ 50107178Snjl#define MILLION 1000000LL /* nano-seconds per milli-second */ 5139215Sgibbs 52107178Snjl#define ALARM 6 /* SIGALRM after this many seconds */ 5339215Sgibbs#define MAXSLEEP 22 /* Maximum delay in seconds */ 54107178Snjl#define KEVNT_TIMEOUT 10300 /* measured in milli-seconds */ 5539215Sgibbs#define FUZZ (40 * MILLION) /* scheduling fuzz accepted - 40 ms */ 56107178Snjl 57107178Snjl/* 58107178Snjl * Timer notes 59162704Smjacob * 60107178Snjl * Most tests use FUZZ as their initial delay value, but 'sleep' 61107178Snjl * starts at 1sec (since it cannot handle sub-second intervals). 62107178Snjl * Subsequent passes double the previous interval, up to MAXSLEEP. 63107178Snjl * 64107178Snjl * The current values result in 5 passes for the 'sleep' test (at 1, 65162704Smjacob * 2, 4, 8, and 16 seconds) and 10 passes for the other tests (at 66121184Ssimokawa * 0.04, 0.08, 0.16, 0.32, 0.64, 1.28, 2.56, 5.12, 10.24, and 20.48 67121184Ssimokawa * seconds). 68107178Snjl * 69107178Snjl * The ALARM is only set if the current pass's delay is longer, and 70107178Snjl * only if the ALARM has not already been triggered. 71107178Snjl * 72107178Snjl * The 'kevent' test needs the ALARM to be set on a different pass 73107178Snjl * from when the KEVNT_TIMEOUT fires. So set ALARM to fire on the 74107178Snjl * penultimate pass, and the KEVNT_TIMEOUT on the final pass. We 75107178Snjl * set KEVNT_TIMEOUT just barely long enough to put it into the 76107178Snjl * last test pass, and set MAXSLEEP a couple seconds longer than 77107178Snjl * necessary, in order to avoid a QEMU bug which nearly doubles 7844498Sgibbs * some timers. 7944498Sgibbs */ 8044498Sgibbs 8144498Sgibbsstatic volatile int sig; 8239215Sgibbs 83107178Snjlint sleeptest(int (*)(struct timespec *, struct timespec *), bool, bool); 84107178Snjlint do_nanosleep(struct timespec *, struct timespec *); 85107178Snjlint do_select(struct timespec *, struct timespec *); 86107178Snjl#ifdef __NetBSD__ 87107178Snjlint do_poll(struct timespec *, struct timespec *); 88107178Snjl#endif 89107178Snjlint do_sleep(struct timespec *, struct timespec *); 90162704Smjacobint do_kevent(struct timespec *, struct timespec *); 91237601Skenvoid sigalrm(int); 92107178Snjl 93107178Snjlvoid 94107178Snjlsigalrm(int s) 95107178Snjl{ 96107178Snjl 97107178Snjl sig++; 98107178Snjl} 9939215Sgibbs 10039215Sgibbsint 10139215Sgibbsdo_nanosleep(struct timespec *delay, struct timespec *remain) 10239215Sgibbs{ 103228481Sed int ret; 104228481Sed 105107178Snjl if (nanosleep(delay, remain) == -1) 106107178Snjl ret = (errno == EINTR ? 0 : errno); 10739215Sgibbs else 108107178Snjl ret = 0; 109107178Snjl return ret; 110107178Snjl} 111107178Snjl 112107178Snjlint 113107178Snjldo_select(struct timespec *delay, struct timespec *remain) 114107178Snjl{ 115107178Snjl int ret; 116107178Snjl struct timeval tv; 117107178Snjl 118107178Snjl TIMESPEC_TO_TIMEVAL(&tv, delay); 119107178Snjl if (select(0, NULL, NULL, NULL, &tv) == -1) 120107178Snjl ret = (errno == EINTR ? 0 : errno); 121162704Smjacob else 12239215Sgibbs ret = 0; 123107178Snjl return ret; 124107178Snjl} 12539215Sgibbs 126107178Snjl#ifdef __NetBSD__ 127107178Snjlint 12839215Sgibbsdo_poll(struct timespec *delay, struct timespec *remain) 129107178Snjl{ 130107178Snjl int ret; 13144498Sgibbs struct timeval tv; 132107178Snjl 133107178Snjl TIMESPEC_TO_TIMEVAL(&tv, delay); 13444498Sgibbs if (pollts(NULL, 0, delay, NULL) == -1) 135107178Snjl ret = (errno == EINTR ? 0 : errno); 136107178Snjl else 137107178Snjl ret = 0; 138107178Snjl return ret; 13944498Sgibbs} 140107178Snjl#endif 141107178Snjl 142107178Snjlint 143107178Snjldo_sleep(struct timespec *delay, struct timespec *remain) 14463185Smjacob{ 145107178Snjl struct timeval tv; 146121184Ssimokawa 147121184Ssimokawa TIMESPEC_TO_TIMEVAL(&tv, delay); 148121184Ssimokawa remain->tv_sec = sleep(delay->tv_sec); 149121184Ssimokawa remain->tv_nsec = 0; 150121184Ssimokawa 151121184Ssimokawa return 0; 152121184Ssimokawa} 153121184Ssimokawa 154121184Ssimokawaint 155121184Ssimokawado_kevent(struct timespec *delay, struct timespec *remain) 156121184Ssimokawa{ 157121184Ssimokawa struct kevent ktimer; 158121184Ssimokawa struct kevent kresult; 159121184Ssimokawa int rtc, kq, kerrno; 160121184Ssimokawa int tmo; 161121184Ssimokawa 162121184Ssimokawa ATF_REQUIRE_MSG((kq = kqueue()) != -1, "kqueue: %s", strerror(errno)); 163121184Ssimokawa 164121184Ssimokawa tmo = KEVNT_TIMEOUT; 165121184Ssimokawa 166121184Ssimokawa /* 167121184Ssimokawa * If we expect the KEVNT_TIMEOUT to fire, and we're running 168121184Ssimokawa * under QEMU, make sure the delay is long enough to account 169121184Ssimokawa * for the effects of PR kern/43997 ! 170121184Ssimokawa */ 171121184Ssimokawa if (isQEMU() && 172121184Ssimokawa tmo/1000 < delay->tv_sec && tmo/500 > delay->tv_sec) 173107178Snjl delay->tv_sec = MAXSLEEP; 174121184Ssimokawa 175107178Snjl EV_SET(&ktimer, 1, EVFILT_TIMER, EV_ADD, 0, tmo, 0); 176107178Snjl 177107178Snjl rtc = kevent(kq, &ktimer, 1, &kresult, 1, delay); 178121184Ssimokawa kerrno = errno; 179107178Snjl 180107178Snjl (void)close(kq); 181107178Snjl 182107178Snjl if (rtc == -1) { 183107178Snjl ATF_REQUIRE_MSG(kerrno == EINTR, "kevent: %s", 184107178Snjl strerror(kerrno)); 185107178Snjl return 0; 186107178Snjl } 187107178Snjl 188107178Snjl if (delay->tv_sec * BILLION + delay->tv_nsec > tmo * MILLION) 189107178Snjl ATF_REQUIRE_MSG(rtc > 0, 190107178Snjl "kevent: KEVNT_TIMEOUT did not cause EVFILT_TIMER event"); 191107178Snjl 192107178Snjl return 0; 193107178Snjl} 194107178Snjl 195107178SnjlATF_TC(nanosleep); 196107178SnjlATF_TC_HEAD(nanosleep, tc) 197162704Smjacob{ 198162704Smjacob 199162704Smjacob atf_tc_set_md_var(tc, "descr", "Test nanosleep(2) timing"); 20039215Sgibbs atf_tc_set_md_var(tc, "timeout", "65"); 20139215Sgibbs} 20239215Sgibbs 20339215SgibbsATF_TC_BODY(nanosleep, tc) 20439215Sgibbs{ 20539215Sgibbs 20639215Sgibbs sleeptest(do_nanosleep, true, false); 207107178Snjl} 208107178Snjl 20939215SgibbsATF_TC(select); 21039215SgibbsATF_TC_HEAD(select, tc) 211107178Snjl{ 212107178Snjl 213107178Snjl atf_tc_set_md_var(tc, "descr", "Test select(2) timing"); 214107178Snjl atf_tc_set_md_var(tc, "timeout", "65"); 215107178Snjl} 216107178Snjl 217107178SnjlATF_TC_BODY(select, tc) 218107178Snjl{ 21944498Sgibbs 22044498Sgibbs sleeptest(do_select, true, true); 22144498Sgibbs} 222107178Snjl 223107178Snjl#ifdef __NetBSD__ 224107178SnjlATF_TC(poll); 22544498SgibbsATF_TC_HEAD(poll, tc) 226107178Snjl{ 227107178Snjl 228107178Snjl atf_tc_set_md_var(tc, "descr", "Test poll(2) timing"); 229196955Ssbruno atf_tc_set_md_var(tc, "timeout", "65"); 23044498Sgibbs} 231107178Snjl 232107178SnjlATF_TC_BODY(poll, tc) 233107178Snjl{ 234107178Snjl 235107178Snjl sleeptest(do_poll, true, true); 236107178Snjl} 237120428Ssimokawa#endif 238120428Ssimokawa 239120428SsimokawaATF_TC(sleep); 240120428SsimokawaATF_TC_HEAD(sleep, tc) 241120428Ssimokawa{ 242120428Ssimokawa 243120428Ssimokawa atf_tc_set_md_var(tc, "descr", "Test sleep(3) timing"); 244120428Ssimokawa atf_tc_set_md_var(tc, "timeout", "65"); 245120428Ssimokawa} 246120428Ssimokawa 247120428SsimokawaATF_TC_BODY(sleep, tc) 248120428Ssimokawa{ 249107178Snjl 250107178Snjl sleeptest(do_sleep, false, false); 25144498Sgibbs} 252121184Ssimokawa 253162704SmjacobATF_TC(kevent); 254121184SsimokawaATF_TC_HEAD(kevent, tc) 255121184Ssimokawa{ 256107178Snjl 257107178Snjl atf_tc_set_md_var(tc, "descr", "Test kevent(2) timing"); 25844498Sgibbs atf_tc_set_md_var(tc, "timeout", "65"); 259162704Smjacob} 260109161Snjl 261109161SnjlATF_TC_BODY(kevent, tc) 262162704Smjacob{ 263109161Snjl 264109161Snjl sleeptest(do_kevent, true, true); 265109161Snjl} 266109161Snjl 267109161Snjlint 268109161Snjlsleeptest(int (*test)(struct timespec *, struct timespec *), 269109161Snjl bool subsec, bool sim_remain) 270109161Snjl{ 271109161Snjl struct timespec tsa, tsb, tslp, tremain; 272162704Smjacob int64_t delta1, delta2, delta3, round; 273162704Smjacob 274162704Smjacob sig = 0; 275162704Smjacob signal(SIGALRM, sigalrm); 276162704Smjacob 277162704Smjacob if (subsec) { 278162704Smjacob round = 1; 279162704Smjacob delta3 = FUZZ; 280109161Snjl } else { 281109161Snjl round = 1000000000; 282162704Smjacob delta3 = round; 283109161Snjl } 284109161Snjl 285109161Snjl tslp.tv_sec = delta3 / 1000000000; 286228481Sed tslp.tv_nsec = delta3 % 1000000000; 287107178Snjl 288228481Sed while (tslp.tv_sec <= MAXSLEEP) { 289196955Ssbruno /* 290228481Sed * disturb sleep by signal on purpose 29163185Smjacob */ 292107178Snjl if (tslp.tv_sec > ALARM && sig == 0) 293107178Snjl alarm(ALARM); 294107178Snjl 295107178Snjl clock_gettime(CLOCK_REALTIME, &tsa); 296107178Snjl (*test)(&tslp, &tremain); 297107178Snjl clock_gettime(CLOCK_REALTIME, &tsb); 298107178Snjl 299107178Snjl if (sim_remain) { 30039215Sgibbs timespecsub(&tsb, &tsa, &tremain); 301107178Snjl timespecsub(&tslp, &tremain, &tremain); 302107178Snjl } 303107178Snjl 304107178Snjl delta1 = (int64_t)tsb.tv_sec - (int64_t)tsa.tv_sec; 305107178Snjl delta1 *= BILLION; 306107178Snjl delta1 += (int64_t)tsb.tv_nsec - (int64_t)tsa.tv_nsec; 307107178Snjl 308107178Snjl delta2 = (int64_t)tremain.tv_sec * BILLION; 309107178Snjl delta2 += (int64_t)tremain.tv_nsec; 310107178Snjl 311162704Smjacob delta3 = (int64_t)tslp.tv_sec * BILLION; 31239215Sgibbs delta3 += (int64_t)tslp.tv_nsec - delta1 - delta2; 31339215Sgibbs 314107178Snjl delta3 /= round; 315107178Snjl delta3 *= round; 316107178Snjl 317196955Ssbruno if (delta3 > FUZZ || delta3 < -FUZZ) { 318107178Snjl if (!sim_remain) 319107178Snjl atf_tc_expect_fail("Long reschedule latency " 32044498Sgibbs "due to PR kern/43997"); 321107178Snjl 322107178Snjl atf_tc_fail("Reschedule latency %"PRId64" exceeds " 323107178Snjl "allowable fuzz %lld", delta3, FUZZ); 32449935Sgibbs } 325107178Snjl delta3 = (int64_t)tslp.tv_sec * 2 * BILLION; 326107178Snjl delta3 += (int64_t)tslp.tv_nsec * 2; 327196955Ssbruno 328107178Snjl delta3 /= round; 32939215Sgibbs delta3 *= round; 330107178Snjl if (delta3 < FUZZ) 33149935Sgibbs break; 33249935Sgibbs tslp.tv_sec = delta3 / BILLION; 33349935Sgibbs tslp.tv_nsec = delta3 % BILLION; 33449935Sgibbs } 33549935Sgibbs ATF_REQUIRE_MSG(sig == 1, "Alarm did not fire!"); 336107178Snjl 337107178Snjl atf_tc_pass(); 33863290Smjacob} 339107178Snjl 34063290SmjacobATF_TP_ADD_TCS(tp) 341107178Snjl{ 34263290Smjacob ATF_TP_ADD_TC(tp, nanosleep); 343107178Snjl ATF_TP_ADD_TC(tp, select); 344107178Snjl#ifdef __NetBSD__ 345107178Snjl ATF_TP_ADD_TC(tp, poll); 346107178Snjl#endif 347107178Snjl ATF_TP_ADD_TC(tp, sleep); 348107178Snjl ATF_TP_ADD_TC(tp, kevent); 34944498Sgibbs 350107178Snjl return atf_no_error(); 351107178Snjl} 352107178Snjl