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