• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2009 FUJITSU LIMITED
4  * Author: Li Zefan <lizf@cn.fujitsu.com>
5  */
6 
7 #include <sys/types.h>
8 #include <sys/mman.h>
9 #include <sys/shm.h>
10 #include <sys/stat.h>
11 #include <err.h>
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <getopt.h>
15 #include <limits.h>
16 #include <signal.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <unistd.h>
21 #define TST_NO_DEFAULT_MAIN
22 #include "tst_test.h"
23 
24 static int fd;
25 
26 static volatile int flag_exit;
27 static volatile int flag_allocated;
28 
29 static int opt_mmap_anon;
30 static int opt_mmap_file;
31 static int opt_mmap_lock1;
32 static int opt_mmap_lock2;
33 static int opt_shm;
34 static int opt_hugepage;
35 
36 static int key_id;			/* used with opt_shm */
37 static unsigned long memsize;
38 
39 #define FILE_HUGEPAGE	"/hugetlb/hugepagefile"
40 
41 #define MMAP_ANON	(SCHAR_MAX + 1)
42 #define MMAP_FILE	(SCHAR_MAX + 2)
43 #define MMAP_LOCK1	(SCHAR_MAX + 3)
44 #define MMAP_LOCK2	(SCHAR_MAX + 4)
45 #define SHM		(SCHAR_MAX + 5)
46 #define HUGEPAGE	(SCHAR_MAX + 6)
47 
48 static const struct option long_opts[] = {
49 	{"mmap-anon", 0, NULL, MMAP_ANON},
50 	{"mmap-file", 0, NULL, MMAP_FILE},
51 	{"mmap-lock1", 0, NULL, MMAP_LOCK1},
52 	{"mmap-lock2", 0, NULL, MMAP_LOCK2},
53 	{"shm", 0, NULL, SHM},
54 	{"hugepage", 0, NULL, HUGEPAGE},
55 	{"size", 1, NULL, 's'},
56 	{"key", 1, NULL, 'k'},
57 	{NULL, 0, NULL, 0},
58 };
59 
60 /*
61  * process_options: read options from user input
62  */
process_options(int argc,char * argv[])63 static void process_options(int argc, char *argv[])
64 {
65 	int c;
66 	char *end;
67 
68 	while ((c = getopt_long(argc, argv, "k:s:", long_opts, NULL)) != -1) {
69 		switch (c) {
70 		case 'k':
71 			key_id = atoi(optarg);
72 			break;
73 		case 's':
74 			memsize = strtoul(optarg, &end, 10);
75 			if (*end != '\0')
76 				errx(1, "wrong -s argument!");
77 			break;
78 		case MMAP_ANON:
79 			opt_mmap_anon = 1;
80 			break;
81 		case MMAP_FILE:
82 			opt_mmap_file = 1;
83 			break;
84 		case MMAP_LOCK1:
85 			opt_mmap_lock1 = 1;
86 			break;
87 		case MMAP_LOCK2:
88 			opt_mmap_lock2 = 1;
89 			break;
90 		case SHM:
91 			opt_shm = 1;
92 			break;
93 		case HUGEPAGE:
94 			opt_hugepage = 1;
95 			break;
96 		default:
97 			errx(1, "unknown option: %c", c);
98 			break;
99 		}
100 	}
101 }
102 
103 /*
104  * touch_memory: force allocating phy memory
105  */
touch_memory(char * p,int size)106 static void touch_memory(char *p, int size)
107 {
108 	int i;
109 	int pagesize = getpagesize();
110 
111 	for (i = 0; i < size; i += pagesize)
112 		p[i] = 0xef;
113 }
114 
mmap_anon(void)115 static void mmap_anon(void)
116 {
117 	static char *p;
118 
119 	if (!flag_allocated) {
120 		p = mmap(NULL, memsize, PROT_WRITE | PROT_READ,
121 			 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
122 		if (p == MAP_FAILED)
123 			err(1, "mmap(anonymous) failed");
124 		touch_memory(p, memsize);
125 	} else {
126 		if (munmap(p, memsize) == -1)
127 			err(1, "munmap(anonymous) failed");
128 	}
129 }
130 
mmap_file(void)131 static void mmap_file(void)
132 {
133 	static char *p;
134 	static int fd_hugepage;
135 	int fd_tmp;
136 
137 	if (!flag_allocated) {
138 		if (opt_hugepage) {
139 			fd_hugepage = open(FILE_HUGEPAGE,
140 					   O_CREAT | O_RDWR, 0755);
141 			if (fd_hugepage < 0)
142 				err(1, "open hugepage file failed");
143 			fd_tmp = fd_hugepage;
144 		} else
145 			fd_tmp = fd;
146 
147 		p = mmap(NULL, memsize, PROT_WRITE | PROT_READ,
148 			 MAP_SHARED, fd_tmp, 0);
149 		if (p == MAP_FAILED) {
150 			if (opt_hugepage)
151 				unlink(FILE_HUGEPAGE);
152 			err(1, "mmap(file) failed");
153 		}
154 		touch_memory(p, memsize);
155 	} else {
156 		if (munmap(p, memsize) == -1)
157 			err(1, "munmap(file) failed");
158 
159 		if (opt_hugepage) {
160 			close(fd_hugepage);
161 			unlink(FILE_HUGEPAGE);
162 		}
163 	}
164 }
165 
mmap_lock1(void)166 static void mmap_lock1(void)
167 {
168 	static char *p;
169 
170 	if (!flag_allocated) {
171 		p = mmap(NULL, memsize, PROT_WRITE | PROT_READ,
172 			 MAP_PRIVATE | MAP_ANONYMOUS | MAP_LOCKED, 0, 0);
173 		if (p == MAP_FAILED)
174 			err(1, "mmap(lock) failed");
175 		touch_memory(p, memsize);
176 	} else {
177 		if (munmap(p, memsize) == -1)
178 			err(1, "munmap(lock) failed");
179 	}
180 }
181 
mmap_lock2(void)182 static void mmap_lock2(void)
183 {
184 	static char *p;
185 
186 	if (!flag_allocated) {
187 		p = mmap(NULL, memsize, PROT_WRITE | PROT_READ,
188 			 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
189 		if (p == MAP_FAILED)
190 			err(1, "mmap failed");
191 
192 		if (mlock(p, memsize) == -1) {
193 			if (errno == EAGAIN)
194 				exit(2);
195 			else
196 				err(1, "mlock failed");
197 		}
198 	} else {
199 		if (munmap(p, memsize) == -1)
200 			err(1, "munmap failed");
201 	}
202 }
203 
shm(void)204 static void shm(void)
205 {
206 	static char *p;
207 	static int shmid;
208 	unsigned long flag;
209 
210 	key_t key;
211 
212 	if (!flag_allocated) {
213 		flag = IPC_CREAT | SHM_R | SHM_W;
214 		if (opt_hugepage)
215 			flag |= SHM_HUGETLB;
216 
217 		key = ftok("/dev/null", key_id);
218 		if (key == -1)
219 			err(1, "ftok() failed");
220 
221 		shmid = shmget(key, memsize, flag);
222 		if (shmid == -1)
223 			err(1, "shmget() failed");
224 
225 		p = shmat(shmid, NULL, 0);
226 		if (p == (void *)-1) {
227 			shmctl(shmid, IPC_RMID, NULL);
228 			err(1, "shmat() failed");
229 		}
230 
231 		if (shmctl(shmid, IPC_RMID, NULL) == -1)
232 			err(1, "shmctl() failed");
233 
234 		touch_memory(p, memsize);
235 	} else {
236 		if (shmdt(p) == -1)
237 			err(1, "shmdt() failed");
238 	}
239 }
240 
241 /*
242  * sigint_handler: handle SIGINT by set the exit flag.
243  */
sigint_handler(int signo)244 static void sigint_handler(int __attribute__ ((unused)) signo)
245 {
246 	flag_exit = 1;
247 }
248 
249 /*
250  * sigusr_handler: handler SIGUSR
251  *
252  * When we receive SIGUSR, we allocate some memory according
253  * to the user input when the process started.
254  *
255  * When we receive SIGUSR again, we will free all the allocated
256  * memory.
257  */
sigusr_handler(int signo)258 static void sigusr_handler(int __attribute__ ((unused)) signo)
259 {
260 	if (opt_mmap_anon)
261 		mmap_anon();
262 
263 	if (opt_mmap_file)
264 		mmap_file();
265 
266 	if (opt_mmap_lock1)
267 		mmap_lock1();
268 
269 	if (opt_mmap_lock2)
270 		mmap_lock2();
271 
272 	if (opt_shm)
273 		shm();
274 
275 	flag_allocated = !flag_allocated;
276 }
277 
main(int argc,char * argv[])278 int main(int argc, char *argv[])
279 {
280 	struct sigaction sigint_action;
281 	struct sigaction sigusr_action;
282 
283 	if ((fd = open("/dev/zero", O_RDWR)) == -1)
284 		err(1, "open /dev/zero failed");
285 
286 	memset(&sigint_action, 0, sizeof(sigint_action));
287 	memset(&sigusr_action, 0, sizeof(sigusr_action));
288 
289 	sigemptyset(&sigint_action.sa_mask);
290 	sigint_action.sa_handler = &sigint_handler;
291 	if (sigaction(SIGINT, &sigint_action, NULL))
292 		err(1, "sigaction(SIGINT)");
293 
294 	sigemptyset(&sigusr_action.sa_mask);
295 	sigusr_action.sa_handler = &sigusr_handler;
296 	if (sigaction(SIGUSR1, &sigusr_action, NULL))
297 		err(1, "sigaction(SIGUSR1)");
298 
299 	process_options(argc, argv);
300 
301 	tst_reinit();
302 
303 	TST_CHECKPOINT_WAKE(0);
304 
305 	while (!flag_exit)
306 		sleep(1);
307 
308 	close(fd);
309 
310 	return 0;
311 }
312