186d7f5d3SJohn Marino /*
286d7f5d3SJohn Marino * Copyright (c) 1996 - 2000
386d7f5d3SJohn Marino * HD Associates, Inc. All rights reserved.
486d7f5d3SJohn Marino *
586d7f5d3SJohn Marino * Redistribution and use in source and binary forms, with or without
686d7f5d3SJohn Marino * modification, are permitted provided that the following conditions
786d7f5d3SJohn Marino * are met:
886d7f5d3SJohn Marino * 1. Redistributions of source code must retain the above copyright
986d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer.
1086d7f5d3SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
1186d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer in the
1286d7f5d3SJohn Marino * documentation and/or other materials provided with the distribution.
1386d7f5d3SJohn Marino * 3. All advertising materials mentioning features or use of this software
1486d7f5d3SJohn Marino * must display the following acknowledgement:
1586d7f5d3SJohn Marino * This product includes software developed by HD Associates, Inc
1686d7f5d3SJohn Marino * 4. Neither the name of the author nor the names of any co-contributors
1786d7f5d3SJohn Marino * may be used to endorse or promote products derived from this software
1886d7f5d3SJohn Marino * without specific prior written permission.
1986d7f5d3SJohn Marino *
2086d7f5d3SJohn Marino * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES AND CONTRIBUTORS ``AS IS'' AND
2186d7f5d3SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2286d7f5d3SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2386d7f5d3SJohn Marino * ARE DISCLAIMED. IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE
2486d7f5d3SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2586d7f5d3SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2686d7f5d3SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2786d7f5d3SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2886d7f5d3SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2986d7f5d3SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3086d7f5d3SJohn Marino * SUCH DAMAGE.
3186d7f5d3SJohn Marino *
3286d7f5d3SJohn Marino * $FreeBSD: src/tools/regression/p1003_1b/fifo.c,v 1.1 2000/02/16 14:28:40 dufault Exp $
3386d7f5d3SJohn Marino * $DragonFly: src/tools/regression/p1003_1b/fifo.c,v 1.3 2007/06/26 23:30:05 josepht Exp $
3486d7f5d3SJohn Marino */
3586d7f5d3SJohn Marino #include <unistd.h>
3686d7f5d3SJohn Marino #include <stdlib.h>
3786d7f5d3SJohn Marino #include <stdio.h>
3886d7f5d3SJohn Marino #include <errno.h>
3986d7f5d3SJohn Marino #include <err.h>
4086d7f5d3SJohn Marino #include <fcntl.h>
4186d7f5d3SJohn Marino #include <sys/types.h>
4286d7f5d3SJohn Marino #include <sys/mman.h>
4386d7f5d3SJohn Marino #include <sys/time.h>
4486d7f5d3SJohn Marino #include <sys/sched.h>
4586d7f5d3SJohn Marino #include <signal.h>
4686d7f5d3SJohn Marino
4786d7f5d3SJohn Marino volatile int ticked;
4886d7f5d3SJohn Marino #define CAN_USE_ALARMS
4986d7f5d3SJohn Marino
5086d7f5d3SJohn Marino #ifdef CAN_USE_ALARMS
tick(int arg)5186d7f5d3SJohn Marino void tick(int arg)
5286d7f5d3SJohn Marino {
5386d7f5d3SJohn Marino ticked = 1;
5486d7f5d3SJohn Marino }
5586d7f5d3SJohn Marino #endif
5686d7f5d3SJohn Marino
5786d7f5d3SJohn Marino /* Fifo: Verify that fifo and round-robin scheduling seem to work.
5886d7f5d3SJohn Marino *
5986d7f5d3SJohn Marino * This tests:
6086d7f5d3SJohn Marino * 1. That sched_rr_get_interval seems to work;
6186d7f5d3SJohn Marino * 2. That FIFO scheduling doesn't seeem to be round-robin;
6286d7f5d3SJohn Marino * 3. That round-robin scheduling seems to work.
6386d7f5d3SJohn Marino *
6486d7f5d3SJohn Marino */
6586d7f5d3SJohn Marino static pid_t child;
tidyup(void)6686d7f5d3SJohn Marino static void tidyup(void)
6786d7f5d3SJohn Marino {
6886d7f5d3SJohn Marino if (child)
6986d7f5d3SJohn Marino kill(child, SIGHUP);
7086d7f5d3SJohn Marino }
7186d7f5d3SJohn Marino
7286d7f5d3SJohn Marino static double
tvsub(const struct timeval * a,const struct timeval * b)7386d7f5d3SJohn Marino tvsub(const struct timeval *a, const struct timeval *b)
7486d7f5d3SJohn Marino {
7586d7f5d3SJohn Marino long sdiff;
7686d7f5d3SJohn Marino long udiff;
7786d7f5d3SJohn Marino
7886d7f5d3SJohn Marino sdiff = a->tv_sec - b->tv_sec;
7986d7f5d3SJohn Marino udiff = a->tv_usec - b->tv_usec;
8086d7f5d3SJohn Marino
8186d7f5d3SJohn Marino return (double)(sdiff * 1000000 + udiff) / 1e6;
8286d7f5d3SJohn Marino }
8386d7f5d3SJohn Marino
fifo(int argc,char * argv[])8486d7f5d3SJohn Marino int fifo(int argc, char *argv[])
8586d7f5d3SJohn Marino {
8686d7f5d3SJohn Marino int e = 0;
8786d7f5d3SJohn Marino volatile long *p, pid;
8886d7f5d3SJohn Marino int i;
8986d7f5d3SJohn Marino struct sched_param fifo_param;
9086d7f5d3SJohn Marino struct timespec interval;
9186d7f5d3SJohn Marino #define MAX_RANAT 32
9286d7f5d3SJohn Marino struct timeval ranat[MAX_RANAT];
9386d7f5d3SJohn Marino
9486d7f5d3SJohn Marino #ifdef CAN_USE_ALARMS
9586d7f5d3SJohn Marino static struct itimerval itimerval;
9686d7f5d3SJohn Marino #endif
9786d7f5d3SJohn Marino
9886d7f5d3SJohn Marino /* What is the round robin interval?
9986d7f5d3SJohn Marino */
10086d7f5d3SJohn Marino
10186d7f5d3SJohn Marino if (sched_rr_get_interval(0, &interval) == -1) {
10286d7f5d3SJohn Marino perror("sched_rr_get_interval");
10386d7f5d3SJohn Marino exit(errno);
10486d7f5d3SJohn Marino }
10586d7f5d3SJohn Marino
10686d7f5d3SJohn Marino #ifdef CAN_USE_ALARMS
10786d7f5d3SJohn Marino signal(SIGALRM, tick);
10886d7f5d3SJohn Marino #endif
10986d7f5d3SJohn Marino
11086d7f5d3SJohn Marino fifo_param.sched_priority = 1;
11186d7f5d3SJohn Marino
11286d7f5d3SJohn Marino p = (long *)mmap(0, sizeof(*p),
11386d7f5d3SJohn Marino PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED|MAP_INHERIT, -1, 0);
11486d7f5d3SJohn Marino
11586d7f5d3SJohn Marino if (p == (long *)-1)
11686d7f5d3SJohn Marino err(errno, "mmap");
11786d7f5d3SJohn Marino
11886d7f5d3SJohn Marino *p = 0;
11986d7f5d3SJohn Marino
12086d7f5d3SJohn Marino if (sched_setscheduler(0, SCHED_FIFO, &fifo_param) == -1)
12186d7f5d3SJohn Marino {
12286d7f5d3SJohn Marino perror("sched_setscheduler");
12386d7f5d3SJohn Marino return -1;
12486d7f5d3SJohn Marino }
12586d7f5d3SJohn Marino
12686d7f5d3SJohn Marino pid = getpid();
12786d7f5d3SJohn Marino
12886d7f5d3SJohn Marino if ((child = fork()) == 0)
12986d7f5d3SJohn Marino {
13086d7f5d3SJohn Marino /* Child process. Just keep setting the pointer to our
13186d7f5d3SJohn Marino * PID. The parent will kill us when it wants to.
13286d7f5d3SJohn Marino */
13386d7f5d3SJohn Marino
13486d7f5d3SJohn Marino pid = getpid();
13586d7f5d3SJohn Marino while (1)
13686d7f5d3SJohn Marino *p = pid;
13786d7f5d3SJohn Marino }
13886d7f5d3SJohn Marino else
13986d7f5d3SJohn Marino {
14086d7f5d3SJohn Marino atexit(tidyup);
14186d7f5d3SJohn Marino *p = pid;
14286d7f5d3SJohn Marino
14386d7f5d3SJohn Marino
14486d7f5d3SJohn Marino ticked = 0;
14586d7f5d3SJohn Marino
14686d7f5d3SJohn Marino #ifdef CAN_USE_ALARMS
14786d7f5d3SJohn Marino /* Set an alarm for 250 times the round-robin interval.
14886d7f5d3SJohn Marino * Then we will verify that a similar priority process
14986d7f5d3SJohn Marino * will not run when we are using the FIFO scheduler.
15086d7f5d3SJohn Marino */
15186d7f5d3SJohn Marino itimerval.it_value.tv_usec = interval.tv_nsec / (1000 / 250);
15286d7f5d3SJohn Marino
15386d7f5d3SJohn Marino itimerval.it_value.tv_sec = itimerval.it_value.tv_usec / 1000000;
15486d7f5d3SJohn Marino itimerval.it_value.tv_usec %= 1000000;
15586d7f5d3SJohn Marino
15686d7f5d3SJohn Marino
15786d7f5d3SJohn Marino if (setitimer(ITIMER_REAL, &itimerval, 0) == -1) {
15886d7f5d3SJohn Marino perror("setitimer");
15986d7f5d3SJohn Marino exit(errno);
16086d7f5d3SJohn Marino }
16186d7f5d3SJohn Marino #endif
16286d7f5d3SJohn Marino
16386d7f5d3SJohn Marino
16486d7f5d3SJohn Marino gettimeofday(ranat, 0);
16586d7f5d3SJohn Marino i = 1;
16686d7f5d3SJohn Marino while (!ticked && i < MAX_RANAT)
16786d7f5d3SJohn Marino if (*p == child) {
16886d7f5d3SJohn Marino gettimeofday(ranat + i, 0);
16986d7f5d3SJohn Marino *p = 0;
17086d7f5d3SJohn Marino e = -1;
17186d7f5d3SJohn Marino i++;
17286d7f5d3SJohn Marino }
17386d7f5d3SJohn Marino
17486d7f5d3SJohn Marino if (e) {
17586d7f5d3SJohn Marino int j;
17686d7f5d3SJohn Marino
17786d7f5d3SJohn Marino fprintf(stderr,
17886d7f5d3SJohn Marino "SCHED_FIFO had erroneous context switches:\n");
17986d7f5d3SJohn Marino for (j = 1; j < i; j++) {
18086d7f5d3SJohn Marino fprintf(stderr, "%d %g\n", j,
18186d7f5d3SJohn Marino tvsub(ranat + j, ranat + j - 1));
18286d7f5d3SJohn Marino }
18386d7f5d3SJohn Marino return e;
18486d7f5d3SJohn Marino }
18586d7f5d3SJohn Marino
18686d7f5d3SJohn Marino /* Switch to the round robin scheduler and the child
18786d7f5d3SJohn Marino * should run within twice the interval.
18886d7f5d3SJohn Marino */
18986d7f5d3SJohn Marino if (sched_setscheduler(child, SCHED_RR, &fifo_param) == -1 ||
19086d7f5d3SJohn Marino sched_setscheduler(0, SCHED_RR, &fifo_param) == -1)
19186d7f5d3SJohn Marino {
19286d7f5d3SJohn Marino perror("sched_setscheduler");
19386d7f5d3SJohn Marino return -1;
19486d7f5d3SJohn Marino }
19586d7f5d3SJohn Marino
19686d7f5d3SJohn Marino e = -1;
19786d7f5d3SJohn Marino
19886d7f5d3SJohn Marino ticked = 0;
19986d7f5d3SJohn Marino
20086d7f5d3SJohn Marino #ifdef CAN_USE_ALARMS
20186d7f5d3SJohn Marino
20286d7f5d3SJohn Marino /* Now we do want to see it run. But only set
20386d7f5d3SJohn Marino * the alarm for twice the interval:
20486d7f5d3SJohn Marino */
20586d7f5d3SJohn Marino itimerval.it_value.tv_usec = interval.tv_nsec / 500;
20686d7f5d3SJohn Marino
20786d7f5d3SJohn Marino if (setitimer(ITIMER_REAL, &itimerval, 0) == -1) {
20886d7f5d3SJohn Marino perror("setitimer");
20986d7f5d3SJohn Marino exit(errno);
21086d7f5d3SJohn Marino }
21186d7f5d3SJohn Marino #endif
21286d7f5d3SJohn Marino
21386d7f5d3SJohn Marino for (i = 0; !ticked; i++)
21486d7f5d3SJohn Marino if (*p == child) {
21586d7f5d3SJohn Marino e = 0;
21686d7f5d3SJohn Marino break;
21786d7f5d3SJohn Marino }
21886d7f5d3SJohn Marino
21986d7f5d3SJohn Marino if (e)
22086d7f5d3SJohn Marino fprintf(stderr,"Child never ran when it should have.\n");
22186d7f5d3SJohn Marino }
22286d7f5d3SJohn Marino
22386d7f5d3SJohn Marino exit(e);
22486d7f5d3SJohn Marino }
22586d7f5d3SJohn Marino
22686d7f5d3SJohn Marino #ifdef STANDALONE_TESTS
main(int argc,char * argv[])22786d7f5d3SJohn Marino int main(int argc, char *argv[]) { return fifo(argc, argv); }
22886d7f5d3SJohn Marino #endif
229