xref: /aosp_15_r20/external/ltp/testcases/kernel/mem/mmapstress/mmapstress03.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker /* IBM Corporation */
2*49cdfc7eSAndroid Build Coastguard Worker /* 01/02/2003	Port to LTP [email protected] */
3*49cdfc7eSAndroid Build Coastguard Worker /* 06/30/2001	Port to Linux	[email protected] */
4*49cdfc7eSAndroid Build Coastguard Worker /*
5*49cdfc7eSAndroid Build Coastguard Worker  *   Copyright (c) International Business Machines  Corp., 2003
6*49cdfc7eSAndroid Build Coastguard Worker  *
7*49cdfc7eSAndroid Build Coastguard Worker  *   This program is free software;  you can redistribute it and/or modify
8*49cdfc7eSAndroid Build Coastguard Worker  *   it under the terms of the GNU General Public License as published by
9*49cdfc7eSAndroid Build Coastguard Worker  *   the Free Software Foundation; either version 2 of the License, or
10*49cdfc7eSAndroid Build Coastguard Worker  *   (at your option) any later version.
11*49cdfc7eSAndroid Build Coastguard Worker  *
12*49cdfc7eSAndroid Build Coastguard Worker  *   This program is distributed in the hope that it will be useful,
13*49cdfc7eSAndroid Build Coastguard Worker  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
14*49cdfc7eSAndroid Build Coastguard Worker  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15*49cdfc7eSAndroid Build Coastguard Worker  *   the GNU General Public License for more details.
16*49cdfc7eSAndroid Build Coastguard Worker  *
17*49cdfc7eSAndroid Build Coastguard Worker  *   You should have received a copy of the GNU General Public License
18*49cdfc7eSAndroid Build Coastguard Worker  *   along with this program;  if not, write to the Free Software
19*49cdfc7eSAndroid Build Coastguard Worker  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20*49cdfc7eSAndroid Build Coastguard Worker  */
21*49cdfc7eSAndroid Build Coastguard Worker 
22*49cdfc7eSAndroid Build Coastguard Worker /*
23*49cdfc7eSAndroid Build Coastguard Worker  *      This test mmaps over the tail of the brk segment, growing and
24*49cdfc7eSAndroid Build Coastguard Worker  *	shrinking brk over holes, while changing from small to large and
25*49cdfc7eSAndroid Build Coastguard Worker  *	large to small virtual memory representations.  After mmaping over the
26*49cdfc7eSAndroid Build Coastguard Worker  *	end of the brk segment, it increases the brk which should split
27*49cdfc7eSAndroid Build Coastguard Worker  *	it into two segments (i.e.  |---brk---|-mmap-|--more brk--|).  Next it
28*49cdfc7eSAndroid Build Coastguard Worker  *	decreases the brk segment to the end of the map, and finally decreases
29*49cdfc7eSAndroid Build Coastguard Worker  *	it some more.  Then more vmsegments are created by punching holes in
30*49cdfc7eSAndroid Build Coastguard Worker  *	the brk segments with munmap.  This should cause the vm system to use a
31*49cdfc7eSAndroid Build Coastguard Worker  *	large virtual address space object to keep track of this process.  The
32*49cdfc7eSAndroid Build Coastguard Worker  *	above test is then repeated using the large process object.  After
33*49cdfc7eSAndroid Build Coastguard Worker  *	this, the brk is shrunk to less than 1 page before exiting in order to
34*49cdfc7eSAndroid Build Coastguard Worker  *	test the code which compacts large address space objects.  It also asks
35*49cdfc7eSAndroid Build Coastguard Worker  *	for a huge mmap which is refused.
36*49cdfc7eSAndroid Build Coastguard Worker  */
37*49cdfc7eSAndroid Build Coastguard Worker 
38*49cdfc7eSAndroid Build Coastguard Worker #define _KMEMUSER
39*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
40*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
41*49cdfc7eSAndroid Build Coastguard Worker #include <sys/mman.h>
42*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
43*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
44*49cdfc7eSAndroid Build Coastguard Worker #include <limits.h>
45*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
46*49cdfc7eSAndroid Build Coastguard Worker #include <stdint.h>
47*49cdfc7eSAndroid Build Coastguard Worker 
48*49cdfc7eSAndroid Build Coastguard Worker #include "test.h"
49*49cdfc7eSAndroid Build Coastguard Worker #include "tst_kernel.h"
50*49cdfc7eSAndroid Build Coastguard Worker 
51*49cdfc7eSAndroid Build Coastguard Worker char *TCID = "mmapstress03";
52*49cdfc7eSAndroid Build Coastguard Worker FILE *temp;
53*49cdfc7eSAndroid Build Coastguard Worker int TST_TOTAL = 1;
54*49cdfc7eSAndroid Build Coastguard Worker 
55*49cdfc7eSAndroid Build Coastguard Worker int anyfail();
56*49cdfc7eSAndroid Build Coastguard Worker void ok_exit();
57*49cdfc7eSAndroid Build Coastguard Worker 
58*49cdfc7eSAndroid Build Coastguard Worker #define AS_SVSM_VSEG_MAX	48UL
59*49cdfc7eSAndroid Build Coastguard Worker #define AS_SVSM_MMAP_MAX	16UL
60*49cdfc7eSAndroid Build Coastguard Worker 
61*49cdfc7eSAndroid Build Coastguard Worker #define EXTRA_VSEGS	2L
62*49cdfc7eSAndroid Build Coastguard Worker #define NUM_SEGS	(AS_SVSM_VSEG_MAX + EXTRA_VSEGS)
63*49cdfc7eSAndroid Build Coastguard Worker #define ERROR(M) (void)fprintf(stderr, "%s: errno = %d: " M "\n", TCID, \
64*49cdfc7eSAndroid Build Coastguard Worker 			errno)
65*49cdfc7eSAndroid Build Coastguard Worker #define NEG1	(char *)-1
66*49cdfc7eSAndroid Build Coastguard Worker 
67*49cdfc7eSAndroid Build Coastguard Worker static void do_test(void* brk_max, long pagesize);
68*49cdfc7eSAndroid Build Coastguard Worker 
main(void)69*49cdfc7eSAndroid Build Coastguard Worker int main(void)
70*49cdfc7eSAndroid Build Coastguard Worker {
71*49cdfc7eSAndroid Build Coastguard Worker 	char *brk_max_addr, *hole_addr, *brk_start, *hole_start;
72*49cdfc7eSAndroid Build Coastguard Worker 	size_t pagesize = (size_t) sysconf(_SC_PAGE_SIZE);
73*49cdfc7eSAndroid Build Coastguard Worker 	int kernel_bits = tst_kernel_bits();
74*49cdfc7eSAndroid Build Coastguard Worker 
75*49cdfc7eSAndroid Build Coastguard Worker 	if ((brk_start = sbrk(0)) == NEG1) {
76*49cdfc7eSAndroid Build Coastguard Worker 		ERROR("initial sbrk failed");
77*49cdfc7eSAndroid Build Coastguard Worker 		anyfail();
78*49cdfc7eSAndroid Build Coastguard Worker 	}
79*49cdfc7eSAndroid Build Coastguard Worker 	if ((u_long) brk_start % (u_long) pagesize) {
80*49cdfc7eSAndroid Build Coastguard Worker 		if (sbrk(pagesize - ((u_long) brk_start % (u_long) pagesize))
81*49cdfc7eSAndroid Build Coastguard Worker 		    == NEG1) {
82*49cdfc7eSAndroid Build Coastguard Worker 			ERROR("couldn't round up brk to a page boundary");
83*49cdfc7eSAndroid Build Coastguard Worker 			anyfail();
84*49cdfc7eSAndroid Build Coastguard Worker 		}
85*49cdfc7eSAndroid Build Coastguard Worker 	}
86*49cdfc7eSAndroid Build Coastguard Worker 	/* The brk is now at the beginning of a page. */
87*49cdfc7eSAndroid Build Coastguard Worker 
88*49cdfc7eSAndroid Build Coastguard Worker 	if ((hole_addr = hole_start = sbrk(NUM_SEGS * 2 * pagesize)) == NEG1) {
89*49cdfc7eSAndroid Build Coastguard Worker 		ERROR("couldn't brk large space for segments");
90*49cdfc7eSAndroid Build Coastguard Worker 		anyfail();
91*49cdfc7eSAndroid Build Coastguard Worker 	}
92*49cdfc7eSAndroid Build Coastguard Worker 	if ((brk_max_addr = sbrk(0)) == NEG1) {
93*49cdfc7eSAndroid Build Coastguard Worker 		ERROR("couldn't find top of brk");
94*49cdfc7eSAndroid Build Coastguard Worker 		anyfail();
95*49cdfc7eSAndroid Build Coastguard Worker 	}
96*49cdfc7eSAndroid Build Coastguard Worker 	do_test((void*) brk_max_addr, pagesize);
97*49cdfc7eSAndroid Build Coastguard Worker 
98*49cdfc7eSAndroid Build Coastguard Worker 	/* now make holes and repeat test */
99*49cdfc7eSAndroid Build Coastguard Worker 	while (hole_addr + pagesize < brk_max_addr) {
100*49cdfc7eSAndroid Build Coastguard Worker 		if (munmap(hole_addr, pagesize) == -1) {
101*49cdfc7eSAndroid Build Coastguard Worker 			ERROR("failed to munmap odd hole in brk segment");
102*49cdfc7eSAndroid Build Coastguard Worker 			anyfail();
103*49cdfc7eSAndroid Build Coastguard Worker 		}
104*49cdfc7eSAndroid Build Coastguard Worker 		hole_addr += 2 * pagesize;
105*49cdfc7eSAndroid Build Coastguard Worker 	}
106*49cdfc7eSAndroid Build Coastguard Worker 
107*49cdfc7eSAndroid Build Coastguard Worker 	if (brk_max_addr != sbrk(0)) {
108*49cdfc7eSAndroid Build Coastguard Worker 		ERROR("do_test should leave the top of brk where it began");
109*49cdfc7eSAndroid Build Coastguard Worker 		anyfail();
110*49cdfc7eSAndroid Build Coastguard Worker 	}
111*49cdfc7eSAndroid Build Coastguard Worker 	do_test((void*) brk_max_addr, pagesize);
112*49cdfc7eSAndroid Build Coastguard Worker 
113*49cdfc7eSAndroid Build Coastguard Worker 	/* Shrink brk */
114*49cdfc7eSAndroid Build Coastguard Worker 	if (sbrk(-NUM_SEGS * pagesize) == NEG1) {
115*49cdfc7eSAndroid Build Coastguard Worker 		ERROR("couldn't brk back over holes");
116*49cdfc7eSAndroid Build Coastguard Worker 		anyfail();
117*49cdfc7eSAndroid Build Coastguard Worker 	}
118*49cdfc7eSAndroid Build Coastguard Worker 	if ((brk_max_addr = sbrk(0)) == NEG1) {
119*49cdfc7eSAndroid Build Coastguard Worker 		ERROR("couldn't find top of break again");
120*49cdfc7eSAndroid Build Coastguard Worker 		anyfail();
121*49cdfc7eSAndroid Build Coastguard Worker 	}
122*49cdfc7eSAndroid Build Coastguard Worker 	/* sbrked over about half the holes */
123*49cdfc7eSAndroid Build Coastguard Worker 
124*49cdfc7eSAndroid Build Coastguard Worker 	hole_addr = hole_start + pagesize;	/* munmap the other pages */
125*49cdfc7eSAndroid Build Coastguard Worker 	while (hole_addr + pagesize < brk_max_addr) {
126*49cdfc7eSAndroid Build Coastguard Worker 		if (munmap(hole_addr, pagesize) == -1) {
127*49cdfc7eSAndroid Build Coastguard Worker 			ERROR("failed to munmap even hole in brk segment");
128*49cdfc7eSAndroid Build Coastguard Worker 			anyfail();
129*49cdfc7eSAndroid Build Coastguard Worker 		}
130*49cdfc7eSAndroid Build Coastguard Worker 		hole_addr += 2 * pagesize;
131*49cdfc7eSAndroid Build Coastguard Worker 	}
132*49cdfc7eSAndroid Build Coastguard Worker 	/* munmaped the rest of the brk except a little at the beginning */
133*49cdfc7eSAndroid Build Coastguard Worker 
134*49cdfc7eSAndroid Build Coastguard Worker 	if (brk(brk_start) == -1) {
135*49cdfc7eSAndroid Build Coastguard Worker 		ERROR("failed to completely remove brk");
136*49cdfc7eSAndroid Build Coastguard Worker 		anyfail();
137*49cdfc7eSAndroid Build Coastguard Worker 	}
138*49cdfc7eSAndroid Build Coastguard Worker 	if (sbrk(pagesize) == NEG1 || sbrk(-pagesize) == NEG1) {
139*49cdfc7eSAndroid Build Coastguard Worker 		ERROR("failed to fiddle with brk at the end");
140*49cdfc7eSAndroid Build Coastguard Worker 		anyfail();
141*49cdfc7eSAndroid Build Coastguard Worker 	}
142*49cdfc7eSAndroid Build Coastguard Worker 
143*49cdfc7eSAndroid Build Coastguard Worker 	/* Ask for a ridiculously large mmap region at a high address */
144*49cdfc7eSAndroid Build Coastguard Worker 	if (mmap((void*) (((uintptr_t)1) << ((sizeof(void*)<<3) - 1)) - pagesize,
145*49cdfc7eSAndroid Build Coastguard Worker 		 (size_t) ((1ULL << (kernel_bits - 1)) - pagesize),
146*49cdfc7eSAndroid Build Coastguard Worker 		 PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_FIXED | MAP_SHARED,
147*49cdfc7eSAndroid Build Coastguard Worker 		 0, 0)
148*49cdfc7eSAndroid Build Coastguard Worker 	    != (void*) - 1) {
149*49cdfc7eSAndroid Build Coastguard Worker 		ERROR("really large mmap didn't fail");
150*49cdfc7eSAndroid Build Coastguard Worker 		anyfail();
151*49cdfc7eSAndroid Build Coastguard Worker 	}
152*49cdfc7eSAndroid Build Coastguard Worker 	if (errno != ENOMEM && errno != EINVAL) {
153*49cdfc7eSAndroid Build Coastguard Worker 		ERROR("really large mmap didn't set errno = ENOMEM nor EINVAL");
154*49cdfc7eSAndroid Build Coastguard Worker 		anyfail();
155*49cdfc7eSAndroid Build Coastguard Worker 	}
156*49cdfc7eSAndroid Build Coastguard Worker 
157*49cdfc7eSAndroid Build Coastguard Worker 	ok_exit();
158*49cdfc7eSAndroid Build Coastguard Worker 	tst_exit();
159*49cdfc7eSAndroid Build Coastguard Worker }
160*49cdfc7eSAndroid Build Coastguard Worker 
161*49cdfc7eSAndroid Build Coastguard Worker /*
162*49cdfc7eSAndroid Build Coastguard Worker  * do_test assumes that brk_max is a multiple of pagesize
163*49cdfc7eSAndroid Build Coastguard Worker  */
164*49cdfc7eSAndroid Build Coastguard Worker 
do_test(void * brk_max,long pagesize)165*49cdfc7eSAndroid Build Coastguard Worker static void do_test(void* brk_max, long pagesize)
166*49cdfc7eSAndroid Build Coastguard Worker {
167*49cdfc7eSAndroid Build Coastguard Worker 	if (mmap((void*) ((long)brk_max - 3 * pagesize), (2 * pagesize),
168*49cdfc7eSAndroid Build Coastguard Worker 		 PROT_READ | PROT_WRITE,
169*49cdfc7eSAndroid Build Coastguard Worker 		 MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, 0, 0)
170*49cdfc7eSAndroid Build Coastguard Worker 	    == (void*) - 1) {
171*49cdfc7eSAndroid Build Coastguard Worker 		ERROR("mmap failed");
172*49cdfc7eSAndroid Build Coastguard Worker 		anyfail();
173*49cdfc7eSAndroid Build Coastguard Worker 	}
174*49cdfc7eSAndroid Build Coastguard Worker 	/* extend mmap */
175*49cdfc7eSAndroid Build Coastguard Worker 	if (mmap((void*) ((long)brk_max - 2 * pagesize), (2 * pagesize),
176*49cdfc7eSAndroid Build Coastguard Worker 		 PROT_READ | PROT_WRITE,
177*49cdfc7eSAndroid Build Coastguard Worker 		 MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, 0, 0)
178*49cdfc7eSAndroid Build Coastguard Worker 	    == (void*) - 1) {
179*49cdfc7eSAndroid Build Coastguard Worker 		ERROR("mmap failed");
180*49cdfc7eSAndroid Build Coastguard Worker 		anyfail();
181*49cdfc7eSAndroid Build Coastguard Worker 	}
182*49cdfc7eSAndroid Build Coastguard Worker 	if (sbrk(pagesize) == NEG1) {
183*49cdfc7eSAndroid Build Coastguard Worker 		ERROR("sbrk failed to grow over mmaped region");
184*49cdfc7eSAndroid Build Coastguard Worker 		anyfail();
185*49cdfc7eSAndroid Build Coastguard Worker 	}
186*49cdfc7eSAndroid Build Coastguard Worker 	if (sbrk(-pagesize) == NEG1) {
187*49cdfc7eSAndroid Build Coastguard Worker 		ERROR("sbrk failed to shrink back to mmaped region");
188*49cdfc7eSAndroid Build Coastguard Worker 		anyfail();
189*49cdfc7eSAndroid Build Coastguard Worker 	}
190*49cdfc7eSAndroid Build Coastguard Worker 	if (sbrk(-pagesize) == NEG1) {
191*49cdfc7eSAndroid Build Coastguard Worker 		ERROR("sbrk failed to shrink over mmaped region more");
192*49cdfc7eSAndroid Build Coastguard Worker 		anyfail();
193*49cdfc7eSAndroid Build Coastguard Worker 	}
194*49cdfc7eSAndroid Build Coastguard Worker 	if (sbrk(-pagesize) == NEG1) {
195*49cdfc7eSAndroid Build Coastguard Worker 		ERROR("sbrk failed to shrink some more");
196*49cdfc7eSAndroid Build Coastguard Worker 		anyfail();
197*49cdfc7eSAndroid Build Coastguard Worker 	}
198*49cdfc7eSAndroid Build Coastguard Worker 	if (sbrk(2 * pagesize) == NEG1) {
199*49cdfc7eSAndroid Build Coastguard Worker 		ERROR("sbrk failed to change brk segment to original size");
200*49cdfc7eSAndroid Build Coastguard Worker 		anyfail();
201*49cdfc7eSAndroid Build Coastguard Worker 	}
202*49cdfc7eSAndroid Build Coastguard Worker }
203*49cdfc7eSAndroid Build Coastguard Worker 
ok_exit(void)204*49cdfc7eSAndroid Build Coastguard Worker void ok_exit(void)
205*49cdfc7eSAndroid Build Coastguard Worker {
206*49cdfc7eSAndroid Build Coastguard Worker 	tst_resm(TPASS, "Test passed");
207*49cdfc7eSAndroid Build Coastguard Worker 	tst_exit();
208*49cdfc7eSAndroid Build Coastguard Worker }
209*49cdfc7eSAndroid Build Coastguard Worker 
anyfail(void)210*49cdfc7eSAndroid Build Coastguard Worker int anyfail(void)
211*49cdfc7eSAndroid Build Coastguard Worker {
212*49cdfc7eSAndroid Build Coastguard Worker 	tst_brkm(TFAIL, NULL, "Test failed");
213*49cdfc7eSAndroid Build Coastguard Worker }
214