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