blob: ebc1081dc1bae085a22087a27678fa94f7482269 [file] [log] [blame]
robbiew84457092003-01-10 17:48:12 +00001/* IBM Corporation */
2/* 01/02/2003 Port to LTP avenkat@us.ibm.com */
3/* 06/30/2001 Port to Linux nsharoff@us.ibm.com */
4/*
5 * Copyright (c) International Business Machines Corp., 2003
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
Wanlong Gao4548c6c2012-10-19 18:03:36 +080019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
robbiew84457092003-01-10 17:48:12 +000020 */
21
22/*
23 * This test mmaps over the tail of the brk segment, growing and
24 * shrinking brk over holes, while changing from small to large and
25 * large to small virtual memory representations. After mmaping over the
26 * end of the brk segment, it increases the brk which should split
27 * it into two segments (i.e. |---brk---|-mmap-|--more brk--|). Next it
28 * decreases the brk segment to the end of the map, and finally decreases
29 * it some more. Then more vmsegments are created by punching holes in
30 * the brk segments with munmap. This should cause the vm system to use a
31 * large virtual address space object to keep track of this process. The
32 * above test is then repeated using the large process object. After
33 * this, the brk is shrunk to less than 1 page before exiting in order to
34 * test the code which compacts large address space objects. It also asks
35 * for a huge mmap which is refused.
36 */
37
38#define _KMEMUSER
39#include <sys/types.h>
40#include <stdio.h>
41#include <sys/mman.h>
vapierf81795e2006-02-15 06:28:58 +000042#include <errno.h>
robbiew84457092003-01-10 17:48:12 +000043#include <unistd.h>
44#include <limits.h>
45
46/***** LTP Port *****/
47#include "test.h"
robbiew84457092003-01-10 17:48:12 +000048#define FAILED 0
49#define PASSED 1
50
51char *TCID = "mmapstress03";
52FILE *temp;
53int TST_TOTAL = 1;
robbiew84457092003-01-10 17:48:12 +000054
55int anyfail();
56void ok_exit();
57/***** ** ** *****/
58
subrata_modakba205d22008-12-11 10:39:40 +000059#define AS_SVSM_VSEG_MAX 48UL
60#define AS_SVSM_MMAP_MAX 16UL
robbiew84457092003-01-10 17:48:12 +000061
subrata_modakba205d22008-12-11 10:39:40 +000062#define EXTRA_VSEGS 2L
robbiew84457092003-01-10 17:48:12 +000063#define NUM_SEGS (AS_SVSM_VSEG_MAX + EXTRA_VSEGS)
64#define ERROR(M) (void)fprintf(stderr, "%s: errno = %d: " M "\n", progname, \
65 errno)
66#define NEG1 (char *)-1
subrata_modak36f63392009-01-06 05:39:35 +000067#define POINTER_SIZE (sizeof(void *) << 3)
robbiew84457092003-01-10 17:48:12 +000068
Wanlong Gao354ebb42012-12-07 10:10:04 +080069extern long sysconf(int name);
70extern void exit(int);
71extern time_t time(time_t *);
72extern char *ctime(const time_t *);
73static void do_test(caddr_t brk_max, long pagesize);
robbiew84457092003-01-10 17:48:12 +000074
75static char *progname;
76
Wanlong Gao354ebb42012-12-07 10:10:04 +080077 /*ARGSUSED*/ int main(int argc, char *argv[])
robbiew84457092003-01-10 17:48:12 +000078{
79 char *brk_max_addr, *hole_addr, *brk_start, *hole_start;
Wanlong Gao354ebb42012-12-07 10:10:04 +080080 size_t pagesize = (size_t) sysconf(_SC_PAGE_SIZE);
81 time_t t;
robbiew84457092003-01-10 17:48:12 +000082
83 progname = argv[0];
84
85 (void)time(&t);
Wanlong Gao354ebb42012-12-07 10:10:04 +080086// (void)printf("%s: Started %s", argv[0], ctime(&t));
robbiew84457092003-01-10 17:48:12 +000087 if ((brk_start = sbrk(0)) == NEG1) {
88 ERROR("initial sbrk failed");
89 anyfail();
90 }
Wanlong Gao354ebb42012-12-07 10:10:04 +080091 if ((u_long) brk_start % (u_long) pagesize) {
92 if (sbrk(pagesize - ((u_long) brk_start % (u_long) pagesize))
93 == NEG1) {
robbiew84457092003-01-10 17:48:12 +000094 ERROR("couldn't round up brk to a page boundary");
Wanlong Gao354ebb42012-12-07 10:10:04 +080095 anyfail();
robbiew84457092003-01-10 17:48:12 +000096 }
97 }
98 /* The brk is now at the beginning of a page. */
99
Garrett Cooperdf3eb162010-11-28 22:44:32 -0800100 if ((hole_addr = hole_start = sbrk(NUM_SEGS * 2 * pagesize)) == NEG1) {
robbiew84457092003-01-10 17:48:12 +0000101 ERROR("couldn't brk large space for segments");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800102 anyfail();
robbiew84457092003-01-10 17:48:12 +0000103 }
104 if ((brk_max_addr = sbrk(0)) == NEG1) {
105 ERROR("couldn't find top of brk");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800106 anyfail();
robbiew84457092003-01-10 17:48:12 +0000107 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800108 do_test((caddr_t) brk_max_addr, pagesize);
robbiew84457092003-01-10 17:48:12 +0000109
110 /* now make holes and repeat test */
111 while (hole_addr + pagesize < brk_max_addr) {
112 if (munmap(hole_addr, pagesize) == -1) {
113 ERROR("failed to munmap odd hole in brk segment");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800114 anyfail();
robbiew84457092003-01-10 17:48:12 +0000115 }
116 hole_addr += 2 * pagesize;
117 }
118
119 if (brk_max_addr != sbrk(0)) {
120 ERROR("do_test should leave the top of brk where it began");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800121 anyfail();
robbiew84457092003-01-10 17:48:12 +0000122 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800123 do_test((caddr_t) brk_max_addr, pagesize);
robbiew84457092003-01-10 17:48:12 +0000124
125 /* Shrink brk */
126 if (sbrk(-NUM_SEGS * pagesize) == NEG1) {
127 ERROR("couldn't brk back over holes");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800128 anyfail();
robbiew84457092003-01-10 17:48:12 +0000129 }
130 if ((brk_max_addr = sbrk(0)) == NEG1) {
131 ERROR("couldn't find top of break again");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800132 anyfail();
robbiew84457092003-01-10 17:48:12 +0000133 }
134 /* sbrked over about half the holes */
subrata_modakbdbaec52009-02-26 12:14:51 +0000135
Wanlong Gao354ebb42012-12-07 10:10:04 +0800136 hole_addr = hole_start + pagesize; /* munmap the other pages */
robbiew84457092003-01-10 17:48:12 +0000137 while (hole_addr + pagesize < brk_max_addr) {
138 if (munmap(hole_addr, pagesize) == -1) {
139 ERROR("failed to munmap even hole in brk segment");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800140 anyfail();
robbiew84457092003-01-10 17:48:12 +0000141 }
142 hole_addr += 2 * pagesize;
143 }
144 /* munmaped the rest of the brk except a little at the beginning */
145
146 if (brk(brk_start) == -1) {
147 ERROR("failed to completely remove brk");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800148 anyfail();
robbiew84457092003-01-10 17:48:12 +0000149 }
150 if (sbrk(pagesize) == NEG1 || sbrk(-pagesize) == NEG1) {
151 ERROR("failed to fiddle with brk at the end");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800152 anyfail();
robbiew84457092003-01-10 17:48:12 +0000153 }
154 /* Ask for a ridiculously large mmap region at a high address */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800155 if (mmap((caddr_t) (1UL << (POINTER_SIZE - 1)) - pagesize,
156 (size_t) ((1UL << (POINTER_SIZE - 1)) - pagesize),
157 PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_FIXED | MAP_SHARED,
158 0, 0)
159 != (caddr_t) - 1) {
robbiew84457092003-01-10 17:48:12 +0000160 ERROR("really large mmap didn't fail");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800161 anyfail();
robbiew84457092003-01-10 17:48:12 +0000162 }
subrata_modak428f6a32009-06-18 16:52:42 +0000163 if (errno != ENOMEM && errno != EINVAL) {
164 ERROR("really large mmap didn't set errno = ENOMEM nor EINVAL");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800165 anyfail();
robbiew84457092003-01-10 17:48:12 +0000166 }
167 (void)time(&t);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800168// (void)printf("%s: Finished %s", argv[0], ctime(&t));
robbiew84457092003-01-10 17:48:12 +0000169 ok_exit();
Garrett Cooper2c282152010-12-16 00:55:50 -0800170 tst_exit();
robbiew84457092003-01-10 17:48:12 +0000171}
172
173/*
174 * do_test assumes that brk_max is a multiple of pagesize
175 */
176
177static
Wanlong Gao354ebb42012-12-07 10:10:04 +0800178void do_test(caddr_t brk_max, long pagesize)
robbiew84457092003-01-10 17:48:12 +0000179{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800180 if (mmap((caddr_t) ((long)brk_max - 3 * pagesize), (2 * pagesize),
181 PROT_READ | PROT_WRITE,
182 MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, 0, 0)
183 == (caddr_t) - 1) {
robbiew84457092003-01-10 17:48:12 +0000184 ERROR("mmap failed");
185 anyfail();
186 }
187 /* extend mmap */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800188 if (mmap((caddr_t) ((long)brk_max - 2 * pagesize), (2 * pagesize),
189 PROT_READ | PROT_WRITE,
190 MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, 0, 0)
191 == (caddr_t) - 1) {
robbiew84457092003-01-10 17:48:12 +0000192 ERROR("mmap failed");
193 anyfail();
194 }
195 if (sbrk(pagesize) == NEG1) {
196 ERROR("sbrk failed to grow over mmaped region");
197 anyfail();
198 }
199 if (sbrk(-pagesize) == NEG1) {
200 ERROR("sbrk failed to shrink back to mmaped region");
201 anyfail();
202 }
203 if (sbrk(-pagesize) == NEG1) {
204 ERROR("sbrk failed to shrink over mmaped region more");
205 anyfail();
206 }
207 if (sbrk(-pagesize) == NEG1) {
208 ERROR("sbrk failed to shrink some more");
209 anyfail();
210 }
211 if (sbrk(2 * pagesize) == NEG1) {
212 ERROR("sbrk failed to change brk segment to original size");
213 anyfail();
214 }
215}
216
217/***** LTP Port *****/
218void ok_exit()
219{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800220 tst_resm(TPASS, "Test passed");
221 tst_exit();
robbiew84457092003-01-10 17:48:12 +0000222}
223
robbiew84457092003-01-10 17:48:12 +0000224int anyfail()
225{
Cyril Hrubis526fdf82014-12-04 14:35:01 +0100226 tst_brkm(TFAIL, NULL, "Test failed");
robbiew84457092003-01-10 17:48:12 +0000227}
228
Chris Dearmanec6edca2012-10-17 19:54:01 -0700229/***** ** ** *****/