]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/test/stress2/misc/contigmalloc.sh
contrib/bc: update to version 5.1.1
[FreeBSD/FreeBSD.git] / tools / test / stress2 / misc / contigmalloc.sh
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) / contigfree(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, "contigfree(%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                         if (p != NULL)
202                                 contigfree(p, size, M_TEMP);
203                 }
204                 return (error);
205
206         case TALLOC:
207                 p = contigmalloc(size, M_TEMP, M_NOWAIT, 0ul, ~0ul, 4096, 0);
208                 if (p != NULL) {
209                         error = copyout(&p, uap->a_ptr, sizeof(p));
210                         return (error);
211                 }
212                 return (ENOMEM);
213         }
214         return (EINVAL);
215 }
216
217 /*
218  * The sysent for the new syscall
219  */
220 static struct sysent cmalloc_sysent = {
221         .sy_narg =  3,                          /* sy_narg */
222         .sy_call = (sy_call_t *) cmalloc        /* sy_call */
223 };
224
225 /*
226  * The offset in sysent where the syscall is allocated.
227  */
228 static int cmalloc_offset = NO_SYSCALL;
229
230 SYSCTL_INT(_debug, OID_AUTO, cmalloc_offset, CTLFLAG_RD, &cmalloc_offset, 0,
231     "cmalloc syscall number");
232
233 /*
234  * The function called at load/unload.
235  */
236
237 static int
238 cmalloc_load(struct module *module, int cmd, void *arg)
239 {
240         int error = 0;
241
242         switch (cmd) {
243         case MOD_LOAD :
244                 break;
245         case MOD_UNLOAD :
246                 break;
247         default :
248                 error = EOPNOTSUPP;
249                 break;
250         }
251         return (error);
252 }
253
254 SYSCALL_MODULE(cmalloc_syscall, &cmalloc_offset, &cmalloc_sysent,
255     cmalloc_load, NULL);