1 /* $NetBSD: sleeptest.c,v 1.1 2006/07/16 19:19:39 kardel 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.
29 #include <sys/event.h>
34 #include <sys/signal.h>
38 #define FUZZ 30000000LL /* scheduling fuzz accepted - 30 ms */
39 #define MAXSLEEP 32000000000LL /* 32 seconds */
40 #define ALARM 11 /* SIGALRM after this time */
41 #define KEVNT_TIMEOUT 13200
45 static char *sleepers
[] = {
53 #define N_SLEEPERS (sizeof(sleepers)/sizeof(sleepers[0]))
62 main(int argc
, char *argv
[])
64 struct timespec tsa
, tsb
, tslp
, tslplast
, tremain
;
66 int64_t delta1
, delta2
, delta3
, round
;
70 printf("Testing sleep/timeout implementations\n");
71 printf("accepted scheduling delta %lld ms\n", FUZZ
/ 1000000LL);
72 printf("testing up to %lld ms for %d interfaces\n", MAXSLEEP
/ 1000000LL, N_SLEEPERS
);
73 printf("ALARM interrupt after %d sec once per run\n", ALARM
);
74 printf("kevent timer will fire after %d ms\n", KEVNT_TIMEOUT
);
76 signal(SIGALRM
, sigalrm
);
78 for (i
= 0; i
< N_SLEEPERS
; i
++) {
80 case 3: /* sleep has only second resolution */
93 tslp
.tv_sec
= delta3
/ 1000000000;
94 tslp
.tv_nsec
= delta3
% 1000000000;
97 while (delta3
<= MAXSLEEP
) {
98 printf("[%s] sleeping %lld nsec ... ", sleepers
[i
], delta3
);
100 * disturb sleep by signal on purpose
102 if (delta3
> ALARM
* 1000000000LL && sig
== 0)
106 clock_gettime(CLOCK_REALTIME
, &tsa
);
108 case 0: /* nanosleep */
110 if (nanosleep(&tslp
, &tremain
) == -1) {
113 printf("- errno=%s (%s) - ", strerror(errno
), (errno
== EINTR
) ? "OK" : "ERROR");
115 clock_gettime(CLOCK_REALTIME
, &tsb
);
119 TIMESPEC_TO_TIMEVAL(&tv
, &tslp
);
120 if (select(0, NULL
, NULL
, NULL
, &tv
) == -1) {
123 printf("- errno=%s (%s) - ", strerror(errno
), (errno
== EINTR
) ? "OK" : "ERROR");
125 /* simulate remaining time */
126 clock_gettime(CLOCK_REALTIME
, &tsb
);
127 timespecsub(&tsb
, &tsa
, &tremain
);
128 timespecsub(&tslp
, &tremain
, &tremain
);
132 TIMESPEC_TO_TIMEVAL(&tv
, &tslp
);
133 if (pollts(NULL
, 0, &tslp
, NULL
) == -1) {
136 printf("- errno=%s (%s) - ", strerror(errno
), (errno
== EINTR
) ? "OK" : "ERROR");
138 /* simulate remaining time */
139 clock_gettime(CLOCK_REALTIME
, &tsb
);
140 timespecsub(&tsb
, &tsa
, &tremain
);
141 timespecsub(&tslp
, &tremain
, &tremain
);
146 tremain
.tv_sec
= sleep(tslp
.tv_sec
);
148 clock_gettime(CLOCK_REALTIME
, &tsb
);
153 struct kevent ktimer
;
154 struct kevent kresult
;
155 int rtc
, timeout
= KEVNT_TIMEOUT
;
159 err(EXIT_FAILURE
, "kqueue");
162 EV_SET(&ktimer
, 1, EVFILT_TIMER
, EV_ADD
, 0, timeout
, 0);
164 rtc
= kevent(kq
, &ktimer
, 1, &kresult
, 1, &tslp
);
168 printf("- errno=%s (%s) - ", strerror(errno
), (errno
== EINTR
) ? "OK" : "ERROR");
170 clock_gettime(CLOCK_REALTIME
, &tsb
);
172 printf("- not fired");
173 if (tslp
.tv_sec
* 1000000000LL + tslp
.tv_nsec
-
174 timeout
* 1000000LL > 0) {
175 printf(" - TIMING ERROR");
179 } else if (rtc
> 0) {
180 printf("- fired - ");
182 timespecsub(&tsb
, &tsa
, &tremain
);
183 timespecsub(&tslp
, &tremain
, &tremain
);
189 errx(EXIT_FAILURE
, "programming error - sleep method to test not implemented\n");
192 delta1
= ((int64_t)tsb
.tv_sec
- (int64_t)tsa
.tv_sec
) * 1000000000LL + (int64_t)tsb
.tv_nsec
- (int64_t)tsa
.tv_nsec
;
193 delta2
= (((int64_t)tremain
.tv_sec
* 1000000000LL) + (int64_t)tremain
.tv_nsec
);
194 delta3
= (int64_t)tslp
.tv_sec
* 1000000000LL + (int64_t)tslp
.tv_nsec
- delta1
- delta2
;
195 printf("sig %d, real time sleep %lld nsec, remain(%s) %lld nsec, diff to supposed sleep %lld nsec (rounded %lld nsec)",
196 sigs
+ sig
, delta1
, rtype
, delta2
, delta3
, (delta3
/ round
) * round
);
200 if (delta3
> FUZZ
|| delta3
< -FUZZ
) {
203 delta3
= ((int64_t)tslp
.tv_sec
+ (int64_t)tslplast
.tv_sec
) * 1000000000LL + (int64_t)tslplast
.tv_nsec
204 + (int64_t)tslp
.tv_nsec
;
209 delta3
= ((int64_t)tslp
.tv_sec
+ (int64_t)tslplast
.tv_sec
) * 1000000000LL + (int64_t)tslplast
.tv_nsec
210 + (int64_t)tslp
.tv_nsec
;
216 tslp
.tv_sec
= delta3
/ 1000000000LL;
217 tslp
.tv_nsec
= delta3
% 1000000000LL;
222 if (errors
|| sigs
!= N_SLEEPERS
) {
223 printf("TEST FAIL (%d errors, %d alarms, %d interfaces)\n", errors
, sigs
, N_SLEEPERS
);
226 printf("TEST SUCCESSFUL\n");