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