xref: /aosp_15_r20/external/ltp/testcases/kernel/mem/mtest06/mmap3.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) International Business Machines Corp., 2001
4*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (C) 2016 Cyril Hrubis <[email protected]>
5*49cdfc7eSAndroid Build Coastguard Worker  * Author: Manoj Iyer, IBM Austin TX <[email protected]>, 2001
6*49cdfc7eSAndroid Build Coastguard Worker  *
7*49cdfc7eSAndroid Build Coastguard Worker  * Tests the LINUX memory manager. The program is aimed at stressing the memory
8*49cdfc7eSAndroid Build Coastguard Worker  * manager by repeaded map/write/unmap of file/memory of random size (maximum
9*49cdfc7eSAndroid Build Coastguard Worker  * 1GB) this is done by multiple threads.
10*49cdfc7eSAndroid Build Coastguard Worker  *
11*49cdfc7eSAndroid Build Coastguard Worker  * Create a file of random size upto 1000 times 4096, map it, change the
12*49cdfc7eSAndroid Build Coastguard Worker  * contents of the file and unmap it. This is repeated several times for the
13*49cdfc7eSAndroid Build Coastguard Worker  * specified number of hours by a certain number of threads.
14*49cdfc7eSAndroid Build Coastguard Worker  */
15*49cdfc7eSAndroid Build Coastguard Worker 
16*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
17*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
18*49cdfc7eSAndroid Build Coastguard Worker #include <limits.h>
19*49cdfc7eSAndroid Build Coastguard Worker #include <pthread.h>
20*49cdfc7eSAndroid Build Coastguard Worker #include "tst_safe_pthread.h"
21*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
22*49cdfc7eSAndroid Build Coastguard Worker 
23*49cdfc7eSAndroid Build Coastguard Worker static char *str_loops;
24*49cdfc7eSAndroid Build Coastguard Worker static char *str_threads;
25*49cdfc7eSAndroid Build Coastguard Worker static char *map_private;
26*49cdfc7eSAndroid Build Coastguard Worker 
27*49cdfc7eSAndroid Build Coastguard Worker static int loops = 1000;
28*49cdfc7eSAndroid Build Coastguard Worker static int threads = 40;
29*49cdfc7eSAndroid Build Coastguard Worker 
30*49cdfc7eSAndroid Build Coastguard Worker static volatile int sig_caught;
31*49cdfc7eSAndroid Build Coastguard Worker static int threads_running;
32*49cdfc7eSAndroid Build Coastguard Worker 
mkfile(int * size)33*49cdfc7eSAndroid Build Coastguard Worker static int mkfile(int *size)
34*49cdfc7eSAndroid Build Coastguard Worker {
35*49cdfc7eSAndroid Build Coastguard Worker 	int fd;
36*49cdfc7eSAndroid Build Coastguard Worker 	int index = 0;
37*49cdfc7eSAndroid Build Coastguard Worker 	char buf[4096];
38*49cdfc7eSAndroid Build Coastguard Worker 	char template[PATH_MAX];
39*49cdfc7eSAndroid Build Coastguard Worker 
40*49cdfc7eSAndroid Build Coastguard Worker 	memset(buf, 'a', 4096);
41*49cdfc7eSAndroid Build Coastguard Worker 	snprintf(template, PATH_MAX, "ashfileXXXXXX");
42*49cdfc7eSAndroid Build Coastguard Worker 	if ((fd = mkstemp(template)) == -1)
43*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK | TERRNO, "mkstemp()");
44*49cdfc7eSAndroid Build Coastguard Worker 	unlink(template);
45*49cdfc7eSAndroid Build Coastguard Worker 
46*49cdfc7eSAndroid Build Coastguard Worker 	*size = (1 + (int)(1000.0 * rand() / (RAND_MAX + 1.0))) * 4096;
47*49cdfc7eSAndroid Build Coastguard Worker 
48*49cdfc7eSAndroid Build Coastguard Worker 	while (index < *size) {
49*49cdfc7eSAndroid Build Coastguard Worker 		index += sizeof(buf);
50*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_WRITE(SAFE_WRITE_ALL, fd, buf, sizeof(buf));
51*49cdfc7eSAndroid Build Coastguard Worker 	}
52*49cdfc7eSAndroid Build Coastguard Worker 
53*49cdfc7eSAndroid Build Coastguard Worker 	fsync(fd);
54*49cdfc7eSAndroid Build Coastguard Worker 
55*49cdfc7eSAndroid Build Coastguard Worker 	return fd;
56*49cdfc7eSAndroid Build Coastguard Worker }
57*49cdfc7eSAndroid Build Coastguard Worker 
58*49cdfc7eSAndroid Build Coastguard Worker static void exit_thread(void) __attribute__ ((noreturn));
59*49cdfc7eSAndroid Build Coastguard Worker 
exit_thread(void)60*49cdfc7eSAndroid Build Coastguard Worker static void exit_thread(void)
61*49cdfc7eSAndroid Build Coastguard Worker {
62*49cdfc7eSAndroid Build Coastguard Worker 	tst_atomic_dec(&threads_running);
63*49cdfc7eSAndroid Build Coastguard Worker 	pthread_exit(NULL);
64*49cdfc7eSAndroid Build Coastguard Worker }
65*49cdfc7eSAndroid Build Coastguard Worker 
map_write_unmap(void * args)66*49cdfc7eSAndroid Build Coastguard Worker void *map_write_unmap(void *args)
67*49cdfc7eSAndroid Build Coastguard Worker {
68*49cdfc7eSAndroid Build Coastguard Worker 	int fsize;
69*49cdfc7eSAndroid Build Coastguard Worker 	int fd;
70*49cdfc7eSAndroid Build Coastguard Worker 	int i;
71*49cdfc7eSAndroid Build Coastguard Worker 	void *addr;
72*49cdfc7eSAndroid Build Coastguard Worker 	long tid = (long)args;
73*49cdfc7eSAndroid Build Coastguard Worker 
74*49cdfc7eSAndroid Build Coastguard Worker 	tst_atomic_inc(&threads_running);
75*49cdfc7eSAndroid Build Coastguard Worker 
76*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < loops; i++) {
77*49cdfc7eSAndroid Build Coastguard Worker 		if (sig_caught)
78*49cdfc7eSAndroid Build Coastguard Worker 			exit_thread();
79*49cdfc7eSAndroid Build Coastguard Worker 
80*49cdfc7eSAndroid Build Coastguard Worker 		if ((fd = mkfile(&fsize)) == -1)
81*49cdfc7eSAndroid Build Coastguard Worker 			exit_thread();
82*49cdfc7eSAndroid Build Coastguard Worker 
83*49cdfc7eSAndroid Build Coastguard Worker 		addr = SAFE_MMAP(NULL, fsize, PROT_WRITE | PROT_READ,
84*49cdfc7eSAndroid Build Coastguard Worker 				 map_private ? MAP_PRIVATE : MAP_SHARED, fd, 0);
85*49cdfc7eSAndroid Build Coastguard Worker 
86*49cdfc7eSAndroid Build Coastguard Worker 		memset(addr, 'A', fsize);
87*49cdfc7eSAndroid Build Coastguard Worker 
88*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "Thread %4li, addr [%p], size %4ikB, iter %4d",
89*49cdfc7eSAndroid Build Coastguard Worker 			tid, addr, fsize/1024, i);
90*49cdfc7eSAndroid Build Coastguard Worker 
91*49cdfc7eSAndroid Build Coastguard Worker 		usleep(1);
92*49cdfc7eSAndroid Build Coastguard Worker 
93*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_MUNMAP(addr, fsize);
94*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_CLOSE(fd);
95*49cdfc7eSAndroid Build Coastguard Worker 	}
96*49cdfc7eSAndroid Build Coastguard Worker 
97*49cdfc7eSAndroid Build Coastguard Worker 	exit_thread();
98*49cdfc7eSAndroid Build Coastguard Worker }
99*49cdfc7eSAndroid Build Coastguard Worker 
sig_handler(int signal)100*49cdfc7eSAndroid Build Coastguard Worker static void sig_handler(int signal)
101*49cdfc7eSAndroid Build Coastguard Worker {
102*49cdfc7eSAndroid Build Coastguard Worker 	sig_caught = signal;
103*49cdfc7eSAndroid Build Coastguard Worker }
104*49cdfc7eSAndroid Build Coastguard Worker 
test_mmap(void)105*49cdfc7eSAndroid Build Coastguard Worker static void test_mmap(void)
106*49cdfc7eSAndroid Build Coastguard Worker {
107*49cdfc7eSAndroid Build Coastguard Worker 	long i;
108*49cdfc7eSAndroid Build Coastguard Worker 	pthread_t thids[threads];
109*49cdfc7eSAndroid Build Coastguard Worker 
110*49cdfc7eSAndroid Build Coastguard Worker 	alarm(tst_remaining_runtime());
111*49cdfc7eSAndroid Build Coastguard Worker 
112*49cdfc7eSAndroid Build Coastguard Worker 	while (!sig_caught) {
113*49cdfc7eSAndroid Build Coastguard Worker 		for (i = 0; i < threads; i++) {
114*49cdfc7eSAndroid Build Coastguard Worker 			SAFE_PTHREAD_CREATE(&thids[i], NULL,
115*49cdfc7eSAndroid Build Coastguard Worker 			                    map_write_unmap, (void*)i);
116*49cdfc7eSAndroid Build Coastguard Worker 			sched_yield();
117*49cdfc7eSAndroid Build Coastguard Worker 		}
118*49cdfc7eSAndroid Build Coastguard Worker 
119*49cdfc7eSAndroid Build Coastguard Worker 		for (i = 0; i < threads; i++)
120*49cdfc7eSAndroid Build Coastguard Worker 			SAFE_PTHREAD_JOIN(thids[i], NULL);
121*49cdfc7eSAndroid Build Coastguard Worker 	}
122*49cdfc7eSAndroid Build Coastguard Worker 
123*49cdfc7eSAndroid Build Coastguard Worker 	if (sig_caught == SIGALRM) {
124*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TPASS, "Test passed");
125*49cdfc7eSAndroid Build Coastguard Worker 	} else {
126*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL, "Unexpected signal caught %s",
127*49cdfc7eSAndroid Build Coastguard Worker 		        tst_strsig(sig_caught));
128*49cdfc7eSAndroid Build Coastguard Worker 	}
129*49cdfc7eSAndroid Build Coastguard Worker }
130*49cdfc7eSAndroid Build Coastguard Worker 
setup(void)131*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
132*49cdfc7eSAndroid Build Coastguard Worker {
133*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_parse_int(str_loops, &loops, 1, INT_MAX))
134*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Invalid number of loops '%s'", str_loops);
135*49cdfc7eSAndroid Build Coastguard Worker 
136*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_parse_int(str_threads, &threads, 1, INT_MAX))
137*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "Invalid number of threads '%s'", str_threads);
138*49cdfc7eSAndroid Build Coastguard Worker 
139*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_SIGNAL(SIGALRM, sig_handler);
140*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_SIGNAL(SIGBUS, sig_handler);
141*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_SIGNAL(SIGSEGV, sig_handler);
142*49cdfc7eSAndroid Build Coastguard Worker 
143*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int seed = time(NULL) % 100;
144*49cdfc7eSAndroid Build Coastguard Worker 
145*49cdfc7eSAndroid Build Coastguard Worker 	srand(seed);
146*49cdfc7eSAndroid Build Coastguard Worker 
147*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "Seed %u", seed);
148*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "Number of loops %i", loops);
149*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "Number of threads %i", threads);
150*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "MAP_PRIVATE = %i", map_private ? 1 : 0);
151*49cdfc7eSAndroid Build Coastguard Worker }
152*49cdfc7eSAndroid Build Coastguard Worker 
cleanup(void)153*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
154*49cdfc7eSAndroid Build Coastguard Worker {
155*49cdfc7eSAndroid Build Coastguard Worker 	static int flag;
156*49cdfc7eSAndroid Build Coastguard Worker 
157*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_atomic_inc(&flag) != 1)
158*49cdfc7eSAndroid Build Coastguard Worker 		exit_thread();
159*49cdfc7eSAndroid Build Coastguard Worker 
160*49cdfc7eSAndroid Build Coastguard Worker 	if (!threads_running)
161*49cdfc7eSAndroid Build Coastguard Worker 		return;
162*49cdfc7eSAndroid Build Coastguard Worker 
163*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "Waiting for %i threads to terminate", threads_running);
164*49cdfc7eSAndroid Build Coastguard Worker 
165*49cdfc7eSAndroid Build Coastguard Worker 	sig_caught = 1;
166*49cdfc7eSAndroid Build Coastguard Worker 
167*49cdfc7eSAndroid Build Coastguard Worker 	while ((volatile int)threads_running > 1) {
168*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "Running threads %i",
169*49cdfc7eSAndroid Build Coastguard Worker 		        (volatile int)threads_running);
170*49cdfc7eSAndroid Build Coastguard Worker 		usleep(500000);
171*49cdfc7eSAndroid Build Coastguard Worker 	}
172*49cdfc7eSAndroid Build Coastguard Worker }
173*49cdfc7eSAndroid Build Coastguard Worker 
174*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
175*49cdfc7eSAndroid Build Coastguard Worker 	.options = (struct tst_option[]) {
176*49cdfc7eSAndroid Build Coastguard Worker 		{"l:", &str_loops, "Number of map-write-unmap loops"},
177*49cdfc7eSAndroid Build Coastguard Worker 		{"n:", &str_threads, "Number of worker threads"},
178*49cdfc7eSAndroid Build Coastguard Worker 		{"p", &map_private, "Turns on MAP_PRIVATE (default MAP_SHARED)"},
179*49cdfc7eSAndroid Build Coastguard Worker 		{}
180*49cdfc7eSAndroid Build Coastguard Worker 	},
181*49cdfc7eSAndroid Build Coastguard Worker 	.needs_tmpdir = 1,
182*49cdfc7eSAndroid Build Coastguard Worker 	.setup = setup,
183*49cdfc7eSAndroid Build Coastguard Worker 	.cleanup = cleanup,
184*49cdfc7eSAndroid Build Coastguard Worker 	.test_all = test_mmap,
185*49cdfc7eSAndroid Build Coastguard Worker 	.max_runtime = 60,
186*49cdfc7eSAndroid Build Coastguard Worker };
187