xref: /dflybsd-src/tools/regression/p1003_1b/yield.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
1*86d7f5d3SJohn Marino /*
2*86d7f5d3SJohn Marino  * Copyright (c) 1996-1999
3*86d7f5d3SJohn Marino  *	HD Associates, Inc.  All rights reserved.
4*86d7f5d3SJohn Marino  *
5*86d7f5d3SJohn Marino  * Redistribution and use in source and binary forms, with or without
6*86d7f5d3SJohn Marino  * modification, are permitted provided that the following conditions
7*86d7f5d3SJohn Marino  * are met:
8*86d7f5d3SJohn Marino  * 1. Redistributions of source code must retain the above copyright
9*86d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer.
10*86d7f5d3SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
11*86d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
12*86d7f5d3SJohn Marino  *    documentation and/or other materials provided with the distribution.
13*86d7f5d3SJohn Marino  * 3. All advertising materials mentioning features or use of this software
14*86d7f5d3SJohn Marino  *    must display the following acknowledgement:
15*86d7f5d3SJohn Marino  *	This product includes software developed by HD Associates, Inc
16*86d7f5d3SJohn Marino  * 4. Neither the name of the author nor the names of any co-contributors
17*86d7f5d3SJohn Marino  *    may be used to endorse or promote products derived from this software
18*86d7f5d3SJohn Marino  *    without specific prior written permission.
19*86d7f5d3SJohn Marino  *
20*86d7f5d3SJohn Marino  * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES AND CONTRIBUTORS ``AS IS'' AND
21*86d7f5d3SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22*86d7f5d3SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23*86d7f5d3SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE
24*86d7f5d3SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25*86d7f5d3SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26*86d7f5d3SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27*86d7f5d3SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28*86d7f5d3SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29*86d7f5d3SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30*86d7f5d3SJohn Marino  * SUCH DAMAGE.
31*86d7f5d3SJohn Marino  * $FreeBSD: src/tools/regression/p1003_1b/yield.c,v 1.1 2000/02/16 14:28:42 dufault Exp $
32*86d7f5d3SJohn Marino  * $DragonFly: src/tools/regression/p1003_1b/yield.c,v 1.3 2007/06/26 23:30:05 josepht Exp $
33*86d7f5d3SJohn Marino  *
34*86d7f5d3SJohn Marino  */
35*86d7f5d3SJohn Marino #include <sys/types.h>
36*86d7f5d3SJohn Marino #include <unistd.h>
37*86d7f5d3SJohn Marino #include <stdlib.h>
38*86d7f5d3SJohn Marino #include <stdio.h>
39*86d7f5d3SJohn Marino #include <errno.h>
40*86d7f5d3SJohn Marino #include <err.h>
41*86d7f5d3SJohn Marino #include <fcntl.h>
42*86d7f5d3SJohn Marino #include <sys/types.h>
43*86d7f5d3SJohn Marino #include <sys/mman.h>
44*86d7f5d3SJohn Marino #include <sys/sched.h>
45*86d7f5d3SJohn Marino #include <stdlib.h>
46*86d7f5d3SJohn Marino #include <sys/wait.h>
47*86d7f5d3SJohn Marino 
48*86d7f5d3SJohn Marino #include "prutil.h"
49*86d7f5d3SJohn Marino 
50*86d7f5d3SJohn Marino /* buzz: busy wait a random amount of time.
51*86d7f5d3SJohn Marino  */
buzz(int n)52*86d7f5d3SJohn Marino static void buzz(int n)
53*86d7f5d3SJohn Marino {
54*86d7f5d3SJohn Marino 	volatile int i;
55*86d7f5d3SJohn Marino 	int m = random() & 0x0ffff;
56*86d7f5d3SJohn Marino 	for (i = 0; i < m; i++)
57*86d7f5d3SJohn Marino 		;
58*86d7f5d3SJohn Marino }
59*86d7f5d3SJohn Marino 
60*86d7f5d3SJohn Marino /* Yield: Verify that "sched_yield" works for the FIFO case.
61*86d7f5d3SJohn Marino  * This runs several processes and verifies that the yield seems
62*86d7f5d3SJohn Marino  * to permit the next one on the ready queue to run.
63*86d7f5d3SJohn Marino  */
yield(int argc,char * argv[])64*86d7f5d3SJohn Marino int yield(int argc, char *argv[])
65*86d7f5d3SJohn Marino {
66*86d7f5d3SJohn Marino 	volatile int *p;
67*86d7f5d3SJohn Marino 	int i;
68*86d7f5d3SJohn Marino 	int nslaves, n;
69*86d7f5d3SJohn Marino 	int master, slave;
70*86d7f5d3SJohn Marino 	pid_t youngest = !0;	/* Our youngest child */
71*86d7f5d3SJohn Marino 	struct sched_param set, got;
72*86d7f5d3SJohn Marino 	int nloops = 1000;
73*86d7f5d3SJohn Marino 
74*86d7f5d3SJohn Marino 	errno = 0;
75*86d7f5d3SJohn Marino 
76*86d7f5d3SJohn Marino 	set.sched_priority = sched_get_priority_max(SCHED_FIFO);
77*86d7f5d3SJohn Marino 	if (set.sched_priority == -1 && errno) {
78*86d7f5d3SJohn Marino 		perror("sched_get_priority_max");
79*86d7f5d3SJohn Marino 		exit(errno);
80*86d7f5d3SJohn Marino 	}
81*86d7f5d3SJohn Marino 
82*86d7f5d3SJohn Marino 	if (argc == 1)
83*86d7f5d3SJohn Marino 		n = nslaves = 10;
84*86d7f5d3SJohn Marino 
85*86d7f5d3SJohn Marino 	else if (argc != 2) {
86*86d7f5d3SJohn Marino 		fprintf(stderr, "Usage: prog [n_instances]\n");
87*86d7f5d3SJohn Marino 		exit(-1);
88*86d7f5d3SJohn Marino 	}
89*86d7f5d3SJohn Marino 	else
90*86d7f5d3SJohn Marino 		n = nslaves = atoi(argv[1]);
91*86d7f5d3SJohn Marino 
92*86d7f5d3SJohn Marino 	p = (int *)mmap(0, sizeof(int),
93*86d7f5d3SJohn Marino 	PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED|MAP_INHERIT, -1, 0);
94*86d7f5d3SJohn Marino 
95*86d7f5d3SJohn Marino 	if (p == (int *)-1)
96*86d7f5d3SJohn Marino 		err(errno, "mmap");
97*86d7f5d3SJohn Marino 
98*86d7f5d3SJohn Marino 	*p = 0;
99*86d7f5d3SJohn Marino 
100*86d7f5d3SJohn Marino 	if (sched_setscheduler(0, SCHED_FIFO, &set) == -1)
101*86d7f5d3SJohn Marino 		err(errno, "sched_setscheduler");
102*86d7f5d3SJohn Marino 
103*86d7f5d3SJohn Marino 	/* I better still be SCHED_FIFO and RT_PRIO_MAX:
104*86d7f5d3SJohn Marino 	 */
105*86d7f5d3SJohn Marino 	(void)sched_is(__LINE__, &got, SCHED_FIFO);
106*86d7f5d3SJohn Marino 	if (got.sched_priority != set.sched_priority) {
107*86d7f5d3SJohn Marino 		fprintf(stderr, "line %d: scheduler screwup\n",
108*86d7f5d3SJohn Marino 		__LINE__);
109*86d7f5d3SJohn Marino 		exit(-1);
110*86d7f5d3SJohn Marino 	}
111*86d7f5d3SJohn Marino 
112*86d7f5d3SJohn Marino 	slave = 0;
113*86d7f5d3SJohn Marino 	master = 1;
114*86d7f5d3SJohn Marino 
115*86d7f5d3SJohn Marino 	/* Fork off the slaves.
116*86d7f5d3SJohn Marino 	 */
117*86d7f5d3SJohn Marino 	for (i = 0; i < nslaves; i++) {
118*86d7f5d3SJohn Marino 		if ((youngest = fork()) == 0) {
119*86d7f5d3SJohn Marino 			/* I better still be SCHED_FIFO and RT_PRIO_MAX:
120*86d7f5d3SJohn Marino 			 */
121*86d7f5d3SJohn Marino 			(void)sched_is(__LINE__, &got, SCHED_FIFO);
122*86d7f5d3SJohn Marino 
123*86d7f5d3SJohn Marino 			if (got.sched_priority != set.sched_priority) {
124*86d7f5d3SJohn Marino 				fprintf(stderr, "line %d: scheduler screwup\n",
125*86d7f5d3SJohn Marino 				__LINE__);
126*86d7f5d3SJohn Marino 				exit(-1);
127*86d7f5d3SJohn Marino 			}
128*86d7f5d3SJohn Marino 
129*86d7f5d3SJohn Marino 			master = 0;	/* I'm a slave */
130*86d7f5d3SJohn Marino 			slave = i + 1;	/* With this flag */
131*86d7f5d3SJohn Marino 			*p = slave;	/* And I live */
132*86d7f5d3SJohn Marino 			break;
133*86d7f5d3SJohn Marino 		}
134*86d7f5d3SJohn Marino 	}
135*86d7f5d3SJohn Marino 
136*86d7f5d3SJohn Marino 	if (master) {
137*86d7f5d3SJohn Marino 		/* If we conform the slave processes haven't run yet.
138*86d7f5d3SJohn Marino 		 * The master must yield to let the first slave run.
139*86d7f5d3SJohn Marino 		 */
140*86d7f5d3SJohn Marino 		if (*p != 0) {
141*86d7f5d3SJohn Marino 			fprintf(stderr,
142*86d7f5d3SJohn Marino 			"Error at line %d: Writer %d has run\n", __LINE__, *p);
143*86d7f5d3SJohn Marino 			exit(-1);
144*86d7f5d3SJohn Marino 		}
145*86d7f5d3SJohn Marino 	}
146*86d7f5d3SJohn Marino 
147*86d7f5d3SJohn Marino 	/* Now the master yields, the first slave runs, and yields,
148*86d7f5d3SJohn Marino 	 * next runs, yields, ...
149*86d7f5d3SJohn Marino 	 *
150*86d7f5d3SJohn Marino 	 * So the master should get through this first.
151*86d7f5d3SJohn Marino 	 */
152*86d7f5d3SJohn Marino 
153*86d7f5d3SJohn Marino 	if (sched_yield() == -1)
154*86d7f5d3SJohn Marino 		err(errno, "sched_yield");
155*86d7f5d3SJohn Marino 
156*86d7f5d3SJohn Marino 	if (master) {
157*86d7f5d3SJohn Marino 		int status;
158*86d7f5d3SJohn Marino 
159*86d7f5d3SJohn Marino 		/* The final slave process should be the last one started.
160*86d7f5d3SJohn Marino 		 */
161*86d7f5d3SJohn Marino 		if (*p != nslaves) {
162*86d7f5d3SJohn Marino 			fprintf(stderr,
163*86d7f5d3SJohn Marino 			"Error at line %d: Final slave is %d not %d.\n",
164*86d7f5d3SJohn Marino 			__LINE__, *p, nslaves);
165*86d7f5d3SJohn Marino 			exit(-1);
166*86d7f5d3SJohn Marino 		}
167*86d7f5d3SJohn Marino 
168*86d7f5d3SJohn Marino 		/* Wait for our youngest to exit:
169*86d7f5d3SJohn Marino 		 */
170*86d7f5d3SJohn Marino 		waitpid(youngest, &status, 0);
171*86d7f5d3SJohn Marino 
172*86d7f5d3SJohn Marino 		exit(WEXITSTATUS(status));	/* Let the slaves continue */
173*86d7f5d3SJohn Marino 	}
174*86d7f5d3SJohn Marino 
175*86d7f5d3SJohn Marino 	/* Now the first one has started up.
176*86d7f5d3SJohn Marino 	 */
177*86d7f5d3SJohn Marino 	for (i = 0; i < nloops; i++) {
178*86d7f5d3SJohn Marino 		if (((*p) % nslaves) !=
179*86d7f5d3SJohn Marino 		((slave + nslaves - 1) % nslaves)) {
180*86d7f5d3SJohn Marino 			fprintf(stderr, "%d ran before %d on iteration %d.\n",
181*86d7f5d3SJohn Marino 			*p, slave, i);
182*86d7f5d3SJohn Marino 			exit(-1);
183*86d7f5d3SJohn Marino 		}
184*86d7f5d3SJohn Marino 		*p = slave;
185*86d7f5d3SJohn Marino 
186*86d7f5d3SJohn Marino 		/* Delay some random amount of time.
187*86d7f5d3SJohn Marino 		 */
188*86d7f5d3SJohn Marino 		buzz(slave);
189*86d7f5d3SJohn Marino 
190*86d7f5d3SJohn Marino 		if (sched_yield() == -1)
191*86d7f5d3SJohn Marino 			err(errno, "sched_yield");
192*86d7f5d3SJohn Marino 	}
193*86d7f5d3SJohn Marino 
194*86d7f5d3SJohn Marino 	exit(0);
195*86d7f5d3SJohn Marino }
196*86d7f5d3SJohn Marino #ifdef STANDALONE_TESTS
main(int argc,char * argv[])197*86d7f5d3SJohn Marino int main(int argc, char *argv[]) { return yield(argc, argv); }
198*86d7f5d3SJohn Marino #endif
199