]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/test/stress2/misc/contigmalloc2.sh
contrib/bc: update to version 5.1.1
[FreeBSD/FreeBSD.git] / tools / test / stress2 / misc / contigmalloc2.sh
1 #!/bin/sh
2
3 #
4 # Copyright (c) 2015 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 # Regression test for allocations >= 2 GiB.
31 # "panic: vm_page_insert_after: mpred doesn't precede pindex" seen.
32 # Fixed by r284207.
33
34 [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
35 [ -d /usr/src/sys ] || exit 0
36 builddir=`sysctl kern.version | grep @ | sed 's/.*://'`
37 [ -d "$builddir" ] && export KERNBUILDDIR=$builddir || exit 0
38 export SYSDIR=`echo $builddir | sed 's#/sys.*#/sys#'`
39
40 . ../default.cfg
41
42 odir=`pwd`
43 dir=/tmp/contigmalloc
44 rm -rf $dir; mkdir -p $dir
45 cat > $dir/ctest2.c <<EOF
46 #include <sys/param.h>
47 #include <sys/syscall.h>
48
49 #include <err.h>
50 #include <errno.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <unistd.h>
54
55 #define TALLOC 1
56 #define TFREE  2
57
58 void *p;
59 long size;
60 int n;
61
62 void
63 test(int argc, char *argv[])
64 {
65         long mw;
66         int no, ps, res;
67
68         if (argc == 3) {
69                 no = atoi(argv[1]);
70                 mw = atol(argv[2]);
71         }
72         if (argc != 3 || no == 0 || mw == 0)
73                 errx(1, "Usage: %s <syscall number> <max wired>", argv[0]);
74
75         ps = getpagesize();
76         size = mw / 100 * 80 * ps;      /* Use 80% of vm.max_user_wired */
77         while (size > 0) {
78                 res = syscall(no, TALLOC, &p, &size);
79                 if (res == -1) {
80                         if (errno != ENOMEM)
81                                 warn("contigmalloc(%lu pages) failed",
82                                     size);
83                 } else {
84 #if defined(TEST)
85                         fprintf(stderr, "pre contigmalloc(%lu pages): %lu MiB\n",
86                             size, size * ps / 1024 / 1024);
87 #endif
88                         res = syscall(no, TFREE, &p, &size);
89 #if defined(TEST)
90                         fprintf(stderr, "contigfree(%lu pages)\n",
91                             size);
92 #endif
93                 }
94                 size /= 2;
95         }
96 }
97
98 int
99 main(int argc, char *argv[])
100 {
101         test(argc, argv);
102
103         return (0);
104 }
105
106 EOF
107 mycc -o /tmp/ctest2 -Wall -Wextra -O0 -g $dir/ctest2.c || exit 1
108 rm $dir/ctest2.c
109
110 cd $dir
111 cat > Makefile <<EOF
112 KMOD= cmalloc2
113 SRCS= cmalloc2.c
114
115 .include <bsd.kmod.mk>
116 EOF
117
118 sed '1,/^EOF2/d' < $odir/$0 > cmalloc2.c
119 make depend all || exit 1
120 kldload $dir/cmalloc2.ko || exit 1
121
122 cd $odir
123 mw=$((`sysctl -n vm.max_user_wired` - \
124     `sysctl -n vm.stats.vm.v_user_wire_count`)) || exit 1
125 /tmp/ctest2 `sysctl -n debug.cmalloc_offset` $mw #2>&1 | tail -5
126 kldunload $dir/cmalloc2.ko
127 rm -rf $dir /tmp/ctest2
128 exit 0
129
130 EOF2
131 #include <sys/param.h>
132 #include <sys/kernel.h>
133 #include <sys/malloc.h>
134 #include <sys/module.h>
135 #include <sys/proc.h>
136 #include <sys/sysctl.h>
137 #include <sys/sysent.h>
138 #include <sys/sysproto.h>
139 #include <sys/systm.h>
140
141 #define TALLOC 1
142 #define TFREE  2
143
144 /*
145  * Hook up a syscall for contigmalloc testing.
146  */
147
148 struct cmalloc_args {
149         int a_op;
150         void *a_ptr;
151         void *a_size;
152 };
153
154 static int
155 cmalloc(struct thread *td, struct cmalloc_args *uap)
156 {
157         void *p;
158         unsigned long size;
159         int error;
160
161         error = copyin(uap->a_size, &size, sizeof(size));
162         if (error != 0) {
163                 return (error);
164         }
165         switch (uap->a_op) {
166         case TFREE:
167                 error = copyin(uap->a_ptr, &p, sizeof(p));
168                 if (error == 0) {
169                         if (p != NULL)
170                                 contigfree(p, size, M_TEMP);
171                 }
172                 return (error);
173
174         case TALLOC:
175                 p = contigmalloc(size, M_TEMP, M_NOWAIT, 0ul, ~0ul, 4096, 0);
176                 if (p != NULL) {
177                         error = copyout(&p, uap->a_ptr, sizeof(p));
178                         return (error);
179                 }
180                 return (ENOMEM);
181         }
182         return (EINVAL);
183 }
184
185 /*
186  * The sysent for the new syscall
187  */
188 static struct sysent cmalloc_sysent = {
189         .sy_narg =  3,                          /* sy_narg */
190         .sy_call = (sy_call_t *) cmalloc        /* sy_call */
191 };
192
193 /*
194  * The offset in sysent where the syscall is allocated.
195  */
196 static int cmalloc_offset = NO_SYSCALL;
197
198 SYSCTL_INT(_debug, OID_AUTO, cmalloc_offset, CTLFLAG_RD, &cmalloc_offset, 0,
199     "cmalloc syscall number");
200
201 /*
202  * The function called at load/unload.
203  */
204
205 static int
206 cmalloc_load(struct module *module, int cmd, void *arg)
207 {
208         int error = 0;
209
210         switch (cmd) {
211         case MOD_LOAD :
212                 break;
213         case MOD_UNLOAD :
214                 break;
215         default :
216                 error = EOPNOTSUPP;
217                 break;
218         }
219         return (error);
220 }
221
222 SYSCALL_MODULE(cmalloc_syscall, &cmalloc_offset, &cmalloc_sysent,
223     cmalloc_load, NULL);