1210284Sjmallett/*- 2232812Sjmallett * SPDX-License-Identifier: BSD-4-Clause 3215990Sjmallett * 4210284Sjmallett * Copyright (c) 1996-1999 5210284Sjmallett * HD Associates, Inc. All rights reserved. 6215990Sjmallett * 7215990Sjmallett * Redistribution and use in source and binary forms, with or without 8215990Sjmallett * modification, are permitted provided that the following conditions 9210284Sjmallett * are met: 10215990Sjmallett * 1. Redistributions of source code must retain the above copyright 11215990Sjmallett * notice, this list of conditions and the following disclaimer. 12210284Sjmallett * 2. Redistributions in binary form must reproduce the above copyright 13215990Sjmallett * notice, this list of conditions and the following disclaimer in the 14215990Sjmallett * documentation and/or other materials provided with the distribution. 15215990Sjmallett * 3. All advertising materials mentioning features or use of this software 16215990Sjmallett * must display the following acknowledgement: 17215990Sjmallett * This product includes software developed by HD Associates, Inc 18232812Sjmallett * 4. Neither the name of the author nor the names of any co-contributors 19215990Sjmallett * may be used to endorse or promote products derived from this software 20215990Sjmallett * without specific prior written permission. 21215990Sjmallett * 22215990Sjmallett * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES AND CONTRIBUTORS ``AS IS'' AND 23215990Sjmallett * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24215990Sjmallett * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25215990Sjmallett * ARE DISCLAIMED. IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE 26215990Sjmallett * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27215990Sjmallett * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28215990Sjmallett * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29232812Sjmallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30215990Sjmallett * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31215990Sjmallett * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32215990Sjmallett * SUCH DAMAGE. 33215990Sjmallett * 34215990Sjmallett */ 35215990Sjmallett#include <sys/types.h> 36215990Sjmallett#include <unistd.h> 37215990Sjmallett#include <stdlib.h> 38210284Sjmallett#include <stdio.h> 39210284Sjmallett#include <errno.h> 40210284Sjmallett#include <err.h> 41210284Sjmallett#include <fcntl.h> 42210284Sjmallett#include <sys/types.h> 43210284Sjmallett#include <sys/mman.h> 44210284Sjmallett#include <sched.h> 45215990Sjmallett#include <stdlib.h> 46210284Sjmallett#include <sys/wait.h> 47210284Sjmallett 48210284Sjmallett#include "prutil.h" 49210284Sjmallett 50210284Sjmallett/* buzz: busy wait a random amount of time. 51210284Sjmallett */ 52210284Sjmallettstatic void buzz(int n) 53210284Sjmallett{ 54232812Sjmallett volatile int i; 55210284Sjmallett int m = random() & 0x0ffff; 56210284Sjmallett for (i = 0; i < m; i++) 57210284Sjmallett ; 58210284Sjmallett} 59210284Sjmallett 60210284Sjmallett/* Yield: Verify that "sched_yield" works for the FIFO case. 61210284Sjmallett * This runs several processes and verifies that the yield seems 62210284Sjmallett * to permit the next one on the ready queue to run. 63210284Sjmallett */ 64210284Sjmallettint yield(int argc, char *argv[]) 65210284Sjmallett{ 66210284Sjmallett volatile int *p; 67210284Sjmallett int i; 68210284Sjmallett int nslaves, n; 69210284Sjmallett int master, slave; 70210284Sjmallett pid_t youngest = !0; /* Our youngest child */ 71210284Sjmallett struct sched_param set, got; 72210284Sjmallett int nloops = 1000; 73210284Sjmallett 74210284Sjmallett errno = 0; 75210284Sjmallett 76210284Sjmallett set.sched_priority = sched_get_priority_max(SCHED_FIFO); 77210284Sjmallett if (set.sched_priority == -1 && errno) { 78210284Sjmallett perror("sched_get_priority_max"); 79210284Sjmallett exit(errno); 80210284Sjmallett } 81210284Sjmallett 82210284Sjmallett if (argc == 1) 83210284Sjmallett n = nslaves = 10; 84210284Sjmallett 85210284Sjmallett else if (argc != 2) { 86210284Sjmallett fprintf(stderr, "usage: prog [n_instances]\n"); 87210284Sjmallett exit(-1); 88210284Sjmallett } 89210284Sjmallett else 90210284Sjmallett n = nslaves = atoi(argv[1]); 91210284Sjmallett 92210284Sjmallett p = (int *)mmap(0, sizeof(int), 93210284Sjmallett PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0); 94210284Sjmallett 95210284Sjmallett if (p == (int *)-1) 96210284Sjmallett err(errno, "mmap"); 97210284Sjmallett 98210284Sjmallett *p = 0; 99210284Sjmallett 100210284Sjmallett if (sched_setscheduler(0, SCHED_FIFO, &set) == -1) 101210284Sjmallett err(errno, "sched_setscheduler"); 102210284Sjmallett 103210284Sjmallett /* I better still be SCHED_FIFO and RT_PRIO_MAX: 104210284Sjmallett */ 105210284Sjmallett (void)sched_is(__LINE__, &got, SCHED_FIFO); 106210284Sjmallett if (got.sched_priority != set.sched_priority) { 107210284Sjmallett fprintf(stderr, "line %d: scheduler screwup\n", 108210284Sjmallett __LINE__); 109210284Sjmallett exit(-1); 110210284Sjmallett } 111210284Sjmallett 112210284Sjmallett slave = 0; 113210284Sjmallett master = 1; 114210284Sjmallett 115210284Sjmallett /* Fork off the slaves. 116210284Sjmallett */ 117210284Sjmallett for (i = 0; i < nslaves; i++) { 118210284Sjmallett if ((youngest = fork()) == 0) { 119210284Sjmallett /* I better still be SCHED_FIFO and RT_PRIO_MAX: 120210284Sjmallett */ 121210284Sjmallett (void)sched_is(__LINE__, &got, SCHED_FIFO); 122210284Sjmallett 123210284Sjmallett if (got.sched_priority != set.sched_priority) { 124210284Sjmallett fprintf(stderr, "line %d: scheduler screwup\n", 125210284Sjmallett __LINE__); 126210284Sjmallett exit(-1); 127210284Sjmallett } 128210284Sjmallett 129210284Sjmallett master = 0; /* I'm a slave */ 130210284Sjmallett slave = i + 1; /* With this flag */ 131210284Sjmallett *p = slave; /* And I live */ 132210284Sjmallett break; 133210284Sjmallett } 134210284Sjmallett } 135 136 if (master) { 137 /* If we conform the slave processes haven't run yet. 138 * The master must yield to let the first slave run. 139 */ 140 if (*p != 0) { 141 fprintf(stderr, 142 "Error at line %d: Writer %d has run\n", __LINE__, *p); 143 exit(-1); 144 } 145 } 146 147 /* Now the master yields, the first slave runs, and yields, 148 * next runs, yields, ... 149 * 150 * So the master should get through this first. 151 */ 152 153 if (sched_yield() == -1) 154 err(errno, "sched_yield"); 155 156 if (master) { 157 int status; 158 159 /* The final slave process should be the last one started. 160 */ 161 if (*p != nslaves) { 162 fprintf(stderr, 163 "Error at line %d: Final slave is %d not %d.\n", 164 __LINE__, *p, nslaves); 165 exit(-1); 166 } 167 168 /* Wait for our youngest to exit: 169 */ 170 waitpid(youngest, &status, 0); 171 172 exit(WEXITSTATUS(status)); /* Let the slaves continue */ 173 } 174 175 /* Now the first one has started up. 176 */ 177 for (i = 0; i < nloops; i++) { 178 if (((*p) % nslaves) != 179 ((slave + nslaves - 1) % nslaves)) { 180 fprintf(stderr, "%d ran before %d on iteration %d.\n", 181 *p, slave, i); 182 exit(-1); 183 } 184 *p = slave; 185 186 /* Delay some random amount of time. 187 */ 188 buzz(slave); 189 190 if (sched_yield() == -1) 191 err(errno, "sched_yield"); 192 } 193 194 exit(0); 195} 196#ifdef STANDALONE_TESTS 197int main(int argc, char *argv[]) { return yield(argc, argv); } 198#endif 199