diff options
-rw-r--r-- | tools/regression/README | 3 | ||||
-rw-r--r-- | tools/regression/p1003_1b/Makefile | 17 | ||||
-rw-r--r-- | tools/regression/p1003_1b/README | 14 | ||||
-rw-r--r-- | tools/regression/p1003_1b/fifo.c | 227 | ||||
-rw-r--r-- | tools/regression/p1003_1b/main.c | 78 | ||||
-rw-r--r-- | tools/regression/p1003_1b/memlock.c | 91 | ||||
-rw-r--r-- | tools/regression/p1003_1b/p26.c | 65 | ||||
-rw-r--r-- | tools/regression/p1003_1b/prutil.c | 61 | ||||
-rw-r--r-- | tools/regression/p1003_1b/prutil.h | 14 | ||||
-rw-r--r-- | tools/regression/p1003_1b/sched.c | 294 | ||||
-rw-r--r-- | tools/regression/p1003_1b/yield.c | 197 |
11 files changed, 1061 insertions, 0 deletions
diff --git a/tools/regression/README b/tools/regression/README index d2a92ed..bf131e6 100644 --- a/tools/regression/README +++ b/tools/regression/README @@ -1,3 +1,5 @@ +$FreeBSD$ + This directory is for regression test programs. A regression test program is one that will exercise a particular bit of the @@ -6,3 +8,4 @@ system to check that we have not reintroduced an old bug. Please make a subdir per program, and add a brief description to this file. nfsmmap Some tests to exercise some tricky cases in NFS and mmap +p1003_1b Exercise 1003.1B scheduler diff --git a/tools/regression/p1003_1b/Makefile b/tools/regression/p1003_1b/Makefile new file mode 100644 index 0000000..66b0be5 --- /dev/null +++ b/tools/regression/p1003_1b/Makefile @@ -0,0 +1,17 @@ +# $FreeBSD$ + +PROG=p1003_1b + +SRCS=\ + fifo.c \ + main.c \ + memlock.c \ + prutil.c \ + p26.c \ + sched.c \ + yield.c + +NOMAN=1 + +COPTS+=-DNO_MEMLOCK +.include <bsd.prog.mk> diff --git a/tools/regression/p1003_1b/README b/tools/regression/p1003_1b/README new file mode 100644 index 0000000..e0b7037 --- /dev/null +++ b/tools/regression/p1003_1b/README @@ -0,0 +1,14 @@ +$FreeBSD$ + +p1003_1b: Regression tests for the scheduling facilities. +The following should always work as of the release of 4.0: + +p1003_1b fifo : Check that the FIFO scheduler seems to work. +p1003_1b p26 : Check that we support the expected features. +p1003_1b sched: Check that schedule switching seems to work. +p1003_1b yield: Check that yielding runs the expected process. + +As of today "p1003_1b yield" doesn't work. I have a minimal set +of patches I'm waiting for approval to commit. + +Peter dufault@freebsd.org diff --git a/tools/regression/p1003_1b/fifo.c b/tools/regression/p1003_1b/fifo.c new file mode 100644 index 0000000..455f7f9 --- /dev/null +++ b/tools/regression/p1003_1b/fifo.c @@ -0,0 +1,227 @@ +/* + * 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. + * + * $FreeBSD$ + */ +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <err.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/time.h> +#include <sched.h> +#include <signal.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|MAP_INHERIT, -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 diff --git a/tools/regression/p1003_1b/main.c b/tools/regression/p1003_1b/main.c new file mode 100644 index 0000000..0e87c6c --- /dev/null +++ b/tools/regression/p1003_1b/main.c @@ -0,0 +1,78 @@ +/* $FreeBSD$ */ +#include <stdio.h> + +int fifo(int argc, char *argv[]); +int memlock(int argc, char *argv[]); +int p26(int argc, char *argv[]); +int sched(int argc, char *argv[]); +int yield(int argc, char *argv[]); + +static struct { + const char *t; + int (*f)(int, char *[]); + int works; +} tab[] = { + { "fifo", fifo, 1 }, + { "memlock", memlock, 0 }, + { "p26", p26, 1 }, + { "sched", sched, 1 }, + { "yield", yield, 1 }, +}; + +#define N(T) (sizeof (T)/ sizeof(T[0])) + +static int usage(int argc, char *argv[]) +{ + int i; + if (argc > 1) + fprintf(stderr, "%s is unknown\n", argv[1]); + + fprintf(stderr, "usage: %s [-a] or one of [", argv[0]); + for (i = 0; i < (sizeof(tab) / sizeof(tab[0])); i++) + fprintf(stderr, "%s%s", (i)? " | " : "", tab[i].t); + fprintf(stderr, "]\n"); + + return -1; +} + +int main(int argc, char *argv[]) +{ + int i; + + if (argc == 2 && strcmp(argv[1], "-a") == 0) { +#if 1 + fprintf(stderr, + "-a should but doesn't really work" + " (my notes say \"because things detach\");\n" + "meanwhile do these individual tests and look" + " for a non-zero exit code:\n"); + for (i = 0; i < N(tab); i++) + if (tab[i].works) + fprintf(stderr, "p1003_1b %s\n", tab[i].t); + return -1; +#else + { + int r; + for (i = 0; i < N(tab); i++) { + if (tab[i].works) { + if ( (r = + (*tab[i].f)(argc - 1, argv + 1)) ) { + fprintf(stderr, + "%s failed\n", tab[i].t); + return r; + } + } + } + return 0; + } +#endif + } + + if (argc > 1) { + for (i = 0; i < N(tab); i++) + if (strcmp(tab[i].t, argv[1]) == 0) + return (*tab[i].f)(argc - 1, argv + 1); + } + + return usage(argc, argv); +} diff --git a/tools/regression/p1003_1b/memlock.c b/tools/regression/p1003_1b/memlock.c new file mode 100644 index 0000000..b55b405 --- /dev/null +++ b/tools/regression/p1003_1b/memlock.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 1996 - 1999 + * 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. + * + * $FreeBSD$ + */ +#include <unistd.h> +#include <stdio.h> +#include <errno.h> +#include <sys/mman.h> + +#include "prutil.h" + +int memlock(int argc, char *argv[]) +{ + int e = 0; + + /* Is memory locking configured? + */ + errno = 0; + if (sysconf(_SC_MEMLOCK) == -1) { + if (errno != 0) { + /* This isn't valid - may be a standard violation + */ + quit("(should not happen) sysconf(_SC_MEMLOCK)"); + } + else { + fprintf(stderr, + "Memory locking is not supported in this environment.\n"); + e = -1; + } + } + + /* Lock yourself in memory: + */ + if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) { + perror("mlockall(MCL_CURRENT | MCL_FUTURE)"); + e = errno; + } + else if (munlockall() == -1) { + perror("munlockall"); + e = errno; + } + + return e; +} + +#ifdef NO_MEMLOCK +int mlockall(int flags) +{ + return EOPNOTSUPP; +} + +int munlockall(void) +{ + return EOPNOTSUPP; +} + + +#endif + +#ifdef STANDALONE_TESTS +int main(int argc, char *argv[]) { return memlock(argc, argv); } +#endif diff --git a/tools/regression/p1003_1b/p26.c b/tools/regression/p1003_1b/p26.c new file mode 100644 index 0000000..538deaf --- /dev/null +++ b/tools/regression/p1003_1b/p26.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 1996-1999 + * 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. + * + * $FreeBSD$ + */ +#define _POSIX_SOURCE +#define _POSIX_C_SOURCE 199309L +#include <unistd.h> +#include <stdio.h> + +int p26(int ac, char *av[]) +{ + int ret = 0; + + #ifndef _POSIX_VERSION + printf("POSIX is not supported.\n"); + ret = -1; + #else /* _POSIX_VERSION */ + + #if (_POSIX_VERSION == 198808L) + printf("POSIX.1 is supported but not POSIX.1B (FIPS 151-1)\n"); + #elif (_POSIX_VERSION == 199009L) + printf("POSIX.1 is supported but not POSIX.1B (FIPS 151-2)\n"); + #elif (_POSIX_VERSION >= 199309L) + printf("POSIX.1 and POSIX.1B are supported.\n"); + #else + printf("_POSIX_VERSION (%ld) not 198808, 199009, or >= 199309.\n", + _POSIX_VERSION); + ret = -1; + #endif + + #endif /* _POSIX_VERSION */ + return ret; +} +#ifdef STANDALONE_TESTS +int main(int argc, char *argv[]) { return p26(argc, argv); } +#endif diff --git a/tools/regression/p1003_1b/prutil.c b/tools/regression/p1003_1b/prutil.c new file mode 100644 index 0000000..e0e3d6f --- /dev/null +++ b/tools/regression/p1003_1b/prutil.c @@ -0,0 +1,61 @@ +#include <errno.h> +#include <unistd.h> +#include <sched.h> +#include <stdio.h> + +#include <err.h> +#include <sysexits.h> +#include "prutil.h" + +/* + * $FreeBSD$ + */ +void quit(const char *text) +{ + err(errno, text); +} + +char *sched_text(int scheduler) +{ + switch(scheduler) + { + case SCHED_FIFO: + return "SCHED_FIFO"; + + case SCHED_RR: + return "SCHED_RR"; + + case SCHED_OTHER: + return "SCHED_OTHER"; + + default: + return "Illegal scheduler value"; + } +} + +int sched_is(int line, struct sched_param *p, int shouldbe) +{ + int scheduler; + struct sched_param param; + + /* What scheduler are we running now? + */ + errno = 0; + scheduler = sched_getscheduler(0); + if (sched_getparam(0, ¶m)) + quit("sched_getparam"); + + if (p) + *p = param; + + if (shouldbe != -1 && scheduler != shouldbe) + { + fprintf(stderr, + "At line %d the scheduler should be %s yet it is %s.\n", + line, sched_text(shouldbe), sched_text(scheduler)); + + exit(-1); + } + + return scheduler; +} diff --git a/tools/regression/p1003_1b/prutil.h b/tools/regression/p1003_1b/prutil.h new file mode 100644 index 0000000..3387b99 --- /dev/null +++ b/tools/regression/p1003_1b/prutil.h @@ -0,0 +1,14 @@ +#ifndef _PRUTIL_H_ +#define _PRUTIL_H_ + +/* + * $FreeBSD$ + */ + +struct sched_param; + +void quit(const char *); +char *sched_text(int); +int sched_is(int line, struct sched_param *, int); + +#endif /* _PRUTIL_H_ */ diff --git a/tools/regression/p1003_1b/sched.c b/tools/regression/p1003_1b/sched.c new file mode 100644 index 0000000..bd978f8 --- /dev/null +++ b/tools/regression/p1003_1b/sched.c @@ -0,0 +1,294 @@ +/* + * Copyright (c) 1996-1999 + * 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. + * $FreeBSD$ + * + */ + +/* XXX: The spec says that if _POSIX_C_SOURCE is defined then + * _POSIX_SOURCE is ignored. However, this is similar to + * the code in the O'Reilly "POSIX.4" book + */ + +#define _POSIX_VERSION 199309L +#define _POSIX_SOURCE +#define _POSIX_C_SOURCE 199309L + +#include <unistd.h> +#include <stdlib.h> + +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/mman.h> + +#include <sched.h> + +#include "prutil.h" + +static FILE *verbose; + +static void +checkpris(int sched) +{ + int smin; + int smax; + + errno = 0; + + if ( (smin = sched_get_priority_min(sched)) == -1 && errno) + quit("sched_get_priority_min"); + + if ( (smax = sched_get_priority_max(sched)) == -1 && errno) + quit("sched_get_priority_max"); + + if (smax - smin + 1 < 32 || smax < smin) { + fprintf(stderr, "Illegal priority range for %s: %d to %d\n", + sched_text(sched), smin, smax); + exit(-1); + } + + if (verbose) + fprintf(verbose, "%12s: sched_min %2d sched_max %2d\n", + sched_text(sched), smin, smax); +} + +/* Set "try_anyway" to quit if you don't want to go on when + * it doesn't look like something should work. + */ +static void try_anyway(const char *s) +{ + fputs(s, stderr); + fprintf(stderr, "(trying anyway)\n"); + errno = 0; +} + +static void q(int line, int code, const char *text) +{ + if (code == -1) + { + fprintf(stderr, "Error at line %d:\n", line); + perror(text); + exit(errno); + } +} + +int sched(int ac, char *av[]) +{ + int fifo_schedmin, fifo_schedmax; + int i; + struct sched_param rt_param; + int n_instances = 10; + int sched; + + verbose = 0; + +#if _POSIX_VERSION < 199309 + try_anyway("The _POSIX_VERSION predates P1003.1B\n"); +#endif + +#if !defined(_POSIX_PRIORITY_SCHEDULING) + try_anyway( + "The environment does not claim to support Posix scheduling.\n"); +#endif + + /* Is priority scheduling configured? + */ + errno = 0; + if (sysconf(_SC_PRIORITY_SCHEDULING) == -1) { + if (errno != 0) { + /* This isn't valid - may be a standard violation + */ + quit("(should not happen) sysconf(_SC_PRIORITY_SCHEDULING)"); + } + else { + try_anyway( + "The environment does not have run-time " + "support for Posix scheduling.\n"); + } + } + + /* Check that the priorities seem reasonable. + */ + + checkpris(SCHED_FIFO); + checkpris(SCHED_RR); + checkpris(SCHED_OTHER); + +/* BSD extensions? + */ +#if defined(SCHED_IDLE) + checkpris(SCHED_IDLE); +#endif + + fifo_schedmin = sched_get_priority_min(SCHED_FIFO); + fifo_schedmax = sched_get_priority_max(SCHED_FIFO); + + /* Make sure we can do some basic schedule switching: + */ + { + struct sched_param orig_param, shouldbe; + int orig_scheduler = sched_is(__LINE__, &orig_param, -1); + + if (verbose) + fprintf(verbose, + "The original scheduler is %s and the priority is %d.\n", + sched_text(orig_scheduler), orig_param.sched_priority); + + /* Basic check: Try to set current settings: + */ + q(__LINE__, sched_setscheduler(0, orig_scheduler, &orig_param), + "sched_setscheduler: Can't set original scheduler"); + + rt_param.sched_priority = fifo_schedmin; + + q(__LINE__, sched_setscheduler(0, SCHED_FIFO, &rt_param), + "sched_setscheduler SCHED_FIFO"); + + (void)sched_is(__LINE__, 0, SCHED_FIFO); + + q(__LINE__, sched_getparam(0, &shouldbe), "sched_getparam"); + + if (shouldbe.sched_priority != fifo_schedmin) + quit("sched_setscheduler wrong priority (min)"); + + rt_param.sched_priority = fifo_schedmin; + + q(__LINE__, sched_setparam(0, &rt_param), + "sched_setparam to fifo_schedmin"); + + rt_param.sched_priority = fifo_schedmin + 1; + + q(__LINE__, sched_setparam(0, &rt_param), + "sched_setparam to fifo_schedmin + 1"); + + q(__LINE__, sched_getparam(0, &shouldbe), + "sched_getparam"); + + if (shouldbe.sched_priority != fifo_schedmin + 1) + quit("sched_setscheduler wrong priority (min + 1)"); + + q(__LINE__, sched_setscheduler(0, SCHED_RR, &rt_param), + "sched_setscheduler SCHED_RR"); + + (void)sched_is(__LINE__, 0, SCHED_RR); + + q(__LINE__, sched_setscheduler(0, orig_scheduler, &orig_param), + "sched_setscheduler restoring original scheduler"); + + (void)sched_is(__LINE__, 0, orig_scheduler); + } + + + { +#define NAM "P1003_1b_schedXXXX" + char nam[L_tmpnam]; + int fd; + pid_t p; + pid_t *lastrun; + + strcpy(nam, NAM); + if (tmpnam(nam) != nam) + q(__LINE__, errno, "tmpnam " NAM); + q(__LINE__, (fd = open(nam, O_RDWR|O_CREAT, 0666)), + "open " NAM); + + (void)unlink(nam); + + p = (pid_t)0; + + write(fd, &p, sizeof(p)); + + q(__LINE__, (int)(lastrun = mmap(0, sizeof(*lastrun), PROT_READ|PROT_WRITE, + MAP_SHARED, fd, 0)), "mmap"); + + /* Set our priority at the highest: + */ + sched = SCHED_FIFO; + rt_param.sched_priority = fifo_schedmax; + q(__LINE__, sched_setscheduler(0, sched, &rt_param), + "sched_setscheduler sched"); + + for (i = 0; i < n_instances; i++) + { + pid_t me; + + /* XXX This is completely bogus. The children never run. + */ + if ((me = fork()) != 0) + { + /* Parent. + */ + (void)sched_is(__LINE__, 0, sched); + + /* Lower our priority: + */ + rt_param.sched_priority--; + + q(__LINE__, sched_setscheduler(0, sched, &rt_param), + "sched_setscheduler sched"); + + while (1) + { + q(__LINE__, sched_getparam(0, &rt_param), "sched_getparam"); + + rt_param.sched_priority--; + + + if (rt_param.sched_priority < fifo_schedmin) + exit(0); + + *lastrun = me; + q(__LINE__, sched_setparam(0, &rt_param), "sched_setparam"); + + if (*lastrun == me) + { + /* The child will run twice + * at the end: + */ + if (!me || rt_param.sched_priority != 0) + { + fprintf(stderr, + "ran process %ld twice at priority %d\n", + (long)me, rt_param.sched_priority + 1); + exit(-1); + } + } + } + } + } + } + + return 0; +} +#ifdef STANDALONE_TESTS +int main(int argc, char *argv[]) { return sched(argc, argv); } +#endif diff --git a/tools/regression/p1003_1b/yield.c b/tools/regression/p1003_1b/yield.c new file mode 100644 index 0000000..b664513 --- /dev/null +++ b/tools/regression/p1003_1b/yield.c @@ -0,0 +1,197 @@ +/* + * Copyright (c) 1996-1999 + * 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. + * $FreeBSD$ + * + */ +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <err.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <sched.h> +#include <stdlib.h> +#include <sys/wait.h> + +#include "prutil.h" + +/* buzz: busy wait a random amount of time. + */ +static void buzz(int n) +{ + volatile int i; + int m = random() & 0x0ffff; + for (i = 0; i < m; i++) + ; +} + +/* Yield: Verify that "sched_yield" works for the FIFO case. + * This runs several processes and verifies that the yield seems + * to permit the next one on the ready queue to run. + */ +int yield(int argc, char *argv[]) +{ + volatile int *p; + int i; + int nslaves, n; + int master, slave; + pid_t youngest = !0; /* Our youngest child */ + struct sched_param set, got; + int nloops = 1000; + + errno = 0; + + set.sched_priority = sched_get_priority_max(SCHED_FIFO); + if (set.sched_priority == -1 && errno) { + perror("sched_get_priority_max"); + exit(errno); + } + + if (argc == 1) + n = nslaves = 10; + + else if (argc != 2) { + fprintf(stderr, "Usage: prog [n_instances]\n"); + exit(-1); + } + else + n = nslaves = atoi(argv[1]); + + p = (int *)mmap(0, sizeof(int), + PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED|MAP_INHERIT, -1, 0); + + if (p == (int *)-1) + err(errno, "mmap"); + + *p = 0; + + if (sched_setscheduler(0, SCHED_FIFO, &set) == -1) + err(errno, "sched_setscheduler"); + + /* I better still be SCHED_FIFO and RT_PRIO_MAX: + */ + (void)sched_is(__LINE__, &got, SCHED_FIFO); + if (got.sched_priority != set.sched_priority) { + fprintf(stderr, "line %d: scheduler screwup\n", + __LINE__); + exit(-1); + } + + slave = 0; + master = 1; + + /* Fork off the slaves. + */ + for (i = 0; i < nslaves; i++) { + if ((youngest = fork()) == 0) { + /* I better still be SCHED_FIFO and RT_PRIO_MAX: + */ + (void)sched_is(__LINE__, &got, SCHED_FIFO); + + if (got.sched_priority != set.sched_priority) { + fprintf(stderr, "line %d: scheduler screwup\n", + __LINE__); + exit(-1); + } + + master = 0; /* I'm a slave */ + slave = i + 1; /* With this flag */ + *p = slave; /* And I live */ + break; + } + } + + if (master) { + /* If we conform the slave processes haven't run yet. + * The master must yield to let the first slave run. + */ + if (*p != 0) { + fprintf(stderr, + "Error at line %d: Writer %d has run\n", __LINE__, *p); + exit(-1); + } + } + + /* Now the master yields, the first slave runs, and yields, + * next runs, yields, ... + * + * So the master should get through this first. + */ + + if (sched_yield() == -1) + err(errno, "sched_yield"); + + if (master) { + int status; + + /* The final slave process should be the last one started. + */ + if (*p != nslaves) { + fprintf(stderr, + "Error at line %d: Final slave is %d not %d.\n", + __LINE__, *p, nslaves); + exit(-1); + } + + /* Wait for our youngest to exit: + */ + waitpid(youngest, &status, 0); + + exit(WEXITSTATUS(status)); /* Let the slaves continue */ + } + + /* Now the first one has started up. + */ + for (i = 0; i < nloops; i++) { + if (((*p) % nslaves) != + ((slave + nslaves - 1) % nslaves)) { + fprintf(stderr, "%d ran before %d on iteration %d.\n", + *p, slave, i); + exit(-1); + } + *p = slave; + + /* Delay some random amount of time. + */ + buzz(slave); + + if (sched_yield() == -1) + err(errno, "sched_yield"); + } + + exit(0); +} +#ifdef STANDALONE_TESTS +int main(int argc, char *argv[]) { return yield(argc, argv); } +#endif |