mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-16 15:11:52 +00:00
These are regression tests for the P1003.1B scheduler.
Approved by: jkh
This commit is contained in:
parent
c24e264a76
commit
e5f1b1b180
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=57257
@ -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
|
||||
|
17
tools/regression/p1003_1b/Makefile
Normal file
17
tools/regression/p1003_1b/Makefile
Normal 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>
|
14
tools/regression/p1003_1b/README
Normal file
14
tools/regression/p1003_1b/README
Normal 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
|
227
tools/regression/p1003_1b/fifo.c
Normal file
227
tools/regression/p1003_1b/fifo.c
Normal 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
|
78
tools/regression/p1003_1b/main.c
Normal file
78
tools/regression/p1003_1b/main.c
Normal 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);
|
||||
}
|
91
tools/regression/p1003_1b/memlock.c
Normal file
91
tools/regression/p1003_1b/memlock.c
Normal 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
|
65
tools/regression/p1003_1b/p26.c
Normal file
65
tools/regression/p1003_1b/p26.c
Normal 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
|
61
tools/regression/p1003_1b/prutil.c
Normal file
61
tools/regression/p1003_1b/prutil.c
Normal 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, ¶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;
|
||||
}
|
14
tools/regression/p1003_1b/prutil.h
Normal file
14
tools/regression/p1003_1b/prutil.h
Normal 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_ */
|
294
tools/regression/p1003_1b/sched.c
Normal file
294
tools/regression/p1003_1b/sched.c
Normal 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
|
197
tools/regression/p1003_1b/yield.c
Normal file
197
tools/regression/p1003_1b/yield.c
Normal 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
|
Loading…
Reference in New Issue
Block a user