These are regression tests for the P1003.1B scheduler.

Approved by:	jkh
This commit is contained in:
Peter Dufault 2000-02-16 14:28:42 +00:00
parent c24e264a76
commit e5f1b1b180
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=57257
11 changed files with 1061 additions and 0 deletions

View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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

View File

@ -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