summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authordufault <dufault@FreeBSD.org>2000-02-16 14:28:42 +0000
committerdufault <dufault@FreeBSD.org>2000-02-16 14:28:42 +0000
commitbe90ff87f364b1ba7de2ef0d814ff95c7b8f5e5e (patch)
tree7ff91386cdefb9fd07cfb62fb6aa61636022da5a /tools
parent2a4aa09c50640c7c267e0913c1a32a6de864f33b (diff)
downloadFreeBSD-src-be90ff87f364b1ba7de2ef0d814ff95c7b8f5e5e.zip
FreeBSD-src-be90ff87f364b1ba7de2ef0d814ff95c7b8f5e5e.tar.gz
These are regression tests for the P1003.1B scheduler.
Approved by: jkh
Diffstat (limited to 'tools')
-rw-r--r--tools/regression/README3
-rw-r--r--tools/regression/p1003_1b/Makefile17
-rw-r--r--tools/regression/p1003_1b/README14
-rw-r--r--tools/regression/p1003_1b/fifo.c227
-rw-r--r--tools/regression/p1003_1b/main.c78
-rw-r--r--tools/regression/p1003_1b/memlock.c91
-rw-r--r--tools/regression/p1003_1b/p26.c65
-rw-r--r--tools/regression/p1003_1b/prutil.c61
-rw-r--r--tools/regression/p1003_1b/prutil.h14
-rw-r--r--tools/regression/p1003_1b/sched.c294
-rw-r--r--tools/regression/p1003_1b/yield.c197
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, &param))
+ 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
OpenPOWER on IntegriCloud