1#!/bin/sh
2
3#
4# Copyright (c) 2016 EMC Corp.
5# 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#
16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26# SUCH DAMAGE.
27#
28
29# pipe(2) test
30
31. ../default.cfg
32[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
33
34dir=/tmp
35odir=`pwd`
36cd $dir
37sed '1,/^EOF/d' < $odir/$0 > $dir/pipe2.c
38mycc -o pipe2 -Wall -Wextra -O0 -g pipe2.c || exit 1
39rm -f pipe2.c
40
41daemon sh -c "(cd $odir/../testcases/swap; ./swap -t 10m -i 20)" > \
42    /dev/null 2>&1
43sleep 10
44
45su $testuser -c /tmp/pipe2
46s=$?
47
48while pgrep -q swap; do
49	pkill -9 swap
50done
51
52rm -rf /tmp/pipe2
53exit $s
54
55EOF
56#include <sys/param.h>
57#include <sys/mman.h>
58
59#include <machine/atomic.h>
60
61#include <err.h>
62#include <errno.h>
63#include <fcntl.h>
64#include <signal.h>
65#include <stdio.h>
66#include <stdlib.h>
67#include <unistd.h>
68
69volatile u_int *share, *share2;
70
71#define R1 1 /* sync start  */
72#define R2 2 /* forks       */
73
74#define PIPES 128
75#define PARALLEL 32
76
77static void
78hand(int i __unused) {	/* handler */
79	fprintf(stderr, "Timed out\n");
80	_exit(1);
81}
82
83void
84test(void)
85{
86	size_t len;
87	int fds[2], r;
88	int token;
89
90	len = PAGE_SIZE;
91	if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE,
92	    MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED)
93		err(1, "mmap");
94
95	if (pipe(fds) == -1)
96		err(1, "pipe");
97	token = 0;
98	write(fds[1], &token, sizeof(token));
99	for (;;) {
100		if (share[R2] >= PIPES)
101			break;
102		if ((r = fork()) == 0) {
103			atomic_add_int(&share[R2], 1);
104			if (read(fds[0], &token, sizeof(token)) != sizeof(token))
105				err(1, "read");
106			close(fds[0]);
107			if (pipe(fds) == -1)
108				err(1, "pipe");
109			token++;
110			if (write(fds[1], &token, sizeof(token)) != sizeof(token))
111				err(1, "write");
112		}
113		if (r == -1)
114			err(1, "fork()");
115		if (r != 0)
116			_exit(0);
117	}
118
119	if (share[R2] == PIPES) {
120#if defined(DEBUG)
121		if (read(fds[0], &token, sizeof(token)) != sizeof(token))
122			err(1, "final read");
123		fprintf(stderr, "FINAL read %d from %d\n", token, fds[0]);
124#endif
125		atomic_add_int(&share2[R1], 1);
126	}
127	_exit(0);
128}
129
130int
131main(void)
132{
133	struct sigaction sa;
134	size_t len;
135	int i;
136
137	len = PAGE_SIZE;
138	if ((share2 = mmap(NULL, len, PROT_READ | PROT_WRITE,
139	    MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED)
140		err(1, "mmap");
141
142	sa.sa_handler = SIG_IGN;
143	sigemptyset(&sa.sa_mask);
144	sa.sa_flags = 0;
145	if (sigaction(SIGCHLD, &sa, 0) == -1)
146		err(1, "sigaction");
147
148	for (i = 0; i < PARALLEL; i++) {
149		if (fork() == 0)
150			test();
151	}
152
153	signal(SIGALRM, hand);
154	alarm(300);
155	while (share2[R1] != PARALLEL) {
156		sleep(1);
157#if defined(DEBUG)
158		fprintf(stderr, "share2 = %d\n", share2[R1]);
159#endif
160	}
161
162	return (0);
163}
164