1 /* $NetBSD: t_sleep.c,v 1.8 2014/07/15 14:56:34 gson Exp $ */
4 * Copyright (c) 2006 Frank Kardel
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
38 #include <sys/cdefs.h>
39 #include <sys/event.h>
40 #include <sys/signal.h>
44 #define BILLION 1000000000LL /* nano-seconds per second */
45 #define MILLION 1000000LL /* nano-seconds per milli-second */
47 #define ALARM 6 /* SIGALRM after this many seconds */
48 #define MAXSLEEP 22 /* Maximum delay in seconds */
49 #define KEVNT_TIMEOUT 10300 /* measured in milli-seconds */
50 #define FUZZ (40 * MILLION) /* scheduling fuzz accepted - 40 ms */
55 * Most tests use FUZZ as their initial delay value, but 'sleep'
56 * starts at 1sec (since it cannot handle sub-second intervals).
57 * Subsequent passes double the previous interval, up to MAXSLEEP.
59 * The current values result in 5 passes for the 'sleep' test (at 1,
60 * 2, 4, 8, and 16 seconds) and 10 passes for the other tests (at
61 * 0.04, 0.08, 0.16, 0.32, 0.64, 1.28, 2.56, 5.12, 10.24, and 20.48
64 * The ALARM is only set if the current pass's delay is longer, and
65 * only if the ALARM has not already been triggered.
67 * The 'kevent' test needs the ALARM to be set on a different pass
68 * from when the KEVNT_TIMEOUT fires. So set ALARM to fire on the
69 * penultimate pass, and the KEVNT_TIMEOUT on the final pass. We
70 * set KEVNT_TIMEOUT just barely long enough to put it into the
71 * last test pass, and set MAXSLEEP a couple seconds longer than
72 * necessary, in order to avoid a QEMU bug which nearly doubles
76 static volatile int sig
;
78 int sleeptest(int (*)(struct timespec
*, struct timespec
*), bool, bool);
79 int do_nanosleep(struct timespec
*, struct timespec
*);
80 int do_select(struct timespec
*, struct timespec
*);
81 int do_poll(struct timespec
*, struct timespec
*);
82 int do_sleep(struct timespec
*, struct timespec
*);
83 int do_kevent(struct timespec
*, struct timespec
*);
94 do_nanosleep(struct timespec
*delay
, struct timespec
*remain
)
98 if (nanosleep(delay
, remain
) == -1)
99 ret
= (errno
== EINTR
? 0 : errno
);
106 do_select(struct timespec
*delay
, struct timespec
*remain
)
111 TIMESPEC_TO_TIMEVAL(&tv
, delay
);
112 if (select(0, NULL
, NULL
, NULL
, &tv
) == -1)
113 ret
= (errno
== EINTR
? 0 : errno
);
120 do_poll(struct timespec
*delay
, struct timespec
*remain
)
125 TIMESPEC_TO_TIMEVAL(&tv
, delay
);
126 if (pollts(NULL
, 0, delay
, NULL
) == -1)
127 ret
= (errno
== EINTR
? 0 : errno
);
134 do_sleep(struct timespec
*delay
, struct timespec
*remain
)
138 TIMESPEC_TO_TIMEVAL(&tv
, delay
);
139 remain
->tv_sec
= sleep(delay
->tv_sec
);
146 do_kevent(struct timespec
*delay
, struct timespec
*remain
)
148 struct kevent ktimer
;
149 struct kevent kresult
;
153 ATF_REQUIRE_MSG((kq
= kqueue()) != -1, "kqueue: %s", strerror(errno
));
158 * If we expect the KEVNT_TIMEOUT to fire, and we're running
159 * under QEMU, make sure the delay is long enough to account
160 * for the effects of PR kern/43997 !
163 tmo
/1000 < delay
->tv_sec
&& tmo
/500 > delay
->tv_sec
)
164 delay
->tv_sec
= MAXSLEEP
;
166 EV_SET(&ktimer
, 1, EVFILT_TIMER
, EV_ADD
, 0, tmo
, 0);
168 rtc
= kevent(kq
, &ktimer
, 1, &kresult
, 1, delay
);
174 ATF_REQUIRE_MSG(kerrno
== EINTR
, "kevent: %s", strerror(errno
));
178 if (delay
->tv_sec
* BILLION
+ delay
->tv_nsec
> tmo
* MILLION
)
179 ATF_REQUIRE_MSG(rtc
> 0,
180 "kevent: KEVNT_TIMEOUT did not cause EVFILT_TIMER event");
186 ATF_TC_HEAD(nanosleep
, tc
)
189 atf_tc_set_md_var(tc
, "descr", "Test nanosleep(2) timing");
190 atf_tc_set_md_var(tc
, "timeout", "65");
193 ATF_TC_BODY(nanosleep
, tc
)
196 sleeptest(do_nanosleep
, true, false);
200 ATF_TC_HEAD(select
, tc
)
203 atf_tc_set_md_var(tc
, "descr", "Test select(2) timing");
204 atf_tc_set_md_var(tc
, "timeout", "65");
207 ATF_TC_BODY(select
, tc
)
210 sleeptest(do_select
, true, true);
214 ATF_TC_HEAD(poll
, tc
)
217 atf_tc_set_md_var(tc
, "descr", "Test poll(2) timing");
218 atf_tc_set_md_var(tc
, "timeout", "65");
221 ATF_TC_BODY(poll
, tc
)
224 sleeptest(do_poll
, true, true);
228 ATF_TC_HEAD(sleep
, tc
)
231 atf_tc_set_md_var(tc
, "descr", "Test sleep(3) timing");
232 atf_tc_set_md_var(tc
, "timeout", "65");
235 ATF_TC_BODY(sleep
, tc
)
238 sleeptest(do_sleep
, false, false);
242 ATF_TC_HEAD(kevent
, tc
)
245 atf_tc_set_md_var(tc
, "descr", "Test kevent(2) timing");
246 atf_tc_set_md_var(tc
, "timeout", "65");
249 ATF_TC_BODY(kevent
, tc
)
252 sleeptest(do_kevent
, true, true);
256 sleeptest(int (*test
)(struct timespec
*, struct timespec
*),
257 bool subsec
, bool sim_remain
)
259 struct timespec tsa
, tsb
, tslp
, tremain
;
260 int64_t delta1
, delta2
, delta3
, round
;
263 signal(SIGALRM
, sigalrm
);
273 tslp
.tv_sec
= delta3
/ 1000000000;
274 tslp
.tv_nsec
= delta3
% 1000000000;
276 while (tslp
.tv_sec
<= MAXSLEEP
) {
278 * disturb sleep by signal on purpose
280 if (tslp
.tv_sec
> ALARM
&& sig
== 0)
283 clock_gettime(CLOCK_REALTIME
, &tsa
);
284 (*test
)(&tslp
, &tremain
);
285 clock_gettime(CLOCK_REALTIME
, &tsb
);
288 timespecsub(&tsb
, &tsa
, &tremain
);
289 timespecsub(&tslp
, &tremain
, &tremain
);
292 delta1
= (int64_t)tsb
.tv_sec
- (int64_t)tsa
.tv_sec
;
294 delta1
+= (int64_t)tsb
.tv_nsec
- (int64_t)tsa
.tv_nsec
;
296 delta2
= (int64_t)tremain
.tv_sec
* BILLION
;
297 delta2
+= (int64_t)tremain
.tv_nsec
;
299 delta3
= (int64_t)tslp
.tv_sec
* BILLION
;
300 delta3
+= (int64_t)tslp
.tv_nsec
- delta1
- delta2
;
305 if (delta3
> FUZZ
|| delta3
< -FUZZ
) {
307 atf_tc_expect_fail("Long reschedule latency "
308 "due to PR kern/43997");
310 atf_tc_fail("Reschedule latency %"PRId64
" exceeds "
311 "allowable fuzz %lld", delta3
, FUZZ
);
313 delta3
= (int64_t)tslp
.tv_sec
* 2 * BILLION
;
314 delta3
+= (int64_t)tslp
.tv_nsec
* 2;
320 tslp
.tv_sec
= delta3
/ BILLION
;
321 tslp
.tv_nsec
= delta3
% BILLION
;
323 ATF_REQUIRE_MSG(sig
== 1, "Alarm did not fire!");
330 ATF_TP_ADD_TC(tp
, nanosleep
);
331 ATF_TP_ADD_TC(tp
, select
);
332 ATF_TP_ADD_TC(tp
, poll
);
333 ATF_TP_ADD_TC(tp
, sleep
);
334 ATF_TP_ADD_TC(tp
, kevent
);
336 return atf_no_error();