xref: /freebsd/tools/test/stress2/misc/radix.sh (revision 8a272653d9fbd9fc37691c9aad6a05089b4ecb4d)
1*8a272653SPeter Holm#!/bin/sh
2*8a272653SPeter Holm
3*8a272653SPeter Holm#
4*8a272653SPeter Holm# Copyright (c) 2013 EMC Corp.
5*8a272653SPeter Holm# All rights reserved.
6*8a272653SPeter Holm#
7*8a272653SPeter Holm# Redistribution and use in source and binary forms, with or without
8*8a272653SPeter Holm# modification, are permitted provided that the following conditions
9*8a272653SPeter Holm# are met:
10*8a272653SPeter Holm# 1. Redistributions of source code must retain the above copyright
11*8a272653SPeter Holm#    notice, this list of conditions and the following disclaimer.
12*8a272653SPeter Holm# 2. Redistributions in binary form must reproduce the above copyright
13*8a272653SPeter Holm#    notice, this list of conditions and the following disclaimer in the
14*8a272653SPeter Holm#    documentation and/or other materials provided with the distribution.
15*8a272653SPeter Holm#
16*8a272653SPeter Holm# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17*8a272653SPeter Holm# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*8a272653SPeter Holm# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*8a272653SPeter Holm# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20*8a272653SPeter Holm# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21*8a272653SPeter Holm# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22*8a272653SPeter Holm# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23*8a272653SPeter Holm# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24*8a272653SPeter Holm# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25*8a272653SPeter Holm# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*8a272653SPeter Holm# SUCH DAMAGE.
27*8a272653SPeter Holm#
28*8a272653SPeter Holm
29*8a272653SPeter Holm# Consume VM radix nodes
30*8a272653SPeter Holm
31*8a272653SPeter Holm# "panic: default pager with handle" seen with WiP kernel code.
32*8a272653SPeter Holm# https://people.freebsd.org/~pho/stress/log/kostik1243.txt
33*8a272653SPeter Holm
34*8a272653SPeter Holm[ `sysctl vm.swap_total | sed 's/.* //'` -eq 0 ] && exit 0
35*8a272653SPeter Holm
36*8a272653SPeter Holm. ../default.cfg
37*8a272653SPeter Holm
38*8a272653SPeter Holmdir=/tmp
39*8a272653SPeter Holmodir=`pwd`
40*8a272653SPeter Holmcd $dir
41*8a272653SPeter Holmsed '1,/^EOF/d' < $odir/$0 > $dir/radix.c
42*8a272653SPeter Holmmycc -o radix -Wall -Wextra radix.c || exit 1
43*8a272653SPeter Holmrm -f radix.c
44*8a272653SPeter Holmcd $odir
45*8a272653SPeter Holm
46*8a272653SPeter Holmset -e
47*8a272653SPeter Holmparallel=1
48*8a272653SPeter Holmusermem=`sysctl hw.usermem | sed 's/.* //'`
49*8a272653SPeter Holmpagesize=`pagesize`
50*8a272653SPeter Holmstart=`date +%s`
51*8a272653SPeter Holmwhile true; do
52*8a272653SPeter Holm	/tmp/radix $parallel > /tmp/radix.log 2>&1
53*8a272653SPeter Holm	used=`awk '{print $4}' < /tmp/radix.log`
54*8a272653SPeter Holm	[ -z "$used" ] && break
55*8a272653SPeter Holm	[ $((`date +%s` - start)) -gt 300 ] && break
56*8a272653SPeter Holm	[ $used -gt $((usermem / pagesize)) ] && break
57*8a272653SPeter Holm	[ $parallel -eq 1 ] &&
58*8a272653SPeter Holm	    parallel=$((usermem / pagesize / used))
59*8a272653SPeter Holm	parallel=$((parallel + 1))
60*8a272653SPeter Holm	echo "`date +%T` parallel=$parallel" # XXX
61*8a272653SPeter Holmdone
62*8a272653SPeter Holmcat /tmp/radix.log
63*8a272653SPeter Holm
64*8a272653SPeter Holmrm -f /tmp/radix #/tmp/radix.log
65*8a272653SPeter Holmexit
66*8a272653SPeter Holm
67*8a272653SPeter HolmEOF
68*8a272653SPeter Holm/*
69*8a272653SPeter Holm   On Wed, 17 Apr 2013 18:57:00 -0500 alc wrote:
70*8a272653SPeter Holm
71*8a272653SPeter Holm   Suppose that I write a program for i386 that creates giant VM objects,
72*8a272653SPeter Holm   perhaps, using shm_open() + ftruncate(), and touches pages 0, 1, 8, 9,
73*8a272653SPeter Holm   64, 65, 72, 73, 512, 513, 520, 521, 576, 577, 584, 585, 4096, 4097,
74*8a272653SPeter Holm   4104, 4105, ... in each of the VM objects. (The sequence would be
75*8a272653SPeter Holm   different on amd64.) I could work around the 32-bit address space
76*8a272653SPeter Holm   limitation by mmap(2)ing and munmap(2)ing windows onto a VM object.
77*8a272653SPeter Holm   Each of the VM objects would have only one less interior node in the
78*8a272653SPeter Holm   radix tree than pages. If I create enough of these VM objects, then I
79*8a272653SPeter Holm   can consume all of the available pages and an almost equal number of
80*8a272653SPeter Holm   interior nodes. (Maybe it's worth writing this program so that some
81*8a272653SPeter Holm   experiments could be done?)
82*8a272653SPeter Holm*/
83*8a272653SPeter Holm
84*8a272653SPeter Holm#include <sys/param.h>
85*8a272653SPeter Holm
86*8a272653SPeter Holm#include <err.h>
87*8a272653SPeter Holm#include <errno.h>
88*8a272653SPeter Holm#include <fcntl.h>
89*8a272653SPeter Holm#include <sched.h>
90*8a272653SPeter Holm#include <signal.h>
91*8a272653SPeter Holm#include <stdint.h>
92*8a272653SPeter Holm#include <stdio.h>
93*8a272653SPeter Holm#include <stdlib.h>
94*8a272653SPeter Holm#include <sys/mman.h>
95*8a272653SPeter Holm#include <sys/wait.h>
96*8a272653SPeter Holm#include <unistd.h>
97*8a272653SPeter Holm
98*8a272653SPeter Holm#ifdef __LP64__
99*8a272653SPeter Holm#define	WIDTH	4
100*8a272653SPeter Holm#else
101*8a272653SPeter Holm#define	WIDTH	3
102*8a272653SPeter Holm#endif
103*8a272653SPeter Holm#define	N	(int)howmany(sizeof(uint64_t) * NBBY, WIDTH)
104*8a272653SPeter Holm
105*8a272653SPeter Holmtypedef uint64_t state_t[N];
106*8a272653SPeter Holm
107*8a272653SPeter Holmstatic uint64_t pgs;
108*8a272653SPeter Holmstatic int fds[2];
109*8a272653SPeter Holmstatic int parallel;
110*8a272653SPeter Holmstatic volatile sig_atomic_t s1;
111*8a272653SPeter Holmstatic int ps;
112*8a272653SPeter Holm
113*8a272653SPeter Holmstatic void
114*8a272653SPeter Holminit(state_t state)
115*8a272653SPeter Holm{
116*8a272653SPeter Holm	int i;
117*8a272653SPeter Holm
118*8a272653SPeter Holm	for (i = 0; i < N; i++)
119*8a272653SPeter Holm		state[i] = 0;
120*8a272653SPeter Holm}
121*8a272653SPeter Holm
122*8a272653SPeter Holmstatic uint64_t
123*8a272653SPeter Holmgenerator(state_t state)
124*8a272653SPeter Holm{
125*8a272653SPeter Holm	uint64_t value;
126*8a272653SPeter Holm	int i;
127*8a272653SPeter Holm
128*8a272653SPeter Holm	value = 0;
129*8a272653SPeter Holm	for (i = 0; i < N; i++)
130*8a272653SPeter Holm		value += state[i] << (i * WIDTH);
131*8a272653SPeter Holm	for (i = 0; i < N; i++)
132*8a272653SPeter Holm		if (state[i] == 0)
133*8a272653SPeter Holm			break;
134*8a272653SPeter Holm	if (i < N)
135*8a272653SPeter Holm		state[i]++;
136*8a272653SPeter Holm	for (i--; i >= 0; i--)
137*8a272653SPeter Holm		state[i]--;
138*8a272653SPeter Holm	return (value);
139*8a272653SPeter Holm}
140*8a272653SPeter Holm
141*8a272653SPeter Holmstatic int
142*8a272653SPeter Holmwr(int fd, off_t pno)
143*8a272653SPeter Holm{
144*8a272653SPeter Holm	off_t len, offset;
145*8a272653SPeter Holm	void *p;
146*8a272653SPeter Holm
147*8a272653SPeter Holm	offset = pno * ps;
148*8a272653SPeter Holm	len = ps;
149*8a272653SPeter Holm	p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_NOSYNC,
150*8a272653SPeter Holm	    fd, offset);
151*8a272653SPeter Holm	if (p == MAP_FAILED) {
152*8a272653SPeter Holm		if (errno == ENOMEM)
153*8a272653SPeter Holm			return (1);
154*8a272653SPeter Holm		err(1, "mmap(len 0x%jx, offset 0x%jx). %s:%d", len, offset,
155*8a272653SPeter Holm		    __FILE__, __LINE__);
156*8a272653SPeter Holm	}
157*8a272653SPeter Holm	*(char *)p = 1;
158*8a272653SPeter Holm	pgs++;
159*8a272653SPeter Holm
160*8a272653SPeter Holm	return (0);
161*8a272653SPeter Holm}
162*8a272653SPeter Holm
163*8a272653SPeter Holmstatic void
164*8a272653SPeter Holmhandler(int s __unused)
165*8a272653SPeter Holm{
166*8a272653SPeter Holm	s1++;
167*8a272653SPeter Holm}
168*8a272653SPeter Holm
169*8a272653SPeter Holmstatic void
170*8a272653SPeter Holmihandler(int s __unused)
171*8a272653SPeter Holm{
172*8a272653SPeter Holm	_exit(0);
173*8a272653SPeter Holm}
174*8a272653SPeter Holm
175*8a272653SPeter Holmstatic int
176*8a272653SPeter Holmradix(void)
177*8a272653SPeter Holm{
178*8a272653SPeter Holm	FILE *f;
179*8a272653SPeter Holm	int r;
180*8a272653SPeter Holm
181*8a272653SPeter Holm	if ((f = popen("vmstat -z | grep RADIX | awk -F',' '{print $3}'", "r")) == NULL)
182*8a272653SPeter Holm		err(1, "popen");
183*8a272653SPeter Holm	fscanf(f, "%d", &r);
184*8a272653SPeter Holm	pclose(f);
185*8a272653SPeter Holm
186*8a272653SPeter Holm	return (r);
187*8a272653SPeter Holm}
188*8a272653SPeter Holm
189*8a272653SPeter Holmstatic void
190*8a272653SPeter Holmtest(void)
191*8a272653SPeter Holm{
192*8a272653SPeter Holm	state_t state;
193*8a272653SPeter Holm	off_t offset;
194*8a272653SPeter Holm	int fd;
195*8a272653SPeter Holm
196*8a272653SPeter Holm	signal(SIGHUP, ihandler);
197*8a272653SPeter Holm	for (;;) {
198*8a272653SPeter Holm		if (access("rendezvous", R_OK) == 0)
199*8a272653SPeter Holm			break;
200*8a272653SPeter Holm		usleep(2000);
201*8a272653SPeter Holm	}
202*8a272653SPeter Holm
203*8a272653SPeter Holm	if ((fd = open("/dev/zero", O_RDWR)) == -1)
204*8a272653SPeter Holm		err(1, "open()");
205*8a272653SPeter Holm
206*8a272653SPeter Holm	init(state);
207*8a272653SPeter Holm	offset = generator(state);
208*8a272653SPeter Holm	do {
209*8a272653SPeter Holm		if (wr(fd, offset) != 0)
210*8a272653SPeter Holm			break;
211*8a272653SPeter Holm		offset = generator(state);
212*8a272653SPeter Holm	} while (offset != 0);
213*8a272653SPeter Holm
214*8a272653SPeter Holm	if (write(fds[1], &pgs, sizeof(pgs)) != sizeof(pgs))
215*8a272653SPeter Holm		err(1, "ewrite pipe");
216*8a272653SPeter Holm	kill(getppid(), SIGHUP);
217*8a272653SPeter Holm	for (;;)
218*8a272653SPeter Holm		sleep(1);
219*8a272653SPeter Holm	close(fd);
220*8a272653SPeter Holm
221*8a272653SPeter Holm	_exit(0);
222*8a272653SPeter Holm}
223*8a272653SPeter Holm
224*8a272653SPeter Holmint
225*8a272653SPeter Holmmain(int argc, char **argv)
226*8a272653SPeter Holm{
227*8a272653SPeter Holm	uint64_t pages;
228*8a272653SPeter Holm	pid_t *pids;
229*8a272653SPeter Holm	int i, r1, r2, rfd;
230*8a272653SPeter Holm
231*8a272653SPeter Holm	if (argc != 2)
232*8a272653SPeter Holm		errx(1, "Usage: %s <number of parallel processes>.", argv[0]);
233*8a272653SPeter Holm	parallel = atoi(argv[1]);
234*8a272653SPeter Holm
235*8a272653SPeter Holm	ps = getpagesize();
236*8a272653SPeter Holm	signal(SIGHUP, handler);
237*8a272653SPeter Holm	unlink("rendezvous");
238*8a272653SPeter Holm	pids = malloc(parallel * sizeof(pid_t));
239*8a272653SPeter Holm	if (pipe(fds) == -1)
240*8a272653SPeter Holm		err(1, "pipe");
241*8a272653SPeter Holm	r1 = radix();
242*8a272653SPeter Holm	for (i = 0; i < parallel; i++) {
243*8a272653SPeter Holm		if ((pids[i] = fork()) == 0)
244*8a272653SPeter Holm			test();
245*8a272653SPeter Holm	}
246*8a272653SPeter Holm	if ((rfd = open("rendezvous", O_CREAT, 0644)) == -1)
247*8a272653SPeter Holm		err(1, "open()");
248*8a272653SPeter Holm	close(rfd);
249*8a272653SPeter Holm	alarm(60);
250*8a272653SPeter Holm	while (s1 != parallel)
251*8a272653SPeter Holm		usleep(10000);
252*8a272653SPeter Holm	alarm(0);
253*8a272653SPeter Holm	r2 = radix();
254*8a272653SPeter Holm	pages = 0;
255*8a272653SPeter Holm	for (i = 0; i < parallel; i++) {
256*8a272653SPeter Holm		kill(pids[i], SIGHUP);
257*8a272653SPeter Holm		if (read(fds[0], &pgs, sizeof(pgs)) != sizeof(pgs))
258*8a272653SPeter Holm			err(1, "read pipe");
259*8a272653SPeter Holm		pages += pgs;
260*8a272653SPeter Holm	}
261*8a272653SPeter Holm	fprintf(stderr, "A total of %jd pages (%.1f MB) touched, %d"
262*8a272653SPeter Holm	    " RADIX nodes used, p/r = %.1f, parallel = %d.\n",
263*8a272653SPeter Holm	    pages, pages * ps / 1024. / 1024, r2 - r1,
264*8a272653SPeter Holm	    pages / (r2 - r1 + 0.), parallel);
265*8a272653SPeter Holm
266*8a272653SPeter Holm	for (i = 0; i < parallel; i++) {
267*8a272653SPeter Holm		wait(NULL);
268*8a272653SPeter Holm	}
269*8a272653SPeter Holm	unlink("rendezvous");
270*8a272653SPeter Holm	return (0);
271*8a272653SPeter Holm}
272