Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tools/test/stress2/misc/contigmalloc.sh
39536 views
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
# contigmalloc(9) / free(9) test scenario.
30
# malloc() a random number of buffers with random size and then free them.
31
32
# A malloc pattern might look like this:
33
# contigmalloc(186 pages)
34
# contigmalloc(56 pages)
35
# contigmalloc(9 pages)
36
# contigmalloc(202 pages)
37
# contigmalloc(49 pages)
38
# contigmalloc(5 pages)
39
40
# "panic: vm_reserv_alloc_contig: reserv 0xff... isn't free" seen.
41
# http://people.freebsd.org/~pho/stress/log/contigmalloc.txt
42
# Fixed by r271351.
43
44
[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
45
[ -d /usr/src/sys ] || exit 0
46
builddir=`sysctl kern.version | grep @ | sed 's/.*://'`
47
[ -d "$builddir" ] && export KERNBUILDDIR=$builddir || exit 0
48
export SYSDIR=`echo $builddir | sed 's#/sys.*#/sys#'`
49
50
. ../default.cfg
51
52
odir=`pwd`
53
dir=/tmp/contigmalloc
54
rm -rf $dir; mkdir -p $dir
55
cat > $dir/ctest.c <<EOF
56
#include <sys/param.h>
57
#include <sys/syscall.h>
58
59
#include <err.h>
60
#include <stdio.h>
61
#include <stdlib.h>
62
#include <time.h>
63
#include <unistd.h>
64
65
#define min(a,b) (((a)<(b))?(a):(b))
66
#define CAP (64 * 1024 * 1024) /* Total allocation */
67
#define MAXBUF (32 * 1024 * 1024) /* Max buffer size */
68
#define N 512 /* Max allocations */
69
#define RUNTIME 120
70
#define TALLOC 1
71
#define TFREE 2
72
73
void *p[N];
74
long size[N];
75
int n;
76
77
void
78
test(int argc, char *argv[])
79
{
80
long mw, s;
81
int i, no, ps, res;
82
83
if (argc == 3) {
84
no = atoi(argv[1]);
85
mw = atol(argv[2]);
86
}
87
if (argc != 3 || no == 0 || mw == 0)
88
errx(1, "Usage: %s <syscall number> <max wired>", argv[0]);
89
90
ps = getpagesize();
91
s = 0;
92
n = arc4random() % N + 1;
93
mw = mw / 100 * 10 * ps; /* Use 10% of vm.max_user_wired */
94
mw = min(mw, CAP);
95
for (i = 0; i < n; i++) {
96
size[i] = round_page((arc4random() % MAXBUF) + 1);
97
if (s + size[i] > mw)
98
continue;
99
res = syscall(no, TALLOC, &p[i], &size[i]);
100
if (res == -1) {
101
warn("contigmalloc(%lu pages) failed at loop %d",
102
size[i] / ps, i);
103
usleep(200000);
104
} else {
105
#if defined(TEST)
106
fprintf(stderr, "contigmalloc(%lu pages)\n",
107
size[i] / ps);
108
#endif
109
s += size[i];
110
}
111
}
112
113
setproctitle("%ld Mb", s / 1024 / 1024);
114
115
for (i = 0; i < n; i++) {
116
if (p[i] != NULL) {
117
res = syscall(no, TFREE, &p[i], &size[i]);
118
#if defined(TEST)
119
fprintf(stderr, "free(%lu pages)\n",
120
size[i] / ps);
121
#endif
122
p[i] = NULL;
123
}
124
}
125
}
126
127
int
128
main(int argc, char *argv[])
129
{
130
time_t start;
131
132
start = time(NULL);
133
while (time(NULL) - start < RUNTIME)
134
test(argc, argv);
135
136
return (0);
137
}
138
139
EOF
140
mycc -o /tmp/ctest -Wall -Wextra -O0 -g $dir/ctest.c || exit 1
141
rm $dir/ctest.c
142
143
cd $dir
144
cat > Makefile <<EOF
145
KMOD= cmalloc
146
SRCS= cmalloc.c
147
148
.include <bsd.kmod.mk>
149
EOF
150
151
sed '1,/^EOF2/d' < $odir/$0 > cmalloc.c
152
make || exit 1
153
kldload $dir/cmalloc.ko || exit 1
154
155
cd $odir
156
mw=`sysctl -n vm.max_user_wired` || exit 1
157
/tmp/ctest `sysctl -n debug.cmalloc_offset` $mw 2>&1 | tail -5
158
kldunload $dir/cmalloc.ko
159
rm -rf $dir /tmp/ctest
160
exit 0
161
162
EOF2
163
#include <sys/param.h>
164
#include <sys/kernel.h>
165
#include <sys/malloc.h>
166
#include <sys/module.h>
167
#include <sys/proc.h>
168
#include <sys/sysctl.h>
169
#include <sys/sysent.h>
170
#include <sys/sysproto.h>
171
#include <sys/systm.h>
172
173
#define TALLOC 1
174
#define TFREE 2
175
176
/*
177
* Hook up a syscall for contigmalloc testing.
178
*/
179
180
struct cmalloc_args {
181
int a_op;
182
void *a_ptr;
183
void *a_size;
184
};
185
186
static int
187
cmalloc(struct thread *td, struct cmalloc_args *uap)
188
{
189
void *p;
190
unsigned long size;
191
int error;
192
193
error = copyin(uap->a_size, &size, sizeof(size));
194
if (error != 0) {
195
return (error);
196
}
197
switch (uap->a_op) {
198
case TFREE:
199
error = copyin(uap->a_ptr, &p, sizeof(p));
200
if (error == 0)
201
free(p, M_TEMP);
202
return (error);
203
204
case TALLOC:
205
p = contigmalloc(size, M_TEMP, M_NOWAIT, 0ul, ~0ul, 4096, 0);
206
if (p != NULL) {
207
error = copyout(&p, uap->a_ptr, sizeof(p));
208
return (error);
209
}
210
return (ENOMEM);
211
}
212
return (EINVAL);
213
}
214
215
/*
216
* The sysent for the new syscall
217
*/
218
static struct sysent cmalloc_sysent = {
219
.sy_narg = 3, /* sy_narg */
220
.sy_call = (sy_call_t *) cmalloc /* sy_call */
221
};
222
223
/*
224
* The offset in sysent where the syscall is allocated.
225
*/
226
static int cmalloc_offset = NO_SYSCALL;
227
228
SYSCTL_INT(_debug, OID_AUTO, cmalloc_offset, CTLFLAG_RD, &cmalloc_offset, 0,
229
"cmalloc syscall number");
230
231
/*
232
* The function called at load/unload.
233
*/
234
235
static int
236
cmalloc_load(struct module *module, int cmd, void *arg)
237
{
238
int error = 0;
239
240
switch (cmd) {
241
case MOD_LOAD :
242
break;
243
case MOD_UNLOAD :
244
break;
245
default :
246
error = EOPNOTSUPP;
247
break;
248
}
249
return (error);
250
}
251
252
SYSCALL_MODULE(cmalloc_syscall, &cmalloc_offset, &cmalloc_sysent,
253
cmalloc_load, NULL);
254
255