diff options
Diffstat (limited to 'tools/regression/p1003_1b/fifo.c')
| -rw-r--r-- | tools/regression/p1003_1b/fifo.c | 227 | 
1 files changed, 227 insertions, 0 deletions
| diff --git a/tools/regression/p1003_1b/fifo.c b/tools/regression/p1003_1b/fifo.c new file mode 100644 index 000000000000..614781f8d4fb --- /dev/null +++ b/tools/regression/p1003_1b/fifo.c @@ -0,0 +1,227 @@ +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (c) 1996 - 2000 + *	HD Associates, Inc.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by HD Associates, Inc + * 4. Neither the name of the author nor the names of any co-contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/time.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <sched.h> +#include <signal.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> + +volatile int ticked; +#define CAN_USE_ALARMS + +#ifdef CAN_USE_ALARMS +void tick(int arg) +{ +	ticked = 1; +} +#endif + +/* Fifo: Verify that fifo and round-robin scheduling seem to work. + * + * This tests: + * 1. That sched_rr_get_interval seems to work; + * 2. That FIFO scheduling doesn't seeem to be round-robin; + * 3. That round-robin scheduling seems to work. + *  + */ +static pid_t child; +static void tidyup(void) +{ +	if (child) +		kill(child, SIGHUP); +} + +static double +tvsub(const struct timeval *a, const struct timeval *b) +{ +	long sdiff; +	long udiff; + +	sdiff = a->tv_sec - b->tv_sec; +	udiff = a->tv_usec - b->tv_usec; + +	return (double)(sdiff * 1000000 + udiff) / 1e6; +} + +int fifo(int argc, char *argv[]) +{ +	int e = 0; +	volatile long *p, pid; +	int i; +	struct sched_param fifo_param; +	struct timespec interval; +#define MAX_RANAT 32 +	struct timeval ranat[MAX_RANAT]; + +#ifdef CAN_USE_ALARMS +	static struct itimerval itimerval; +#endif + +	/* What is the round robin interval? +	 */ + +	if (sched_rr_get_interval(0, &interval) == -1) { +		perror("sched_rr_get_interval"); +		exit(errno); +	} + +#ifdef CAN_USE_ALARMS +	signal(SIGALRM, tick); +#endif + +	fifo_param.sched_priority = 1; + +	p = (long *)mmap(0, sizeof(*p), +	PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0); + +	if (p == (long *)-1) +		err(errno, "mmap"); + +	*p = 0; + +	if (sched_setscheduler(0, SCHED_FIFO, &fifo_param) == -1) +	{ +		perror("sched_setscheduler"); +		return -1; +	} + +	pid = getpid(); + +	if ((child = fork()) == 0) +	{ +		/* Child process.  Just keep setting the pointer to our +		 * PID.  The parent will kill us when it wants to. +		 */ + +		pid = getpid(); +		while (1) +			*p = pid; +	} +	else +	{ +		atexit(tidyup); +		*p = pid; + + +		ticked = 0; + +#ifdef CAN_USE_ALARMS +		/* Set an alarm for 250 times the round-robin interval. +		 * Then we will verify that a similar priority process +		 * will not run when we are using the FIFO scheduler. +		 */ +		itimerval.it_value.tv_usec = interval.tv_nsec / (1000 / 250); + +		itimerval.it_value.tv_sec = itimerval.it_value.tv_usec / 1000000; +		itimerval.it_value.tv_usec %= 1000000; + + +		if (setitimer(ITIMER_REAL, &itimerval, 0) == -1) { +			perror("setitimer"); +			exit(errno); +		} +#endif + + +		gettimeofday(ranat, 0); +		i = 1; +		while (!ticked && i < MAX_RANAT) +			if (*p == child) { +				gettimeofday(ranat + i, 0); +				*p = 0; +				e = -1; +				i++; +			} + +		if (e) { +			int j; + +			fprintf(stderr, +			"SCHED_FIFO had erroneous context switches:\n"); +			for (j = 1; j < i; j++) { +				fprintf(stderr, "%d %g\n", j, +					tvsub(ranat + j, ranat + j - 1)); +			} +			return e; +		} + +		/* Switch to the round robin scheduler and the child +		 * should run within twice the interval. +		 */ +		if (sched_setscheduler(child, SCHED_RR, &fifo_param) == -1 || +		sched_setscheduler(0, SCHED_RR, &fifo_param) == -1) +		{ +			perror("sched_setscheduler"); +			return -1; +		} + +		e = -1; + +		ticked = 0; + +#ifdef CAN_USE_ALARMS + +		/* Now we do want to see it run.  But only set +		 * the alarm for twice the interval: +		 */ +		itimerval.it_value.tv_usec = interval.tv_nsec / 500; + +		if (setitimer(ITIMER_REAL, &itimerval, 0) == -1) { +			perror("setitimer"); +			exit(errno); +		} +#endif + +		for (i = 0; !ticked; i++) +			if (*p == child) { +				e = 0; +				break; +			} + +		if (e) +			fprintf(stderr,"Child never ran when it should have.\n"); +	} + +	exit(e); +} + +#ifdef STANDALONE_TESTS +int main(int argc, char *argv[]) { return fifo(argc, argv); } +#endif | 
