Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / regress / sys / kern / sleeping / sleeptest.c
blob6bd50cecd0a819fc4a38a5f40856cd1dac525134
1 /* $NetBSD: sleeptest.c,v 1.1 2006/07/16 19:19:39 kardel Exp $ */
3 /*-
4 * Copyright (c) 2006 Frank Kardel
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <time.h>
33 #include <errno.h>
34 #include <sys/signal.h>
35 #include <string.h>
36 #include <err.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
43 static int sig, sigs;
45 static char *sleepers[] = {
46 "nanosleep",
47 "select",
48 "poll",
49 "sleep",
50 "kevent"
53 #define N_SLEEPERS (sizeof(sleepers)/sizeof(sleepers[0]))
55 void
56 sigalrm()
58 sig++;
61 int
62 main(int argc, char *argv[])
64 struct timespec tsa, tsb, tslp, tslplast, tremain;
65 struct timeval tv;
66 int64_t delta1, delta2, delta3, round;
67 int errors = 0, i;
68 char *rtype;
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++) {
79 switch (i) {
80 case 3: /* sleep has only second resolution */
81 round = 1000000000;
82 delta3 = round;
83 break;
84 default:
85 round = 1;
86 delta3 = FUZZ;
87 break;
89 sigs += sig;
90 sig = 0;
91 rtype = "simulated";
93 tslp.tv_sec = delta3 / 1000000000;
94 tslp.tv_nsec = delta3 % 1000000000;
95 tslplast = tslp;
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)
103 alarm(ALARM);
105 fflush(stdout);
106 clock_gettime(CLOCK_REALTIME, &tsa);
107 switch (i) {
108 case 0: /* nanosleep */
109 rtype = "returned";
110 if (nanosleep(&tslp, &tremain) == -1) {
111 if (errno != EINTR)
112 errors++;
113 printf("- errno=%s (%s) - ", strerror(errno), (errno == EINTR) ? "OK" : "ERROR");
115 clock_gettime(CLOCK_REALTIME, &tsb);
116 break;
118 case 1: /* select */
119 TIMESPEC_TO_TIMEVAL(&tv, &tslp);
120 if (select(0, NULL, NULL, NULL, &tv) == -1) {
121 if (errno != EINTR)
122 errors++;
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);
129 break;
131 case 2: /* poll */
132 TIMESPEC_TO_TIMEVAL(&tv, &tslp);
133 if (pollts(NULL, 0, &tslp, NULL) == -1) {
134 if (errno != EINTR)
135 errors++;
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);
142 break;
144 case 3: /* sleep */
145 rtype = "returned";
146 tremain.tv_sec = sleep(tslp.tv_sec);
147 tremain.tv_nsec = 0;
148 clock_gettime(CLOCK_REALTIME, &tsb);
149 break;
151 case 4: /* kevent */
153 struct kevent ktimer;
154 struct kevent kresult;
155 int rtc, timeout = KEVNT_TIMEOUT;
156 int kq = kqueue();
158 if (kq == -1) {
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);
165 if (rtc == -1) {
166 if (errno != EINTR)
167 errors++;
168 printf("- errno=%s (%s) - ", strerror(errno), (errno == EINTR) ? "OK" : "ERROR");
170 clock_gettime(CLOCK_REALTIME, &tsb);
171 if (rtc == 0) {
172 printf("- not fired");
173 if (tslp.tv_sec * 1000000000LL + tslp.tv_nsec -
174 timeout * 1000000LL > 0) {
175 printf(" - TIMING ERROR");
176 errors++;
178 printf(" - ");
179 } else if (rtc > 0) {
180 printf("- fired - ");
182 timespecsub(&tsb, &tsa, &tremain);
183 timespecsub(&tslp, &tremain, &tremain);
184 (void)close(kq);
186 break;
188 default:
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);
197 fflush(stdout);
198 delta3 /= round;
199 delta3 *= round;
200 if (delta3 > FUZZ || delta3 < -FUZZ) {
201 errors++;
202 printf(" ERROR\n");
203 delta3 = ((int64_t)tslp.tv_sec + (int64_t)tslplast.tv_sec) * 1000000000LL + (int64_t)tslplast.tv_nsec
204 + (int64_t)tslp.tv_nsec;
205 delta3 /= 2;
206 } else {
207 printf(" OK\n");
208 tslplast = tslp;
209 delta3 = ((int64_t)tslp.tv_sec + (int64_t)tslplast.tv_sec) * 1000000000LL + (int64_t)tslplast.tv_nsec
210 + (int64_t)tslp.tv_nsec;
212 delta3 /= round;
213 delta3 *= round;
214 if (delta3 < FUZZ)
215 break;
216 tslp.tv_sec = delta3 / 1000000000LL;
217 tslp.tv_nsec = delta3 % 1000000000LL;
220 sigs += sig;
222 if (errors || sigs != N_SLEEPERS) {
223 printf("TEST FAIL (%d errors, %d alarms, %d interfaces)\n", errors, sigs, N_SLEEPERS);
224 return 1;
225 } else {
226 printf("TEST SUCCESSFUL\n");
227 return 0;