1*86d7f5d3SJohn Marino /*
2*86d7f5d3SJohn Marino * Copyright (c) 1996 - 2000
3*86d7f5d3SJohn Marino * HD Associates, Inc. All rights reserved.
4*86d7f5d3SJohn Marino *
5*86d7f5d3SJohn Marino * Redistribution and use in source and binary forms, with or without
6*86d7f5d3SJohn Marino * modification, are permitted provided that the following conditions
7*86d7f5d3SJohn Marino * are met:
8*86d7f5d3SJohn Marino * 1. Redistributions of source code must retain the above copyright
9*86d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer.
10*86d7f5d3SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
11*86d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer in the
12*86d7f5d3SJohn Marino * documentation and/or other materials provided with the distribution.
13*86d7f5d3SJohn Marino * 3. All advertising materials mentioning features or use of this software
14*86d7f5d3SJohn Marino * must display the following acknowledgement:
15*86d7f5d3SJohn Marino * This product includes software developed by HD Associates, Inc
16*86d7f5d3SJohn Marino * 4. Neither the name of the author nor the names of any co-contributors
17*86d7f5d3SJohn Marino * may be used to endorse or promote products derived from this software
18*86d7f5d3SJohn Marino * without specific prior written permission.
19*86d7f5d3SJohn Marino *
20*86d7f5d3SJohn Marino * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES AND CONTRIBUTORS ``AS IS'' AND
21*86d7f5d3SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22*86d7f5d3SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23*86d7f5d3SJohn Marino * ARE DISCLAIMED. IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE
24*86d7f5d3SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25*86d7f5d3SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26*86d7f5d3SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27*86d7f5d3SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28*86d7f5d3SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29*86d7f5d3SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30*86d7f5d3SJohn Marino * SUCH DAMAGE.
31*86d7f5d3SJohn Marino *
32*86d7f5d3SJohn Marino * $FreeBSD: src/tools/regression/p1003_1b/fifo.c,v 1.1 2000/02/16 14:28:40 dufault Exp $
33*86d7f5d3SJohn Marino * $DragonFly: src/tools/regression/p1003_1b/fifo.c,v 1.3 2007/06/26 23:30:05 josepht Exp $
34*86d7f5d3SJohn Marino */
35*86d7f5d3SJohn Marino #include <unistd.h>
36*86d7f5d3SJohn Marino #include <stdlib.h>
37*86d7f5d3SJohn Marino #include <stdio.h>
38*86d7f5d3SJohn Marino #include <errno.h>
39*86d7f5d3SJohn Marino #include <err.h>
40*86d7f5d3SJohn Marino #include <fcntl.h>
41*86d7f5d3SJohn Marino #include <sys/types.h>
42*86d7f5d3SJohn Marino #include <sys/mman.h>
43*86d7f5d3SJohn Marino #include <sys/time.h>
44*86d7f5d3SJohn Marino #include <sys/sched.h>
45*86d7f5d3SJohn Marino #include <signal.h>
46*86d7f5d3SJohn Marino
47*86d7f5d3SJohn Marino volatile int ticked;
48*86d7f5d3SJohn Marino #define CAN_USE_ALARMS
49*86d7f5d3SJohn Marino
50*86d7f5d3SJohn Marino #ifdef CAN_USE_ALARMS
tick(int arg)51*86d7f5d3SJohn Marino void tick(int arg)
52*86d7f5d3SJohn Marino {
53*86d7f5d3SJohn Marino ticked = 1;
54*86d7f5d3SJohn Marino }
55*86d7f5d3SJohn Marino #endif
56*86d7f5d3SJohn Marino
57*86d7f5d3SJohn Marino /* Fifo: Verify that fifo and round-robin scheduling seem to work.
58*86d7f5d3SJohn Marino *
59*86d7f5d3SJohn Marino * This tests:
60*86d7f5d3SJohn Marino * 1. That sched_rr_get_interval seems to work;
61*86d7f5d3SJohn Marino * 2. That FIFO scheduling doesn't seeem to be round-robin;
62*86d7f5d3SJohn Marino * 3. That round-robin scheduling seems to work.
63*86d7f5d3SJohn Marino *
64*86d7f5d3SJohn Marino */
65*86d7f5d3SJohn Marino static pid_t child;
tidyup(void)66*86d7f5d3SJohn Marino static void tidyup(void)
67*86d7f5d3SJohn Marino {
68*86d7f5d3SJohn Marino if (child)
69*86d7f5d3SJohn Marino kill(child, SIGHUP);
70*86d7f5d3SJohn Marino }
71*86d7f5d3SJohn Marino
72*86d7f5d3SJohn Marino static double
tvsub(const struct timeval * a,const struct timeval * b)73*86d7f5d3SJohn Marino tvsub(const struct timeval *a, const struct timeval *b)
74*86d7f5d3SJohn Marino {
75*86d7f5d3SJohn Marino long sdiff;
76*86d7f5d3SJohn Marino long udiff;
77*86d7f5d3SJohn Marino
78*86d7f5d3SJohn Marino sdiff = a->tv_sec - b->tv_sec;
79*86d7f5d3SJohn Marino udiff = a->tv_usec - b->tv_usec;
80*86d7f5d3SJohn Marino
81*86d7f5d3SJohn Marino return (double)(sdiff * 1000000 + udiff) / 1e6;
82*86d7f5d3SJohn Marino }
83*86d7f5d3SJohn Marino
fifo(int argc,char * argv[])84*86d7f5d3SJohn Marino int fifo(int argc, char *argv[])
85*86d7f5d3SJohn Marino {
86*86d7f5d3SJohn Marino int e = 0;
87*86d7f5d3SJohn Marino volatile long *p, pid;
88*86d7f5d3SJohn Marino int i;
89*86d7f5d3SJohn Marino struct sched_param fifo_param;
90*86d7f5d3SJohn Marino struct timespec interval;
91*86d7f5d3SJohn Marino #define MAX_RANAT 32
92*86d7f5d3SJohn Marino struct timeval ranat[MAX_RANAT];
93*86d7f5d3SJohn Marino
94*86d7f5d3SJohn Marino #ifdef CAN_USE_ALARMS
95*86d7f5d3SJohn Marino static struct itimerval itimerval;
96*86d7f5d3SJohn Marino #endif
97*86d7f5d3SJohn Marino
98*86d7f5d3SJohn Marino /* What is the round robin interval?
99*86d7f5d3SJohn Marino */
100*86d7f5d3SJohn Marino
101*86d7f5d3SJohn Marino if (sched_rr_get_interval(0, &interval) == -1) {
102*86d7f5d3SJohn Marino perror("sched_rr_get_interval");
103*86d7f5d3SJohn Marino exit(errno);
104*86d7f5d3SJohn Marino }
105*86d7f5d3SJohn Marino
106*86d7f5d3SJohn Marino #ifdef CAN_USE_ALARMS
107*86d7f5d3SJohn Marino signal(SIGALRM, tick);
108*86d7f5d3SJohn Marino #endif
109*86d7f5d3SJohn Marino
110*86d7f5d3SJohn Marino fifo_param.sched_priority = 1;
111*86d7f5d3SJohn Marino
112*86d7f5d3SJohn Marino p = (long *)mmap(0, sizeof(*p),
113*86d7f5d3SJohn Marino PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED|MAP_INHERIT, -1, 0);
114*86d7f5d3SJohn Marino
115*86d7f5d3SJohn Marino if (p == (long *)-1)
116*86d7f5d3SJohn Marino err(errno, "mmap");
117*86d7f5d3SJohn Marino
118*86d7f5d3SJohn Marino *p = 0;
119*86d7f5d3SJohn Marino
120*86d7f5d3SJohn Marino if (sched_setscheduler(0, SCHED_FIFO, &fifo_param) == -1)
121*86d7f5d3SJohn Marino {
122*86d7f5d3SJohn Marino perror("sched_setscheduler");
123*86d7f5d3SJohn Marino return -1;
124*86d7f5d3SJohn Marino }
125*86d7f5d3SJohn Marino
126*86d7f5d3SJohn Marino pid = getpid();
127*86d7f5d3SJohn Marino
128*86d7f5d3SJohn Marino if ((child = fork()) == 0)
129*86d7f5d3SJohn Marino {
130*86d7f5d3SJohn Marino /* Child process. Just keep setting the pointer to our
131*86d7f5d3SJohn Marino * PID. The parent will kill us when it wants to.
132*86d7f5d3SJohn Marino */
133*86d7f5d3SJohn Marino
134*86d7f5d3SJohn Marino pid = getpid();
135*86d7f5d3SJohn Marino while (1)
136*86d7f5d3SJohn Marino *p = pid;
137*86d7f5d3SJohn Marino }
138*86d7f5d3SJohn Marino else
139*86d7f5d3SJohn Marino {
140*86d7f5d3SJohn Marino atexit(tidyup);
141*86d7f5d3SJohn Marino *p = pid;
142*86d7f5d3SJohn Marino
143*86d7f5d3SJohn Marino
144*86d7f5d3SJohn Marino ticked = 0;
145*86d7f5d3SJohn Marino
146*86d7f5d3SJohn Marino #ifdef CAN_USE_ALARMS
147*86d7f5d3SJohn Marino /* Set an alarm for 250 times the round-robin interval.
148*86d7f5d3SJohn Marino * Then we will verify that a similar priority process
149*86d7f5d3SJohn Marino * will not run when we are using the FIFO scheduler.
150*86d7f5d3SJohn Marino */
151*86d7f5d3SJohn Marino itimerval.it_value.tv_usec = interval.tv_nsec / (1000 / 250);
152*86d7f5d3SJohn Marino
153*86d7f5d3SJohn Marino itimerval.it_value.tv_sec = itimerval.it_value.tv_usec / 1000000;
154*86d7f5d3SJohn Marino itimerval.it_value.tv_usec %= 1000000;
155*86d7f5d3SJohn Marino
156*86d7f5d3SJohn Marino
157*86d7f5d3SJohn Marino if (setitimer(ITIMER_REAL, &itimerval, 0) == -1) {
158*86d7f5d3SJohn Marino perror("setitimer");
159*86d7f5d3SJohn Marino exit(errno);
160*86d7f5d3SJohn Marino }
161*86d7f5d3SJohn Marino #endif
162*86d7f5d3SJohn Marino
163*86d7f5d3SJohn Marino
164*86d7f5d3SJohn Marino gettimeofday(ranat, 0);
165*86d7f5d3SJohn Marino i = 1;
166*86d7f5d3SJohn Marino while (!ticked && i < MAX_RANAT)
167*86d7f5d3SJohn Marino if (*p == child) {
168*86d7f5d3SJohn Marino gettimeofday(ranat + i, 0);
169*86d7f5d3SJohn Marino *p = 0;
170*86d7f5d3SJohn Marino e = -1;
171*86d7f5d3SJohn Marino i++;
172*86d7f5d3SJohn Marino }
173*86d7f5d3SJohn Marino
174*86d7f5d3SJohn Marino if (e) {
175*86d7f5d3SJohn Marino int j;
176*86d7f5d3SJohn Marino
177*86d7f5d3SJohn Marino fprintf(stderr,
178*86d7f5d3SJohn Marino "SCHED_FIFO had erroneous context switches:\n");
179*86d7f5d3SJohn Marino for (j = 1; j < i; j++) {
180*86d7f5d3SJohn Marino fprintf(stderr, "%d %g\n", j,
181*86d7f5d3SJohn Marino tvsub(ranat + j, ranat + j - 1));
182*86d7f5d3SJohn Marino }
183*86d7f5d3SJohn Marino return e;
184*86d7f5d3SJohn Marino }
185*86d7f5d3SJohn Marino
186*86d7f5d3SJohn Marino /* Switch to the round robin scheduler and the child
187*86d7f5d3SJohn Marino * should run within twice the interval.
188*86d7f5d3SJohn Marino */
189*86d7f5d3SJohn Marino if (sched_setscheduler(child, SCHED_RR, &fifo_param) == -1 ||
190*86d7f5d3SJohn Marino sched_setscheduler(0, SCHED_RR, &fifo_param) == -1)
191*86d7f5d3SJohn Marino {
192*86d7f5d3SJohn Marino perror("sched_setscheduler");
193*86d7f5d3SJohn Marino return -1;
194*86d7f5d3SJohn Marino }
195*86d7f5d3SJohn Marino
196*86d7f5d3SJohn Marino e = -1;
197*86d7f5d3SJohn Marino
198*86d7f5d3SJohn Marino ticked = 0;
199*86d7f5d3SJohn Marino
200*86d7f5d3SJohn Marino #ifdef CAN_USE_ALARMS
201*86d7f5d3SJohn Marino
202*86d7f5d3SJohn Marino /* Now we do want to see it run. But only set
203*86d7f5d3SJohn Marino * the alarm for twice the interval:
204*86d7f5d3SJohn Marino */
205*86d7f5d3SJohn Marino itimerval.it_value.tv_usec = interval.tv_nsec / 500;
206*86d7f5d3SJohn Marino
207*86d7f5d3SJohn Marino if (setitimer(ITIMER_REAL, &itimerval, 0) == -1) {
208*86d7f5d3SJohn Marino perror("setitimer");
209*86d7f5d3SJohn Marino exit(errno);
210*86d7f5d3SJohn Marino }
211*86d7f5d3SJohn Marino #endif
212*86d7f5d3SJohn Marino
213*86d7f5d3SJohn Marino for (i = 0; !ticked; i++)
214*86d7f5d3SJohn Marino if (*p == child) {
215*86d7f5d3SJohn Marino e = 0;
216*86d7f5d3SJohn Marino break;
217*86d7f5d3SJohn Marino }
218*86d7f5d3SJohn Marino
219*86d7f5d3SJohn Marino if (e)
220*86d7f5d3SJohn Marino fprintf(stderr,"Child never ran when it should have.\n");
221*86d7f5d3SJohn Marino }
222*86d7f5d3SJohn Marino
223*86d7f5d3SJohn Marino exit(e);
224*86d7f5d3SJohn Marino }
225*86d7f5d3SJohn Marino
226*86d7f5d3SJohn Marino #ifdef STANDALONE_TESTS
main(int argc,char * argv[])227*86d7f5d3SJohn Marino int main(int argc, char *argv[]) { return fifo(argc, argv); }
228*86d7f5d3SJohn Marino #endif
229