summaryrefslogtreecommitdiffstats
path: root/tools/regression/p1003_1b/yield.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/regression/p1003_1b/yield.c')
-rw-r--r--tools/regression/p1003_1b/yield.c197
1 files changed, 197 insertions, 0 deletions
diff --git a/tools/regression/p1003_1b/yield.c b/tools/regression/p1003_1b/yield.c
new file mode 100644
index 0000000..ac31a99
--- /dev/null
+++ b/tools/regression/p1003_1b/yield.c
@@ -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
OpenPOWER on IntegriCloud