4 # Copyright (c) 2014 EMC Corp.
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
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.
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
29 # contigmalloc(9) / contigfree(9) test scenario.
30 # malloc() a random number of buffers with random size and then free them.
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)
40 # "panic: vm_reserv_alloc_contig: reserv 0xff... isn't free" seen.
41 # http://people.freebsd.org/~pho/stress/log/contigmalloc.txt
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#'`
54 rm -rf $dir; mkdir -p $dir
55 cat > $dir/ctest.c <<EOF
56 #include <sys/param.h>
57 #include <sys/syscall.h>
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 */
78 test(int argc, char *argv[])
87 if (argc != 3 || no == 0 || mw == 0)
88 errx(1, "Usage: %s <syscall number> <max wired>", argv[0]);
92 n = arc4random() % N + 1;
93 mw = mw / 100 * 10 * ps; /* Use 10% of vm.max_user_wired */
95 for (i = 0; i < n; i++) {
96 size[i] = round_page((arc4random() % MAXBUF) + 1);
99 res = syscall(no, TALLOC, &p[i], &size[i]);
101 warn("contigmalloc(%lu pages) failed at loop %d",
106 fprintf(stderr, "contigmalloc(%lu pages)\n",
113 setproctitle("%ld Mb", s / 1024 / 1024);
115 for (i = 0; i < n; i++) {
117 res = syscall(no, TFREE, &p[i], &size[i]);
119 fprintf(stderr, "contigfree(%lu pages)\n",
128 main(int argc, char *argv[])
133 while (time(NULL) - start < RUNTIME)
140 mycc -o /tmp/ctest -Wall -Wextra -O0 -g $dir/ctest.c || exit 1
148 .include <bsd.kmod.mk>
151 sed '1,/^EOF2/d' < $odir/$0 > cmalloc.c
153 kldload $dir/cmalloc.ko || exit 1
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
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>
177 * Hook up a syscall for contigmalloc testing.
180 struct cmalloc_args {
187 cmalloc(struct thread *td, struct cmalloc_args *uap)
193 error = copyin(uap->a_size, &size, sizeof(size));
199 error = copyin(uap->a_ptr, &p, sizeof(p));
202 contigfree(p, size, M_TEMP);
207 p = contigmalloc(size, M_TEMP, M_NOWAIT, 0ul, ~0ul, 4096, 0);
209 error = copyout(&p, uap->a_ptr, sizeof(p));
218 * The sysent for the new syscall
220 static struct sysent cmalloc_sysent = {
221 .sy_narg = 3, /* sy_narg */
222 .sy_call = (sy_call_t *) cmalloc /* sy_call */
226 * The offset in sysent where the syscall is allocated.
228 static int cmalloc_offset = NO_SYSCALL;
230 SYSCTL_INT(_debug, OID_AUTO, cmalloc_offset, CTLFLAG_RD, &cmalloc_offset, 0,
231 "cmalloc syscall number");
234 * The function called at load/unload.
238 cmalloc_load(struct module *module, int cmd, void *arg)
254 SYSCALL_MODULE(cmalloc_syscall, &cmalloc_offset, &cmalloc_sysent,