xref: /freebsd/tools/test/stress2/misc/mmap10.sh (revision d4eeb02986980bf33dd56c41ceb9fc5f180c0d47)
1#!/bin/sh
2
3#
4# Copyright (c) 2014 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# "panic: vm_page_dirty: page is invalid!" seen.
30# http://people.freebsd.org/~pho/stress/log/mmap10.txt
31# No problems seen after r271681.
32
33. ../default.cfg
34
35[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
36
37here=`pwd`
38cd /tmp
39sed '1,/^EOF/d' < $here/$0 > mmap10.c
40mycc -o mmap10 -Wall -Wextra -O2 -g mmap10.c -lpthread || exit 1
41rm -f mmap10.c
42
43daemon sh -c "(cd $here/../testcases/swap; ./swap -t 2m -i 20 -k)"
44sleep `jot -r 1 0 9`
45for i in `jot 2`; do
46	/tmp/mmap10 &
47done
48sleep 300
49while pgrep -q mmap10; do
50	pkill -9 mmap10
51	sleep 2
52done
53wait
54killall -q swap
55
56rm -f /tmp/mmap10 /tmp/mmap10.core
57exit 0
58EOF
59#include <sys/types.h>
60#include <sys/mman.h>
61#include <sys/stat.h>
62#include <sys/wait.h>
63
64#include <err.h>
65#include <errno.h>
66#include <fcntl.h>
67#include <pthread.h>
68#include <pthread_np.h>
69#include <stdio.h>
70#include <stdlib.h>
71#include <string.h>
72#include <unistd.h>
73
74#define LOOPS 2
75#define MMSIZE (192 * 1024 * 1024)
76#define N (128 * 1024 / (int)sizeof(u_int32_t))
77#define PARALLEL 50
78
79void *p;
80u_int32_t r[N];
81
82unsigned long
83makearg(void)
84{
85	unsigned long val;
86	unsigned int i;
87
88	val = arc4random();
89	i   = arc4random() % 100;
90	if (i < 20)
91		val = val & 0xff;
92	if (i >= 20 && i < 40)
93		val = val & 0xffff;
94	if (i >= 40 && i < 60)
95		val = (unsigned long)(r) | (val & 0xffff);
96#if defined(__LP64__)
97	if (i >= 60) {
98		val = (val << 32) | arc4random();
99		if (i > 80)
100			val = val & 0x00007fffffffffffUL;
101	}
102#endif
103
104	return(val);
105}
106
107void *
108makeptr(void)
109{
110	unsigned long val;
111
112	if (p != MAP_FAILED && p != NULL)
113		val = (unsigned long)p + arc4random();
114	else
115		val = makearg();
116	val = trunc_page(val);
117
118	return ((void *)val);
119}
120
121void *
122tmmap(void *arg __unused)
123{
124	size_t len;
125	int i, j, fd;
126
127	pthread_set_name_np(pthread_self(), __func__);
128	len = MMSIZE;
129
130	for (i = 0, j = 0; i < 100; i++) {
131		if ((fd = open("/dev/zero", O_RDWR)) == -1)
132			err(1,"open()");
133
134		if ((p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE,
135		    fd, 0)) != MAP_FAILED) {
136			usleep(100);
137			munmap(p, len);
138			j++;
139		}
140
141		if ((p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_ANON,
142		    -1, 0)) != MAP_FAILED) {
143			usleep(100);
144			munmap(p, len);
145			j++;
146		}
147		close(fd);
148	}
149	if (j == 0)
150		fprintf(stderr, "FAIL: all mmap(2) calls failed.\n");
151
152	return (NULL);
153}
154
155void *
156tmlock(void *arg __unused)
157{
158	size_t len;
159	int i, n;
160
161	pthread_set_name_np(pthread_self(), __func__);
162	n = 0;
163	for (i = 0; i < 200; i++) {
164		len = trunc_page(makearg());
165		if (mlock(makeptr(), len) == 0)
166			n++;
167		len = trunc_page(makearg());
168		if (arc4random() % 100 < 50)
169			if (munlock(makeptr(), len) == 0)
170				n++;
171	}
172	if (n < 10)
173		fprintf(stderr, "Note: tmlock() only succeeded %d times.\n",
174		    n);
175
176	return (NULL);
177}
178
179void *
180tmprotect(void *arg __unused)
181{
182	size_t len;
183	void *addr;
184	int i, n, prot;
185
186	pthread_set_name_np(pthread_self(), __func__);
187	n = 0;
188	for (i = 0; i < 200; i++) {
189		addr = makeptr();
190		len = trunc_page(makearg());
191		prot = makearg();
192		if (mprotect(addr, len, prot) == 0)
193			n++;
194		usleep(1000);
195	}
196	if (n < 10)
197		fprintf(stderr, "Note: tmprotect() only succeeded %d times.\n",
198		    n);
199
200	return (NULL);
201}
202
203void *
204tmlockall(void *arg __unused)
205{
206	int flags, i, n;
207
208	pthread_set_name_np(pthread_self(), __func__);
209	n = 0;
210	for (i = 0; i < 200; i++) {
211		flags = makearg();
212		if (mlockall(flags) == 0)
213			n++;
214		usleep(100);
215		munlockall();
216		usleep(1000);
217	}
218	if (n < 10)
219		fprintf(stderr, "Note: tmlockall() only succeeded %d times.\n",
220		    n);
221
222	return (NULL);
223}
224
225void
226test(void)
227{
228	pthread_t tid[4];
229	int i, rc;
230
231	if ((rc = pthread_create(&tid[0], NULL, tmmap, NULL)) != 0)
232		errc(1, rc, "tmmap()");
233	if ((rc = pthread_create(&tid[1], NULL, tmlock, NULL)) != 0)
234		errc(1, rc, "tmlock()");
235	if ((rc = pthread_create(&tid[2], NULL, tmprotect, NULL)) != 0)
236		errc(1, rc, "tmprotect()");
237	if ((rc = pthread_create(&tid[3], NULL, tmlockall, NULL)) != 0)
238		errc(1, rc, "tmlockall()");
239
240	for (i = 0; i < 100; i++) {
241		if (fork() == 0) {
242			usleep(10000);
243			_exit(0);
244		}
245		wait(NULL);
246	}
247
248	for (i = 0; i < 4; i++)
249		if ((rc = pthread_join(tid[i], NULL)) != 0)
250			errc(1, rc, "pthread_join(%d)", i);
251	_exit(0);
252}
253
254int
255main(void)
256{
257	int i, j;
258
259	for (i = 0; i < N; i++)
260		r[i] = arc4random();
261
262	for (i = 0; i < LOOPS; i++) {
263		for (j = 0; j < PARALLEL; j++) {
264			if (fork() == 0)
265				test();
266		}
267
268		for (j = 0; j < PARALLEL; j++)
269			wait(NULL);
270	}
271
272	return (0);
273}
274