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