xref: /freebsd/tools/test/stress2/misc/holdcnt02.sh (revision 2e3507c25e42292b45a5482e116d278f5515d04d)
1#!/bin/sh
2
3#
4# Copyright (c) 2015 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# Copy of holdcnt0.sh, but without the memory disk usage.
30
31# Test scenario suggestion by alc@
32
33[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
34[ `swapinfo | wc -l` -eq 1 ] && exit 0
35[ `sysctl -n hw.physmem` -lt $((32 * 1024 * 1024 * 1024)) ] && exit 0
36
37. ../default.cfg
38
39here=`pwd`
40cd /tmp
41sed '1,/^EOF/d' < $here/$0 > holdcnt02.c
42mycc -o holdcnt02 -Wall -Wextra -g holdcnt02.c || exit 1
43rm -f holdcnt02.c
44cd $here
45
46trap "rm -f /tmp/holdcnt02 `dirname $diskimage`/f000???" EXIT INT
47(cd `dirname $diskimage`; /tmp/holdcnt02) &
48pid=$!
49sleep 5
50while kill -0 $! 2> /dev/null; do
51	(cd ../testcases/swap; ./swap -t 1m -i 1) > /dev/null 2>&1
52done
53wait $pid
54exit
55EOF
56/*
57   A test that causes the page daemon to generate cached pages
58   within a bunch of files and has some consumer that is trying to
59   allocate new pages to the same files.
60*/
61
62#include <sys/types.h>
63#include <sys/mman.h>
64#include <sys/stat.h>
65#include <sys/wait.h>
66
67#include <err.h>
68#include <errno.h>
69#include <fcntl.h>
70#include <setjmp.h>
71#include <signal.h>
72#include <stdio.h>
73#include <stdlib.h>
74#include <time.h>
75#include <unistd.h>
76
77#define BUFSIZE (1024 * 1024)
78#define FILES 200
79#define RPARALLEL 8
80#define WPARALLEL 2
81
82static jmp_buf jbuf;
83static off_t maxsize;
84static int ps;
85static char *buf;
86static volatile char val;
87
88static void
89hand(int i __unused) {  /* handler */
90        longjmp(jbuf, 1);
91}
92
93static void
94cleanup(void)
95{
96	int i;
97	char file[80];
98
99	for (i = 0; i < FILES; i++) {
100		snprintf(file, sizeof(file), "f%06d", i);
101		unlink(file);
102	}
103}
104
105static void
106init(void)
107{
108	int fd, i;
109	char file[80];
110
111	for (i = 0; i < FILES; i++) {
112		snprintf(file, sizeof(file), "f%06d", i);
113		if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0644)) ==
114		    -1)
115			err(1, "open(%s)", file);
116		if (write(fd, buf, BUFSIZE) != BUFSIZE)
117			err(1, "write");
118		close(fd);
119	}
120
121}
122
123static void
124writer(void)
125{
126	int fd, i;
127	char file[80];
128	time_t start;
129	struct stat statbuf;
130
131	setproctitle("writer");
132	start = time(NULL);
133	while (time(NULL) - start < 600) {
134		for (i = 0; i < FILES; i++) {
135			snprintf(file, sizeof(file), "f%06d", i);
136			if ((fd = open(file, O_RDWR | O_APPEND)) == -1) {
137				if (errno != ENOENT)
138					err(1, "open(%s) append", file);
139				goto err;
140			}
141			if (fstat(fd, &statbuf) < 0)
142				err(1, "fstat error");
143			if (statbuf.st_size < maxsize) {
144				if (write(fd, buf, ps) != ps) {
145					warn("writer");
146					goto err;
147				}
148			}
149			close(fd);
150		}
151	}
152err:
153	cleanup();
154
155	_exit(0);
156}
157
158static void
159reader(void)
160{
161	int fd, i, j, n;
162	void *p;
163	size_t len;
164	char file[80];
165	struct stat statbuf;
166
167	setproctitle("reader");
168	signal(SIGSEGV, hand);
169	signal(SIGBUS, hand);
170	fd = 0;
171	for (;;) {
172		(void)setjmp(jbuf);
173		for (i = 0; i < FILES; i++) {
174			snprintf(file, sizeof(file), "f%06d", i);
175			if (fd > 0)
176				close(fd);
177			if ((fd = open(file, O_RDWR)) == -1) {
178				if (errno != ENOENT)
179					warn("reader(%s)", file);
180				_exit(0);
181			}
182			if (fstat(fd, &statbuf) < 0)
183				err(1, "fstat error");
184			if (statbuf.st_size >= maxsize) {
185				if (ftruncate(fd, ps) == -1)
186					err(1, "ftruncate");
187				continue;
188			}
189			len = statbuf.st_size;
190			if ((p = mmap(p, len, PROT_READ, MAP_SHARED, fd, 0))
191			    == MAP_FAILED)
192				err(1, "mmap()");
193			close(fd);
194			n = statbuf.st_size / ps;
195			for (j = 0; j < n; j++) {
196				val = *(char *)p;
197				p = p + ps;
198			}
199#if 0
200			if (munmap(p, len) == -1)
201				perror("munmap");
202#endif
203		}
204	}
205	_exit(0);
206}
207int
208main(void)
209{
210	pid_t rpid[RPARALLEL], wpid[WPARALLEL];
211	int e, i, s;
212
213	maxsize = 2LL * 1024 * 1024 * 1024 / FILES;
214	buf = malloc(BUFSIZE);
215	ps = getpagesize();
216
217	init();
218	e = 0;
219	for (i = 0; i < WPARALLEL; i++) {
220		if ((wpid[i] = fork()) == 0)
221			writer();
222	}
223	for (i = 0; i < RPARALLEL; i++) {
224		if ((rpid[i] = fork()) == 0)
225			reader();
226	}
227
228	for (i = 0; i < WPARALLEL; i++)
229		waitpid(wpid[i], &s, 0);
230	e += s == 0 ? 0 : 1;
231	for (i = 0; i < RPARALLEL; i++)
232		waitpid(rpid[i], &s, 0);
233	e += s == 0 ? 0 : 1;
234
235	free(buf);
236
237	return (e);
238}
239