1#!/bin/sh
2
3#
4# Copyright (c) 2017 Dell EMC Isilon
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# Test scenario for 2MB page promotions.
30# No problems seen.
31
32. ../default.cfg
33[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
34[ "`uname -p`" = "amd64" ] || exit 0
35
36dir=/tmp
37odir=`pwd`
38cd $dir
39sed '1,/^EOF/d' < $odir/$0 > $dir/mmap31.c
40mycc -o mmap31 -Wall -Wextra -O0 -g mmap31.c || exit 1
41rm -f mmap31.c
42cd $odir
43
44(cd ../testcases/swap; ./swap -t 10m -i 20) > /dev/null &
45
46/tmp/mmap31
47s=$?
48kill $! 2>/dev/null
49while pkill -9 swap; do :; done
50wait
51
52rm -rf /tmp/mmap31
53exit $s
54
55EOF
56#include <sys/param.h>
57#include <sys/mman.h>
58#include <sys/stat.h>
59#include <sys/wait.h>
60
61#include <machine/atomic.h>
62
63#include <err.h>
64#include <errno.h>
65#include <fcntl.h>
66#include <stdio.h>
67#include <stdlib.h>
68#include <signal.h>
69#include <time.h>
70#include <unistd.h>
71
72#define SEGS 512
73static size_t l[SEGS];
74static char *c[SEGS];
75static volatile char r;
76static volatile u_int *share;
77
78#define PARALLEL 8
79#define RUNTIME (2 * 60)
80#define SYNC 0
81
82static void
83handler(int s __unused)
84{
85	_exit(0);
86}
87
88static void
89touch(void)
90{
91	time_t t;
92	int idx;
93	char *c1;
94
95	t = time(NULL);
96	while (time(NULL) - t < 5) {
97		idx = arc4random() % SEGS;
98		c1 = c[idx];
99		idx = arc4random() % l[idx];
100		r += c1[idx];
101		c1[idx] += 1;
102	}
103}
104
105static void
106test(void)
107{
108	pid_t pid;
109	int i, mode, status;
110
111	r = 0;
112	for (i = 0; i < SEGS; i++) {
113		l[i] = (arc4random() % 512 + 1) * PAGE_SIZE;
114		mode = PROT_READ | PROT_WRITE;
115		if ((c[i] = (char *)mmap(NULL, l[i], mode,
116		    MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED)
117			err(1, "mmap");
118	}
119
120	if ((pid = fork()) == 0) {
121		signal(SIGHUP, handler);
122		atomic_add_int(&share[SYNC], 1);
123		while (share[SYNC] != PARALLEL)
124			;
125		touch();
126		pause();
127		_exit(0);
128	}
129
130	while (share[SYNC] != PARALLEL)
131		;
132	touch();
133
134	kill(pid, SIGHUP);
135	if (waitpid(pid, &status, 0) != pid)
136		err(1, "waitpid");
137	if (status != 0)
138		errx(1, "child status = %d", status);
139
140	_exit(status);
141}
142
143int
144main(void)
145{
146	pid_t pids[PARALLEL];
147	size_t len;
148	time_t start;
149	int e, i, status;
150
151	e = 0;
152	len = PAGE_SIZE;
153	if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE,
154	    MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED)
155		err(1, "mmap");
156
157	start = time(NULL);
158	while ((time(NULL) - start) < RUNTIME && e == 0) {
159		share[SYNC] = 0;
160		for (i = 0; i < PARALLEL; i++) {
161			if ((pids[i] = fork()) == 0)
162				test();
163			if (pids[i] == -1)
164				err(1, "fork()");
165		}
166		for (i = 0; i < PARALLEL; i++) {
167			if (waitpid(pids[i], &status, 0) == -1)
168				err(1, "waitpid(%d)", pids[i]);
169			e += status == 0 ? 0 : 1;
170		}
171	}
172
173	return (e);
174}
175